backend phase 11

This commit is contained in:
hamid
2026-07-09 02:13:30 +03:30
parent 23605591eb
commit 465f75c29e
78 changed files with 9555 additions and 27 deletions
@@ -25,4 +25,18 @@
## (d) Supporting database entities
**`cancellation_policies`**, `bookings` (policy snapshot, `dispute_window_ends_at`), `refunds` (admin-only, `ticket_id`, fee-leg decomposition, `refund_channel`), `tickets`, `nurse_clawbacks` (post-payout case), `ledger_entries`.
## (e) As built (backend-phase-11)
Decisions fixed while building the refund/clawback/invoice engine (config-driven where possible):
- **Refund channel canonical code:** the out-of-band bank refund is stored and served as **`manual`** (the wire
code), not `manual_bank` — they are the same channel. Full set: `psp_card` | `bnpl_revert` | `manual`.
- **Ticket link is config-gated until b15.** `refunds.ticket_id` is a nullable column with **no FK yet**
(`tickets` arrives in b15). "A refund must link a ticket" is enforced by the `refund_ticket_required` config
flag, **default `false`** so admin refunds are testable today; b15 wires the FK and flips it on.
- **BNPL refund ETA** is `now + config(bnpl_refund_eta_business_days, default 10)` business days (Fridays skipped),
surfaced as `expected_customer_refund_eta`; the refund sits in `processing` until reconciled. Card refunds are
immediate (`succeeded`, no ETA). Card and BNPL post the **same** reversal ledger legs.
- **Pre-payout vs post-payout fork** is decided by whether the nurse was already paid — derived from the booking's
`dispute_window_ends_at` close until b13 ships `nurse_payouts` (a `refund_assume_nurse_paid` override exists).
Clawback **recovery/netting is b13**; b11 only opens the `pending` receivable + supports admin write-off.
> **Related:** Data model — [Payments Ledger & Refunds](../data-model/06-payments-ledger-and-refunds.md).