Marco 4e9b4b9dd4 Add bankName back to InvoiceSeller, shown alongside IBAN/BIC
Dropped by accident when bankDetails split into iban/bic — a bank name
has no fixed format to validate, so it stays free text, but it's still
useful context next to the account numbers in the invoice footer.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-23 10:26:23 +00:00

@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:

  1. The backend's emailed correction invoice silently dropped each line item's variantName (the frontend's re-download copy showed it).
  2. The backend's correction-invoice footer wasn't position: fixed, unlike the original invoice and the frontend's copy.
  3. 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.tscomputeTaxBreakdown(), the per-VAT-rate net/tax grouping math shared by every document type here.
  • formatters.tsformatPrice()/formatDate(), canonical formatting for every document.
  • invoicePdf.tsx — the original invoice ("Rechnung"): InvoiceDocument, renderInvoicePdf(), plus SAMPLE_INVOICE_ORDER (used by the frontend's Payload Live Preview for company-settings).
  • correctionInvoicePdf.tsx — Stornorechnung/Gutschrift: renderCorrectionInvoicePdf().
  • seller.ts — the shared InvoiceSeller type both document types render in their footer.
S
Description
Shared invoice/correction-invoice PDF generation + VAT breakdown, used by both einfach-produktiv (frontend) and payload (backend) — internal git dependency, not published to npm.
Readme 1.1 MiB
Languages
TypeScript 100%