PRD: Reservations
| Module | Sale | PRD ID | PRD-RSV-001 |
| Status | Ready to dev | FEAT | RSV |
| Epic | — | Plane | BANA-1560 |
| Date | 2026-05-29 | Version | v1.0 |
| Packages | @nx/sale | URD | RSV |
| Surface | Sale · POS | ||
| Owner | Phát Nguyễn | ||
TL;DR
Lets a full-service venue take table bookings ahead of service - guest, party size, date/time, table/room - drive them through a clear lifecycle, and turn a booking into a live order on check-in without re-keying. Floor view and zone availability update in real time, so hosts always know what's held, confirmed, or seated.
1. Context & Problem
Full-service F&B venues take table bookings before service: a host records the guest, party size, and a date/time, then seats the party on arrival. BANA's order flow has no first-class booking entity, so a future booking and its eventual order are disconnected - the host re-keys the order at the table, holds on a zone/unit are invisible, and the floor view cannot show what is reserved versus seated. This blocks the host workflow that full-service venues depend on and makes table utilisation impossible to track.
This feature adds a first-class reservation entity - its own lifecycle, source/occasion metadata, and a zone/unit hold - connecting the booking to a live order on check-in.
2. Goals & Non-Goals
Goals
- A reservation entity capturing guest name, phone, party size, and date/time, scoped to the merchant.
- A booking lifecycle:
PENDING → CONFIRMED → CHECKED_IN / CANCELLED- reservations are created directly as CONFIRMED today (no separate confirm step; PENDING is never produced), so the effective lifecycle isCONFIRMED → CHECKED_IN / CANCELLED. - Occasion tagging (birthday, anniversary, business, etc.) captured on create. A source field (phone, walk-in, online, other) exists on the data model but is not yet accepted on create - defaults to phone - so source tracking is not functional yet.
- Auto-spawn and link a sale order on check-in, so the booking becomes the live order without re-keying.
- Zone/unit (table/room) holds via a table/room hold record, with real-time updates to the floor view.
Non-Goals
- Table-layout / seating management - Planned, separate from booking.
- A dedicated kitchen display application.
- Order templates and delivery order tracking.
3. Success Metrics
| Metric | Target / signal |
|---|---|
| Re-key elimination | 100% of checked-in reservations spawn and link a sale order (no manual order creation at the table) |
| Floor accuracy | Zone/unit availability reflects active reservation holds with no stale entries |
| Real-time sync | Reservation and zone updates propagate to the floor view in real time within the live session |
| Booking conversion | Share of confirmed reservations that reach CHECKED_IN trends up per merchant |
4. Personas & Use Cases
| Persona | Goal in this feature |
|---|---|
| Host | Take and manage bookings, hold the right table, check guests in |
| Cashier | Continue the spawned order from check-in without re-entry |
| Manager / Owner | See table holds and booking activity on the floor view |
Core flow: host creates a reservation (party size, date/time, table) - recorded immediately as CONFIRMED → guest arrives, host checks in → order spawns and links, table hold is recorded, floor view updates live.
5. User Stories
- As a host, I want to create a reservation with guest name, phone, party size, and date/time, so the booking is recorded against the merchant.
- As a host, I want to cancel a booking, so its lifecycle reflects what will actually happen. (Reservations are created already confirmed; no separate confirm step exists.)
- As a host, I want to tag the occasion of a booking, so the venue can prepare and report on it. (Source field exists on the model but is not yet accepted on create.)
- As a host, I want to hold a specific table/room for a booking, so the floor view shows it as reserved.
- As a host, I want check-in to spawn and link a sale order, so the seated party's order continues from the booking without re-keying.
- As a manager, I want the floor view and zone availability to update in real time, so holds and seatings are always current.
6. Functional Requirements
| # | Requirement | URD ref |
|---|---|---|
| FR-1 | Create a reservation with guest name, phone, party size, and date/time, scoped to the merchant | URD-RSV-001 |
| FR-2 | Lifecycle PENDING → CONFIRMED → CHECKED_IN / CANCELLED - partial: a reservation is created directly as CONFIRMED (no separate confirm step / endpoint; PENDING is not produced), so the effective lifecycle is CONFIRMED → CHECKED_IN / CANCELLED | URD-RSV-002 |
| FR-3 | Source tracking: phone, walk-in, online, other - data model only: the field exists but is not accepted on create (defaults to phone), so it is not functionally tracked yet | URD-RSV-003 |
| FR-4 | Occasion tagging: birthday, anniversary, business, etc. | URD-RSV-004 |
| FR-5 | On check-in, spawn and link a sale order to the reservation | URD-RSV-005 |
| FR-6 | Table/room (zone/unit) association via a table/room hold record; filter by the table/room and zone | URD-RSV-001 |
| FR-7 | Real-time updates for the table/room hold record and zones to keep the floor view and zone availability live | URD-RSV-002 |
Full requirement text and acceptance criteria live in the Orders URD. This PRD references them rather than restating them.
7. Non-Functional Requirements
| Area | Requirement |
|---|---|
| Data integrity | A checked-in reservation and its linked order are written together; the table/room hold record is captured so a hold is never lost |
| Tenancy & authz | All operations confined to the user's own merchant; reservation actions are permission-gated |
| Performance / scale | List/filter of orders and reservations uses optimized querying; creation time surfaced for list ordering |
| Real-time | Table/room hold record and zone changes emit real-time updates for the floor view within the session |
| i18n | User-facing labels/statuses are bilingual (English & Vietnamese) |
8. UX & Flows
Front-of-house surfaces live in the POS front end: Reservation Sheet, detail view, create from list, date/time editing, and real-time update handling.
9. Data & Domain
| Entity | Role |
|---|---|
| Reservation | Booking - guest, party size, date/time, occasion, status, optional linked order (source field modelled but not yet accepted on create) |
| Table/room hold record | Record holding the reserved zone/unit (table/room) for the reservation |
| Order | Spawned and linked on check-in so the booking becomes the live order |
Conceptual only - full schema and invariants in the sale domain model.
10. Dependencies & Assumptions
Depends on
- Sale Order (URD-ORD) - check-in spawns and links a sale order.
- Zone/unit hold model - holds the reserved table or room against the booking.
- Real-time update layer - floor view and zone availability are kept live via real-time updates.
Assumptions
- The merchant defines zones/units (tables/rooms) that a reservation can hold.
- A host operates the front-of-house surface (the POS front end).
11. Risks & Open Questions
| Risk / question | Mitigation / status |
|---|---|
| A hold could diverge from the booking on partial failure | The table/room hold record is captured with the reservation; check-in writes booking + order together |
| No table-layout / seating management | Out of scope this increment; reservation holds a zone/unit but layout is Planned |
| Stale zone availability if a real-time update is missed | Floor view reconciles on hold and zone updates; revisit if drift is observed |
| Cancellation after a hold | Lifecycle supports CANCELLED; hold is released on cancel |
12. Release Plan & Launch Criteria
| Aspect | Plan |
|---|---|
| Phase | P2 (F&B extensions) - see Orders URD feature catalog |
| Rollout | All F&B merchants; no feature flag |
| Migration | New entity; the table/room hold record extended for zone/unit binding |
| Launch criteria | Create → confirm → check-in verified end-to-end; order spawned and linked; zone hold and real-time updates verified live |
| Monitoring | Reservation volume per merchant, check-in conversion, zone-hold consistency, real-time update delivery |
13. FAQ
Does check-in create the order automatically? Yes - check-in spawns and links a sale order automatically.
Can a reservation hold a specific table or room? Yes - the hold is recorded per zone/unit, and the reservation list can filter by table or room.
What happens to the table hold if a booking is cancelled? The hold is released - status moves to CANCELLED and the zone/unit becomes available again.
Does this include drag-and-drop table-layout management? No - table-layout / seating management is Planned (a separate increment). This feature holds a zone/unit but does not manage the floor plan.
How does the floor view stay current? Hold and zone changes emit real-time updates within the session.
References
- URD: Orders - Reservations
- Builds on: Sale Order
- Module: Orders - URD
- Developer: @nx/sale · domain model