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 983f3d2da FINERACT-1981: Reschedule loan with new repayment date 
(Progressive loan schedule)
983f3d2da is described below

commit 983f3d2da0909dddd6810810c2545992825fc1ce
Author: Adam Saghy <[email protected]>
AuthorDate: Tue Nov 7 12:22:01 2023 +0100

    FINERACT-1981: Reschedule loan with new repayment date (Progressive loan 
schedule)
---
 .../portfolio/loanaccount/domain/Loan.java         |   7 +-
 .../AbstractProgressiveLoanScheduleGenerator.java  |  59 +++++++---
 ...nRescheduleRequestWritePlatformServiceImpl.java |   7 +-
 ...PaymentAllocationLoanRepaymentScheduleTest.java | 126 ++++++++++++++++++++-
 .../common/LoanRescheduleRequestHelper.java        |  15 ++-
 5 files changed, 191 insertions(+), 23 deletions(-)

diff --git 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
index ea173c3d4..a8614c9a4 100644
--- 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
+++ 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
@@ -5516,7 +5516,12 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom {
         if (loanSchedule == null) {
             return;
         }
-        updateLoanSchedule(loanSchedule.getInstallments());
+        // Either the installments got recalculated or the model
+        if (loanSchedule.getInstallments() != null) {
+            updateLoanSchedule(loanSchedule.getInstallments());
+        } else {
+            updateLoanSchedule(loanSchedule.getLoanScheduleModel());
+        }
         this.interestRecalculatedOn = DateUtils.getBusinessLocalDate();
         LocalDate lastRepaymentDate = this.getLastRepaymentPeriodDueDate(true);
         Set<LoanCharge> charges = this.getActiveCharges();
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractProgressiveLoanScheduleGenerator.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractProgressiveLoanScheduleGenerator.java
index 8912fad65..d46b9aa1b 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractProgressiveLoanScheduleGenerator.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractProgressiveLoanScheduleGenerator.java
@@ -21,6 +21,7 @@ package 
org.apache.fineract.portfolio.loanaccount.loanschedule.domain;
 import java.math.BigDecimal;
 import java.math.MathContext;
 import java.time.LocalDate;
+import java.time.temporal.ChronoUnit;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashSet;
@@ -117,16 +118,13 @@ public abstract class 
AbstractProgressiveLoanScheduleGenerator implements LoanSc
             isFirstRepayment = false;
             LocalDate scheduledDueDate = 
adjustedDateDetailsDTO.getChangedScheduleDate();
 
-            // this block is to generate the schedule till the specified
-            // date(used for calculating preclosure)
-            boolean isCompletePeriod = true;
-            if (scheduleParams.getScheduleTillDate() != null && 
!scheduledDueDate.isBefore(scheduleParams.getScheduleTillDate())) {
-                if 
(!scheduledDueDate.isEqual(scheduleParams.getScheduleTillDate())) {
-                    isCompletePeriod = false;
-                }
-                scheduledDueDate = scheduleParams.getScheduleTillDate();
-                isNextRepaymentAvailable = false;
-            }
+            // Loan Schedule Exceptions that need to be applied for Loan 
Account
+            LoanTermVariationParams termVariationParams = 
applyLoanTermVariations(loanApplicationTerms, scheduleParams, scheduledDueDate);
+            scheduledDueDate = termVariationParams.scheduledDueDate();
+
+            // Updates total days in term
+            scheduleParams
+                    
.addLoanTermInDays(Math.toIntExact(ChronoUnit.DAYS.between(scheduleParams.getPeriodStartDate(),
 scheduledDueDate)));
 
             ScheduleCurrentPeriodParams currentPeriodParams = new 
ScheduleCurrentPeriodParams(currency, BigDecimal.ZERO);
 
@@ -134,10 +132,6 @@ public abstract class 
AbstractProgressiveLoanScheduleGenerator implements LoanSc
                 processDisbursements(loanApplicationTerms, 
chargesDueAtTimeOfDisbursement, scheduleParams, periods, scheduledDueDate);
             }
 
-            if (currentPeriodParams.isSkipCurrentLoop()) {
-                continue;
-            }
-
             // 5 determine principal,interest of repayment period
             PrincipalInterest principalInterestForThisPeriod = 
calculatePrincipalInterestComponentsForPeriod(
                     getPaymentPeriodsInOneYearCalculator(), 
currentPeriodParams.getInterestCalculationGraceOnRepaymentPeriodFraction(),
@@ -178,7 +172,7 @@ public abstract class 
AbstractProgressiveLoanScheduleGenerator implements LoanSc
                     scheduleParams.getPeriodStartDate(), scheduledDueDate, 
currentPeriodParams.getPrincipalForThisPeriod(),
                     scheduleParams.getOutstandingBalance(), 
currentPeriodParams.getInterestForThisPeriod(),
                     currentPeriodParams.getFeeChargesForInstallment(), 
currentPeriodParams.getPenaltyChargesForInstallment(),
-                    totalInstallmentDue, !isCompletePeriod);
+                    totalInstallmentDue, false);
             if (principalInterestForThisPeriod.getRescheduleInterestPortion() 
!= null) {
                 
installment.setRescheduleInterestPortion(principalInterestForThisPeriod.getRescheduleInterestPortion().getAmount());
             }
@@ -190,7 +184,7 @@ public abstract class 
AbstractProgressiveLoanScheduleGenerator implements LoanSc
 
             periods.add(installment);
 
-            // Updates principal paid map with efective date for reducing
+            // Updates principal paid map with effective date for reducing
             // the amount from outstanding balance(interest calculation)
             updateAmountsWithEffectiveDate(loanApplicationTerms, 
holidayDetailDTO, scheduleParams, scheduledDueDate, currentPeriodParams,
                     installment);
@@ -229,7 +223,9 @@ public abstract class 
AbstractProgressiveLoanScheduleGenerator implements LoanSc
     public LoanScheduleDTO rescheduleNextInstallments(MathContext mc, 
LoanApplicationTerms loanApplicationTerms, Loan loan,
             HolidayDetailDTO holidayDetailDTO, 
LoanRepaymentScheduleTransactionProcessor 
loanRepaymentScheduleTransactionProcessor,
             LocalDate rescheduleFrom) {
-        return null;
+
+        LoanScheduleModel model = generate(mc, loanApplicationTerms, 
loan.getActiveCharges(), holidayDetailDTO);
+        return LoanScheduleDTO.from(null, model);
     }
 
     @Override
@@ -626,4 +622,33 @@ public abstract class 
AbstractProgressiveLoanScheduleGenerator implements LoanSc
         scheduleParams
                 
.reduceOutstandingBalance(currentPeriodParams.getPrincipalForThisPeriod().minus(currentPeriodParams.getReducedBalance()));
     }
+
+    /**
+     * @param loanApplicationTerms
+     * @param scheduleParams
+     * @param scheduledDueDate
+     * @return
+     */
+    private LoanTermVariationParams applyLoanTermVariations(final 
LoanApplicationTerms loanApplicationTerms,
+            final LoanScheduleParams scheduleParams, final LocalDate 
scheduledDueDate) {
+        boolean skipPeriod = false;
+        boolean recalculateAmounts = false;
+        LocalDate modifiedScheduledDueDate = scheduledDueDate;
+        ArrayList<LoanTermVariationsData> variationsData = null;
+
+        // due date changes should be applied only for that dueDate
+        if 
(loanApplicationTerms.getLoanTermVariations().hasDueDateVariation(scheduledDueDate))
 {
+            LoanTermVariationsData loanTermVariationsData = 
loanApplicationTerms.getLoanTermVariations().nextDueDateVariation();
+            if (DateUtils.isEqual(modifiedScheduledDueDate, 
loanTermVariationsData.getTermVariationApplicableFrom())) {
+                modifiedScheduledDueDate = 
loanTermVariationsData.getDateValue();
+                if (!loanTermVariationsData.isSpecificToInstallment()) {
+                    
scheduleParams.setActualRepaymentDate(modifiedScheduledDueDate);
+                    
loanApplicationTerms.setNewScheduledDueDateStart(modifiedScheduledDueDate);
+                }
+                loanTermVariationsData.setProcessed(true);
+            }
+        }
+
+        return new LoanTermVariationParams(skipPeriod, recalculateAmounts, 
modifiedScheduledDueDate, variationsData);
+    }
 }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java
index dba4557f6..3c0d41236 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java
@@ -443,7 +443,12 @@ public class LoanRescheduleRequestWritePlatformServiceImpl 
implements LoanResche
             final LoanScheduleDTO loanSchedule = 
loanScheduleGenerator.rescheduleNextInstallments(mathContext, 
loanApplicationTerms, loan,
                     loanApplicationTerms.getHolidayDetailDTO(), 
loanRepaymentScheduleTransactionProcessor, rescheduleFromDate);
 
-            loan.updateLoanSchedule(loanSchedule.getInstallments());
+            // Either the installments got recalculated or the model
+            if (loanSchedule.getInstallments() != null) {
+                loan.updateLoanSchedule(loanSchedule.getInstallments());
+            } else {
+                loan.updateLoanSchedule(loanSchedule.getLoanScheduleModel());
+            }
             loan.recalculateAllCharges();
             ChangedTransactionDetail changedTransactionDetail = 
loan.processTransactions();
 
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/AdvancedPaymentAllocationLoanRepaymentScheduleTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/AdvancedPaymentAllocationLoanRepaymentScheduleTest.java
index c177431ec..49002bc38 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/AdvancedPaymentAllocationLoanRepaymentScheduleTest.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/AdvancedPaymentAllocationLoanRepaymentScheduleTest.java
@@ -28,6 +28,7 @@ import io.restassured.http.ContentType;
 import io.restassured.specification.RequestSpecification;
 import io.restassured.specification.ResponseSpecification;
 import java.math.BigDecimal;
+import java.time.LocalDate;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
@@ -38,15 +39,19 @@ import 
org.apache.fineract.client.models.GetLoansLoanIdRepaymentPeriod;
 import org.apache.fineract.client.models.GetLoansLoanIdResponse;
 import org.apache.fineract.client.models.PaymentAllocationOrder;
 import org.apache.fineract.client.models.PostClientsResponse;
+import org.apache.fineract.client.models.PostCreateRescheduleLoansRequest;
+import org.apache.fineract.client.models.PostCreateRescheduleLoansResponse;
 import org.apache.fineract.client.models.PostLoansLoanIdRequest;
 import org.apache.fineract.client.models.PostLoansLoanIdTransactionsRequest;
 import 
org.apache.fineract.client.models.PostLoansLoanIdTransactionsTransactionIdRequest;
 import org.apache.fineract.client.models.PostLoansRequest;
 import org.apache.fineract.client.models.PostLoansResponse;
+import org.apache.fineract.client.models.PostUpdateRescheduleLoansRequest;
 import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
 import org.apache.fineract.integrationtests.common.BusinessDateHelper;
 import org.apache.fineract.integrationtests.common.ClientHelper;
 import org.apache.fineract.integrationtests.common.GlobalConfigurationHelper;
+import org.apache.fineract.integrationtests.common.LoanRescheduleRequestHelper;
 import org.apache.fineract.integrationtests.common.Utils;
 import org.apache.fineract.integrationtests.common.accounting.Account;
 import org.apache.fineract.integrationtests.common.accounting.AccountHelper;
@@ -76,6 +81,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
     private static AccountHelper accountHelper;
     private static Integer commonLoanProductId;
     private static PostClientsResponse client;
+    private static LoanRescheduleRequestHelper loanRescheduleRequestHelper;
 
     @BeforeAll
     public static void setup() {
@@ -88,6 +94,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
         businessDateHelper = new BusinessDateHelper();
         accountHelper = new AccountHelper(requestSpec, responseSpec);
         ClientHelper clientHelper = new ClientHelper(requestSpec, 
responseSpec);
+        loanRescheduleRequestHelper = new 
LoanRescheduleRequestHelper(requestSpec, responseSpec);
 
         final Account assetAccount = accountHelper.createAssetAccount();
         final Account incomeAccount = accountHelper.createIncomeAccount();
@@ -1718,7 +1725,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
     // UC101: Multiple disbursement test
     // ADVANCED_PAYMENT_ALLOCATION_STRATEGY
     // 1. Disburse the loan
-    // 3. Pay over the down payment
+    // 2. Pay over the down payment
     // 3. Disburse again
     @Test
     public void uc101() {
@@ -1790,7 +1797,107 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             validateRepaymentPeriod(loanDetails, 3, 250.0, 50.0, 200.0, 50.0, 
0.0);
             validateRepaymentPeriod(loanDetails, 4, 250.0, 0.0, 250.0, 0.0, 
0.0);
             validateRepaymentPeriod(loanDetails, 5, 250.0, 0.0, 250.0, 0.0, 
0.0);
-            validateRepaymentPeriod(loanDetails, 6, 0.0, 0.0, 0.0, 0.0, 0.0, 
0.0, 100.0, 0.0, 100.0, 0.0, 0.0, 0.0, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 6, LocalDate.of(2023, 2, 22), 
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 100.0, 0.0, 100.0, 0.0, 0.0,
+                    0.0, 0.0, 0.0);
+            assertTrue(loanDetails.getStatus().getActive());
+        } finally {
+            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
+        }
+    }
+
+    // UC102: Multiple disbursement & reschedule test
+    // ADVANCED_PAYMENT_ALLOCATION_STRATEGY
+    // 1. Disburse the loan (500)
+    // 2. Reschedule the 2nd period
+    // 3. Repayment (450)
+    // 3. Disburse again (250)
+    // 4. Reschedule the 3rd period to be later than the 2nd disbursement
+    @Test
+    public void uc102() {
+        try {
+
+            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
+            businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
+                    .date("2023.02.20").dateFormat("yyyy.MM.dd").locale("en"));
+
+            final Account assetAccount = accountHelper.createAssetAccount();
+            final Account incomeAccount = accountHelper.createIncomeAccount();
+            final Account expenseAccount = 
accountHelper.createExpenseAccount();
+            final Account overpaymentAccount = 
accountHelper.createLiabilityAccount();
+            Integer localLoanProductId = createLoanProduct("500", "15", "4", 
false, assetAccount, incomeAccount, expenseAccount,
+                    overpaymentAccount);
+            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), localLoanProductId, 500L, 45, 15, 
3, 0,
+                    "01 January 2023", "01 January 2023");
+
+            loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
+                    new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
+                            .approvedOnDate("01 January 2023").locale("en"));
+
+            loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
+                    new PostLoansLoanIdRequest().actualDisbursementDate("01 
January 2023").dateFormat(DATETIME_PATTERN)
+                            
.transactionAmount(BigDecimal.valueOf(500.00)).locale("en"));
+
+            GetLoansLoanIdResponse loanDetails = 
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
+            validateLoanSummaryBalances(loanDetails, 500.0, 0.0, 500.0, 0.0, 
null);
+            validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 
125.0, 0.0, 125.0, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), 
125.0, 0.0, 125.0, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 1, 31), 
125.0, 0.0, 125.0, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 15), 
125.0, 0.0, 125.0, 0.0, 0.0);
+            assertTrue(loanDetails.getStatus().getActive());
+
+            PostCreateRescheduleLoansResponse rescheduleLoansResponse = 
loanRescheduleRequestHelper
+                    .createLoanRescheduleRequest(new 
PostCreateRescheduleLoansRequest().loanId(loanDetails.getId()).locale("en")
+                            
.dateFormat(DATETIME_PATTERN).rescheduleReasonId(1L).rescheduleFromDate("16 
January 2023")
+                            .adjustedDueDate("31 January 
2023").submittedOnDate("16 January 2023"));
+
+            
loanRescheduleRequestHelper.approveLoanRescheduleRequest(rescheduleLoansResponse.getResourceId(),
+                    new PostUpdateRescheduleLoansRequest().approvedOnDate("16 
January 2023").locale("en").dateFormat(DATETIME_PATTERN));
+
+            loanDetails = 
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
+            validateLoanSummaryBalances(loanDetails, 500.0, 0.0, 500.0, 0.0, 
null);
+            validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 
125.0, 0.0, 125.0, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 31), 
125.0, 0.0, 125.0, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 2, 15), 
125.0, 0.0, 125.0, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 3, 2), 
125.0, 0.0, 125.0, 0.0, 0.0);
+            assertTrue(loanDetails.getStatus().getActive());
+
+            loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), 
new PostLoansLoanIdTransactionsRequest()
+                    .dateFormat(DATETIME_PATTERN).transactionDate("16 January 
2023").locale("en").transactionAmount(350.0));
+            loanDetails = 
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
+            validateLoanSummaryBalances(loanDetails, 150.0, 350.0, 150.0, 
350.0, null);
+            validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 
125.0, 125.0, 0.0, 0.0, 125.0);
+            validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 31), 
125.0, 125.0, 0.0, 125.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 2, 15), 
125.0, 100.0, 25.0, 100.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 3, 2), 
125.0, 0.0, 125.0, 0.0, 0.0);
+            assertTrue(loanDetails.getStatus().getActive());
+
+            loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
+                    new PostLoansLoanIdRequest().actualDisbursementDate("20 
February 2023").dateFormat(DATETIME_PATTERN)
+                            
.transactionAmount(BigDecimal.valueOf(250.0)).locale("en"));
+
+            loanDetails = 
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
+            validateLoanSummaryBalances(loanDetails, 400.0, 350.0, 400.0, 
350.0, null);
+            validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 
125.0, 125.0, 0.0, 0.0, 125.0);
+            validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 31), 
125.0, 125.0, 0.0, 125.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 2, 15), 
125.0, 100.0, 25.0, 100.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 20), 
62.5, 0.0, 62.5, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 5, LocalDate.of(2023, 3, 2), 
312.5, 0.0, 312.5, 0.0, 0.0);
+            assertTrue(loanDetails.getStatus().getActive());
+
+            rescheduleLoansResponse = 
loanRescheduleRequestHelper.createLoanRescheduleRequest(new 
PostCreateRescheduleLoansRequest()
+                    
.loanId(loanDetails.getId()).locale("en").dateFormat(DATETIME_PATTERN).rescheduleReasonId(1L)
+                    .rescheduleFromDate("15 February 
2023").adjustedDueDate("25 February 2023").submittedOnDate("15 February 2023"));
+
+            
loanRescheduleRequestHelper.approveLoanRescheduleRequest(rescheduleLoansResponse.getResourceId(),
+                    new PostUpdateRescheduleLoansRequest().approvedOnDate("15 
February 2023").locale("en").dateFormat(DATETIME_PATTERN));
+
+            loanDetails = 
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
+            validateLoanSummaryBalances(loanDetails, 400.0, 350.0, 400.0, 
350.0, null);
+            validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 
125.0, 125.0, 0.0, 0.0, 125.0);
+            validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 31), 
125.0, 125.0, 0.0, 125.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 2, 20), 
62.5, 0.0, 62.5, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 25), 
218.75, 100.0, 118.75, 100.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 5, LocalDate.of(2023, 3, 12), 
218.75, 0.0, 218.75, 0.0, 0.0);
             assertTrue(loanDetails.getStatus().getActive());
         } finally {
             GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
@@ -1867,10 +1974,11 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
         return loanTransactionHelper.getLoanProductId(loanProductJSON);
     }
 
-    private static void validateRepaymentPeriod(GetLoansLoanIdResponse 
loanDetails, Integer index, double principalDue,
+    private static void validateRepaymentPeriod(GetLoansLoanIdResponse 
loanDetails, Integer index, LocalDate dueDate, double principalDue,
             double principalPaid, double principalOutstanding, double 
paidInAdvance, double paidLate) {
         GetLoansLoanIdRepaymentPeriod period = 
loanDetails.getRepaymentSchedule().getPeriods().stream()
                 .filter(p -> Objects.equals(p.getPeriod(), 
index)).findFirst().orElseThrow();
+        assertEquals(dueDate, period.getDueDate());
         assertEquals(principalDue, period.getPrincipalDue());
         assertEquals(principalPaid, period.getPrincipalPaid());
         assertEquals(principalOutstanding, period.getPrincipalOutstanding());
@@ -1879,11 +1987,23 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
     }
 
     private static void validateRepaymentPeriod(GetLoansLoanIdResponse 
loanDetails, Integer index, double principalDue,
+            double principalPaid, double principalOutstanding, double 
paidInAdvance, double paidLate) {
+        GetLoansLoanIdRepaymentPeriod period = 
loanDetails.getRepaymentSchedule().getPeriods().stream()
+                .filter(p -> Objects.equals(p.getPeriod(), 
index)).findFirst().orElseThrow();
+        assertEquals(principalDue, period.getPrincipalDue());
+        assertEquals(principalPaid, period.getPrincipalPaid());
+        assertEquals(principalOutstanding, period.getPrincipalOutstanding());
+        assertEquals(paidInAdvance, period.getTotalPaidInAdvanceForPeriod());
+        assertEquals(paidLate, period.getTotalPaidLateForPeriod());
+    }
+
+    private static void validateRepaymentPeriod(GetLoansLoanIdResponse 
loanDetails, Integer index, LocalDate dueDate, double principalDue,
             double principalPaid, double principalOutstanding, double feeDue, 
double feePaid, double feeOutstanding, double penaltyDue,
             double penaltyPaid, double penaltyOutstanding, double interestDue, 
double interestPaid, double interestOutstanding,
             double paidInAdvance, double paidLate) {
         GetLoansLoanIdRepaymentPeriod period = 
loanDetails.getRepaymentSchedule().getPeriods().stream()
                 .filter(p -> Objects.equals(p.getPeriod(), 
index)).findFirst().orElseThrow();
+        assertEquals(dueDate, period.getDueDate());
         assertEquals(principalDue, period.getPrincipalDue());
         assertEquals(principalPaid, period.getPrincipalPaid());
         assertEquals(principalOutstanding, period.getPrincipalOutstanding());
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/LoanRescheduleRequestHelper.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/LoanRescheduleRequestHelper.java
index 4e3b827f4..901e52dfe 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/LoanRescheduleRequestHelper.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/LoanRescheduleRequestHelper.java
@@ -23,8 +23,13 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import io.restassured.specification.RequestSpecification;
 import io.restassured.specification.ResponseSpecification;
 import java.util.HashMap;
+import org.apache.fineract.client.models.PostCreateRescheduleLoansRequest;
+import org.apache.fineract.client.models.PostCreateRescheduleLoansResponse;
+import org.apache.fineract.client.models.PostUpdateRescheduleLoansRequest;
+import org.apache.fineract.client.models.PostUpdateRescheduleLoansResponse;
+import org.apache.fineract.integrationtests.client.IntegrationTest;
 
-public class LoanRescheduleRequestHelper {
+public class LoanRescheduleRequestHelper extends IntegrationTest {
 
     private final RequestSpecification requestSpec;
     private final ResponseSpecification responseSpec;
@@ -70,4 +75,12 @@ public class LoanRescheduleRequestHelper {
         final Integer id = Utils.performServerGet(requestSpec, responseSpec, 
URL, "id");
         assertEquals(requestId, id, "ERROR IN CREATING LOAN RESCHEDULE 
REQUES");
     }
+
+    public PostCreateRescheduleLoansResponse 
createLoanRescheduleRequest(PostCreateRescheduleLoansRequest request) {
+        return 
ok(fineract().rescheduleLoans.createLoanRescheduleRequest(request));
+    }
+
+    public PostUpdateRescheduleLoansResponse approveLoanRescheduleRequest(Long 
scheduleId, PostUpdateRescheduleLoansRequest request) {
+        return 
ok(fineract().rescheduleLoans.updateLoanRescheduleRequest(scheduleId, request, 
"approve"));
+    }
 }

Reply via email to