Files
picpeak/backend
Luca 5ed2fec2fe feat(crm): Mahngebühr on a separate Mahnung document; invoice stays immutable
Corrected dunning model (Mara): a Mahnung is a reminder LETTER showing the new
total (original + Mahngebühr), NOT a separate invoice and NOT a mutation of the
issued invoice.

- The invoice PDF no longer shows the fee (buildInvoiceRenderContext reports
  lateFeeAmountMinor 0) and is NEVER re-rendered by a reminder — it stays
  immutable (§14/§11).
- applyReminder now: tracks the fee as dunning state on the row (gross
  late_fee_amount_minor + new late_fee_vat_minor for the VAT portion, migration
  144), renders a separate MAHNUNG PDF (pdfService 'mahnung' kind — reuses the
  invoice layout: same lines + Mahngebühr row + new total, 'Mahnung' title, no
  QR), stored under storage/business-docs/mahnung/, and attaches BOTH the
  unchanged original invoice + the Mahnung to the reminder email.
- Fee resolvers split into net + VAT-rate (toggle + org-rate gated); a gross
  wrapper feeds the payment-check preview. en + de PDF title.

Outstanding/collections still read late_fee_amount_minor (now dunning state).
P3 (tax-report/Banana booking of the Mahngebühr VAT) stays Treuhänder-gated.
Syntax + 17/17 workflow/invoice tests green.

NOTE: the Mahnung PDF render path isn't unit-tested (PDF rendering is flaky in
the test env) — eyeball on the dev box: fire a level-2 reminder, confirm the
Mahnung PDF shows the new total and the original invoice PDF is unchanged.
2026-06-23 13:08:19 +02:00
..