Loan Repayment via Teller
Customer repays loan installment via teller counter (Cash payment).
Overview
Loan repayment via teller allows customers to pay their loan obligations through cash presented at the teller counter. The transaction reduces the loan balances (Principal, Interest, Penalties, Fees) and increases the teller till balance.
Key Features:
- Cash payment through teller
- Payment allocation (Interest → Principal → Penalties → Fees)
- Loan schedule tracking and updates
- Till balance impact
- Multiple schedule support (for restructured loans)
- Approval workflow for early settlements
- Concurrent transaction safety with impact tracking
Transaction Flow
Entities Impacted
Standard Repayment Scenario
Command: LoanRepaymentWithTellerCommand (BPMCore)
Payment: ₦15,000 allocated as:
- Interest: ₦5,000
- Principal: ₦10,000
ImpactedEntities:
[
{
entityType: "LoanAccount",
entityId: 54321,
fieldName: "InterestBalance",
oldValue: 50000.00,
newValue: 45000.00,
deltaAmount: -5000.00
},
{
entityType: "LoanAccount",
entityId: 54321,
fieldName: "PrincipalBalance",
oldValue: 500000.00,
newValue: 490000.00,
deltaAmount: -10000.00
},
{
entityType: "LoanSchedule",
entityId: 1001,
fieldName: "InterestPaid",
oldValue: 0.00,
newValue: 5000.00,
deltaAmount: +5000.00
},
{
entityType: "LoanSchedule",
entityId: 1001,
fieldName: "PrincipalPaid",
oldValue: 0.00,
newValue: 10000.00,
deltaAmount: +10000.00
},
{
entityType: "LoanSchedule",
entityId: 1001,
fieldName: "State",
oldValue: "ACTIVE",
newValue: "PAID",
deltaAmount: 0
},
{
entityType: "TellerTill",
entityId: 789,
fieldName: "CashBalance",
oldValue: 50000.00,
newValue: 65000.00,
deltaAmount: +15000.00
},
{
entityType: "TellerTill",
entityId: 789,
fieldName: "TransactionCount",
oldValue: 42,
newValue: 43,
deltaAmount: +1
},
{
entityType: "GLAccount",
entityKey: "1050-CASH-IN-TILL",
fieldName: "DebitAmount",
deltaAmount: +15000.00
},
{
entityType: "GLAccount",
entityKey: "3001-LOANS-RECEIVABLE",
fieldName: "CreditAmount",
deltaAmount: +10000.00
},
{
entityType: "GLAccount",
entityKey: "4001-INTEREST-INCOME",
fieldName: "CreditAmount",
deltaAmount: +5000.00
}
]
```text
### Repayment with Penalties & Fees
**Payment**: ₦20,000 allocated as:
- Interest: ₦5,000
- Principal: ₦10,000
- Penalty: ₦3,000
- Fees: ₦2,000
```typescript
ImpactedEntities:
[
// LoanAccount balances...
{
entityType: "LoanAccount",
entityId: 54321,
fieldName: "PenaltyBalance",
oldValue: 5000.00,
newValue: 2000.00,
deltaAmount: -3000.00
},
{
entityType: "LoanAccount",
entityId: 54321,
fieldName: "FeeBalance",
oldValue: 10000.00,
newValue: 8000.00,
deltaAmount: -2000.00
},
// LoanSchedule updates...
{
entityType: "LoanSchedule",
entityId: 1001,
fieldName: "PenaltyBalance",
oldValue: 3000.00,
newValue: 0.00,
deltaAmount: -3000.00
},
{
entityType: "LoanSchedule",
entityId: 1001,
fieldName: "FeeBalance",
oldValue: 2000.00,
newValue: 0.00,
deltaAmount: -2000.00
},
// Additional GL entries...
{
entityType: "GLAccount",
entityKey: "4002-PENALTY-INCOME",
fieldName: "CreditAmount",
deltaAmount: +3000.00
},
{
entityType: "GLAccount",
entityKey: "4003-FEE-INCOME",
fieldName: "CreditAmount",
deltaAmount: +2000.00
}
]
```text
---
## Implementation
### Loan Repayment with Teller Implementation
**BPMCore Command**: `LoanRepaymentWithTellerCommand`
:::warning[Code Removed]
**Implementation details removed for security.**
Contact support for implementation guidance.
:::text
---
## Payment Allocation Rules
### Allocation Order
Payments are allocated in the following priority:
1. **Interest** (oldest schedule first)
2. **Principal** (oldest schedule first)
3. **Penalties** (account-level)
4. **Fees** (account-level)
### Example Allocation
**Loan State**:
- Schedule 1 (Due Jan 15): Interest ₦5,000, Principal ₦10,000
- Schedule 2 (Due Feb 15): Interest ₦5,000, Principal ₦10,000
- Penalty Balance: ₦3,000
- Fee Balance: ₦2,000
**Payment**: ₦18,000
**Allocation**:
```text
1. Interest (Schedule 1): ₦5,000 → Remaining: ₦13,000
2. Interest (Schedule 2): ₦5,000 → Remaining: ₦8,000
3. Principal (Schedule 1): ₦8,000 → Remaining: ₦0
Result:
- Schedule 1: Interest PAID (₦5,000), Principal PARTIAL (₦8,000/₦10,000)
- Schedule 2: Interest PAID (₦5,000), Principal NOT PAID
- Penalties: ₦3,000 (unpaid)
- Fees: ₦2,000 (unpaid)
```text
---
## Validation Rules
### Till Validation
| Rule | Check | Error Message |
|------|-------|---------------|
| **Till Exists** | Till found by `TillId` or `EncodedKey` | "Till not found" |
| **Till State** | `TillAccountState == OPENED` | "Till {TillId} is not opened" |
| **Till Type** | `TillType == TellerTill` | "Invalid till type" |
| **Currency Match** | Till currency == Loan currency | "Currency mismatch" |
| **Maximum Balance** | `Balance + Amount <= MaximumBalance` (if Hard constraint) | "Transaction will exceed till maximum balance by {excess}" |
### Loan Validation
| Rule | Check | Error Message |
|------|-------|---------------|
| **Loan Exists** | Loan found by `AccountNumber` and `ClientEncodedKey` | "Loan account not found" |
| **Loan Active** | `LoanState == ACTIVE` | "Loan account is not active" |
| **Not Closed** | `LoanState != CLOSED` | "Loan account is closed" |
| **Not Written Off** | `LoanState != WRITTEN_OFF` | "Loan account has been written off" |
| **Active Schedules** | At least one active schedule exists | "No active loan schedules found" |
| **Amount Valid** | `Amount > 0` | "Payment amount must be greater than zero" |
---
## GL Account Postings
### Standard Repayment
| Account | Debit (Dr) | Credit (Cr) | Description |
|---------|------------|-------------|-------------|
| **Cash-in-Till Asset** | Amount | - | Increase till cash |
| **Loans Receivable Asset** | - | Principal | Reduce loan asset |
| **Interest Income** | - | Interest | Recognize interest revenue |
| **Penalty Income** | - | Penalty | Recognize penalty revenue |
| **Fee Income** | - | Fees | Recognize fee revenue |
**Example** (₦20,000 payment: ₦5K interest, ₦10K principal, ₦3K penalty, ₦2K fees):
```text
DR: 1050-Cash-in-Till ₦20,000
CR: 3001-Loans-Receivable ₦10,000
CR: 4001-Interest-Income ₦5,000
CR: 4002-Penalty-Income ₦3,000
CR: 4003-Fee-Income ₦2,000
```text
---
## Testing
### Test Scenario 1: Standard Installment Payment
**Setup**:
- Loan: ₦500,000 principal, ₦50,000 interest balance
- Schedule Due: Interest ₦5,000, Principal ₦10,000
- Payment: ₦15,000 (exact installment)
**Expected Results**:
```typescript
LoanAccount:
InterestBalance: 50000 → 45000 ✓
PrincipalBalance: 500000 → 490000 ✓
LoanSchedule:
InterestPaid: 0 → 5000 ✓
PrincipalPaid: 0 → 10000 ✓
State: ACTIVE → PAID ✓
TellerTill:
Balance: +15000 ✓
TransactionCount: +1 ✓
GLEntries:
DR: Cash-in-Till: ₦15,000 ✓
CR: Loans-Receivable: ₦10,000 ✓
CR: Interest-Income: ₦5,000 ✓
```text
### Test Scenario 2: Partial Payment
**Setup**:
- Schedule Due: Interest ₦5,000, Principal ₦10,000
- Payment: ₦8,000 (partial)
**Expected Results**:
```typescript
Allocation:
Interest: ₦5,000 (full) ✓
Principal: ₦3,000 (partial) ✓
LoanSchedule:
InterestPaid: 0 → 5000 ✓
PrincipalPaid: 0 → 3000 ✓
State: ACTIVE (not fully paid) ✓
```text
### Test Scenario 3: Multiple Schedules
**Setup**:
- Schedule 1: Interest ₦5K, Principal ₦10K
- Schedule 2: Interest ₦5K, Principal ₦10K
- Payment: ₦25,000
**Expected Results**:
```typescript
Allocation:
Schedule 1 Interest: ₦5,000 ✓
Schedule 2 Interest: ₦5,000 ✓
Schedule 1 Principal: ₦10,000 ✓
Schedule 2 Principal: ₦5,000 (partial) ✓
Schedule 1: PAID ✓
Schedule 2: ACTIVE (partial payment) ✓
```text
### Test Scenario 4: Full Settlement with Penalties
**Setup**:
- Remaining Principal: ₦50,000
- Remaining Interest: ₦5,000
- Penalty Balance: ₦3,000
- Payment: ₦58,000 (full settlement)
**Expected Results**:
```typescript
LoanAccount:
PrincipalBalance: 50000 → 0 ✓
InterestBalance: 5000 → 0 ✓
PenaltyBalance: 3000 → 0 ✓
LoanState: ACTIVE → CLOSED ✓
ClosedDate: Set ✓
GLEntries:
DR: Cash-in-Till: ₦58,000 ✓
CR: Loans-Receivable: ₦50,000 ✓
CR: Interest-Income: ₦5,000 ✓
CR: Penalty-Income: ₦3,000 ✓
V2 API Commands
Architecture Overview
The V2 loan repayment with deposit command follows the Delegation Pattern:
- V2 Facade:
InitiateLoanRepaymentWithDepositCommand(BPMCore compatible) - V1 Implementation: Delegates to existing V1
LoanRepaymentWithDepositCommandwith full business logic - BPM Integration: Accepts parameters via
BpmUtil.GetPropertyValue()
Implementation: CB.Administration.Api/Commands/BPMCore/Loans/AdministrationCoreLoanCommandHandlers.Transactions.cs
InitiateLoanRepaymentWithDepositCommand
Purpose: Process loan repayment via cash deposit to teller till (no deposit account needed)
Command: InitiateLoanRepaymentWithDepositCommand
Delegation: → LoanRepaymentWithDepositCommand (V1 implementation)
BPM Parameters
{
"commandName": "InitiateLoanRepaymentWithDepositCommand",
"data": {
"accountEncodedKey": "string (mandatory)",
"clientEncodedKey": "string (mandatory)",
"paymentAmount": "decimal (mandatory)",
"tillId": "string (mandatory)",
"transactionDate": "DateTime (optional)",
"notes": "string (optional)"
}
}
Parameter Details
| Parameter | Type | Required | Description |
|---|---|---|---|
accountEncodedKey | string | ✅ Yes | Loan account for repayment |
clientEncodedKey | string | ✅ Yes | Client/borrower encoded key |
paymentAmount | decimal | ✅ Yes | Cash payment amount (must be > 0) |
tillId | string | ✅ Yes | Teller till ID receiving cash |
transactionDate | DateTime | ⌠No | Payment date (defaults to today) |
notes | string | ⌠No | Repayment notes/remarks |
Balance Impact
Loan Account: (same as regular repayment)
- ✅ PrincipalBalance, InterestBalance, PenaltyBalance, FeesBalance reduced
- ✅ Payment allocated across schedules (Penalty → Interest → Fees → Principal)
Teller Till:
| Balance Field | Change | Reason |
|---|---|---|
TillBalance | +paymentAmount | Cash received |
TotalCashIn | +paymentAmount | Track cash inflow |
No Deposit Account Impact: Customer pays cash directly (no deposit account debit)
Example Response
{
"isSuccessful": true,
"transactionId": "TXN-LOAN-RPMT-TELLER-20251229-0001",
"transactionState": "SETTLED",
"message": "Loan repayment with cash deposit processed successfully",
"data": {
"loanAccountKey": "8a8080827f23loan017f23def456",
"paymentAmount": 50000.00,
"tillId": "TILL-001",
"allocation": {
"penaltyPaid": 2000.00,
"interestPaid": 15000.00,
"feesPaid": 1000.00,
"principalPaid": 32000.00
},
"tillBalance": {
"previousBalance": 500000.00,
"newBalance": 550000.00
},
"schedulesAffected": 2
}
}
Related Documentation
- Loan Repayment - General loan repayment processing
- Loan Disbursement - Loan disbursement process
- Teller Deposit - Teller deposit transactions
- Transaction Impact Tracking - Delta-based tracking system
Developer Resources
For API implementation details, see: