PRD: Shift reports (X/Z)
| Module | Reports | PRD ID | PRD-SHF-001 |
| Status | Ready to dev | FEAT | SHF · BANA-1440 |
| Epic | — | Plane | BANA-1556 |
| Date | 2026-04-22 | Version | v0.1 |
| Packages | @nx/sale | URD | SHF |
| Surface | Sale · POSClient · Owner/Mgr | ||
| Owner | Phát Nguyễn | ||
TL;DR
Reconcile the cash drawer at the counter: an X report for a repeatable mid-shift snapshot, a Z report for the locked close-shift figures. Each pairs cash reconciliation (opening float, cash sales, pay-in/out, expected vs. actual, discrepancy) with a sales summary - so every shift closes on a number you can verify, not a guess.
1. Context & Problem
POS cashiers work in shifts: a shift opens, one or more cashiers work it, then it closes. Today a shift tracks cash movements but produces no report - so there is no way to read shift totals or reconcile the drawer at the counter. A cashier can't see expected vs. actual cash, can't pull an interim mid-shift summary, and has no locked snapshot to hand off at close. Handovers fall back on manual counting, and the owner gets no auditable record of what each shift took in - a blocker for the cash-honest operations BANA targets at HKD/SME scale.
This increment delivers the two reports a cashier expects against a shift - an interim X report and a closing Z report - backed by a locked closing snapshot, built on the existing shift lifecycle and cash-movement tracking.
2. Goals & Non-Goals
Goals
- An X report (interim): a live in-shift snapshot taken from the current open shift, repeatable any number of times.
- A Z report (closing): the final close-shift report, read once per shift and backed by a locked closing snapshot.
- Cash reconciliation: opening float, cash sales, pay-in / pay-out, expected vs. actual counted cash, and discrepancy, with a counted-cash recount captured at close.
- A sales summary on the report: gross, discount, tax, net, and order count.
- Merchant + sale-channel scoping and shift listing with pagination.
Non-Goals
- Daily / product / category sales reports - owned by the
SLSfeature (URD-SLS). - Profit & loss, inventory valuation, customer analytics, export, and scheduled reports -
ADV, Planned (URD-ADV). - Payment-method and category breakdowns on the shift report (Should-level URD-SHF-005..006).
- PIN step-up on report access.
3. Success Metrics
| Metric | Target / signal |
|---|---|
| Reconciliation coverage | 100% of closed shifts produce exactly one Z report |
| Cash accuracy | Discrepancy = counted cash − (opening float + cash sales − pay-outs); surfaced on every close |
| Interim usability | X report is repeatable mid-shift and leaves the shift unchanged |
| Scoping correctness | Zero cross-merchant figures returned on any report |
4. Personas & Use Cases
| Persona | Goal in this feature |
|---|---|
| Cashier | Pull an X report mid-shift; close the shift to produce the Z report with a counted-cash reconciliation |
| Manager | Review any shift's Z report for their merchant |
| Owner | See shift reconciliation across their merchants |
Core scenarios: open a shift → other cashiers may join while it runs → pull an X report mid-shift (repeatable) → at close, count actual cash → the system computes expected vs. actual and locks a Z report snapshot, one per shift.
5. User Stories
- As a cashier, I want to pull an X report from my open shift, so I can check interim cash and sales totals without closing the shift.
- As a cashier, I want the X report to be repeatable, so I can re-check totals as the shift progresses.
- As a cashier, I want to close my shift with a counted-cash recount, so the Z report shows expected vs. actual and the discrepancy.
- As a manager, I want exactly one locked Z report per shift, so closed-shift figures can't drift.
- As an owner, I want shift reports scoped to my merchant, so no other merchant's figures leak in.
6. Functional Requirements
| # | Requirement | URD ref |
|---|---|---|
| FR-1 | X report (interim): request a live snapshot of the current open shift; repeatable, leaves the shift unchanged | URD-SHF-001 |
| FR-2 | Z report (closing): the aggregated close-shift report, read once per shift, backed by a locked closing snapshot | URD-SHF-002 |
| FR-3 | Cash reconciliation: opening float, cash sales, pay-in / pay-out, expected vs. actual counted cash, discrepancy, plus a counted-cash recount captured at close | URD-SHF-003 |
| FR-4 | Sales summary on the report: gross, discount, tax, net, order count | URD-SHF-004 |
| FR-5 | Reports scoped per merchant and sale channel; shift listing with pagination and filters | URD-SHF-001..002 |
| FR-6 | Only authorized users (read permission on shift reports) can open the two reports | URD-SHF-001..002 |
Full requirement text and acceptance criteria live in the Reports URD. This PRD references them rather than restating them. Payment-method and category breakdowns (URD-SHF-005..006, Should) are out of this increment -
SHFremains In-progress.
7. Non-Functional Requirements
| Area | Requirement |
|---|---|
| Data integrity | The Z report is a one-per-shift terminal snapshot; once locked at close it does not change |
| Read-only | Reports aggregate over cash movements and completed orders; the X report never changes the shift |
| Tenancy & authz | All operations are confined to the user's own merchant and sale channel; the two reports are opened only by users with read permission on shift reports |
| Precision | Cash and monetary amounts are tracked to 4-decimal precision |
| Performance / scale | Shift listing is paginated; report aggregation runs over a single shift's movements |
| i18n | User-facing labels/statuses are bilingual (English / Vietnamese) |
8. UX & Flows
Key screens: the shift view, the X-report action, the close-shift recount, and the Z-report view.
9. Data & Domain
| Concept | Role |
|---|---|
| The shift | A working session a cashier opens and closes, joinable by one or more cashiers while it runs - lifecycle (open/close), cash-movement tracking, counted-cash recount at close |
| The locked closing snapshot | The final close-shift (Z) figures captured at close - cash reconciliation + sales summary, one per shift |
| The cash movements | Pay-in / pay-out and cash sales aggregated by the report to feed the reconciliation |
Conceptual only - full detail and invariants in the shift domain model.
10. Dependencies & Assumptions
Depends on
- Shift lifecycle & cash-movement tracking - the X/Z reports aggregate an open or just-closed shift.
- Completed orders (Orders) - the sales summary aggregates completed orders in the shift.
- Cash / payment movements - pay-in/out and cash sales feed the reconciliation.
- Shift data store - holds the shift and its locked closing snapshot.
Assumptions
- A cashier opens a shift with an opening float before transacting.
- Each shift closes exactly once, producing exactly one Z report.
11. Risks & Open Questions
| Risk / question | Mitigation / status |
|---|---|
| Cash reconciliation diverging from the finance ledger | The report aggregates cash movements directly and owns the shift's reconciled view, so the closing report - not the ledger - is the source of truth for the shift |
| Double Z report per shift | Z report is read once per shift against a locked snapshot; terminal by design |
| Payment-method / category breakdowns expected by some merchants | Out of this increment (URD-SHF-005..006); SHF stays In-progress until delivered |
| PIN step-up on report access | Out of scope here; tracked separately |
12. Release Plan & Launch Criteria
| Aspect | Plan |
|---|---|
| Phase | P2 - see URD feature catalog |
| Rollout | All merchants; no feature flag |
| Migration | New capability with no merchant-facing data migration; the closing report owns the shift's reconciled view |
| Launch criteria | X report repeatable on an open shift; exactly one Z report per closed shift; cash reconciliation and sales summary verified against counted cash |
| Monitoring | Z reports per closed shift (expect 1:1), reconciliation discrepancy distribution, report request error rate |
13. FAQ
What is the difference between an X report and a Z report? The X report is an interim, repeatable mid-shift snapshot pulled while the shift is open; the Z report is the final close-shift report, produced once per shift and locked.
Does pulling an X report change anything? No - it is read-only and repeatable; it does not change the shift or any cash records.
Can a shift have more than one Z report? No - exactly one Z report is produced per shift at close, backed by a locked snapshot.
How does the report stay consistent with the ledger? The report aggregates cash movements directly and owns the shift's reconciled view, so the closing report is the source of truth for the shift's cash position.
Do shift reports include payment-method or category breakdowns? Not in this increment - those are Should-level (URD-SHF-005..006) and remain open.
References
- URD: Reports → Shift Reports - requirements (SHF area)
- Related: Sales Reports · Access & Scoping · Advanced Analytics
- Module: Reports - URD
- Developer: Shift domain model - shift lifecycle and the closing snapshot