This is an automated email from the ASF dual-hosted git repository.

arnold pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git

commit 42f5de937d68deeebefc4557098eedbe6d769b61
Author: Oleksii Novikov <[email protected]>
AuthorDate: Sat May 31 01:50:12 2025 +0300

    FINERACT-2152: Fix interest pause on the 1st day of the 1st period
---
 .../data/ProgressiveLoanInterestScheduleModel.java | 16 ++++------
 .../calc/ProgressiveEMICalculatorTest.java         | 37 ++++++++++++++++++++++
 2 files changed, 44 insertions(+), 9 deletions(-)

diff --git 
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/data/ProgressiveLoanInterestScheduleModel.java
 
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/data/ProgressiveLoanInterestScheduleModel.java
index 38cde0ba2b..c7c4410adc 100644
--- 
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/data/ProgressiveLoanInterestScheduleModel.java
+++ 
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/data/ProgressiveLoanInterestScheduleModel.java
@@ -161,13 +161,13 @@ public class ProgressiveLoanInterestScheduleModel {
         if (repaymentPeriods.isEmpty()) {
             return 0;
         }
-        final RepaymentPeriod firstPeriod = repaymentPeriods.get(0);
+        final RepaymentPeriod firstPeriod = repaymentPeriods.getFirst();
         final RepaymentPeriod lastPeriod = repaymentPeriods.size() > 1 ? 
getLastRepaymentPeriod() : firstPeriod;
         return DateUtils.getExactDifferenceInDays(firstPeriod.getFromDate(), 
lastPeriod.getDueDate());
     }
 
     public LocalDate getStartDate() {
-        return !repaymentPeriods.isEmpty() ? 
repaymentPeriods.get(0).getFromDate() : null;
+        return !repaymentPeriods.isEmpty() ? 
repaymentPeriods.getFirst().getFromDate() : null;
     }
 
     public LocalDate getMaturityDate() {
@@ -264,7 +264,9 @@ public class ProgressiveLoanInterestScheduleModel {
     }
 
     private void insertInterestPausePeriods(final RepaymentPeriod 
repaymentPeriod, final LocalDate pauseStart, final LocalDate pauseEnd) {
-        final LocalDate effectivePauseStart = pauseStart.minusDays(1);
+        final boolean isPauseStartOnFirstDayOfPeriod = 
pauseStart.isEqual(repaymentPeriod.getFromDate().plusDays(1));
+        final LocalDate effectivePauseStart = isPauseStartOnFirstDayOfPeriod ? 
pauseStart : pauseStart.minusDays(1);
+
         final LocalDate finalPauseStart = 
effectivePauseStart.isBefore(repaymentPeriod.getFromDate()) ? 
repaymentPeriod.getFromDate()
                 : effectivePauseStart;
         final LocalDate finalPauseEnd = 
pauseEnd.isAfter(repaymentPeriod.getDueDate()) ? repaymentPeriod.getDueDate() : 
pauseEnd;
@@ -302,7 +304,7 @@ public class ProgressiveLoanInterestScheduleModel {
         } else {
             return repaymentPeriod.getInterestPeriods().stream()
                     .filter(ip -> date.isAfter(ip.getFromDate()) && 
!date.isAfter(ip.getDueDate())).reduce((first, second) -> second)
-                    .orElse(repaymentPeriod.getInterestPeriods().get(0));
+                    .orElse(repaymentPeriod.getInterestPeriods().getFirst());
         }
     }
 
@@ -357,10 +359,6 @@ public class ProgressiveLoanInterestScheduleModel {
         return 
MathUtil.negativeToZero(getTotalDuePrincipal().minus(getTotalPaidPrincipal()));
     }
 
-    public Money getTotalOutstandingInterest() {
-        return 
MathUtil.negativeToZero(getTotalDueInterest().minus(getTotalPaidInterest()));
-    }
-
     public Optional<RepaymentPeriod> findRepaymentPeriod(@NotNull LocalDate 
transactionDate) {
         return repaymentPeriods.stream() //
                 .filter(period -> isInPeriod(transactionDate, 
period.getFromDate(), period.getDueDate(), period.isFirstRepaymentPeriod()))//
@@ -381,7 +379,7 @@ public class ProgressiveLoanInterestScheduleModel {
 
     @NotNull
     public RepaymentPeriod getLastRepaymentPeriod() {
-        return repaymentPeriods.get(repaymentPeriods.size() - 1);
+        return repaymentPeriods.getLast();
     }
 
     public boolean isLastRepaymentPeriod(@NotNull RepaymentPeriod 
repaymentPeriod) {
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 298c57c6b4..207da71ab7 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
@@ -1809,6 +1809,43 @@ class ProgressiveEMICalculatorTest {
         checkPeriod(interestSchedule, 5, 0, 16.48, 0.005833333333, 
0.0955499999946, 0.1, 16.38, 0.0);
     }
 
+    @Test
+    public void 
test_interestPauseOnTheFirstDayOfFirstPeriodAmt100_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, 3, 
1)),
+                repayment(3, LocalDate.of(2024, 3, 1), LocalDate.of(2024, 4, 
1)),
+                repayment(4, LocalDate.of(2024, 4, 1), LocalDate.of(2024, 5, 
1)),
+                repayment(5, LocalDate.of(2024, 5, 1), LocalDate.of(2024, 6, 
1)),
+                repayment(6, LocalDate.of(2024, 6, 1), LocalDate.of(2024, 7, 
1)));
+
+        final BigDecimal interestRate = BigDecimal.valueOf(7.0);
+        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);
+        List<LoanTermVariationsData> loanTermVariations = new ArrayList<>();
+
+        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);
+        emiCalculator.applyInterestPause(interestSchedule, LocalDate.of(2024, 
1, 2), LocalDate.of(2024, 1, 10));
+        checkPeriod(interestSchedule, 0, 0, 17.01, 0.0, 0.0, 0.43, 16.58, 
83.42);
+        checkPeriod(interestSchedule, 0, 1, 17.01, 0.000188172043, 
0.0188172043, 0.43, 16.58, 83.42);
+        checkPeriod(interestSchedule, 0, 2, 17.01, 0.001505376344, 0.0, 0.43, 
16.58, 83.42);
+        checkPeriod(interestSchedule, 1, 0, 17.01, 0.005833333333, 
0.486616666638, 0.49, 16.52, 66.90);
+        checkPeriod(interestSchedule, 2, 0, 17.01, 0.005833333333, 
0.390249999978, 0.39, 16.62, 50.28);
+        checkPeriod(interestSchedule, 3, 0, 17.01, 0.005833333333, 
0.293299999983, 0.29, 16.72, 33.56);
+        checkPeriod(interestSchedule, 4, 0, 17.01, 0.005833333333, 
0.195766666655, 0.20, 16.81, 16.75);
+        checkPeriod(interestSchedule, 5, 0, 16.85, 0.005833333333, 
0.0977083333278, 0.10, 16.75, 0.0);
+    }
+
     @Test
     public void 
test_reschedule_disbursedAmt100_dayInYears360_daysInMonth30_repayEvery1Month() {
         final List<LoanScheduleModelRepaymentPeriod> expectedRepaymentPeriods 
= List.of(

Reply via email to