46 lines
2.8 KiB
Markdown
46 lines
2.8 KiB
Markdown
# 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](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](04-payment-timezone.md)). Resolve consistently with that fix, not ad hoc here.
|