feat: mid-shift X-report (read-only takings-so-far)
Let the operator see, on demand during an open shift, the opening float inherited, cash/card collected so far, pay-ins/pay-outs, and the current expected drawer balance — without closing. GET /api/shift/report (shift:read; 204 when no shift is open) returns the same drawer projection the Z-report computes. Factored that math into a shared ShiftService.#summariseWindow(open, asOf) used by BOTH the X-report (asOf=now, read-only) and close()'s Z-report (asOf=endedAt, signed), so the two can't drift. The X-report appends NOTHING — it's a snapshot, not an accountability mark; the Z-report at close remains the signed record. UI: a "Takings so far" button on the shift control reveals a cyan X-report panel; the header still shows the live drawer total for the at-a-glance figure. Verified against a copy of the live DB: X figures match drawerBalance(), the drawer identity holds, zero events appended, chain still verifies. Claude-Session: https://claude.ai/code/session_01Xcm6ikLgGoCxxHrxtjkk5V
This commit is contained in:
+10
-6
@@ -204,11 +204,15 @@ reconciles the signed Z-report against the actual drawer and the bank/POS batch
|
||||
- **Shift ↔ session boundary:** a vehicle may enter under one shift and pay under another — the
|
||||
Z-report sums by **payment time** (when cash/card was taken), which is the operator who handled
|
||||
the money. Confirm that's the intended accountability (vs. by entry).
|
||||
- **Mid-shift report / X-report — REQUESTED 2026-06-20, not yet built.** The operator wants to see,
|
||||
on demand during the shift, the **opening float inherited**, **cash collected so far**, the
|
||||
pay-ins/pay-outs, and the **current expected drawer balance** — without closing. It's the same
|
||||
drawer projection the Z-report computes, just read-only and mid-shift. (The header already shows the
|
||||
live drawer *total*; this is the full breakdown.) Deferred behind the voucher re-model done the same
|
||||
day; build next if wanted.
|
||||
- **Mid-shift report / X-report — BUILT 2026-06-20.** On demand during the shift, the operator sees
|
||||
the **opening float inherited**, **cash/card collected so far**, the **pay-ins/pay-outs**, and the
|
||||
**current expected drawer balance** — without closing. `GET /api/shift/report` (`shift:read`, 204
|
||||
when no shift is open) returns the SAME drawer projection the Z-report computes, factored into a
|
||||
shared `ShiftService.#summariseWindow(open, asOf)` so X (asOf = now, read-only) and Z (asOf =
|
||||
endedAt, signed) can never drift. **It appends NOTHING** — it's not an accountability mark (the
|
||||
Z-report at close is the signed record). UI: a "Takings so far" button on the shift control opens a
|
||||
cyan X-report panel; the header still shows the live drawer *total* for the at-a-glance number.
|
||||
Verified against a copy of the live DB: matches `drawerBalance()`, drawer identity holds, 0 events
|
||||
appended, chain still verifies.
|
||||
- **Multiple lanes/booths** — whether a shift is per-operator, per-booth, or per-site
|
||||
(relates to [[open-questions]] #1 lane topology).
|
||||
|
||||
Reference in New Issue
Block a user