FINERACT-1981: Fix interest calculation logic (rounding issues with sub interest periods)

This commit is contained in:
Adam Saghy
2025-02-20 14:24:24 +01:00
parent b4b9d3ea71
commit e02420f998
17 changed files with 803 additions and 782 deletions
@@ -499,7 +499,7 @@ public final class ProgressiveEMICalculator implements EMICalculator {
final DaysInMonthType daysInMonthType = DaysInMonthType.fromInt(loanProductRelatedDetail.getDaysInMonthType());
final PeriodFrequencyType repaymentFrequency = loanProductRelatedDetail.getRepaymentPeriodFrequencyType();
final BigDecimal daysInYear = BigDecimal.valueOf(daysInYearType.getNumberOfDays(interestPeriodFromDate));
BigDecimal daysInYear = BigDecimal.valueOf(daysInYearType.getNumberOfDays(interestPeriodFromDate));
final BigDecimal actualDaysInPeriod = BigDecimal
.valueOf(DateUtils.getDifferenceInDays(interestPeriodFromDate, interestPeriodDueDate));
final BigDecimal calculatedDaysInPeriod = BigDecimal
@@ -611,7 +611,7 @@ public final class ProgressiveEMICalculator implements EMICalculator {
final PeriodFrequencyType repaymentFrequency = loanProductRelatedDetail.getRepaymentPeriodFrequencyType();
final BigDecimal repaymentEvery = BigDecimal.valueOf(loanProductRelatedDetail.getRepayEvery());
final BigDecimal daysInYear = BigDecimal.valueOf(daysInYearType.getNumberOfDays(interestPeriodFromDate));
BigDecimal daysInYear = BigDecimal.valueOf(daysInYearType.getNumberOfDays(interestPeriodFromDate));
final BigDecimal actualDaysInPeriod = BigDecimal
.valueOf(DateUtils.getDifferenceInDays(interestPeriodFromDate, interestPeriodDueDate));
final BigDecimal calculatedDaysInPeriod = BigDecimal
@@ -103,20 +103,19 @@ public class InterestPeriod implements Comparable<InterestPeriod> {
this.chargebackInterest = MathUtil.plus(this.chargebackInterest, chargebackInterest, mc);
}
public Money getCalculatedDueInterest() {
public BigDecimal getCalculatedDueInterest() {
if (isPaused) {
return chargebackInterest;
return chargebackInterest.getAmount();
}
long lengthTillPeriodDueDate = getLengthTillPeriodDueDate();
final Money interestDueTillRepaymentDueDate = Money.of(outstandingLoanBalance.getCurrencyData(), lengthTillPeriodDueDate == 0 //
final BigDecimal interestDueTillRepaymentDueDate = lengthTillPeriodDueDate == 0 //
? BigDecimal.ZERO //
: getOutstandingLoanBalance().getAmount() //
.multiply(getRateFactorTillPeriodDueDate(), mc) //
.divide(BigDecimal.valueOf(lengthTillPeriodDueDate), mc) //
.multiply(BigDecimal.valueOf(getLength()), mc),
mc); //
return MathUtil.plus(chargebackInterest, interestDueTillRepaymentDueDate, mc);
.multiply(BigDecimal.valueOf(getLength()), mc); //
return MathUtil.add(chargebackInterest.getAmount(), interestDueTillRepaymentDueDate, mc);
}
public long getLength() {
@@ -296,8 +296,7 @@ public class ProgressiveLoanInterestScheduleModel {
* @return
*/
public Money getTotalDueInterest() {
return repaymentPeriods().stream().flatMap(rp -> rp.getInterestPeriods().stream().map(InterestPeriod::getCalculatedDueInterest))
.reduce(zero(), Money::plus);
return repaymentPeriods().stream().map(RepaymentPeriod::getCalculatedDueInterest).reduce(zero(), Money::plus);
}
/**
@@ -149,8 +149,8 @@ public final class RepaymentPeriod {
}
private Money calculateCalculatedDueInterest() {
Money calculatedDueInterest = getInterestPeriods().stream().map(InterestPeriod::getCalculatedDueInterest).reduce(getZero(mc),
(m1, m2) -> m1.plus(m2, mc));
Money calculatedDueInterest = Money.of(emi.getCurrencyData(),
getInterestPeriods().stream().map(InterestPeriod::getCalculatedDueInterest).reduce(BigDecimal.ZERO, BigDecimal::add), mc);
if (getPrevious().isPresent()) {
calculatedDueInterest = calculatedDueInterest.add(getPrevious().get().getUnrecognizedInterest(), mc);
}