Add optional per-line SKU + shipping recipient company/contact fields (v0.2.7)
Validate e-invoices / mustang (push) Successful in 43s
Validate e-invoices / mustang (push) Successful in 43s
Invoice PDFs (visual + EN16931 XML) and correction invoices now show an "Art.-Nr." line when an order item has a SKU snapshot, and the Lieferadresse block includes company name/contact email/phone when set.
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@einfach-produktiv/invoicing",
|
||||
"version": "0.2.6",
|
||||
"version": "0.2.7",
|
||||
"private": true,
|
||||
"description": "Shared invoice / correction-invoice (Stornorechnung, Gutschrift) PDF generation and VAT-breakdown math, consumed as a git dependency by both the einfach-produktiv frontend and the payload backend — not published to npm.",
|
||||
"type": "module",
|
||||
|
||||
@@ -132,6 +132,7 @@ export type CorrectionInvoiceItem = {
|
||||
variantName?: string | null;
|
||||
returnQuantity?: number;
|
||||
imageUrl?: string | null;
|
||||
sku?: string | null;
|
||||
};
|
||||
|
||||
export type CorrectionInvoiceOrder = {
|
||||
@@ -303,6 +304,7 @@ function CorrectionInvoiceDocument({ kind, order, seller }: { kind: CorrectionIn
|
||||
{item.variantName ? ` (${item.variantName})` : ""}
|
||||
</Text>
|
||||
{item.bundleContents ? <Text style={styles.bundleLine}>{item.bundleContents}</Text> : null}
|
||||
{item.sku ? <Text style={styles.bundleLine}>Art.-Nr. {item.sku}</Text> : null}
|
||||
</View>
|
||||
<Text style={styles.colQty}>{effectiveQuantity}</Text>
|
||||
<Text style={styles.colPrice}>{formatPrice(item.unitPrice)}</Text>
|
||||
|
||||
@@ -220,7 +220,18 @@ function buyerParty(name: string, street: string | null | undefined, zip: string
|
||||
};
|
||||
}
|
||||
|
||||
type LineInput = { productName: string; variantName?: string | null; quantity: number; unitPrice: number; taxRatePercent: number };
|
||||
type LineInput = {
|
||||
productName: string;
|
||||
variantName?: string | null;
|
||||
quantity: number;
|
||||
unitPrice: number;
|
||||
taxRatePercent: number;
|
||||
// BT-155 (Item seller's identifier) when present — variant SKU if one
|
||||
// was selected, else the product's own (see Orders.items.sku in the
|
||||
// Payload backend). Omitted entirely when neither is set, same as the
|
||||
// visual PDF's own optional "Art.-Nr." line.
|
||||
sku?: string | null;
|
||||
};
|
||||
type ComputedLine = { item: LineInput; netCents: number };
|
||||
type RateGroup = { rate: number; lineNetCents: number; allowanceCents: number; chargeCents: number; taxableCents: number; taxCents: number };
|
||||
|
||||
@@ -337,6 +348,7 @@ function invoiceLines(lines: ComputedLine[], vatMode: VatMode): UblInvoice["cac:
|
||||
"cac:Item": {
|
||||
"cbc:Name": item.variantName ? `${item.productName} (${item.variantName})` : item.productName,
|
||||
"cac:ClassifiedTaxCategory": vatTaxCategory(item.taxRatePercent, vatMode),
|
||||
...(item.sku ? { "cac:SellersItemIdentification": { "cbc:ID": item.sku } } : {}),
|
||||
},
|
||||
// Unit price, not a summed/reconciled total — kept as the plain
|
||||
// (unrounded-to-cent) net unit price for reference; BR-CO-10 only
|
||||
|
||||
@@ -160,6 +160,11 @@ export type InvoiceItem = {
|
||||
bundleContents?: string | null;
|
||||
variantName?: string | null;
|
||||
imageUrl?: string | null;
|
||||
// Snapshot from the order (Orders.items.sku in the Payload backend) —
|
||||
// variant SKU if one was selected, else the product's own, else absent.
|
||||
// Shown next to productName only when actually set; a product/variant
|
||||
// with no SKU configured renders exactly as before this field existed.
|
||||
sku?: string | null;
|
||||
};
|
||||
|
||||
export type InvoiceOrder = {
|
||||
@@ -206,6 +211,10 @@ export type InvoiceOrder = {
|
||||
hasDifferentShippingAddress?: boolean;
|
||||
shippingFirstName?: string | null;
|
||||
shippingLastName?: string | null;
|
||||
// Optional, mirrors companyName above — no shipping-side vatId (billing-
|
||||
// only concept). Contact email/phone are handed to the shipping carrier,
|
||||
// shown here for the customer's own reference on their invoice copy.
|
||||
shippingCompanyName?: string | null;
|
||||
shippingDeliveryMethod?: "address" | "packstation" | null;
|
||||
shippingStreet?: string | null;
|
||||
shippingPackstationNumber?: string | null;
|
||||
@@ -213,6 +222,8 @@ export type InvoiceOrder = {
|
||||
shippingZip?: string | null;
|
||||
shippingCity?: string | null;
|
||||
shippingCountry?: string | null;
|
||||
shippingContactEmail?: string | null;
|
||||
shippingContactPhone?: string | null;
|
||||
paymentMethodTitle: string;
|
||||
items: InvoiceItem[];
|
||||
subtotal: number;
|
||||
@@ -345,6 +356,7 @@ export function InvoiceDocument({ order, seller }: { order: InvoiceOrder; seller
|
||||
{order.hasDifferentShippingAddress && (
|
||||
<View style={addressBlockStyle}>
|
||||
<Text style={styles.addressLabel}>Lieferadresse</Text>
|
||||
{order.shippingCompanyName && <Text style={styles.addressLine}>{order.shippingCompanyName}</Text>}
|
||||
<Text style={styles.addressLine}>
|
||||
{order.shippingFirstName} {order.shippingLastName}
|
||||
</Text>
|
||||
@@ -358,6 +370,8 @@ export function InvoiceDocument({ order, seller }: { order: InvoiceOrder; seller
|
||||
{order.shippingZip} {order.shippingCity}
|
||||
</Text>
|
||||
<Text style={styles.addressLine}>{order.shippingCountry}</Text>
|
||||
{order.shippingContactEmail && <Text style={styles.addressLine}>{order.shippingContactEmail}</Text>}
|
||||
{order.shippingContactPhone && <Text style={styles.addressLine}>{order.shippingContactPhone}</Text>}
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
@@ -396,6 +410,7 @@ export function InvoiceDocument({ order, seller }: { order: InvoiceOrder; seller
|
||||
{item.variantName ? ` (${item.variantName})` : ""}
|
||||
</Text>
|
||||
{item.bundleContents ? <Text style={styles.bundleLine}>{item.bundleContents}</Text> : null}
|
||||
{item.sku ? <Text style={styles.bundleLine}>Art.-Nr. {item.sku}</Text> : null}
|
||||
</View>
|
||||
<Text style={styles.colQty}>{item.quantity}</Text>
|
||||
<Text style={styles.colPrice}>{formatPrice(item.unitPrice)}</Text>
|
||||
|
||||
Reference in New Issue
Block a user