feat(offers): generate Angebot/Offer PDFs for draft orders

This commit is contained in:
Gerhard Scheikl
2026-05-09 19:26:33 +02:00
parent 1ec4faaac5
commit 6224597497
8 changed files with 465 additions and 41 deletions
+17 -4
View File
@@ -28,6 +28,14 @@ interface ComposeArgs {
storno?: { cancelsNumber: string };
/** Optional override for invoice/delivery date (defaults to order date). */
issueDate?: Date;
/**
* When true, render as an Angebot/Offer instead of an invoice:
* - `kind = "offer"`
* - no payment-due date (the dueDate field is repurposed by the renderer
* as the offer's validity expiry).
* - GiroCode and payment-terms text are suppressed.
*/
offer?: boolean;
}
export function composeInvoice({
@@ -37,6 +45,7 @@ export function composeInvoice({
forceLanguage,
storno,
issueDate,
offer,
}: ComposeArgs): InvoiceViewModel {
const language = forceLanguage
?? pickLanguage(order.customer?.locale ?? settings.defaultLanguage);
@@ -51,9 +60,13 @@ export function composeInvoice({
const invoiceDate = issueDate ?? new Date(order.processedAt ?? order.createdAt);
const deliveryDate = invoiceDate;
const dueDate = !storno && settings.paymentTermDays > 0
? addDays(invoiceDate, settings.paymentTermDays)
: undefined;
// For offers we treat `dueDate` as the offer's validity expiry (default 30
// days from issue). The PDF renderer renders a different label.
const dueDate = offer
? addDays(invoiceDate, 30)
: !storno && settings.paymentTermDays > 0
? addDays(invoiceDate, settings.paymentTermDays)
: undefined;
const paid = (order.displayFinancialStatus || "").toUpperCase() === "PAID";
@@ -80,7 +93,7 @@ export function composeInvoice({
return {
language,
currency: order.currencyCode,
kind: storno ? "storno" : "invoice",
kind: storno ? "storno" : offer ? "offer" : "invoice",
number: invoiceNumber,
cancelsNumber: storno?.cancelsNumber,
invoiceDate,