Balance Verification API
The Balance Verification Service reconciles cached wallet balances against the ledger to detect and flag discrepancies.
Overview
Keshless maintains two balance representations:
- Cached Balance -
User.walletBalance/Vendor.walletBalance(fast reads) - Ledger Balance - Sum of all posted ledger entries (source of truth)
The Balance Verification Service ensures these stay synchronized.
Service Methods
verifyUserBalance(userId)
Verify a single user's balance.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
userId | string | Yes | User ID |
Returns:
{
userId: string;
walletBalance: number; // Cached balance
ledgerBalance: number; // Calculated from ledger
difference: number; // Absolute difference
isReconciled: boolean; // true if difference < E0.01
}Example:
const result = await balanceVerificationService.verifyUserBalance('user-123');
if (!result.isReconciled) {
console.warn(`Discrepancy: E${result.difference}`);
}verifyVendorBalance(vendorId)
Verify a single vendor's balance.
Returns: Same structure as verifyUserBalance
verifyAccountBalance(accountCode, userId?, vendorId?)
Verify an account balance cache against ledger.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
accountCode | string | Yes | Account code (e.g., 1110) |
userId | string | No | User ID for entity-specific |
vendorId | string | No | Vendor ID for entity-specific |
Returns:
{
accountCode: string;
entityUserId?: string;
entityVendorId?: string;
cachedBalance: number;
ledgerBalance: number;
difference: number;
isReconciled: boolean;
}verifyAllUserBalances(options)
Verify all user balances in batch.
Parameters:
| Parameter | Type | Description |
|---|---|---|
options.triggeredBy | string | Actor ID for audit |
options.limit | number | Max users to check |
Returns: Reconciliation record with discrepancies
Example:
const reconciliation = await balanceVerificationService.verifyAllUserBalances({
triggeredBy: 'admin-456',
limit: 1000
});
console.log(`Checked: ${reconciliation.notes}`);
console.log(`Discrepancies: ${reconciliation.discrepancies.length}`);verifyAllVendorBalances(options)
Verify all vendor balances in batch.
Returns: Reconciliation record
verifyAllAccountBalances(options)
Verify all account balance caches.
Returns: Reconciliation record
correctUserBalance(userId, correctedBy, reason)
Correct a user's balance discrepancy by updating wallet balance to match ledger.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
userId | string | Yes | User ID |
correctedBy | string | Yes | Admin ID |
reason | string | Yes | Correction reason |
Side Effects:
- Updates
User.walletBalanceto match ledger - Creates
AuditLogentry withMANUAL_ADJUSTMENTevent
Example:
await balanceVerificationService.correctUserBalance(
'user-123',
'admin-456',
'Monthly reconciliation correction'
);correctVendorBalance(vendorId, correctedBy, reason)
Correct a vendor's balance discrepancy.
getReconciliationSummary(reconciliationId)
Get detailed summary of a reconciliation run.
Returns:
{
reconciliation: Reconciliation;
criticalDiscrepancies: number; // > E100
highPriorityDiscrepancies: number; // > E10
totalDiscrepancyAmount: number;
}autoCorrectSmallDiscrepancies(threshold, dryRun)
Automatically correct discrepancies under a threshold.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
threshold | number | 1.0 | Max amount (E) to auto-correct |
dryRun | boolean | false | Preview without changes |
Returns:
{
corrected: number;
totalAmount: number;
errors: Array<{ entityId: string; error: string }>;
}Example:
// Preview corrections under E1.00
const preview = await balanceVerificationService.autoCorrectSmallDiscrepancies(1.0, true);
console.log(`Would correct ${preview.corrected} discrepancies (E${preview.totalAmount})`);
// Execute corrections
const result = await balanceVerificationService.autoCorrectSmallDiscrepancies(1.0, false);Discrepancy Severity Levels
| Severity | Threshold | Action |
|---|---|---|
CRITICAL | > E100 | Immediate investigation |
HIGH | > E10 | Manual review required |
MEDIUM | ≤ E10 | May auto-correct |
Reconciliation Record Schema
{
id: string;
reconciliationType: 'BALANCE_VERIFICATION' | 'ACCOUNT_RECONCILIATION';
periodStart: Date;
periodEnd: Date;
systemBalance: Decimal;
calculatedBalance: Decimal;
difference: Decimal;
isReconciled: boolean;
reconciledAt?: Date;
discrepancies: Array<{
accountCode: string;
accountName: string;
entityUserId?: string;
entityVendorId?: string;
entityType: 'User' | 'Vendor' | 'System';
expectedBalance: number;
actualBalance: number;
difference: number;
severity: 'CRITICAL' | 'HIGH' | 'MEDIUM';
}>;
notes: string;
resolution?: string;
}Scheduled Verification
Balance verification runs automatically via Cloud Scheduler:
| Job | Schedule | Scope |
|---|---|---|
| User Balance Check | Daily 3:00 AM | All users with balance > 0 |
| Vendor Balance Check | Daily 3:30 AM | All vendors with balance > 0 |
| Account Balance Check | Daily 4:00 AM | All cached balances |
Dashboard Integration
Access reconciliation reports in the admin dashboard:
- Reconciliation History:
/admin/reconciliations - Discrepancy Details:
/admin/reconciliations/:id - Correction Log:
/admin/audit-logs?type=MANUAL_ADJUSTMENT
Related
- Ledger Service - Core ledger operations
- Trial Balance - Accounting equation verification
- Reconciliation - Reconciliation workflows