You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by av...@apache.org on 2022/03/28 17:11:45 UTC

[fineract] branch develop updated: FINERACT-1450-fix (#2177)

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

avikg 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 bc0b5c0   FINERACT-1450-fix (#2177)
bc0b5c0 is described below

commit bc0b5c00bba8829ef3837940ce225cc3090e13b9
Author: Manoj <56...@users.noreply.github.com>
AuthorDate: Mon Mar 28 22:41:36 2022 +0530

     FINERACT-1450-fix (#2177)
---
 .../domain/AbstractLoanScheduleGenerator.java      |  23 +-
 .../domain/DefaultScheduledDateGenerator.java      |   7 +-
 .../LoanRescheduleOnDecliningBalanceLoanTest.java  |  17 +-
 .../LoanRescheduleWithAdvancePaymentTest.java      | 258 +++++++++++++++++++++
 .../integrationtests/common/WorkingDaysHelper.java |  18 ++
 .../loans/LoanRescheduleRequestTestBuilder.java    |   5 +-
 .../common/loans/LoanTransactionHelper.java        |   7 +
 7 files changed, 317 insertions(+), 18 deletions(-)

diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java
index 396dc1f..0f6d470 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java
@@ -177,7 +177,6 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
 
             isFirstRepayment = false;
         }
-
         while (!scheduleParams.getOutstandingBalance().isZero() || !scheduleParams.getDisburseDetailMap().isEmpty()) {
             LocalDate previousRepaymentDate = scheduleParams.getActualRepaymentDate();
             scheduleParams.setActualRepaymentDate(this.scheduledDateGenerator
@@ -2196,16 +2195,32 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
                             actualRepaymentDate = lastInstallmentDate;
                         }
                         isFirstRepayment = false;
+                        LocalDate prevLastInstDate = lastInstallmentDate;
                         lastInstallmentDate = this.scheduledDateGenerator
                                 .adjustRepaymentDate(actualRepaymentDate, loanApplicationTerms, holidayDetailDTO).getChangedScheduleDate();
+                        LocalDate modifiedLastInstDate = null;
+                        LoanTermVariationsData variation1 = null;
                         while (loanApplicationTerms.getLoanTermVariations().hasDueDateVariation(lastInstallmentDate)) {
                             LoanTermVariationsData variation = loanApplicationTerms.getLoanTermVariations().nextDueDateVariation();
                             if (!variation.isSpecificToInstallment()) {
-                                actualRepaymentDate = variation.getDateValue();
-                                lastInstallmentDate = actualRepaymentDate;
+                                modifiedLastInstDate = variation.getDateValue();
+                                variation1 = variation;
+                            }
+                        }
+
+                        if (!lastInstallmentDate.isEqual(installment.getDueDate())
+                                && !installment.getDueDate().equals(modifiedLastInstDate)) {
+                            lastInstallmentDate = prevLastInstDate;
+                            actualRepaymentDate = lastInstallmentDate;
+                            if (modifiedLastInstDate != null) {
+                                loanApplicationTerms.getLoanTermVariations().previousDueDateVariation();
                             }
-                            dueDateVariationsDataList.add(variation);
+                        } else if (installment.getDueDate().equals(modifiedLastInstDate)) {
+                            actualRepaymentDate = modifiedLastInstDate;
+                            lastInstallmentDate = actualRepaymentDate;
+                            dueDateVariationsDataList.add(variation1);
                         }
+
                         loanTermVariationParams = applyExceptionLoanTermVariations(loanApplicationTerms, lastInstallmentDate,
                                 exceptionDataListIterator, instalmentNumber, totalCumulativePrincipal, totalCumulativeInterest, mc);
                     } while (loanTermVariationParams != null && loanTermVariationParams.isSkipPeriod());
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/DefaultScheduledDateGenerator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/DefaultScheduledDateGenerator.java
index 584de8c..b2221bc 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/DefaultScheduledDateGenerator.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/DefaultScheduledDateGenerator.java
@@ -338,11 +338,12 @@ public class DefaultScheduledDateGenerator implements ScheduledDateGenerator {
             generatedDate = loanApplicationTerms.getNewScheduledDueDateStart();
             isFirstRepayment = false;
         }
-        while (!generatedDate.isAfter(lastRepaymentDate)) {
+        LocalDate adjustedDate = generatedDate;
+        while (!adjustedDate.isAfter(lastRepaymentDate)) {
             generatedDate = generateNextRepaymentDate(generatedDate, loanApplicationTerms, isFirstRepayment);
+            adjustedDate = adjustRepaymentDate(generatedDate, loanApplicationTerms, holidayDetailDTO).getChangedScheduleDate();
             isFirstRepayment = false;
         }
-        generatedDate = adjustRepaymentDate(generatedDate, loanApplicationTerms, holidayDetailDTO).getChangedScheduleDate();
-        return generatedDate;
+        return adjustedDate;
     }
 }
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleOnDecliningBalanceLoanTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleOnDecliningBalanceLoanTest.java
index 6fb1607..70eeb52 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleOnDecliningBalanceLoanTest.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleOnDecliningBalanceLoanTest.java
@@ -185,8 +185,8 @@ public class LoanRescheduleOnDecliningBalanceLoanTest {
 
         LOG.info("Sucessfully created loan (ID: {} )", this.loanId);
 
-        this.approveLoanApplication();
-        this.disburseLoan();
+        this.approveLoanApplication(this.dateString);
+        this.disburseLoan(this.dateString);
     }
 
     private void addCollaterals(List<HashMap> collaterals, Integer collateralId, BigDecimal quantity) {
@@ -203,10 +203,10 @@ public class LoanRescheduleOnDecliningBalanceLoanTest {
     /**
      * approve the loan application
      **/
-    private void approveLoanApplication() {
+    private void approveLoanApplication(String approveDate) {
 
         if (this.loanId != null) {
-            this.loanTransactionHelper.approveLoan(this.dateString, this.loanId);
+            this.loanTransactionHelper.approveLoan(approveDate, this.loanId);
             LOG.info("Successfully approved loan (ID: {} )", this.loanId);
         }
     }
@@ -214,11 +214,11 @@ public class LoanRescheduleOnDecliningBalanceLoanTest {
     /**
      * disburse the newly created loan
      **/
-    private void disburseLoan() {
+    private void disburseLoan(String disburseDate) {
 
         if (this.loanId != null) {
             String loanDetails = this.loanTransactionHelper.getLoanDetails(this.requestSpec, this.responseSpec, this.loanId);
-            this.loanTransactionHelper.disburseLoan(this.dateString, this.loanId,
+            this.loanTransactionHelper.disburseLoan(disburseDate, this.loanId,
                     JsonPath.from(loanDetails).get("netDisbursalAmount").toString());
             LOG.info("Successfully disbursed loan (ID: {} )", this.loanId);
         }
@@ -485,8 +485,8 @@ public class LoanRescheduleOnDecliningBalanceLoanTest {
 
         LOG.info("Sucessfully created loan (ID: {} )", this.loanId);
 
-        this.approveLoanApplication();
-        this.disburseLoan();
+        this.approveLoanApplication(this.dateString);
+        this.disburseLoan(this.dateString);
     }
 
     /**
@@ -529,5 +529,4 @@ public class LoanRescheduleOnDecliningBalanceLoanTest {
         LOG.info("Successfully approved loan reschedule request (ID: {})", this.loanRescheduleRequestId);
 
     }
-
 }
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleWithAdvancePaymentTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleWithAdvancePaymentTest.java
new file mode 100644
index 0000000..758db0d
--- /dev/null
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleWithAdvancePaymentTest.java
@@ -0,0 +1,258 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.integrationtests;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import io.restassured.builder.RequestSpecBuilder;
+import io.restassured.builder.ResponseSpecBuilder;
+import io.restassured.http.ContentType;
+import io.restassured.path.json.JsonPath;
+import io.restassured.specification.RequestSpecification;
+import io.restassured.specification.ResponseSpecification;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+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.WorkingDaysHelper;
+import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder;
+import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder;
+import org.apache.fineract.integrationtests.common.loans.LoanRescheduleRequestTestBuilder;
+import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class LoanRescheduleWithAdvancePaymentTest {
+
+    private static final Logger LOG = LoggerFactory.getLogger(LoanRescheduleWithAdvancePaymentTest.class);
+    private ResponseSpecification responseSpec;
+    private ResponseSpecification generalResponseSpec;
+    private RequestSpecification requestSpec;
+    private LoanTransactionHelper loanTransactionHelper;
+    private LoanRescheduleRequestHelper loanRescheduleRequestHelper;
+    private Integer clientId;
+    private Integer loanProductId;
+    private Integer loanId;
+    private Integer loanRescheduleRequestId;
+    private final String loanPrincipalAmount = "100000.00";
+    private final String numberOfRepayments = "12";
+    private final String interestRatePerPeriod = "18";
+
+    @BeforeEach
+    public void initialize() {
+        Utils.initializeRESTAssured();
+        this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build();
+        this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
+        this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
+        this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec);
+        this.loanRescheduleRequestHelper = new LoanRescheduleRequestHelper(this.requestSpec, this.responseSpec);
+
+        this.generalResponseSpec = new ResponseSpecBuilder().build();
+
+    }
+
+    @AfterEach
+    public void tearDown() {
+        disableConfig();
+    }
+
+    /**
+     * enables the configuration `is-interest-to-be-recovered-first-when-greater-than-emi`
+     **/
+    private void enableConfig() {
+        GlobalConfigurationHelper.updateEnabledFlagForGlobalConfiguration(this.requestSpec, this.responseSpec, "42", true);
+    }
+
+    /**
+     * disables the configuration `is-interest-to-be-recovered-first-when-greater-than-emi`
+     **/
+    private void disableConfig() {
+        GlobalConfigurationHelper.updateEnabledFlagForGlobalConfiguration(this.requestSpec, this.responseSpec, "42", false);
+    }
+
+    /**
+     * enables the configuration `is-principal-compounding-disabled-for-overdue-loans`
+     **/
+    private void enablePrincipalCompoundingConfig() {
+        GlobalConfigurationHelper.updateEnabledFlagForGlobalConfiguration(this.requestSpec, this.responseSpec, "43", true);
+    }
+
+    /**
+     * disables the configuration `is-principal-compounding-disabled-for-overdue-loans`
+     **/
+    private void disablePrincipalCompoundingConfig() {
+        GlobalConfigurationHelper.updateEnabledFlagForGlobalConfiguration(this.requestSpec, this.responseSpec, "43", false);
+    }
+
+    /**
+     * approve the loan application
+     **/
+    private void approveLoanApplication(String approveDate) {
+
+        if (this.loanId != null) {
+            this.loanTransactionHelper.approveLoan(approveDate, this.loanId);
+            LOG.info("Successfully approved loan (ID: {} )", this.loanId);
+        }
+    }
+
+    /**
+     * disburse the newly created loan
+     **/
+    private void disburseLoan(String disburseDate) {
+
+        if (this.loanId != null) {
+            String loanDetails = this.loanTransactionHelper.getLoanDetails(this.requestSpec, this.responseSpec, this.loanId);
+            this.loanTransactionHelper.disburseLoan(disburseDate, this.loanId,
+                    JsonPath.from(loanDetails).get("netDisbursalAmount").toString());
+            LOG.info("Successfully disbursed loan (ID: {} )", this.loanId);
+        }
+    }
+
+    /* FINERACT-1450 */
+    @Test
+    public void testRescheduleAfterLatePayment() {
+        this.enableConfig();
+        this.enablePrincipalCompoundingConfig();
+        WorkingDaysHelper.updateWorkingDaysWeekDays(this.requestSpec, this.responseSpec);
+        // create all required entities
+        this.createRequiredEntitiesWithLatePayment();
+        this.createApproveLoanRescheduleRequestAfterLatePayment();
+        WorkingDaysHelper.updateWorkingDays(this.requestSpec, this.responseSpec);
+        this.disablePrincipalCompoundingConfig();
+        this.disableConfig();
+    }
+
+    /**
+     * create a new client
+     **/
+    private void createClientEntity() {
+        this.clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec);
+
+        ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, this.clientId);
+    }
+
+    private void createRequiredEntitiesWithLatePayment() {
+        this.createClientEntity();
+        this.createLoanProductWithInterestRecalculation();
+        this.createLoanEntityWithEntitiesForTestResceduleWithLatePayment();
+    }
+
+    private void createLoanProductWithInterestRecalculation() {
+        LOG.info(
+                "---------------------------------CREATING LOAN PRODUCT WITH RECALULATION ENABLED ------------------------------------------");
+
+        final String interestRecalculationCompoundingMethod = LoanProductTestBuilder.RECALCULATION_COMPOUNDING_METHOD_NONE;
+        final String rescheduleStrategyMethod = LoanProductTestBuilder.RECALCULATION_STRATEGY_REDUCE_NUMBER_OF_INSTALLMENTS;
+        final String recalculationRestFrequencyType = LoanProductTestBuilder.RECALCULATION_FREQUENCY_TYPE_DAILY;
+        final String recalculationRestFrequencyInterval = "0";
+        final String preCloseInterestCalculationStrategy = LoanProductTestBuilder.INTEREST_APPLICABLE_STRATEGY_ON_PRE_CLOSE_DATE;
+        final String recalculationCompoundingFrequencyType = null;
+        final String recalculationCompoundingFrequencyInterval = null;
+        final Integer recalculationCompoundingFrequencyOnDayType = null;
+        final Integer recalculationCompoundingFrequencyDayOfWeekType = null;
+        final Integer recalculationRestFrequencyOnDayType = null;
+        final Integer recalculationRestFrequencyDayOfWeekType = null;
+
+        final String loanProductJSON = new LoanProductTestBuilder().withPrincipal(loanPrincipalAmount)
+                .withNumberOfRepayments(numberOfRepayments).withinterestRatePerPeriod(interestRatePerPeriod)
+                .withInterestRateFrequencyTypeAsYear().withInterestTypeAsDecliningBalance().withInterestCalculationPeriodTypeAsDays()
+                .withInterestRecalculationDetails(interestRecalculationCompoundingMethod, rescheduleStrategyMethod,
+                        preCloseInterestCalculationStrategy)
+                .withInterestRecalculationRestFrequencyDetails(recalculationRestFrequencyType, recalculationRestFrequencyInterval,
+                        recalculationRestFrequencyOnDayType, recalculationRestFrequencyDayOfWeekType)
+                .withInterestRecalculationCompoundingFrequencyDetails(recalculationCompoundingFrequencyType,
+                        recalculationCompoundingFrequencyInterval, recalculationCompoundingFrequencyOnDayType,
+                        recalculationCompoundingFrequencyDayOfWeekType)
+                .build(null);
+
+        this.loanProductId = this.loanTransactionHelper.getLoanProductId(loanProductJSON);
+        LOG.info("Successfully created loan product  (ID:{}) ", this.loanProductId);
+    }
+
+    private void createLoanEntityWithEntitiesForTestResceduleWithLatePayment() {
+        String firstRepaymentDate = "14 June 2021";
+        String submittedDate = "10 May 2021";
+
+        LOG.info("---------------------------------NEW LOAN APPLICATION------------------------------------------");
+
+        final String loanApplicationJSON = new LoanApplicationTestBuilder().withPrincipal("15000").withLoanTermFrequency("12")
+                .withLoanTermFrequencyAsMonths().withNumberOfRepayments("12").withRepaymentEveryAfter("1")
+                .withRepaymentFrequencyTypeAsMonths().withAmortizationTypeAsEqualInstallments().withInterestCalculationPeriodTypeAsDays()
+                .withInterestRatePerPeriod("12").withInterestTypeAsDecliningBalance().withSubmittedOnDate(submittedDate)
+                .withExpectedDisbursementDate(submittedDate).withFirstRepaymentDate(firstRepaymentDate)
+                .withwithRepaymentStrategy(LoanApplicationTestBuilder.INTEREST_PRINCIPAL_PENALTIES_FEES_ORDER_STRATEGY)
+                .withinterestChargedFromDate(submittedDate).build(this.clientId.toString(), this.loanProductId.toString(), null);
+
+        this.loanId = this.loanTransactionHelper.getLoanId(loanApplicationJSON);
+
+        LOG.info("Sucessfully created loan (ID: {} )", this.loanId);
+
+        this.approveLoanApplication(submittedDate);
+        this.disburseLoan(submittedDate);
+    }
+
+    private void createApproveLoanRescheduleRequestAfterLatePayment() {
+        LOG.info("-------------Make repayment 1-----------");
+        this.loanTransactionHelper.makeRepayment("14 June 2021", Float.parseFloat("1331.58"), loanId);
+
+        LOG.info("-------------Make repayment 2-----------");
+        this.loanTransactionHelper.makeRepayment("15 July 2021", Float.parseFloat("1331.58"), loanId);
+
+        LOG.info(
+                "---------------------------------CREATING LOAN RESCHEDULE REQUEST FOR LOAN WITH RECALCULATION------------------------------------");
+
+        final String requestJSON = new LoanRescheduleRequestTestBuilder().updateGraceOnPrincipal(null).updateGraceOnInterest(null)
+                .updateExtraTerms(null).updateRescheduleFromDate("16 August 2021").updateAdjustedDueDate("31 August 2021")
+                .updateRecalculateInterest(false).updateSubmittedOnDate("16 August 2022").build(this.loanId.toString());
+        LOG.info("Reschedule request : {}", requestJSON);
+        this.loanRescheduleRequestId = this.loanRescheduleRequestHelper.createLoanRescheduleRequest(requestJSON);
+        this.loanRescheduleRequestHelper.verifyCreationOfLoanRescheduleRequest(this.loanRescheduleRequestId);
+
+        LOG.info("Successfully created loan reschedule request (ID: {} )", this.loanRescheduleRequestId);
+
+        final String aproveRequestJSON = new LoanRescheduleRequestTestBuilder().updateSubmittedOnDate("16 August 2022")
+                .getApproveLoanRescheduleRequestJSON();
+        this.loanRescheduleRequestHelper.approveLoanRescheduleRequest(this.loanRescheduleRequestId, aproveRequestJSON);
+
+        final HashMap response = (HashMap) this.loanRescheduleRequestHelper.getLoanRescheduleRequest(loanRescheduleRequestId, "statusEnum");
+        assertTrue((Boolean) response.get("approved"));
+
+        LOG.info("Successfully approved loan reschedule request (ID: {})", this.loanRescheduleRequestId);
+
+        final Map repaymentSchedule = (Map) this.loanTransactionHelper.getLoanDetailExcludeFutureSchedule(requestSpec, generalResponseSpec,
+                this.loanId, "repaymentSchedule");
+        LOG.info("Repayment Schedule for id {} : {}", this.loanId, repaymentSchedule);
+        final ArrayList periods = (ArrayList) repaymentSchedule.get("periods");
+
+        HashMap period = (HashMap) periods.get(4);
+        LOG.info("period  {}", period);
+
+        assertEquals(new ArrayList<>(Arrays.asList(2021, 8, 31)), period.get("dueDate"), "Checking for Due Date for 1st Month");
+
+    }
+
+}
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/WorkingDaysHelper.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/WorkingDaysHelper.java
index b06682e..1c73d92 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/WorkingDaysHelper.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/WorkingDaysHelper.java
@@ -51,6 +51,24 @@ public final class WorkingDaysHelper {
                 jsonAttributeToGetback);
     }
 
+    public static Object updateWorkingDaysWeekDays(final RequestSpecification requestSpec, final ResponseSpecification responseSpec) {
+        final String UPDATE_WORKINGDAYS_URL = WORKINGDAYS_URL + "?" + Utils.TENANT_IDENTIFIER;
+        LOG.info("---------------------------------UPDATE WORKINGDAY---------------------------------------------");
+        return Utils.performServerPut(requestSpec, responseSpec, UPDATE_WORKINGDAYS_URL, updateWorkingWeekDaysDaysAsJson(), "");
+    }
+
+    @SuppressFBWarnings(value = {
+            "DMI_RANDOM_USED_ONLY_ONCE" }, justification = "False positive for random object created and used only once")
+    public static String updateWorkingWeekDaysDaysAsJson() {
+        final HashMap<String, Object> map = new HashMap<>();
+        map.put("recurrence", "FREQ=WEEKLY;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR");
+        map.put("locale", "en");
+        map.put("repaymentRescheduleType", 2);
+        map.put("extendTermForDailyRepayments", false);
+        LOG.info("map :  {}", map);
+        return new Gson().toJson(map);
+    }
+
     @SuppressFBWarnings(value = {
             "DMI_RANDOM_USED_ONLY_ONCE" }, justification = "False positive for random object created and used only once")
     public static String updateWorkingDaysAsJson() {
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanRescheduleRequestTestBuilder.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanRescheduleRequestTestBuilder.java
index f1dfb1f..d05e78a 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanRescheduleRequestTestBuilder.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanRescheduleRequestTestBuilder.java
@@ -56,8 +56,9 @@ public class LoanRescheduleRequestTestBuilder {
         if (extraTerms != null) {
             map.put("extraTerms", extraTerms);
         }
-
-        map.put("recalculateInterest", recalculateInterest);
+        if (recalculateInterest) {
+            map.put("recalculateInterest", recalculateInterest);
+        }
 
         if (newInterestRate != null) {
             map.put("newInterestRate", newInterestRate);
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java
index fdd9004..3f40da0 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java
@@ -144,6 +144,13 @@ public class LoanTransactionHelper {
         return Utils.performServerGet(requestSpec, responseSpec, URL, param);
     }
 
+    public Object getLoanDetailExcludeFutureSchedule(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
+            final Integer loanID, final String param) {
+        final String URL = "/fineract-provider/api/v1/loans/" + loanID + "?associations=all&exclude=guarantors,futureSchedule&"
+                + Utils.TENANT_IDENTIFIER;
+        return Utils.performServerGet(requestSpec, responseSpec, URL, param);
+    }
+
     public String getLoanDetails(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, final Integer loanID) {
         final String URL = "/fineract-provider/api/v1/loans/" + loanID + "?associations=all&" + Utils.TENANT_IDENTIFIER;
         return Utils.performServerGet(requestSpec, responseSpec, URL, null);