← All tests

POS Section Rework — Slice 1 (prod)

2026-05-14 Gate 2 on Supabase prod + get-coffee. First slice of the POS Section Rework arc (Narong spec items 8 & 9): the session-scoped landing-summary data layer SHIPPED. The /cafe/pos landing cards were already session-scoped — the real defect was the summary query filtering state <> 'closed', so a register whose latest session had already closed showed a blank, all-zeros card. The data layer now takes the register's latest session of any state and surfaces its closing-side metrics. Pure data-layer change — the card UI is Slice 2. No migration.

8/8 prod test PASS — bug fix confirmed on get-coffee's real data. 1 commit, no migration.
/cafe/pos landing on get-coffee

Prod probe — get-coffee, 5 Pro registers

latest-session state spread:  { closed: 4, open: 1 }   (69 sessions total)

register   state    sold    orders  openingCash  endingCash  cashSales  cashIn  cashOut  theoreticalClosing
  cfg 4    closed   11.50      3        0.00        0.00        0.00      0.00    0.00       0.00
  cfg 5    closed    5.00      1        0.00         —          5.00      0.00    0.00       5.00
  cfg 6    opened   13.75      2      100.00         —         30.00      0.00    0.00     130.00
  cfg 7    closed    3.00      1        0.00        0.00        3.00      0.00    0.00       3.00
  cfg 8    closed    0.00      0        0.00        0.00        0.00      0.00    0.00       0.00

Pre-Slice-1: cfg 4 / 5 / 7 / 8 all returned state 'none' + zeros (filtered
out by `state <> 'closed'`). Now each surfaces its closed session's real
numbers. Some closed sessions carry $0 opening/ending cash — that's
get-coffee's actual seed/test data; the probe's independent recompute
matched the helper's output for every metric, so the helper is faithfully
reporting what's in the tables.

Prod test — 8/8

✓ Part A — prod DAO probe ran clean against get-coffee
✓ fetchSessionSummariesFromMirror covers every Pro register + carries all new fields
✓ Latest-session pick matches an independent JS fetch-all-and-pick (real history)
✓ Canary session metrics match an independent recompute from the tables
✓ Closed-latest register surfaces real numbers, not a blank card (the bug fix, real data)
✓ Part B — SSO login to get-coffee
✓ /cafe/pos landing renders register cards on the deployed Worker (no 5xx)
✓ Manager-live drawer endpoint responds (consumes the reworked data layer)
59/59 regression green — no regressions from this push. 67/67 effective (8 Slice 1 prod + 59 regression).
test-phase1-prod.mjs — route/SSO smoke11/11
test-phase2-sso-outdoor-prod.mjs6/6
test-phase2-cafe-multishop-prod.mjs6/6
test-m1-prod.mjs — shop scoping10/10
test-r7-prod.mjs — dashboard + manager-live drawer14/14
test-r8-prod.mjs — auth/security4/4
test-r1-2-landing-prod.mjs — POS landing8/8

Files touched — commit 3459a9e

nix-cafe (6 files, no migration):
  lib/db/cafe_sessions.ts     (+ fetchLatestSessionSummaries, computeTheoreticalClosing,
                                 landingStateForSession, SessionSummary type)
  lib/db/pos_configs.ts       (fetchSessionSummariesFromMirror reworked; type extended)
  lib/db/starter_landing.ts   (buildStarterLanding → shared helper)
  lib/db/manager_live.ts      (nixCashByConfig overlay removed; cardFor extended)
  lib/odoo/queries.ts         (PosConfigSummary extended + placeholder defaults)
  app/(authed)/pos/pos-landing.tsx  (LandingConfig type extended — UI consumes in Slice 2)

Next — Slice 2

Slice 1 ships the DATA. The landing card UI still renders the old 3-cell
layout (Cash opening / Sold today / Opened) and shows "—" for closed
registers — it doesn't read the new closing-side fields yet. Slice 2
reworks RegisterCard to the Odoo-parity layout (Opening / Closing balance,
Cash + Bank balance, Sold) and makes the closed-register card show its
final numbers per the locked decision. The soldToday/bankToday → sold/bank
rename also rides along in Slice 2's card rework.