FINERACT-2114: Align recalculated EMI after Interest Rate change
This commit is contained in:
committed by
Adam Saghy
parent
75ad6082d0
commit
17a4392c26
+26
-12
@@ -286,27 +286,40 @@ public final class ProgressiveEMICalculator implements EMICalculator {
|
|||||||
private void checkAndAdjustEmiIfNeededOnRelatedRepaymentPeriods(final ProgressiveLoanInterestScheduleModel scheduleModel,
|
private void checkAndAdjustEmiIfNeededOnRelatedRepaymentPeriods(final ProgressiveLoanInterestScheduleModel scheduleModel,
|
||||||
final List<RepaymentPeriod> relatedRepaymentPeriods) {
|
final List<RepaymentPeriod> relatedRepaymentPeriods) {
|
||||||
MathContext mc = scheduleModel.mc();
|
MathContext mc = scheduleModel.mc();
|
||||||
final Money emiDifference = getDifferenceBetweenLastTwoPeriod(relatedRepaymentPeriods, scheduleModel);
|
ProgressiveLoanInterestScheduleModel newScheduleModel = null;
|
||||||
|
|
||||||
final int numberOfRelatedPeriods = relatedRepaymentPeriods.size();
|
final int numberOfRelatedPeriods = relatedRepaymentPeriods.size();
|
||||||
double lowerHalfOfRelatedPeriods = Math.floor(numberOfRelatedPeriods / 2.0);
|
double lowerHalfOfRelatedPeriods = Math.floor(numberOfRelatedPeriods / 2.0);
|
||||||
if (emiDifference.isZero(mc) || lowerHalfOfRelatedPeriods == 0.0) {
|
if (lowerHalfOfRelatedPeriods == 0.0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final Money originalEmi = relatedRepaymentPeriods.get(numberOfRelatedPeriods - 2).getEmi();
|
|
||||||
boolean shouldBeAdjusted = emiDifference.abs(mc).multipliedBy(100, mc)
|
|
||||||
.isGreaterThan(Money.of(originalEmi.getCurrency(), BigDecimal.valueOf(lowerHalfOfRelatedPeriods), mc));
|
|
||||||
|
|
||||||
if (shouldBeAdjusted) {
|
long uncountablePeriods;
|
||||||
long uncountablePeriods = relatedRepaymentPeriods.stream().filter(rp -> originalEmi.isLessThan(rp.getTotalPaidAmount()))
|
int adjustCounter = 0;
|
||||||
.count();
|
|
||||||
|
do {
|
||||||
|
final Money emiDifference = getDifferenceBetweenLastTwoPeriod(relatedRepaymentPeriods, scheduleModel);
|
||||||
|
if (emiDifference.isZero(mc)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
final Money originalEmi = relatedRepaymentPeriods.get(numberOfRelatedPeriods - 2).getEmi();
|
||||||
|
boolean shouldBeAdjusted = emiDifference.abs(mc).multipliedBy(100, mc)
|
||||||
|
.isGreaterThan(Money.of(originalEmi.getCurrency(), BigDecimal.valueOf(lowerHalfOfRelatedPeriods), mc));
|
||||||
|
if (!shouldBeAdjusted) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
uncountablePeriods = relatedRepaymentPeriods.stream().filter(rp -> originalEmi.isLessThan(rp.getTotalPaidAmount())).count();
|
||||||
Money adjustment = emiDifference.dividedBy(Math.max(1, numberOfRelatedPeriods - uncountablePeriods), mc);
|
Money adjustment = emiDifference.dividedBy(Math.max(1, numberOfRelatedPeriods - uncountablePeriods), mc);
|
||||||
Money adjustedEqualMonthlyInstallmentValue = applyInstallmentAmountInMultiplesOf(scheduleModel,
|
Money adjustedEqualMonthlyInstallmentValue = applyInstallmentAmountInMultiplesOf(scheduleModel,
|
||||||
originalEmi.plus(adjustment, mc));
|
originalEmi.plus(adjustment, mc));
|
||||||
if (adjustedEqualMonthlyInstallmentValue.isEqualTo(originalEmi)) {
|
if (adjustedEqualMonthlyInstallmentValue.isEqualTo(originalEmi)) {
|
||||||
return;
|
break;
|
||||||
|
}
|
||||||
|
if (newScheduleModel == null) {
|
||||||
|
newScheduleModel = scheduleModel.deepCopy(mc);
|
||||||
}
|
}
|
||||||
final LocalDate relatedPeriodsFirstDueDate = relatedRepaymentPeriods.get(0).getDueDate();
|
final LocalDate relatedPeriodsFirstDueDate = relatedRepaymentPeriods.get(0).getDueDate();
|
||||||
final ProgressiveLoanInterestScheduleModel newScheduleModel = scheduleModel.deepCopy(mc);
|
|
||||||
newScheduleModel.repaymentPeriods().forEach(period -> {
|
newScheduleModel.repaymentPeriods().forEach(period -> {
|
||||||
if (!period.getDueDate().isBefore(relatedPeriodsFirstDueDate)
|
if (!period.getDueDate().isBefore(relatedPeriodsFirstDueDate)
|
||||||
&& !adjustedEqualMonthlyInstallmentValue.isLessThan(period.getTotalPaidAmount())) {
|
&& !adjustedEqualMonthlyInstallmentValue.isLessThan(period.getTotalPaidAmount())) {
|
||||||
@@ -319,7 +332,7 @@ public final class ProgressiveEMICalculator implements EMICalculator {
|
|||||||
final Money newEmiDifference = getDifferenceBetweenLastTwoPeriod(newScheduleModel.repaymentPeriods(), scheduleModel);
|
final Money newEmiDifference = getDifferenceBetweenLastTwoPeriod(newScheduleModel.repaymentPeriods(), scheduleModel);
|
||||||
final boolean newEmiHasLessDifference = newEmiDifference.abs(mc).isLessThan(emiDifference.abs(mc));
|
final boolean newEmiHasLessDifference = newEmiDifference.abs(mc).isLessThan(emiDifference.abs(mc));
|
||||||
if (!newEmiHasLessDifference) {
|
if (!newEmiHasLessDifference) {
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Iterator<RepaymentPeriod> relatedPeriodFromNewModelIterator = newScheduleModel.repaymentPeriods().stream()//
|
final Iterator<RepaymentPeriod> relatedPeriodFromNewModelIterator = newScheduleModel.repaymentPeriods().stream()//
|
||||||
@@ -335,7 +348,8 @@ public final class ProgressiveEMICalculator implements EMICalculator {
|
|||||||
relatedRepaymentPeriod.setOriginalEmi(newRepaymentPeriod.getEmi());
|
relatedRepaymentPeriod.setOriginalEmi(newRepaymentPeriod.getEmi());
|
||||||
});
|
});
|
||||||
calculateOutstandingBalance(scheduleModel);
|
calculateOutstandingBalance(scheduleModel);
|
||||||
}
|
adjustCounter++;
|
||||||
|
} while (uncountablePeriods > 0 && adjustCounter < 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+4
-4
@@ -474,10 +474,10 @@ class ProgressiveEMICalculatorTest {
|
|||||||
checkPeriod(interestModel, 0, 0, 17.01, 0.0, 0.0, 0.58, 16.43, 66.67);
|
checkPeriod(interestModel, 0, 0, 17.01, 0.0, 0.0, 0.58, 16.43, 66.67);
|
||||||
checkPeriod(interestModel, 0, 1, 17.01, 0.005833333333, 0.58, 16.43, 66.67);
|
checkPeriod(interestModel, 0, 1, 17.01, 0.005833333333, 0.58, 16.43, 66.67);
|
||||||
checkPeriod(interestModel, 1, 0, 17.01, 0.003333333333, 0.22, 0.0, 17.01, 66.56);
|
checkPeriod(interestModel, 1, 0, 17.01, 0.003333333333, 0.22, 0.0, 17.01, 66.56);
|
||||||
checkPeriod(interestModel, 2, 0, 16.85, 0.003333333333, 0.22, 0.44, 16.41, 50.15);
|
checkPeriod(interestModel, 2, 0, 16.83, 0.003333333333, 0.22, 0.44, 16.39, 50.17);
|
||||||
checkPeriod(interestModel, 3, 0, 16.85, 0.003333333333, 0.17, 16.68, 33.47);
|
checkPeriod(interestModel, 3, 0, 16.83, 0.003333333333, 0.17, 16.66, 33.51);
|
||||||
checkPeriod(interestModel, 4, 0, 16.85, 0.003333333333, 0.11, 16.74, 16.73);
|
checkPeriod(interestModel, 4, 0, 16.83, 0.003333333333, 0.11, 16.72, 16.79);
|
||||||
checkPeriod(interestModel, 5, 0, 16.79, 0.003333333333, 0.06, 16.73, 0.0);
|
checkPeriod(interestModel, 5, 0, 16.85, 0.003333333333, 0.06, 16.79, 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user