Skip to main content

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

TransitionUI controlSuccess redirectError pathVisible in list
PENDING → CONFIRMEDMISSING — no "Confirm" button anywhere on detail or listn/an/ayes (chip)
CONFIRMED → CHECKED_INyes (/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 onlyyes
CHECKED_IN → CHECKED_OUTyes (/front-desk/check-out/[id], line 236)yes (router.push('/front-desk') at 247)toast onlyyes
CONFIRMED/PENDING → CANCELLEDyes (list dropdown line 294 + tape-chart ConfirmCancelDialog)only invalidates queries; user stays on listtoastyes
CHECKED_IN → CANCELLEDDISABLED in list (line 273); no explicit "void check-in" pathn/an/ayes
any → NO_SHOWMISSING — no manual mark-no-show button. Backend sets via night-audit cron onlyn/an/ayes (chip)
CART_HOLD → CONFIRMED/CANCELLEDMISSING — no UI surface; this is booking-engine internal but tape-chart shows themn/an/apartially
CHECKED_OUT → reopen / undoMISSING — no undo-checkout flow (intentional?)n/an/ayes

Findings (Reservation)​

  1. CRITICAL — checkin success leaves stale guard (issue #1 confirmed). …/front-desk/check-in/[id]/keynova.tsx:933 jumps to step "complete" but guard at 1026-1033 blocks any subsequent render of the page when status is no longer CONFIRMED. Fix: after toast.success, router.replace('/front-desk/folio/' + id).
  2. CRITICAL — no "Mark No-Show" UI. Add a "Mark no-show" action in the /reservations/[id] overflow menu (gated to status === CONFIRMED && arrivalDate <= today).
  3. HIGH — no "Confirm" button for PENDING reservations.
  4. HIGH — cancel flow doesn't redirect or refetch detail.
  5. 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)​

  1. CRITICAL — folio status never rendered anywhere on /front-desk/folio/[id]. After Settle Folio succeeds, the Settle button stays clickable, all action buttons remain enabled, the "balance due" tile still says "OPEN". Fix: read folio.status; gate all mutation buttons behind folio.status === 'OPEN'; show a "SETTLED" badge.
  2. HIGH — Settle Folio doesn't redirect.
  3. MEDIUM — no Void Folio action.

Room lifecycle (RoomStatus + FrontOfficeStatus + HousekeepingStatus)​

Status enums (hmp-property-service/prisma/schema.prisma:277-297)

Findings (Room)​

  1. HIGH — front-end HousekeepingStatus enum drifted from backend. src/types/room.ts:33 defines OUT_OF_ORDER + OUT_OF_SERVICE in HousekeepingStatus enum, but backend Prisma HousekeepingStatus only has CLEAN/DIRTY/INSPECTED/PICKUP. Code path is dead.
  2. MEDIUM — no manual room-status set UI from housekeeping board.
  3. MEDIUM — FrontOfficeStatus (DUE_OUT) is never set or displayed.

POSOrder lifecycle​

Status enum: OPEN / BILLED / PAID / CANCELLED / VOID

Findings (POS)​

  1. HIGH — no Cancel Order action anywhere.
  2. MEDIUM — KOT generation has no visible state separator.
  3. 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)​

  1. LOW — no confirm dialog before CANCELLED transition.
  2. LOW — IN_PROGRESS → COMPLETED click has no post-completion redirect.

HousekeepingTask lifecycle​

Status enum: PENDING / IN_PROGRESS / COMPLETED / INSPECTED / CANCELLED

Findings (Housekeeping tasks)​

  1. MEDIUM — no Reassign Task action.
  2. 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)​

  1. HIGH — frontend status enum drift. Either expose canonical 5 or add explicit translation layer.
  2. MEDIUM — no redirect on COMPLETED state for ERASURE.
  3. LOW — no "Re-open from REJECTED".

Cross-cutting findings​

  1. CRITICAL — pattern: success → invalidateQueries but no router.push. Issue #1 root cause. Same anti-pattern in:
    • front-desk/check-in/[id]/keynova.tsx:908-934
    • front-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/useUpdateEventStatus hooks
  2. HIGH — guard pages with no recovery link.
  3. HIGH — no entity has a "transition history" tab.
  4. MEDIUM — every status enum has at least one inconsistency between backend Prisma, frontend src/types/, and DTO copies.
  5. MEDIUM — toast.success is the only feedback for most transitions.
  6. 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_TRANSITIONS table)
  • Worst-implemented: Folio — status field never displayed

Top 10 prioritized fixes​

  1. Check-in success → redirect (…/front-desk/check-in/[id]/keynova.tsx:933): closes issue #1.
  2. Folio page must read and gate on folio.status.
  3. Add "Mark No-Show" action in /reservations/[id] overflow menu.
  4. Add "Confirm" action for PENDING reservations.
  5. Add "Cancel Order" / "Void Order" action to POS.
  6. Adopt banquet's STATUS_TRANSITIONS declarative pattern for reservation, folio, POS order, HK task, DSAR.
  7. Reconcile DSAR status enum between backend (5 states) and frontend (4 states).
  8. Reconcile HousekeepingStatus enum in hmp-web-dashboard/src/types/room.ts:33.
  9. Add "Reassign" action to housekeeping tasks dropdown.
  10. Universal guard-page improvement: every "wrong status" guard must include a router.push CTA.