Double-Entry Accounting Architecture
Tracepos is designed from the ground up as an accounting-first ERP and POS platform. Unlike conventional point-of-sale systems that merely store receipts in isolated tables, every transactional operation in Tracepos automatically generates mathematically verified, balanced Journal Entries across your General Ledger.
This page explains how the double-entry accounting engine works, the chart of accounts structure, how API requests map to ledger debits and credits, and how imbalance protection safeguards financial data integrity.
1. The Balanced Ledger Rule
In double-entry bookkeeping, every financial event must satisfy the core fundamental equation:
$$\sum \text{Debits} = \sum \text{Credits}$$
Tracepos enforces this rule inside AccountingService::createEntry():
- Arbitrary Precision Comparison: Tracepos compares
totalDebitandtotalCreditusing PHP'sbccomp()to two decimal places:if (bccomp((string) $totalDebit, (string) $totalCredit, 2) !== 0) { // Abort transaction and log failure } - Strict Imbalance Protection: If an operation results in an imbalance (even by 1 kobo / 1 cent), the database transaction is immediately rolled back, a record is written to
log_failed_transactions, and a422 Unprocessable Entityis returned to the API client. No partial or corrupted ledger records can ever be saved.
2. Standard Chart of Accounts (COA)
Tracepos initializes a standardized Chart of Accounts for each company, partitioned into 5 standard accounting classes:
| Account Code | Account Name | Type | Normal Balance | Description |
|---|---|---|---|---|
11100 | Cash & Bank Accounts | Asset | Debit | Cash drawer floats, bank accounts, POS merchant accounts |
11500 | Accounts Receivable (A/R) | Asset | Debit | Money owed by customers for credit sales |
11700 | Inventory Asset | Asset | Debit | Total balance sheet valuation of merchandise in stock |
21100 | Accounts Payable (A/P) | Liability | Credit | Money owed to vendors for purchases on credit |
41100 | Sales Revenue | Income | Credit | Gross income from merchandise and service sales |
41200 | Sales Returns | Contra-Income | Debit | Reductions in revenue from returned customer orders |
51100 | Cost of Goods Sold (COGS) | Expense | Debit | Purchase cost of goods sold during checkout |
51200 | Purchase Returns | Contra-Expense | Credit | Reversals of procurement costs returned to suppliers |
52000+ | Operating Expenses | Expense | Debit | Store rent, diesel, utility bills, maintenance |
3. How API Endpoints Map to Ledgers
Every API write endpoint seamlessly orchestrates accounting entries behind the scenes:
1. Sale on Credit (POST /sales)
When a customer purchases goods on credit (without payment):
- Debit:
11500Accounts Receivable (Total Invoice Value) - Credit:
41100Sales Revenue (Subtotal) - Credit:
21200Sales Tax Payable (Tax Amount) - Inventory Movement:
- Debit:
51100Cost of Goods Sold (Unit Cost × Quantity) - Credit:
11700Inventory Asset (Unit Cost × Quantity)
- Debit:
2. Sale with Immediate POS Payment (POST /sales with all_payments)
When a sale is paid immediately via Cash or POS terminal:
- Debit:
11100Cash / Bank / POS Clearing Account (Tender Amount) - Credit:
41100Sales Revenue (Subtotal) - Credit:
21200Sales Tax Payable (Tax Amount) - Inventory Movement:
- Debit:
51100Cost of Goods Sold - Credit:
11700Inventory Asset
- Debit:
3. Customer Debt Settlement (POST /payments with payment_type = 'in')
When a customer pays their outstanding bill:
- Debit:
11100Cash Drawer or Bank Account - Credit:
11500Accounts Receivable (reducing customer debt)
4. Supplier Stock Intake (POST /purchases)
When receiving new shipment from a vendor on credit:
- Debit:
11700Inventory Asset (Total Purchase Cost) - Credit:
21100Accounts Payable (increasing debt owed to vendor)
5. Supplier Bill Payment (POST /payments with payment_type = 'out')
When disbursing wire transfer or cash to a supplier:
- Debit:
21100Accounts Payable (reducing debt owed to vendor) - Credit:
11100Cash Drawer or Bank Account
6. Stock Adjustment (POST /stock-adjustments)
When physical inventory is corrected during an audit:
- Adding Stock (
add):- Debit:
11700Inventory Asset - Credit:
51100Inventory Overages & Gain
- Debit:
- Subtracting Stock (
subtract):- Debit:
51100Inventory Shrinkage & Loss (COGS) - Credit:
11700Inventory Asset
- Debit:
7. Operating Expense (POST /expenses)
- Auto-Approved / Paid Immediately:
- Debit: Category Expense Ledger (e.g.
52100Fuel & Energy) - Credit:
11100Cash or Bank
- Debit: Category Expense Ledger (e.g.
- Pending Approval:
- Debit: Category Expense Ledger
- Credit:
21100Accounts Payable
4. Audit Trail & Imbalance Logs
If third-party integrations attempt an invalid or mathematically unsound transaction, Tracepos captures complete failure telemetry in log_failed_transactions:
{
"company_id": 4,
"warehouse_id": 1,
"reason": "Imbalance Detected: Total Debit (15000.00) !== Total Credit (14990.00)",
"transaction_data": {
"entries": [
{ "account_id": 12, "debit_amount": 15000.00, "credit_amount": 0.00 },
{ "account_id": 34, "debit_amount": 0.00, "credit_amount": 14990.00 }
],
"context": {
"user_id": 105,
"narration": "API Payment Settlement #PAY-IN-48"
}
},
"timestamp": "2026-09-30T14:15:00.000000Z"
}
This prevents silent ledger discrepancies and allows enterprise engineering teams to debug rounding mismatches or third-party fee deductions quickly.
Reconciliation Guidelines for Fintech Integrations
- Reconciling POS Terminals: Map your smart terminal settlements into a designated clearing account under
11100(e.g.,11105 - Moniepoint POS Terminal 01). At the end of each day, perform a ledger transfer from11105to your primary commercial bank account once settlement funds are credited. - Handling Gateway Transaction Fees: When payment gateways (such as Paystack, Flutterwave, or Stripe) deduct transaction processing fees (e.g. 1.5%), record the customer payment for the full invoice gross amount to clear accounts receivable completely, then record a separate
POST /expensesfor the gateway processing fee against52300 - Bank & Payment Gateway Charges. - Multi-Currency Hedging: When operating across currency borders, transactions are normalized against the company's base currency (
base_currency_id), tracking foreign exchange variance in dedicated Gain/Loss ledger accounts.
