# Handoff — after backend phase 9 (Bookings, sessions, care instructions & EVV) **The booking engine is live.** A paid request now becomes a real engagement: `bookings` + N `booking_sessions`, encrypted `booking_care_instructions`, per-session `visit_verifications` (EVV), and the dispute-window gate. Capture is **mocked** behind `IPaymentCaptureSimulator`; the real conversion trigger arrives with **b10 payments**. ## What f8-b9 can now build - **Booking detail & "My bookings"** — `GET bookings/get/{id}`, `GET bookings/list?role=customer|nurse|all&status=`. Header + money summary (three amounts as **digit-strings**, `platformFeeRate`, `pspFeeAmount`) + sessions + status timeline. The **nurse view omits `addressSnapshotJson`**. - **Nurse EVV** — `GET booking_sessions/today?date=` (today's visits + CTA state), `POST booking_sessions/check_in/{id}` and `POST booking_sessions/check_out/{id}` (send `{latitude, longitude}`; both nullable if GPS denied), `GET booking_sessions/evv/{id}` (raw GPS, owning nurse + admin only). - **Care instructions** — `POST bookings/submit_care_instructions/{id}` (customer/admin, booking must be confirmed+), `GET bookings/care_instructions/{id}` (**assigned nurse + admin only, post-confirmation** — the two-stage disclosure boundary; everyone else gets 404). - **Status timeline & cancel** — `POST bookings/cancel/{id}` (customer/nurse/admin; returns the policy snapshot + refundable amount), `POST booking_sessions/cancel/{id}` (single un-started session). - **Admin** — `GET admin_evv/list?type=mismatch|no_show`, `POST admin_evv/detect_no_shows`, `POST admin_cancellation_policies/upsert` + `GET admin_cancellation_policies/list`, `POST bookings/transition/{id}`. ## Live endpoints / contracts - Contract: [`dev/contracts/domains/bookings-evv.md`](../../contracts/domains/bookings-evv.md); machine schema in the refreshed [`swagger.v1.json`](../../contracts/openapi/swagger.v1.json). - Enums: `BookingStatus`, `BookingSessionStatus`, `VisitVerificationStatus`, `CancellationActor`. ## Load-bearing rules the client must honour - **Money is IRR integer, on the wire as a digit-string.** `grossPriceIrr = balinyaarCommissionIrr + nursePayoutAmount`. Never coerce to a JS number for math. - **Payout eligibility is derived from `disputeWindowEndsAt` / per-session `payoutEligibleAt`, not from `completed`.** - **EVV address mismatch is advisory** — a flagged check-in still succeeds; surface it, don't block. - **Care-instruction clinical fields never appear in a list or the booking detail** — only via the gated read. ## Mocked here → make real later - **`IPaymentCaptureSimulator`** (🟡) — the temporary conversion trigger. In **b10**, the real card capture calls `ConvertRequestToBooking` directly on a `payment_transactions.succeeded`; this seam is then removed. A config switch (`Seams:PaymentCapture:ForceFailure`) exercises the "capture failed → no booking" path today. - The **no-show cron** is DEFERRED — `POST admin_evv/detect_no_shows` runs the same idempotent command a scheduler will later call (config `no_show_scan_cadence_hours`). ## Consumed by later backend phases - **b10** — real capture posts the ledger and calls the conversion; sets the real `psp_fee_amount`. - **b11** — refund execution consumes the frozen `cancellationPolicyCode` + `refundableAmountIrr` (no ledger posted here). - **b13** — payout batching consumes `disputeWindowEndsAt` / `payoutEligibleAt`. - **b14** — reviews on a completed booking. - **b15** — `partner_centers` wires the nullable `partner_center_id`.