Skip to content

Commit

Permalink
FINERACT-1981: Enhance EMI Adjustment
Browse files Browse the repository at this point in the history
  • Loading branch information
janez89 committed Jan 14, 2025
1 parent 8663c05 commit 3bc4490
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4115,10 +4115,10 @@ Feature: EMI calculation and repayment schedule checks for interest bearing loan
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| | | 01 January 2024 | | 250.0 | | | 0.0 | | 0.0 | 0.0 | | | |
| | | 04 January 2024 | | 750.0 | | | 0.0 | | 0.0 | 0.0 | | | |
| 1 | 31 | 01 February 2024 | 22 January 2024 | 750.09 | 249.91 | 5.07 | 0.0 | 0.0 | 254.98 | 254.98 | 254.98 | 0.0 | 0.0 |
| 2 | 29 | 01 March 2024 | 22 January 2024 | 495.11 | 254.98 | 0.0 | 0.0 | 0.0 | 254.98 | 254.98 | 254.98 | 0.0 | 0.0 |
| 3 | 31 | 01 April 2024 | 22 January 2024 | 240.13 | 254.98 | 0.0 | 0.0 | 0.0 | 254.98 | 254.98 | 254.98 | 0.0 | 0.0 |
| 4 | 30 | 01 May 2024 | 22 January 2024 | 0.0 | 240.13 | 0.0 | 0.0 | 0.0 | 240.13 | 240.13 | 240.13 | 0.0 | 0.0 |
| 1 | 31 | 01 February 2024 | 22 January 2024 | 750.08 | 249.92 | 5.07 | 0.0 | 0.0 | 254.99 | 254.99 | 254.99 | 0.0 | 0.0 |
| 2 | 29 | 01 March 2024 | 22 January 2024 | 495.09 | 254.99 | 0.0 | 0.0 | 0.0 | 254.99 | 254.99 | 254.99 | 0.0 | 0.0 |
| 3 | 31 | 01 April 2024 | 22 January 2024 | 240.1 | 254.99 | 0.0 | 0.0 | 0.0 | 254.99 | 254.99 | 254.99 | 0.0 | 0.0 |
| 4 | 30 | 01 May 2024 | 22 January 2024 | 0.0 | 240.1 | 0.0 | 0.0 | 0.0 | 240.1 | 240.1 | 240.1 | 0.0 | 0.0 |
Then Loan Repayment schedule has the following data in Total row:
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| 1000.0 | 5.07 | 0.0 | 0.0 | 1005.07 | 1005.07 | 1005.07 | 0.0 | 0.0 |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ private void checkAndAdjustEmiIfNeededOnRelatedRepaymentPeriods(final Progressiv
final List<RepaymentPeriod> relatedRepaymentPeriods) {
MathContext mc = scheduleModel.mc();
ProgressiveLoanInterestScheduleModel newScheduleModel = null;
int adjustCounter = 0;
int adjustCounter = 1;
EmiAdjustment emiAdjustment;

do {
Expand Down Expand Up @@ -361,7 +361,7 @@ private void checkAndAdjustEmiIfNeededOnRelatedRepaymentPeriods(final Progressiv
});
calculateOutstandingBalance(scheduleModel);
adjustCounter++;
} while (emiAdjustment.hasUncountablePeriods() && adjustCounter < 3);
} while (adjustCounter <= 3);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -999,6 +999,50 @@ public void test_disbursedAmt100_dayInYearsActual_daysInMonthActual_repayEvery1M
checkPeriod(interestSchedule, 5, 0, 17.13, 0.008031371585, 0.14, 16.99, 0.0);
}

@Test
public void test_multidisbursement_total_repay1st_dayInYears360_daysInMonth30_repayEvery1Month() {

final List<LoanScheduleModelRepaymentPeriod> expectedRepaymentPeriods = List.of(
repayment(1, LocalDate.of(2024, 1, 1), LocalDate.of(2024, 2, 1)),
repayment(2, LocalDate.of(2024, 2, 1), LocalDate.of(2024, 3, 1)),
repayment(3, LocalDate.of(2024, 3, 1), LocalDate.of(2024, 4, 1)),
repayment(4, LocalDate.of(2024, 4, 1), LocalDate.of(2024, 5, 1)),
repayment(5, LocalDate.of(2024, 5, 1), LocalDate.of(2024, 6, 1)),
repayment(6, LocalDate.of(2024, 6, 1), LocalDate.of(2024, 7, 1)));

final BigDecimal interestRate = BigDecimal.valueOf(7.0);
final Integer installmentAmountInMultiplesOf = null;

Mockito.when(loanProductRelatedDetail.getAnnualNominalInterestRate()).thenReturn(interestRate);
Mockito.when(loanProductRelatedDetail.getDaysInYearType()).thenReturn(DaysInYearType.DAYS_360.getValue());
Mockito.when(loanProductRelatedDetail.getDaysInMonthType()).thenReturn(DaysInMonthType.DAYS_30.getValue());
Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS);
Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1);
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);

final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);

emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), toMoney(300.0));
Assertions.assertEquals(6.15, toDouble(interestSchedule.getTotalDueInterest()));

// pay back the whole loan on first day
emiCalculator.payPrincipal(interestSchedule, LocalDate.of(2024, 2, 1), LocalDate.of(2024, 1, 1), toMoney(51.03));
emiCalculator.payPrincipal(interestSchedule, LocalDate.of(2024, 3, 1), LocalDate.of(2024, 1, 1), toMoney(51.03));
emiCalculator.payPrincipal(interestSchedule, LocalDate.of(2024, 4, 1), LocalDate.of(2024, 1, 1), toMoney(51.03));
emiCalculator.payPrincipal(interestSchedule, LocalDate.of(2024, 5, 1), LocalDate.of(2024, 1, 1), toMoney(51.03));
emiCalculator.payPrincipal(interestSchedule, LocalDate.of(2024, 6, 1), LocalDate.of(2024, 1, 1), toMoney(51.03));
emiCalculator.payPrincipal(interestSchedule, LocalDate.of(2024, 7, 1), LocalDate.of(2024, 1, 1), toMoney(44.85));

Assertions.assertEquals(0.0, toDouble(interestSchedule.getTotalDueInterest()));

emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), toMoney(200.0));
Assertions.assertEquals(4.20, toDouble(interestSchedule.getTotalDueInterest()));

checkEmi(interestSchedule, 4, 84.03);
checkEmi(interestSchedule, 5, 84.05);
}

@Test
public void test_disbursedAmt1000_NoInterest_repayEvery1Month() {

Expand Down Expand Up @@ -1291,6 +1335,11 @@ private static void checkDailyInterest(final ProgressiveLoanInterestScheduleMode
Assertions.assertEquals(interest, toDouble(currentInterest));
}

private static void checkEmi(final ProgressiveLoanInterestScheduleModel interestScheduleModel, final int repaymentIdx,
final double emiValue) {
Assertions.assertEquals(emiValue, toDouble(interestScheduleModel.repaymentPeriods().get(repaymentIdx).getEmi()));
}

private static void checkPeriod(final ProgressiveLoanInterestScheduleModel interestScheduleModel, final int repaymentIdx,
final int interestIdx, final double emiValue, final double rateFactor, final double interestDue, final double principalDue,
final double remaingBalance) {
Expand Down

0 comments on commit 3bc4490

Please sign in to comment.