FINERACT-2413: Re-amortization:- Accrual and Accrual Activity handling - Equal outstanding interest split

This commit is contained in:
Soma Sörös
2026-02-23 10:10:38 +00:00
committed by Adam Saghy
parent c7b4fc5404
commit fb43706e6c
4 changed files with 60 additions and 50 deletions
@@ -9366,16 +9366,16 @@ Feature: LoanReAgingEqualAmortization
| frequencyNumber | frequencyType | startDate | numberOfInstallments | reAgeInterestHandling | | frequencyNumber | frequencyType | startDate | numberOfInstallments | reAgeInterestHandling |
| 1 | MONTHS | 15 February 2024 | 6 | EQUAL_AMORTIZATION_FULL_INTEREST | | 1 | MONTHS | 15 February 2024 | 6 | EQUAL_AMORTIZATION_FULL_INTEREST |
Then Loan Repayment schedule has 8 periods, with the following data for periods: Then Loan Repayment schedule has 8 periods, with the following data for periods:
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding | | Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| | | 01 January 2024 | | 100.0 | | | 0.0 | | 0.0 | 0.0 | | | | | | | 01 January 2024 | | 100.0 | | | 0.0 | | 0.0 | 0.0 | | | |
| 1 | 31 | 01 February 2024 | 01 February 2024 | 83.57 | 16.43 | 0.58 | 0.0 | 0.0 | 17.01 | 17.01 | 0.0 | 0.0 | 0.0 | | 1 | 31 | 01 February 2024 | 01 February 2024 | 83.57 | 16.43 | 0.58 | 0.0 | 0.0 | 17.01 | 17.01 | 0.0 | 0.0 | 0.0 |
| 2 | 14 | 15 February 2024 | 15 February 2024 | 83.57 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | | 2 | 14 | 15 February 2024 | 15 February 2024 | 83.57 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 3 | 0 | 15 February 2024 | | 69.64 | 13.93 | 0.24 | 0.0 | 0.0 | 14.17 | 0.0 | 0.0 | 0.0 | 14.17 | | 3 | 0 | 15 February 2024 | | 69.64 | 13.93 | 0.24 | 0.0 | 0.0 | 14.17 | 0.0 | 0.0 | 0.0 | 14.17 |
| 4 | 29 | 15 March 2024 | | 55.71 | 13.93 | 0.24 | 0.0 | 0.0 | 14.17 | 0.0 | 0.0 | 0.0 | 14.17 | | 4 | 29 | 15 March 2024 | | 55.71 | 13.93 | 0.24 | 0.0 | 0.0 | 14.17 | 0.0 | 0.0 | 0.0 | 14.17 |
| 5 | 31 | 15 April 2024 | | 41.77 | 13.94 | 0.24 | 0.0 | 0.0 | 14.18 | 0.0 | 0.0 | 0.0 | 14.18 | | 5 | 31 | 15 April 2024 | | 41.78 | 13.93 | 0.24 | 0.0 | 0.0 | 14.17 | 0.0 | 0.0 | 0.0 | 14.17 |
| 6 | 30 | 15 May 2024 | | 27.83 | 13.94 | 0.24 | 0.0 | 0.0 | 14.18 | 0.0 | 0.0 | 0.0 | 14.18 | | 6 | 30 | 15 May 2024 | | 27.85 | 13.93 | 0.24 | 0.0 | 0.0 | 14.17 | 0.0 | 0.0 | 0.0 | 14.17 |
| 7 | 31 | 15 June 2024 | | 13.89 | 13.94 | 0.24 | 0.0 | 0.0 | 14.18 | 0.0 | 0.0 | 0.0 | 14.18 | | 7 | 31 | 15 June 2024 | | 13.92 | 13.93 | 0.24 | 0.0 | 0.0 | 14.17 | 0.0 | 0.0 | 0.0 | 14.17 |
| 8 | 30 | 15 July 2024 | | 0.0 | 13.89 | 0.27 | 0.0 | 0.0 | 14.16 | 0.0 | 0.0 | 0.0 | 14.16 | | 8 | 30 | 15 July 2024 | | 0.0 | 13.92 | 0.27 | 0.0 | 0.0 | 14.19 | 0.0 | 0.0 | 0.0 | 14.19 |
And Loan Repayment schedule has the following data in Total row: And Loan Repayment schedule has the following data in Total row:
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding | | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| 100.0 | 2.05 | 0.0 | 0.0 | 102.05 | 17.01 | 0.0 | 0.0 | 85.04 | | 100.0 | 2.05 | 0.0 | 0.0 | 102.05 | 17.01 | 0.0 | 0.0 | 85.04 |
@@ -4818,13 +4818,13 @@ Feature: LoanReAmortization
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding | | Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| | | 01 January 2024 | | 100.0 | | | 0.0 | | 0.0 | 0.0 | | | | | | | 01 January 2024 | | 100.0 | | | 0.0 | | 0.0 | 0.0 | | | |
| 1 | 31 | 01 February 2024 | 01 February 2024 | 83.57 | 16.43 | 0.58 | 0.0 | 0.0 | 17.01 | 17.01 | 0.0 | 0.0 | 0.0 | | 1 | 31 | 01 February 2024 | 01 February 2024 | 83.57 | 16.43 | 0.58 | 0.0 | 0.0 | 17.01 | 17.01 | 0.0 | 0.0 | 0.0 |
| 2 | 29 | 01 March 2024 | 15 March 2024 | 83.57 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | | 2 | 29 | 01 March 2024 | 15 March 2024 | 83.57 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 3 | 31 | 01 April 2024 | | 69.84 | 13.73 | 0.57 | 0.0 | 0.0 | 14.3 | 0.0 | 0.0 | 0.0 | 14.3 | | 3 | 31 | 01 April 2024 | | 69.85 | 13.72 | 0.57 | 0.0 | 0.0 | 14.29 | 0.0 | 0.0 | 0.0 | 14.29 |
| 4 | 30 | 01 May 2024 | | 56.03 | 13.81 | 0.49 | 0.0 | 0.0 | 14.3 | 0.0 | 0.0 | 0.0 | 14.3 | | 4 | 30 | 01 May 2024 | | 56.05 | 13.8 | 0.49 | 0.0 | 0.0 | 14.29 | 0.0 | 0.0 | 0.0 | 14.29 |
| 5 | 31 | 01 June 2024 | | 42.14 | 13.89 | 0.41 | 0.0 | 0.0 | 14.3 | 0.0 | 0.0 | 0.0 | 14.3 | | 5 | 31 | 01 June 2024 | | 42.17 | 13.88 | 0.41 | 0.0 | 0.0 | 14.29 | 0.0 | 0.0 | 0.0 | 14.29 |
| 6 | 30 | 01 July 2024 | | 28.17 | 13.97 | 0.33 | 0.0 | 0.0 | 14.3 | 0.0 | 0.0 | 0.0 | 14.3 | | 6 | 30 | 01 July 2024 | | 28.21 | 13.96 | 0.33 | 0.0 | 0.0 | 14.29 | 0.0 | 0.0 | 0.0 | 14.29 |
| 7 | 31 | 01 August 2024 | | 14.11 | 14.06 | 0.24 | 0.0 | 0.0 | 14.3 | 0.0 | 0.0 | 0.0 | 14.3 | | 7 | 31 | 01 August 2024 | | 14.16 | 14.05 | 0.24 | 0.0 | 0.0 | 14.29 | 0.0 | 0.0 | 0.0 | 14.29 |
| 8 | 31 | 01 September 2024 | | 0.0 | 14.11 | 0.16 | 0.0 | 0.0 | 14.27 | 0.0 | 0.0 | 0.0 | 14.27 | | 8 | 31 | 01 September 2024 | | 0.0 | 14.16 | 0.16 | 0.0 | 0.0 | 14.32 | 0.0 | 0.0 | 0.0 | 14.32 |
Then Loan Repayment schedule has the following data in Total row: Then Loan Repayment schedule has the following data in Total row:
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding | | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| 100.0 | 2.78 | 0.0 | 0.0 | 102.78 | 17.01 | 0.0 | 0.0 | 85.77 | | 100.0 | 2.78 | 0.0 | 0.0 | 102.78 | 17.01 | 0.0 | 0.0 | 85.77 |
@@ -4842,15 +4842,15 @@ Feature: LoanReAmortization
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding | | Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| | | 01 January 2024 | | 100.0 | | | 0.0 | | 0.0 | 0.0 | | | | | | | 01 January 2024 | | 100.0 | | | 0.0 | | 0.0 | 0.0 | | | |
| 1 | 31 | 01 February 2024 | 01 February 2024 | 83.57 | 16.43 | 0.58 | 0.0 | 0.0 | 17.01 | 17.01 | 0.0 | 0.0 | 0.0 | | 1 | 31 | 01 February 2024 | 01 February 2024 | 83.57 | 16.43 | 0.58 | 0.0 | 0.0 | 17.01 | 17.01 | 0.0 | 0.0 | 0.0 |
| 2 | 29 | 01 March 2024 | 15 March 2024 | 83.57 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | | 2 | 29 | 01 March 2024 | 15 March 2024 | 83.57 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 3 | 31 | 01 April 2024 | | 69.84 | 13.73 | 0.57 | 0.0 | 0.0 | 14.3 | 0.0 | 0.0 | 0.0 | 14.3 | | 3 | 31 | 01 April 2024 | | 69.85 | 13.72 | 0.57 | 0.0 | 0.0 | 14.29 | 0.0 | 0.0 | 0.0 | 14.29 |
| 4 | 30 | 01 May 2024 | | 56.03 | 13.81 | 0.49 | 0.0 | 0.0 | 14.3 | 0.0 | 0.0 | 0.0 | 14.3 | | 4 | 30 | 01 May 2024 | | 56.05 | 13.8 | 0.49 | 0.0 | 0.0 | 14.29 | 0.0 | 0.0 | 0.0 | 14.29 |
| 5 | 31 | 01 June 2024 | | 42.14 | 13.89 | 0.41 | 0.0 | 0.0 | 14.3 | 0.0 | 0.0 | 0.0 | 14.3 | | 5 | 31 | 01 June 2024 | | 42.17 | 13.88 | 0.41 | 0.0 | 0.0 | 14.29 | 0.0 | 0.0 | 0.0 | 14.29 |
| 6 | 30 | 01 July 2024 | | 33.84 | 8.3 | 0.33 | 0.0 | 0.0 | 8.63 | 0.0 | 0.0 | 0.0 | 8.63 | | 6 | 30 | 01 July 2024 | | 33.87 | 8.3 | 0.33 | 0.0 | 0.0 | 8.63 | 0.0 | 0.0 | 0.0 | 8.63 |
| 7 | 31 | 01 August 2024 | | 25.49 | 8.35 | 0.28 | 0.0 | 0.0 | 8.63 | 0.0 | 0.0 | 0.0 | 8.63 | | 7 | 31 | 01 August 2024 | | 25.52 | 8.35 | 0.28 | 0.0 | 0.0 | 8.63 | 0.0 | 0.0 | 0.0 | 8.63 |
| 8 | 31 | 01 September 2024 | | 17.09 | 8.4 | 0.23 | 0.0 | 0.0 | 8.63 | 0.0 | 0.0 | 0.0 | 8.63 | | 8 | 31 | 01 September 2024 | | 17.12 | 8.4 | 0.23 | 0.0 | 0.0 | 8.63 | 0.0 | 0.0 | 0.0 | 8.63 |
| 9 | 30 | 01 October 2024 | | 8.56 | 8.53 | 0.1 | 0.0 | 0.0 | 8.63 | 0.0 | 0.0 | 0.0 | 8.63 | | 9 | 30 | 01 October 2024 | | 8.59 | 8.53 | 0.1 | 0.0 | 0.0 | 8.63 | 0.0 | 0.0 | 0.0 | 8.63 |
| 10 | 31 | 01 November 2024 | | 0.0 | 8.56 | 0.05 | 0.0 | 0.0 | 8.61 | 0.0 | 0.0 | 0.0 | 8.61 | | 10 | 31 | 01 November 2024 | | 0.0 | 8.59 | 0.05 | 0.0 | 0.0 | 8.64 | 0.0 | 0.0 | 0.0 | 8.64 |
Then Loan Repayment schedule has the following data in Total row: Then Loan Repayment schedule has the following data in Total row:
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding | | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| 100.0 | 3.04 | 0.0 | 0.0 | 103.04 | 17.01 | 0.0 | 0.0 | 86.03 | | 100.0 | 3.04 | 0.0 | 0.0 | 103.04 | 17.01 | 0.0 | 0.0 | 86.03 |
@@ -7129,14 +7129,14 @@ Feature: LoanReAmortization
When Admin runs inline COB job for Loan When Admin runs inline COB job for Loan
Then Loan Transactions tab has the following new accrual data: Then Loan Transactions tab has the following new accrual data:
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed | | Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
| 01 April 2024 | Accrual Adjustment | 0.42 | 0.0 | 0.42 | 0.0 | 0.0 | 0.0 | false | false | | 01 April 2024 | Accrual Adjustment | 0.86 | 0.0 | 0.86 | 0.0 | 0.0 | 0.0 | false | false |
When Admin sets the business date to "01 May 2024" When Admin sets the business date to "01 May 2024"
When Admin runs inline COB job for Loan When Admin runs inline COB job for Loan
## Why we have accrual adjustment on 02 april ## Why we have accrual adjustment on 02 april
Then Loan Transactions tab has the following new accrual data: Then Loan Transactions tab has the following new accrual data:
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed | | Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
| 02 April 2024 | Accrual Adjustment | 0.4 | 0.0 | 0.4 | 0.0 | 0.0 | 0.0 | false | false | | 02 April 2024 | Accrual | 0.04 | 0.0 | 0.04 | 0.0 | 0.0 | 0.0 | false | false |
| 03 April 2024 | Accrual | 0.05 | 0.0 | 0.05 | 0.0 | 0.0 | 0.0 | false | false | | 03 April 2024 | Accrual | 0.05 | 0.0 | 0.05 | 0.0 | 0.0 | 0.0 | false | false |
| 04 April 2024 | Accrual | 0.04 | 0.0 | 0.04 | 0.0 | 0.0 | 0.0 | false | false | | 04 April 2024 | Accrual | 0.04 | 0.0 | 0.04 | 0.0 | 0.0 | 0.0 | false | false |
| 05 April 2024 | Accrual | 0.05 | 0.0 | 0.05 | 0.0 | 0.0 | 0.0 | false | false | | 05 April 2024 | Accrual | 0.05 | 0.0 | 0.05 | 0.0 | 0.0 | 0.0 | false | false |
@@ -896,7 +896,7 @@ public final class ProgressiveEMICalculator implements EMICalculator {
} }
rp.setEmi(rp.getTotalPaidAmount()); rp.setEmi(rp.getTotalPaidAmount());
rp.moveOutstandingDueToReAging(); rp.moveOutstandingDueToReAging();
rp.setNoUnrecognisedInterest(true); rp.setInterestMovedDownward(true);
}); });
} }
@@ -1098,7 +1098,7 @@ public final class ProgressiveEMICalculator implements EMICalculator {
findLastUnpaidRepaymentPeriod.ifPresent(repaymentPeriod -> { findLastUnpaidRepaymentPeriod.ifPresent(repaymentPeriod -> {
repaymentPeriod.setFutureUnrecognizedInterest(scheduleModel.zero()); repaymentPeriod.setFutureUnrecognizedInterest(scheduleModel.zero());
scheduleModel.repaymentPeriods().forEach(rp -> { scheduleModel.repaymentPeriods().forEach(rp -> {
rp.setInterestMoved(false); rp.setInterestMovedUpward(false);
}); });
MathContext mc = scheduleModel.mc(); MathContext mc = scheduleModel.mc();
@@ -1161,7 +1161,7 @@ public final class ProgressiveEMICalculator implements EMICalculator {
repaymentPeriod.setFutureUnrecognizedInterest(period.getUnrecognizedInterest()); repaymentPeriod.setFutureUnrecognizedInterest(period.getUnrecognizedInterest());
scheduleModel.repaymentPeriods().stream().filter(rp -> rp.getDueDate().isAfter(repaymentPeriod.getDueDate())) // scheduleModel.repaymentPeriods().stream().filter(rp -> rp.getDueDate().isAfter(repaymentPeriod.getDueDate())) //
.forEach(rp -> { .forEach(rp -> {
rp.setInterestMoved(true); rp.setInterestMovedUpward(true);
}); });
}); });
} }
@@ -1530,7 +1530,7 @@ public final class ProgressiveEMICalculator implements EMICalculator {
final CurrencyData currency = scheduleModel.loanProductRelatedDetail().getCurrencyData(); final CurrencyData currency = scheduleModel.loanProductRelatedDetail().getCurrencyData();
RepaymentPeriod firstRepaymentPeriod = repaymentPeriods.getFirst(); RepaymentPeriod firstRepaymentPeriod = repaymentPeriods.getFirst();
RepaymentPeriod lastRepaymentPeriod = repaymentPeriods.getLast(); RepaymentPeriod lastRepaymentPeriod = repaymentPeriods.getLast();
Money sumOfInterest = Money.zero(currency); Money sumOfInterest = Money.of(currency, calculateEMIValueForFixedInterest(repaymentPeriods, mc), mc);
for (RepaymentPeriod rp : repaymentPeriods) { for (RepaymentPeriod rp : repaymentPeriods) {
Money interest = rp.calculateCalculatedDueInterest(); Money interest = rp.calculateCalculatedDueInterest();
sumOfInterest = sumOfInterest.add(interest); sumOfInterest = sumOfInterest.add(interest);
@@ -1604,8 +1604,9 @@ public final class ProgressiveEMICalculator implements EMICalculator {
final Money outstandingBalance = startPeriod.getInitialBalanceForEmiRecalculation(); final Money outstandingBalance = startPeriod.getInitialBalanceForEmiRecalculation();
final Money equalMonthlyInstallment = Money.of(outstandingBalance.getCurrencyData(), final Money equalMonthlyInstallment = Money
calculateEMIValue(rateFactorN, outstandingBalance.getAmount(), fnResult, mc), mc); .of(outstandingBalance.getCurrencyData(), calculateEMIValue(rateFactorN, outstandingBalance.getAmount(), fnResult, mc), mc)
.add(calculateEMIValueForFixedInterest(repaymentPeriods, mc));
final Money finalEqualMonthlyInstallment = applyInstallmentAmountInMultiplesOf(scheduleModel, equalMonthlyInstallment); final Money finalEqualMonthlyInstallment = applyInstallmentAmountInMultiplesOf(scheduleModel, equalMonthlyInstallment);
repaymentPeriods.forEach(period -> { repaymentPeriods.forEach(period -> {
@@ -1716,6 +1717,14 @@ public final class ProgressiveEMICalculator implements EMICalculator {
return rateFactorPlus1N.multiply(outstandingBalanceForRest, mc).divide(fnResult, mc); return rateFactorPlus1N.multiply(outstandingBalanceForRest, mc).divide(fnResult, mc);
} }
/**
* Calculate the EMI (Equal Monthly Installment) value for fixed interest portion
*/
private BigDecimal calculateEMIValueForFixedInterest(final List<RepaymentPeriod> repaymentPeriods, MathContext mc) {
return repaymentPeriods.stream().map(RepaymentPeriod::getFixedInterest).map(Money::getAmount).reduce(ZERO, BigDecimal::add)
.divide(BigDecimal.valueOf(repaymentPeriods.isEmpty() ? 1 : repaymentPeriods.size()), mc);
}
/** /**
* To calculate the daily payment, we first need to calculate something called the Rate Factor. We're going to be * To calculate the daily payment, we first need to calculate something called the Rate Factor. We're going to be
* using simple interest. The Rate Factor for simple interest is calculated by the following formula: * using simple interest. The Rate Factor for simple interest is calculated by the following formula:
@@ -1994,12 +2003,9 @@ public final class ProgressiveEMICalculator implements EMICalculator {
.addCreditedInterestAmount(MathUtil.min(rp.getOutstandingInterest(), rp.getCreditedInterest(), false).negated()); .addCreditedInterestAmount(MathUtil.min(rp.getOutstandingInterest(), rp.getCreditedInterest(), false).negated());
rp.setEmi(rp.getTotalPaidAmount()); rp.setEmi(rp.getTotalPaidAmount());
rp.moveOutstandingDueToReAging(); rp.moveOutstandingDueToReAging();
rp.setNoUnrecognisedInterest(true); rp.setInterestMovedDownward(true);
}); });
// stop calculate unrecognised interest at this point because all
interestSchedule.getLastRepaymentPeriod().setNoUnrecognisedInterest(true);
if (!originalMaturityDate.isBefore(transactionDate)) { if (!originalMaturityDate.isBefore(transactionDate)) {
createRepaymentPeriodForEarlyRepaidAmountsDuringReAgeing(interestSchedule, createRepaymentPeriodForEarlyRepaidAmountsDuringReAgeing(interestSchedule,
paidBalancesFromTransactionDate.getOutstandingPrincipal(), paidBalancesFromTransactionDate.getOutstandingInterest(), paidBalancesFromTransactionDate.getOutstandingPrincipal(), paidBalancesFromTransactionDate.getOutstandingInterest(),
@@ -77,7 +77,7 @@ public class RepaymentPeriod {
private Memo<Money> outstandingBalanceCalculation; private Memo<Money> outstandingBalanceCalculation;
@Getter @Getter
@Setter @Setter
private boolean isInterestMoved = false; private boolean isInterestMovedUpward = false;
@Setter @Setter
private Money totalDisbursedAmount; private Money totalDisbursedAmount;
@@ -99,7 +99,7 @@ public class RepaymentPeriod {
private Money creditedInterestMovedDueReAge; private Money creditedInterestMovedDueReAge;
@Setter @Setter
@Getter @Getter
private boolean noUnrecognisedInterest; private boolean isInterestMovedDownward;
@Setter @Setter
@Getter @Getter
private boolean reAged; private boolean reAged;
@@ -111,7 +111,7 @@ public class RepaymentPeriod {
protected RepaymentPeriod(RepaymentPeriod previous, LocalDate fromDate, LocalDate dueDate, List<InterestPeriod> interestPeriods, protected RepaymentPeriod(RepaymentPeriod previous, LocalDate fromDate, LocalDate dueDate, List<InterestPeriod> interestPeriods,
Money emi, Money originalEmi, Money paidPrincipal, Money paidInterest, Money futureUnrecognizedInterest, MathContext mc, Money emi, Money originalEmi, Money paidPrincipal, Money paidInterest, Money futureUnrecognizedInterest, MathContext mc,
ILoanConfigurationDetails loanProductRelatedDetail, boolean noUnrecognisedInterest, boolean reAged, ILoanConfigurationDetails loanProductRelatedDetail, boolean isInterestMovedDownward, boolean reAged,
boolean reAgedEarlyRepaymentHolder, Money fixedInterest) { boolean reAgedEarlyRepaymentHolder, Money fixedInterest) {
this.previous = previous; this.previous = previous;
this.fromDate = fromDate; this.fromDate = fromDate;
@@ -124,7 +124,7 @@ public class RepaymentPeriod {
this.futureUnrecognizedInterest = futureUnrecognizedInterest; this.futureUnrecognizedInterest = futureUnrecognizedInterest;
this.mc = mc; this.mc = mc;
this.loanProductRelatedDetail = loanProductRelatedDetail; this.loanProductRelatedDetail = loanProductRelatedDetail;
this.noUnrecognisedInterest = noUnrecognisedInterest; this.isInterestMovedDownward = isInterestMovedDownward;
this.reAged = reAged; this.reAged = reAged;
this.reAgedEarlyRepaymentHolder = reAgedEarlyRepaymentHolder; this.reAgedEarlyRepaymentHolder = reAgedEarlyRepaymentHolder;
this.fixedInterest = fixedInterest; this.fixedInterest = fixedInterest;
@@ -151,13 +151,13 @@ public class RepaymentPeriod {
final RepaymentPeriod newRepaymentPeriod = new RepaymentPeriod(previous, repaymentPeriod.getFromDate(), final RepaymentPeriod newRepaymentPeriod = new RepaymentPeriod(previous, repaymentPeriod.getFromDate(),
repaymentPeriod.getDueDate(), new ArrayList<>(), repaymentPeriod.getEmi(), repaymentPeriod.getOriginalEmi(), repaymentPeriod.getDueDate(), new ArrayList<>(), repaymentPeriod.getEmi(), repaymentPeriod.getOriginalEmi(),
repaymentPeriod.getPaidPrincipal(), repaymentPeriod.getPaidInterest(), repaymentPeriod.getFutureUnrecognizedInterest(), mc, repaymentPeriod.getPaidPrincipal(), repaymentPeriod.getPaidInterest(), repaymentPeriod.getFutureUnrecognizedInterest(), mc,
repaymentPeriod.getLoanProductRelatedDetail(), repaymentPeriod.isNoUnrecognisedInterest(), repaymentPeriod.isReAged(), repaymentPeriod.getLoanProductRelatedDetail(), repaymentPeriod.isInterestMovedDownward(), repaymentPeriod.isReAged(),
repaymentPeriod.isReAgedEarlyRepaymentHolder(), repaymentPeriod.getFixedInterest()); repaymentPeriod.isReAgedEarlyRepaymentHolder(), repaymentPeriod.getFixedInterest());
newRepaymentPeriod.setCreditedPrincipalMovedDueReAge(repaymentPeriod.getCreditedPrincipalMovedDueReAge()); newRepaymentPeriod.setCreditedPrincipalMovedDueReAge(repaymentPeriod.getCreditedPrincipalMovedDueReAge());
newRepaymentPeriod.setCreditedInterestMovedDueReAge(repaymentPeriod.getCreditedInterestMovedDueReAge()); newRepaymentPeriod.setCreditedInterestMovedDueReAge(repaymentPeriod.getCreditedInterestMovedDueReAge());
newRepaymentPeriod.setTotalDisbursedAmount(repaymentPeriod.getTotalDisbursedAmount()); newRepaymentPeriod.setTotalDisbursedAmount(repaymentPeriod.getTotalDisbursedAmount());
newRepaymentPeriod.setTotalCapitalizedIncomeAmount(repaymentPeriod.getTotalCapitalizedIncomeAmount()); newRepaymentPeriod.setTotalCapitalizedIncomeAmount(repaymentPeriod.getTotalCapitalizedIncomeAmount());
newRepaymentPeriod.setInterestMoved(repaymentPeriod.isInterestMoved()); newRepaymentPeriod.setInterestMovedUpward(repaymentPeriod.isInterestMovedUpward());
newRepaymentPeriod.setCurrency(repaymentPeriod.getCurrency()); newRepaymentPeriod.setCurrency(repaymentPeriod.getCurrency());
// There is always at least 1 interest period, by default with same from-due date as repayment period // There is always at least 1 interest period, by default with same from-due date as repayment period
for (InterestPeriod interestPeriod : repaymentPeriod.getInterestPeriods()) { for (InterestPeriod interestPeriod : repaymentPeriod.getInterestPeriods()) {
@@ -170,13 +170,16 @@ public class RepaymentPeriod {
final Money zero = Money.zero(repaymentPeriod.getCurrency(), mc); final Money zero = Money.zero(repaymentPeriod.getCurrency(), mc);
final RepaymentPeriod newRepaymentPeriod = new RepaymentPeriod(previous, repaymentPeriod.getFromDate(), final RepaymentPeriod newRepaymentPeriod = new RepaymentPeriod(previous, repaymentPeriod.getFromDate(),
repaymentPeriod.getDueDate(), new ArrayList<>(), repaymentPeriod.getEmi(), repaymentPeriod.getOriginalEmi(), zero, zero, repaymentPeriod.getDueDate(), new ArrayList<>(), repaymentPeriod.getEmi(), repaymentPeriod.getOriginalEmi(), zero, zero,
zero, mc, repaymentPeriod.getLoanProductRelatedDetail(), repaymentPeriod.isNoUnrecognisedInterest(), zero, mc, repaymentPeriod.getLoanProductRelatedDetail(), repaymentPeriod.isInterestMovedDownward(),
repaymentPeriod.isReAged(), repaymentPeriod.isReAgedEarlyRepaymentHolder(), repaymentPeriod.getFixedInterest()); repaymentPeriod.isReAged(), repaymentPeriod.isReAgedEarlyRepaymentHolder(), repaymentPeriod.getFixedInterest());
newRepaymentPeriod.setCreditedPrincipalMovedDueReAge(repaymentPeriod.getCreditedPrincipalMovedDueReAge()); newRepaymentPeriod.setCreditedPrincipalMovedDueReAge(repaymentPeriod.getCreditedPrincipalMovedDueReAge());
newRepaymentPeriod.setCreditedInterestMovedDueReAge(repaymentPeriod.getCreditedInterestMovedDueReAge()); newRepaymentPeriod.setCreditedInterestMovedDueReAge(repaymentPeriod.getCreditedInterestMovedDueReAge());
if (repaymentPeriod.isInterestMovedDownward()) {
newRepaymentPeriod.setFixedInterest(repaymentPeriod.getPaidInterest());
}
newRepaymentPeriod.setTotalDisbursedAmount(repaymentPeriod.getTotalDisbursedAmount()); newRepaymentPeriod.setTotalDisbursedAmount(repaymentPeriod.getTotalDisbursedAmount());
newRepaymentPeriod.setTotalCapitalizedIncomeAmount(repaymentPeriod.getTotalCapitalizedIncomeAmount()); newRepaymentPeriod.setTotalCapitalizedIncomeAmount(repaymentPeriod.getTotalCapitalizedIncomeAmount());
newRepaymentPeriod.setInterestMoved(repaymentPeriod.isInterestMoved()); newRepaymentPeriod.setInterestMovedUpward(repaymentPeriod.isInterestMovedUpward());
newRepaymentPeriod.setCurrency(repaymentPeriod.getCurrency()); newRepaymentPeriod.setCurrency(repaymentPeriod.getCurrency());
// There is always at least 1 interest period, by default with same from-due date as repayment period // There is always at least 1 interest period, by default with same from-due date as repayment period
for (InterestPeriod interestPeriod : repaymentPeriod.getInterestPeriods()) { for (InterestPeriod interestPeriod : repaymentPeriod.getInterestPeriods()) {
@@ -217,8 +220,9 @@ public class RepaymentPeriod {
@NotNull @NotNull
public Money getCalculatedDueInterest() { public Money getCalculatedDueInterest() {
if (calculatedDueInterestCalculation == null) { if (calculatedDueInterestCalculation == null) {
calculatedDueInterestCalculation = Memo.of(this::calculateCalculatedDueInterest, () -> new Object[] { previous, interestPeriods, calculatedDueInterestCalculation = Memo.of(this::calculateCalculatedDueInterest,
futureUnrecognizedInterest, isInterestMoved, totalDisbursedAmount, fixedInterest, reAged }); () -> new Object[] { previous, interestPeriods, futureUnrecognizedInterest, isInterestMovedUpward,
isInterestMovedDownward, totalDisbursedAmount, fixedInterest, reAged });
} }
return calculatedDueInterestCalculation.get(); return calculatedDueInterestCalculation.get();
} }
@@ -242,7 +246,7 @@ public class RepaymentPeriod {
public Money calculateCalculatedDueInterest() { public Money calculateCalculatedDueInterest() {
Money calculatedDueInterest = getZero(); Money calculatedDueInterest = getZero();
if (!isInterestMoved()) { if (!isInterestMovedUpward() && !isInterestMovedDownward()) {
calculatedDueInterest = Money.of(getEmi().getCurrencyData(), calculatedDueInterest = Money.of(getEmi().getCurrencyData(),
getInterestPeriods().stream().map(InterestPeriod::getCalculatedDueInterest).reduce(BigDecimal.ZERO, BigDecimal::add), getInterestPeriods().stream().map(InterestPeriod::getCalculatedDueInterest).reduce(BigDecimal.ZERO, BigDecimal::add),
mc); mc);
@@ -367,7 +371,7 @@ public class RepaymentPeriod {
* @return * @return
*/ */
public Money getUnrecognizedInterest() { public Money getUnrecognizedInterest() {
return noUnrecognisedInterest ? getZero() : getCalculatedDueInterest().minus(getDueInterest(), getMc()); return MathUtil.negativeToZero(getCalculatedDueInterest().minus(getDueInterest(), getMc()), getMc());
} }
public Money getCreditedAmounts() { public Money getCreditedAmounts() {