- 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>
27 lines
1.5 KiB
TypeScript
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" },
|
|
};
|