diff --git a/src/lib/pdf/format.ts b/src/lib/pdf/format.ts index 1f49cf0..150783a 100644 --- a/src/lib/pdf/format.ts +++ b/src/lib/pdf/format.ts @@ -41,9 +41,18 @@ export function quoteSubtotal(items: { quantity: number; selling_price: number } /** * Sum of (order_qty ?? quantity) * cost_price across PO items. Differs - * from `quoteSubtotal()` in using supplier-facing cost and order quantity. - * A blank or zero order_qty falls back to quantity so it never zeroes a line. - * Rounds to 2dp so the printed table doesn't show floating-point dust. + * from `quoteSubtotal()` in two ways: + * 1. Multiplies by `cost_price` (the supplier-facing price), not + * `selling_price` (the customer-facing price). + * 2. Prefers `order_qty` when set, falls back to `quantity` so a + * blank `order_qty` (the common case when the operator hasn't + * adjusted the supplier-facing qty yet) never zeroes the line. + * A literal `order_qty: 0` is also treated as missing — that's + * almost always an operator mistake. + * + * Rounds to 2dp so the printed table doesn't show floating-point dust + * (1.0000000003 R etc). The supplier-facing PO uses this for both + * `Subtotal` and the base of the `VAT (15%)` line. */ export function poSubtotal( items: { order_qty?: number | null; quantity: number; cost_price: number }[] @@ -51,6 +60,9 @@ export function poSubtotal( return Math.round( items.reduce( (sum, it) => + // `||` (not `??`) is intentional: we want `order_qty: 0` to fall through + // to `quantity`, since a literal 0 on a PO line is almost always an + // operator mistake (blank input) rather than a real "zero qty". sum + (Number(it.order_qty) || Number(it.quantity) || 0) * (Number(it.cost_price) || 0),