fineract-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nazeer1100...@apache.org
Subject [1/2] incubator-fineract git commit: Center Rescheduling
Date Wed, 02 Mar 2016 12:35:19 GMT
Repository: incubator-fineract
Updated Branches:
  refs/heads/develop 00e0ea673 -> 1485dc9a8


Center Rescheduling


Project: http://git-wip-us.apache.org/repos/asf/incubator-fineract/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-fineract/commit/a01c1e36
Tree: http://git-wip-us.apache.org/repos/asf/incubator-fineract/tree/a01c1e36
Diff: http://git-wip-us.apache.org/repos/asf/incubator-fineract/diff/a01c1e36

Branch: refs/heads/develop
Commit: a01c1e361ff2cf91eafe8888102b492f67030476
Parents: 8d160d3
Author: sachinkulkarni12 <sachin.kulkarni@confluxtechnologies.com>
Authored: Wed Mar 2 17:12:31 2016 +0530
Committer: sachinkulkarni12 <sachin.kulkarni@confluxtechnologies.com>
Committed: Wed Mar 2 17:12:31 2016 +0530

----------------------------------------------------------------------
 .../LoanReschedulingWithinCenterTest.java       | 392 +++++++++++++++++++
 .../integrationtests/common/CalendarHelper.java |  41 ++
 .../data/CalendarHistoryDataWrapper.java        |  61 +++
 .../portfolio/calendar/domain/Calendar.java     |  10 +-
 ...arWritePlatformServiceJpaRepositoryImpl.java |  14 +-
 .../loanaccount/data/ScheduleGeneratorDTO.java  |  18 +-
 .../portfolio/loanaccount/domain/Loan.java      |  17 +-
 .../domain/DefaultScheduledDateGenerator.java   |  25 +-
 .../domain/LoanApplicationTerms.java            |  32 +-
 .../loanaccount/service/LoanUtilService.java    |  36 +-
 ...anWritePlatformServiceJpaRepositoryImpl.java |  28 +-
 11 files changed, 635 insertions(+), 39 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/a01c1e36/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/LoanReschedulingWithinCenterTest.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/LoanReschedulingWithinCenterTest.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/LoanReschedulingWithinCenterTest.java
new file mode 100644
index 0000000..a825bcb
--- /dev/null
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/LoanReschedulingWithinCenterTest.java
@@ -0,0 +1,392 @@
+/**
+ * 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.Assert.assertEquals;
+
+import java.sql.Timestamp;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.apache.fineract.integrationtests.common.CalendarHelper;
+import org.apache.fineract.integrationtests.common.CenterDomain;
+import org.apache.fineract.integrationtests.common.CenterHelper;
+import org.apache.fineract.integrationtests.common.ClientHelper;
+import org.apache.fineract.integrationtests.common.GroupHelper;
+import org.apache.fineract.integrationtests.common.OfficeHelper;
+import org.apache.fineract.integrationtests.common.Utils;
+import org.apache.fineract.integrationtests.common.accounting.Account;
+import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder;
+import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder;
+import org.apache.fineract.integrationtests.common.loans.LoanStatusChecker;
+import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
+import org.apache.fineract.integrationtests.common.organisation.StaffHelper;
+
+import com.google.gson.Gson;
+import com.jayway.restassured.builder.RequestSpecBuilder;
+import com.jayway.restassured.builder.ResponseSpecBuilder;
+import com.jayway.restassured.http.ContentType;
+import com.jayway.restassured.specification.RequestSpecification;
+import com.jayway.restassured.specification.ResponseSpecification;
+
+public class LoanReschedulingWithinCenterTest {
+
+    private RequestSpecification requestSpec;
+    private ResponseSpecification responseSpec;
+    private LoanTransactionHelper loanTransactionHelper;
+    private ResponseSpecification generalResponseSpec;
+    private LoanApplicationApprovalTest loanApplicationApprovalTest;
+
+    @Before
+    public void setup() {
+        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.loanApplicationApprovalTest = new LoanApplicationApprovalTest();
+        this.generalResponseSpec = new ResponseSpecBuilder().build();
+    }
+
+    @SuppressWarnings("rawtypes")
+    @Test
+    public void testCenterReschedulingLoansWithInterestRecalculationEnabled() {
+
+        Integer officeId = new OfficeHelper(requestSpec, responseSpec).createOffice("01 July 2007");
+        String name = "TestFullCreation" + new Timestamp(new java.util.Date().getTime());
+        String externalId = Utils.randomStringGenerator("ID_", 7, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
+        int staffId = StaffHelper.createStaff(requestSpec, responseSpec);
+        int[] groupMembers = generateGroupMembers(1, officeId);
+        final String centerActivationDate = "01 July 2007";
+        Integer centerId = CenterHelper.createCenter(name, officeId, externalId, staffId, groupMembers, centerActivationDate, requestSpec,
+                responseSpec);
+        CenterDomain center = CenterHelper.retrieveByID(centerId, requestSpec, responseSpec);
+        Integer groupId = groupMembers[0];
+        Assert.assertNotNull(center);
+        Assert.assertTrue(center.getStaffId() == staffId);
+        Assert.assertTrue(center.isActive() == true);
+
+        Integer calendarId = createCalendarMeeting(centerId);
+
+        Integer clientId = createClient(officeId);
+
+        associateClientsToGroup(groupId, clientId);
+        
+        DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy");
+        dateFormat.setTimeZone(Utils.getTimeZoneOfTenant());
+        Calendar today = Calendar.getInstance(Utils.getTimeZoneOfTenant());
+        today.add(Calendar.DAY_OF_MONTH, -14);
+        // CREATE A LOAN PRODUCT
+        final String disbursalDate = dateFormat.format(today.getTime());
+        final String recalculationRestFrequencyDate = "01 January 2012";
+        final boolean isMultiTrancheLoan = false;
+
+        // CREATE LOAN MULTIDISBURSAL PRODUCT WITH INTEREST RECALCULATION
+        final Integer loanProductID = createLoanProductWithInterestRecalculation(LoanProductTestBuilder.RBI_INDIA_STRATEGY,
+                LoanProductTestBuilder.RECALCULATION_COMPOUNDING_METHOD_NONE,
+                LoanProductTestBuilder.RECALCULATION_STRATEGY_REDUCE_NUMBER_OF_INSTALLMENTS,
+                LoanProductTestBuilder.RECALCULATION_FREQUENCY_TYPE_DAILY, "0", recalculationRestFrequencyDate,
+                LoanProductTestBuilder.INTEREST_APPLICABLE_STRATEGY_ON_PRE_CLOSE_DATE, null, isMultiTrancheLoan);
+
+        // APPLY FOR TRANCHE LOAN WITH INTEREST RECALCULATION
+        final Integer loanId = applyForLoanApplicationForInterestRecalculation(clientId, groupId, calendarId, loanProductID, disbursalDate,
+                recalculationRestFrequencyDate, LoanApplicationTestBuilder.RBI_INDIA_STRATEGY, new ArrayList<HashMap>(0), null);
+
+        // Test for loan account is created
+        Assert.assertNotNull(loanId);
+        HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanId);
+
+        // Test for loan account is created, can be approved
+        this.loanTransactionHelper.approveLoan(disbursalDate, loanId);
+        loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanId);
+        LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
+
+        // Test for loan account approved can be disbursed
+        this.loanTransactionHelper.disburseLoan(disbursalDate, loanId);
+        loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanId);
+        LoanStatusChecker.verifyLoanIsActive(loanStatusHashMap);
+
+        System.out.println("---------------------------------CHANGING GROUP MEETING DATE ------------------------------------------");
+        Calendar todaysdate = Calendar.getInstance(Utils.getTimeZoneOfTenant());
+        todaysdate.add(Calendar.DAY_OF_MONTH, 14);
+        String oldMeetingDate = dateFormat.format(todaysdate.getTime());
+        todaysdate.add(Calendar.DAY_OF_MONTH, 1);
+        final String centerMeetingNewStartDate = dateFormat.format(todaysdate.getTime());
+        CalendarHelper.updateMeetingCalendarForCenter(this.requestSpec, this.responseSpec, centerId, calendarId.toString(), oldMeetingDate,
+                centerMeetingNewStartDate);
+
+        ArrayList loanRepaymnetSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(requestSpec, generalResponseSpec, loanId);
+        // VERIFY RESCHEDULED DATE
+        ArrayList dueDateLoanSchedule = (ArrayList) ((HashMap) loanRepaymnetSchedule.get(2)).get("dueDate");
+        assertEquals(getDateAsArray(todaysdate, 0), dueDateLoanSchedule);
+
+        // VERIFY THE INTEREST
+        Float interestDue = (Float) ((HashMap) loanRepaymnetSchedule.get(2)).get("interestDue");
+        assertEquals(String.valueOf(interestDue), "90.82");
+
+    }
+    
+    private void associateClientsToGroup(Integer groupId, Integer clientId) {
+        // Associate client to the group
+        GroupHelper.associateClient(this.requestSpec, this.responseSpec, groupId.toString(), clientId.toString());
+        GroupHelper.verifyGroupMembers(this.requestSpec, this.responseSpec, groupId, clientId);
+    }
+
+    private Integer createClient(Integer officeId) {
+        // CREATE CLIENT
+        final String clientActivationDate = "01 July 2014";
+        Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec, clientActivationDate, officeId.toString());
+        ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientId);
+        return clientId;
+    }
+
+    private Integer createCalendarMeeting(Integer centerId) {
+        DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy");
+        dateFormat.setTimeZone(Utils.getTimeZoneOfTenant());
+        Calendar today = Calendar.getInstance(Utils.getTimeZoneOfTenant());
+        final String startDate = dateFormat.format(today.getTime());
+        final String frequency = "2"; // 2:Weekly
+        final String interval = "2"; // Every one week
+        final Integer repeatsOnDay = today.get(Calendar.DAY_OF_WEEK) - 1;
+
+        Integer calendarId = CalendarHelper.createMeetingForGroup(this.requestSpec, this.responseSpec, centerId, startDate, frequency,
+                interval, repeatsOnDay.toString());
+        System.out.println("calendarId " + calendarId);
+        return calendarId;
+    }
+
+    @SuppressWarnings("rawtypes")
+    @Test
+    public void testCenterReschedulingMultiTrancheLoansWithInterestRecalculationEnabled() {
+
+        Integer officeId = new OfficeHelper(requestSpec, responseSpec).createOffice("01 July 2007");
+        String name = "TestFullCreation" + new Timestamp(new java.util.Date().getTime());
+        String externalId = Utils.randomStringGenerator("ID_", 7, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
+        int staffId = StaffHelper.createStaff(requestSpec, responseSpec);
+        int[] groupMembers = generateGroupMembers(1, officeId);
+        final String centerActivationDate = "01 July 2007";
+        Integer centerId = CenterHelper.createCenter(name, officeId, externalId, staffId, groupMembers, centerActivationDate, requestSpec,
+                responseSpec);
+        CenterDomain center = CenterHelper.retrieveByID(centerId, requestSpec, responseSpec);
+        Integer groupId = groupMembers[0];
+        Assert.assertNotNull(center);
+        Assert.assertTrue(center.getStaffId() == staffId);
+        Assert.assertTrue(center.isActive() == true);
+
+        Integer calendarId = createCalendarMeeting(centerId);
+
+        Integer clientId = createClient(officeId);
+
+        associateClientsToGroup(groupId, clientId);
+
+        // CREATE A LOAN PRODUCT
+        DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy");
+        dateFormat.setTimeZone(Utils.getTimeZoneOfTenant());
+        Calendar today = Calendar.getInstance(Utils.getTimeZoneOfTenant());
+        today.add(Calendar.DAY_OF_MONTH, -14);
+        // CREATE A LOAN PRODUCT
+        final String approveDate = dateFormat.format(today.getTime());
+        final String expectedDisbursementDate = dateFormat.format(today.getTime());
+        final String disbursementDate = dateFormat.format(today.getTime());
+        final String approvalAmount = "10000";
+        final String recalculationRestFrequencyDate = "01 January 2012";
+        final boolean isMultiTrancheLoan = true;
+
+        // CREATE LOAN MULTIDISBURSAL PRODUCT WITH INTEREST RECALCULATION
+        final Integer loanProductID = createLoanProductWithInterestRecalculation(LoanProductTestBuilder.RBI_INDIA_STRATEGY,
+                LoanProductTestBuilder.RECALCULATION_COMPOUNDING_METHOD_NONE,
+                LoanProductTestBuilder.RECALCULATION_STRATEGY_REDUCE_NUMBER_OF_INSTALLMENTS,
+                LoanProductTestBuilder.RECALCULATION_FREQUENCY_TYPE_DAILY, "0", recalculationRestFrequencyDate,
+                LoanProductTestBuilder.INTEREST_APPLICABLE_STRATEGY_ON_PRE_CLOSE_DATE, null, isMultiTrancheLoan);
+
+        // CREATE TRANCHES
+        List<HashMap> createTranches = new ArrayList<>();
+        createTranches.add(this.loanApplicationApprovalTest.createTrancheDetail(disbursementDate, "5000"));
+        createTranches.add(this.loanApplicationApprovalTest.createTrancheDetail("25 June 2016", "5000"));
+
+        // APPROVE TRANCHES
+        List<HashMap> approveTranches = new ArrayList<>();
+        approveTranches.add(this.loanApplicationApprovalTest.createTrancheDetail(disbursementDate, "5000"));
+        approveTranches.add(this.loanApplicationApprovalTest.createTrancheDetail("25 June 2016", "5000"));
+
+        // APPLY FOR TRANCHE LOAN WITH INTEREST RECALCULATION
+        final Integer loanID = applyForLoanApplicationForInterestRecalculation(clientId, groupId, calendarId, loanProductID,
+                disbursementDate, recalculationRestFrequencyDate, LoanApplicationTestBuilder.RBI_INDIA_STRATEGY, new ArrayList<HashMap>(0),
+                createTranches);
+        HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
+
+        // VALIDATE THE LOAN STATUS
+        LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
+
+        System.out.println("-----------------------------------APPROVE LOAN-----------------------------------------------------------");
+        loanStatusHashMap = this.loanTransactionHelper.approveLoanWithApproveAmount(approveDate, expectedDisbursementDate, approvalAmount,
+                loanID, approveTranches);
+
+        // VALIDATE THE LOAN IS APPROVED
+        LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
+        LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap);
+
+        // DISBURSE A FIRST TRANCHE
+        this.loanTransactionHelper.disburseLoan(disbursementDate, loanID);
+        loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
+
+        System.out.println("---------------------------------CHANGING GROUP MEETING DATE ------------------------------------------");
+        Calendar todaysdate = Calendar.getInstance(Utils.getTimeZoneOfTenant());
+        todaysdate.add(Calendar.DAY_OF_MONTH, 14);
+        String oldMeetingDate = dateFormat.format(todaysdate.getTime());
+        todaysdate.add(Calendar.DAY_OF_MONTH, 1);
+        final String centerMeetingNewStartDate = dateFormat.format(todaysdate.getTime());
+        CalendarHelper.updateMeetingCalendarForCenter(this.requestSpec, this.responseSpec, centerId, calendarId.toString(), oldMeetingDate,
+                centerMeetingNewStartDate);
+
+        ArrayList loanRepaymnetSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(requestSpec, generalResponseSpec, loanID);
+        // VERIFY RESCHEDULED DATE
+        ArrayList dueDateLoanSchedule = (ArrayList) ((HashMap) loanRepaymnetSchedule.get(2)).get("dueDate");
+        assertEquals(getDateAsArray(todaysdate, 0), dueDateLoanSchedule);
+
+        // VERIFY THE INTEREST
+        Float interestDue = (Float) ((HashMap) loanRepaymnetSchedule.get(2)).get("interestDue");
+        assertEquals(String.valueOf(interestDue), "41.05");
+
+    }
+
+    private Integer createLoanProductWithInterestRecalculation(final String repaymentStrategy,
+            final String interestRecalculationCompoundingMethod, final String rescheduleStrategyMethod,
+            final String recalculationRestFrequencyType, final String recalculationRestFrequencyInterval,
+            final String recalculationRestFrequencyDate, final String preCloseInterestCalculationStrategy, final Account[] accounts,
+            final boolean isMultiTrancheLoan) {
+        final String recalculationCompoundingFrequencyType = null;
+        final String recalculationCompoundingFrequencyInterval = null;
+        final String recalculationCompoundingFrequencyDate = null;
+        return createLoanProductWithInterestRecalculation(repaymentStrategy, interestRecalculationCompoundingMethod,
+                rescheduleStrategyMethod, recalculationRestFrequencyType, recalculationRestFrequencyInterval,
+                recalculationRestFrequencyDate, recalculationCompoundingFrequencyType, recalculationCompoundingFrequencyInterval,
+                recalculationCompoundingFrequencyDate, preCloseInterestCalculationStrategy, accounts, null, false, isMultiTrancheLoan);
+    }
+
+    private Integer createLoanProductWithInterestRecalculation(final String repaymentStrategy,
+            final String interestRecalculationCompoundingMethod, final String rescheduleStrategyMethod,
+            final String recalculationRestFrequencyType, final String recalculationRestFrequencyInterval,
+            final String recalculationRestFrequencyDate, final String recalculationCompoundingFrequencyType,
+            final String recalculationCompoundingFrequencyInterval, final String recalculationCompoundingFrequencyDate,
+            final String preCloseInterestCalculationStrategy, final Account[] accounts, final String chargeId,
+            boolean isArrearsBasedOnOriginalSchedule, final boolean isMultiTrancheLoan) {
+        System.out.println("------------------------------CREATING NEW LOAN PRODUCT ---------------------------------------");
+        LoanProductTestBuilder builder = new LoanProductTestBuilder()
+                .withPrincipal("10000.00")
+                .withNumberOfRepayments("12")
+                .withRepaymentAfterEvery("2")
+                .withRepaymentTypeAsWeek()
+                .withinterestRatePerPeriod("2")
+                .withInterestRateFrequencyTypeAsMonths()
+                .withTranches(isMultiTrancheLoan)
+                .withInterestCalculationPeriodTypeAsRepaymentPeriod(true)
+                .withRepaymentStrategy(repaymentStrategy)
+                .withInterestTypeAsDecliningBalance()
+                .withInterestRecalculationDetails(interestRecalculationCompoundingMethod, rescheduleStrategyMethod,
+                        preCloseInterestCalculationStrategy)
+                .withInterestRecalculationRestFrequencyDetails(recalculationRestFrequencyType, recalculationRestFrequencyInterval,
+                        recalculationRestFrequencyDate)
+                .withInterestRecalculationCompoundingFrequencyDetails(recalculationCompoundingFrequencyType,
+                        recalculationCompoundingFrequencyInterval, recalculationCompoundingFrequencyDate);
+        if (accounts != null) {
+            builder = builder.withAccountingRulePeriodicAccrual(accounts);
+        }
+
+        if (isArrearsBasedOnOriginalSchedule) builder = builder.withArrearsConfiguration();
+
+        final String loanProductJSON = builder.build(chargeId);
+        return this.loanTransactionHelper.getLoanProductId(loanProductJSON);
+    }
+
+    @SuppressWarnings("rawtypes")
+    private Integer applyForLoanApplicationForInterestRecalculation(final Integer clientID, Integer groupId, Integer calendarId,
+            final Integer loanProductID, final String disbursementDate, final String restStartDate, final String repaymentStrategy,
+            final List<HashMap> charges, List<HashMap> tranches) {
+        final String graceOnInterestPayment = null;
+        final String compoundingStartDate = null;
+        final String graceOnPrincipalPayment = null;
+        return applyForLoanApplicationForInterestRecalculation(clientID, groupId, calendarId, loanProductID, disbursementDate,
+                restStartDate, compoundingStartDate, repaymentStrategy, charges, graceOnInterestPayment, graceOnPrincipalPayment, tranches);
+    }
+
+    @SuppressWarnings({ "rawtypes", "unused" })
+    private Integer applyForLoanApplicationForInterestRecalculation(final Integer clientID, Integer groupId, Integer calendarId,
+            final Integer loanProductID, final String disbursementDate, final String restStartDate, final String compoundingStartDate,
+            final String repaymentStrategy, final List<HashMap> charges, final String graceOnInterestPayment,
+            final String graceOnPrincipalPayment, List<HashMap> tranches) {
+        System.out.println("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
+        final String loanApplicationJSON = new LoanApplicationTestBuilder() //
+                .withPrincipal("10000.00") //
+                .withLoanTermFrequency("24") //
+                .withLoanTermFrequencyAsWeeks() //
+                .withNumberOfRepayments("12") //
+                .withRepaymentEveryAfter("2") //
+                .withRepaymentFrequencyTypeAsWeeks() //
+                .withInterestRatePerPeriod("2").withLoanType("jlg") //
+                .withCalendarID(calendarId.toString()).withAmortizationTypeAsEqualInstallments() //
+                .withFixedEmiAmount("") //
+                .withTranches(tranches).withInterestTypeAsDecliningBalance() //
+                .withInterestCalculationPeriodTypeAsDays() //
+                .withInterestCalculationPeriodTypeAsDays() //
+                .withExpectedDisbursementDate(disbursementDate) //
+                .withSubmittedOnDate(disbursementDate) //
+                .withRestFrequencyDate(restStartDate)//
+                .withwithRepaymentStrategy(repaymentStrategy) //
+                .withCharges(charges)//
+                .build(clientID.toString(), groupId.toString(), loanProductID.toString(), null);
+        return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
+    }
+
+    private int[] generateGroupMembers(int size, int officeId) {
+        int[] groupMembers = new int[size];
+        for (int i = 0; i < groupMembers.length; i++) {
+            final HashMap<String, String> map = new HashMap<>();
+            map.put("officeId", "" + officeId);
+            map.put("name", Utils.randomStringGenerator("Group_Name_", 5));
+            map.put("externalId", Utils.randomStringGenerator("ID_", 7, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"));
+            map.put("dateFormat", "dd MMMM yyyy");
+            map.put("locale", "en");
+            map.put("active", "true");
+            map.put("activationDate", "04 March 2011");
+
+            groupMembers[i] = Utils.performServerPost(requestSpec, responseSpec, "/fineract-provider/api/v1/groups?"
+                    + Utils.TENANT_IDENTIFIER, new Gson().toJson(map), "groupId");
+        }
+        return groupMembers;
+    }
+
+    private List getDateAsArray(Calendar date, int addPeriod) {
+        return getDateAsArray(date, addPeriod, Calendar.DAY_OF_MONTH);
+    }
+
+    private List getDateAsArray(Calendar date, int addvalue, int type) {
+        date.add(type, addvalue);
+        return new ArrayList<>(Arrays.asList(date.get(Calendar.YEAR), date.get(Calendar.MONTH) + 1, date.get(Calendar.DAY_OF_MONTH)));
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/a01c1e36/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/CalendarHelper.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/CalendarHelper.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/CalendarHelper.java
index 0e9423b..e4bac93 100644
--- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/CalendarHelper.java
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/CalendarHelper.java
@@ -32,6 +32,8 @@ public class CalendarHelper {
     private static final String BASE_URL = "/fineract-provider/api/v1/";
     private static final String PARENT_ENTITY_NAME = "groups/";
     private static final String ENITY_NAME = "/calendars";
+    private static final String Center_Entity = "centers/";
+    private static final String Edit_Calendar = "editcalendarbasedonmeetingdates/";
 
     public static Integer createMeetingCalendarForGroup(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
             final Integer groupId, final String startDate, final String frequency, final String interval, final String repeatsOnDay) {
@@ -86,4 +88,43 @@ public class CalendarHelper {
         final Integer responseCalendarId = from(responseCalendarDetailsinJSON).get("id");
         assertEquals("ERROR IN CREATING THE CALENDAR", generatedCalendarId, responseCalendarId);
     }
+    
+    public static Integer createMeetingForGroup(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
+    final Integer groupId, final String startDate, final String frequency, final String interval, final String repeatsOnDay) {
+
+    	System.out.println("---------------------------------CREATING A MEETING CALENDAR FOR THE GROUP------------------------------");
+
+    	final String CALENDAR_RESOURCE_URL = BASE_URL + Center_Entity + groupId + ENITY_NAME + "?" + Utils.TENANT_IDENTIFIER;
+
+    	System.out.println(CALENDAR_RESOURCE_URL);
+
+    	return Utils.performServerPost(requestSpec, responseSpec, CALENDAR_RESOURCE_URL,
+    			getTestCalendarAsJSON(frequency, interval, repeatsOnDay, startDate), "resourceId");
+    }
+
+    public static Integer updateMeetingCalendarForCenter(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
+            Integer centerId, String calendarID, String oldDate, String startDate) {
+
+        System.out.println("---------------------------------UPADATING A MEETING CALENDAR FOR THE CENTER------------------------------");
+
+        final String CALENDAR_RESOURCE_URL = BASE_URL + Center_Entity + centerId + ENITY_NAME + "/" + calendarID + "?"
+                + Utils.TENANT_IDENTIFIER;
+
+        System.out.println(CALENDAR_RESOURCE_URL);
+
+        return Utils.performServerPut(requestSpec, responseSpec, CALENDAR_RESOURCE_URL, getTestCalendarMeetingAsJSON(oldDate, startDate),
+                "resourceId");
+
+    }
+
+    private static String getTestCalendarMeetingAsJSON(String oldDate, String startDate) {
+        final HashMap<String, String> map = new HashMap<>();
+        map.put("dateFormat", "dd MMMM yyyy");
+        map.put("locale", "en");
+        map.put("newMeetingDate", startDate);
+        map.put("presentMeetingDate", oldDate);
+        map.put("reschedulebasedOnMeetingDates", "true");
+        System.out.println("map : " + map);
+        return new Gson().toJson(map);
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/a01c1e36/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/data/CalendarHistoryDataWrapper.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/data/CalendarHistoryDataWrapper.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/data/CalendarHistoryDataWrapper.java
new file mode 100644
index 0000000..6e8e678
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/data/CalendarHistoryDataWrapper.java
@@ -0,0 +1,61 @@
+/**
+ * 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.portfolio.calendar.data;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.fineract.portfolio.calendar.domain.CalendarHistory;
+import org.joda.time.LocalDate;
+
+
+public class CalendarHistoryDataWrapper {
+    
+    private final List<CalendarHistory> calendarHistoryList;
+    
+    public CalendarHistoryDataWrapper(final Set<CalendarHistory> calendarHistoryList){
+        this.calendarHistoryList = new ArrayList<>();       
+        this.calendarHistoryList.addAll(calendarHistoryList);
+        final Comparator<CalendarHistory> orderByDate = new Comparator<CalendarHistory>() {
+            @Override
+            public int compare(CalendarHistory calendarHistory1, CalendarHistory calendarHistory2) {
+                return calendarHistory1.getEndDateLocalDate().compareTo(calendarHistory2.getEndDateLocalDate());
+            }
+        };
+        Collections.sort(this.calendarHistoryList, orderByDate);
+    }
+    
+    public CalendarHistory getCalendarHistory(final LocalDate dueRepaymentPeriodDate) {
+        CalendarHistory calendarHistory = null;
+        for (CalendarHistory history : this.calendarHistoryList) {
+            if (history.getEndDateLocalDate().isAfter(dueRepaymentPeriodDate)) {
+                calendarHistory = history;
+               break;
+            }
+        }
+        return calendarHistory;
+    }
+        
+    public List<CalendarHistory> getCalendarHistoryList(){
+        return this.calendarHistoryList;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/a01c1e36/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/domain/Calendar.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/domain/Calendar.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/domain/Calendar.java
index 103b96f..98e8096 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/domain/Calendar.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/domain/Calendar.java
@@ -95,7 +95,7 @@ public class Calendar extends AbstractAuditableCustom<AppUser, Long> {
 
     @OneToMany(fetch = FetchType.EAGER)
     @JoinColumn(name = "calendar_id")
-    private final Set<CalendarHistory> calendarHistory = new HashSet<>();
+    private Set<CalendarHistory> calendarHistory = new HashSet<>();
 
     protected Calendar() {
 
@@ -581,4 +581,12 @@ public class Calendar extends AbstractAuditableCustom<AppUser, Long> {
         this.startDate = startDate.toDate();
         this.endDate = endDate.toDate();
     }
+    
+    public Set<CalendarHistory> getCalendarHistory(){
+    	return this.calendarHistory;
+    }
+    
+    public void updateCalendarHistory(final Set<CalendarHistory> calendarHistory){
+    	this.calendarHistory = calendarHistory;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/a01c1e36/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarWritePlatformServiceJpaRepositoryImpl.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarWritePlatformServiceJpaRepositoryImpl.java
index 7e59642..438c687 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarWritePlatformServiceJpaRepositoryImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarWritePlatformServiceJpaRepositoryImpl.java
@@ -24,6 +24,7 @@ import java.util.Collection;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
 import org.apache.fineract.infrastructure.core.api.JsonCommand;
@@ -239,7 +240,6 @@ public class CalendarWritePlatformServiceJpaRepositoryImpl implements CalendarWr
         if (calendarForUpdate == null) { throw new CalendarNotFoundException(calendarId); }
         
         final Date oldStartDate = calendarForUpdate.getStartDate();
-        final LocalDate currentDate = DateUtils.getLocalDateOfTenant();
         // create calendar history before updating calendar
         final CalendarHistory calendarHistory = new CalendarHistory(calendarForUpdate, oldStartDate);
 
@@ -288,12 +288,12 @@ public class CalendarWritePlatformServiceJpaRepositoryImpl implements CalendarWr
         if (!changes.isEmpty()) {
             // update calendar history table only if there is a change in
             // calendar start date.
-            if (currentDate.isAfter(new LocalDate(oldStartDate))) {
-                final Date endDate = calendarForUpdate.getStartDateLocalDate().minusDays(1).toDate();
-                calendarHistory.updateEndDate(endDate);
-                this.calendarHistoryRepository.save(calendarHistory);
-            }
-
+            final Date endDate = presentMeetingDate.minusDays(1).toDate();
+            calendarHistory.updateEndDate(endDate);
+            this.calendarHistoryRepository.save(calendarHistory);
+            Set<CalendarHistory> history = calendarForUpdate.getCalendarHistory();
+            history.add(calendarHistory);
+            calendarForUpdate.updateCalendarHistory(history);
             this.calendarRepository.saveAndFlush(calendarForUpdate);
 
             if (this.configurationDomainService.isRescheduleFutureRepaymentsEnabled() && calendarForUpdate.isRepeating()) {

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/a01c1e36/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/ScheduleGeneratorDTO.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/ScheduleGeneratorDTO.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/ScheduleGeneratorDTO.java
index dde8599..a8f7a35 100755
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/ScheduleGeneratorDTO.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/ScheduleGeneratorDTO.java
@@ -19,6 +19,8 @@
 package org.apache.fineract.portfolio.loanaccount.data;
 
 import org.apache.fineract.organisation.monetary.domain.ApplicationCurrency;
+import org.apache.fineract.portfolio.calendar.data.CalendarHistoryDataWrapper;
+import org.apache.fineract.portfolio.calendar.domain.Calendar;
 import org.apache.fineract.portfolio.calendar.domain.CalendarInstance;
 import org.apache.fineract.portfolio.floatingrates.data.FloatingRateDTO;
 import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleGeneratorFactory;
@@ -35,11 +37,14 @@ public class ScheduleGeneratorDTO {
     LocalDate recalculateFrom;
     final Long overdurPenaltyWaitPeriod;
     final FloatingRateDTO floatingRateDTO;
+    final Calendar calendar;
+    final CalendarHistoryDataWrapper calendarHistoryDataWrapper;
 
     public ScheduleGeneratorDTO(final LoanScheduleGeneratorFactory loanScheduleFactory, final ApplicationCurrency applicationCurrency,
             final LocalDate calculatedRepaymentsStartingFromDate, final HolidayDetailDTO holidayDetailDTO,
             final CalendarInstance calendarInstanceForInterestRecalculation, final CalendarInstance compoundingCalendarInstance,
-            final LocalDate recalculateFrom, final Long overdurPenaltyWaitPeriod, final FloatingRateDTO floatingRateDTO) {
+            final LocalDate recalculateFrom, final Long overdurPenaltyWaitPeriod, final FloatingRateDTO floatingRateDTO,
+            final Calendar calendar, final CalendarHistoryDataWrapper calendarHistoryDataWrapper) {
 
         this.loanScheduleFactory = loanScheduleFactory;
         this.applicationCurrency = applicationCurrency;
@@ -50,6 +55,9 @@ public class ScheduleGeneratorDTO {
         this.overdurPenaltyWaitPeriod = overdurPenaltyWaitPeriod;
         this.holidayDetailDTO = holidayDetailDTO;
         this.floatingRateDTO = floatingRateDTO;
+        this.calendar = calendar;
+        this.calendarHistoryDataWrapper  = calendarHistoryDataWrapper;
+
     }
 
     public LoanScheduleGeneratorFactory getLoanScheduleFactory() {
@@ -99,5 +107,13 @@ public class ScheduleGeneratorDTO {
     public FloatingRateDTO getFloatingRateDTO() {
         return this.floatingRateDTO;
     }
+    
+    public Calendar getCalendar(){
+    	return this.calendar;
+    }
+    
+    public CalendarHistoryDataWrapper getCalendarHistoryDataWrapper(){
+        return this.calendarHistoryDataWrapper;
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/a01c1e36/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
index 56fd87c..78e284e 100755
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
@@ -71,7 +71,9 @@ import org.apache.fineract.organisation.staff.domain.Staff;
 import org.apache.fineract.organisation.workingdays.domain.WorkingDays;
 import org.apache.fineract.organisation.workingdays.service.WorkingDaysUtil;
 import org.apache.fineract.portfolio.accountdetails.domain.AccountType;
+import org.apache.fineract.portfolio.calendar.data.CalendarHistoryDataWrapper;
 import org.apache.fineract.portfolio.calendar.domain.Calendar;
+import org.apache.fineract.portfolio.calendar.domain.CalendarHistory;
 import org.apache.fineract.portfolio.calendar.domain.CalendarInstance;
 import org.apache.fineract.portfolio.calendar.service.CalendarUtils;
 import org.apache.fineract.portfolio.charge.domain.Charge;
@@ -5032,6 +5034,8 @@ public class Loan extends AbstractPersistable<Long> {
         InterestRecalculationCompoundingMethod compoundingMethod = null;
         RecalculationFrequencyType compoundingFrequencyType = null;
         LoanRescheduleStrategyMethod rescheduleStrategyMethod = null;
+        Calendar calendar = null;
+        CalendarHistoryDataWrapper calendarHistoryDataWrapper = null;
         if (this.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
             restCalendarInstance = scheduleGeneratorDTO.getCalendarInstanceForInterestRecalculation();
             compoundingCalendarInstance = scheduleGeneratorDTO.getCompoundingCalendarInstance();
@@ -5039,6 +5043,8 @@ public class Loan extends AbstractPersistable<Long> {
             compoundingMethod = this.loanInterestRecalculationDetails.getInterestRecalculationCompoundingMethod();
             compoundingFrequencyType = this.loanInterestRecalculationDetails.getCompoundingFrequencyType();
             rescheduleStrategyMethod = this.loanInterestRecalculationDetails.getRescheduleStrategyMethod();
+            calendar = scheduleGeneratorDTO.getCalendar();
+            calendarHistoryDataWrapper = scheduleGeneratorDTO.getCalendarHistoryDataWrapper();
         }
 
         BigDecimal annualNominalInterestRate = this.loanRepaymentScheduleDetail.getAnnualNominalInterestRate();
@@ -5053,7 +5059,7 @@ public class Loan extends AbstractPersistable<Long> {
                 this.maxOutstandingLoanBalance, getInterestChargedFromDate(), this.loanProduct.getPrincipalThresholdForLastInstallment(),
                 this.loanProduct.getInstallmentAmountInMultiplesOf(), recalculationFrequencyType, restCalendarInstance, compoundingMethod,
                 compoundingCalendarInstance, compoundingFrequencyType, this.loanProduct.preCloseInterestCalculationStrategy(),
-                rescheduleStrategyMethod, getApprovedPrincipal(), annualNominalInterestRate, loanTermVariations);
+                rescheduleStrategyMethod, calendar, getApprovedPrincipal(), annualNominalInterestRate, loanTermVariations, calendarHistoryDataWrapper);
         return loanApplicationTerms;
     }
 
@@ -5269,6 +5275,12 @@ public class Loan extends AbstractPersistable<Long> {
         final BigDecimal maxOutstandingBalance = getMaxOutstandingLoanBalance();
 
         final List<DisbursementData> disbursementData = getDisbursmentData();
+        
+        CalendarHistoryDataWrapper calendarHistoryDataWrapper = null;
+        if (loanCalendar != null) {
+            Set<CalendarHistory> calendarHistory = loanCalendar.getCalendarHistory();
+            calendarHistoryDataWrapper = new CalendarHistoryDataWrapper(calendarHistory);
+        }
 
         RecalculationFrequencyType recalculationFrequencyType = null;
         InterestRecalculationCompoundingMethod compoundingMethod = null;
@@ -5290,7 +5302,8 @@ public class Loan extends AbstractPersistable<Long> {
                 maxOutstandingBalance, interestChargedFromDate, this.loanProduct.getPrincipalThresholdForLastInstallment(),
                 this.loanProduct.getInstallmentAmountInMultiplesOf(), recalculationFrequencyType, restCalendarInstance, compoundingMethod,
                 compoundingCalendarInstance, compoundingFrequencyType, this.loanProduct.preCloseInterestCalculationStrategy(),
-                rescheduleStrategyMethod, loanCalendar, getApprovedPrincipal(), annualNominalInterestRate, loanTermVariations);
+                rescheduleStrategyMethod, loanCalendar, getApprovedPrincipal(), annualNominalInterestRate, loanTermVariations, 
+                calendarHistoryDataWrapper);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/a01c1e36/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/DefaultScheduledDateGenerator.java
----------------------------------------------------------------------
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 0a8ac12..a23f1e4 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
@@ -18,10 +18,13 @@
  */
 package org.apache.fineract.portfolio.loanaccount.loanschedule.domain;
 
+
 import org.apache.fineract.organisation.holiday.service.HolidayUtil;
 import org.apache.fineract.organisation.workingdays.domain.RepaymentRescheduleType;
 import org.apache.fineract.organisation.workingdays.service.WorkingDaysUtil;
+import org.apache.fineract.portfolio.calendar.data.CalendarHistoryDataWrapper;
 import org.apache.fineract.portfolio.calendar.domain.Calendar;
+import org.apache.fineract.portfolio.calendar.domain.CalendarHistory;
 import org.apache.fineract.portfolio.calendar.service.CalendarUtils;
 import org.apache.fineract.portfolio.common.domain.DayOfWeekType;
 import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
@@ -68,9 +71,25 @@ public class DefaultScheduledDateGenerator implements ScheduledDateGenerator {
                 // calendar associated with
                 // the loan, and we should use it in order to calculate next
                 // repayment
-                LocalDate seedDate = currentCalendar.getStartDateLocalDate();
-                String reccuringString = currentCalendar.getRecurrence();
-                dueRepaymentPeriodDate = CalendarUtils.getNewRepaymentMeetingDate(reccuringString, seedDate, dueRepaymentPeriodDate,
+                
+                CalendarHistory calendarHistory = null;
+                CalendarHistoryDataWrapper calendarHistoryDataWrapper = loanApplicationTerms.getCalendarHistoryDataWrapper();
+                if(calendarHistoryDataWrapper != null){
+                    calendarHistory = loanApplicationTerms.getCalendarHistoryDataWrapper().getCalendarHistory(dueRepaymentPeriodDate);
+                }
+ 
+                // get the start date from the calendar history
+                LocalDate seedDate = null;
+                String reccuringString = null;
+                if (calendarHistory == null) {
+                    seedDate = currentCalendar.getStartDateLocalDate();
+                    reccuringString = currentCalendar.getRecurrence();
+                } else {
+                    seedDate = calendarHistory.getStartDateLocalDate();
+                    reccuringString = calendarHistory.getRecurrence();
+                }
+
+                dueRepaymentPeriodDate = CalendarUtils.getNewRepaymentMeetingDate(reccuringString, seedDate, lastRepaymentDate.plusDays(1),
                         loanApplicationTerms.getRepaymentEvery(),
                         CalendarUtils.getMeetingFrequencyFromPeriodFrequencyType(loanApplicationTerms.getLoanTermPeriodFrequencyType()),
                         holidayDetailDTO.getWorkingDays());

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/a01c1e36/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java
index c33091c..80e2530 100755
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java
@@ -27,6 +27,7 @@ import org.apache.fineract.organisation.monetary.domain.ApplicationCurrency;
 import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
 import org.apache.fineract.organisation.monetary.domain.Money;
 import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
+import org.apache.fineract.portfolio.calendar.data.CalendarHistoryDataWrapper;
 import org.apache.fineract.portfolio.calendar.domain.Calendar;
 import org.apache.fineract.portfolio.calendar.domain.CalendarInstance;
 import org.apache.fineract.portfolio.common.domain.DayOfWeekType;
@@ -177,6 +178,8 @@ public final class LoanApplicationTerms {
     private Money adjustPrincipalForFlatLoans;
 
     private final LocalDate seedDate;
+    
+    private final CalendarHistoryDataWrapper calendarHistoryDataWrapper;
 
     public static LoanApplicationTerms assembleFrom(final ApplicationCurrency currency, final Integer loanTermFrequency,
             final PeriodFrequencyType loanTermPeriodFrequencyType, final Integer numberOfRepayments, final Integer repaymentEvery,
@@ -198,6 +201,7 @@ public final class LoanApplicationTerms {
 
         final LoanRescheduleStrategyMethod rescheduleStrategyMethod = null;
         final InterestRecalculationCompoundingMethod interestRecalculationCompoundingMethod = null;
+        final CalendarHistoryDataWrapper calendarHistoryDataWrapper = null;
         return new LoanApplicationTerms(currency, loanTermFrequency, loanTermPeriodFrequencyType, numberOfRepayments, repaymentEvery,
                 repaymentPeriodFrequencyType, nthDay, weekDayType, amortizationMethod, interestMethod, interestRatePerPeriod,
                 interestRatePeriodFrequencyType, annualNominalInterestRate, interestCalculationPeriodMethod,
@@ -207,7 +211,7 @@ public final class LoanApplicationTerms {
                 graceOnArrearsAgeing, daysInMonthType, daysInYearType, isInterestRecalculationEnabled, rescheduleStrategyMethod,
                 interestRecalculationCompoundingMethod, restCalendarInstance, recalculationFrequencyType, compoundingCalendarInstance,
                 compoundingFrequencyType, principalThresholdForLastInstalment, installmentAmountInMultiplesOf,
-                preClosureInterestCalculationStrategy, loanCalendar, approvedAmount, loanTermVariations);
+                preClosureInterestCalculationStrategy, loanCalendar, approvedAmount, loanTermVariations, calendarHistoryDataWrapper);
     }
 
     public static LoanApplicationTerms assembleFrom(final ApplicationCurrency applicationCurrency, final Integer loanTermFrequency,
@@ -224,13 +228,14 @@ public final class LoanApplicationTerms {
             final LoanRescheduleStrategyMethod rescheduleStrategyMethod, BigDecimal approvedAmount, BigDecimal annualNominalInterestRate,
             List<LoanTermVariationsData> loanTermVariations) {
         final Calendar loanCalendar = null;
+        final CalendarHistoryDataWrapper calendarHistoryDataWrapper = null;
 
         return assembleFrom(applicationCurrency, loanTermFrequency, loanTermPeriodFrequencyType, nthDay, dayOfWeek,
                 expectedDisbursementDate, repaymentsStartingFromDate, calculatedRepaymentsStartingFromDate, inArrearsTolerance,
                 loanProductRelatedDetail, multiDisburseLoan, emiAmount, disbursementDatas, maxOutstandingBalance, interestChargedFromDate,
                 principalThresholdForLastInstalment, installmentAmountInMultiplesOf, recalculationFrequencyType, restCalendarInstance,
                 compoundingMethod, compoundingCalendarInstance, compoundingFrequencyType, loanPreClosureInterestCalculationStrategy,
-                rescheduleStrategyMethod, loanCalendar, approvedAmount, annualNominalInterestRate, loanTermVariations);
+                rescheduleStrategyMethod, loanCalendar, approvedAmount, annualNominalInterestRate, loanTermVariations, calendarHistoryDataWrapper);
     }
 
     public static LoanApplicationTerms assembleFrom(final ApplicationCurrency applicationCurrency, final Integer loanTermFrequency,
@@ -245,7 +250,8 @@ public final class LoanApplicationTerms {
             final CalendarInstance compoundingCalendarInstance, final RecalculationFrequencyType compoundingFrequencyType,
             final LoanPreClosureInterestCalculationStrategy loanPreClosureInterestCalculationStrategy,
             final LoanRescheduleStrategyMethod rescheduleStrategyMethod, final Calendar loanCalendar, BigDecimal approvedAmount,
-            BigDecimal annualNominalInterestRate, final List<LoanTermVariationsData> loanTermVariations) {
+            BigDecimal annualNominalInterestRate, final List<LoanTermVariationsData> loanTermVariations, 
+            final CalendarHistoryDataWrapper calendarHistoryDataWrapper) {
 
         final Integer numberOfRepayments = loanProductRelatedDetail.getNumberOfRepayments();
         final Integer repaymentEvery = loanProductRelatedDetail.getRepayEvery();
@@ -277,7 +283,7 @@ public final class LoanApplicationTerms {
                 loanProductRelatedDetail.getGraceOnDueDate(), daysInMonthType, daysInYearType, isInterestRecalculationEnabled,
                 rescheduleStrategyMethod, compoundingMethod, restCalendarInstance, recalculationFrequencyType, compoundingCalendarInstance,
                 compoundingFrequencyType, principalThresholdForLastInstalment, installmentAmountInMultiplesOf,
-                loanPreClosureInterestCalculationStrategy, loanCalendar, approvedAmount, loanTermVariations);
+                loanPreClosureInterestCalculationStrategy, loanCalendar, approvedAmount, loanTermVariations, calendarHistoryDataWrapper);
     }
 
     public static LoanApplicationTerms assembleFrom(final ApplicationCurrency applicationCurrency, final Integer loanTermFrequency,
@@ -289,8 +295,8 @@ public final class LoanApplicationTerms {
             final CalendarInstance restCalendarInstance, final RecalculationFrequencyType recalculationFrequencyType,
             final CalendarInstance compoundingCalendarInstance, final RecalculationFrequencyType compoundingFrequencyType,
             final BigDecimal principalThresholdForLastInstalment, final Integer installmentAmountInMultiplesOf,
-            final LoanPreClosureInterestCalculationStrategy loanPreClosureInterestCalculationStrategy, BigDecimal approvedAmount,
-            final BigDecimal annualNominalInterestRate, final List<LoanTermVariationsData> loanTermVariations) {
+            final LoanPreClosureInterestCalculationStrategy loanPreClosureInterestCalculationStrategy, final Calendar loanCalendar,
+            BigDecimal approvedAmount, final BigDecimal annualNominalInterestRate, final List<LoanTermVariationsData> loanTermVariations) {
 
         final Integer numberOfRepayments = loanProductRelatedDetail.getNumberOfRepayments();
         final Integer repaymentEvery = loanProductRelatedDetail.getRepayEvery();
@@ -319,7 +325,8 @@ public final class LoanApplicationTerms {
             rescheduleStrategyMethod = interestRecalculationDetails.getRescheduleStrategyMethod();
             interestRecalculationCompoundingMethod = interestRecalculationDetails.getInterestRecalculationCompoundingMethod();
         }
-        final Calendar loanCalendar = null;
+        final CalendarHistoryDataWrapper calendarHistoryDataWrapper = null;
+        
         return new LoanApplicationTerms(applicationCurrency, loanTermFrequency, loanTermPeriodFrequencyType, numberOfRepayments,
                 repaymentEvery, repaymentPeriodFrequencyType, null, null, amortizationMethod, interestMethod, interestRatePerPeriod,
                 interestRatePeriodFrequencyType, annualNominalInterestRate, interestCalculationPeriodMethod,
@@ -329,7 +336,7 @@ public final class LoanApplicationTerms {
                 loanProductRelatedDetail.getGraceOnDueDate(), daysInMonthType, daysInYearType, isInterestRecalculationEnabled,
                 rescheduleStrategyMethod, interestRecalculationCompoundingMethod, restCalendarInstance, recalculationFrequencyType,
                 compoundingCalendarInstance, compoundingFrequencyType, principalThresholdForLastInstalment, installmentAmountInMultiplesOf,
-                loanPreClosureInterestCalculationStrategy, loanCalendar, approvedAmount, loanTermVariations);
+                loanPreClosureInterestCalculationStrategy, loanCalendar, approvedAmount, loanTermVariations, calendarHistoryDataWrapper);
     }
 
     public static LoanApplicationTerms assembleFrom(final LoanApplicationTerms applicationTerms,
@@ -351,7 +358,7 @@ public final class LoanApplicationTerms {
                 applicationTerms.compoundingCalendarInstance, applicationTerms.compoundingFrequencyType,
                 applicationTerms.principalThresholdForLastInstalment, applicationTerms.installmentAmountInMultiplesOf,
                 applicationTerms.preClosureInterestCalculationStrategy, applicationTerms.loanCalendar,
-                applicationTerms.approvedPrincipal.getAmount(), loanTermVariations);
+                applicationTerms.approvedPrincipal.getAmount(), loanTermVariations, applicationTerms.calendarHistoryDataWrapper);
     }
 
     private LoanApplicationTerms(final ApplicationCurrency currency, final Integer loanTermFrequency,
@@ -372,7 +379,7 @@ public final class LoanApplicationTerms {
             final CalendarInstance compoundingCalendarInstance, final RecalculationFrequencyType compoundingFrequencyType,
             final BigDecimal principalThresholdForLastInstalment, final Integer installmentAmountInMultiplesOf,
             final LoanPreClosureInterestCalculationStrategy preClosureInterestCalculationStrategy, final Calendar loanCalendar,
-            BigDecimal approvedAmount, List<LoanTermVariationsData> loanTermVariations) {
+            BigDecimal approvedAmount, List<LoanTermVariationsData> loanTermVariations, final CalendarHistoryDataWrapper calendarHistoryDataWrapper) {
         this.currency = currency;
         this.loanTermFrequency = loanTermFrequency;
         this.loanTermPeriodFrequencyType = loanTermPeriodFrequencyType;
@@ -430,6 +437,7 @@ public final class LoanApplicationTerms {
         } else {
             this.seedDate = this.calculatedRepaymentsStartingFromDate;
         }
+        this.calendarHistoryDataWrapper = calendarHistoryDataWrapper;
     }
 
     public Money adjustPrincipalIfLastRepaymentPeriod(final Money principalForPeriod, final Money totalCumulativePrincipalToDate,
@@ -1421,5 +1429,9 @@ public final class LoanApplicationTerms {
     public LocalDate getSeedDate() {
         return this.seedDate;
     }
+    
+    public CalendarHistoryDataWrapper getCalendarHistoryDataWrapper(){
+        return this.calendarHistoryDataWrapper;
+    }
 
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/a01c1e36/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanUtilService.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanUtilService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanUtilService.java
index 423e346..103209b 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanUtilService.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanUtilService.java
@@ -20,6 +20,7 @@ package org.apache.fineract.portfolio.loanaccount.service;
 
 import java.math.BigDecimal;
 import java.util.List;
+import java.util.Set;
 
 import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
 import org.apache.fineract.organisation.holiday.domain.Holiday;
@@ -30,8 +31,10 @@ import org.apache.fineract.organisation.monetary.domain.ApplicationCurrencyRepos
 import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
 import org.apache.fineract.organisation.workingdays.domain.WorkingDays;
 import org.apache.fineract.organisation.workingdays.domain.WorkingDaysRepositoryWrapper;
+import org.apache.fineract.portfolio.calendar.data.CalendarHistoryDataWrapper;
 import org.apache.fineract.portfolio.calendar.domain.Calendar;
 import org.apache.fineract.portfolio.calendar.domain.CalendarEntityType;
+import org.apache.fineract.portfolio.calendar.domain.CalendarHistory;
 import org.apache.fineract.portfolio.calendar.domain.CalendarInstance;
 import org.apache.fineract.portfolio.calendar.domain.CalendarInstanceRepository;
 import org.apache.fineract.portfolio.calendar.service.CalendarUtils;
@@ -88,8 +91,15 @@ public class LoanUtilService {
         ApplicationCurrency applicationCurrency = this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency);
         final CalendarInstance calendarInstance = this.calendarInstanceRepository.findCalendarInstaneByEntityId(loan.getId(),
                 CalendarEntityType.LOANS.getValue());
+        Calendar calendar = null;
+        CalendarHistoryDataWrapper calendarHistoryDataWrapper = null;
+        if (calendarInstance != null) {
+            calendar = calendarInstance.getCalendar();
+            Set<CalendarHistory> calendarHistory = calendar.getCalendarHistory();
+            calendarHistoryDataWrapper = new CalendarHistoryDataWrapper(calendarHistory);
+        }
         LocalDate calculatedRepaymentsStartingFromDate = this.getCalculatedRepaymentsStartingFromDate(loan.getDisbursementDate(), loan,
-                calendarInstance);
+                calendarInstance, calendarHistoryDataWrapper);
         CalendarInstance restCalendarInstance = null;
         CalendarInstance compoundingCalendarInstance = null;
         Long overdurPenaltyWaitPeriod = null;
@@ -103,7 +113,7 @@ public class LoanUtilService {
         FloatingRateDTO floatingRateDTO = constructFloatingRateDTO(loan);
         ScheduleGeneratorDTO scheduleGeneratorDTO = new ScheduleGeneratorDTO(loanScheduleFactory, applicationCurrency,
                 calculatedRepaymentsStartingFromDate, holidayDetails, restCalendarInstance, compoundingCalendarInstance, recalculateFrom,
-                overdurPenaltyWaitPeriod, floatingRateDTO);
+                overdurPenaltyWaitPeriod, floatingRateDTO, calendar, calendarHistoryDataWrapper);
 
         return scheduleGeneratorDTO;
     }
@@ -111,7 +121,8 @@ public class LoanUtilService {
     public LocalDate getCalculatedRepaymentsStartingFromDate(final Loan loan) {
         final CalendarInstance calendarInstance = this.calendarInstanceRepository.findCalendarInstaneByEntityId(loan.getId(),
                 CalendarEntityType.LOANS.getValue());
-        return this.getCalculatedRepaymentsStartingFromDate(loan.getDisbursementDate(), loan, calendarInstance);
+        final CalendarHistoryDataWrapper calendarHistoryDataWrapper = null;
+        return this.getCalculatedRepaymentsStartingFromDate(loan.getDisbursementDate(), loan, calendarInstance, calendarHistoryDataWrapper);
     }
 
     private HolidayDetailDTO constructHolidayDTO(final Loan loan) {
@@ -146,22 +157,33 @@ public class LoanUtilService {
     }
 
     private LocalDate getCalculatedRepaymentsStartingFromDate(final LocalDate actualDisbursementDate, final Loan loan,
-            final CalendarInstance calendarInstance) {
+            final CalendarInstance calendarInstance, final CalendarHistoryDataWrapper calendarHistoryDataWrapper) {
         final Calendar calendar = calendarInstance == null ? null : calendarInstance.getCalendar();
-        return calculateRepaymentStartingFromDate(actualDisbursementDate, loan, calendar);
+        return calculateRepaymentStartingFromDate(actualDisbursementDate, loan, calendar, calendarHistoryDataWrapper);
     }
 
     public LocalDate getCalculatedRepaymentsStartingFromDate(final LocalDate actualDisbursementDate, final Loan loan,
             final Calendar calendar) {
+        final CalendarHistoryDataWrapper calendarHistoryDataWrapper = null;
         if (calendar == null) { return getCalculatedRepaymentsStartingFromDate(loan); }
-        return calculateRepaymentStartingFromDate(actualDisbursementDate, loan, calendar);
+        return calculateRepaymentStartingFromDate(actualDisbursementDate, loan, calendar, calendarHistoryDataWrapper);
 
     }
 
-    private LocalDate calculateRepaymentStartingFromDate(final LocalDate actualDisbursementDate, final Loan loan, final Calendar calendar) {
+    private LocalDate calculateRepaymentStartingFromDate(final LocalDate actualDisbursementDate, final Loan loan, final Calendar calendar, 
+            final CalendarHistoryDataWrapper calendarHistoryDataWrapper) {
         LocalDate calculatedRepaymentsStartingFromDate = loan.getExpectedFirstRepaymentOnDate();
         if (calendar != null) {// sync repayments
 
+            if (calculatedRepaymentsStartingFromDate == null && !calendar.getCalendarHistory().isEmpty() &&
+                    calendarHistoryDataWrapper != null) {
+                for (CalendarHistory calendarHistory : calendarHistoryDataWrapper.getCalendarHistoryList()) {
+                    calculatedRepaymentsStartingFromDate = calendarHistory.getStartDateLocalDate();
+                    break;
+                }
+                return calculatedRepaymentsStartingFromDate;
+            }
+
             // TODO: AA - user provided first repayment date takes precedence
             // over recalculated meeting date
             if (calculatedRepaymentsStartingFromDate == null) {

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/a01c1e36/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java
index 06ae1b1..dddc901 100755
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java
@@ -83,7 +83,6 @@ import org.apache.fineract.portfolio.calendar.domain.CalendarInstance;
 import org.apache.fineract.portfolio.calendar.domain.CalendarInstanceRepository;
 import org.apache.fineract.portfolio.calendar.domain.CalendarRepository;
 import org.apache.fineract.portfolio.calendar.domain.CalendarType;
-import org.apache.fineract.portfolio.calendar.exception.CalendarParameterUpdateNotSupportedException;
 import org.apache.fineract.portfolio.charge.domain.Charge;
 import org.apache.fineract.portfolio.charge.domain.ChargePaymentMode;
 import org.apache.fineract.portfolio.charge.domain.ChargeRepositoryWrapper;
@@ -130,8 +129,10 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanLifecycleStateMachin
 import org.apache.fineract.portfolio.loanaccount.domain.LoanOverdueInstallmentCharge;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallmentRepository;
+import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleTransactionProcessorFactory;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus;
+import org.apache.fineract.portfolio.loanaccount.domain.LoanSummaryWrapper;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanTrancheDisbursementCharge;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
@@ -219,6 +220,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
     private final BusinessEventNotifierService businessEventNotifierService;
     private final GuarantorDomainService guarantorDomainService;
     private final LoanUtilService loanUtilService;
+    private final LoanSummaryWrapper loanSummaryWrapper;
+    private final LoanRepaymentScheduleTransactionProcessorFactory transactionProcessingStrategy;
 
     @Autowired
     public LoanWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
@@ -245,7 +248,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
             final AccountAssociationsRepository accountAssociationRepository,
             final AccountTransferDetailRepository accountTransferDetailRepository,
             final BusinessEventNotifierService businessEventNotifierService, final GuarantorDomainService guarantorDomainService,
-            final LoanUtilService loanUtilService) {
+            final LoanUtilService loanUtilService, final LoanSummaryWrapper loanSummaryWrapper,
+            final LoanRepaymentScheduleTransactionProcessorFactory transactionProcessingStrategy) {
         this.context = context;
         this.loanEventApiJsonValidator = loanEventApiJsonValidator;
         this.loanAssembler = loanAssembler;
@@ -280,6 +284,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
         this.businessEventNotifierService = businessEventNotifierService;
         this.guarantorDomainService = guarantorDomainService;
         this.loanUtilService = loanUtilService;
+        this.loanSummaryWrapper = loanSummaryWrapper;
+        this.transactionProcessingStrategy = transactionProcessingStrategy;
     }
 
     private LoanLifecycleStateMachine defaultLoanLifecycleStateMachine() {
@@ -1955,6 +1961,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
 
         final boolean isHolidayEnabled = this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled();
         final WorkingDays workingDays = this.workingDaysRepository.findOne();
+        final AppUser currentUser = getAppUserIfPresent();
+        final List<Long> existingTransactionIds = new ArrayList<>();
+        final List<Long> existingReversedTransactionIds = new ArrayList<>();
         final Collection<Integer> loanStatuses = new ArrayList<>(Arrays.asList(LoanStatus.SUBMITTED_AND_PENDING_APPROVAL.getValue(),
                 LoanStatus.APPROVED.getValue(), LoanStatus.ACTIVE.getValue()));
         final Collection<Integer> loanTypes = new ArrayList<>(Arrays.asList(AccountType.GROUP.getValue(), AccountType.JLG.getValue()));
@@ -1966,16 +1975,19 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
 
         final List<Loan> loans = this.loanRepository.findByIdsAndLoanStatusAndLoanType(loanIds, loanStatuses, loanTypes);
         List<Holiday> holidays = null;
+        final LocalDate recalculateFrom = null;
         // loop through each loan to reschedule the repayment dates
         for (final Loan loan : loans) {
             if (loan != null) {
-                if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
-                    final String defaultUserMessage = "Meeting calendar type update is not supported";
-                    throw new CalendarParameterUpdateNotSupportedException("jlg.loan.recalculation", defaultUserMessage);
-                }
                 holidays = this.holidayRepository.findByOfficeIdAndGreaterThanDate(loan.getOfficeId(), loan.getDisbursementDate().toDate());
-
-                if (reschedulebasedOnMeetingDates != null && reschedulebasedOnMeetingDates) {
+                if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
+                    ScheduleGeneratorDTO scheduleGeneratorDTO = loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
+                    loan.setHelpers(null, this.loanSummaryWrapper, this.transactionProcessingStrategy);
+                    loan.recalculateScheduleFromLastTransaction(scheduleGeneratorDTO, existingTransactionIds,
+                            existingReversedTransactionIds, currentUser);
+                    this.loanScheduleHistoryWritePlatformService.createAndSaveLoanScheduleArchive(
+                            loan.fetchRepaymentScheduleInstallments(), loan, null);
+                } else if (reschedulebasedOnMeetingDates != null && reschedulebasedOnMeetingDates) {
                     loan.updateLoanRepaymentScheduleDates(calendar.getStartDateLocalDate(), calendar.getRecurrence(), isHolidayEnabled,
                             holidays, workingDays, reschedulebasedOnMeetingDates, presentMeetingDate, newMeetingDate);
                 } else {


Mime
View raw message