From f6bfb6f1eb972826ef75ccb9044454efbc90f0d1 Mon Sep 17 00:00:00 2001 From: Dave Date: Mon, 31 Aug 2026 01:30:15 +0200 Subject: [PATCH] feat(pos): add PosCatalogItem/PosSale/PosSaleItem types Supports all four POS tender types (cash/card/eft/account) rather than just cash/card: only cash puts money in the drawer, so cashup needs the distinction. PosSale.client_ref carries the till's local sale id as an idempotency key for the offline queue. Co-Authored-By: Claude --- src/lib/types.ts | 64 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/src/lib/types.ts b/src/lib/types.ts index f457cda..d14736b 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -1535,6 +1535,70 @@ export interface StockLedger extends BaseRecord { }; } +// ───────────────────────────────────────────────────────────────── +// WFSALES POS (standalone counter-sale app) — added 2026-08-30 +// ───────────────────────────────────────────────────────────────── + +/** Shape returned by GET /api/v1/pos/catalog — flattened stock_items row. */ +export interface PosCatalogItem { + id: string; + sku: string; + name: string; + description: string; + unit: string; + /** Expanded category name, or "" if uncategorised. */ + category: string; + current_qty: number; + selling_price: number; + cost_price: number; +} + +/** + * The four tender types the POS offers. Only `cash` puts money in the + * drawer — `card` and `eft` settle outside the till, and `account` is + * pay-later (the customer takes the goods on a delivery note). Cashup + * relies on that distinction, so all four are recorded distinctly + * rather than collapsed to cash/card. + */ +export type PosPaymentMethod = "cash" | "card" | "eft" | "account"; + +export const POS_PAYMENT_METHOD_VALUES: readonly PosPaymentMethod[] = [ + "cash", + "card", + "eft", + "account", +] as const; + +export interface PosSale extends BaseRecord { + sale_number: string; + payment_method: PosPaymentMethod; + /** Only meaningful for `cash`; 0 for every other tender. */ + cash_given: number; + change_given: number; + subtotal: number; + vat: number; + total: number; + /** customers relation id, or "" for a walk-in with no customer picked. */ + customer: string; + /** + * Client-generated idempotency key (the POS device's local sale id). + * A sale that was committed server-side but whose response never + * reached the till gets re-posted by the offline queue; matching on + * this returns the original sale instead of decrementing stock twice. + */ + client_ref: string; +} + +export interface PosSaleItem extends BaseRecord { + sale: string; + stock_item: string; + sku: string; + description: string; + qty: number; + unit_cost: number; + unit_price: number; +} + // ───────────────────────────────────────────────────────────────── // Stock purchases (v2 pure stock-purchase flow) — added 2026-07-14 // ─────────────────────────────────────────────────────────────────