Steuerkram/src/Views/invoices/form.php

181 lines
10 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?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) ?>" class="invoice-form">
<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-primary btn-sm" onclick="showAddLineDialog(this)">+ 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 class="invoice-form-table" style="width:calc(100% - 20px);table-layout:fixed">
<colgroup>
<col style="width:3.5em"><!-- Pos. -->
<col><!-- Bezeichnung (flex) -->
<col style="width:5.5em"><!-- Menge -->
<col style="width:6em"><!-- Einheit -->
<col style="width:5em"><!-- USt. -->
<col style="width:8em"><!-- Einzelpreis -->
<col style="width:7em"><!-- Netto -->
<col style="width:7em"><!-- Brutto -->
<col style="width:2.5em"><!-- Löschen -->
</colgroup>
<thead>
<tr>
<th>Pos.</th>
<th>Bezeichnung</th>
<th>Menge</th>
<th>Einheit</th>
<th>USt.</th>
<th>Einzelpreis</th>
<th class="td-right">Netto</th>
<th class="td-right">Brutto</th>
<th></th>
</tr>
</thead>
<tbody id="invoice-lines-body">
<?php
$posIdx = 0;
foreach ($lines as $i => $line):
$isHeading = ($line['type'] ?? 'position') === 'heading';
?>
<?php if ($isHeading): ?>
<tr class="invoice-heading-row">
<td colspan="8">
<input type="hidden" name="lines[<?= $i ?>][type]" value="heading">
<textarea name="lines[<?= $i ?>][bezeichnung]" required placeholder="Überschrift" rows="1" class="line-bez-input" style="width:100%;font-weight:bold"><?= $h($line['bezeichnung']) ?></textarea>
</td>
<td><button type="button" class="btn btn-danger btn-sm" onclick="removeInvoiceLine(this)">✕</button></td>
</tr>
<?php else: ?>
<tr class="invoice-line-row">
<td><span class="line-pos text-muted"><?= ++$posIdx ?></span></td>
<td>
<input type="hidden" name="lines[<?= $i ?>][type]" value="position">
<textarea name="lines[<?= $i ?>][bezeichnung]" required rows="1" class="line-bez-input" style="width:100%"><?= $h($line['bezeichnung']) ?></textarea>
</td>
<td><input type="number" name="lines[<?= $i ?>][menge]" value="<?= $h($line['menge']) ?>" min="0.001" step="0.001" style="width:100%" required></td>
<td>
<select name="lines[<?= $i ?>][einheit]" style="width:100%">
<?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:100%">
<?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:100%" 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 endif; ?>
<?php endforeach; ?>
</tbody>
</table>
</div>
<!-- Summen -->
<div style="display:flex;justify-content:flex-end;margin-top:.75rem;padding-right:.5rem">
<table style="width:auto;font-size:.7rem">
<tr><td style="padding:.3rem 0">Nettobetrag:</td><td class="td-right" style="padding:.3rem 0;width:7.5em" id="total-netto">–</td></tr>
<tr><td style="padding:.3rem 0">zzgl. Umsatzsteuer:</td><td class="td-right" style="padding:.3rem 0" id="total-ust">–</td></tr>
<tr style="font-size:.78rem;font-weight:700">
<td style="padding:.5rem 0">Rechnungsbetrag:</td>
<td class="td-right" style="padding:.5rem 0" 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>