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 <noreply@anthropic.com>
This commit is contained in:
Dave 2026-08-31 01:30:15 +02:00
parent a73f3b3f97
commit f6bfb6f1eb

View file

@ -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
// ─────────────────────────────────────────────────────────────────