Skip to main content

Loan Reschedule Transaction

Overview

A Loan Reschedule (also called Loan Restructuring or Loan Modification) is a transaction where the terms of an existing loan are modified to help a borrower who is experiencing financial difficulty. This typically involves extending the loan term, reducing the interest rate, or changing the repayment schedule.

Key Characteristics

  • Purpose: Modify loan terms to avoid default and support borrower recovery
  • Transaction Type: RSCH (Reschedule)
  • Complexity: Very High - Creates new schedule while preserving old schedule history
  • Multi-Entity Impact: LoanAccount, old LoanSchedules (SUPERSEDED), new LoanSchedules (ACTIVE)
  • Critical Requirement: Old schedule supersession with full audit trail, new schedule creation

Reschedule vs Other Loan Transactions

AspectRescheduleRefinanceWrite-Off
Loan AccountSame loan modifiedNew loan createdLoan removed from books
Outstanding BalancePreservedTransferred to new loanWritten off
ScheduleOld SUPERSEDED, new ACTIVEOld closed, new createdAll WRITTEN_OFF
PurposeHelp struggling borrowerBetter terms/consolidationRecognize bad debt
Payment HistoryPreservedStarts freshEnded

Transaction Flow

Entities Impacted

Scenario 1: Term Extension with Rate Reduction

Context:

  • Loan: NGN 1,000,000 principal, 22% annual interest, 36 months
  • Current Status: 18 months paid, NGN 500,000 principal remaining
  • Financial Hardship: Borrower income reduced by 40%
  • Current Monthly Payment: NGN 55,000
  • Restructure Request: Extend to 48 months total (30 remaining), reduce rate to 18%

Old Schedule:

  • 18 schedules paid (1-18): NGN 55,000/month
  • 18 schedules outstanding (19-36): ACTIVE, NGN 55,000/month each

New Schedule Calculation:

Outstanding Balance = 500,000 (principal) + 90,000 (accrued interest) = 590,000
New Interest Rate = 18% (reduced from 22%)
New Term = 30 months (extended from 18 remaining)
New Monthly Payment = 590,000 / 30 + (590,000 × 0.18 / 12) = 19,667 + 8,850 = 28,517

Restructuring Fee = 1% of outstanding = 5,900
```text
**Entities Impacted** (32 ImpactedEntity records):

```typescript
{
transactionId: "RSCH-001",
transactionType: "Loan Reschedule",
rescheduleDate: "2025-12-28",
rescheduleReason: "Borrower income reduced 40%, requesting payment relief",
impactedEntities: [

// 1-18: Old Schedule Supersession (18 outstanding schedules)
// Schedule 19 (example)
{
entityType: "LoanSchedule",
entityId: 219,
entityKey: "SCH-219",
fieldName: "State",
oldValue: "ACTIVE",
newValue: "SUPERSEDED",
deltaAmount: 0
},
{
entityType: "LoanSchedule",
entityId: 219,
fieldName: "SupersededDate",
oldValue: null,
newValue: "2025-12-28",
deltaAmount: 0
},
{
entityType: "LoanSchedule",
entityId: 219,
fieldName: "SupersededByTransactionId",
oldValue: null,
newValue: "RSCH-001",
deltaAmount: 0
},
// ... (17 more old schedules, each with 3 field changes = 51 records)

// 19-48: New Schedule Creation (30 new schedules)
// New Schedule 1 (example)
{
entityType: "LoanSchedule",
entityId: 501, // New ID
entityKey: "SCH-501",
fieldName: "ScheduleNumber",
oldValue: null,
newValue: "19", // Continues from old schedule numbering
deltaAmount: 0
},
{
entityType: "LoanSchedule",
entityId: 501,
fieldName: "DueDate",
oldValue: null,
newValue: "2026-01-28",
deltaAmount: 0
},
{
entityType: "LoanSchedule",
entityId: 501,
fieldName: "PrincipalDue",
oldValue: null,
newValue: 19667.00,
deltaAmount: +19667.00
},
{
entityType: "LoanSchedule",
entityId: 501,
fieldName: "InterestDue",
oldValue: null,
newValue: 8850.00,
deltaAmount: +8850.00
},
{
entityType: "LoanSchedule",
entityId: 501,
fieldName: "State",
oldValue: null,
newValue: "ACTIVE",
deltaAmount: 0
},
{
entityType: "LoanSchedule",
entityId: 501,
fieldName: "CreatedByTransactionId",
oldValue: null,
newValue: "RSCH-001",
deltaAmount: 0
},
// ... (29 more new schedules, each with 6 field changes = 174 records)

// 49-55: LoanAccount impacts
{
entityType: "LoanAccount",
entityId: 101,
entityKey: "LOAN-101",
fieldName: "InterestRate",
oldValue: 22.00,
newValue: 18.00,
deltaAmount: -4.00
},
{
entityType: "LoanAccount",
entityId: 101,
fieldName: "TermMonths",
oldValue: 36,
newValue: 48,
deltaAmount: +12
},
{
entityType: "LoanAccount",
entityId: 101,
fieldName: "MaturityDate",
oldValue: "2026-12-15",
newValue: "2028-12-28",
deltaAmount: 0
},
{
entityType: "LoanAccount",
entityId: 101,
fieldName: "RescheduleCount",
oldValue: 0,
newValue: 1,
deltaAmount: +1
},
{
entityType: "LoanAccount",
entityId: 101,
fieldName: "LastRescheduleDate",
oldValue: null,
newValue: "2025-12-28",
deltaAmount: 0
},
{
entityType: "LoanAccount",
entityId: 101,
fieldName: "MonthlyInstallment",
oldValue: 55000.00,
newValue: 28517.00,
deltaAmount: -26483.00
},
{
entityType: "LoanAccount",
entityId: 101,
fieldName: "ScheduleCount",
oldValue: 36,
newValue: 48, // 18 paid + 30 new
deltaAmount: +12
},

// 56-57: GL Account impacts (restructuring fee)
{
entityType: "GLAccount",
entityKey: "4106-LOAN-RESTRUCTURING-INCOME",
fieldName: "CreditAmount",
deltaAmount: +5900.00
},
{
entityType: "GLAccount",
entityKey: "2101-CUSTOMER-DEPOSITS",
fieldName: "DebitAmount",
deltaAmount: +5900.00 // Deducted from customer account
}
]
}
```text
**Key Point**: Old schedule 19-36 marked SUPERSEDED (not deleted), new schedule 19-48 created as ACTIVE. Payment history on schedules 1-18 preserved.

---

## Reschedule Calculation Algorithm

:::warning[Code Removed]
**Implementation details removed for security.**

Contact support for implementation guidance.
:::text
---

## Reschedule Execution

:::warning[Code Removed]
**Implementation details removed for security.**

Contact support for implementation guidance.
:::text
---

## Best Practices

### For Product Managers

1. **Reschedule Policy**:
- Define clear eligibility criteria (financial hardship documentation)
- Limit reschedules per loan (e.g., maximum 2 reschedules)
- Set restructuring fees (typically 1-2% of outstanding balance)

2. **Risk Management**:
- Track reschedule count per borrower (indicator of credit risk)
- Monitor NPL rates for rescheduled loans
- Provisioning requirements may increase for rescheduled loans

3. **Customer Support**:
- Offer payment relief without harming credit history
- Balance bank profitability with customer retention
- Communicate new terms clearly

### For Developers

1. **Schedule Supersession**:
- NEVER delete old schedules (audit trail required)
- Mark old schedules as SUPERSEDED with link to reschedule transaction
- Preserve all payment history on paid schedules

2. **Impact Tracking**:
- Track EVERY old schedule supersession
- Track EVERY new schedule creation
- Link old and new schedules via transaction ID

3. **Concurrent Safety**:
- Lock loan account during reschedule
- Verify no payments pending on old schedules
- Use database transactions

### For Bank Operations

1. **Approval Process**:
- Credit committee review required
- Verify financial hardship documentation
- Assess borrower's ability to service new terms

2. **Documentation**:
- Signed reschedule agreement from borrower
- Updated loan contract with new terms
- Notification of new payment schedule

3. **Monitoring**:
- Track performance of rescheduled loans
- Early warning if second reschedule needed
- Provisioning requirements

---

## V2 API Commands

### Architecture Overview

The V2 loan reschedule command follows the **Delegation Pattern**:

- **V2 Facade**: `InitiateLoanRescheduleCommand` (BPMCore compatible)
- **V1 Implementation**: Delegates to existing V1 `LoanRescheduleCommand` with full business logic
- **BPM Integration**: Accepts parameters via `BpmUtil.GetPropertyValue()`

**Implementation**: `CB.Administration.Api/Commands/BPMCore/Loans/AdministrationCoreLoanCommandHandlers.Transactions.cs`

---

### InitiateLoanRescheduleCommand

**Purpose**: Reschedule loan payment terms (modify schedule, extend term, adjust amount)

**Command**: `InitiateLoanRescheduleCommand`

**Delegation**: → `LoanRescheduleCommand` (V1 implementation)

#### BPM Parameters

```json
{
"commandName": "InitiateLoanRescheduleCommand",
"data": {
"accountEncodedKey": "string (mandatory)",
"clientEncodedKey": "string (mandatory)",
"newTermMonths": "int (optional)",
"newInstallmentAmount": "decimal (optional)",
"rescheduleReason": "string (optional)",
"transactionDate": "DateTime (optional)",
"notes": "string (optional)"
}
}

Parameter Details

ParameterTypeRequiredDescription
accountEncodedKeystring✅ YesLoan account to reschedule
clientEncodedKeystring✅ YesClient/borrower encoded key
newTermMonthsint❌ NoNew loan term in months
newInstallmentAmountdecimal❌ NoNew installment amount
rescheduleReasonstring❌ NoReason code (e.g., "FINANCIAL_DIFFICULTY")
transactionDateDateTime❌ NoReschedule date (defaults to today)
notesstring❌ NoReschedule notes/remarks

Impact

Loan Account:

  • ✅ Old schedules closed/modified
  • ✅ New schedules generated with revised terms
  • ✅ Loan term extended (if applicable)
  • ✅ Installment amount reduced (if applicable)
  • ✅ Reschedule history tracked

Example Response

{
"isSuccessful": true,
"transactionId": "TXN-LOAN-RSCH-20251229-0001",
"transactionState": "SETTLED",
"message": "Loan rescheduled successfully",
"data": {
"loanAccountKey": "8a8080827f23loan017f23def456",
"oldTermMonths": 36,
"newTermMonths": 48,
"oldInstallmentAmount": 50000.00,
"newInstallmentAmount": 37500.00,
"schedulesModified": 24,
"schedulesCreated": 12
}
}

Implementation Checklist

Phase 1: Calculation

  • Implement CalculateRescheduleTermsAsync
  • Add schedule generation for new terms
  • Calculate restructuring fees
  • Unit tests (5+ scenarios)

Phase 2: Execution

  • Implement ProcessLoanRescheduleAsync
  • Add old schedule supersession logic
  • Add new schedule creation
  • Integration tests

Phase 3: API

  • Create reschedule calculation endpoint
  • Create reschedule execution endpoint
  • Add validation rules
  • API tests

Phase 4: Testing

  • End-to-end tests (3+ scenarios)
  • Audit trail verification
  • Production deployment

Developer Resources

For API implementation details, see:


Document Version: 1.0
Last Updated: December 28, 2025
Related Documents: