diff --git a/src/lib/pdf/stock-purchase-document.tsx b/src/lib/pdf/stock-purchase-document.tsx index 52dc67a..73545d7 100644 --- a/src/lib/pdf/stock-purchase-document.tsx +++ b/src/lib/pdf/stock-purchase-document.tsx @@ -1,7 +1,7 @@ import { Document, Page, View, Text, Image, StyleSheet } from "@react-pdf/renderer"; import type { Letterhead } from "@/lib/letterhead"; import type { StockPurchase, StockPurchaseItem, Supplier } from "@/lib/types"; -import { formatZAR, formatDateLong } from "./format"; +import { formatZAR, formatDateLong, vatAmount } from "./format"; import { defaultAccentFor } from "@/lib/letterhead"; /** @@ -57,14 +57,15 @@ export interface StockPurchaseDocumentProps { * Cost / Line Total). The SKU column is new vs. customer POs — * stock POs reference stock_items by SKU so the supplier can * cross-check the line. - * - right-aligned totals (Subtotal + Total) + * - right-aligned totals (Subtotal + VAT (15%) + Total — rule above Total) * * Intentionally stripped (vs. the customer PO PDF): * - **No Order Ref line** — stock POs have no customer order. The * supplier must NOT learn anything about the end customer. Same * confidentiality rule as customer POs. - * - **No banking details / no VAT line** — same rationale as the - * customer PO: we pay what the supplier quotes, no markup math. + * - **No banking details** — supplier invoices via the normal + * commercial channel; the PO is an instruction to supply, not + * a payment instruction. * * The `STK` suffix on the PO number (e.g. `PO26071601STK`) is the * in-band signal to the supplier that this is a stock order, not a @@ -96,11 +97,20 @@ export function StockPurchaseDocument({ 0 ) * 100 ) / 100; - // Re-use the supplied snapshot if it differs from the live - // computation by < 0.01 — caller might have included an explicit - // total_amount that we want to honour (e.g. from the regenerate - // API where the PO record already has total_amount set). - const total = Math.abs(totalAmount - subtotal) < 0.01 ? totalAmount : subtotal; + // 15% VAT on top of the supplier-quoted subtotal — same helper the + // customer PO and quote PDFs use, so all three documents compute + // VAT identically. Total = subtotal + vat, rounded to 2dp so the + // line matches the printed figures exactly. + // + // The `totalAmount` prop is carried for API backwards-compat with + // the existing route (the stock_purchases row stores the VAT-ex + // subtotal there); we deliberately ignore it for the printed Total + // because the office reconciles VAT returns from the printed PDF, + // not the stored field. Mirrors the customer PO behaviour + // (`PurchaseOrderDocument` does the same). + void totalAmount; + const vat = vatAmount(subtotal); + const totalInclVat = Math.round((subtotal + vat) * 100) / 100; return ( - {/* Totals — just Subtotal + Total. No VAT (we're buying, the - supplier's price is what we pay). Rule above Total mirrors - the customer-PO totals block so the two feel like siblings. */} + {/* Totals — Subtotal + VAT (15%) + rule + Total. Mirrors the + customer-PO totals block so the two PDFs feel like + siblings when filed side-by-side. `Subtotal` is the VAT-ex + sum (stored on `stock_purchases.total_amount`); the printed + `Total` is `subtotal × 1.15` — the figure the office uses + for budget / VAT-return reconciliation. */} Subtotal: {formatZAR(subtotal)} + + VAT (15%): + {formatZAR(vat)} + Total: - {formatZAR(total)} + {formatZAR(totalInclVat)}