J-10 — Group Booking with Multiple Rooms & Single Folio
One-liner: A group books multiple rooms; the front desk treats them as one party with a master folio routed to a corporate payer.
1. Purpose
A group of guests (corporate, wedding, tour) books multiple rooms; the property must treat them as one party with a master folio that captures the group balance and routes payment to a corporate payer. Outcome: a group reservation with N child reservations, a master folio with correct routing of charges per guest's preference, and a single check-out experience for the corporate payer.
2. Persona Context
- Persona: Receptionist / Group Coordinator.
- Surface: Electron Desktop.
- Primary BFF:
bff-backoffice-service. - Backing services:
booking-service,folio-service,payments-service,audit-service. - Preconditions: Tenant has group-booking feature enabled; corporate payer exists in CRM (or is created inline).
- Trigger: Receptionist clicks "New group booking" or imports from a sales lead.
3. Entry Points
| # | Entry | Notes |
|---|---|---|
| 1 | "New group booking" CTA on Front Desk | Default |
| 2 | Import from sales lead (P2) | CRM-driven |
| 3 | Walk-up group walk-in | Manual entry |
4. Screen-by-Screen Flow
4.1 GroupSetupScreen
- Layout: Group name, organizer (corporate payer), contract code (optional), arrival window, departure window, special instructions.
- Components:
Form,OrganizerPicker(search + create),DateRangePicker. - Offline: Editable; queued.
- AI: Phase 2 — corporate matcher suggestion.
- Errors: Validation per field.
- Loading: Sub-200 ms.
- A11y: Field labels.
- RTL: Mirror.
- Perf: <= 200 ms.
- Telemetry:
frontend.group.setup_started.
4.2 RoomBlockBuilder
- Layout: Add N room types; assign per-room guest names; quick-add for repeat guests; contracted rate plans selectable.
- Components:
RoomBlockTable,GuestRow,RatePlanSelect,Button("Add room"). - Offline: Local edits; queued.
- AI: None.
- Errors: Insufficient inventory -> banner with alternatives.
- Loading: Sub-200 ms.
- A11y: Table semantics; row-add announces "Room
added". - RTL: Mirror.
- Perf: <= 200 ms per add.
- Telemetry:
frontend.group.room_added;frontend.group.guest_assigned.
4.3 MasterFolioRoutingScreen
- Layout: Per-charge-type matrix (room, taxes, F&B, extras) with routing target (master / individual / split %) per row; visual preview of master folio + per-room incidental folios.
- Components:
RoutingMatrix,FolioPreview. - Offline: Local edits; queued.
- AI: None.
- Errors: Routing must sum to 100% per row -> validation.
- Loading: Sub-200 ms.
- A11y: Matrix is a structured
<table>with headers; preview block has live region. - RTL: Mirror.
- Perf: <= 200 ms re-preview on change.
- Telemetry:
frontend.group.routing_changed.
4.4 ConfirmGroupBookingScreen
- Layout: Summary of all rooms, guests, master folio routing, total estimate, deposit terms; "Confirm" CTA.
- Components:
GroupSummaryCard,Button("Confirm group"). - Offline: Local persist; queued.
- AI: None.
- Errors: Conflict on a sub-room -> per-row error display; confirm button disabled until resolved.
- Loading: Confirm <= 3 s p95 (multi-aggregate write).
- A11y: Summary announced in segments; confirm announces success/failure.
- RTL: Mirror.
- Perf: Confirm <= 3 s p95.
- Telemetry:
frontend.group.confirmed { groupId, roomCount }.
5. State Machine
6. Data Requirements
6.1 Server state
POST /api/v1/group-bookings(idempotent; multi-aggregate write inside booking-service)GET /api/v1/group-bookings/:idPATCH /api/v1/group-bookings/:id/routing
6.2 Local persistence
- SQLite
group_bookings_local,group_room_assignments_local,outbox. - Master folio reflected in
folios.
6.3 Idempotency
- Group create idempotent at the group level; sub-room creates idempotent per assignment.
7. AI Behavior
n/a in P1; P2 — group-rate optimisation suggestion (HITL).
8. Offline Behavior
- Walk-in path (J-07) handles offline group creation; conflict UX in Sync Center.
- Online: full multi-room transaction.
9. Error States
| Error | Trigger | UX shown | Recovery | Telemetry |
|---|---|---|---|---|
INSUFFICIENT_INVENTORY_FOR_BLOCK | Not enough rooms | Banner with alternatives | Adjust block | frontend.group.insufficient_inventory |
ROUTING_NOT_100PCT | Row sum != 100% | Inline error | User adjusts | frontend.group.invalid_routing |
SUB_ROOM_CONFLICT_ON_CONFIRM | Concurrent booking grabbed a room | Per-row error display | Re-pick room | frontend.group.sub_room_conflict |
MULTI_AGGREGATE_WRITE_FAILED | Server-side multi-write rollback | Banner with retry | Retry | error.surfaced { code } |
10. E2E Test Gates
- Composite gate
G-DESK-OPS-2: setup -> room block -> routing -> confirm -> single master folio created. - Sub-room conflict variant.
- Routing change propagation verified.
11. Performance Requirements
| Metric | Target |
|---|---|
| Each step transition | <= 200 ms |
| Routing re-preview | <= 200 ms |
| Confirm RTT | <= 3 s p95 |
12. Accessibility Requirements
- Routing matrix is a
<table>with row/column headers. - Live region announces summary updates.
- All keyboard-completable.
13. Telemetry
Frontend events
frontend.group.setup_startedfrontend.group.room_added/guest_assignedfrontend.group.routing_changedfrontend.group.confirmed { groupId, roomCount }
Domain events emitted
melmastoon.booking.group.created.v1melmastoon.booking.created.v1(per sub-room)melmastoon.folio.master.opened.v1melmastoon.audit.recorded.v1
14. Success Criteria
- Group of N rooms created in <= 3 s p95.
- Single master folio with correct routing routing per charge type.
- Conflicts surfaced per row; no silent overbookings.
- Audit log entries for group + each sub-room.