Files
baya-monorepo/archive/build-chain/working-context/backend/handoff/after-backend-phase-11.md
T
2026-08-02 18:48:32 +03:30

3.5 KiB
Raw Blame History

Handoff — after backend-phase-11 (Refunds, clawbacks & invoices)

The reversal leg of the payments arc is live. Money can now flow backwards: an admin reverses a captured booking payment across both fee legs, the balanced reversal posts to the append-only ledger, and the flow forks on whether the nurse was already paid (clean nurse_payable reversal vs a first-class nurse_clawbacks receivable). The minimal commission invoice (VAT on the commission line, sequential number, mocked مودیان) ships too.

What the frontend (f10-b11) can now build

  • Admin refund console — create a refund (POST admin_refunds: full/partial by percentage or explicit legs), the refund worklist (GET admin_refunds — channel, decomposed legs, status, ETA, policy snapshot), and the clawback write-off (POST admin_clawbacks/{id}/write_off).
  • Admin invoice issuancePOST admin_invoices (sequential number, VAT on commission, مودیان pending).
  • Customer cancellation/refund-status viewGET refunds/{id}/status (tenancy-scoped; status, channel, amount, expected_customer_refund_eta for the BNPL 710-business-day window, masked reference). This is the only customer-visible refund surface — refunds are admin-initiated, there is no self-service initiation.
  • Customer/admin invoice viewGET invoices/{booking_id} (number, gross, commission, VAT, مودیان status, PDF URL when present).

Live endpoints / contract

  • Contract: dev/contracts/domains/refunds-invoices.md (enums, DTO shapes, IRR digit-strings, masked references, failure codes, side-effects). Machine schema: dev/contracts/openapi/swagger.v1.json refreshed.
  • All money is IRR integer, on the wire as a digit-string. expected_customer_refund_eta is a date.
  • Admin endpoints are behind the admin policy and rate-limited (sensitive). Refunds are never customer self-service.

What is mocked / waiting

  • سامانه مودیان is mocked behind IMoadianClient (pending/no-ref by default; a config switch forces a registered 22-digit ref). See reports/mocks-registry.md.
  • BNPL revert runs against IBnplProvider — a thin local stub now; b12 owns the real seam and its adapter. The bnpl_revert ledger legs are already identical to the card path.
  • "Was the nurse paid?" is derived from the booking's dispute-window close (INursePayoutStatus) until b13 ships nurse_payouts; clawback recovery/netting is b13 (this phase only opens the pending receivable + supports write-off).
  • tickets arrives in b15: refunds.ticket_id is a nullable column (no FK yet); the "ticket required" rule is config-gated off (refund_ticket_required = false).
  • Deferred crons (thin/manual today): the مودیان reconciliation job (pending → registered) and the BNPL-revert reconciliation job that clears refund_payable ↔ escrow_held for a processing refund.

Notes for the next backend phases

  • b12 (BNPL): owns the real IBnplProvider; the refund bnpl_revert path already calls it through the seam.
  • b13 (payouts): implement the real INursePayoutStatus (nurse_payout_booking_links) and net pending nurse_clawbacks out of a payout batch (set recovered_in_payout_id / original_payout_id, post DEBIT nurse_payable / CREDIT nurse_clawback_receivable).
  • b15 (tickets/partner centers): wire the real refunds.ticket_id FK + flip refund_ticket_required on; wire invoices.partner_center_id + nurse_clawbacks payout FKs.