From ff21304cacb70b837436a557e1e164942f591de6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Soma=20S=C3=B6r=C3=B6s?= Date: Thu, 13 Feb 2025 11:26:37 +0100 Subject: [PATCH] FINERACT-2174: Calculate fraction period - In case `interestRecognitionFromDisbursementDate` is true, we need to include from date and exclude due date --- .../domain/LoanApplicationTerms.java | 14 ++- .../LoanRepaymentScheduleModelData.java | 13 +- .../LoanProductRelatedDetailMinimumData.java | 9 +- ...MinimumRepaymentScheduleRelatedDetail.java | 2 + .../misc/Main.java | 3 +- ...eProgressiveLoanScheduleGeneratorTest.java | 3 +- .../calc/ProgressiveEMICalculator.java | 36 ++++-- .../domain/LoanScheduleGeneratorTest.java | 4 +- .../calc/ProgressiveEMICalculatorTest.java | 111 ++++++++++++++++++ 9 files changed, 179 insertions(+), 16 deletions(-) diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java index 7dde2c14b..f4aaa9108 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java @@ -254,6 +254,8 @@ public final class LoanApplicationTerms { this.seedDate = builder.seedDate; this.isDownPaymentEnabled = builder.isDownPaymentEnabled; this.disbursedAmountPercentageForDownPayment = builder.downPaymentPercentage; + this.interestRecognitionOnDisbursementDate = builder.interestRecognitionOnDisbursementDate != null + && builder.interestRecognitionOnDisbursementDate; if (isDownPaymentEnabled) { this.downPaymentAmount = Money.of(getCurrency(), MathUtil.percentageOf(getPrincipal().getAmount(), getDisbursedAmountPercentageForDownPayment(), builder.mc), @@ -291,6 +293,7 @@ public final class LoanApplicationTerms { private LocalDate submittedOnDate; private LocalDate seedDate; private MathContext mc; + private Boolean interestRecognitionOnDisbursementDate; public Builder currency(CurrencyData currency) { this.currency = currency; @@ -402,6 +405,11 @@ public final class LoanApplicationTerms { return this; } + public Builder interestRecognitionOnDisbursementDate(boolean value) { + this.interestRecognitionOnDisbursementDate = value; + return this; + } + public LoanApplicationTerms build() { return new LoanApplicationTerms(this); } @@ -430,7 +438,8 @@ public final class LoanApplicationTerms { .daysInMonthType(modelData.daysInMonth()).daysInYearType(modelData.daysInYear()).fixedLength(modelData.fixedLength()) .inArrearsTolerance(Money.zero(modelData.currency(), mc)).disbursementDatas(new ArrayList<>()) .isDownPaymentEnabled(modelData.downPaymentEnabled()).downPaymentPercentage(downPaymentPercentage) - .submittedOnDate(modelData.scheduleGenerationStartDate()).seedDate(seedDate).mc(mc).build(); + .submittedOnDate(modelData.scheduleGenerationStartDate()).seedDate(seedDate) + .interestRecognitionOnDisbursementDate(modelData.interestRecognitionOnDisbursementDate()).mc(mc).build(); } public static LoanApplicationTerms assembleFrom(final CurrencyData currency, final Integer loanTermFrequency, @@ -1557,7 +1566,8 @@ public final class LoanApplicationTerms { return new LoanProductRelatedDetailMinimumData(currency, interestRatePerPeriod, annualNominalInterestRate, interestChargingGrace, interestPaymentGrace, principalGrace, recurringMoratoriumOnPrincipalPeriods, interestMethod, interestCalculationPeriodMethod, daysInYearType, daysInMonthType, amortizationMethod, repaymentPeriodFrequencyType, - repaymentEvery, numberOfRepayments); + repaymentEvery, numberOfRepayments, + isInterestChargedFromDateSameAsDisbursalDateEnabled != null && isInterestChargedFromDateSameAsDisbursalDateEnabled); } public Integer getLoanTermFrequency() { diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanRepaymentScheduleModelData.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanRepaymentScheduleModelData.java index 3a1894d30..ec6f11b6d 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanRepaymentScheduleModelData.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanRepaymentScheduleModelData.java @@ -30,5 +30,16 @@ public record LoanRepaymentScheduleModelData(@NotNull LocalDate scheduleGenerati @NotNull BigDecimal disbursementAmount, @NotNull LocalDate disbursementDate, @NotNull int numberOfRepayments, @NotNull int repaymentFrequency, @NotBlank String repaymentFrequencyType, @NotNull BigDecimal annualNominalInterestRate, @NotNull boolean downPaymentEnabled, @NotNull DaysInMonthType daysInMonth, @NotNull DaysInYearType daysInYear, - BigDecimal downPaymentPercentage, Integer installmentAmountInMultiplesOf, Integer fixedLength) { + BigDecimal downPaymentPercentage, Integer installmentAmountInMultiplesOf, Integer fixedLength, + @NotNull Boolean interestRecognitionOnDisbursementDate) { + + LoanRepaymentScheduleModelData(@NotNull LocalDate scheduleGenerationStartDate, @NotNull CurrencyData currency, + @NotNull BigDecimal disbursementAmount, @NotNull LocalDate disbursementDate, @NotNull int numberOfRepayments, + @NotNull int repaymentFrequency, @NotBlank String repaymentFrequencyType, @NotNull BigDecimal annualNominalInterestRate, + @NotNull boolean downPaymentEnabled, @NotNull DaysInMonthType daysInMonth, @NotNull DaysInYearType daysInYear, + BigDecimal downPaymentPercentage, Integer installmentAmountInMultiplesOf, Integer fixedLength) { + this(scheduleGenerationStartDate, currency, disbursementAmount, disbursementDate, numberOfRepayments, repaymentFrequency, + repaymentFrequencyType, annualNominalInterestRate, downPaymentEnabled, daysInMonth, daysInYear, downPaymentPercentage, + installmentAmountInMultiplesOf, fixedLength, false); + } } diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/data/LoanProductRelatedDetailMinimumData.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/data/LoanProductRelatedDetailMinimumData.java index 5e2b80115..3ff587d6c 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/data/LoanProductRelatedDetailMinimumData.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/data/LoanProductRelatedDetailMinimumData.java @@ -45,13 +45,14 @@ public class LoanProductRelatedDetailMinimumData implements LoanProductMinimumRe private final PeriodFrequencyType repaymentPeriodFrequencyType; private final Integer repaymentEvery; private final Integer numberOfRepayments; + private final boolean interestRecognitionOnDisbursementDate; public LoanProductRelatedDetailMinimumData(CurrencyData currency, BigDecimal interestRatePerPeriod, BigDecimal annualNominalInterestRate, Integer interestChargingGrace, Integer interestPaymentGrace, Integer principalGrace, Integer recurringMoratoriumOnPrincipalPeriods, InterestMethod interestMethod, InterestCalculationPeriodMethod interestCalculationPeriodMethod, DaysInYearType daysInYearType, DaysInMonthType daysInMonthType, AmortizationMethod amortizationMethod, PeriodFrequencyType repaymentPeriodFrequencyType, Integer repaymentEvery, - Integer numberOfRepayments) { + Integer numberOfRepayments, boolean interestRecognitionOnDisbursementDate) { this.currency = currency; this.interestRatePerPeriod = interestRatePerPeriod; this.annualNominalInterestRate = annualNominalInterestRate; @@ -67,6 +68,7 @@ public class LoanProductRelatedDetailMinimumData implements LoanProductMinimumRe this.repaymentPeriodFrequencyType = repaymentPeriodFrequencyType; this.repaymentEvery = repaymentEvery; this.numberOfRepayments = numberOfRepayments; + this.interestRecognitionOnDisbursementDate = interestRecognitionOnDisbursementDate; } private Integer defaultToNullIfZero(final Integer value) { @@ -161,4 +163,9 @@ public class LoanProductRelatedDetailMinimumData implements LoanProductMinimumRe public Integer getDaysInYearType() { return daysInYearType.getValue(); } + + @Override + public boolean isInterestRecognitionOnDisbursementDate() { + return interestRecognitionOnDisbursementDate; + } } diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProductMinimumRepaymentScheduleRelatedDetail.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProductMinimumRepaymentScheduleRelatedDetail.java index 0509405a5..8fddc4a92 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProductMinimumRepaymentScheduleRelatedDetail.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProductMinimumRepaymentScheduleRelatedDetail.java @@ -60,4 +60,6 @@ public interface LoanProductMinimumRepaymentScheduleRelatedDetail { Integer getDaysInMonthType(); Integer getDaysInYearType(); + + boolean isInterestRecognitionOnDisbursementDate(); } diff --git a/fineract-progressive-loan-embeddable-schedule-generator/misc/Main.java b/fineract-progressive-loan-embeddable-schedule-generator/misc/Main.java index 1cca7c5a9..7b3641326 100644 --- a/fineract-progressive-loan-embeddable-schedule-generator/misc/Main.java +++ b/fineract-progressive-loan-embeddable-schedule-generator/misc/Main.java @@ -55,8 +55,9 @@ public class Main { final DaysInYearType daysInYearType = DaysInYearType.DAYS_360; final Integer installmentAmountInMultiplesOf = null; final Integer fixedLength = null; + final Boolean interestRecognitionOnDisbursementDate = false; - var config = new LoanRepaymentScheduleModelData(startDate, currency, disbursedAmount, disbursementDate, noRepayments, repaymentFrequency, repaymentFrequencyType, annualNominalInterestRate, isDownPaymentEnabled, daysInMonthType, daysInYearType, downPaymentPercentage, installmentAmountInMultiplesOf, fixedLength); + var config = new LoanRepaymentScheduleModelData(startDate, currency, disbursedAmount, disbursementDate, noRepayments, repaymentFrequency, repaymentFrequencyType, annualNominalInterestRate, isDownPaymentEnabled, daysInMonthType, daysInYearType, downPaymentPercentage, installmentAmountInMultiplesOf, fixedLength, interestRecognitionOnDisbursementDate); final LoanSchedulePlan plan = calculator.generate(mc, config); printPlan(plan); diff --git a/fineract-progressive-loan-embeddable-schedule-generator/src/test/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/EmbeddableProgressiveLoanScheduleGeneratorTest.java b/fineract-progressive-loan-embeddable-schedule-generator/src/test/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/EmbeddableProgressiveLoanScheduleGeneratorTest.java index 69a9803e3..f6b74ffcd 100644 --- a/fineract-progressive-loan-embeddable-schedule-generator/src/test/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/EmbeddableProgressiveLoanScheduleGeneratorTest.java +++ b/fineract-progressive-loan-embeddable-schedule-generator/src/test/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/EmbeddableProgressiveLoanScheduleGeneratorTest.java @@ -54,10 +54,11 @@ class EmbeddableProgressiveLoanScheduleGeneratorTest { final DaysInYearType daysInYearType = DaysInYearType.DAYS_360; final Integer installmentAmountInMultiplesOf = null; final Integer fixedLength = null; + final Boolean interestRecognitionOnDisbursementDate = false; var config = new LoanRepaymentScheduleModelData(startDate, currency, disbursedAmount, disbursementDate, noRepayments, repaymentFrequency, repaymentFrequencyType, annualNominalInterestRate, isDownPaymentEnabled, daysInMonthType, - daysInYearType, downPaymentPercentage, installmentAmountInMultiplesOf, fixedLength); + daysInYearType, downPaymentPercentage, installmentAmountInMultiplesOf, fixedLength, interestRecognitionOnDisbursementDate); final LoanSchedulePlan plan = calculator.generate(mc, config); 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 aa27a757b..bc2104758 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 @@ -511,7 +511,8 @@ public final class ProgressiveEMICalculator implements EMICalculator { // TODO review: (repayment frequency: days, weeks, years; validation day is month fix 30) // TODO refactor this logic to represent in interest period if (partialPeriodCalculationNeeded) { - final BigDecimal cumulatedPeriodFractions = calculatePeriodFractions(interestPeriodFromDate, interestPeriodDueDate, mc); + final BigDecimal cumulatedPeriodFractions = calculatePeriodFractions(scheduleModel, interestPeriodFromDate, + interestPeriodDueDate, mc); return rateFactorByRepaymentPartialPeriod(interestRate, BigDecimal.ONE, cumulatedPeriodFractions, BigDecimal.ONE, BigDecimal.ONE, mc); } @@ -623,7 +624,8 @@ public final class ProgressiveEMICalculator implements EMICalculator { // TODO review: (repayment frequency: days, weeks, years; validation day is month fix 30) // TODO refactor this logic to represent in interest period if (partialPeriodCalculationNeeded) { - final BigDecimal cumulatedPeriodFractions = calculatePeriodFractions(interestPeriodFromDate, interestPeriodDueDate, mc); + final BigDecimal cumulatedPeriodFractions = calculatePeriodFractions(scheduleModel, interestPeriodFromDate, + interestPeriodDueDate, mc); return rateFactorByRepaymentPartialPeriod(interestRate, BigDecimal.ONE, cumulatedPeriodFractions, BigDecimal.ONE, BigDecimal.ONE, mc); } @@ -640,29 +642,47 @@ public final class ProgressiveEMICalculator implements EMICalculator { /** * Calculate Period fractions part based on how much year has in the period * + * @param scheduleModel * @param interestPeriodFromDate * @param interestPeriodDueDate * @return */ - private BigDecimal calculatePeriodFractions(final LocalDate interestPeriodFromDate, final LocalDate interestPeriodDueDate, - MathContext mc) { + public BigDecimal calculatePeriodFractions(ProgressiveLoanInterestScheduleModel scheduleModel, final LocalDate interestPeriodFromDate, + final LocalDate interestPeriodDueDate, MathContext mc) { BigDecimal cumulatedRateFactor = BigDecimal.ZERO; int actualYear = interestPeriodFromDate.getYear(); int endYear = interestPeriodDueDate.getYear(); LocalDate actualDate = interestPeriodFromDate; - LocalDate endOfActualYear; + LocalDate fractionPeriodDueDate; while (actualYear <= endYear) { - endOfActualYear = actualYear == endYear ? interestPeriodDueDate : LocalDate.of(actualYear, 12, 31); + fractionPeriodDueDate = actualYear == endYear ? interestPeriodDueDate + : getFractionPeriodDueDateForEndOfYear(scheduleModel, actualYear); BigDecimal numberOfDaysInYear = BigDecimal.valueOf(Year.of(actualYear).length()); - BigDecimal calculatedDaysInActualYear = BigDecimal.valueOf(DateUtils.getDifferenceInDays(actualDate, endOfActualYear)); + BigDecimal calculatedDaysInActualYear = BigDecimal.valueOf(DateUtils.getDifferenceInDays(actualDate, fractionPeriodDueDate)); cumulatedRateFactor = cumulatedRateFactor.add(calculatedDaysInActualYear.divide(numberOfDaysInYear, mc), mc); - actualDate = endOfActualYear; + actualDate = fractionPeriodDueDate; actualYear++; } return cumulatedRateFactor; } + /** + * Determines the last date of the year for interest calculation depending on the + * isInterestRecognitionOnDisbursementDate flag. + * + * @param scheduleModel + * @param year + * @return + */ + private LocalDate getFractionPeriodDueDateForEndOfYear(ProgressiveLoanInterestScheduleModel scheduleModel, int year) { + if (scheduleModel.loanProductRelatedDetail().isInterestRecognitionOnDisbursementDate()) { + return LocalDate.of(year + 1, 1, 1); + } else { + return LocalDate.of(year, 12, 31); + } + } + /** * Calculate Rate Factor based on Repayment Frequency Type * diff --git a/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleGeneratorTest.java b/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleGeneratorTest.java index 4a19f2fa8..2e3c1a8a4 100644 --- a/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleGeneratorTest.java +++ b/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleGeneratorTest.java @@ -54,7 +54,7 @@ class LoanScheduleGeneratorTest { void testGenerateLoanSchedule() { LoanRepaymentScheduleModelData modelData = new LoanRepaymentScheduleModelData(LocalDate.of(2024, 1, 1), CURRENCY, DISBURSEMENT_AMOUNT, DISBURSEMENT_DATE, NUMBER_OF_REPAYMENTS, REPAYMENT_FREQUENCY, REPAYMENT_FREQUENCY_TYPE, - NOMINAL_INTEREST_RATE, false, DaysInMonthType.DAYS_30, DaysInYearType.DAYS_360, null, null, null); + NOMINAL_INTEREST_RATE, false, DaysInMonthType.DAYS_30, DaysInYearType.DAYS_360, null, null, null, false); ScheduledDateGenerator scheduledDateGenerator = new DefaultScheduledDateGenerator(); ProgressiveLoanScheduleGenerator generator = new ProgressiveLoanScheduleGenerator(scheduledDateGenerator, emiCalculator); @@ -89,7 +89,7 @@ class LoanScheduleGeneratorTest { void testGenerateLoanScheduleWithDownPayment() { LoanRepaymentScheduleModelData modelData = new LoanRepaymentScheduleModelData(LocalDate.of(2024, 1, 1), CURRENCY, DISBURSEMENT_AMOUNT_100, LocalDate.of(2024, 1, 1), NUMBER_OF_REPAYMENTS, REPAYMENT_FREQUENCY, REPAYMENT_FREQUENCY_TYPE, - NOMINAL_INTEREST_RATE, true, DaysInMonthType.DAYS_30, DaysInYearType.DAYS_360, DOWN_PAYMENT_PORTION, null, null); + NOMINAL_INTEREST_RATE, true, DaysInMonthType.DAYS_30, DaysInYearType.DAYS_360, DOWN_PAYMENT_PORTION, null, null, false); ScheduledDateGenerator scheduledDateGenerator = new DefaultScheduledDateGenerator(); ProgressiveLoanScheduleGenerator generator = new ProgressiveLoanScheduleGenerator(scheduledDateGenerator, emiCalculator); 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 e3ccfa56f..9a40cc386 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 @@ -208,6 +208,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); @@ -252,6 +253,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); @@ -288,6 +290,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); @@ -324,6 +327,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); @@ -370,6 +374,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); threadLocalContextUtil.when(ThreadLocalContextUtil::getBusinessDate).thenReturn(LocalDate.of(2024, 2, 14)); @@ -412,6 +417,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); threadLocalContextUtil.when(ThreadLocalContextUtil::getBusinessDate).thenReturn(LocalDate.of(2024, 2, 14)); @@ -459,6 +465,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); threadLocalContextUtil.when(ThreadLocalContextUtil::getBusinessDate).thenReturn(LocalDate.of(2024, 2, 14)); @@ -505,6 +512,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); threadLocalContextUtil.when(ThreadLocalContextUtil::getBusinessDate).thenReturn(LocalDate.of(2024, 2, 14)); @@ -551,6 +559,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); threadLocalContextUtil.when(ThreadLocalContextUtil::getBusinessDate).thenReturn(LocalDate.of(2024, 2, 15)); @@ -658,6 +667,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); threadLocalContextUtil.when(ThreadLocalContextUtil::getBusinessDate).thenReturn(LocalDate.of(2024, 2, 15)); @@ -729,6 +739,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); threadLocalContextUtil.when(ThreadLocalContextUtil::getBusinessDate).thenReturn(LocalDate.of(2024, 2, 15)); @@ -808,6 +819,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); @@ -857,6 +869,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); @@ -906,6 +919,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); @@ -952,6 +966,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); @@ -988,6 +1003,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); @@ -1030,6 +1046,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); @@ -1063,6 +1080,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.WEEKS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); @@ -1096,6 +1114,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.WEEKS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(2); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); @@ -1129,6 +1148,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.DAYS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(15); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); @@ -1171,6 +1191,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); @@ -1219,6 +1240,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); final ProgressiveLoanInterestScheduleModel interestModel = emiCalculator.generatePeriodInterestScheduleModel( expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); @@ -1348,6 +1370,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); final ProgressiveLoanInterestScheduleModel interestModel = emiCalculator.generatePeriodInterestScheduleModel( expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); @@ -1421,6 +1444,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); @@ -1459,6 +1483,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); @@ -1497,6 +1522,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); List loanTermVariations = new ArrayList<>(); final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( @@ -1536,6 +1562,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); List loanTermVariations = new ArrayList<>(); final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( @@ -1575,6 +1602,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); List loanTermVariations = new ArrayList<>(); final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( @@ -1614,6 +1642,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); List loanTermVariations = new ArrayList<>(); final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( @@ -1653,6 +1682,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); List loanTermVariations = new ArrayList<>(); final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( @@ -1695,6 +1725,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); List loanTermVariations = new ArrayList<>(); final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( @@ -1740,6 +1771,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); List loanTermVariations = new ArrayList<>(); final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( @@ -1781,6 +1813,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); List loanTermVariations = new ArrayList<>(); final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( @@ -1819,6 +1852,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); List loanTermVariationsData = List.of(// new LoanTermVariationsData(1L, LoanTermVariationType.DUE_DATE.getValue(), // LocalDate.of(2024, 2, 1), null, // @@ -1858,6 +1892,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); List loanTermVariationsData = List.of(// new LoanTermVariationsData(1L, LoanTermVariationType.DUE_DATE.getValue(), // LocalDate.of(2024, 2, 1), null, // @@ -1900,6 +1935,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); List loanTermVariationsData = List.of(// new LoanTermVariationsData(1L, LoanTermVariationType.DUE_DATE.getValue(), // LocalDate.of(2024, 3, 1), null, // @@ -1940,6 +1976,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); @@ -1989,6 +2026,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); @@ -2033,6 +2071,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); @@ -2082,6 +2121,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); @@ -2119,6 +2159,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); @@ -2156,6 +2197,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(2); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); @@ -2193,6 +2235,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); @@ -2230,6 +2273,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); @@ -2267,6 +2311,7 @@ class ProgressiveEMICalculatorTest { Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); @@ -2284,6 +2329,72 @@ class ProgressiveEMICalculatorTest { checkPeriod(interestSchedule, 5, 867.65, 10.03, 857.62, 0.00, false); } + @Test + public void test_actual_actual_fraction_period_calculation_with_interestRecognitionFromDisbursementDate_false() { + MathContext mc = new MathContext(12, RoundingMode.HALF_UP); + final List expectedRepaymentPeriods = List.of( + repayment(1, LocalDate.of(2023, 11, 13), LocalDate.of(2023, 12, 13)), + repayment(2, LocalDate.of(2023, 12, 13), LocalDate.of(2024, 1, 13)), + repayment(3, LocalDate.of(2024, 1, 13), LocalDate.of(2024, 2, 13)), + repayment(4, LocalDate.of(2024, 2, 13), LocalDate.of(2024, 3, 13)), + repayment(5, LocalDate.of(2024, 3, 13), LocalDate.of(2024, 4, 13)), + repayment(6, LocalDate.of(2024, 4, 13), LocalDate.of(2024, 5, 13))); + + final BigDecimal interestRate = BigDecimal.valueOf(9.99); + + Mockito.when(loanProductRelatedDetail.getAnnualNominalInterestRate()).thenReturn(interestRate); + Mockito.when(loanProductRelatedDetail.getDaysInYearType()).thenReturn(DaysInYearType.ACTUAL.getValue()); + Mockito.when(loanProductRelatedDetail.getDaysInMonthType()).thenReturn(DaysInMonthType.ACTUAL.getValue()); + Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); + Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); + Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(false); + + final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator + .generatePeriodInterestScheduleModel(expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), null, mc); + + emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2023, 11, 13), Money.of(currency, BigDecimal.valueOf(5000), mc)); + checkPeriod(interestSchedule, 0, 857.71, 41.05, 816.66, 4183.34, false); + checkPeriod(interestSchedule, 1, 857.71, 35.45, 822.26, 3361.08, false); + checkPeriod(interestSchedule, 2, 857.71, 28.44, 829.27, 2531.81, false); + checkPeriod(interestSchedule, 3, 857.71, 20.04, 837.67, 1694.14, false); + checkPeriod(interestSchedule, 4, 857.71, 14.33, 843.38, 850.76, false); + checkPeriod(interestSchedule, 5, 857.73, 6.97, 850.76, 0.00, false); + } + + @Test + public void test_actual_actual_fraction_period_calculation_with_interestRecognitionFromDisbursementDate_true() { + MathContext mc = new MathContext(12, RoundingMode.HALF_UP); + final List expectedRepaymentPeriods = List.of( + repayment(1, LocalDate.of(2023, 11, 13), LocalDate.of(2023, 12, 13)), + repayment(2, LocalDate.of(2023, 12, 13), LocalDate.of(2024, 1, 13)), + repayment(3, LocalDate.of(2024, 1, 13), LocalDate.of(2024, 2, 13)), + repayment(4, LocalDate.of(2024, 2, 13), LocalDate.of(2024, 3, 13)), + repayment(5, LocalDate.of(2024, 3, 13), LocalDate.of(2024, 4, 13)), + repayment(6, LocalDate.of(2024, 4, 13), LocalDate.of(2024, 5, 13))); + + final BigDecimal interestRate = BigDecimal.valueOf(9.99); + + Mockito.when(loanProductRelatedDetail.getAnnualNominalInterestRate()).thenReturn(interestRate); + Mockito.when(loanProductRelatedDetail.getDaysInYearType()).thenReturn(DaysInYearType.ACTUAL.getValue()); + Mockito.when(loanProductRelatedDetail.getDaysInMonthType()).thenReturn(DaysInMonthType.ACTUAL.getValue()); + Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); + Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); + Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); + Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(true); + + final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator + .generatePeriodInterestScheduleModel(expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), null, mc); + + emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2023, 11, 13), Money.of(currency, BigDecimal.valueOf(5000), mc)); + checkPeriod(interestSchedule, 0, 857.72, 41.05, 816.67, 4183.33, false); + checkPeriod(interestSchedule, 1, 857.72, 35.46, 822.26, 3361.07, false); + checkPeriod(interestSchedule, 2, 857.72, 28.44, 829.28, 2531.79, false); + checkPeriod(interestSchedule, 3, 857.72, 20.04, 837.68, 1694.11, false); + checkPeriod(interestSchedule, 4, 857.72, 14.33, 843.39, 850.72, false); + checkPeriod(interestSchedule, 5, 857.69, 6.97, 850.72, 0.00, false); + } + @Nested class ChargeBackPrincipalAmt100DayInYears360DaysInMonth30RepayEvery1MonthTests {