37 lines
2.8 KiB
Markdown
37 lines
2.8 KiB
Markdown
# Domain 8 — BNPL / Installments
|
|
|
|
[← Database Model](index.md)
|
|
|
|
**Related:** business requirements — [Installments / BNPL](../business/09-installments-bnpl.md). Settlement and reversal detail are explained in depth in the payments docs — [BNPL landscape](../payments/bnpl-landscape.md) and [Cancellation & payout](../payments/cancellation-and-payout.md).
|
|
|
|
**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.
|