Appearance
Loan Operations
Complete guide to managing loan transactions — disbursements, repayments, write-offs, recoveries, and reversals.
Navigation: Loans → Loan Accounts → [Account] → Transactions
Transaction Types
Disbursement
The initial loan amount paid to the client when the loan account is created.
Automatic Disbursement (on application approval):
- Triggered automatically when a loan application is approved
- Amount: Full requested amount
- GL posting: DR Loan Receivable, CR Cash/Bank
Manual Disbursement (if needed):
- Click account → Transactions → New Disbursement
- Fill in:
- Amount (principal)
- Disbursement Date
- Payment Method (CASH, BANK_TRANSFER, CHEQUE)
- Click Disburse
GL Posting:
- DR: Loan Receivable (via
LOAN_RECEIVABLE_RESOLVEhandler) - CR: Cash/Bank (via
CASH_BANK_RESOLVEhandler) - Rule:
LOAN.DISBURSE
Schedule Impact:
- Repayment schedule created with payment dates
- Outstanding principal updated
Repayment
Client payment toward the loan balance.
Steps:
- Click account → Transactions → New Repayment
- Fill in:
- Repayment Amount (total payment)
- Repayment Date
- Repayment Method (CASH, BANK_TRANSFER, CHEQUE, MOBILE_MONEY)
- Deposit Account (if BANK_TRANSFER — the account money came from)
- Click Allocate to split among principal/interest/fees/penalties
- Click Post Repayment
Allocation Order:
- Penalties (if any outstanding)
- Fees (if any outstanding)
- Interest (accrued interest)
- Principal (remaining amount)
GL Posting (varies by repayment method):
Cash Repayment:
- DR: Till/Cash (via
CASH_IN_TILLtag) - CR: Loan Receivable (via
LOAN_RECEIVABLE_RESOLVEhandler) - Rule:
LOAN.REPAY.CASH
Bank Transfer Repayment:
- DR: Bank/Deposit Account (via
CASH_BANK_RESOLVEhandler — resolves to client's deposit account sub-ledger) - CR: Loan Receivable (via
LOAN_RECEIVABLE_RESOLVEhandler) - Rule:
LOAN.REPAY.BANK
Schedule Impact:
- Payment marked as PAID on schedule
- Outstanding balance reduced
- Next due date updated
Write-Off
Mark a loan as uncollectible and remove it from active portfolio.
Steps:
- Click account → Transactions → New Write-Off
- Fill in:
- Write-Off Amount (total uncollectible)
- Write-Off Reason (e.g., "Client deceased", "Unrecoverable", "Legal action failed")
- Write-Off Date
- Click Write Off
GL Posting:
- DR: Provision Liability (the reserve previously set aside)
- CR: Loan Receivable (remove from active receivables)
- Rule:
LOAN.WRITEOFF
Account Impact:
- Status:
WRITTEN_OFF - Outstanding balance: Zeroed
- Schedule: Marked as WRITTEN_OFF
Recovery
Collect payment on a previously written-off loan.
Steps:
- Click account → Transactions → New Recovery
- Fill in:
- Recovery Amount (partial or full)
- Recovery Date
- Payment Method (CASH, BANK_TRANSFER, etc.)
- Click Recover
GL Posting:
- DR: Cash/Bank (via
CASH_BANK_RESOLVEhandler) - CR: Recovery Income (fixed COA)
- Rule:
LOAN.RECOVERY
Account Impact:
- Status:
CLOSED(if fully recovered) - Outstanding balance: Reduced by recovery amount
Reversal
Undo a previous transaction (disbursement, repayment, write-off, or recovery).
Steps:
- Click account → Transactions → [Select transaction] → Reverse
- Fill in:
- Reversal Reason (e.g., "Duplicate entry", "Data correction", "Client request")
- Reversal Date
- Click Reverse
GL Posting:
- Exact reversal of original transaction (amounts negated)
- Rule: Original rule code +
.REVsuffix (e.g.,LOAN.REPAY.CASH.REV)
Schedule Impact:
- Original transaction marked as
REVERSED - Schedule rolled back to pre-transaction state
- Balances recalculated
Rollback Behavior:
- If GL posting fails, entire reversal is rolled back (no partial state)
- Original transaction remains unchanged
- Error message returned to user
Interest & Penalties
Interest Accrual
Automatic daily processing (via EOD):
Flat Rate:
- Interest calculated on original principal
- Same amount accrued each day
Reducing Balance:
- Interest calculated on outstanding balance
- Amount decreases as principal is repaid
GL Posting:
- DR: Interest Receivable
- CR: Interest Income
- Rule:
LOAN.INT.ACCRUE
Late Penalties
Applied when payment >30 days overdue (configurable per product):
GL Posting:
- DR: Penalty Receivable
- CR: Penalty Income
- Rule:
LOAN.PENALTY
Manual Adjustments
- Click account → Transactions → New Adjustment
- Fill in:
- Adjustment Type (Interest Capitalization, Interest Suspension, Penalty Waiver)
- Amount
- Reason
- Click Apply
Interest Capitalization:
- Adds unpaid interest to principal
- GL: DR Loan Receivable, CR Interest Receivable
- Rule:
LOAN.INT.CAPITALIZE
Interest Suspension:
- Stops accruing interest (for hardship cases)
- GL: DR Interest Income, CR Interest Receivable
- Rule:
LOAN.INT.SUSPEND
Loan Restructuring
Modify loan terms when client circumstances change.
Steps:
- Click account → Restructure
- Fill in:
- New Principal (if reducing/increasing)
- New Interest Rate (if changing)
- New Repayment Period (if extending/shortening)
- Restructure Reason (e.g., "Financial hardship", "Business expansion")
- Click Preview to see new schedule
- Click Restructure
Schedule Impact:
- Old schedule archived
- New schedule created with recalculated amounts
- Paid schedule rows preserved (not recalculated)
- Outstanding balance recalculated
- Account status:
RESTRUCTURED
GL Impact:
- No GL posting (internal adjustment)
- Balances updated in loan_transaction and loan_account
Transaction Status Tracking
Each transaction has a status:
| Status | Meaning |
|---|---|
| PENDING | Created but not yet posted |
| POSTED | GL posting successful, gl_posted=1 |
| REVERSED | Transaction has been reversed |
| FAILED | GL posting failed, transaction rolled back |
View transaction status in the Transactions tab.
GL Posting Validation
Before posting a loan transaction, the system validates:
- ✅ Fiscal period is OPEN
- ✅ All COAs in rule details exist and are APPROVED
- ✅ Loan product has GL rules bound
- ✅ All GL rules have
LOAN_GL_RULEsystem tags - ✅ All DOMAIN_RESOLVED lines have handler bindings
- ✅ Handlers can resolve COAs (deposit accounts, loan products)
- ✅ Draft batch has all lines with
line_status = COMPLETE - ✅ All system tasks have
task_status = COMPLETED - ✅ DEBIT = CREDIT totals
If any validation fails, the transaction is rolled back completely — no partial state.
GL Posting Failure Behavior
All loan transactions rollback completely if GL posting fails:
- Outstanding balances are NOT affected
- No loan_transaction record is created
- No schedule updates are applied
- The error is returned to the user
Exception: Batch operations (interest accrual, penalties)
- Individual loan failures are logged
- Other loans continue processing
- Failed loans are retried next cycle
Key Concepts
Loan Receivable COA
The account that tracks the principal amount owed by the client.
- Resolved by
hdlr_loan_receivable_resolvehandler - For BANK_TRANSFER repayments: Uses client's deposit account sub_ledger
- For CASH repayments: Uses loan product's default COA
- Appears as DEBIT in disbursements, CREDIT in repayments
Cash/Bank COA
The account that tracks cash inflows/outflows.
- Resolved by
hdlr_cash_bank_resolvehandler - For CASH repayments: Uses till account (COA 167 — Till Cash Control)
- For BANK_TRANSFER repayments: Uses till account as fallback
- Appears as CREDIT in disbursements, DEBIT in repayments
Deposit Account Sub-Ledger
For BANK_TRANSFER repayments, the system resolves the client's deposit account and its sub_ledger:
- Sub_ledger tracks the client's savings balance
- COA resolves to the deposit account's GL account
- Used to ensure repayments are credited to the correct client account
Troubleshooting
"GL posting failed ... Transaction rolled back"
Cause: GL engine rejected the posting
Fix:
- Check Fiscal Periods — ensure current period is OPEN
- Check Chart of Accounts — verify all COAs in rule details exist and are APPROVED
- Check Rule Details — verify all DOMAIN_RESOLVED lines have handler bindings
- Check GL Configuration — verify business unit has proper GL settings
"Cannot resolve coa_id for cash/bank"
Cause: Loan product has no default COA set
Fix:
- Go to Loan Products → [Product]
- Set Default COA to a valid loan receivable account
- Retry transaction
"Handler produced invalid/multiple coa_id"
Cause: Handler returned NULL or multiple COAs
Fix:
- For BANK_TRANSFER repayments: Verify
deposit_account_idis in transaction payload - Verify deposit account exists and is APPROVED
- Verify deposit account has a sub_ledger registered in
gl_domain_object_registry - Verify sub_ledger has a valid COA assigned
"Some draft rules are incomplete"
Cause: GL draft batch has incomplete lines or tasks
Fix:
- Check GL Posting Draft Batch for the transaction
- Verify all draft lines have
line_status = COMPLETE - Verify all system tasks have
task_status = COMPLETED - Check GL Posting Rule Details — ensure all DOMAIN_RESOLVED lines have handler bindings
"rules not balanced"
Cause: DEBIT ≠ CREDIT totals
Fix:
- Check all detail lines have correct
amount_source(SYSTEM, MANUAL, SUM_OF_OTHERS) - Verify handlers are resolving correct amounts
- Check GL Posting Draft Lines for the transaction
- Verify all amounts are correctly calculated
Best Practices
- Deposit Accounts: For BANK_TRANSFER repayments, always include
deposit_account_idin the transaction payload. - Reversals: Always reverse via the UI. Manual reversals can cause data inconsistencies.
- Restructuring: Preserve paid schedule rows. Only recalculate unpaid rows.
- Error Handling: If GL posting fails, the entire transaction rolls back. No partial state.
- Fiscal Periods: Ensure fiscal periods are open before posting. Closed periods reject all GL entries.
Related Documentation
- Loan Products — Product configuration
- Loan Accounts — Account management
- Loan GL Setup — GL posting rules and handlers
- GL Posting Rules — Rule creation and binding
