J-21 — Mid-Stay Cleaning Request
One-liner: Guest requests mid-stay cleaning from the mobile app; housekeeping picks it up and notifies the guest when done.
1. Purpose
In-house guest requests a mid-stay cleaning (towels, full clean, do-not-disturb override) from the tenant mobile app; housekeeping receives it as a task; on completion, the guest is notified. Outcome: light-touch service request loop with minimal staff overhead.
2. Persona Context
- Personas: Guest (initiator); Housekeeping (executor).
- Surfaces: Tenant Booking Mobile (guest); Electron Desktop (housekeeping).
- Primary BFFs:
bff-tenant-booking-service(guest);bff-backoffice-service(HK). - Backing services:
housekeeping-service,notification-service,audit-service. - Preconditions: Guest is in-house; tenant has the feature enabled.
- Trigger: Guest taps "Request cleaning" in My Stay.
3. Entry Points
| # | Entry | Notes |
|---|---|---|
| 1 | "Request service" in My Stay | Default |
| 2 | "Do not disturb" toggle | Special case |
4. Screen-by-Screen Flow
4.1 (Guest) RequestCleaningSheet
- Layout: Service type (towels / full clean / DND override), preferred time window, notes, "Request" CTA.
- Components:
Form,ServiceTypeSelect,TimeWindowPicker. - Offline: Editable; submit deferred until online.
- AI: None.
- Errors: Validation per field.
- Loading: Submit <= 1 s.
- A11y: Field labels.
- RTL: Mirror.
- Perf: <= 1 s.
- Telemetry:
frontend.guest.cleaning_requested { type }.
4.2 (Housekeeping) IncomingTaskNotification
- Layout: Toast on Kanban: "New mid-stay request - Room
"; tile appears in Vacant Dirty / Special column. - Components:
Toast,RoomTaskTile. - Offline: Receives via SSE when online; local-state if same Electron instance.
- AI: None.
- Errors: Same as J-19.
- Loading: Sub-second.
- A11y: Toast announced via
aria-live; tile tab-stop. - RTL: Mirror.
- Perf: SSE delivery <= 1 s.
- Telemetry:
frontend.housekeeping.midstay_received { roomId }.
4.3 (Guest) ServiceCompleteNotification
- Layout: Push notification + in-app banner: "Cleaning complete - Room
". - Components:
PushNotificationHandler,InAppBanner. - Offline: Push delivered when device online.
- AI: None.
- Errors: Push delivery failure -> in-app banner on next open.
- Loading: n/a.
- A11y: Banner announced.
- RTL: Mirror.
- Perf: Push <= 30 s after completion.
- Telemetry:
frontend.guest.service_complete_notified.
5. State Machine
6. Data Requirements
6.1 Server state
POST /api/v1/guest/service-requests(idempotent)GET /api/v1/housekeeping/tasks(already in J-19)- Push notification via
notification-service
6.2 Local persistence
- Request cached in mobile app for status checks.
6.3 Idempotency
- All mutations carry
X-Idempotency-Key.
7. AI Behavior
n/a; P2 — auto-route based on housekeeper proximity.
8. Offline Behavior
- Guest side: request queued; submit on reconnect.
- HK side: same as J-19.
9. Error States
| Error | Trigger | UX shown | Recovery | Telemetry |
|---|---|---|---|---|
REQUEST_QUEUE_FAILED | Mobile submit failure | Banner with retry | Retry | frontend.guest.request_failed |
PUSH_DELIVERY_FAILED | Push undelivered | In-app banner on next open | n/a | frontend.guest.push_failed |
DND_OVERRIDE_DENIED | Policy rejects DND override | Inline error | n/a | frontend.guest.dnd_denied |
10. E2E Test Gates
- Composite gate
G-HK-3: guest request -> HK receives -> completes -> guest notified.
11. Performance Requirements
| Metric | Target |
|---|---|
| Guest submit | <= 1 s p95 |
| HK SSE delivery | <= 1 s |
| Push to guest | <= 30 s after completion |
12. Accessibility Requirements
- Toasts and banners announced.
- All keyboard-completable.
13. Telemetry
Frontend events
frontend.guest.cleaning_requested { type }frontend.housekeeping.midstay_received { roomId }frontend.guest.service_complete_notified
Domain events emitted
melmastoon.guest.service_request.created.v1melmastoon.housekeeping.task.created.v1melmastoon.notifications.push.delivered.v1melmastoon.audit.recorded.v1
14. Success Criteria
- Loop completes <= 30 min wall-clock typical.
- Guest receives reliable status updates.
- Audit log records the request lifecycle.