Commit Graph

2 Commits

Author SHA1 Message Date
denis_ireri f865837b27 Address the 11 October test report findings
The initial test report (run before the pilot-readiness changes) raised
seven findings and a retest plan. This closes the ones still open.

- F-01: a business on its free trial may run 2 active branches whatever
  its tier, so an owner can try transfers and per-branch stock. Only
  active branches count towards any limit.
- F-06: owners can rename branches and deactivate/reactivate them from
  the Branches page. A branch can only be deactivated once it holds no
  stock and no active staff; its history stays in every report, and it
  leaves every picker.
- F-04: the Products page lists deactivated products under a toggle with
  Reactivate. Deactivating warns about stock still on hand, which stays
  on the Stock page so it can be transferred or counted out.
- F-05: products carry a unit (L, ml, kg, g, pcs, tray, pack) instead of
  everything being litres.
- CAT-12: product prices must be above zero and names are unique per
  business, ignoring case.
- F-03: a reversed report period is refused by the page and the API, and
  the page labels which period the cards show. Report dates are Nairobi
  business days.
- F-07: cost of goods sold is units sold x average buying price. Stock
  bought in the period is reported separately, with a cash surplus line,
  so unsold stock no longer shows as a loss.
- STA-04: staff and new branch managers can be invited with a one-time,
  7-day link; the person sets their own password. Managers can issue a
  new link for their own cashiers.
- OFF-02 / POS-02: the till shows each product's stock and deducts every
  sale immediately, online or offline; it warns before selling more than
  the recorded stock, and has a Clear sale button.
- npm run backfill:stock turns purchases recorded before the stock ledger
  into stock, so existing tenants (and the report's ZERRO fixtures) start
  from what they bought.

tests/retest-plan.test.ts runs the report's completion and retest plan
and checks every balance and total it predicts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 10:29:21 +03:00
denis_ireri 8817c0f52f Add a stock ledger, inter-branch transfers and a sync protocol that cannot jam
Stock (PRD 5.2): a branch's stock of a product is now the sum of its
StockMovement rows. Every movement names the document that caused it and
(type, refId) is unique, so replaying a sale, retrying a transfer or a
second M-Pesa callback never moves the same stock twice.

- Cash sales and confirmed M-Pesa payments deduct stock; purchases of a
  catalogue product add it.
- POST /api/stock/transfers moves stock between two branches (owner: any
  two; manager: out of their own) and refuses to send more than the
  sending branch holds. Double submits are applied once.
- POST /api/stock/adjustments records opening stock, breakage or a
  physical count (the ledger is corrected to the counted number).
- GET /api/stock returns every branch x product with LOW/OUT flags
  (per-product lowStockThreshold, default 10); GET /api/stock/movements
  is the history.

Sync (PRD 5.3/5.5): POST /api/transactions/cash now returns a result per
sale - saved, duplicate or rejected - instead of silently skipping
replays. The old client never learned a replayed sale had synced, so
rows piled up until the batch passed the 100-sale limit and every flush
failed with 400. Also:
- A sale can hold several products (one Transaction per line, grouped by
  saleId); the old single-product payload is still accepted.
- One bad sale is rejected on its own instead of failing the batch.
- A queued sale is only accepted from the cashier who recorded it, and
  stays with the branch where it happened.
- A product deactivated while offline is still recorded at its price; an
  invalid phone is dropped rather than losing the sale; the phone is now
  optional for cash sales.
- The price the device showed is kept and a difference is flagged
  (priceMismatch) instead of being silently overwritten.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 18:39:11 +03:00