Getting Started
Welcome to the Keshless Accounting System documentation. This guide will help you understand and integrate the double-entry bookkeeping system into your fintech application.
What is the Keshless Accounting System?
A complete ACID-compliant double-entry bookkeeping system built specifically for the Keshless fintech application. Every financial transaction creates balanced journal entries with immutable audit trails, ensuring regulatory compliance and accurate financial records.
Key Features
- ACID Compliance - All operations wrapped in PostgreSQL transactions with automatic rollback on failures
- Double-Entry Bookkeeping - Every transaction creates balanced debit/credit pairs following accounting principles
- Immutability - Posted ledger entries cannot be modified, only reversed through proper accounting procedures
- Tamper-Proof Audit Trail - Complete logging with SHA-256 hash chaining to detect any tampering
- Pending/Posted Workflow - Validate transactions for 30 minutes before finalization
- Automated Reconciliation - Daily balance verification at 2 AM to ensure wallet balances match ledger
- Financial Reports - Trial balance, account statements, and P&L reports ready out of the box
System Components
Models (6)
- ChartOfAccounts - Hierarchical account structure (Assets, Liabilities, Equity, Revenue, Expenses)
- JournalEntry - Groups related ledger entries with workflow status (PENDING/POSTED/REVERSED)
- LedgerEntry - Individual debit/credit records (immutable once posted)
- AccountBalance - Performance cache with reconciliation tracking
- Reconciliation - Audit reconciliation records with discrepancy detection
- AuditLog - Tamper-proof audit trail with hash chaining
Services (7)
- chartOfAccountsService - Manage chart of accounts
- transactionTemplatesService - 10+ predefined double-entry patterns
- ledgerService - ACID-compliant journal/ledger operations
- postingService - Pending → Posted workflow management
- balanceVerificationService - Reconciliation logic
- trialBalanceService - Financial reporting
- statementService - Account statements generation
Jobs (1)
- dailyReconciliation - Automated reconciliation runs at 2 AM daily
Currency
All amounts are in E (Emalageni) - the system is locked to this currency only. No multi-currency support.
Quick Start
1. Initialize the System
Run this once on server startup to seed the chart of accounts and verify system integrity:
import { initializeAccountingSystem } from './utils/initializeAccounting';
// Run once on server startup
await initializeAccountingSystem();This will:
- Seed 25+ standard accounts to Chart of Accounts
- Verify audit log integrity
- Display system status in console
2. Your First Transaction: P2P Transfer
Here's how to create a peer-to-peer transfer between two users:
import { ledgerService, transactionTemplatesService } from './services/accounting';
// Step 1: Create transfer template
const template = transactionTemplatesService.getUserTransferTemplate(
senderId, // User sending money
recipientId, // User receiving money
100, // Amount (E100)
'REF-12345' // Optional reference
);
// Step 2: Create journal entry (ACID transaction - POSTED immediately)
const { journal, ledgerEntries } = await ledgerService.createJournalEntry(template, {
walletTransactionId: walletTxn._id,
actorId: senderId,
ipAddress: req.ip,
requestId: req.id,
// autoPost defaults to true (industry standard - immediate posting)
// Only set to false for flagged/high-risk transactions requiring manual review
});
console.log(`✅ Journal ${journal.journalId} created with ${ledgerEntries.length} entries`);What happens behind the scenes:
- Debit: User A's wallet account (asset) decreases by E100
- Credit: User B's wallet account (asset) increases by E100
- Both entries are created atomically in a PostgreSQL transaction
- Entries are immediately POSTED (finalized) - industry standard
- User B can spend the money instantly
- An audit log entry is created with hash chaining
3. Example: Vendor Payment with Fee
When a user pays a vendor and Keshless charges a transaction fee:
const template = transactionTemplatesService.getUserPaymentTemplate(
userId, // User paying
vendorId, // Vendor receiving
95, // Payment amount (E95)
5, // Fee (E5)
'PAY-789' // Reference
);
const { journal } = await ledgerService.createJournalEntry(template, {
walletTransactionId: walletTxn._id,
actorId: userId,
autoPost: false, // Exception: High-value payment requires manual review
amlStatus: 'flagged', // Mark for compliance team review
});
// Later, manually post it after compliance review
await postingService.postEntry(journal.journalId, {
postedBy: adminId,
notes: 'Compliance verified - approved',
});What happens behind the scenes:
- Debit: User wallet account decreases by E100 (95 + 5)
- Credit: Vendor wallet account increases by E95
- Credit: Fee revenue account increases by E5
- Total debits (E100) = Total credits (E95 + E5) ✅
- Entry is PENDING (exception) awaiting compliance review
- User and vendor balances are updated immediately regardless
Workflow States
Journal entries follow this lifecycle:
POSTED (default 95%+) → [REVERSED if correction needed]
PENDING (exception <5%) → POSTED or CANCELLED- POSTED (default): Entry finalized immediately and immutable - industry standard
- PENDING (exception): High-risk/flagged entries awaiting manual review
- REVERSED: Posted entry corrected with offsetting entry (original remains intact)
- CANCELLED: Pending entry rejected before posting
Next Steps
- Architecture Guide - Understand the system design
- Integration Guide - Step-by-step integration with wallet operations
- Transaction Templates - All 10+ available templates
- API Reference - Detailed service methods
Need Help?
Check the Troubleshooting Guide for common issues and solutions.