← Payments overview

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

See also the BNPL data model (../data-model/08-bnpl.md) and the business view (../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:

AmountMeaningDrives
gross_price_irrWhat the customer is charged (booking price)The invoice; the inbound escrow_held debit
balinyaar_commission_irrBalinyaar's own cut (was platform_fee_amount)platform_revenue; the nurse payout
bnpl_commission_irrThe BNPL provider's merchant discountbnpl_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.

↑ Back to top