Skip to main content

Loan Product - Accounting Configuration (V2)

Module: Loan Products
Configuration Section: accountingConfig
Version: V2 (ConfigData YAML)
Status: ✅ Production Ready


Overview

The Accounting Configuration section defines how loan transactions are posted to the General Ledger. V2 uses a flexible Account Leg system where each transaction component maps to specific GL accounts based on the accounting methodology.

Key Concepts

  1. Account Legs: Predefined transaction components (e.g., PortfolioControl, InterestReceivable)
  2. Methodology: Accrual or Cash accounting
  3. GL Account Mapping: Each leg maps to a specific GL account code
  4. Multi-Company Support: Optional company-specific GL accounts

Accounting Methodology

MethodologyDescriptionWhen to UseImpact
CashRecognize revenue when cash is receivedSimple operations, high-risk lendingRevenue only when collected
AccrualRecognize revenue when earned (regardless of payment)Standard banking practice, IFRS 9 complianceRevenue accrued daily, provisions tracked

Cash vs Accrual Comparison

Cash Accounting:

accountingConfig:
interestRecognitionMethod: Cash
  • ✅ Simple revenue recognition
  • ✅ No accruals to manage
  • ❌ Overstates profitability (ignores unpaid interest)
  • ❌ Poor risk visibility
  • Use Case: Microfinance, high-risk consumer lending

Accrual Accounting:

accountingConfig:
interestRecognitionMethod: Accrual
  • ✅ True financial position (IFRS 9 compliant)
  • ✅ Shows expected cash flows
  • ✅ Better risk management (provisions, NPLs)
  • ❌ More complex GL posting
  • Use Case: Commercial banking, regulatory compliance

Account Leg Types

The V2 system defines 9 standard account legs for loan products:

1. PortfolioControl (Required)

Purpose: Loan principal outstanding (asset account)
Account Type: Asset
Normal Balance: Debit

Transactions:

  • Disbursement: Debit (increase asset)
  • Principal Repayment: Credit (decrease asset)
  • Write-off: Credit (remove asset)

Example:

- legType: PortfolioControl
accountCode: "1020100" # Loans and Advances - Customer
description: "Loan portfolio principal outstanding"

2. InterestReceivable (Accrual Only)

Purpose: Accrued but uncollected interest income
Account Type: Asset
Normal Balance: Debit

Transactions:

  • Daily Accrual: Debit (increase receivable)
  • Interest Payment: Credit (clear receivable)
  • Write-off: Credit (remove uncollectible)

Example:

- legType: InterestReceivable
accountCode: "1020200" # Interest Receivable on Loans
description: "Accrued interest on loan portfolio"

3. InterestIncome (Required)

Purpose: Interest revenue earned
Account Type: Income
Normal Balance: Credit

Transactions:

  • Accrual Accounting: Credit (daily accrual)
  • Cash Accounting: Credit (when payment received)

Example:

- legType: InterestIncome
accountCode: "4020100" # Interest Income on Loans
description: "Interest revenue from loan portfolio"

4. FeeReceivable (Accrual Only)

Purpose: Accrued but uncollected fee income
Account Type: Asset
Normal Balance: Debit

Transactions:

  • Fee Charge: Debit (increase receivable)
  • Fee Payment: Credit (clear receivable)

Example:

- legType: FeeReceivable
accountCode: "1020300" # Fee Receivable
description: "Processing and management fees receivable"

5. FeeIncome (Required)

Purpose: Fee revenue earned
Account Type: Income
Normal Balance: Credit

Transactions:

  • Processing Fee: Credit (at disbursement)
  • Management Fee: Credit (periodic)
  • Late Payment Fee: Credit (when charged)

Example:

- legType: FeeIncome
accountCode: "4020200" # Fee Income on Loans
description: "Non-interest income from loan products"

6. PenaltyReceivable (Accrual Only)

Purpose: Accrued but uncollected penalties
Account Type: Asset
Normal Balance: Debit

Transactions:

  • Penalty Charge: Debit (increase receivable)
  • Penalty Payment: Credit (clear receivable)
  • Waiver: Credit (forgive penalty)

Example:

- legType: PenaltyReceivable
accountCode: "1020400" # Penalty Receivable
description: "Late payment and default penalties"

7. PenaltyIncome (Optional)

Purpose: Penalty revenue earned
Account Type: Income
Normal Balance: Credit

Transactions:

  • Late Payment Penalty: Credit (when charged)
  • Default Penalty: Credit (when applied)

Example:

- legType: PenaltyIncome
accountCode: "4020300" # Penalty Income
description: "Revenue from penalties and late fees"

8. WriteOffExpensePrincipal (Required for Write-offs)

Purpose: Loss on uncollectible principal
Account Type: Expense
Normal Balance: Debit

Transactions:

  • Write-off Principal: Debit (recognize loss)
  • Recovery: Credit (reverse loss)

Example:

- legType: WriteOffExpensePrincipal
accountCode: "5030100" # Loan Write-off Expense - Principal
description: "Uncollectible loan principal expense"

9. WriteOffExpenseInterest (Optional)

Purpose: Loss on uncollectible interest
Account Type: Expense
Normal Balance: Debit

Transactions:

  • Write-off Interest: Debit (recognize loss)
  • Recovery: Credit (reverse loss)

Example:

- legType: WriteOffExpenseInterest
accountCode: "5030200" # Loan Write-off Expense - Interest
description: "Uncollectible interest expense"

Complete AccountingConfig Section

Basic Structure

accountingConfig:
interestRecognitionMethod: Cash | Accrual
accountLegs:
- legType: PortfolioControl
accountCode: "string"
companyCode: "string" # Optional
description: "string" # Optional
- legType: InterestIncome
accountCode: "string"
# ... additional legs

Field Reference

Field NameData TypeRequiredDescriptionExample
interestRecognitionMethodEnum✅ YesAccounting methodology"Cash" or "Accrual"
accountLegs[]Array✅ YesGL account mappingsSee below
accountLegs[].legTypeEnum✅ YesAccount leg type"PortfolioControl"
accountLegs[].accountCodeString✅ YesGL account code"1020100"
accountLegs[].companyCodeStringNoCompany code (multi-company)"COMP001"
accountLegs[].descriptionStringNoLeg description"Loan principal"

Required Account Legs by Methodology

MethodologyRequired LegsOptional Legs
Cash• PortfolioControl
• InterestIncome
• FeeIncome
• PenaltyIncome
• WriteOffExpensePrincipal
• WriteOffExpenseInterest
Accrual• PortfolioControl
• InterestReceivable
• InterestIncome
• FeeReceivable
• FeeIncome
• PenaltyReceivable
• PenaltyIncome
• WriteOffExpensePrincipal
• WriteOffExpenseInterest

Sample Configurations

Example 1: Cash Accounting (Simple Consumer Loan)

accountingConfig:
interestRecognitionMethod: Cash
accountLegs:
# Loan principal outstanding
- legType: PortfolioControl
accountCode: "1020100"
description: "Personal Loan Portfolio"

# Interest income (recognized when received)
- legType: InterestIncome
accountCode: "4020100"
description: "Interest Income on Personal Loans"

# Processing and management fees
- legType: FeeIncome
accountCode: "4020200"
description: "Loan Fee Income"

# Optional: Penalties
- legType: PenaltyIncome
accountCode: "4020300"
description: "Late Payment Penalties"

# Optional: Write-offs
- legType: WriteOffExpensePrincipal
accountCode: "5030100"
description: "Bad Debt Expense - Principal"

Transaction Flow (Disbursement of ₦100,000):

DR: PortfolioControl (1020100)   ₦100,000
CR: Cash/Disbursement Account ₦100,000

Transaction Flow (Repayment: ₦10,000 Principal + ₦2,000 Interest):

DR: Cash Account                 ₦12,000
CR: PortfolioControl (1020100) ₦10,000
CR: InterestIncome (4020100) ₦2,000

Example 2: Accrual Accounting (Standard Banking)

accountingConfig:
interestRecognitionMethod: Accrual
accountLegs:
# Loan principal outstanding
- legType: PortfolioControl
accountCode: "1020100"
description: "Term Loan Portfolio"

# Accrued interest receivable
- legType: InterestReceivable
accountCode: "1020200"
description: "Interest Receivable on Term Loans"

# Interest income (accrued daily)
- legType: InterestIncome
accountCode: "4020100"
description: "Interest Income on Term Loans"

# Fee receivable
- legType: FeeReceivable
accountCode: "1020300"
description: "Fee Receivable"

# Fee income
- legType: FeeIncome
accountCode: "4020200"
description: "Loan Fee Income"

# Penalty receivable
- legType: PenaltyReceivable
accountCode: "1020400"
description: "Penalty Receivable"

# Penalty income
- legType: PenaltyIncome
accountCode: "4020300"
description: "Penalty Income"

# Write-off expense accounts
- legType: WriteOffExpensePrincipal
accountCode: "5030100"
description: "Write-off Expense - Principal"

- legType: WriteOffExpenseInterest
accountCode: "5030200"
description: "Write-off Expense - Interest"

Transaction Flow (Daily Interest Accrual of ₦50):

DR: InterestReceivable (1020200)  ₦50
CR: InterestIncome (4020100) ₦50

Transaction Flow (Repayment: ₦10,000 Principal + ₦2,000 Interest):

DR: Cash Account                  ₦12,000
CR: PortfolioControl (1020100) ₦10,000
CR: InterestReceivable (1020200) ₦2,000

Transaction Flow (Write-off: ₦5,000 Principal + ₦500 Interest):

DR: WriteOffExpensePrincipal (5030100)  ₦5,000
DR: WriteOffExpenseInterest (5030200) ₦500
CR: PortfolioControl (1020100) ₦5,000
CR: InterestReceivable (1020200) ₦500

Example 3: Multi-Company Configuration

accountingConfig:
interestRecognitionMethod: Accrual
accountLegs:
# Company A - Retail loans
- legType: PortfolioControl
accountCode: "1020100"
companyCode: "RETAIL"
description: "Retail Loan Portfolio"

# Company B - SME loans
- legType: PortfolioControl
accountCode: "1020150"
companyCode: "SME"
description: "SME Loan Portfolio"

# Shared interest income (no company code)
- legType: InterestIncome
accountCode: "4020100"
description: "Interest Income (All Companies)"

# ... other legs

Transaction Processing

How BPMCore Uses AccountingConfig

All BPMCore loan transaction handlers follow this pattern:

Code Removed

Implementation details removed for security.

Contact support for implementation guidance.

Repayment Waterfall Logic

When a payment is received, it's applied in this order:

  1. Penalty (oldest first)
  2. Fee (processing, management)
  3. Interest (accrued)
  4. Principal (remaining amount)

Example: ₦15,000 Payment

Outstanding Balances:
- Penalty: ₦500
- Fee: ₦1,000
- Interest: ₦3,500
- Principal: ₦95,000

Payment Allocation:
1. ₦500 → PenaltyReceivable
2. ₦1,000 → FeeReceivable
3. ₦3,500 → InterestReceivable
4. ₦10,000 → PortfolioControl (principal)

Total: ₦15,000

Validation Rules

The system automatically validates:

  1. Required Legs Present: Based on methodology
  2. Valid Account Codes: GL accounts must exist
  3. No Duplicates: Each leg type appears once per company
  4. Methodology Consistency: Accrual requires receivable accounts

Example Validation Error:

# ❌ INVALID: Missing InterestReceivable for Accrual
accountingConfig:
interestRecognitionMethod: Accrual
accountLegs:
- legType: PortfolioControl
accountCode: "1020100"
- legType: InterestIncome
accountCode: "4020100"
# Missing: InterestReceivable (required for Accrual)

Error Message: "Accrual accounting requires InterestReceivable account leg"


Advanced Scenarios

Scenario 1: Interest Capitalization

When unpaid interest is added to principal:

// Accrual: Move from InterestReceivable to PortfolioControl
DR: InterestReceivable (1020200) (₦1,000) [Reduce receivable]
CR: InterestReceivable (1020200) ₦1,000 [Reverse accrual]

DR: PortfolioControl (1020100) ₦1,000 [Increase principal]
CR: InterestIncome (4020100) ₦1,000 [Recognize as income]

Scenario 2: Partial Write-off (Restructuring)

When ₦10,000 of ₦50,000 loan is forgiven:

DR: WriteOffExpensePrincipal (5030100)  ₦10,000
CR: PortfolioControl (1020100) ₦10,000

New Principal: ₦40,000

Scenario 3: Loan Recovery (After Write-off)

When previously written-off ₦5,000 is recovered:

DR: Cash Account                        ₦5,000
CR: WriteOffExpensePrincipal (5030100) ₦5,000 [Reverse expense]

OR (alternative treatment):
DR: Cash Account ₦5,000
CR: RecoveryIncome (4020400) ₦5,000 [New income]

Migration from V1

V1 Structure (Old)

Code Removed

Implementation details removed for security.

Contact support for implementation guidance.

V2 Structure (New)

accountingConfig:
interestRecognitionMethod: Accrual
accountLegs:
- legType: PortfolioControl
accountCode: "1020100"
- legType: InterestReceivable
accountCode: "1020200"
- legType: InterestIncome
accountCode: "4020100"

Migration Benefits

  1. Flexibility: Add custom legs without schema changes
  2. Multi-Company: Support multiple companies in one product
  3. Granularity: Separate write-off by component (principal vs interest)
  4. Validation: Built-in YAML validation
  5. Documentation: Self-documenting with descriptions

Automatic V1 Fallback

If ConfigData is null, the system automatically uses V1:

Code Removed

Implementation details removed for security.

Contact support for implementation guidance.


Troubleshooting

Common Issues

Issue 1: Missing Required Leg

Error: "PortfolioControl account leg is required"

Solution:

accountingConfig:
interestRecognitionMethod: Cash
accountLegs:
- legType: PortfolioControl # ✅ Add this
accountCode: "1020100"

Issue 2: Invalid GL Account

Error: "GL Account '9999999' not found"

Solution: Verify account code exists in Chart of Accounts

Issue 3: Receivable Missing for Accrual

Error: "Accrual methodology requires InterestReceivable"

Solution: Add missing receivable accounts for Accrual

Issue 4: Write-off Without Expense Account

Error: "WriteOffExpensePrincipal account required for write-off transactions"

Solution: Add write-off expense accounts if write-offs are expected


Best Practices

1. Use Accrual for Regulated Institutions

# ✅ RECOMMENDED: IFRS 9 compliance
interestRecognitionMethod: Accrual

2. Always Include Write-off Accounts

# ✅ GOOD: Prepared for NPLs
- legType: WriteOffExpensePrincipal
accountCode: "5030100"
- legType: WriteOffExpenseInterest
accountCode: "5030200"

3. Document Each Leg

# ✅ GOOD: Clear descriptions
- legType: PortfolioControl
accountCode: "1020100"
description: "Personal loan portfolio - retail customers"

4. Separate Write-off by Type

# ✅ GOOD: Track principal vs interest separately
- legType: WriteOffExpensePrincipal
accountCode: "5030100" # Principal losses
- legType: WriteOffExpenseInterest
accountCode: "5030200" # Interest losses

5. Plan for Recoveries

# ✅ GOOD: Use same write-off account for recoveries
# OR create separate recovery income account
- legType: RecoveryIncome # Future extension
accountCode: "4020400"


Version History

VersionDateChanges
V2.0Jan 2026Initial V2 AccountingConfig documentation
V1.0-Legacy table-based accounting (deprecated)

Support

For questions or issues: