153 lines
8.3 KiB
PHP
153 lines
8.3 KiB
PHP
<?php
|
||
use Steuerkram\View;
|
||
$h = fn($v) => View::h($v);
|
||
$isEdit = !empty($invoice['id']);
|
||
// Pre-select customer if passed via GET
|
||
$preCustomer = (int)($_GET['customer_id'] ?? 0);
|
||
?>
|
||
|
||
<div class="card">
|
||
<div class="card-body">
|
||
<form method="post" action="<?= $h($action) ?>">
|
||
|
||
<div class="form-grid form-grid-2 mb-2">
|
||
<div class="form-group">
|
||
<label for="customer_id">Kunde *</label>
|
||
<select id="customer_id" name="customer_id"
|
||
class="<?= isset($errors['customer_id']) ? 'input-error' : '' ?>" required
|
||
onchange="updatePaymentDays(this)">
|
||
<option value="">– Kunde wählen –</option>
|
||
<?php foreach ($customers as $c): ?>
|
||
<?php $selected = ($invoice['customer_id'] ?? $preCustomer) == $c['id'] ? ' selected' : ''; ?>
|
||
<option value="<?= $c['id'] ?>"<?= $selected ?>
|
||
data-payment="<?= $c['payment_days'] ?>">
|
||
<?= $h($c['kundennummer']) ?> – <?= $h(\Steuerkram\Models\Customer::displayName($c)) ?>
|
||
</option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
<?php if (isset($errors['customer_id'])): ?><div class="error-text"><?= $h($errors['customer_id']) ?></div><?php endif; ?>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="betreff">Betreff *</label>
|
||
<input type="text" id="betreff" name="betreff"
|
||
value="<?= $h($invoice['betreff'] ?? '') ?>"
|
||
class="<?= isset($errors['betreff']) ? 'input-error' : '' ?>" required>
|
||
<?php if (isset($errors['betreff'])): ?><div class="error-text"><?= $h($errors['betreff']) ?></div><?php endif; ?>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-grid form-grid-3 mb-2">
|
||
<div class="form-group">
|
||
<label for="rechnungs_datum">Rechnungsdatum *</label>
|
||
<input type="date" id="rechnungs_datum" name="rechnungs_datum"
|
||
value="<?= $h($invoice['rechnungs_datum'] ?? date('Y-m-d')) ?>" required>
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="leistungszeitraum">Leistungszeitraum</label>
|
||
<input type="text" id="leistungszeitraum" name="leistungszeitraum"
|
||
value="<?= $h($invoice['leistungszeitraum'] ?? '') ?>">
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="payment_days">Zahlungsziel (Tage)</label>
|
||
<input type="number" id="payment_days" name="payment_days"
|
||
value="<?= $h($invoice['payment_days'] ?? $settings['payment_days_default'] ?? 14) ?>"
|
||
min="0">
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Positionen-Tabelle -->
|
||
<div class="mb-2">
|
||
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:.75rem">
|
||
<strong>Rechnungspositionen</strong>
|
||
<button type="button" class="btn btn-secondary btn-sm" onclick="addInvoiceLine()">+ Position hinzufügen</button>
|
||
</div>
|
||
|
||
<?php if (isset($errors['lines'])): ?>
|
||
<div class="flash flash-error mb-2"><?= $h($errors['lines']) ?></div>
|
||
<?php endif; ?>
|
||
|
||
<div class="table-wrap">
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th style="width:40px">Pos.</th>
|
||
<th>Bezeichnung</th>
|
||
<th style="width:80px">Menge</th>
|
||
<th style="width:80px">Einheit</th>
|
||
<th style="width:80px">USt.</th>
|
||
<th style="width:110px">Einzelpreis</th>
|
||
<th style="width:100px" class="td-right">Netto</th>
|
||
<th style="width:110px" class="td-right">Brutto</th>
|
||
<th style="width:40px"></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="invoice-lines-body">
|
||
<?php foreach ($lines as $i => $line): ?>
|
||
<tr class="invoice-line-row">
|
||
<td><span class="line-pos text-muted"><?= $i+1 ?></span></td>
|
||
<td><input type="text" name="lines[<?= $i ?>][bezeichnung]" value="<?= $h($line['bezeichnung']) ?>" required style="min-width:200px"></td>
|
||
<td><input type="number" name="lines[<?= $i ?>][menge]" value="<?= $h($line['menge']) ?>" min="0.001" step="0.001" style="width:75px" required></td>
|
||
<td>
|
||
<select name="lines[<?= $i ?>][einheit]" style="width:75px">
|
||
<?php foreach (['Stk.','h','Tage','Monat','Pauschale','km'] as $eu): ?>
|
||
<option value="<?= $eu ?>"<?= $line['einheit'] === $eu ? ' selected' : '' ?>><?= $eu ?></option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
</td>
|
||
<td>
|
||
<select name="lines[<?= $i ?>][ust_satz]" style="width:75px">
|
||
<?php foreach ([19, 7, 0] as $r): ?>
|
||
<option value="<?= $r ?>"<?= (float)$line['ust_satz'] === (float)$r ? ' selected' : '' ?>><?= $r ?> %</option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
</td>
|
||
<td><input type="number" name="lines[<?= $i ?>][einzelpreis]" value="<?= $h($line['einzelpreis']) ?>" step="0.01" min="0" style="width:105px" required></td>
|
||
<td class="td-right line-netto text-muted"><?= View::formatMoney($line['betrag_netto']) ?></td>
|
||
<td class="td-right line-brutto font-bold"><?= View::formatMoney($line['betrag_brutto']) ?></td>
|
||
<td><button type="button" class="btn btn-danger btn-sm" onclick="removeInvoiceLine(this)">✕</button></td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<!-- Summen -->
|
||
<div style="display:flex;justify-content:flex-end;margin-top:.75rem">
|
||
<table style="width:280px;font-size:.9rem">
|
||
<tr><td>Nettobetrag:</td><td class="td-right" id="total-netto">–</td></tr>
|
||
<tr><td>zzgl. Umsatzsteuer:</td><td class="td-right" id="total-ust">–</td></tr>
|
||
<tr style="font-size:1rem;font-weight:700">
|
||
<td>Rechnungsbetrag:</td>
|
||
<td class="td-right" id="total-brutto">–</td>
|
||
</tr>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="notes">Interne Notizen</label>
|
||
<textarea id="notes" name="notes" rows="2"><?= $h($invoice['notes'] ?? '') ?></textarea>
|
||
</div>
|
||
|
||
<div style="display:flex;gap:.75rem;margin-top:1rem">
|
||
<button type="submit" class="btn btn-primary">Entwurf speichern</button>
|
||
<a href="/invoices" class="btn btn-secondary">Abbrechen</a>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
function updatePaymentDays(sel) {
|
||
const opt = sel.options[sel.selectedIndex];
|
||
const days = opt.dataset.payment;
|
||
if (days) document.getElementById('payment_days').value = days;
|
||
}
|
||
<?php if (!$isEdit): ?>
|
||
document.addEventListener('DOMContentLoaded', function () {
|
||
const sel = document.getElementById('customer_id');
|
||
if (sel && sel.value) updatePaymentDays(sel);
|
||
});
|
||
<?php endif; ?>
|
||
</script>
|