frontend phase 10

This commit is contained in:
hamid
2026-07-10 12:51:53 +03:30
parent 40cc1d163b
commit ccfa27aff6
32 changed files with 2151 additions and 3 deletions
@@ -263,3 +263,63 @@ delivers fixes in its own change. **Frontend never edits backend code to "fix" a
capture to demo the full flow), but on the real rails every fresh payment would land on that empty
state.
- **Status:** open
## REQ-019 — Customer-initiated booking cancellation command — filed by frontend-phase-10-b11 — 2026-07-10
- **Need:** A **customer-facing** command to cancel a booking (post-payment) and open its refund, e.g.
`POST api/v1/bookings/{bookingId}/cancel` (owner-scoped) with body
`{ sessionIds?: long[], reasonCategory: string, reasonNotes?: string }`
the created refund summary (`{ id, bookingId, status, refundChannel, amount, expectedCustomerRefundEta,
reference }`, i.e. the `refunds/{id}/status` shape). `sessionIds` omitted = cancel all un-started
(remaining) sessions; completed-and-verified sessions stay payout-eligible.
- **Why:** b11 shipped refunds **admin-only** (`POST admin_refunds`) — there is **no** customer path to
request a cancellation, but f10's whole cancel flow is customer-initiated (the customer *requests*; an
admin still *approves/processes* the money). The client mocks this behind the `services/refunds` seam:
the mock flips the booking to `cancelled` (stamping the b9 cancellation snapshot), decomposes the refund
across the two fee legs, and returns a card-immediate (`succeeded`) or BNPL-`processing` refund. The real
`refundsClientApi.cancelBooking` already targets this slug.
- **Proposed shape:** `POST api/v1/bookings/{bookingId}/cancel` body as above → `RefundStatusDto`. The
server resolves the snapshotted policy, enforces the outside-policy/state rules (`409`), posts the
balanced reversal, and (per the admin-only rule) may route the refund through an admin/ticket step — the
customer surface just needs to *create* the cancellation request and read the resulting refund.
- **Status:** open
## REQ-020 — Cancellation-policy preview (pre-cancel, per-session) — filed by frontend-phase-10-b11 — 2026-07-10
- **Need:** A read that **resolves the applicable cancellation policy by current lead time** *before* the
customer confirms, incl. the per-session refundability breakdown. Proposed
`GET api/v1/bookings/{bookingId}/cancellation_policy` (owner-scoped) →
`{ bookingId, cancellable, cancellationPolicyCode, refundPercentageApplied, feePercentage,
refundAmountIrr, feeAmountIrr, refundableAmountIrr, platformFeeRefundedIrr, nursePayoutRefundedIrr,
appliesTo, leadTimeLabel, refundChannel, expectedCustomerRefundEta,
sessions: [{ bookingSessionId, sessionIndex, scheduledDate, refundable, reasonCode }] }` (IRR fields are
digit-strings; `refundAmountIrr + feeAmountIrr = refundableAmountIrr`; the fee-leg split is served,
never client-derived).
- **Why:** The phase's load-bearing rule is **disclose the fee/refund % before confirm** — an
outside-policy fee is never a surprise. b9 snapshots `cancellationPolicyCode`/`cancellationRefundPercentage`/
`refundableAmountIrr` on the booking only *after* a cancel; there is no pre-cancel preview that resolves
the tier by current lead time and enumerates which sessions are refundable (un-started) vs locked
(completed-and-verified). The client mocks the whole preview behind the `services/refunds` seam; the tier
**codes** (`free_24h` / `partial_under_24h` / `customer_no_show`) are client-invented placeholders (the
product doc pins no wire codes) mapped to i18n keys — please define the canonical `cancellation_policy_code`
set so the client maps the real codes.
- **Proposed shape:** as above. The `cancellationPolicyCode` set + the per-session `reasonCode` set
(`un_started` / the blocking session status) should be documented as stable enum codes → i18n keys.
- **Status:** open
## REQ-021 — Customer refund lookup-by-booking + fee-leg decomposition on the customer status — filed by frontend-phase-10-b11 — 2026-07-10
- **Need:** Two additions to the customer refund surface:
1. **Reach a refund from its booking.** `GET api/v1/refunds/by_booking/{bookingId}` (owner-scoped) →
the `refunds/{id}/status` shape, or `404` when the booking has no refund. Today the only customer read
is `GET refunds/{id}/status` keyed by a **refund id** the customer can't obtain (the refund id lives on
the admin-only `GET admin_refunds` worklist).
2. **Expose the decomposition to the customer.** Add `platformFeeRefundedIrr`, `nursePayoutRefundedIrr`,
`refundPercentageApplied`, `cancellationPolicyCode`, `createdAt`, `completedAt` to the customer
`refunds/{id}/status` payload (they exist on the admin-only `RefundListItem`).
- **Why:** f10's refund-status screen deep-links from a booking and renders (where the design calls for it)
a **fee-leg transparency split** (Balinyaar-fee-refunded vs service-cost-refunded). Without (1) the
customer can't find their refund; without (2) the split can't render on the real path (the client mock
fills all six fields; the real `refundsClientApi` leaves them `null` and the split is hidden).
- **Also (minor):** please confirm `provider_commission_reversed_amount` (the BNPL provider's own
commission on a revert) is **nullable** on the refund shape and reconciled from the provider response —
the b12 `IBnplProvider` mock echoes it as nullable and the client treats any provider-commission figure
as opaque/never customer-facing.
- **Status:** open