mega-plant/lib/purchase-invoice-status.ts
David 642d23dd24 Suppliers: replace the menu entry with the new page, flag over-invoiced POs, audited invoice amount corrections
- Menu: old Suppliers leaf hidden (route kept), Suppliers 2 renamed Suppliers
- PO invoice status: new 'over' state (never closed), live over-PO warning when typing
- Admin correction of invoice amount/date/number with mandatory reason, logged to purchase_invoice_edits
- Payable now carries unpaid balance forward month to month

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-29 20:49:05 +02:00

27 lines
1.5 KiB
TypeScript

/** How far a purchase order has been invoiced. Pure — client-safe. Shared by Purchases and Suppliers 2. */
/** Invoiced within this many rand of the PO total counts as fully invoiced (rounding). */
export const CLOSE_TOLERANCE = 1;
export type InvoiceStatus = "none" | "partial" | "complete" | "over";
/**
* red = no invoice; amber = some invoiced but the money does not cover the PO (an invoice with
* no amount typed in also lands here, since its value is unknown); teal = invoiced to within R1
* of the PO total, so it can be closed; purple = invoiced MORE than the PO by over R1. That is
* never "closed": it is a typo, a duplicate or a changed order, and a person has to look.
*/
export function invoiceStatusOf(total: number, amounts: (number | null)[]): { status: InvoiceStatus; invoiced: number } {
const invoiced = amounts.reduce<number>((s, a) => s + (a ?? 0), 0);
if (amounts.length === 0) return { status: "none", invoiced };
if (invoiced - total > CLOSE_TOLERANCE) return { status: "over", invoiced };
if (invoiced > 0 && total - invoiced <= CLOSE_TOLERANCE) return { status: "complete", invoiced };
return { status: "partial", invoiced };
}
export const STATUS_STYLE: Record<InvoiceStatus, { color: string; label: string }> = {
none: { color: "#D1495B", label: "No invoice yet" },
partial: { color: "#EDAE49", label: "Partly invoiced" },
complete: { color: "#00798C", label: "Fully invoiced — can be closed" },
over: { color: "#8B5CF6", label: "Invoiced MORE than the PO — check" },
};