feat: Umsatzsteuer ueber VAT_RATE_PERCENT konfigurierbar und auf der Rechnung ausgewiesen

Die Rechnung wies bisher gar keine Steuer aus — weder Satz und Betrag noch
den Pflichthinweis nach § 19 UStG. Der Satz kommt jetzt aus
VAT_RATE_PERCENT und steht auf PDF und HTML-Ansicht: 7 (ermaessigt, Honig
als Lebensmittel), 19 (voll) oder 0 fuer die Kleinunternehmerregelung, bei
der anstelle der Steuerzeilen der vorgeschriebene Hinweis erscheint.

DIE SHOP-PREISE SIND BRUTTOPREISE. Gegenueber Verbrauchern ist der
Gesamtpreis inklusive Umsatzsteuer anzugeben (§ 1 PAngV), und genau dieser
Betrag steht in Product.priceCents und Order.totalCents. Die Steuer wird
deshalb herausgerechnet, nicht aufgeschlagen — ein Aufschlag ergaebe einen
anderen Endpreis als den, den die Kundschaft im Warenkorb gesehen und
bezahlt hat.

Gerechnet wird auf der Gesamtsumme statt je Position, damit sich Rundungen
einzelner Zeilen nicht aufsummieren, und der Steuerbetrag ergibt sich als
Rest statt aus einer zweiten Rundung: nur so gilt immer netto + steuer ===
brutto. Eine Rechnung, die sich nicht aufaddiert, ist keine brauchbare
Rechnung. Der Versand traegt den Satz der Ware, er ist umsatzsteuerlich
eine Nebenleistung.

Der Satz wird als Invoice.vatRatePercent FESTGESCHRIEBEN statt bei jeder
Anzeige aus der Umgebung gelesen. Wechselt der Steuerstatus des Betriebs,
muessen alte Rechnungen weiterhin den damals ausgewiesenen Satz zeigen — ein
Beleg ist die Aufzeichnung eines vergangenen Vorgangs, keine Ansicht auf die
heutige Konfiguration. Bestehende Rechnungen tragen null und zeigen wie
bisher keine Steuerzeilen, weil rueckwirkend nicht feststellbar ist, welcher
Satz gegolten haette.

Ein unbrauchbarer Wert faellt auf 7% zurueck und wird laut geloggt, statt
eine bereits bezahlte Bestellung scheitern zu lassen. Damit das nicht
unbemerkt bleibt, prueft "pnpm preflight" den Wert jetzt als Blocker und
warnt zusaetzlich bei einem in Deutschland unueblichen Satz.

Der bisherige legalNote war ein Platzhalter ("Kleinunternehmerregelung /
Umsatzsteuerausweis gemaess tatsaechlichem Status ergaenzen") und ist
ersetzt, da die Angabe nun tatsaechlich erfolgt.

Bekannte Grenze, im README vermerkt: es gibt genau EINEN Satz. Honig ist
ermaessigt besteuert, Kerzen nicht — werden beide verkauft, braucht es einen
Satz je ProductCategory.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
Nick SzaunigandClaude Opus 5 committed 2026-09-17 06:32:12 +02:00
1 parent 70ede77dde
commit 7c59283ede
15 files changed
+334 -7

No files matched your search

+16 -3
View File
@@ -274,10 +274,23 @@ Das Jahr steht zuerst, weil sich die Aufbewahrungsfrist danach richtet: ein abge
> Bei **mehr als einem Knoten**: das PVC `wabenhain-invoices` ist `ReadWriteOnce` und lässt sich nur von Pods auf demselben Knoten einhängen. Landet der Sicherungs-Pod woanders als die App, bleibt er in „Pending" — ohne Fehlermeldung. Dann das PVC auf `ReadWriteMany` umstellen (NFS/SMB/CephFS).
**Noch offen** und vor dem Live-Gang zu klären:
### Umsatzsteuer
- Die Rechnungsnummer (`RE-2026-<8 Hex>`) ist eindeutig, aber **nicht fortlaufend**. § 14 Abs. 4 Nr. 4 UStG verlangt eine fortlaufende Nummer.
- Das PDF weist **keine Umsatzsteuer** aus — weder Satz und Betrag noch den Hinweis nach § 19 UStG bei Kleinunternehmerregelung. Welches von beidem nötig ist, hängt vom Steuerstatus der Imkerei ab.
Der Satz kommt aus `VAT_RATE_PERCENT` (ganze Prozent) und steht auf Rechnungsansicht und PDF:
| Wert | Bedeutung | Auf der Rechnung |
|------|-----------|------------------|
| `7` | ermäßigt — Honig als Lebensmittel, Anlage 2 zum UStG | Nettobetrag + „zzgl. 7 % Umsatzsteuer" |
| `19` | voller Satz | Nettobetrag + „zzgl. 19 % Umsatzsteuer" |
| `0` | Kleinunternehmerregelung | „Gemäß § 19 UStG wird keine Umsatzsteuer berechnet." anstelle der Steuerzeilen |
**Die Shop-Preise sind Bruttopreise.** Gegenüber Verbraucher:innen ist der Gesamtpreis inklusive Umsatzsteuer anzugeben (§ 1 PAngV), und genau dieser Betrag steht in `Product.priceCents` und `Order.totalCents`. Die Steuer wird deshalb **herausgerechnet, nicht aufgeschlagen** — ein Aufschlag würde den Endpreis verändern und von dem abweichen, was im Warenkorb stand. Gerechnet wird auf der Gesamtsumme, damit sich Rundungen einzelner Positionen nicht aufsummieren; der Steuerbetrag ergibt sich als Rest, sodass Netto + Steuer immer exakt den Bruttobetrag ergibt. Der Versand trägt den Satz der Ware (umsatzsteuerliche Nebenleistung).
Der Satz wird bei jeder Rechnung als `Invoice.vatRatePercent` **festgeschrieben**. Ändert sich der Steuerstatus, gilt der neue Wert nur für künftige Rechnungen — ein Beleg über einen vergangenen Vorgang darf sich nicht rückwirkend ändern. `pnpm preflight` blockiert einen fehlenden oder unplausiblen Wert.
> **Ein Satz für alle Artikel.** Honig ist ermäßigt besteuert, Kerzen nicht. Werden beide verkauft, ist der eine Wert zwangsläufig für eine der beiden Gruppen falsch — dafür bräuchte es einen Satz je `ProductCategory`. Solange nur Honig verkauft wird, genügt `7`.
**Noch offen:** die Rechnungsnummer (`RE-2026-<8 Hex>`) ist eindeutig, aber **nicht fortlaufend**. § 14 Abs. 4 Nr. 4 UStG verlangt eine fortlaufende Nummer.
## Health-Endpunkte