Skip to content

Double-Entry Financial Ledger Engine ​

To guarantee zero financial discrepancies, fraud resistance, and full auditability, Reyhan Commerce includes a built-in Double-Entry General Ledger Subsystem.

Every commercial transaction (order settlement, wallet top-up, voucher grant, customer refund) creates an atomic LedgerTransaction containing strictly balanced LedgerEntry records (sum(debit) === sum(credit)).


1. Accounting Chart of Accounts ​

Reyhan seeds standard enterprise ledger accounts during framework installation:

Account CodeAccount NameTypeNormal BalanceDescription
10101Online Gateway Clearing (Shaparak)AssetDebitFunds received via online banking gateways (Zarinpal, SEP, Behpardakht)
10102Card-to-Card In-TransitAssetDebitOffline card-to-card settlements awaiting staff approval
20101Customer Wallet LiabilitiesLiabilityCreditCustomer deposited store credit and gift wallet balances
20301Value-Added Tax (VAT) PayableLiabilityCreditOfficial Iranian 10% sales tax collected on behalf of the tax authority
40101Gross Merchandise RevenueRevenueCreditGross merchandise value sold across catalog items
40201Shipping & Logistics RevenueRevenueCreditShipping fees paid by customers
50101Promotional Discount ExpenseExpenseDebitMarketing vouchers and coupon deductions absorbed by the store

2. Order Settlement Balance Equation ​

Upon successful payment verification, CreateLedgerJournalEntryAction validates the following invariant:

$$\text{Debit} (\text{Bank} + \text{Wallet} + \text{Discounts}) = \text{Credit} (\text{Merchandise} + \text{Shipping} + \text{VAT})$$

If an unbalanced transaction is attempted, the database transaction rolls back immediately and throws an InvalidArgumentException.


3. The Ledger Facade ​

Developers and extensions interact with the accounting engine via the fluent Ledger facade:

php
use Reyhan\Core\Facades\Ledger;

// Record a balanced journal entry for an order payment
$transaction = Ledger::recordOrderSettlement($order, $payment);

// Query net balance for any ledger account
$gatewayCash = Ledger::getAccountBalance('10101'); // Net Bank Clearing
$walletLiability = Ledger::getAccountBalance('20101'); // Total customer deposits held
$taxCollected = Ledger::getAccountBalance('20301'); // Total VAT due

Released under the MIT License.