Loan Disbursement
Complete guide to loan disbursement transactions in BankLingo V2, including fund release, schedule activation, and fee handling.
Overviewβ
A Loan Disbursement Transaction releases approved loan funds to the borrower's account. This transaction activates the loan account and its repayment schedule.
Key Characteristics:
- Prerequisites: Loan must be APPROVED, schedules generated
- Fund Release: Transfer from loan disbursement account to customer account
- Schedule Activation: Marks loan schedules as ACTIVE
- Fee Deduction: Processing fees deducted at disbursement
- GL Integration: Multiple GL postings (loan asset, deposits, fees, settlement)
- Partial Disbursement: Support for tranched disbursements
Disbursement Methods:
- Direct to Account: Credit to customer's deposit account
- Cash Disbursement: Cash via teller till
- Third-Party Payment: Direct payment to vendor/supplier
- Tranche Disbursement: Multiple partial disbursements over time
Transaction Flowβ
Entities Impactedβ
Scenario 1: Full Disbursement to Customer Accountβ
Disburse NGN 1,000,000 loan with 2% processing fee
COMPLETED Phase:
{
transactionId: "DISB123456",
transactionState: "COMPLETED",
disbursementAmount: 1000000.00,
processingFee: 20000.00, // 2% of 1,000,000
netDisbursement: 980000.00,
impactedEntities: [
// Loan Account
{
entityType: "LoanAccount",
entityId: 100,
entityKey: "LOAN-001",
fieldName: "State",
oldValue: "APPROVED",
newValue: "ACTIVE",
deltaAmount: 0
},
{
entityType: "LoanAccount",
entityId: 100,
entityKey: "LOAN-001",
fieldName: "PrincipalBalance",
oldValue: 0.00,
newValue: 1000000.00,
deltaAmount: +1000000.00
},
{
entityType: "LoanAccount",
entityId: 100,
entityKey: "LOAN-001",
fieldName: "DisbursedAmount",
oldValue: 0.00,
newValue: 1000000.00,
deltaAmount: +1000000.00
},
{
entityType: "LoanAccount",
entityId: 100,
entityKey: "LOAN-001",
fieldName: "DisbursementDate",
oldValue: null,
newValue: "2025-12-28T10:00:00Z",
deltaAmount: 0
},
{
entityType: "LoanAccount",
entityId: 100,
entityKey: "LOAN-001",
fieldName: "FirstRepaymentDate",
oldValue: null,
newValue: "2026-01-28",
deltaAmount: 0
},
// Loan Schedules (all activated)
{
entityType: "LoanSchedule",
entityId: 201,
entityKey: "SCH-001-01",
fieldName: "State",
oldValue: "PENDING",
newValue: "ACTIVE",
deltaAmount: 0
},
{
entityType: "LoanSchedule",
entityId: 202,
entityKey: "SCH-001-02",
fieldName: "State",
oldValue: "PENDING",
newValue: "ACTIVE",
deltaAmount: 0
},
// ... (all 12 schedules activated)
// Customer Deposit Account (net amount after fees)
{
entityType: "DepositAccount",
entityId: 456,
entityKey: "ACC-CUST-001",
fieldName: "AvailableBalance",
oldValue: 50000.00,
newValue: 1030000.00, // 50000 + 980000
deltaAmount: +980000.00
},
{
entityType: "DepositAccount",
entityId: 456,
entityKey: "ACC-CUST-001",
fieldName: "BookBalance",
oldValue: 50000.00,
newValue: 1030000.00,
deltaAmount: +980000.00
},
// Loan Disbursement Account
{
entityType: "DepositAccount",
entityId: 999,
entityKey: "ACC-DISB-POOL",
fieldName: "AvailableBalance",
oldValue: 10000000.00,
newValue: 9000000.00,
deltaAmount: -1000000.00
},
{
entityType: "DepositAccount",
entityId: 999,
entityKey: "ACC-DISB-POOL",
fieldName: "BookBalance",
oldValue: 10000000.00,
newValue: 9000000.00,
deltaAmount: -1000000.00
},
// GL Accounts
{
entityType: "GLAccount",
entityKey: "3100-001", // Loans to Customers (Asset)
fieldName: "DebitAmount",
deltaAmount: +1000000.00
},
{
entityType: "GLAccount",
entityKey: "1050-001", // Loan Disbursement Account
fieldName: "CreditAmount",
deltaAmount: +1000000.00
},
{
entityType: "GLAccount",
entityKey: "1050-001", // Loan Disbursement Account
fieldName: "DebitAmount",
deltaAmount: +980000.00
},
{
entityType: "GLAccount",
entityKey: "2100-001", // Customer Deposits Liability
fieldName: "CreditAmount",
deltaAmount: +980000.00
},
{
entityType: "GLAccount",
entityKey: "4200-001", // Loan Processing Fee Income
fieldName: "CreditAmount",
deltaAmount: +20000.00
}
]
}
```text
### Scenario 2: Partial Disbursement (Tranche 1 of 2)
**Disburse NGN 500,000 (first tranche of NGN 1,000,000 loan)**
```typescript
{
transactionId: "DISB234567",
transactionState: "COMPLETED",
loanAmount: 1000000.00,
trancheNumber: 1,
trancheAmount: 500000.00,
processingFee: 10000.00, // 2% of tranche
netDisbursement: 490000.00,
impactedEntities: [
// Loan Account
{
entityType: "LoanAccount",
entityId: 100,
entityKey: "LOAN-001",
fieldName: "State",
oldValue: "APPROVED",
newValue: "ACTIVE_PARTIAL", // Partially disbursed
deltaAmount: 0
},
{
entityType: "LoanAccount",
entityId: 100,
entityKey: "LOAN-001",
fieldName: "PrincipalBalance",
oldValue: 0.00,
newValue: 500000.00,
deltaAmount: +500000.00
},
{
entityType: "LoanAccount",
entityId: 100,
entityKey: "LOAN-001",
fieldName: "DisbursedAmount",
oldValue: 0.00,
newValue: 500000.00,
deltaAmount: +500000.00
},
{
entityType: "LoanAccount",
entityId: 100,
entityKey: "LOAN-001",
fieldName: "UndisbursedAmount",
oldValue: 1000000.00,
newValue: 500000.00,
deltaAmount: -500000.00
},
// Loan Schedules (proportionally activated)
{
entityType: "LoanSchedule",
entityId: 201,
entityKey: "SCH-001-01",
fieldName: "State",
oldValue: "PENDING",
newValue: "ACTIVE",
deltaAmount: 0
},
{
entityType: "LoanSchedule",
entityId: 201,
entityKey: "SCH-001-01",
fieldName: "PrincipalDue",
oldValue: 83333.33, // Original for 1M
newValue: 41666.67, // Adjusted for 500K
deltaAmount: -41666.66
},
// Customer Deposit Account
{
entityType: "DepositAccount",
entityId: 456,
entityKey: "ACC-CUST-001",
fieldName: "AvailableBalance",
oldValue: 50000.00,
newValue: 540000.00,
deltaAmount: +490000.00
},
// GL Accounts
{
entityType: "GLAccount",
entityKey: "3100-001", // Loans to Customers
fieldName: "DebitAmount",
deltaAmount: +500000.00
},
{
entityType: "GLAccount",
entityKey: "4200-001", // Fee Income
fieldName: "CreditAmount",
deltaAmount: +10000.00
}
]
}
```text
### Scenario 3: Cash Disbursement via Teller
**Disburse NGN 200,000 loan as cash**
```typescript
{
transactionId: "DISB345678",
transactionState: "COMPLETED",
disbursementAmount: 200000.00,
processingFee: 4000.00,
netDisbursement: 196000.00,
disbursementMethod: "CASH",
impactedEntities: [
// Loan Account
{
entityType: "LoanAccount",
entityId: 100,
entityKey: "LOAN-001",
fieldName: "State",
oldValue: "APPROVED",
newValue: "ACTIVE",
deltaAmount: 0
},
{
entityType: "LoanAccount",
entityId: 100,
entityKey: "LOAN-001",
fieldName: "PrincipalBalance",
oldValue: 0.00,
newValue: 200000.00,
deltaAmount: +200000.00
},
// Teller Till (cash disbursed)
{
entityType: "TellerTill",
entityId: 789,
entityKey: "TILL-001",
fieldName: "CashBalance",
oldValue: 500000.00,
newValue: 304000.00, // 500000 - 196000
deltaAmount: -196000.00
},
{
entityType: "TellerTill",
entityId: 789,
entityKey: "TILL-001",
fieldName: "TransactionCount",
oldValue: 45,
newValue: 46,
deltaAmount: +1
},
// GL Accounts
{
entityType: "GLAccount",
entityKey: "3100-001", // Loans to Customers
fieldName: "DebitAmount",
deltaAmount: +200000.00
},
{
entityType: "GLAccount",
entityKey: "1010-001", // Cash in Till
fieldName: "CreditAmount",
deltaAmount: +196000.00
},
{
entityType: "GLAccount",
entityKey: "4200-001", // Fee Income
fieldName: "CreditAmount",
deltaAmount: +4000.00
}
]
}
```text
---
## Disbursement States
:::warning[Code Removed]
**Implementation details removed for security.**
Contact support for implementation guidance.
:::text
### State Transitions
```text
PENDING Γ’ββ¬Γ’ββ¬Γ’β¬Òββ¬Γ’ββ¬Γ’βΒΊ APPROVED Γ’ββ¬Γ’ββ¬Γ’βΒΊ COMPLETED Γ’ββ¬Γ’ββ¬Γ’βΒΊ ACTIVE
Γ’ββ Γ’ββ
Γ’ββΓ’ββ¬Γ’ββ¬Γ’βΒΊ REJECTED Γ’ββΓ’ββ¬Γ’ββ¬Γ’βΒΊ FAILED
ACTIVE Γ’ββ¬Γ’ββ¬Γ’βΒΊ REVERSED (special case for early reversal)
```text
---
## Fee Calculation
### Processing Fee
```yaml
processingFees:
- loanProductId: "PERSONAL_LOAN"
feeType: PERCENTAGE
percentage: 2.0
minAmount: 5000.00
maxAmount: 50000.00
deductionMethod: UPFRONT # Deducted at disbursement
- loanProductId: "SME_LOAN"
feeType: TIERED
tiers:
- minAmount: 0
maxAmount: 500000
fee: 10000.00
- minAmount: 500001
maxAmount: 2000000
fee: 25000.00
- minAmount: 2000001
maxAmount: null
fee: 50000.00
deductionMethod: UPFRONT
Insurance Premiumβ
insurancePremium:
- loanProductId: "PERSONAL_LOAN"
premiumType: PERCENTAGE
percentage: 1.5
deductionMethod: UPFRONT
insuranceProvider: "XYZ Insurance"
Fee Calculation Logicβ
Code Removed
Implementation details removed for security.
Contact support for implementation guidance.
Validation Rulesβ
| Rule | Check | Error Code | Message |
|---|---|---|---|
| Loan Approved | LoanAccount.State is APPROVED | 05 | Loan not approved |
| Schedules Generated | LoanSchedules.Count > 0 | 30 | Loan schedules not generated |
| Not Already Disbursed | LoanAccount.DisbursedAmount is 0 | 31 | Loan already disbursed |
| Valid Amount | DisbursementAmount not exceeds ApprovedAmount | 12 | Exceeds approved amount |
| Customer Account Active | DestAccount.State is ACTIVE | 14 | Customer account not active |
| Disbursement Account Balance | DisbAccount.Balance sufficient for DisbursementAmount | 51 | Insufficient funds in disbursement pool |
| Tranche Validation | If tranche: Amount not exceeds UndisbursedAmount | 32 | Exceeds undisbursed amount |
| Collateral Verified | If required: Collateral.Status is VERIFIED | 33 | Collateral not verified |
GL Postingβ
Journal Entriesβ
Example 1: Full Disbursement to Account
| Account | Description | Debit | Credit |
|---|---|---|---|
| 3100-001 | Loans to Customers (Asset) | 1,000,000.00 | - |
| 1050-001 | Loan Disbursement Account | - | 1,000,000.00 |
| 1050-001 | Loan Disbursement Account | 980,000.00 | - |
| 2100-001 | Customer Deposits | - | 980,000.00 |
| 4200-001 | Loan Processing Fee Income | - | 20,000.00 |
Example 2: Cash Disbursement
| Account | Description | Debit | Credit |
|---|---|---|---|
| 3100-001 | Loans to Customers | 200,000.00 | - |
| 1010-001 | Cash in Till | - | 196,000.00 |
| 4200-001 | Fee Income | - | 4,000.00 |
Example 3: Third-Party Payment (Vendor)
| Account | Description | Debit | Credit |
|---|---|---|---|
| 3100-001 | Loans to Customers | 500,000.00 | - |
| 2200-001 | Payable to Vendor | - | 490,000.00 |
| 4200-001 | Fee Income | - | 10,000.00 |
API Usageβ
Requestβ
POST /api/v2/transactions/loan/disburse
Content-Type: application/json
Authorization: Bearer {token}
{
"loanAccountEncodedKey": "LOAN-001",
"disbursementAmount": 1000000.00,
"disbursementMethod": "TO_ACCOUNT",
"destinationAccountEncodedKey": "ACC-CUST-001",
"disbursementDate": "2025-12-28",
"notes": "Full disbursement - personal loan",
"channelType": "BRANCH",
"tellerId": 123,
"isTranche": false
}
```text
### Response - Success (Auto-Approved)
```json
{
"success": true,
"transactionKey": "DISB123456",
"disbursementId": 789012,
"state": "COMPLETED",
"loanAccountNumber": "LN-0001",
"loanAccountName": "John Doe",
"disbursementAmount": 1000000.00,
"processingFee": 20000.00,
"insurancePremium": 15000.00,
"netDisbursement": 965000.00,
"destinationAccount": "0123456789",
"destinationAccountNewBalance": 1015000.00,
"loanState": "ACTIVE",
"principalBalance": 1000000.00,
"firstRepaymentDate": "2026-01-28",
"schedulesActivated": 12,
"disbursementDate": "2025-12-28T10:00:00Z",
"impactRecordId": 456,
"message": "Loan disbursed successfully"
}
```text
### Response - Pending Approval
```json
{
"success": true,
"transactionKey": "DISB123457",
"disbursementId": 789013,
"state": "PENDING",
"loanAccountNumber": "LN-0001",
"disbursementAmount": 5000000.00,
"approvalRequired": true,
"message": "Disbursement pending approval. Amount exceeds auto-approval limit."
}
```text
### Response - Error (Loan Not Approved)
```json
{
"success": false,
"errorCode": "05",
"errorMessage": "Loan not approved",
"loanAccountNumber": "LN-0001",
"currentState": "PENDING_APPROVAL",
"requiredState": "APPROVED"
}
```text
---
## Error Codes
| Code | Message | Cause | Resolution |
|------|---------|-------|------------|
| 00 | Success | Disbursement completed | None |
| 05 | Loan not approved | Loan state != APPROVED | Complete loan approval |
| 12 | Invalid amount | Amount is 0 or negative or exceeds approved | Correct amount |
| 14 | Invalid account | Destination account invalid | Verify account |
| 30 | Schedules not generated | No loan schedules exist | Generate schedules |
| 31 | Already disbursed | Loan already has disbursement | Check loan status |
| 32 | Exceeds undisbursed amount | Tranche > remaining | Reduce tranche amount |
| 33 | Collateral not verified | Required collateral missing | Complete collateral verification |
| 51 | Insufficient disbursement funds | Disbursement pool balance low | Fund disbursement account |
| 91 | System error | Database/network failure | Retry or contact support |
---
## Schedule Activation
### Full Disbursement
:::warning[Code Removed]
**Implementation details removed for security.**
Contact support for implementation guidance.
:::text
### Partial Disbursement (Tranche)
:::warning[Code Removed]
**Implementation details removed for security.**
Contact support for implementation guidance.
:::text
---
## Best Practices
### For Loan Officers
1. **Verify Approval**: Ensure loan is fully approved before disbursement
2. **Check Documents**: Verify all required documents are complete
3. **Confirm Account**: Verify destination account belongs to customer
4. **Review Fees**: Explain all fees to customer before disbursement
5. **Schedule Review**: Review repayment schedule with customer
6. **Disbursement Method**: Confirm preferred disbursement method
7. **Documentation**: Document disbursement in loan file
### For Developers
1. **Atomic Operation**: Wrap entire disbursement in database transaction
2. **Track All Impacts**: Record loan account, schedules, deposit account, GL
3. **Fee Calculation**: Apply all fees before crediting customer
4. **Schedule Activation**: Ensure all schedules activated atomically
5. **GL Consistency**: Verify debits equal credits
6. **Idempotency**: Prevent duplicate disbursements with unique keys
7. **Audit Trail**: Log all state changes and amounts
### For Operations
1. **Monitor Disbursement Pool**: Ensure sufficient balance
2. **Review Large Disbursements**: Flag disbursements > threshold
3. **Reconcile Daily**: Match disbursements to GL postings
4. **Track Failures**: Investigate failed disbursements immediately
5. **Verify Schedules**: Confirm schedules activated correctly
---
## Implementation Checklist
### Database Requirements
- [ ] Create `LoanDisbursement` table
- [ ] Add columns: State, DisbursementAmount, ProcessingFee, NetDisbursement, DisbursementMethod
- [ ] Add `DisbursedAmount` and `UndisbursedAmount` to LoanAccount
- [ ] Add `ActivationDate` to LoanSchedule
- [ ] Create `TransactionImpactRecord` and `ImpactedEntity` tables
- [ ] Add index on `LoanDisbursement(LoanAccountId, State)`
### Code Requirements
- [ ] Implement `ProcessLoanDisbursementAsync` with impact tracking
- [ ] Add fee calculation (processing fee, insurance)
- [ ] Implement schedule activation logic
- [ ] Add support for partial/tranche disbursements
- [ ] Implement GL posting for disbursements
- [ ] Add validation for loan state and schedules
- [ ] Create background job for failed disbursement retry
### Testing Requirements
- [ ] Unit test: Full disbursement with fee deduction
- [ ] Unit test: Partial disbursement (tranche)
- [ ] Unit test: Schedule activation
- [ ] Integration test: End-to-end disbursement to account
- [ ] Integration test: Cash disbursement via teller
- [ ] Integration test: Disbursement + reversal
- [ ] Performance test: 100 concurrent disbursements
### Documentation Requirements
- [ ] Update API documentation with disbursement endpoints
- [ ] Create loan officer guide on disbursement process
- [ ] Document fee structures by product
- [ ] Create runbook for failed disbursements
---
**Next**: [Loan Repayment Γ’β β](./repayment)
## Developer Resources
For API implementation details, see:
- [Loan Transactions API Reference](../../developer/)
- [Loan Transactions Developer Guide](../../developer/overview)
---