Skip to content

Integration Guide

This guide shows how to integrate the double-entry accounting system with wallet operations.

Integration Pattern

Every wallet operation follows this flow:

  1. Create WalletTransaction (existing model)
  2. Create Journal Entry (double-entry record)
  3. Update Wallet Balances (existing logic)
  4. All within a database transaction (ACID compliance)

Key Principles

Use Database Transactions

All operations must be wrapped in a database transaction to ensure ACID compliance. If any step fails, everything rolls back.

autoPost Defaults to True

Transactions are posted immediately by default. Only set autoPost: false for flagged/high-risk transactions requiring compliance review.

Always Use Templates

Use the predefined templates from transactionTemplatesService - never create journal entries manually.

Always link journal entries to their source wallet transaction using walletTransactionId.


Transaction Types

User → User Transfer (P2P)

StepAction
1Validate sender has sufficient balance
2Create WalletTransaction with type USER_TRANSFER_SENT
3Create journal using getUserTransferTemplate(senderId, recipientId, amount)
4Deduct from sender balance
5Add to recipient balance

User → Vendor Payment

StepAction
1Validate user has sufficient balance (amount + fee)
2Create WalletTransaction with type PAYMENT
3Create journal using getUserPaymentTemplate(userId, vendorId, amount, fee)
4Deduct (amount + fee) from user balance
5Add amount to vendor balance

Note: Fee goes to platform revenue (account 4110)


Wallet Topup

StepAction
1Process external payment (mobile money, etc.)
2Create WalletTransaction with type TOPUP
3Create journal using getUserTopupTemplate(userId, amount, source)
4Add amount to user balance

Cash Withdrawal

StepAction
1Validate user has sufficient balance (amount + fee)
2Create WalletTransaction with type WITHDRAWAL
3Create journal using getUserWithdrawalTemplate(userId, vendorId, amount, fee)
4Deduct (amount + fee) from user balance
5Add amount to vendor cash-on-hand

Refund

StepAction
1Get original transaction details
2Create WalletTransaction with type REFUND
3Create journal using getUserRefundTemplate(userId, amount, reason)
4Add amount back to original payer
5Deduct from original recipient

Note: Refunds require approval, use autoPost: false


Error Handling

Transaction Rollback

If any operation fails, the entire transaction is rolled back. No partial state is persisted.

Balance Validation

Always validate balance before deducting:

CheckDescription
Sufficient balanceUser/vendor has enough funds
Positive amountTransaction amount > 0
Valid entitiesSender and recipient exist

Duplicate Detection

Check for duplicate transactions within the last minute using same entityId, type, and amount.


Journal Entry Options

OptionTypeDefaultDescription
walletTransactionIdstring-Link to source transaction (required)
actorIdstring-User/admin performing action
ipAddressstring-Request IP for audit
requestIdstring-Request tracking ID
autoPostbooleantruePost immediately vs pending review
amlStatusstring-Set if flagged for AML review

When to Disable autoPost

ScenarioReason
High-value paymentsCompliance review threshold
AML flagged transactionSuspicious activity detected
Refund processingRequires admin approval
Manual adjustmentsFinance team review

Reconciliation

Daily reconciliation runs automatically at 2 AM and verifies:

  • Wallet balances match ledger entries
  • All transactions have corresponding journal entries
  • No orphaned entries exist

If discrepancies are found, alerts are generated automatically.


Benefits of Integration

BeforeAfter
No audit trailComplete audit trail with tamper detection
Balance discrepancies hard to traceAutomatic reconciliation verification
No regulatory complianceDouble-entry bookkeeping compliance
Partial failures possibleACID-compliant (all-or-nothing)

Internal use only - Keshless Payment Platform