Add innergemeinschaftliche-Lieferung (VAT exemption) support
Validate e-invoices / mustang (push) Successful in 18s
Validate e-invoices / mustang (push) Successful in 18s
InvoiceOrder/CorrectionInvoiceOrder gained an optional vatExempt flag — items already carry 0% rate and de-grossed prices when true (the caller's responsibility), this only controls display/XML mapping: - Visual PDF: replaces the "enthält X% MwSt." annotation with "Steuerfreie innergemeinschaftliche Lieferung (§4 Nr. 1b UStG)" on both the invoice and its Storno/Gutschrift. - EN16931 XML (buildEInvoiceData.ts): VAT category 'K' instead of 'S' on every line/tax-subtotal, plus BT-120/BT-121 exemption reason (VATEX-EU-IC) — but only on cac:TaxTotal's own TaxSubtotal.TaxCategory, not on InvoiceLine/AllowanceCharge's TaxCategory, which @e-invoice-eu/core's schema rejects those same two fields on (caught locally before Mustang ever saw it — a fully-rendered PDF/A-3 with a hand-inflated CII XML confirmed CategoryCode/ExemptionReasonCode/ ExemptionReason land correctly). Also surfaced (not fixed, unrelated to this change): a seller with no iban configured throws in @e-invoice-eu/core's UBL→CII conversion — doesn't affect this shop's own production data (iban is always set), noting for whoever touches this next. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+23
-6
@@ -145,6 +145,14 @@ export type InvoiceOrder = {
|
||||
// the address. Neither implies the other (see Orders.ts's own comment).
|
||||
companyName?: string | null;
|
||||
vatId?: string | null;
|
||||
// Innergemeinschaftliche Lieferung (§4 Nr. 1b UStG) — decided server-side
|
||||
// at checkout via a live VIES lookup (see the frontend's api/checkout/
|
||||
// route.ts and lib/vatExemption.ts), never guessed from vatId's mere
|
||||
// presence/format. When true, every item's own taxRatePercent is already
|
||||
// 0 and unitPrice already de-grossed (the actual charged/persisted
|
||||
// figures) — this flag only controls the exemption note shown here,
|
||||
// it doesn't itself change any arithmetic in this file.
|
||||
vatExempt?: boolean;
|
||||
deliveryMethod: "address" | "packstation";
|
||||
street?: string | null;
|
||||
packstationNumber?: string | null;
|
||||
@@ -373,12 +381,21 @@ export function InvoiceDocument({ order, seller }: { order: InvoiceOrder; seller
|
||||
<Text style={styles.grandTotalValue}>{formatPrice(order.total)}</Text>
|
||||
</View>
|
||||
<View style={styles.vatNotes}>
|
||||
{rateGroups.map((g) => (
|
||||
<View style={styles.vatNoteRow} key={g.rate}>
|
||||
<Text style={styles.vatNoteLabel}>enthält {g.rate}% MwSt.</Text>
|
||||
<Text style={styles.vatNoteValue}>{formatPrice(g.tax)}</Text>
|
||||
</View>
|
||||
))}
|
||||
{/* Exempt orders already have every item at 0% (see this
|
||||
file's own InvoiceOrder.vatExempt comment) — "enthält
|
||||
0% MwSt.: 0,00 €" would be a meaningless thing to print,
|
||||
so this replaces the whole per-rate breakdown with the
|
||||
actual legal basis instead. */}
|
||||
{order.vatExempt ? (
|
||||
<Text style={styles.vatNoteLabel}>Steuerfreie innergemeinschaftliche Lieferung (§4 Nr. 1b UStG)</Text>
|
||||
) : (
|
||||
rateGroups.map((g) => (
|
||||
<View style={styles.vatNoteRow} key={g.rate}>
|
||||
<Text style={styles.vatNoteLabel}>enthält {g.rate}% MwSt.</Text>
|
||||
<Text style={styles.vatNoteValue}>{formatPrice(g.tax)}</Text>
|
||||
</View>
|
||||
))
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
{paid && (
|
||||
|
||||
Reference in New Issue
Block a user