InvoiceSeller.bankDetails becomes iban/bic (EN16931 wants discrete PaymentMeans data, not a paragraph a human formatted by hand). The footer's bank-details line also drops the misleading "(für Überweisung)" qualifier — it was never actually conditional on the order's payment method (only on whether the field was set at all), just worded as if it were. Now shown whenever iban or bic is set, regardless of payment method. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@einfach-produktiv/invoicing
Shared invoice / correction-invoice (Stornorechnung, Gutschrift) PDF generation and VAT-breakdown math, used by both:
einfach-produktiv(the Next.js storefront — generates the original invoice at checkout, plus on-demand re-downloads of both document types)payload(the Payload CMS backend — generates the authoritative Stornorechnung/Gutschrift the moment an order's status changes)
Why this exists
Before this package, taxBreakdown.ts and correctionInvoicePdf.tsx were hand-duplicated between both repos ("kept in sync by eye"). That drifted in three concrete, customer-visible ways before this package fixed it:
- The backend's emailed correction invoice silently dropped each line item's
variantName(the frontend's re-download copy showed it). - The backend's correction-invoice footer wasn't
position: fixed, unlike the original invoice and the frontend's copy. - The backend's correction invoice used a numeric date format (
03.07.2025); the original invoice and the frontend's re-download copy both used a spelled-out month (03. Juli 2025) — so a re-downloaded document didn't match what was originally emailed.
One canonical implementation, consumed by both repos, makes this class of drift structurally impossible instead of relying on manual vigilance.
2026-07-23, Phase 2: InvoiceSeller.bankDetails (a free-text textarea on company-settings) became structured iban/bic fields — EN16931 e-invoicing wants discrete PaymentMeans data, not a paragraph a human formatted by hand. The footer's bank-details line also changed from "Bankverbindung (für Überweisung): …" to plain "Bankverbindung: IBAN … · BIC …", shown whenever either is set — it was never actually conditional on the order's payment method (that label was misleading), and there's no reason to hide it from a card/PayPal customer who might still want it (e.g. for a refund).
How this is consumed
Not published to npm — installed as a git dependency:
"@einfach-produktiv/invoicing": "git+https://git.mk360.de/Marco/einfach-produktiv-invoicing.git"
Ships raw TypeScript/TSX source (no build step) via main/types pointing straight at src/index.ts. Each consuming Next.js app must add this package to its own next.config.ts's transpilePackages array so its own bundler compiles the source — the same pattern a monorepo tool like Turborepo uses for internal packages, just without the monorepo.
react and @react-pdf/renderer are peer dependencies — each consumer supplies its own copy rather than this package pinning a version that could conflict.
Layout
taxBreakdown.ts—computeTaxBreakdown(), the per-VAT-rate net/tax grouping math shared by every document type here.formatters.ts—formatPrice()/formatDate(), canonical formatting for every document.invoicePdf.tsx— the original invoice ("Rechnung"):InvoiceDocument,renderInvoicePdf(), plusSAMPLE_INVOICE_ORDER(used by the frontend's Payload Live Preview for company-settings).correctionInvoicePdf.tsx— Stornorechnung/Gutschrift:renderCorrectionInvoicePdf().seller.ts— the sharedInvoiceSellertype both document types render in their footer.