Domain 8 — BNPL / Installments
Related: business requirements — Installments / BNPL. Settlement and reversal detail are explained in depth in the payments docs — BNPL landscape and Cancellation & payout.
Resolved. Because verified research shows Iranian provider-financed BNPL settles the full amount to the merchant in one lump (provider owns the customer's installments and default risk), a BNPL order is — in our books — a card payment that lands net-of-fee. The original installment_plans + installment_entries subsystem (which tried to track the customer's repayment schedule and default) is deleted: it modeled a receivable Balinyaar never owns and a risk it never bears.
bnpl_transactions [MVP] — NEW (replaces installment_plans)
Role: One row per BNPL order, 1:1 with its payment_transaction — the single inbound settlement to reconcile, plus the revert path. Why one row, not a plan+entries tree: there is nothing to amortize on our side; we track the settlement, the provider's commission, and the reversal.
| Field | Type | Notes |
|---|---|---|
id | BIGINT PK | |
payment_transaction_id | BIGINT FK UNIQUE | 1:1 |
provider_code | NVARCHAR(50) | snapppay / digipay / tara / torobpay |
merchant_of_record | NVARCHAR(40) | Balinyaar entity or partner center |
external_payment_token | NVARCHAR(200) | For verify/settle/revert |
external_transaction_id | NVARCHAR(200) | |
eligibility_status | NVARCHAR(30) | |
order_amount_irr | BIGINT | Gross order |
settled_amount_irr | BIGINT | Net of provider commission actually received |
bnpl_commission_irr | BIGINT | Provider's merchant discount = platform expense (never the nurse's) |
currency | NVARCHAR(5) | IRR/TOMAN at boundary; convert in |
installment_count | TINYINT | Informational (default 4) — owned by the provider |
status | NVARCHAR(30) | State machine: eligible/token_issued/verified/settled/reverted/cancelled/failed |
settled_at | DATETIME2 NULL | Per-transaction — timing is contract-defined (daily/T+1-3/weekly), never assumed instant |
revert_transaction_id, reverted_amount_irr, reverted_at | … | Reversal path |
refund_channel | NVARCHAR(20) | |
callback_payload_json | NVARCHAR(MAX) | Raw verify/settle payload |
| timestamps | … |
Relations: 1:1 → payment_transactions. State-machine guard on status for idempotency.
bnpl_settlement_entries [DEFERRED]
Role/Why: Only needed if a future provider uses tranched settlement (pays the platform over time). No mainstream Iranian provider does today, so it's modeled-but-inactive; adding it later is a purely additive migration.
↑ Back to top