Files
baya-monorepo/product/payments/escrow-ledger.html
T
2026-06-24 01:32:46 +03:30

70 lines
11 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Escrow as an Internal Ledger, Not Held Cash — Balinyaar docs</title>
<link rel="stylesheet" href="../assets/doc.css">
</head>
<body>
<div class="layout">
<aside class="sidebar">
<a class="brand" href="../index.html"><span class="dot"></span> Balinyaar docs</a>
<p class="tagline">Trust-first home-nursing marketplace · Iran</p>
<nav><div class="group"><div class="label">Start here</div><ul><li><a href="../index.html">Docs home</a></li><li><a href="../overview/platform-summary.html">Platform summary &amp; ground truths</a></li></ul></div><div class="group"><div class="label">Business requirements</div><ul><li><a href="../business/index.html">Overview &amp; MVP scope</a></li><li><a href="../business/01-actors-and-onboarding.html">1. Actors &amp; onboarding</a></li><li><a href="../business/02-nurse-verification.html">2. Nurse verification</a></li><li><a href="../business/03-service-catalog-and-pricing.html">3. Service catalog &amp; pricing</a></li><li><a href="../business/04-search-and-matching.html">4. Search &amp; matching</a></li><li><a href="../business/05-booking-and-scheduling.html">5. Booking &amp; scheduling</a></li><li><a href="../business/06-evv-and-service-delivery.html">6. EVV / service delivery</a></li><li><a href="../business/07-cancellation-and-refunds.html">7. Cancellation &amp; refunds</a></li><li><a href="../business/08-payments-and-escrow.html">8. Payments &amp; escrow</a></li><li><a href="../business/09-installments-bnpl.html">9. Installments / BNPL</a></li><li><a href="../business/10-payouts.html">10. Payouts to nurses</a></li><li><a href="../business/11-reviews-trust-and-safety.html">11. Reviews, trust &amp; safety</a></li><li><a href="../business/12-messaging-and-emergencies.html">12. Messaging &amp; emergencies</a></li><li><a href="../business/13-tax-invoicing-and-legal.html">13. Tax, invoicing &amp; legal</a></li><li><a href="../business/14-notifications-and-admin.html">14. Notifications &amp; admin</a></li></ul></div><div class="group"><div class="label">Database model</div><ul><li><a href="../data-model/index.html">Overview &amp; decisions</a></li><li><a href="../data-model/diagrams.html">Diagrams</a></li><li><a href="../data-model/01-identity-and-access.html">1. Identity &amp; access</a></li><li><a href="../data-model/02-geography.html">2. Geography</a></li><li><a href="../data-model/03-services-and-pricing.html">3. Services &amp; pricing</a></li><li><a href="../data-model/04-verification-and-credentials.html">4. Verification &amp; credentials</a></li><li><a href="../data-model/05-booking-and-scheduling.html">5. Booking &amp; scheduling</a></li><li><a href="../data-model/06-payments-ledger-and-refunds.html">6. Payments, ledger &amp; refunds</a></li><li><a href="../data-model/07-payouts.html">7. Payouts</a></li><li><a href="../data-model/08-bnpl.html">8. BNPL / installments</a></li><li><a href="../data-model/09-messaging.html">9. Messaging</a></li><li><a href="../data-model/10-reviews-and-records.html">10. Reviews &amp; records</a></li><li><a href="../data-model/11-notifications.html">11. Notifications</a></li><li><a href="../data-model/12-audit-config-and-reference.html">12. Audit, config &amp; reference</a></li><li><a href="../data-model/13-partner-centers-and-future.html">13. Partner centers &amp; future</a></li></ul></div><div class="group"><div class="label">Payments deep-dive</div><ul><li><a href="index.html">Overview &amp; exec summary</a></li><li><a href="iranian-payment-reality.html">Iranian payment reality</a></li><li><a class="active" href="escrow-ledger.html">Escrow as a ledger</a></li><li><a href="bnpl-landscape.html">BNPL landscape &amp; finding</a></li><li><a href="cancellation-and-payout.html">Cancellation &amp; nurse payout</a></li><li><a href="integration-notes.html">Integration &amp; schema touchpoints</a></li><li><a href="sources.html">Recommendations &amp; sources</a></li></ul></div><div class="group"><div class="label">Research &amp; strategy</div><ul><li><a href="../research/index.html">Overview &amp; exec summary</a></li><li><a href="../research/market-and-competitors.html">Market &amp; competitors</a></li><li><a href="../research/problems-and-risks.html">Problems &amp; risks</a></li><li><a href="../research/verification.html">Verification (research)</a></li><li><a href="../research/legal-landscape.html">Legal landscape</a></li><li><a href="../research/go-to-market.html">Go-to-market &amp; sources</a></li></ul></div><div class="group"><div class="label">Notes &amp; more</div><ul><li><a href="../notes/open-questions.html">Open questions</a></li><li><a href="../notes/future-ideas.html">Future ideas</a></li><li><a href="../wireframes/index.html">Wireframes</a></li><li><a href="../fa/index.html">Farsi documents</a></li></ul></div></nav>
</aside>
<main class="main"><div class="content">
<div class="topbar"><button class="theme-toggle" type="button" onclick="__t()">theme</button></div>
<p><a href="index.html">← Payments overview</a></p>
<h1 id="escrow-as-an-internal-ledger-not-held-cash">Escrow as an Internal Ledger, Not Held Cash</h1>
<p>Because Balinyaar cannot custody buyer funds (§2.2), <strong>"escrow" must be a software construct: a double-entry ledger STATE over money that legally sits at a licensed provider/bank.</strong> The original ~45-table model had <strong>no ledger</strong> — escrow was only inferable by joining <code>bookings.status</code>, <code>bookings.payout_released</code>, <code>payment_transactions.status</code>, and <code>refunds</code>, with no single answer to "how much do we owe nurses right now?" Three independent critiques rated this a <strong>critical</strong> gap. The fix is one append-only table.</p>
<p>The ledger entity is detailed in the data model: see <a href="../data-model/06-payments-ledger-and-refunds.html">payments, ledger &amp; refunds</a>.</p>
<h2 id="31-ledger_entries-the-financial-source-of-truth">3.1 <code>ledger_entries</code> — the financial source of truth <a class="anchor" href="#31-ledger_entries-the-financial-source-of-truth" aria-hidden="true">#</a></h2>
<p>Append-only, never updated or deleted. Every money event posts <strong>balanced</strong> rows sharing a <code>transaction_group_id</code> (Σ debit = Σ credit). Per-nurse balances are <em>derived by filter</em>, never cached in a drifting wallet-balance column.</p>
<p><strong>Account types:</strong></p>
<div class="table-wrap"><table><thead><tr><th>account_type</th><th>Meaning</th></tr></thead><tbody>
<tr><td><code>escrow_held</code></td><td>Funds received and held (over provider custody) not yet released or refunded</td></tr>
<tr><td><code>platform_revenue</code></td><td>Balinyaar's own commission income</td></tr>
<tr><td><code>nurse_payable</code></td><td>What the platform owes the nurse (accrued, awaiting weekly payout)</td></tr>
<tr><td><code>refund_payable</code></td><td>Amount owed back to the customer / in-flight reversal</td></tr>
<tr><td><code>bnpl_fee_expense</code></td><td>The BNPL provider's merchant commission — a platform expense</td></tr>
<tr><td><code>nurse_clawback_receivable</code></td><td>Money a nurse owes back after a refund-after-payout</td></tr>
</tbody></table></div>
<h2 id="32-the-postings">3.2 The postings <a class="anchor" href="#32-the-postings" aria-hidden="true">#</a></h2>
<p>Amounts are positive; <code>direction</code> carries the sign. The three-amount split (<code>gross_price_irr</code>, <code>balinyaar_commission_irr</code>, <code>bnpl_commission_irr</code>) is defined in §7.</p>
<p><strong>(a) Card payment capture (inbound):</strong></p>
<pre><code>DEBIT escrow_held gross_price_irr
CREDIT platform_revenue balinyaar_commission_irr
CREDIT nurse_payable nurse_payout_amount (= gross balinyaar_commission)</code></pre>
<p><strong>(b) BNPL settle (inbound) — identical to a card capture, plus the provider-fee leg:</strong></p>
<pre><code>DEBIT escrow_held gross_price_irr
CREDIT platform_revenue balinyaar_commission_irr
CREDIT nurse_payable nurse_payout_amount
DEBIT bnpl_fee_expense bnpl_commission_irr
CREDIT escrow_held bnpl_commission_irr (escrow reflects NET cash actually received)</code></pre>
<p>Posted <strong>once</strong>, idempotently, keyed on the settling transaction. <strong>No installment-level postings</strong> — the customer's repayment schedule is SnappPay's ledger, not ours.</p>
<p><strong>(c) Refund — BEFORE the nurse is paid out (clean reversal):</strong></p>
<pre><code>DEBIT platform_revenue platform_fee_refunded_irr
DEBIT nurse_payable nurse_payout_refunded_irr
CREDIT refund_payable (sum)</code></pre>
<p>Clear <code>refund_payable</code> when the PSP / SnappPay confirms the customer cash-back. Nothing leaves Balinyaar toward the nurse — the <code>nurse_payable</code> accrual is simply reversed.</p>
<p><strong>(d) Clawback — refund AFTER the nurse was already paid:</strong> The nurse's <code>nurse_payable</code> was already drained by a processed payout batch, so there is nothing left to reverse. Instead the platform books a receivable:</p>
<pre><code>DEBIT nurse_clawback_receivable amount_irr (nurse_id set; nurse now owes the platform)
CREDIT refund_payable amount_irr</code></pre>
<p>Recovered by <strong>netting against the nurse's next <code>nurse_payable</code></strong> at batch time, or marked <code>written_off</code> if uncollectable. A <code>nurse_clawbacks</code> row carries the lifecycle (<code>pending</code> / <code>recovered</code> / <code>written_off</code>). This is unavoidable because <strong>Iranian payouts are real bank transfers — hard/impossible to reverse</strong> — so the right defense is <em>gating payout on the dispute window</em>, with clawback as the fallback.</p>
<h2 id="33-why-the-ledger-not-more-columns">3.3 Why the ledger, not more columns <a class="anchor" href="#33-why-the-ledger-not-more-columns" aria-hidden="true">#</a></h2>
<p>A marketplace that holds escrow, pays out weekly minus commission, and handles refunds + clawbacks has exactly the shape double-entry was invented for. The MVP cost is <strong>one table + posting discipline</strong>. The alternative (more money columns on bookings/payouts) cannot answer "how much is held but unreleased" without fragile joins and makes bank/Shaparak reconciliation nearly impossible. Keep the per-booking fee snapshot as the <em>pricing</em> record; the ledger is the <em>financial-truth / reconciliation</em> layer posted alongside.</p>
<a class="back-to-top" href="#">↑ Back to top</a>
</div></main>
</div>
<script>
(function(){var k='balinyaar-docs-theme';var s=localStorage.getItem(k);
if(s)document.documentElement.setAttribute('data-theme',s);
else if(matchMedia('(prefers-color-scheme: dark)').matches)document.documentElement.setAttribute('data-theme','dark');})();
function __t(){var d=document.documentElement;var n=d.getAttribute('data-theme')==='dark'?'light':'dark';
d.setAttribute('data-theme',n);localStorage.setItem('balinyaar-docs-theme',n);}
</script>
</body>
</html>