Skip to content

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):

  1. Click account → TransactionsNew Disbursement
  2. Fill in:
    • Amount (principal)
    • Disbursement Date
    • Payment Method (CASH, BANK_TRANSFER, CHEQUE)
  3. Click Disburse

GL Posting:

  • DR: Loan Receivable (via LOAN_RECEIVABLE_RESOLVE handler)
  • CR: Cash/Bank (via CASH_BANK_RESOLVE handler)
  • Rule: LOAN.DISBURSE

Schedule Impact:

  • Repayment schedule created with payment dates
  • Outstanding principal updated

Repayment

Client payment toward the loan balance.

Steps:

  1. Click account → TransactionsNew Repayment
  2. 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)
  3. Click Allocate to split among principal/interest/fees/penalties
  4. Click Post Repayment

Allocation Order:

  1. Penalties (if any outstanding)
  2. Fees (if any outstanding)
  3. Interest (accrued interest)
  4. Principal (remaining amount)

GL Posting (varies by repayment method):

Cash Repayment:

  • DR: Till/Cash (via CASH_IN_TILL tag)
  • CR: Loan Receivable (via LOAN_RECEIVABLE_RESOLVE handler)
  • Rule: LOAN.REPAY.CASH

Bank Transfer Repayment:

  • DR: Bank/Deposit Account (via CASH_BANK_RESOLVE handler — resolves to client's deposit account sub-ledger)
  • CR: Loan Receivable (via LOAN_RECEIVABLE_RESOLVE handler)
  • 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:

  1. Click account → TransactionsNew Write-Off
  2. Fill in:
    • Write-Off Amount (total uncollectible)
    • Write-Off Reason (e.g., "Client deceased", "Unrecoverable", "Legal action failed")
    • Write-Off Date
  3. 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:

  1. Click account → TransactionsNew Recovery
  2. Fill in:
    • Recovery Amount (partial or full)
    • Recovery Date
    • Payment Method (CASH, BANK_TRANSFER, etc.)
  3. Click Recover

GL Posting:

  • DR: Cash/Bank (via CASH_BANK_RESOLVE handler)
  • 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:

  1. Click account → Transactions → [Select transaction] → Reverse
  2. Fill in:
    • Reversal Reason (e.g., "Duplicate entry", "Data correction", "Client request")
    • Reversal Date
  3. Click Reverse

GL Posting:

  • Exact reversal of original transaction (amounts negated)
  • Rule: Original rule code + .REV suffix (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

  1. Click account → TransactionsNew Adjustment
  2. Fill in:
    • Adjustment Type (Interest Capitalization, Interest Suspension, Penalty Waiver)
    • Amount
    • Reason
  3. 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:

  1. Click account → Restructure
  2. 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")
  3. Click Preview to see new schedule
  4. 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:

StatusMeaning
PENDINGCreated but not yet posted
POSTEDGL posting successful, gl_posted=1
REVERSEDTransaction has been reversed
FAILEDGL 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_RULE system 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_resolve handler
  • 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_resolve handler
  • 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:

  1. Check Fiscal Periods — ensure current period is OPEN
  2. Check Chart of Accounts — verify all COAs in rule details exist and are APPROVED
  3. Check Rule Details — verify all DOMAIN_RESOLVED lines have handler bindings
  4. 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:

  1. Go to Loan Products → [Product]
  2. Set Default COA to a valid loan receivable account
  3. Retry transaction

"Handler produced invalid/multiple coa_id"

Cause: Handler returned NULL or multiple COAs

Fix:

  1. For BANK_TRANSFER repayments: Verify deposit_account_id is in transaction payload
  2. Verify deposit account exists and is APPROVED
  3. Verify deposit account has a sub_ledger registered in gl_domain_object_registry
  4. Verify sub_ledger has a valid COA assigned

"Some draft rules are incomplete"

Cause: GL draft batch has incomplete lines or tasks

Fix:

  1. Check GL Posting Draft Batch for the transaction
  2. Verify all draft lines have line_status = COMPLETE
  3. Verify all system tasks have task_status = COMPLETED
  4. Check GL Posting Rule Details — ensure all DOMAIN_RESOLVED lines have handler bindings

"rules not balanced"

Cause: DEBIT ≠ CREDIT totals

Fix:

  1. Check all detail lines have correct amount_source (SYSTEM, MANUAL, SUM_OF_OTHERS)
  2. Verify handlers are resolving correct amounts
  3. Check GL Posting Draft Lines for the transaction
  4. Verify all amounts are correctly calculated

Best Practices

  1. Deposit Accounts: For BANK_TRANSFER repayments, always include deposit_account_id in the transaction payload.
  2. Reversals: Always reverse via the UI. Manual reversals can cause data inconsistencies.
  3. Restructuring: Preserve paid schedule rows. Only recalculate unpaid rows.
  4. Error Handling: If GL posting fails, the entire transaction rolls back. No partial state.
  5. Fiscal Periods: Ensure fiscal periods are open before posting. Closed periods reject all GL entries.

PinkApple ERP by Stat Solutions Network