Files
baya-monorepo/mvp/blocker-phases/13-booking-lifecycle.md
T
2026-08-02 20:37:14 +03:30

2.8 KiB

Phase 13 — Booking lifecycle

Blocker: blockers.md § "Booking lifecycle." Depends on: 13a's edge case needs a product decision (see below); 13b should use whatever timezone approach you land on in 04-payment-timezone.md.


13a. Stuck partial-missed bookings

The domain's own comment (BookingStatus.cs:19) states Completed means "every session is completed/cancelled/missed" — implying a mixed completed+missed booking should reach Completed. The only place that actually checks this is CheckOutVisitCommand.Handler.cs:64-70 (allSettled check, runs after a real check-out). The no-show sweep (DetectNoShowSessionsCommand.Handler.cs:25-76, run by NoShowSweepJob) marks individual sessions Missed but never re-checks allSettled afterward — so a booking with one completed session and the rest auto-missed later gets permanently stuck at InProgress, and PayoutRepository's eligibility query only considers Status == Completed, so the nurse's completed-session payout never becomes eligible. An admin can manually rescue this specific case (TransitionBookingStatusCommand.Handler.cs:43-55 allows InProgress → Completed), but nothing does it automatically.

Fix: extract the allSettled check from CheckOutVisitCommand.Handler.cs:64-70 into a shared helper, call it from DetectNoShowSessionsCommand.Handler.cs after marking sessions Missed, per affected booking in that sweep batch.

Flag, don't guess: what should happen to a booking where zero sessions were ever completed (all missed straight from Confirmed)? BookingTransitions.cs has no Confirmed → Completed edge today, and Cancel is explicitly refused as a substitute (TransitionBookingStatusCommand.Handler.cs:28-29). Nothing in mvp//archive/product/ answers this — it needs a product decision (does it still reach Completed with a zero payout, or some other terminal state?) before writing the edge-case code.

13b. "Today's visits" is unfiltered by default

ListSessionsForNurseQuery documents itself as "today's visits by default," but BookingRepository.cs:185-192 only applies the date filter when date is explicitly passed — both real client call sites (nurse/visits/page.tsx:26, NurseDashboardScreen.tsx:85) omit it, so the entire history returns. The mock already implements the intended default correctly (mockApi.ts:438: date ?? isoDate(0)).

Fix: default request.Date to "today" via IDateTimeProvider inside the handler/repository when null, mirroring the mock.

Flag: "today" needs a timezone decision (Iran local date vs. UTC day boundary) — there's no Asia/Tehran-aware date logic anywhere in the codebase yet (same class of gap as 04-payment-timezone.md). Resolve consistently with that fix, not ad hoc here.