feat(pdf): include VAT calculation in stock purchase document
- Added VAT calculation to the stock purchase document PDF, displaying VAT (15%) alongside the subtotal and total. - Updated the layout to reflect the new totals structure, ensuring consistency with customer PO documents. - Revised comments for clarity on the handling of total amounts and VAT reconciliation.
This commit is contained in:
parent
43bbdfc458
commit
d194603dce
1 changed files with 30 additions and 13 deletions
|
|
@ -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 (
|
||||
<Document
|
||||
|
|
@ -212,18 +222,25 @@ export function StockPurchaseDocument({
|
|||
})}
|
||||
</View>
|
||||
|
||||
{/* 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. */}
|
||||
<View style={styles.totals}>
|
||||
<View style={styles.totalLine}>
|
||||
<Text style={styles.totalLabel}>Subtotal:</Text>
|
||||
<Text style={styles.totalValue}>{formatZAR(subtotal)}</Text>
|
||||
</View>
|
||||
<View style={styles.totalLine}>
|
||||
<Text style={styles.totalLabel}>VAT (15%):</Text>
|
||||
<Text style={styles.totalValue}>{formatZAR(vat)}</Text>
|
||||
</View>
|
||||
<View style={styles.totalRule} />
|
||||
<View style={styles.totalLine}>
|
||||
<Text style={styles.totalFinalLabel}>Total:</Text>
|
||||
<Text style={styles.totalFinalValue}>{formatZAR(total)}</Text>
|
||||
<Text style={styles.totalFinalValue}>{formatZAR(totalInclVat)}</Text>
|
||||
</View>
|
||||
</View>
|
||||
</Page>
|
||||
|
|
|
|||
Loading…
Reference in a new issue