[← Payments overview](index.md)

# BNPL Cancellation, Refund & Nurse Payout (Q1 & Q2)

See also the BNPL data model ([../data-model/08-bnpl.md](../data-model/08-bnpl.md)) and the business view ([../business/09-installments-bnpl.md](../business/09-installments-bnpl.md)).

## 6. Q1 — Cancellation / refund of a BNPL booking mid-plan

**Decisive rule: money ALWAYS flows `customer ↔ SnappPay ↔ Balinyaar`. Never refund the customer directly, and never route a nurse→customer refund.** Balinyaar initiates the reversal through SnappPay's API using the stored payment token/transaction id:

- **Full cancel/refund → `revert`** (full amount).
- **Partial / shortened-visit → `update`** (new amount must be strictly lower than the original settled amount) — or `cancel` per the provider's partial semantics.

SnappPay then, on its own ledger and asynchronously:
1. **cancels the customer's remaining UNPAID installments** and credits their equivalent back to the customer's **credit wallet** (reusable BNPL credit — not merely "wiped"),
2. **refunds any already-PAID installment** to the customer's **bank account in ~7–10 business days.**

The merchant's only role is to authorize/cancel; **SnappPay owns the unwind.** *(VERIFIED verbatim: "اقساط پرداخت‌نشده لغو و معادل آن به موجودی حساب اعتباری شما برگشت داده می‌شود"; "مبلغ قسط پرداخت‌شده به حساب بانکی شما برگشت داده خواهد شد (۷ تا ۱۰ روز کاری)".)*

### Balinyaar's internal bookkeeping

1. Record a **`refund` row** with `refund_channel = 'bnpl_revert'`, `external_revert_reference`, `expected_customer_refund_eta`, and a `refund_status` that stays `processing` until SnappPay confirms (a reconciliation job clears it). **Surface the asynchronous 7–10-day window in the UI and reconciliation** — never assume instant.
2. **Decompose the refund** across the two fee legs: `platform_fee_refunded_irr` and `nurse_payout_refunded_irr` (the booking gross = platform fee + nurse payout; the refund must say how much of each is reversed).
3. **Post balanced ledger entries** (§3.2c/d): debit the decomposed `platform_revenue` / `nurse_payable`, credit `refund_payable`; record the revert reference on the `bnpl_transactions` row (`reverted_amount_irr`, `reverted_at`, `refund_channel`).
4. **If the nurse has NOT been paid** (booking still inside the dispute window / not in a processed batch): reverse the `nurse_payable` accrual — clean, nothing leaves Balinyaar. *(This is the common case if you gate payout on the dispute window.)*
5. **If the nurse HAS been paid** (refund-after-payout): take the **clawback** path — a `nurse_clawbacks` row + a `nurse_clawback_receivable` ledger leg (§3.2d), recovered from the next payout batch or written off.

**Partial / shortened-visit** maps to the `update` endpoint with a reduced amount: record `refund_delta_irr`, reduce `settled_amount_irr` on the `bnpl_transactions` row, and apply the same fee-leg decomposition.

> **UNCERTAIN (confirm at contracting):** whether the provider returns *its* merchant commission on a full vs partial refund (full / pro-rata / not at all) is **undocumented** and directly affects platform P&L on cancellations. Model `provider_commission_reversed_amount` as nullable and reconcile from the provider's refund response — do not hardcode. Digipay's exact mid-installment proration mechanics are likewise undocumented and contract-dependent.

---

## 7. Q2 — Under BNPL, who pays the nurse, and when?

**Balinyaar pays the nurse, on Balinyaar's own normal weekly payout schedule, after EVV check-out and after the dispute window closes — exactly the same path as a card-funded booking.** SnappPay **never** pays the nurse and is indifferent to Balinyaar's internal split. The customer's BNPL repayment timeline is completely decoupled from the nurse payout cycle.

### The crucial accounting rule — the three-amount split

The nurse's payout is computed from the booking's **own price and Balinyaar's own commission**, **NOT** from the BNPL-net amount. SnappPay's commission is a **cost of accepting BNPL, borne by Balinyaar**, and must **never** be passed through to the nurse. Store three separate amounts so the two fee deductions are never conflated:

| Amount | Meaning | Drives |
|---|---|---|
| `gross_price_irr` | What the customer is charged (booking price) | The invoice; the inbound `escrow_held` debit |
| `balinyaar_commission_irr` | Balinyaar's own cut (was `platform_fee_amount`) | `platform_revenue`; **the nurse payout** |
| `bnpl_commission_irr` | The BNPL provider's merchant discount | `bnpl_fee_expense` (platform expense) — **never the nurse** |

```
nurse_payout_amount = gross_price_irr − balinyaar_commission_irr
```

**The nurse receives the identical amount whether the family paid by card or by SnappPay, and on the identical weekly timing** (batch, gated on `dispute_window_ends_at < now()`). The only difference a BNPL order makes to the books is the extra `bnpl_fee_expense` leg that reduces *Balinyaar's* margin — not the nurse's pay.

**Worked example** (illustrative; rates are config): gross `5,000,000` IRR, Balinyaar commission 15% = `750,000`, nurse payout = `4,250,000`. If paid via SnappPay at a 10% merchant commission, `bnpl_commission_irr = 500,000` is a Balinyaar expense; SnappPay settles `4,500,000` net to Balinyaar; the **nurse still receives `4,250,000`**, and Balinyaar's net margin is `750,000 − 500,000 = 250,000` (before PSP/VAT). The nurse payout is invariant to the payment method.

> **Timing guard (CONFIGURABLE):** because BNPL settlement can lag, optionally key weekly-payout eligibility off `bnpl_transactions.settled_at` (settlement actually received) in addition to EVV + dispute window, so the platform never advances a nurse before it holds the cash.
