Skip to main content

J-07 — Walk-In Booking with Cash Deposit (Offline)

One-liner: Internet down at the front desk; receptionist creates a new reservation, takes cash, issues a key, and trusts that everything reconciles when the link is back.

1. Purpose

The internet is down at the front desk. A walk-in guest needs a room now. The receptionist must create a new reservation, take cash, issue a key, and trust that the system will reconcile when the link is back. Outcome: a reservation in Confirmed (and possibly Checked-in) state, a folio with a cash deposit, an issued key — all locally — that reconciles cleanly when the network returns.

2. Persona Context

  • Persona: Receptionist.
  • Surface: Electron Desktop (apps/desktop), offline-primary.
  • Primary "BFF": None online. The Electron app's local SQLite + outbox + signed offline-cert acts as the system of record for the duration of the outage.
  • Backing services (when reconnected): booking-service, folio-service, payments-service, lock-and-key-service, audit-service.
  • Preconditions: Electron app has fresh "primer" pack (today's published rates + room inventory + tenant policies + offline-cert valid for the day). Cash drawer is opened and counted at start-of-shift.
  • Trigger: A walk-in guest at the desk + connectivity indicator showing "Offline".

3. Entry Points

#EntryNotes
1"New booking" CTA on Front Desk screen with offline pill visibleDefault
2Quick action keyboard shortcut (e.g., Ctrl+N)Power user

4. Screen-by-Screen Flow

4.1 OfflineBanner (always visible during this journey)

  • Layout: Persistent banner: "Offline mode - changes will sync when connection returns. Pending: events."
  • Components: OfflineStatusPill, SyncCenterButton.
  • Offline: Always reflects local state.
  • A11y: Banner announced at offline-state change; status pill is keyboard-reachable and opens Sync Center.

4.2 WalkInBookingWizardStep1RoomTypeSelection

  • Layout: Same as J-03 §4.1 but reads inventory from local SQLite snapshot; rate plan from primer.
  • Components: RoomTypeListCard, OccupancyEditor.
  • Offline: Primary source. Rate display shows "Snapshot 14:30" timestamp.
  • AI: None.
  • Errors: Snapshot stale (> 24 h) -> blocking modal "Reconnect to refresh inventory".
  • Loading: Sub-200 ms.
  • A11y: Same as J-03; offline pill prominent.
  • RTL: Mirror.
  • Perf: <= 200 ms.
  • Telemetry: frontend.walkin.step_viewed { step: 1, mode: offline }.

4.3 WalkInBookingWizardStep2GuestInformation

  • Layout: Same fields as J-03 §4.3; transliteration AI uses edge ONNX (lower confidence).
  • Components: Form, PhoneInput, BidiText, AiTransliterationCard (edge mode).
  • Offline: Primary mode.
  • AI: Edge ONNX transliteration; provenance shows local=true; receptionist always confirms.
  • Errors: Validation per field; phone format coerced.
  • Loading: Sub-100 ms.
  • A11y: Field-by-field labels; transliteration suggestion announced.
  • RTL: Mirror.
  • Perf: Form responsive; transliteration <= 200 ms edge.
  • Telemetry: frontend.walkin.guest_info_completed.

4.4 WalkInBookingWizardStep3CashDeposit

  • Layout: Cash amount input, currency picker (tenant-supported only), denominations breakdown (helper for till-counting), receipt-print preview, "Take cash" CTA.
  • Components: MoneyInput, DenominationsBreakdown, ReceiptPreview, Button ("Take cash").
  • Offline: Primary mode; logged to local cash drawer.
  • AI: None.
  • Errors: Amount < required deposit -> warning; currency mismatch warning.
  • Loading: Sub-200 ms.
  • A11y: Field-by-field labels; denominations announced.
  • RTL: Mirror; numerals localised per tenant policy.
  • Perf: <= 200 ms; receipt print <= 5 s.
  • Telemetry: frontend.walkin.cash_taken { amount, currency }.

4.5 WalkInBookingWizardStep4CheckInAndKey

  • Layout: Optional ID capture (uses J-05 §4.2 but in offline-primary mode), key issuance via offline-cert, "Done" CTA.
  • Components: IdCameraCapture (edge OCR), LockEncoderPanel (offline-cert path).
  • Offline: Primary mode; offline-cert signs key payload.
  • AI: Edge OCR.
  • Errors: Encoder USB disconnect -> retry UX.
  • Loading: Encoder cycle <= 8 s.
  • A11y: Encoder progress announced; "Done" announces completion.
  • RTL: Mirror.
  • Perf: Wizard total <= 60 s p95 offline.
  • Telemetry: frontend.walkin.completed { mode: offline }.

4.6 SyncCenterScreen (post-reconnect)

  • Layout: List of pending events (reservation, folio open, deposit, key issued) with status: queued / synced / conflict; "Retry all" + per-item retry; conflict diff viewer.
  • Components: SyncCenterTable, ConflictDiffViewer, Button ("Retry all").
  • Offline: Lists local outbox.
  • AI: None on flush. P2 — conflict resolution suggestion.
  • Errors: Conflict UX described in §9.
  • Loading: Spinner during flush.
  • A11y: Each row is a tab stop with status announced; conflict diff is a structured view with <th> for fields.
  • RTL: Mirror.
  • Perf: Flush total <= 30 s p95 for typical walk-in (5-10 events).
  • Telemetry: frontend.sync.flush_started; frontend.sync.flush_completed { okCount, errorCount }; frontend.sync.conflict { entity, strategy }.

5. State Machine

6. Data Requirements

6.1 Local persistence (primary system of record offline)

  • SQLite tables: reservations, folios, folio_charges, payments_local, key_credentials_local, room_status_local, outbox, audit_local.
  • outbox rows have deterministic keys (<entity>:<localId>:<op>); flushed in causal order (reservation -> folio -> deposit -> key).

6.2 Server reconciliation

  • On reconnect, outbox flushes via BFF endpoints (same as J-03/J-05/J-06) with X-Idempotency-Key matching local IDs.
  • Server returns canonical IDs; local IDs map to canonical IDs in id_mapping.
  • Conflicts (e.g., room overbooked due to concurrent online booking) trigger conflict UX per §9.

6.3 Idempotency

  • Mandatory; without it, retries during flush would overbook or double-charge.

7. AI Behavior

  • Edge ONNX transliteration in Step 2 (low-confidence; receptionist always confirms).
  • Edge ONNX OCR in Step 4 (low-confidence; receptionist always confirms).
  • No cloud AI calls during this journey.

8. Offline Behavior

  • This is the primary mode of this journey.
  • All steps work offline.
  • Receipts printed locally.
  • Cash drawer logged locally; reconciled to EOD report (J-12).

9. Error States

ErrorTriggerUX shownRecoveryTelemetry
OFFLINE_PRIMER_STALESnapshot > 24 h oldBlocking modal: "Reconnect to refresh inventory"Reconnect requiredfrontend.walkin.primer_stale
OFFLINE_CERT_EXPIREDDay-cert expiredBlocking modal: "Cannot issue keys offline - reconnect"Reconnect to refresh certfrontend.walkin.cert_expired
LOCK_ENCODER_USB_DISCONNECTEDUSB unplugModal: "Reconnect encoder and retry"Replug; auto-retryfrontend.walkin.encoder_disconnected
RESERVATION_CONFLICT_ON_FLUSHConcurrent online booking took the roomConflict UX in Sync Center: "Room was booked online while you were offline. Pick alternative"Receptionist selects alt; confirms with guestfrontend.sync.conflict { entity: reservation }
FOLIO_CHARGE_DUPLICATE_ON_FLUSHDuplicate detected via idempotencySilent dedupen/afrontend.sync.dedupe { entity: folio_charge }
OUTBOX_FLUSH_PARTIALSome events failSync Center shows errorsManual retry per itemfrontend.sync.partial_failure

10. E2E Test Gates

  • Composite gate G-DESK-3: walk-in flow offline (full wizard) -> reconnect -> outbox flush success.
  • Conflict variant: room booked online during outage; conflict UX exercised.
  • Outbox flush ordering verified; audit log entries correct.

11. Performance Requirements

MetricTarget
Wizard total (offline)<= 60 s p95
Edge OCR<= 1 s p95
Edge transliteration<= 200 ms
Encoder cycle<= 8 s p95
Receipt print<= 5 s
Outbox flush (typical 5-10 events)<= 30 s p95

12. Accessibility Requirements

  • All keyboard-completable.
  • Offline pill announced; Sync Center reachable via shortcut and tab.
  • Encoder + camera live regions announce status.
  • Conflict diff viewer is structured for screen readers.

13. Telemetry

Frontend events

  • frontend.walkin.step_viewed { step, mode: offline }
  • frontend.walkin.guest_info_completed
  • frontend.walkin.cash_taken { amount, currency }
  • frontend.walkin.completed { mode: offline }
  • frontend.sync.flush_started / flush_completed { okCount, errorCount }
  • frontend.sync.conflict { entity, strategy }

Domain events emitted (after reconnect, in order)

  • melmastoon.booking.created.v1 (with offline-origin marker)
  • melmastoon.folio.opened.v1
  • melmastoon.payments.cash.received.v1
  • melmastoon.lock_and_key.credential.issued.v1 (with mode=offline_cert)
  • melmastoon.audit.recorded.v1 (per step)

14. Success Criteria

  • Walk-in flow completes <= 60 s p95 fully offline.
  • Receipt printed locally; cash drawer logged locally.
  • Lock-key issuance succeeds via offline-cert; key works on the door.
  • Outbox flushes cleanly on reconnect; conflicts surface with explicit UX (no silent overbooking).
  • Audit log entries match local timeline once flushed.
  • EOD cash drawer (J-12) reconciles correctly without manual intervention.

References