Audit C — State Machine Completeness Report
Generated: 2026-04-26 by automated audit. Part of Production Readiness Audit Plan.
Reservation lifecycle
Status enum: PENDING / CONFIRMED / CHECKED_IN / CHECKED_OUT / CANCELLED / NO_SHOW / CART_HOLD
Files: hmp-reservation-service/prisma/schema.prisma:120, hmp-web-dashboard/src/app/(dashboard)/reservations/[id]/keynova.tsx, …/front-desk/check-in/[id]/keynova.tsx, …/front-desk/check-out/[id]/keynova.tsx, …/components/modules/reservations/reservation-list.tsx
| Transition | UI control | Success redirect | Error path | Visible in list |
|---|---|---|---|---|
| PENDING → CONFIRMED | MISSING — no "Confirm" button anywhere on detail or list | n/a | n/a | yes (chip) |
| CONFIRMED → CHECKED_IN | yes (/front-desk/check-in/[id], line 906) | NO — setCurrentStep('complete') only; back/refresh re-hits guard at line 1026 "Only confirmed reservations…" (issue #1 confirmed) | toast extractApiError only | yes |
| CHECKED_IN → CHECKED_OUT | yes (/front-desk/check-out/[id], line 236) | yes (router.push('/front-desk') at 247) | toast only | yes |
| CONFIRMED/PENDING → CANCELLED | yes (list dropdown line 294 + tape-chart ConfirmCancelDialog) | only invalidates queries; user stays on list | toast | yes |
| CHECKED_IN → CANCELLED | DISABLED in list (line 273); no explicit "void check-in" path | n/a | n/a | yes |
| any → NO_SHOW | MISSING — no manual mark-no-show button. Backend sets via night-audit cron only | n/a | n/a | yes (chip) |
| CART_HOLD → CONFIRMED/CANCELLED | MISSING — no UI surface; this is booking-engine internal but tape-chart shows them | n/a | n/a | partially |
| CHECKED_OUT → reopen / undo | MISSING — no undo-checkout flow (intentional?) | n/a | n/a | yes |
Findings (Reservation)
- CRITICAL — checkin success leaves stale guard (issue #1 confirmed).
…/front-desk/check-in/[id]/keynova.tsx:933jumps to step "complete" but guard at1026-1033blocks any subsequent render of the page when status is no longer CONFIRMED. Fix: aftertoast.success,router.replace('/front-desk/folio/' + id). - CRITICAL — no "Mark No-Show" UI. Add a "Mark no-show" action in the
/reservations/[id]overflow menu (gated to status === CONFIRMED && arrivalDate <= today). - HIGH — no "Confirm" button for PENDING reservations.
- HIGH — cancel flow doesn't redirect or refetch detail.
- MEDIUM — late-cancel after CHECKED_IN disabled with no error message.
Folio lifecycle
Status enum: OPEN / SETTLED / TRANSFERRED / VOID
File: hmp-frontdesk-service/prisma/schema.prisma:62, hmp-web-dashboard/src/app/(dashboard)/front-desk/folio/[id]/page.tsx
Findings (Folio)
- CRITICAL — folio status never rendered anywhere on
/front-desk/folio/[id]. AfterSettle Foliosucceeds, the Settle button stays clickable, all action buttons remain enabled, the "balance due" tile still says "OPEN". Fix: readfolio.status; gate all mutation buttons behindfolio.status === 'OPEN'; show a "SETTLED" badge. - HIGH — Settle Folio doesn't redirect.
- MEDIUM — no Void Folio action.
Room lifecycle (RoomStatus + FrontOfficeStatus + HousekeepingStatus)
Status enums (hmp-property-service/prisma/schema.prisma:277-297)
Findings (Room)
- HIGH — front-end
HousekeepingStatusenum drifted from backend.src/types/room.ts:33defines OUT_OF_ORDER + OUT_OF_SERVICE inHousekeepingStatusenum, but backend PrismaHousekeepingStatusonly has CLEAN/DIRTY/INSPECTED/PICKUP. Code path is dead. - MEDIUM — no manual room-status set UI from housekeeping board.
- MEDIUM —
FrontOfficeStatus(DUE_OUT) is never set or displayed.
POSOrder lifecycle
Status enum: OPEN / BILLED / PAID / CANCELLED / VOID
Findings (POS)
- HIGH — no Cancel Order action anywhere.
- MEDIUM — KOT generation has no visible state separator.
- MEDIUM — Charge to Room dialog requires UUID paste (no autocomplete).
EventBooking (banquet) lifecycle — gold-standard pattern
Status enum: INQUIRY / QUOTATION_SENT / TENTATIVE / CONFIRMED / IN_PROGRESS / COMPLETED / CANCELLED
This is the gold-standard pattern other entities should follow (declarative STATUS_TRANSITIONS table at line 81-89 driving allowed buttons).
Findings (Banquet)
- LOW — no confirm dialog before CANCELLED transition.
- LOW — IN_PROGRESS → COMPLETED click has no post-completion redirect.
HousekeepingTask lifecycle
Status enum: PENDING / IN_PROGRESS / COMPLETED / INSPECTED / CANCELLED
Findings (Housekeeping tasks)
- MEDIUM — no Reassign Task action.
- LOW — Cancel does not prompt for reason.
DSAR (DsarRequest) lifecycle
Backend enum: RECEIVED / VERIFIED / IN_PROGRESS / COMPLETED / REJECTED Frontend enum: PENDING / IN_REVIEW / COMPLETED / REJECTED — 5 vs 4 mismatch
Findings (DSAR)
- HIGH — frontend status enum drift. Either expose canonical 5 or add explicit translation layer.
- MEDIUM — no redirect on COMPLETED state for ERASURE.
- LOW — no "Re-open from REJECTED".
Cross-cutting findings
- CRITICAL — pattern: success → invalidateQueries but no router.push. Issue #1 root cause. Same anti-pattern in:
front-desk/check-in/[id]/keynova.tsx:908-934front-desk/folio/[id]/page.tsx:365(settle folio)pos/orders/keynova.tsx:201(merge orders)crm/dsar/[id]/page.tsx:117(erase + complete)- All
useUpdateTaskStatus/useUpdateEventStatushooks
- HIGH — guard pages with no recovery link.
- HIGH — no entity has a "transition history" tab.
- MEDIUM — every status enum has at least one inconsistency between backend Prisma, frontend
src/types/, and DTO copies. - MEDIUM — toast.success is the only feedback for most transitions.
- LOW — confirm dialogs are inconsistent.
Summary stats
- Entities audited: 7
- Distinct status enums: 9
- Total transitions inventoried: ~55 expected
- ~13 missing UI controls
- ~9 missing post-success redirects
- ~7 missing error-recovery paths
- Best-implemented: EventBooking (declarative
STATUS_TRANSITIONStable) - Worst-implemented: Folio — status field never displayed
Top 10 prioritized fixes
- Check-in success → redirect (
…/front-desk/check-in/[id]/keynova.tsx:933): closes issue #1. - Folio page must read and gate on
folio.status. - Add "Mark No-Show" action in
/reservations/[id]overflow menu. - Add "Confirm" action for PENDING reservations.
- Add "Cancel Order" / "Void Order" action to POS.
- Adopt banquet's
STATUS_TRANSITIONSdeclarative pattern for reservation, folio, POS order, HK task, DSAR. - Reconcile DSAR status enum between backend (5 states) and frontend (4 states).
- Reconcile
HousekeepingStatusenum inhmp-web-dashboard/src/types/room.ts:33. - Add "Reassign" action to housekeeping tasks dropdown.
- Universal guard-page improvement: every "wrong status" guard must include a
router.pushCTA.