This is an automated email from the ASF dual-hosted git repository.
adamsaghy pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git
The following commit(s) were added to refs/heads/develop by this push:
new 5729af5e7 FINERACT-1981: fix progressive installment reschedule
5729af5e7 is described below
commit 5729af5e76e4cc97d9f420df209879cea96c967e
Author: adam.magyari <[email protected]>
AuthorDate: Mon Jan 20 16:44:32 2025 +0100
FINERACT-1981: fix progressive installment reschedule
---
...dvancedPaymentScheduleTransactionProcessor.java | 10 +-
.../data/ProgressiveLoanInterestScheduleModel.java | 16 +-
.../domain/ProgressiveLoanScheduleGenerator.java | 2 +-
.../portfolio/loanproduct/calc/EMICalculator.java | 9 +-
.../loanproduct/calc/ProgressiveEMICalculator.java | 36 ++--
.../calc/ProgressiveEMICalculatorTest.java | 214 +++++++++++++++------
6 files changed, 200 insertions(+), 87 deletions(-)
diff --git
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java
index 0c9021998..a9a70e4b7 100644
---
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java
+++
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java
@@ -183,17 +183,17 @@ public class AdvancedPaymentScheduleTransactionProcessor
extends AbstractLoanRep
MoneyHolder overpaymentHolder = new MoneyHolder(Money.zero(currency));
final Loan loan = loanTransactions.get(0).getLoan();
+ LoanTermVariationsDataWrapper loanTermVariations = Optional
+
.ofNullable(loan.getActiveLoanTermVariations()).map(loanTermVariationsSet ->
loanTermVariationsSet.stream()
+
.map(LoanTermVariations::toData).collect(Collectors.toCollection(ArrayList::new)))
+ .map(LoanTermVariationsDataWrapper::new).orElse(null);
final Integer installmentAmountInMultiplesOf =
loan.getLoanProduct().getInstallmentAmountInMultiplesOf();
final LoanProductRelatedDetail loanProductRelatedDetail =
loan.getLoanRepaymentScheduleDetail();
ProgressiveLoanInterestScheduleModel scheduleModel =
emiCalculator.generateInstallmentInterestScheduleModel(installments,
- loanProductRelatedDetail, installmentAmountInMultiplesOf,
overpaymentHolder.getMoneyObject().getMc());
+ loanProductRelatedDetail, loanTermVariations,
installmentAmountInMultiplesOf, overpaymentHolder.getMoneyObject().getMc());
ProgressiveTransactionCtx ctx = new
ProgressiveTransactionCtx(currency, installments, charges, overpaymentHolder,
changedTransactionDetail, scheduleModel);
- LoanTermVariationsDataWrapper loanTermVariations = Optional
-
.ofNullable(loan.getActiveLoanTermVariations()).map(loanTermVariationsSet ->
loanTermVariationsSet.stream()
-
.map(LoanTermVariations::toData).collect(Collectors.toCollection(ArrayList::new)))
- .map(LoanTermVariationsDataWrapper::new).orElse(null);
List<ChangeOperation> changeOperations =
createSortedChangeList(loanTermVariations, loanTransactions, charges);
List<LoanTransaction> overpaidTransactions = new ArrayList<>();
diff --git
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/data/ProgressiveLoanInterestScheduleModel.java
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/data/ProgressiveLoanInterestScheduleModel.java
index 94bc3f6eb..543ecb776 100644
---
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/data/ProgressiveLoanInterestScheduleModel.java
+++
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/data/ProgressiveLoanInterestScheduleModel.java
@@ -37,6 +37,7 @@ import lombok.Data;
import lombok.experimental.Accessors;
import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.apache.fineract.organisation.monetary.domain.Money;
+import
org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsDataWrapper;
import
org.apache.fineract.portfolio.loanproduct.domain.LoanProductMinimumRepaymentScheduleRelatedDetail;
@Data
@@ -46,35 +47,38 @@ public class ProgressiveLoanInterestScheduleModel {
private final List<RepaymentPeriod> repaymentPeriods;
private final TreeSet<InterestRate> interestRates;
private final LoanProductMinimumRepaymentScheduleRelatedDetail
loanProductRelatedDetail;
+ private final LoanTermVariationsDataWrapper loanTermVariations;
private final Integer installmentAmountInMultiplesOf;
private final MathContext mc;
private final Money zero;
public ProgressiveLoanInterestScheduleModel(final List<RepaymentPeriod>
repaymentPeriods,
- final LoanProductMinimumRepaymentScheduleRelatedDetail
loanProductRelatedDetail, final Integer installmentAmountInMultiplesOf,
- final MathContext mc) {
+ final LoanProductMinimumRepaymentScheduleRelatedDetail
loanProductRelatedDetail,
+ final LoanTermVariationsDataWrapper loanTermVariations, final
Integer installmentAmountInMultiplesOf, final MathContext mc) {
this.repaymentPeriods = repaymentPeriods;
this.interestRates = new TreeSet<>(Collections.reverseOrder());
this.loanProductRelatedDetail = loanProductRelatedDetail;
+ this.loanTermVariations = loanTermVariations;
this.installmentAmountInMultiplesOf = installmentAmountInMultiplesOf;
this.mc = mc;
this.zero = Money.zero(loanProductRelatedDetail.getCurrencyData(), mc);
}
private ProgressiveLoanInterestScheduleModel(final List<RepaymentPeriod>
repaymentPeriods, final TreeSet<InterestRate> interestRates,
- final LoanProductMinimumRepaymentScheduleRelatedDetail
loanProductRelatedDetail, final Integer installmentAmountInMultiplesOf,
- final MathContext mc) {
+ final LoanProductMinimumRepaymentScheduleRelatedDetail
loanProductRelatedDetail,
+ final LoanTermVariationsDataWrapper loanTermVariations, final
Integer installmentAmountInMultiplesOf, final MathContext mc) {
this.mc = mc;
this.repaymentPeriods = copyRepaymentPeriods(repaymentPeriods,
(previousPeriod, repaymentPeriod) -> new
RepaymentPeriod(previousPeriod, repaymentPeriod, mc));
this.interestRates = new TreeSet<>(interestRates);
this.loanProductRelatedDetail = loanProductRelatedDetail;
+ this.loanTermVariations = loanTermVariations;
this.installmentAmountInMultiplesOf = installmentAmountInMultiplesOf;
this.zero = Money.zero(loanProductRelatedDetail.getCurrencyData(), mc);
}
public ProgressiveLoanInterestScheduleModel deepCopy(MathContext mc) {
- return new ProgressiveLoanInterestScheduleModel(repaymentPeriods,
interestRates, loanProductRelatedDetail,
+ return new ProgressiveLoanInterestScheduleModel(repaymentPeriods,
interestRates, loanProductRelatedDetail, loanTermVariations,
installmentAmountInMultiplesOf, mc);
}
@@ -82,7 +86,7 @@ public class ProgressiveLoanInterestScheduleModel {
final List<RepaymentPeriod> repaymentPeriodCopies =
copyRepaymentPeriods(repaymentPeriods,
(previousPeriod, repaymentPeriod) -> new
RepaymentPeriod(previousPeriod, repaymentPeriod.getFromDate(),
repaymentPeriod.getDueDate(),
repaymentPeriod.getEmi().zero(), mc));
- return new ProgressiveLoanInterestScheduleModel(repaymentPeriodCopies,
interestRates, loanProductRelatedDetail,
+ return new ProgressiveLoanInterestScheduleModel(repaymentPeriodCopies,
interestRates, loanProductRelatedDetail, loanTermVariations,
installmentAmountInMultiplesOf, mc);
}
diff --git
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/ProgressiveLoanScheduleGenerator.java
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/ProgressiveLoanScheduleGenerator.java
index ab58c4237..d6053752c 100644
---
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/ProgressiveLoanScheduleGenerator.java
+++
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/ProgressiveLoanScheduleGenerator.java
@@ -90,7 +90,7 @@ public class ProgressiveLoanScheduleGenerator implements
LoanScheduleGenerator {
periodStartDate, loanApplicationTerms, holidayDetailDTO);
final ProgressiveLoanInterestScheduleModel interestScheduleModel =
emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods,
loanApplicationTerms.toLoanProductRelatedDetailMinimumData(),
- loanApplicationTerms.getInstallmentAmountInMultiplesOf(), mc);
+ loanApplicationTerms.getLoanTermVariations(),
loanApplicationTerms.getInstallmentAmountInMultiplesOf(), mc);
final List<LoanScheduleModelPeriod> periods = new
ArrayList<>(expectedRepaymentPeriods.size());
prepareDisbursementsOnLoanApplicationTerms(loanApplicationTerms);
diff --git
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/EMICalculator.java
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/EMICalculator.java
index 3f8641600..193e859da 100644
---
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/EMICalculator.java
+++
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/EMICalculator.java
@@ -25,6 +25,7 @@ import java.time.LocalDate;
import java.util.List;
import java.util.Optional;
import org.apache.fineract.organisation.monetary.domain.Money;
+import
org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsDataWrapper;
import
org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
import
org.apache.fineract.portfolio.loanaccount.loanschedule.data.OutstandingDetails;
import
org.apache.fineract.portfolio.loanaccount.loanschedule.data.PeriodDueDetails;
@@ -37,14 +38,14 @@ public interface EMICalculator {
@NotNull
ProgressiveLoanInterestScheduleModel
generatePeriodInterestScheduleModel(@NotNull
List<LoanScheduleModelRepaymentPeriod> periods,
- @NotNull LoanProductMinimumRepaymentScheduleRelatedDetail
loanProductRelatedDetail, Integer installmentAmountInMultiplesOf,
- MathContext mc);
+ @NotNull LoanProductMinimumRepaymentScheduleRelatedDetail
loanProductRelatedDetail,
+ LoanTermVariationsDataWrapper loanTermVariations, Integer
installmentAmountInMultiplesOf, MathContext mc);
@NotNull
ProgressiveLoanInterestScheduleModel
generateInstallmentInterestScheduleModel(
@NotNull List<LoanRepaymentScheduleInstallment> installments,
- @NotNull LoanProductMinimumRepaymentScheduleRelatedDetail
loanProductRelatedDetail, Integer installmentAmountInMultiplesOf,
- MathContext mc);
+ @NotNull LoanProductMinimumRepaymentScheduleRelatedDetail
loanProductRelatedDetail,
+ LoanTermVariationsDataWrapper loanTermVariations, Integer
installmentAmountInMultiplesOf, MathContext mc);
Optional<RepaymentPeriod>
findRepaymentPeriod(ProgressiveLoanInterestScheduleModel scheduleModel,
LocalDate dueDate);
diff --git
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/ProgressiveEMICalculator.java
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/ProgressiveEMICalculator.java
index 994d16432..e9d67f72d 100644
---
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/ProgressiveEMICalculator.java
+++
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/ProgressiveEMICalculator.java
@@ -35,6 +35,7 @@ import org.apache.fineract.organisation.monetary.domain.Money;
import org.apache.fineract.portfolio.common.domain.DaysInMonthType;
import org.apache.fineract.portfolio.common.domain.DaysInYearType;
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
+import
org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsDataWrapper;
import
org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
import
org.apache.fineract.portfolio.loanaccount.loanschedule.data.EmiAdjustment;
import
org.apache.fineract.portfolio.loanaccount.loanschedule.data.InterestPeriod;
@@ -57,9 +58,10 @@ public final class ProgressiveEMICalculator implements
EMICalculator {
@NotNull
public ProgressiveLoanInterestScheduleModel
generatePeriodInterestScheduleModel(@NotNull
List<LoanScheduleModelRepaymentPeriod> periods,
@NotNull LoanProductMinimumRepaymentScheduleRelatedDetail
loanProductRelatedDetail,
- final Integer installmentAmountInMultiplesOf, final MathContext
mc) {
+ LoanTermVariationsDataWrapper loanTermVariations, final Integer
installmentAmountInMultiplesOf, final MathContext mc) {
return generateInterestScheduleModel(periods,
LoanScheduleModelRepaymentPeriod::periodFromDate,
- LoanScheduleModelRepaymentPeriod::periodDueDate,
loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
+ LoanScheduleModelRepaymentPeriod::periodDueDate,
loanProductRelatedDetail, loanTermVariations,
+ installmentAmountInMultiplesOf, mc);
}
@Override
@@ -67,16 +69,17 @@ public final class ProgressiveEMICalculator implements
EMICalculator {
public ProgressiveLoanInterestScheduleModel
generateInstallmentInterestScheduleModel(
@NotNull List<LoanRepaymentScheduleInstallment> installments,
@NotNull LoanProductMinimumRepaymentScheduleRelatedDetail
loanProductRelatedDetail,
- final Integer installmentAmountInMultiplesOf, final MathContext
mc) {
+ LoanTermVariationsDataWrapper loanTermVariations, final Integer
installmentAmountInMultiplesOf, final MathContext mc) {
installments = installments.stream().filter(installment ->
!installment.isDownPayment() && !installment.isAdditional()).toList();
return generateInterestScheduleModel(installments,
LoanRepaymentScheduleInstallment::getFromDate,
- LoanRepaymentScheduleInstallment::getDueDate,
loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
+ LoanRepaymentScheduleInstallment::getDueDate,
loanProductRelatedDetail, loanTermVariations, installmentAmountInMultiplesOf,
+ mc);
}
@NotNull
private <T> ProgressiveLoanInterestScheduleModel
generateInterestScheduleModel(@NotNull List<T> periods, Function<T, LocalDate>
from,
Function<T, LocalDate> to, @NotNull
LoanProductMinimumRepaymentScheduleRelatedDetail loanProductRelatedDetail,
- final Integer installmentAmountInMultiplesOf, final MathContext
mc) {
+ LoanTermVariationsDataWrapper loanTermVariations, final Integer
installmentAmountInMultiplesOf, final MathContext mc) {
final Money zero =
Money.zero(loanProductRelatedDetail.getCurrencyData(), mc);
final AtomicReference<RepaymentPeriod> prev = new AtomicReference<>();
List<RepaymentPeriod> repaymentPeriods = periods.stream().map(e -> {
@@ -84,7 +87,8 @@ public final class ProgressiveEMICalculator implements
EMICalculator {
prev.set(rp);
return rp;
}).toList();
- return new ProgressiveLoanInterestScheduleModel(repaymentPeriods,
loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
+ return new ProgressiveLoanInterestScheduleModel(repaymentPeriods,
loanProductRelatedDetail, loanTermVariations,
+ installmentAmountInMultiplesOf, mc);
}
@Override
@@ -310,7 +314,8 @@ public final class ProgressiveEMICalculator implements
EMICalculator {
}
calculateOutstandingBalance(scheduleModel);
calculateLastUnpaidRepaymentPeriodEMI(scheduleModel);
- if (onlyOnActualModelShouldApply) {
+ if (onlyOnActualModelShouldApply
+ && (scheduleModel.loanTermVariations() == null ||
scheduleModel.loanTermVariations().getDueDateVariation().isEmpty())) {
checkAndAdjustEmiIfNeededOnRelatedRepaymentPeriods(scheduleModel,
relatedRepaymentPeriods);
}
}
@@ -415,9 +420,9 @@ public final class ProgressiveEMICalculator implements
EMICalculator {
final ProgressiveLoanInterestScheduleModel scheduleModel) {
repaymentPeriod.getInterestPeriods().forEach(interestPeriod -> {
interestPeriod.setRateFactor(calculateRateFactorPerPeriod(scheduleModel,
repaymentPeriod, interestPeriod.getFromDate(),
- interestPeriod.getDueDate()));
+ interestPeriod.getDueDate(), false));
interestPeriod.setRateFactorTillPeriodDueDate(calculateRateFactorPerPeriod(scheduleModel,
repaymentPeriod,
- interestPeriod.getFromDate(),
repaymentPeriod.getDueDate()));
+ interestPeriod.getFromDate(),
repaymentPeriod.getDueDate(), true));
});
}
@@ -425,7 +430,8 @@ public final class ProgressiveEMICalculator implements
EMICalculator {
* Calculate Rate Factor for an exact Period
*/
private BigDecimal calculateRateFactorPerPeriod(final
ProgressiveLoanInterestScheduleModel scheduleModel,
- final RepaymentPeriod repaymentPeriod, final LocalDate
interestPeriodFromDate, final LocalDate interestPeriodDueDate) {
+ final RepaymentPeriod repaymentPeriod, final LocalDate
interestPeriodFromDate, final LocalDate interestPeriodDueDate,
+ final boolean isTillDate) {
final MathContext mc = scheduleModel.mc();
final LoanProductMinimumRepaymentScheduleRelatedDetail
loanProductRelatedDetail = scheduleModel.loanProductRelatedDetail();
final BigDecimal interestRate =
calcNominalInterestRatePercentage(scheduleModel.getInterestRate(interestPeriodFromDate),
@@ -444,6 +450,14 @@ public final class ProgressiveEMICalculator implements
EMICalculator {
final int numberOfYearsDifferenceInPeriod =
interestPeriodDueDate.getYear() - interestPeriodFromDate.getYear();
final boolean partialPeriodCalculationNeeded = daysInYearType ==
DaysInYearType.ACTUAL && numberOfYearsDifferenceInPeriod > 0;
+ long addedDays = !isTillDate || scheduleModel.loanTermVariations() ==
null ? 0L
+ :
scheduleModel.loanTermVariations().getDueDateVariation().stream()
+ .filter(x ->
!repaymentPeriod.getFromDate().isAfter(x.getTermVariationApplicableFrom())
+ &&
!repaymentPeriod.getDueDate().isBefore(x.getTermVariationApplicableFrom())
+ &&
!repaymentPeriod.getDueDate().isAfter(x.getDateValue()))
+ .map(x ->
DateUtils.getDifferenceInDays(x.getTermVariationApplicableFrom(),
x.getDateValue()))
+ .reduce(0L, Long::sum);
+
// TODO check:
loanApplicationTerms.calculatePeriodsBetweenDates(startDate, endDate); //
calculate period data
// TODO review: (repayment frequency: days, weeks, years; validation
day is month fix 30)
// TODO refactor this logic to represent in interest period
@@ -454,7 +468,7 @@ public final class ProgressiveEMICalculator implements
EMICalculator {
}
return
calculateRateFactorPerPeriodBasedOnRepaymentFrequency(interestRate,
repaymentFrequency, repaymentEvery, daysInMonth,
- daysInYear, actualDaysInPeriod, calculatedDaysInPeriod, mc);
+ daysInYear, actualDaysInPeriod,
calculatedDaysInPeriod.subtract(BigDecimal.valueOf(addedDays), mc), mc);
}
/**
diff --git
a/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanproduct/calc/ProgressiveEMICalculatorTest.java
b/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanproduct/calc/ProgressiveEMICalculatorTest.java
index edf91cd7a..852e778a6 100644
---
a/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanproduct/calc/ProgressiveEMICalculatorTest.java
+++
b/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanproduct/calc/ProgressiveEMICalculatorTest.java
@@ -32,7 +32,10 @@ import
org.apache.fineract.organisation.monetary.domain.MoneyHelper;
import org.apache.fineract.portfolio.common.domain.DaysInMonthType;
import org.apache.fineract.portfolio.common.domain.DaysInYearType;
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
+import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData;
+import
org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsDataWrapper;
import
org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
+import org.apache.fineract.portfolio.loanaccount.domain.LoanTermVariationType;
import
org.apache.fineract.portfolio.loanaccount.loanschedule.data.InterestPeriod;
import
org.apache.fineract.portfolio.loanaccount.loanschedule.data.PeriodDueDetails;
import
org.apache.fineract.portfolio.loanaccount.loanschedule.data.ProgressiveLoanInterestScheduleModel;
@@ -43,6 +46,7 @@ import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Timeout;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -60,6 +64,7 @@ class ProgressiveEMICalculatorTest {
private static MathContext mc = new MathContext(12,
RoundingMode.HALF_EVEN);
private static LoanProductMinimumRepaymentScheduleRelatedDetail
loanProductRelatedDetail = Mockito
.mock(LoanProductMinimumRepaymentScheduleRelatedDetail.class);
+ private static LoanTermVariationsDataWrapper loanTermVariations =
Mockito.mock(LoanTermVariationsDataWrapper.class);
private static final CurrencyData currency = new CurrencyData("USD",
"USD", 2, 1, "$", "USD");
@@ -82,6 +87,11 @@ class ProgressiveEMICalculatorTest {
moneyHelper.when(MoneyHelper::getMathContext).thenReturn(new
MathContext(12, RoundingMode.HALF_EVEN));
}
+ @BeforeEach
+ public void setup() {
+ Mockito.when(loanTermVariations.getDueDateVariation()).thenReturn(new
ArrayList<>());
+ }
+
@AfterAll
public static void tearDown() {
threadLocalContextUtil.close();
@@ -168,7 +178,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestScheduleModel =
emiCalculator.generatePeriodInterestScheduleModel(
- expectedRepaymentPeriods, loanProductRelatedDetail,
installmentAmountInMultiplesOf, mc);
+ expectedRepaymentPeriods, loanProductRelatedDetail,
loanTermVariations, installmentAmountInMultiplesOf, mc);
Assertions.assertTrue(interestScheduleModel != null);
Assertions.assertTrue(interestScheduleModel.loanProductRelatedDetail()
!= null);
@@ -207,7 +217,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule =
emiCalculator.generatePeriodInterestScheduleModel(
- expectedRepaymentPeriods, loanProductRelatedDetail,
installmentAmountInMultiplesOf, mc);
+ expectedRepaymentPeriods, loanProductRelatedDetail,
loanTermVariations, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1,
1), disbursedAmount);
@@ -251,7 +261,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule =
emiCalculator.generatePeriodInterestScheduleModel(
- expectedRepaymentPeriods, loanProductRelatedDetail,
installmentAmountInMultiplesOf, mc);
+ expectedRepaymentPeriods, loanProductRelatedDetail,
loanTermVariations, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1,
1), disbursedAmount);
@@ -287,7 +297,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule =
emiCalculator.generatePeriodInterestScheduleModel(
- expectedRepaymentPeriods, loanProductRelatedDetail,
installmentAmountInMultiplesOf, mc);
+ expectedRepaymentPeriods, loanProductRelatedDetail,
loanTermVariations, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1,
1), disbursedAmount);
@@ -323,7 +333,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule =
emiCalculator.generatePeriodInterestScheduleModel(
- expectedRepaymentPeriods, loanProductRelatedDetail,
installmentAmountInMultiplesOf, mc);
+ expectedRepaymentPeriods, loanProductRelatedDetail,
loanTermVariations, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1,
1), disbursedAmount);
@@ -347,42 +357,6 @@ class ProgressiveEMICalculatorTest {
checkPeriod(interestSchedule, 5, 0, 42.61, 0.007901833333, 0.33,
42.28, 0.0);
}
- @Test
- public void
test_reschedule_disbursedAmt100_dayInYears360_daysInMonth30_repayEvery1Month() {
- final List<LoanScheduleModelRepaymentPeriod> expectedRepaymentPeriods
= new ArrayList<>();
-
- expectedRepaymentPeriods.add(repayment(1, LocalDate.of(2024, 1, 1),
LocalDate.of(2024, 2, 1)));
- expectedRepaymentPeriods.add(repayment(2, LocalDate.of(2024, 2, 1),
LocalDate.of(2024, 3, 15)));
- expectedRepaymentPeriods.add(repayment(3, LocalDate.of(2024, 3, 15),
LocalDate.of(2024, 4, 15)));
- expectedRepaymentPeriods.add(repayment(4, LocalDate.of(2024, 4, 15),
LocalDate.of(2024, 5, 15)));
- expectedRepaymentPeriods.add(repayment(5, LocalDate.of(2024, 5, 15),
LocalDate.of(2024, 6, 15)));
- expectedRepaymentPeriods.add(repayment(6, LocalDate.of(2024, 6, 15),
LocalDate.of(2024, 7, 15)));
-
- final BigDecimal interestRate = BigDecimal.valueOf(9.4822);
- 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);
-
- final Money disbursedAmount = toMoney(100.0);
- emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1,
1), disbursedAmount);
-
- checkPeriod(interestSchedule, 0, 0, 17.13, 0.0, 0.0, 0.79, 16.34,
83.66);
- checkPeriod(interestSchedule, 0, 1, 17.13, 0.007901833333, 0.79,
16.34, 83.66);
- checkPeriod(interestSchedule, 1, 0, 17.13, 0.007901833333, 0.66,
16.47, 67.19);
- checkPeriod(interestSchedule, 2, 0, 17.13, 0.007901833333, 0.53,
16.60, 50.59);
- checkPeriod(interestSchedule, 3, 0, 17.13, 0.007901833333, 0.40,
16.73, 33.86);
- checkPeriod(interestSchedule, 4, 0, 17.13, 0.007901833333, 0.27,
16.86, 17.0);
- checkPeriod(interestSchedule, 5, 0, 17.13, 0.007901833333, 0.13,
17.00, 0.0);
- }
-
@Test
public void
test_reschedule_interest_on0201_4per_disbursedAmt100_dayInYears360_daysInMonth30_repayEvery1Month()
{
final List<LoanScheduleModelRepaymentPeriod> expectedRepaymentPeriods
= new ArrayList<>();
@@ -407,7 +381,7 @@ class ProgressiveEMICalculatorTest {
threadLocalContextUtil.when(ThreadLocalContextUtil::getBusinessDate).thenReturn(LocalDate.of(2024,
2, 14));
final ProgressiveLoanInterestScheduleModel interestSchedule =
emiCalculator.generatePeriodInterestScheduleModel(
- expectedRepaymentPeriods, loanProductRelatedDetail,
installmentAmountInMultiplesOf, mc);
+ expectedRepaymentPeriods, loanProductRelatedDetail,
loanTermVariations, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1,
1), disbursedAmount);
@@ -449,7 +423,7 @@ class ProgressiveEMICalculatorTest {
threadLocalContextUtil.when(ThreadLocalContextUtil::getBusinessDate).thenReturn(LocalDate.of(2024,
2, 14));
final ProgressiveLoanInterestScheduleModel interestModel =
emiCalculator.generatePeriodInterestScheduleModel(
- expectedRepaymentPeriods, loanProductRelatedDetail,
installmentAmountInMultiplesOf, mc);
+ expectedRepaymentPeriods, loanProductRelatedDetail,
loanTermVariations, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestModel, LocalDate.of(2024, 1, 1),
disbursedAmount);
@@ -496,7 +470,7 @@ class ProgressiveEMICalculatorTest {
threadLocalContextUtil.when(ThreadLocalContextUtil::getBusinessDate).thenReturn(LocalDate.of(2024,
2, 14));
final ProgressiveLoanInterestScheduleModel interestModel =
emiCalculator.generatePeriodInterestScheduleModel(
- expectedRepaymentPeriods, loanProductRelatedDetail,
installmentAmountInMultiplesOf, mc);
+ expectedRepaymentPeriods, loanProductRelatedDetail,
loanTermVariations, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestModel, LocalDate.of(2024, 1, 1),
disbursedAmount);
@@ -542,7 +516,7 @@ class ProgressiveEMICalculatorTest {
threadLocalContextUtil.when(ThreadLocalContextUtil::getBusinessDate).thenReturn(LocalDate.of(2024,
2, 14));
final ProgressiveLoanInterestScheduleModel interestSchedule =
emiCalculator.generatePeriodInterestScheduleModel(
- expectedRepaymentPeriods, loanProductRelatedDetail,
installmentAmountInMultiplesOf, mc);
+ expectedRepaymentPeriods, loanProductRelatedDetail,
loanTermVariations, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1,
1), disbursedAmount);
@@ -588,7 +562,7 @@ class ProgressiveEMICalculatorTest {
threadLocalContextUtil.when(ThreadLocalContextUtil::getBusinessDate).thenReturn(LocalDate.of(2024,
2, 15));
final ProgressiveLoanInterestScheduleModel interestSchedule =
emiCalculator.generatePeriodInterestScheduleModel(
- expectedRepaymentPeriods, loanProductRelatedDetail,
installmentAmountInMultiplesOf, mc);
+ expectedRepaymentPeriods, loanProductRelatedDetail,
loanTermVariations, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1,
1), disbursedAmount);
@@ -695,7 +669,7 @@ class ProgressiveEMICalculatorTest {
threadLocalContextUtil.when(ThreadLocalContextUtil::getBusinessDate).thenReturn(LocalDate.of(2024,
2, 15));
final ProgressiveLoanInterestScheduleModel interestSchedule =
emiCalculator.generatePeriodInterestScheduleModel(
- expectedRepaymentPeriods, loanProductRelatedDetail,
installmentAmountInMultiplesOf, mc);
+ expectedRepaymentPeriods, loanProductRelatedDetail,
loanTermVariations, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1,
1), disbursedAmount);
@@ -766,7 +740,7 @@ class ProgressiveEMICalculatorTest {
threadLocalContextUtil.when(ThreadLocalContextUtil::getBusinessDate).thenReturn(LocalDate.of(2024,
2, 15));
final ProgressiveLoanInterestScheduleModel interestSchedule =
emiCalculator.generatePeriodInterestScheduleModel(
- expectedRepaymentPeriods, loanProductRelatedDetail,
installmentAmountInMultiplesOf, mc);
+ expectedRepaymentPeriods, loanProductRelatedDetail,
loanTermVariations, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1,
1), disbursedAmount);
@@ -843,7 +817,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule =
emiCalculator.generatePeriodInterestScheduleModel(
- expectedRepaymentPeriods, loanProductRelatedDetail,
installmentAmountInMultiplesOf, mc);
+ expectedRepaymentPeriods, loanProductRelatedDetail,
loanTermVariations, installmentAmountInMultiplesOf, mc);
Money disbursedAmount = toMoney(100);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1,
1), disbursedAmount);
@@ -892,7 +866,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule =
emiCalculator.generatePeriodInterestScheduleModel(
- expectedRepaymentPeriods, loanProductRelatedDetail,
installmentAmountInMultiplesOf, mc);
+ expectedRepaymentPeriods, loanProductRelatedDetail,
loanTermVariations, installmentAmountInMultiplesOf, mc);
Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1,
1), disbursedAmount);
@@ -941,7 +915,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule =
emiCalculator.generatePeriodInterestScheduleModel(
- expectedRepaymentPeriods, loanProductRelatedDetail,
installmentAmountInMultiplesOf, mc);
+ expectedRepaymentPeriods, loanProductRelatedDetail,
loanTermVariations, installmentAmountInMultiplesOf, mc);
Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1,
5), disbursedAmount);
@@ -987,7 +961,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule =
emiCalculator.generatePeriodInterestScheduleModel(
- expectedRepaymentPeriods, loanProductRelatedDetail,
installmentAmountInMultiplesOf, mc);
+ expectedRepaymentPeriods, loanProductRelatedDetail,
loanTermVariations, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2023, 12,
12), disbursedAmount);
@@ -1023,7 +997,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule =
emiCalculator.generatePeriodInterestScheduleModel(
- expectedRepaymentPeriods, loanProductRelatedDetail,
installmentAmountInMultiplesOf, mc);
+ expectedRepaymentPeriods, loanProductRelatedDetail,
loanTermVariations, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1,
1), toMoney(300.0));
Assertions.assertEquals(6.15,
toDouble(interestSchedule.getTotalDueInterest()));
@@ -1065,7 +1039,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule =
emiCalculator.generatePeriodInterestScheduleModel(
- expectedRepaymentPeriods, loanProductRelatedDetail,
installmentAmountInMultiplesOf, mc);
+ expectedRepaymentPeriods, loanProductRelatedDetail,
loanTermVariations, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(1000.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1,
1), disbursedAmount);
@@ -1098,7 +1072,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule =
emiCalculator.generatePeriodInterestScheduleModel(
- expectedRepaymentPeriods, loanProductRelatedDetail,
installmentAmountInMultiplesOf, mc);
+ expectedRepaymentPeriods, loanProductRelatedDetail,
loanTermVariations, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1,
1), disbursedAmount);
@@ -1131,7 +1105,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule =
emiCalculator.generatePeriodInterestScheduleModel(
- expectedRepaymentPeriods, loanProductRelatedDetail,
installmentAmountInMultiplesOf, mc);
+ expectedRepaymentPeriods, loanProductRelatedDetail,
loanTermVariations, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1,
1), disbursedAmount);
@@ -1164,7 +1138,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule =
emiCalculator.generatePeriodInterestScheduleModel(
- expectedRepaymentPeriods, loanProductRelatedDetail,
installmentAmountInMultiplesOf, mc);
+ expectedRepaymentPeriods, loanProductRelatedDetail,
loanTermVariations, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1,
1), disbursedAmount);
@@ -1206,7 +1180,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule =
emiCalculator.generatePeriodInterestScheduleModel(
- expectedRepaymentPeriods, loanProductRelatedDetail,
installmentAmountInMultiplesOf, mc);
+ expectedRepaymentPeriods, loanProductRelatedDetail,
loanTermVariations, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(1000.0);
LocalDate disbursementDate = LocalDate.of(2024, 1, 1);
@@ -1254,7 +1228,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestModel =
emiCalculator.generatePeriodInterestScheduleModel(
- expectedRepaymentPeriods, loanProductRelatedDetail,
installmentAmountInMultiplesOf, mc);
+ expectedRepaymentPeriods, loanProductRelatedDetail,
loanTermVariations, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(1000.0);
emiCalculator.addDisbursement(interestModel, LocalDate.of(2024, 1, 1),
disbursedAmount);
@@ -1316,7 +1290,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestModel =
emiCalculator.generatePeriodInterestScheduleModel(
- expectedRepaymentPeriods, loanProductRelatedDetail,
installmentAmountInMultiplesOf, mc);
+ expectedRepaymentPeriods, loanProductRelatedDetail,
loanTermVariations, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount1st = toMoney(1000.0);
final Money disbursedAmount2nd = toMoney(1000.0);
@@ -1368,6 +1342,126 @@ class ProgressiveEMICalculatorTest {
checkDailyInterest(interestModel, dueDate, startDay, 31, 0.38, 9.03);
}
+ @Test
+ public void
test_reschedule_disbursedAmt100_dayInYears360_daysInMonth30_repayEvery1Month() {
+ final List<LoanScheduleModelRepaymentPeriod> expectedRepaymentPeriods
= List.of(
+ repayment(1, LocalDate.of(2024, 1, 1), LocalDate.of(2024, 3,
1)),
+ repayment(2, LocalDate.of(2024, 3, 1), LocalDate.of(2024, 4,
1)),
+ repayment(3, LocalDate.of(2024, 4, 1), LocalDate.of(2024, 5,
1)),
+ repayment(4, LocalDate.of(2024, 5, 1), LocalDate.of(2024, 6,
1)),
+ repayment(5, LocalDate.of(2024, 6, 1), LocalDate.of(2024, 7,
1)),
+ repayment(6, LocalDate.of(2024, 7, 1), LocalDate.of(2024, 8,
1)));
+
+ final BigDecimal interestRate = BigDecimal.valueOf(7);
+ 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);
+ Mockito.when(loanTermVariations.getDueDateVariation()).thenReturn(new
ArrayList<>(List.of(//
+ new LoanTermVariationsData(1L,
LoanTermVariationType.DUE_DATE.getValue(), //
+ LocalDate.of(2024, 2, 1), null, //
+ LocalDate.of(2024, 3, 1), false))));
+
+ final ProgressiveLoanInterestScheduleModel interestSchedule =
emiCalculator.generatePeriodInterestScheduleModel(
+ expectedRepaymentPeriods, loanProductRelatedDetail,
loanTermVariations, installmentAmountInMultiplesOf, mc);
+
+ final Money disbursedAmount = toMoney(100.0);
+ emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1,
1), disbursedAmount);
+
+ checkPeriod(interestSchedule, 0, 0, 17.01, 0.0, 0.0, 1.13, 15.88,
84.12);
+ checkPeriod(interestSchedule, 0, 1, 17.01, 0.005833333333, 1.13,
15.88, 84.12);
+ checkPeriod(interestSchedule, 1, 0, 17.01, 0.005833333333, 0.49,
16.52, 67.60);
+ checkPeriod(interestSchedule, 2, 0, 17.01, 0.005833333333, 0.39,
16.62, 50.98);
+ checkPeriod(interestSchedule, 3, 0, 17.01, 0.005833333333, 0.30,
16.71, 34.27);
+ checkPeriod(interestSchedule, 4, 0, 17.01, 0.005833333333, 0.20,
16.81, 17.46);
+ checkPeriod(interestSchedule, 5, 0, 17.56, 0.005833333333, 0.10,
17.46, 0.0);
+ }
+
+ @Test
+ public void
test_two_reschedules_disbursedAmt100_dayInYears360_daysInMonth30_repayEvery1Month()
{
+ final List<LoanScheduleModelRepaymentPeriod> expectedRepaymentPeriods
= List.of(
+ repayment(1, LocalDate.of(2024, 1, 1), LocalDate.of(2024, 3,
1)),
+ repayment(2, LocalDate.of(2024, 3, 1), LocalDate.of(2024, 4,
1)),
+ repayment(3, LocalDate.of(2024, 4, 1), LocalDate.of(2024, 6,
1)),
+ repayment(4, LocalDate.of(2024, 6, 1), LocalDate.of(2024, 7,
1)),
+ repayment(5, LocalDate.of(2024, 7, 1), LocalDate.of(2024, 8,
1)),
+ repayment(6, LocalDate.of(2024, 8, 1), LocalDate.of(2024, 9,
1)));
+
+ final BigDecimal interestRate = BigDecimal.valueOf(7);
+ 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);
+ Mockito.when(loanTermVariations.getDueDateVariation()).thenReturn(new
ArrayList<>(List.of(//
+ new LoanTermVariationsData(1L,
LoanTermVariationType.DUE_DATE.getValue(), //
+ LocalDate.of(2024, 2, 1), null, //
+ LocalDate.of(2024, 3, 1), false), //
+ new LoanTermVariationsData(2L,
LoanTermVariationType.DUE_DATE.getValue(), //
+ LocalDate.of(2024, 5, 1), null, //
+ LocalDate.of(2024, 6, 1), false))));
+
+ final ProgressiveLoanInterestScheduleModel interestSchedule =
emiCalculator.generatePeriodInterestScheduleModel(
+ expectedRepaymentPeriods, loanProductRelatedDetail,
loanTermVariations, installmentAmountInMultiplesOf, mc);
+
+ final Money disbursedAmount = toMoney(100.0);
+ emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1,
1), disbursedAmount);
+
+ checkPeriod(interestSchedule, 0, 0, 17.01, 0.0, 0.0, 1.13, 15.88,
84.12);
+ checkPeriod(interestSchedule, 0, 1, 17.01, 0.005833333333, 1.13,
15.88, 84.12);
+ checkPeriod(interestSchedule, 1, 0, 17.01, 0.005833333333, 0.49,
16.52, 67.60);
+ checkPeriod(interestSchedule, 2, 0, 17.01, 0.005833333333, 0.80,
16.21, 51.39);
+ checkPeriod(interestSchedule, 3, 0, 17.01, 0.005833333333, 0.30,
16.71, 34.68);
+ checkPeriod(interestSchedule, 4, 0, 17.01, 0.005833333333, 0.20,
16.81, 17.87);
+ checkPeriod(interestSchedule, 5, 0, 17.97, 0.005833333333, 0.10,
17.87, 0.0);
+ }
+
+ @Test
+ public void
test_reschedule_partial_period_disbursedAmt100_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, 4,
15)),
+ repayment(3, LocalDate.of(2024, 4, 15), LocalDate.of(2024, 5,
15)),
+ repayment(4, LocalDate.of(2024, 5, 15), LocalDate.of(2024, 6,
15)),
+ repayment(5, LocalDate.of(2024, 6, 15), LocalDate.of(2024, 7,
15)),
+ repayment(6, LocalDate.of(2024, 7, 15), LocalDate.of(2024, 8,
15)));
+
+ final BigDecimal interestRate = BigDecimal.valueOf(7);
+ 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);
+ Mockito.when(loanTermVariations.getDueDateVariation()).thenReturn(new
ArrayList<>(List.of(//
+ new LoanTermVariationsData(1L,
LoanTermVariationType.DUE_DATE.getValue(), //
+ LocalDate.of(2024, 3, 1), null, //
+ LocalDate.of(2024, 4, 15), false))));
+
+ final ProgressiveLoanInterestScheduleModel interestSchedule =
emiCalculator.generatePeriodInterestScheduleModel(
+ expectedRepaymentPeriods, loanProductRelatedDetail,
loanTermVariations, installmentAmountInMultiplesOf, mc);
+
+ final Money disbursedAmount = toMoney(100.0);
+ emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1,
1), disbursedAmount);
+
+ checkPeriod(interestSchedule, 0, 0, 17.01, 0.0, 0.0, 0.58, 16.43,
83.57);
+ checkPeriod(interestSchedule, 0, 1, 17.01, 0.005833333333, 0.58,
16.43, 83.57);
+ checkPeriod(interestSchedule, 1, 0, 17.01, 0.005833333333, 1.24,
15.77, 67.80);
+ checkPeriod(interestSchedule, 2, 0, 17.01, 0.005833333333, 0.40,
16.61, 51.19);
+ checkPeriod(interestSchedule, 3, 0, 17.01, 0.005833333333, 0.30,
16.71, 34.48);
+ checkPeriod(interestSchedule, 4, 0, 17.01, 0.005833333333, 0.20,
16.81, 17.67);
+ checkPeriod(interestSchedule, 5, 0, 17.77, 0.005833333333, 0.10,
17.67, 0.0);
+ }
+
private static LoanScheduleModelRepaymentPeriod repayment(int
periodNumber, LocalDate fromDate, LocalDate dueDate) {
final Money zeroAmount = Money.zero(currency);
return LoanScheduleModelRepaymentPeriod.repayment(periodNumber,
fromDate, dueDate, zeroAmount, zeroAmount, zeroAmount, zeroAmount,