/clean-ack — cleaner state machine
/clean-ack?b={bookingId} is the cleaner-facing landing page. It
renders one of 6 states based on the booking’s cleanings row, and
its POST handlers transition between states.
The 6 states
Forward-progress state machine — picks the furthest state reached:
- Completed —
complete_atset → confirmation page - Ack’d —
ack_atset, nocomplete_at→ “Mark Complete” prompt - Time-commit —
time_commit_sent_atset, noack_at→ time picker (same-day) OR simple confirm (gap-day) - T-2 reconfirm —
t2_reminder_sent_atset, not2_reminder_ack_at→ reconfirm button - In queue —
heads_up_ack_atset → “you’re on the schedule” view - Confirm assignment — default → “Yes I’m on it” button
POST actions
| Action | Sets column | Precondition (guarded with 409 on violation) |
|---|---|---|
confirm-heads-up | heads_up_ack_at | heads_up_sent_at IS NOT NULL AND heads_up_ack_at IS NULL |
confirm-t2 | t2_reminder_ack_at | t2_reminder_sent_at IS NOT NULL AND t2_reminder_ack_at IS NULL |
ack | ack_at + eta_at | time_commit_sent_at IS NOT NULL AND ack_at IS NULL (requires eta_at) |
commit-flexible | ack_at (no eta) | same as ack |
complete | complete_at | ack_at IS NOT NULL AND complete_at IS NULL |
issue | (escape hatch) | always allowed → redirect to /forms/clean |
The state-machine guards (P5.M85) are critical — they prevent test seeds or out-of-order POSTs from corrupting state.
Side effects on transitions
ack/commit-flexible→ emails Bill with cleaner’s commitment (subject includes the committed time for same-day)complete→ emails Bill confirming the unit is ready (with committed-vs-actual comparison)
Issue path
The “Report a problem” button (rendered on every pre-complete state)
redirects to /forms/clean?bookingID={id} where the cleaner can
describe an issue + attach photos. Submitting that form:
- Inserts a
form_submissionsrow - Emails Bill with the full issue description + guest contact info
- Sets
cleanings.issue_summary
URL anatomy
https://stayonthesnow-pms.minnetonka.workers.dev/clean-ack?b={bookingId}
Unauthenticated — booking ID is the secret. URL is shared only via direct cleaner email/SMS for that booking.
Source
src/routes/clean-ack.ts— GET render + POST handlers + state machinesrc/lib/cleanings.ts—getCleaning,updateCleaningsrc/routes/forms-clean.ts— issue-report path- Tests:
test/routes/clean-ack.test.ts(39 cases, including state-guard tests)