Skip to content

/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:

  1. Completedcomplete_at set → confirmation page
  2. Ack’dack_at set, no complete_at → “Mark Complete” prompt
  3. Time-committime_commit_sent_at set, no ack_at → time picker (same-day) OR simple confirm (gap-day)
  4. T-2 reconfirmt2_reminder_sent_at set, no t2_reminder_ack_at → reconfirm button
  5. In queueheads_up_ack_at set → “you’re on the schedule” view
  6. Confirm assignment — default → “Yes I’m on it” button

POST actions

ActionSets columnPrecondition (guarded with 409 on violation)
confirm-heads-upheads_up_ack_atheads_up_sent_at IS NOT NULL AND heads_up_ack_at IS NULL
confirm-t2t2_reminder_ack_att2_reminder_sent_at IS NOT NULL AND t2_reminder_ack_at IS NULL
ackack_at + eta_attime_commit_sent_at IS NOT NULL AND ack_at IS NULL (requires eta_at)
commit-flexibleack_at (no eta)same as ack
completecomplete_atack_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_submissions row
  • 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 machine
  • src/lib/cleanings.tsgetCleaning, updateCleaning
  • src/routes/forms-clean.ts — issue-report path
  • Tests: test/routes/clean-ack.test.ts (39 cases, including state-guard tests)