Files
einfach-produktiv/app/lib/invoiceData.ts
T
Marco 66ac184a6f Move invoice/tax-breakdown PDF generation into @einfach-produktiv/invoicing
Phase 0 of the e-invoicing migration plan (see the E-Rechnung planning
session) — moves invoicePdf.tsx, correctionInvoicePdf.tsx, and
taxBreakdown.ts into a new shared package, consumed as a git dependency
by both this repo and the payload backend, instead of hand-duplicating
the correction-invoice logic between them (see that package's own README
for the three real drifts the duplication had already caused).

Consumed as raw TS/TSX source via next.config.ts's transpilePackages, not
a pre-built package. Needs `git` in the Docker deps stage and a
project .npmrc (allow-git=root) to let npm ci fetch a git-URL dependency
at all — npm 12+ disables that by default.

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

52 lines
2.2 KiB
TypeScript

import { getCompanySettings, type CompanySettings } from "./payload";
import {
renderInvoicePdf,
renderCorrectionInvoicePdf,
type InvoiceOrder,
type CorrectionInvoiceKind,
type CorrectionInvoiceOrder,
} from "@einfach-produktiv/invoicing";
export type { CompanySettings };
// Fetched once by callers that need seller data for more than one purpose
// in the same request (e.g. orderEmail.ts also needs it for the email's
// legal footer, see buildLegalFooterLines() in emailTemplates.ts) — avoids
// a second identical company-settings round trip, unlike calling
// getCompanySettings() again inside each generator.
export async function getSellerForInvoice(): Promise<CompanySettings | null> {
return getCompanySettings();
}
// Shared by app/lib/orderEmail.ts (checkout — attaches to the confirmation
// mail) and app/api/account/orders/[orderNumber]/invoice/route.ts (on-demand
// download) — same render call both times, so what a customer downloads
// later always matches what they were emailed. `seller` is passed in
// rather than fetched here, so a caller that already has it (see above)
// doesn't fetch it twice.
export async function generateInvoicePdf(order: InvoiceOrder, seller: CompanySettings | null): Promise<Buffer | null> {
if (!seller) {
console.error("generateInvoicePdf: no company-settings row found for tenant");
return null;
}
return renderInvoicePdf(order, seller);
}
// Frontend-side regeneration for the "Stornorechnung/Gutschrift
// herunterladen" download button — the real document was already
// generated once (Payload's Orders.ts afterChange hook) and emailed; this
// reproduces the identical PDF from the order's own stored
// correctionInvoiceNumber/correctionInvoiceIssuedAt, same "deterministic
// regeneration, not file storage" approach as the original invoice.
export async function generateCorrectionInvoicePdf(
kind: CorrectionInvoiceKind,
order: CorrectionInvoiceOrder,
seller: CompanySettings | null,
): Promise<Buffer | null> {
if (!seller) {
console.error("generateCorrectionInvoicePdf: no company-settings row found for tenant");
return null;
}
return renderCorrectionInvoicePdf(kind, order, seller);
}