You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by na...@apache.org on 2017/07/20 13:22:06 UTC

[1/2] fineract git commit: holiday changes for next repayment date

Repository: fineract
Updated Branches:
  refs/heads/develop 0373ce467 -> c3a602ced


holiday changes for next repayment date


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

Branch: refs/heads/develop
Commit: b9017e2be2aa5e697c103c74a8b754a4c6bf19f5
Parents: 6946f1c
Author: nazeer shaik <na...@confluxtechnologies.com>
Authored: Thu Jul 20 17:10:11 2017 +0530
Committer: nazeer shaik <na...@confluxtechnologies.com>
Committed: Thu Jul 20 17:10:11 2017 +0530

----------------------------------------------------------------------
 .../holiday/api/HolidayApiConstants.java        |   1 +
 .../holiday/api/HolidaysApiResource.java        |   9 +
 .../organisation/holiday/data/HolidayData.java  |   4 +-
 .../holiday/data/HolidayDataValidator.java      |  22 ++-
 .../organisation/holiday/domain/Holiday.java    |  36 +++-
 .../holiday/domain/RescheduleType.java          |  64 +++++++
 .../holiday/service/HolidayEnumerations.java    |  26 +++
 .../service/HolidayReadPlatformService.java     |   4 +
 .../service/HolidayReadPlatformServiceImpl.java |  16 +-
 .../holiday/service/HolidayUtil.java            |  17 ++
 ...ayWritePlatformServiceJpaRepositoryImpl.java |  68 ++++---
 .../data/AdjustedDateDetailsDTO.java            |  76 ++++++++
 .../domain/RepaymentRescheduleType.java         |   7 +-
 .../workingdays/service/WorkingDaysUtil.java    |  12 ++
 .../calendar/service/CalendarUtils.java         | 108 +++++++++++
 .../domain/AbstractLoanScheduleGenerator.java   |  55 ++----
 .../domain/DefaultScheduledDateGenerator.java   | 179 ++++++++++++-------
 .../domain/LoanApplicationTerms.java            |   6 +-
 .../domain/ScheduledDateGenerator.java          |   9 +-
 ...oanReschedulePreviewPlatformServiceImpl.java |   4 +-
 ...scheduleRequestWritePlatformServiceImpl.java |   4 +-
 ...anWritePlatformServiceJpaRepositoryImpl.java |   2 +-
 .../core_db/V331__holiday_schema_changes.sql    |  23 +++
 23 files changed, 594 insertions(+), 158 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/fineract/blob/b9017e2b/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/api/HolidayApiConstants.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/api/HolidayApiConstants.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/api/HolidayApiConstants.java
index 27fa538..dc019a5 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/api/HolidayApiConstants.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/api/HolidayApiConstants.java
@@ -41,6 +41,7 @@ public class HolidayApiConstants {
     public static final String repaymentsRescheduledToParamName = "repaymentsRescheduledTo";
     public static final String processed = "processed";
     public static final String status = "status";
+    public static final String reschedulingType = "reschedulingType";
 
 	protected static final Set<String> HOLIDAY_RESPONSE_DATA_PARAMETERS = new HashSet<>(
 			Arrays.asList(idParamName, nameParamName, fromDateParamName, descriptionParamName, toDateParamName,

http://git-wip-us.apache.org/repos/asf/fineract/blob/b9017e2b/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/api/HolidaysApiResource.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/api/HolidaysApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/api/HolidaysApiResource.java
index 061f225..e8b22d3 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/api/HolidaysApiResource.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/api/HolidaysApiResource.java
@@ -180,4 +180,13 @@ public class HolidaysApiResource {
         final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
         return this.toApiJsonSerializer.serialize(settings, holidays, HOLIDAY_RESPONSE_DATA_PARAMETERS);
     }
+    
+    @GET
+    @Path("/template")
+    @Consumes({MediaType.APPLICATION_JSON})
+    @Produces({MediaType.APPLICATION_JSON})
+    public String retrieveRepaymentScheduleUpdationTyeOptions(@Context final UriInfo uriInfo){
+        this.context.authenticatedUser().validateHasReadPermission(HOLIDAY_RESOURCE_NAME);
+        return this.toApiJsonSerializer.serialize(this.holidayReadPlatformService.retrieveRepaymentScheduleUpdationTyeOptions());
+    }
 }

http://git-wip-us.apache.org/repos/asf/fineract/blob/b9017e2b/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/data/HolidayData.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/data/HolidayData.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/data/HolidayData.java
index 70f9839..12c2d0a 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/data/HolidayData.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/data/HolidayData.java
@@ -39,9 +39,10 @@ public class HolidayData {
     private final Long officeId;
     @SuppressWarnings("unused")
     private final EnumOptionData status;
+    private final Integer reschedulingType;
 
     public HolidayData(final Long id, final String name, final String description, final LocalDate fromDate, final LocalDate toDate,
-            final LocalDate repaymentsRescheduledTo, final EnumOptionData status) {
+            final LocalDate repaymentsRescheduledTo, final EnumOptionData status, final Integer reschedulingType) {
         this.id = id;
         this.name = name;
         this.description = description;
@@ -50,5 +51,6 @@ public class HolidayData {
         this.repaymentsRescheduledTo = repaymentsRescheduledTo;
         this.officeId = null;
         this.status = status;
+        this.reschedulingType = reschedulingType;
     }
 }

http://git-wip-us.apache.org/repos/asf/fineract/blob/b9017e2b/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/data/HolidayDataValidator.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/data/HolidayDataValidator.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/data/HolidayDataValidator.java
index e99eafb..755292c 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/data/HolidayDataValidator.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/data/HolidayDataValidator.java
@@ -23,6 +23,7 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
 
@@ -33,6 +34,7 @@ import org.apache.fineract.infrastructure.core.exception.InvalidJsonException;
 import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
 import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
 import org.apache.fineract.organisation.holiday.api.HolidayApiConstants;
+import org.apache.fineract.organisation.holiday.domain.RescheduleType;
 import org.joda.time.LocalDate;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
@@ -50,7 +52,8 @@ public class HolidayDataValidator {
 			Arrays.asList(HolidayApiConstants.localeParamName, HolidayApiConstants.dateFormatParamName,
 					HolidayApiConstants.nameParamName, HolidayApiConstants.fromDateParamName,
 					HolidayApiConstants.toDateParamName, HolidayApiConstants.descriptionParamName,
-					HolidayApiConstants.officesParamName, HolidayApiConstants.repaymentsRescheduledToParamName));
+					HolidayApiConstants.officesParamName, HolidayApiConstants.repaymentsRescheduledToParamName,
+					HolidayApiConstants.reschedulingType));
 
     @Autowired
     public HolidayDataValidator(final FromJsonHelper fromApiJsonHelper) {
@@ -79,11 +82,18 @@ public class HolidayDataValidator {
 
         final LocalDate toDate = this.fromApiJsonHelper.extractLocalDateNamed(HolidayApiConstants.toDateParamName, element);
         baseDataValidator.reset().parameter(HolidayApiConstants.toDateParamName).value(toDate).notNull();
-
-        final LocalDate repaymentsRescheduledTo = this.fromApiJsonHelper.extractLocalDateNamed(
-                HolidayApiConstants.repaymentsRescheduledToParamName, element);
-        baseDataValidator.reset().parameter(HolidayApiConstants.repaymentsRescheduledToParamName).value(repaymentsRescheduledTo).notNull();
-
+        
+        Integer reschedulingType = null;
+        if(this.fromApiJsonHelper.parameterExists(HolidayApiConstants.reschedulingType, element)){
+            reschedulingType = this.fromApiJsonHelper.extractIntegerNamed(HolidayApiConstants.reschedulingType, element, Locale.ENGLISH);
+        }
+       
+        LocalDate repaymentsRescheduledTo = null;
+        if(reschedulingType == null || reschedulingType.equals(RescheduleType.RESCHEDULETOSPECIFICDATE.getValue())){
+            repaymentsRescheduledTo = this.fromApiJsonHelper.extractLocalDateNamed(
+                    HolidayApiConstants.repaymentsRescheduledToParamName, element);
+            baseDataValidator.reset().parameter(HolidayApiConstants.repaymentsRescheduledToParamName).value(repaymentsRescheduledTo).notNull();
+        }
         Set<Long> offices = null;
         final JsonObject topLevelJsonElement = element.getAsJsonObject();
 

http://git-wip-us.apache.org/repos/asf/fineract/blob/b9017e2b/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/domain/Holiday.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/domain/Holiday.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/domain/Holiday.java
index be79b25..c25a3bf 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/domain/Holiday.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/domain/Holiday.java
@@ -73,9 +73,12 @@ public class Holiday extends AbstractPersistableCustom<Long> {
     @Temporal(TemporalType.DATE)
     private Date toDate;
 
-    @Column(name = "repayments_rescheduled_to", nullable = false)
+    @Column(name = "repayments_rescheduled_to", nullable = true)
     @Temporal(TemporalType.DATE)
     private Date repaymentsRescheduledTo;
+    
+    @Column(name = "rescheduling_type", nullable = false)
+    private int reschedulingType;
 
     @Column(name = "status_enum", nullable = false)
     private Integer status;
@@ -94,13 +97,21 @@ public class Holiday extends AbstractPersistableCustom<Long> {
         final String name = command.stringValueOfParameterNamed(HolidayApiConstants.nameParamName);
         final LocalDate fromDate = command.localDateValueOfParameterNamed(HolidayApiConstants.fromDateParamName);
         final LocalDate toDate = command.localDateValueOfParameterNamed(HolidayApiConstants.toDateParamName);
-        final LocalDate repaymentsRescheduledTo = command
-                .localDateValueOfParameterNamed(HolidayApiConstants.repaymentsRescheduledToParamName);
+        Integer reschedulingType = null;
+        if(command.parameterExists(HolidayApiConstants.reschedulingType)){
+            reschedulingType = command.integerValueOfParameterNamed(HolidayApiConstants.reschedulingType);
+        }
+        LocalDate repaymentsRescheduledTo = null;
+        if(reschedulingType == null || reschedulingType.equals(RescheduleType.RESCHEDULETOSPECIFICDATE.getValue())){
+            repaymentsRescheduledTo = command
+                    .localDateValueOfParameterNamed(HolidayApiConstants.repaymentsRescheduledToParamName);
+        }
         final Integer status = HolidayStatusType.PENDING_FOR_ACTIVATION.getValue();
         final boolean processed = false;// default it to false. Only batch job
                                         // should update this field.
         final String description = command.stringValueOfParameterNamed(HolidayApiConstants.descriptionParamName);
-        return new Holiday(name, fromDate, toDate, repaymentsRescheduledTo, status, processed, description, offices);
+        
+        return new Holiday(name, fromDate, toDate, repaymentsRescheduledTo, status, processed, description, offices, reschedulingType);
     }
 
     public Map<String, Object> update(final JsonCommand command) {
@@ -125,6 +136,16 @@ public class Holiday extends AbstractPersistableCustom<Long> {
             actualChanges.put(descriptionParamName, newValue);
             this.description = StringUtils.defaultIfEmpty(newValue, null);
         }
+        
+        
+        if (command.isChangeInIntegerParameterNamed(HolidayApiConstants.reschedulingType,this.reschedulingType)) {
+            final Integer newValue =command.integerValueOfParameterNamed(HolidayApiConstants.reschedulingType);
+            actualChanges.put(HolidayApiConstants.reschedulingType, newValue);
+            this.reschedulingType = RescheduleType.fromInt(newValue).getValue();
+            if(newValue.equals(RescheduleType.RESCHEDULETONEXTREPAYMENTDATE.getValue())){
+                this.repaymentsRescheduledTo = null;
+            }
+        } 
 
         if (currentStatus.isPendingActivation()) {
             if (command.isChangeInLocalDateParameterNamed(fromDateParamName, getFromDateLocalDate())) {
@@ -205,7 +226,7 @@ public class Holiday extends AbstractPersistableCustom<Long> {
     }
 
     private Holiday(final String name, final LocalDate fromDate, final LocalDate toDate, final LocalDate repaymentsRescheduledTo,
-            final Integer status, final boolean processed, final String description, final Set<Office> offices) {
+            final Integer status, final boolean processed, final String description, final Set<Office> offices, final int reschedulingType) {
         if (StringUtils.isNotBlank(name)) {
             this.name = name.trim();
         }
@@ -234,6 +255,7 @@ public class Holiday extends AbstractPersistableCustom<Long> {
         if (offices != null) {
             this.offices = offices;
         }
+        this.reschedulingType = reschedulingType;
     }
 
     protected Holiday() {}
@@ -298,4 +320,8 @@ public class Holiday extends AbstractPersistableCustom<Long> {
         }
         this.status = HolidayStatusType.DELETED.getValue();
     }
+    
+    public RescheduleType getReScheduleType() {
+        return RescheduleType.fromInt(this.reschedulingType);
+    }
 }

http://git-wip-us.apache.org/repos/asf/fineract/blob/b9017e2b/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/domain/RescheduleType.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/domain/RescheduleType.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/domain/RescheduleType.java
new file mode 100644
index 0000000..a87b658
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/domain/RescheduleType.java
@@ -0,0 +1,64 @@
+/**
+ * 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.organisation.holiday.domain;
+
+public enum RescheduleType {
+
+    INVALID(0, "rescheduletype.invalid"), RESCHEDULETOSPECIFICDATE(2, "rescheduletype.rescheduletospecificdate"), //
+    RESCHEDULETONEXTREPAYMENTDATE(1, "rescheduletype.rescheduletonextrepaymentdate");
+
+    private final Integer value;
+    private final String code;
+
+    private RescheduleType(Integer value, String code) {
+            this.value = value;
+            this.code = code;
+    }
+
+    public static RescheduleType fromInt(int rescheduleTypeValue) {
+            RescheduleType enumerration = RescheduleType.INVALID;
+            switch (rescheduleTypeValue) {
+            case 1:
+                    enumerration = RescheduleType.RESCHEDULETONEXTREPAYMENTDATE;
+                    break;
+            case 2:
+                    enumerration = RescheduleType.RESCHEDULETOSPECIFICDATE;
+                    break;
+            }
+            return enumerration;
+    }
+
+    public boolean isRescheduleToSpecificDate(){
+            return this.value.equals(RescheduleType.RESCHEDULETOSPECIFICDATE.getValue());
+    }
+    
+    public boolean isResheduleToNextRepaymentDate(){
+            return this.value.equals(RescheduleType.RESCHEDULETONEXTREPAYMENTDATE.getValue());
+    }
+
+    
+    public Integer getValue() {
+            return this.value;
+    }
+
+    public String getCode() {
+            return this.code;
+    }
+    
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/fineract/blob/b9017e2b/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/service/HolidayEnumerations.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/service/HolidayEnumerations.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/service/HolidayEnumerations.java
index 43e22d0..176a3c8 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/service/HolidayEnumerations.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/service/HolidayEnumerations.java
@@ -20,6 +20,7 @@ package org.apache.fineract.organisation.holiday.service;
 
 import org.apache.fineract.infrastructure.core.data.EnumOptionData;
 import org.apache.fineract.organisation.holiday.domain.HolidayStatusType;
+import org.apache.fineract.organisation.holiday.domain.RescheduleType;
 
 public class HolidayEnumerations {
 
@@ -49,4 +50,29 @@ public class HolidayEnumerations {
         }
         return optionData;
     }
+    
+    public static EnumOptionData rescheduleType(final int id) {
+        return rescheduleType(RescheduleType.fromInt(id));
+    }
+
+    
+    public static EnumOptionData rescheduleType(final RescheduleType type) {
+        EnumOptionData optionData = null;
+        switch (type) {
+            case RESCHEDULETONEXTREPAYMENTDATE:
+                optionData = new EnumOptionData(RescheduleType.RESCHEDULETONEXTREPAYMENTDATE.getValue().longValue(),
+                        RescheduleType.RESCHEDULETONEXTREPAYMENTDATE.getCode(), "Reschedule to next repayment date");
+            break;
+            case RESCHEDULETOSPECIFICDATE:
+                optionData = new EnumOptionData(RescheduleType.RESCHEDULETOSPECIFICDATE.getValue().longValue(),
+                        RescheduleType.RESCHEDULETOSPECIFICDATE.getCode(), "Reschedule to specified date");
+            break;
+           
+            default:
+                optionData = new EnumOptionData(RescheduleType.INVALID.getValue().longValue(),
+                        RescheduleType.INVALID.getCode(), "Invalid");
+            break;
+        }
+        return optionData;
+    }
 }

http://git-wip-us.apache.org/repos/asf/fineract/blob/b9017e2b/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/service/HolidayReadPlatformService.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/service/HolidayReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/service/HolidayReadPlatformService.java
index 309af96..9ca4b3f 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/service/HolidayReadPlatformService.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/service/HolidayReadPlatformService.java
@@ -20,7 +20,9 @@ package org.apache.fineract.organisation.holiday.service;
 
 import java.util.Collection;
 import java.util.Date;
+import java.util.List;
 
+import org.apache.fineract.infrastructure.core.data.EnumOptionData;
 import org.apache.fineract.organisation.holiday.data.HolidayData;
 
 public interface HolidayReadPlatformService {
@@ -28,4 +30,6 @@ public interface HolidayReadPlatformService {
     Collection<HolidayData> retrieveAllHolidaysBySearchParamerters(final Long officeId, Date fromDate, Date toDate);
 
     HolidayData retrieveHoliday(final Long holidayId);
+    
+    List<EnumOptionData> retrieveRepaymentScheduleUpdationTyeOptions();
 }

http://git-wip-us.apache.org/repos/asf/fineract/blob/b9017e2b/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/service/HolidayReadPlatformServiceImpl.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/service/HolidayReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/service/HolidayReadPlatformServiceImpl.java
index 2601d21..96ccb72 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/service/HolidayReadPlatformServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/service/HolidayReadPlatformServiceImpl.java
@@ -25,12 +25,14 @@ import java.text.SimpleDateFormat;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Date;
+import java.util.List;
 
 import org.apache.fineract.infrastructure.core.data.EnumOptionData;
 import org.apache.fineract.infrastructure.core.domain.JdbcSupport;
 import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
 import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
 import org.apache.fineract.organisation.holiday.data.HolidayData;
+import org.apache.fineract.organisation.holiday.domain.RescheduleType;
 import org.apache.fineract.organisation.holiday.exception.HolidayNotFoundException;
 import org.joda.time.LocalDate;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -58,7 +60,7 @@ public class HolidayReadPlatformServiceImpl implements HolidayReadPlatformServic
         public HolidayMapper() {
             final StringBuilder sqlBuilder = new StringBuilder(200);
             sqlBuilder.append("h.id as id, h.name as name, h.description as description, h.from_date as fromDate, h.to_date as toDate, ");
-            sqlBuilder.append("h.repayments_rescheduled_to as repaymentsScheduleTO, h.status_enum as statusEnum ");
+            sqlBuilder.append("h.repayments_rescheduled_to as repaymentsScheduleTO, h.rescheduling_type as reschedulingType, h.status_enum as statusEnum ");
             sqlBuilder.append("from m_holiday h ");
             this.schema = sqlBuilder.toString();
         }
@@ -76,9 +78,10 @@ public class HolidayReadPlatformServiceImpl implements HolidayReadPlatformServic
             final LocalDate toDate = JdbcSupport.getLocalDate(rs, "toDate");
             final LocalDate repaymentsScheduleTO = JdbcSupport.getLocalDate(rs, "repaymentsScheduleTO");
             final Integer statusEnum = JdbcSupport.getInteger(rs, "statusEnum");
+            final Integer reschedulingType = JdbcSupport.getInteger(rs, "reschedulingType");
             final EnumOptionData status = HolidayEnumerations.holidayStatusType(statusEnum);
 
-            return new HolidayData(id, name, description, fromDate, toDate, repaymentsScheduleTO, status);
+            return new HolidayData(id, name, description, fromDate, toDate, repaymentsScheduleTO, status, reschedulingType);
         }
 
     }
@@ -133,5 +136,14 @@ public class HolidayReadPlatformServiceImpl implements HolidayReadPlatformServic
             throw new HolidayNotFoundException(holidayId);
         }
     }
+    
+    @Override
+    public List<EnumOptionData> retrieveRepaymentScheduleUpdationTyeOptions(){
+        
+        final List<EnumOptionData> repSchUpdationTypeOptions = Arrays.asList(
+                HolidayEnumerations.rescheduleType(RescheduleType.RESCHEDULETOSPECIFICDATE),
+                HolidayEnumerations.rescheduleType(RescheduleType.RESCHEDULETONEXTREPAYMENTDATE));
+        return repSchUpdationTypeOptions;
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/fineract/blob/b9017e2b/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/service/HolidayUtil.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/service/HolidayUtil.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/service/HolidayUtil.java
index c026ac1..ba729f0 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/service/HolidayUtil.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/service/HolidayUtil.java
@@ -21,6 +21,7 @@ package org.apache.fineract.organisation.holiday.service;
 import java.util.List;
 
 import org.apache.fineract.organisation.holiday.domain.Holiday;
+import org.apache.fineract.organisation.workingdays.data.AdjustedDateDetailsDTO;
 import org.joda.time.LocalDate;
 
 public class HolidayUtil {
@@ -56,4 +57,20 @@ public class HolidayUtil {
 
         return false;
     }
+    
+    public static Holiday getApplicableHoliday(final LocalDate repaymentDate, final List<Holiday> holidays) {
+        Holiday referedHoliday = null;
+        for (final Holiday holiday : holidays) {
+            if (!repaymentDate.isBefore(holiday.getFromDateLocalDate()) && !repaymentDate.isAfter(holiday.getToDateLocalDate())) {
+                referedHoliday = holiday;
+            }
+        }
+        return referedHoliday;
+    }
+    public static void updateRepaymentRescheduleDateToWorkingDayIfItIsHoliday(final AdjustedDateDetailsDTO adjustedDateDetailsDTO,
+            final Holiday holiday) {
+        if (holiday.getReScheduleType().isRescheduleToSpecificDate()) {
+            adjustedDateDetailsDTO.setChangedScheduleDate(holiday.getRepaymentsRescheduledToLocalDate());
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/fineract/blob/b9017e2b/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/service/HolidayWritePlatformServiceJpaRepositoryImpl.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/service/HolidayWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/service/HolidayWritePlatformServiceJpaRepositoryImpl.java
index 6bce676..6ff9818 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/service/HolidayWritePlatformServiceJpaRepositoryImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/holiday/service/HolidayWritePlatformServiceJpaRepositoryImpl.java
@@ -194,9 +194,18 @@ public class HolidayWritePlatformServiceJpaRepositoryImpl implements HolidayWrit
     private void validateInputDates(final JsonCommand command) {
         final LocalDate fromDate = command.localDateValueOfParameterNamed(HolidayApiConstants.fromDateParamName);
         final LocalDate toDate = command.localDateValueOfParameterNamed(HolidayApiConstants.toDateParamName);
-        final LocalDate repaymentsRescheduledTo = command
-                .localDateValueOfParameterNamed(HolidayApiConstants.repaymentsRescheduledToParamName);
-        this.validateInputDates(fromDate, toDate, repaymentsRescheduledTo);
+        Integer reshedulingType = null;
+        if(command.parameterExists(HolidayApiConstants.reschedulingType)){
+            reshedulingType = command.integerValueOfParameterNamed(HolidayApiConstants.reschedulingType);
+        }
+        LocalDate repaymentsRescheduledTo = null;
+        if(reshedulingType != null && reshedulingType.equals(2)){
+            repaymentsRescheduledTo = command
+                    .localDateValueOfParameterNamed(HolidayApiConstants.repaymentsRescheduledToParamName);
+        }
+        if(repaymentsRescheduledTo != null){
+            this.validateInputDates(fromDate, toDate, repaymentsRescheduledTo);
+        }
     }
 
     private void validateInputDates(final LocalDate fromDate, final LocalDate toDate, final LocalDate repaymentsRescheduledTo) {
@@ -208,37 +217,40 @@ public class HolidayWritePlatformServiceJpaRepositoryImpl implements HolidayWrit
             throw new HolidayDateException("to.date.cannot.be.before.from.date", defaultUserMessage, fromDate.toString(),
                     toDate.toString());
         }
+        if(repaymentsRescheduledTo != null){
+            if ((repaymentsRescheduledTo.isEqual(fromDate) || repaymentsRescheduledTo.isEqual(toDate)
+                    || (repaymentsRescheduledTo.isAfter(fromDate) && repaymentsRescheduledTo.isBefore(toDate)))) {
 
-        if (repaymentsRescheduledTo.isEqual(fromDate) || repaymentsRescheduledTo.isEqual(toDate)
-                || (repaymentsRescheduledTo.isAfter(fromDate) && repaymentsRescheduledTo.isBefore(toDate))) {
+                defaultUserMessage = "Repayments rescheduled date should be before from date or after to date.";
+                throw new HolidayDateException("repayments.rescheduled.date.should.be.before.from.date.or.after.to.date", defaultUserMessage,
+                        repaymentsRescheduledTo.toString());
+            }
 
-            defaultUserMessage = "Repayments rescheduled date should be before from date or after to date.";
-            throw new HolidayDateException("repayments.rescheduled.date.should.be.before.from.date.or.after.to.date", defaultUserMessage,
-                    repaymentsRescheduledTo.toString());
-        }
+            final WorkingDays workingDays = this.daysRepositoryWrapper.findOne();
+            final Boolean isRepaymentOnWorkingDay = WorkingDaysUtil.isWorkingDay(workingDays, repaymentsRescheduledTo);
 
-        final WorkingDays workingDays = this.daysRepositoryWrapper.findOne();
-        final Boolean isRepaymentOnWorkingDay = WorkingDaysUtil.isWorkingDay(workingDays, repaymentsRescheduledTo);
+            if (!isRepaymentOnWorkingDay) {
+                defaultUserMessage = "Repayments rescheduled date should not fall on non working days";
+                throw new HolidayDateException("repayments.rescheduled.date.should.not.fall.on.non.working.day", defaultUserMessage,
+                        repaymentsRescheduledTo.toString());
+            }
 
-        if (!isRepaymentOnWorkingDay) {
-            defaultUserMessage = "Repayments rescheduled date should not fall on non working days";
-            throw new HolidayDateException("repayments.rescheduled.date.should.not.fall.on.non.working.day", defaultUserMessage,
-                    repaymentsRescheduledTo.toString());
+            // validate repaymentsRescheduledTo date
+            // 1. should be within a 7 days date range.
+            // 2. Alternative date should not be an exist holiday.//TBD
+            // 3. Holiday should not be on an repaymentsRescheduledTo date of
+            // another holiday.//TBD
+
+            // restricting repaymentsRescheduledTo date to be within 7 days range
+            // before or after from date and to date.
+            if (repaymentsRescheduledTo.isBefore(fromDate.minusDays(7)) || repaymentsRescheduledTo.isAfter(toDate.plusDays(7))) {
+                defaultUserMessage = "Repayments Rescheduled to date must be within 7 days before or after from and to dates";
+                throw new HolidayDateException("repayments.rescheduled.to.must.be.within.range", defaultUserMessage, fromDate.toString(),
+                        toDate.toString(), repaymentsRescheduledTo.toString());
+            }
         }
 
-        // validate repaymentsRescheduledTo date
-        // 1. should be within a 7 days date range.
-        // 2. Alternative date should not be an exist holiday.//TBD
-        // 3. Holiday should not be on an repaymentsRescheduledTo date of
-        // another holiday.//TBD
-
-        // restricting repaymentsRescheduledTo date to be within 7 days range
-        // before or after from date and to date.
-        if (repaymentsRescheduledTo.isBefore(fromDate.minusDays(7)) || repaymentsRescheduledTo.isAfter(toDate.plusDays(7))) {
-            defaultUserMessage = "Repayments Rescheduled to date must be within 7 days before or after from and to dates";
-            throw new HolidayDateException("repayments.rescheduled.to.must.be.within.range", defaultUserMessage, fromDate.toString(),
-                    toDate.toString(), repaymentsRescheduledTo.toString());
-        }
+
     }
 
 }

http://git-wip-us.apache.org/repos/asf/fineract/blob/b9017e2b/fineract-provider/src/main/java/org/apache/fineract/organisation/workingdays/data/AdjustedDateDetailsDTO.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/workingdays/data/AdjustedDateDetailsDTO.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/workingdays/data/AdjustedDateDetailsDTO.java
new file mode 100644
index 0000000..916c2fd
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/workingdays/data/AdjustedDateDetailsDTO.java
@@ -0,0 +1,76 @@
+/**
+ * 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.organisation.workingdays.data;
+
+import org.joda.time.LocalDate;
+
+
+public class AdjustedDateDetailsDTO {
+
+    /**
+     * Variable tracks the current schedule date that has been changed
+     */
+    LocalDate changedScheduleDate;
+    /**
+     * Variable tracks If the meeting has been changed , i.e future schedule
+     * also changes along with the current repayments date.
+     */
+    LocalDate changedActualRepaymentDate;
+
+    /**
+     * Variable tracks the next repayment period due date
+     */
+    LocalDate nextRepaymentPeriodDueDate;
+
+    public AdjustedDateDetailsDTO(final LocalDate changedScheduleDate, final LocalDate changedActualRepaymentDate) {
+        this.changedScheduleDate = changedScheduleDate;
+        this.changedActualRepaymentDate = changedActualRepaymentDate;
+    }
+
+    public AdjustedDateDetailsDTO(final LocalDate changedScheduleDate, final LocalDate changedActualRepaymentDate,
+            final LocalDate nextRepaymentPeriodDueDate) {
+        this.changedScheduleDate = changedScheduleDate;
+        this.changedActualRepaymentDate = changedActualRepaymentDate;
+        this.nextRepaymentPeriodDueDate = nextRepaymentPeriodDueDate;
+    }
+
+    public LocalDate getChangedScheduleDate() {
+        return this.changedScheduleDate;
+    }
+
+    public LocalDate getChangedActualRepaymentDate() {
+        return this.changedActualRepaymentDate;
+    }
+
+    public void setChangedScheduleDate(final LocalDate changedScheduleDate) {
+        this.changedScheduleDate = changedScheduleDate;
+    }
+
+    public void setChangedActualRepaymentDate(final LocalDate changedActualRepaymentDate) {
+        this.changedActualRepaymentDate = changedActualRepaymentDate;
+    }
+
+    public LocalDate getNextRepaymentPeriodDueDate() {
+        return this.nextRepaymentPeriodDueDate;
+    }
+
+    public void setNextRepaymentPeriodDueDate(final LocalDate nextRepaymentPeriodDueDate) {
+        this.nextRepaymentPeriodDueDate = nextRepaymentPeriodDueDate;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/fineract/blob/b9017e2b/fineract-provider/src/main/java/org/apache/fineract/organisation/workingdays/domain/RepaymentRescheduleType.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/workingdays/domain/RepaymentRescheduleType.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/workingdays/domain/RepaymentRescheduleType.java
index 0194cd7..d658f92 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/organisation/workingdays/domain/RepaymentRescheduleType.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/workingdays/domain/RepaymentRescheduleType.java
@@ -26,7 +26,8 @@ public enum RepaymentRescheduleType {
     INVALID(0, "RepaymentRescheduleType.invalid"), SAME_DAY(1, "RepaymentRescheduleType.same.day"), MOVE_TO_NEXT_WORKING_DAY(2,
             "RepaymentRescheduleType.move.to.next.working.day"), MOVE_TO_NEXT_REPAYMENT_MEETING_DAY(3,
             "RepaymentRescheduleType.move.to.next.repayment.meeting.day"), MOVE_TO_PREVIOUS_WORKING_DAY(4,
-            "RepaymentRescheduleType.move.to.previous.working.day");
+            "RepaymentRescheduleType.move.to.previous.working.day"),
+            MOVE_TO_NEXT_MEETING_DAY(5, "RepaymentRescheduleType.move.to.next.meeting.day");
 
     private final Integer value;
     private final String code;
@@ -43,6 +44,10 @@ public enum RepaymentRescheduleType {
     public String getCode() {
         return this.code;
     }
+    
+    public boolean isMoveToNextRepaymentDay() {
+        return this.value.equals(RepaymentRescheduleType.MOVE_TO_NEXT_REPAYMENT_MEETING_DAY.getValue());
+    }
 
     private static final Map<Integer, RepaymentRescheduleType> intToEnumMap = new HashMap<>();
     private static int minValue;

http://git-wip-us.apache.org/repos/asf/fineract/blob/b9017e2b/fineract-provider/src/main/java/org/apache/fineract/organisation/workingdays/service/WorkingDaysUtil.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/workingdays/service/WorkingDaysUtil.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/workingdays/service/WorkingDaysUtil.java
index ac0fc39..605a891 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/organisation/workingdays/service/WorkingDaysUtil.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/workingdays/service/WorkingDaysUtil.java
@@ -18,6 +18,7 @@
  */
 package org.apache.fineract.organisation.workingdays.service;
 
+import org.apache.fineract.organisation.workingdays.data.AdjustedDateDetailsDTO;
 import org.apache.fineract.organisation.workingdays.domain.RepaymentRescheduleType;
 import org.apache.fineract.organisation.workingdays.domain.WorkingDays;
 import org.apache.fineract.portfolio.calendar.service.CalendarUtils;
@@ -56,4 +57,15 @@ public class WorkingDaysUtil {
     public static boolean isNonWorkingDay(final WorkingDays workingDays, final LocalDate date) {
         return !isWorkingDay(workingDays, date);
     }
+    
+    public static void updateWorkingDayIfRepaymentDateIsNonWorkingDay(final AdjustedDateDetailsDTO adjustedDateDetailsDTO, final WorkingDays workingDays) {
+        final LocalDate changedScheduleDate = getOffSetDateIfNonWorkingDay(adjustedDateDetailsDTO.getChangedScheduleDate(),
+                adjustedDateDetailsDTO.getNextRepaymentPeriodDueDate(), workingDays);
+        adjustedDateDetailsDTO.setChangedScheduleDate(changedScheduleDate);
+    }
+    
+    public static RepaymentRescheduleType getRepaymentRescheduleType(final WorkingDays workingDays, final LocalDate date) {
+        RepaymentRescheduleType rescheduleType = RepaymentRescheduleType.fromInt(workingDays.getRepaymentReschedulingType());
+        return rescheduleType;
+    }
 }

http://git-wip-us.apache.org/repos/asf/fineract/blob/b9017e2b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarUtils.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarUtils.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarUtils.java
index 6360380..c7f10cb 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarUtils.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarUtils.java
@@ -700,4 +700,112 @@ public class CalendarUtils {
         }
         return monthOnDay;
     }
+    
+    public static LocalDate getNextRepaymentMeetingDate(final String recurringRule, final LocalDate seedDate,
+            final LocalDate repaymentDate, final Integer loanRepaymentInterval, final String frequency, final WorkingDays workingDays,
+            boolean isSkipRepaymentOnFirstDayOfMonth, final Integer numberOfDays, boolean applyWorkingDays) {
+        boolean isCalledFirstTime = true;
+        return getNextRepaymentMeetingDate(recurringRule, seedDate, repaymentDate, loanRepaymentInterval, frequency,
+                workingDays, isSkipRepaymentOnFirstDayOfMonth, numberOfDays, isCalledFirstTime, applyWorkingDays);
+    }
+    
+    public static LocalDate getNextRepaymentMeetingDate(final String recurringRule, final LocalDate seedDate,
+            final LocalDate repaymentDate, final Integer loanRepaymentInterval, final String frequency, 
+            boolean isSkipRepaymentOnFirstDayOfMonth, final Integer numberOfDays) {
+        boolean isCalledFirstTime = true;
+        final WorkingDays workingDays = null;
+        boolean applyWorkingDays = false;
+        return getNextRepaymentMeetingDate(recurringRule, seedDate, repaymentDate, loanRepaymentInterval, frequency,
+                workingDays, isSkipRepaymentOnFirstDayOfMonth, numberOfDays, isCalledFirstTime, applyWorkingDays);
+    }
+    
+    public static LocalDate getNextRepaymentMeetingDate(final String recurringRule, final LocalDate seedDate,
+            final LocalDate repaymentDate, final Integer loanRepaymentInterval, final String frequency, final WorkingDays workingDays,
+            boolean isSkipRepaymentOnFirstDayOfMonth, final Integer numberOfDays, boolean isCalledFirstTime, boolean applyWorkingDays) {
+
+        final Recur recur = CalendarUtils.getICalRecur(recurringRule);
+        if (recur == null) { return null; }
+        LocalDate tmpDate = repaymentDate;
+        
+        final Integer repaymentInterval = getMeetingIntervalFromFrequency(loanRepaymentInterval, frequency, recur);
+        /*
+         * Recurring dates should follow loanRepaymentInterval.
+         * 
+         * e.g. The weekly meeting will have interval of 1, if the loan product
+         * with fortnightly frequency will have interval of 2, to generate right
+         * set of meeting dates reset interval same as loan repayment interval.
+         */
+        int meetingInterval = recur.getInterval();
+        if(meetingInterval < 1){
+                meetingInterval = 1;
+        }
+        int rep = repaymentInterval<meetingInterval ? 1: repaymentInterval / meetingInterval ;
+
+        /*
+         * Recurring dates should follow loanRepayment frequency. //e.g. daily
+         * meeting frequency should support all loan products with any type of
+         * frequency. to generate right set of meeting dates reset frequency
+         * same as loan repayment frequency.
+         */
+        if (recur.getFrequency().equals(Recur.DAILY)) {
+            recur.setFrequency(frequency);
+        }
+        
+        /**
+         * Below code modified as discussed with Pramod N 
+         */
+        LocalDate newRepaymentDate = tmpDate;
+        int newRepayment = rep;
+        while (newRepayment > 0) {
+            newRepaymentDate = getNextRecurringDate(recur, seedDate, newRepaymentDate);
+            newRepayment--;
+        }
+
+        LocalDate nextRepaymentDate = null;
+        if (applyWorkingDays) {
+            if (WorkingDaysUtil.isNonWorkingDay(workingDays, newRepaymentDate)
+                    && WorkingDaysUtil.getRepaymentRescheduleType(workingDays, newRepaymentDate).isMoveToNextRepaymentDay()) {
+                newRepaymentDate = getNextRepaymentMeetingDate(recurringRule, seedDate, newRepaymentDate.plusDays(1),
+                        loanRepaymentInterval, frequency, workingDays, isSkipRepaymentOnFirstDayOfMonth, numberOfDays, isCalledFirstTime,
+                        applyWorkingDays);
+            } else {
+                newRepaymentDate = WorkingDaysUtil.getOffSetDateIfNonWorkingDay(newRepaymentDate, nextRepaymentDate, workingDays);
+            }
+        }
+        
+        if(isCalledFirstTime && newRepaymentDate.equals(repaymentDate)){
+            isCalledFirstTime = false;
+            newRepaymentDate = getNextRepaymentMeetingDate(recurringRule, seedDate, repaymentDate.plusDays(1), loanRepaymentInterval,
+                    frequency, workingDays, isSkipRepaymentOnFirstDayOfMonth, numberOfDays, isCalledFirstTime, applyWorkingDays);
+        }
+        
+        if (isSkipRepaymentOnFirstDayOfMonth) {
+            final LocalDate newRepaymentDateTemp = adjustRecurringDate(newRepaymentDate, numberOfDays);
+            if (applyWorkingDays) {
+                if (WorkingDaysUtil.isNonWorkingDay(workingDays, newRepaymentDateTemp)
+                        && WorkingDaysUtil.getRepaymentRescheduleType(workingDays, newRepaymentDateTemp).isMoveToNextRepaymentDay()) {
+                    newRepaymentDate = getNextRepaymentMeetingDate(recurringRule, seedDate, newRepaymentDate.plusDays(1),
+                            loanRepaymentInterval, frequency, workingDays, isSkipRepaymentOnFirstDayOfMonth, numberOfDays,
+                            isCalledFirstTime, applyWorkingDays);
+                } else {
+                    newRepaymentDate = WorkingDaysUtil.getOffSetDateIfNonWorkingDay(newRepaymentDateTemp, nextRepaymentDate, workingDays);
+                }
+            }
+        }
+        return newRepaymentDate;
+    }
+    
+    public static Integer getMeetingIntervalFromFrequency(final Integer loanRepaymentInterval, final String frequency, final Recur recur) {
+        final Integer interval = 4;
+        Integer repaymentInterval = loanRepaymentInterval;
+        /*
+         * check loanRepaymentInterval equal to 1, if repayments frequency is
+         * monthly and meeting frequency is weekly, then generate repayments
+         * schedule as every 4 weeks
+         */
+        if (frequency.equals(Recur.MONTHLY) && recur.getFrequency().equals(Recur.WEEKLY)) {
+            repaymentInterval = loanRepaymentInterval*interval;
+        }
+        return repaymentInterval;
+    }
 }

http://git-wip-us.apache.org/repos/asf/fineract/blob/b9017e2b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java
----------------------------------------------------------------------
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 cb42bf5..d8baaf3 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
@@ -34,6 +34,7 @@ import org.apache.fineract.infrastructure.core.service.DateUtils;
 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.workingdays.data.AdjustedDateDetailsDTO;
 import org.apache.fineract.organisation.workingdays.domain.RepaymentRescheduleType;
 import org.apache.fineract.portfolio.calendar.domain.CalendarInstance;
 import org.apache.fineract.portfolio.calendar.service.CalendarUtils;
@@ -121,7 +122,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
         
         boolean isFirstRepayment = true;
         LocalDate firstRepaymentdate = this.scheduledDateGenerator.generateNextRepaymentDate(
-                loanApplicationTerms.getExpectedDisbursementDate(), loanApplicationTerms, isFirstRepayment, holidayDetailDTO);
+                loanApplicationTerms.getExpectedDisbursementDate(), loanApplicationTerms, isFirstRepayment);
         final LocalDate idealDisbursementDate = this.scheduledDateGenerator.idealDisbursementDateBasedOnFirstRepaymentDate(
                 loanApplicationTerms.getLoanTermPeriodFrequencyType(), loanApplicationTerms.getRepaymentEvery(), firstRepaymentdate,
                 loanApplicationTerms.getLoanCalendar(), loanApplicationTerms.getHolidayDetailDTO(), loanApplicationTerms);
@@ -179,10 +180,12 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
         while (!scheduleParams.getOutstandingBalance().isZero() || !scheduleParams.getDisburseDetailMap().isEmpty()) {
             LocalDate previousRepaymentDate = scheduleParams.getActualRepaymentDate();
             scheduleParams.setActualRepaymentDate(this.scheduledDateGenerator.generateNextRepaymentDate(
-                    scheduleParams.getActualRepaymentDate(), loanApplicationTerms, isFirstRepayment, holidayDetailDTO));
+                    scheduleParams.getActualRepaymentDate(), loanApplicationTerms, isFirstRepayment));
+            AdjustedDateDetailsDTO adjustedDateDetailsDTO = this.scheduledDateGenerator.adjustRepaymentDate(
+                    scheduleParams.getActualRepaymentDate(), loanApplicationTerms, holidayDetailDTO);
+            scheduleParams.setActualRepaymentDate(adjustedDateDetailsDTO.getChangedActualRepaymentDate());
             isFirstRepayment = false;
-            LocalDate scheduledDueDate = this.scheduledDateGenerator.adjustRepaymentDate(scheduleParams.getActualRepaymentDate(),
-                    loanApplicationTerms, holidayDetailDTO);
+            LocalDate scheduledDueDate = adjustedDateDetailsDTO.getChangedScheduleDate();
             
             // calculated interest start date for the period
             LocalDate periodStartDateApplicableForInterest = calculateInterestStartDateForPeriod(loanApplicationTerms,
@@ -1320,7 +1323,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
         do {
 
             params.setActualRepaymentDate(this.scheduledDateGenerator.generateNextRepaymentDate(params.getActualRepaymentDate(),
-                    loanApplicationTerms, isFirstRepayment, holidayDetailDTO));
+                    loanApplicationTerms, isFirstRepayment));
             if (params.getActualRepaymentDate().isAfter(currentDate)) {
                 params.setActualRepaymentDate(currentDate);
             }
@@ -2172,41 +2175,17 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
                     ArrayList<LoanTermVariationsData> dueDateVariationsDataList = new ArrayList<>();
                     
 
-                 // check for date changes
+                   // check for date changes
                    
-                    do {
-                        actualRepaymentDate = this.scheduledDateGenerator.generateNextRepaymentDate(actualRepaymentDate,
-                                loanApplicationTerms, isFirstRepayment, holidayDetailDTO);
-                        isFirstRepayment = false;
-                        lastInstallmentDate = this.scheduledDateGenerator.adjustRepaymentDate(actualRepaymentDate, loanApplicationTerms,
-                                holidayDetailDTO);
-                        while (loanApplicationTerms.getLoanTermVariations().hasDueDateVariation(lastInstallmentDate)) {
-                            LoanTermVariationsData variation = loanApplicationTerms.getLoanTermVariations().nextDueDateVariation();
-                            if (!variation.isSpecificToInstallment()) {
-                                actualRepaymentDate = variation.getDateValue();
-                                /*if (!isDueDateChangeApplied) {
-                                    previousRepaymentDate = actualRepaymentDate;
-                                    isDueDateChangeApplied = true;
-                                }*/
-                                lastInstallmentDate = actualRepaymentDate;
-                            }
-                            dueDateVariationsDataList.add(variation);
+                    while (loanApplicationTerms.getLoanTermVariations().hasDueDateVariation(lastInstallmentDate)) {
+                        LoanTermVariationsData variation = loanApplicationTerms.getLoanTermVariations().nextDueDateVariation();
+                        if (!variation.isSpecificToInstallment()) {
+                            actualRepaymentDate = variation.getDateValue();
+                            loanApplicationTerms.setSeedDate(actualRepaymentDate);
                         }
-                        loanTermVariationParams = applyExceptionLoanTermVariations(loanApplicationTerms, lastInstallmentDate,
-                                exceptionDataListIterator, instalmentNumber, totalCumulativePrincipal, totalCumulativeInterest, mc);
-                    } while (loanTermVariationParams != null && loanTermVariationParams.isSkipPeriod());
-
-                    /*if (!lastInstallmentDate.isBefore(rescheduleFrom)) {
-                        actualRepaymentDate = previousRepaymentDate;
-                        if(isDueDateChangeApplied){
-                            int numberOfDateChangesApplied = dueDateVariationsDataList.size();
-                            while(numberOfDateChangesApplied >0 ){
-                                loanApplicationTerms.getLoanTermVariations().previousDueDateVariation();
-                                numberOfDateChangesApplied--;
-                            }
-                        }
-                        break;
-                    }*/
+                        lastInstallmentDate = variation.getDateValue();
+                        dueDateVariationsDataList.add(variation);
+                    }
                     periodNumber++;
 
                     for (LoanTermVariationsData dueDateVariation : dueDateVariationsDataList) {

http://git-wip-us.apache.org/repos/asf/fineract/blob/b9017e2b/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 93a58ce..5974d3f 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
@@ -20,6 +20,7 @@ package org.apache.fineract.portfolio.loanaccount.loanschedule.domain;
 
 import org.apache.fineract.organisation.holiday.domain.Holiday;
 import org.apache.fineract.organisation.holiday.service.HolidayUtil;
+import org.apache.fineract.organisation.workingdays.data.AdjustedDateDetailsDTO;
 import org.apache.fineract.organisation.workingdays.domain.RepaymentRescheduleType;
 import org.apache.fineract.organisation.workingdays.domain.WorkingDays;
 import org.apache.fineract.organisation.workingdays.service.WorkingDaysUtil;
@@ -45,25 +46,26 @@ public class DefaultScheduledDateGenerator implements ScheduledDateGenerator {
         LocalDate lastRepaymentDate = loanApplicationTerms.getExpectedDisbursementDate();
         boolean isFirstRepayment = true;
         for (int repaymentPeriod = 1; repaymentPeriod <= numberOfRepayments; repaymentPeriod++) {
-            lastRepaymentDate = generateNextRepaymentDate(lastRepaymentDate, loanApplicationTerms, isFirstRepayment, holidayDetailDTO);
+            lastRepaymentDate = generateNextRepaymentDate(lastRepaymentDate, loanApplicationTerms, isFirstRepayment);
             isFirstRepayment = false;
         }
-        lastRepaymentDate = adjustRepaymentDate(lastRepaymentDate, loanApplicationTerms, holidayDetailDTO);
+        lastRepaymentDate = adjustRepaymentDate(lastRepaymentDate, loanApplicationTerms, holidayDetailDTO).getChangedScheduleDate();
         return lastRepaymentDate;
     }
 
     @Override
     public LocalDate generateNextRepaymentDate(final LocalDate lastRepaymentDate, final LoanApplicationTerms loanApplicationTerms,
-            boolean isFirstRepayment, final HolidayDetailDTO holidayDetailDTO) {
+            boolean isFirstRepayment) {
         final LocalDate firstRepaymentPeriodDate = loanApplicationTerms.getCalculatedRepaymentsStartingFromLocalDate();
         LocalDate dueRepaymentPeriodDate = null;
-        Calendar currentCalendar = loanApplicationTerms.getLoanCalendar();
         if (isFirstRepayment && firstRepaymentPeriodDate != null) {
             dueRepaymentPeriodDate = firstRepaymentPeriodDate;
         } else {
+                 LocalDate seedDate = null;
+             String reccuringString = null;
+            Calendar currentCalendar = loanApplicationTerms.getLoanCalendar();
             dueRepaymentPeriodDate = getRepaymentPeriodDate(loanApplicationTerms.getRepaymentPeriodFrequencyType(),
-                    loanApplicationTerms.getRepaymentEvery(), lastRepaymentDate, null,
-                    null);
+                    loanApplicationTerms.getRepaymentEvery(), lastRepaymentDate);
             dueRepaymentPeriodDate = CalendarUtils.adjustDate(dueRepaymentPeriodDate, loanApplicationTerms.getSeedDate(),
                     loanApplicationTerms.getRepaymentPeriodFrequencyType());
             if (currentCalendar != null) {
@@ -79,8 +81,6 @@ public class DefaultScheduledDateGenerator implements ScheduledDateGenerator {
                 }
  
                 // get the start date from the calendar history
-                LocalDate seedDate = null;
-                String reccuringString = null;
                 if (calendarHistory == null) {
                     seedDate = currentCalendar.getStartDateLocalDate();
                     reccuringString = currentCalendar.getRecurrence();
@@ -89,80 +89,130 @@ public class DefaultScheduledDateGenerator implements ScheduledDateGenerator {
                     reccuringString = calendarHistory.getRecurrence();
                 }
 
-                dueRepaymentPeriodDate = CalendarUtils.getNewRepaymentMeetingDate(reccuringString, seedDate, lastRepaymentDate.plusDays(1),
+                dueRepaymentPeriodDate = CalendarUtils.getNextRepaymentMeetingDate(reccuringString, seedDate, lastRepaymentDate,
                         loanApplicationTerms.getRepaymentEvery(),
                         CalendarUtils.getMeetingFrequencyFromPeriodFrequencyType(loanApplicationTerms.getLoanTermPeriodFrequencyType()),
-                        holidayDetailDTO.getWorkingDays(), loanApplicationTerms.isSkipRepaymentOnFirstDayofMonth(),
+                        loanApplicationTerms.isSkipRepaymentOnFirstDayofMonth(),
                         loanApplicationTerms.getNumberOfdays());
             }
         }
-        if (currentCalendar == null && holidayDetailDTO.getWorkingDays().getExtendTermForRepaymentsOnHolidays()) {
-            boolean repaymentDateIsOnHoliday = false;
-            // compile the list of holidays into Intervals to see if this date lands on a holiday
-            final List<Interval> holidayInterval = new ArrayList<>();
-            for (Holiday holiday : holidayDetailDTO.getHolidays()) {
-                holidayInterval.add(new Interval(
-                        holiday.getFromDateLocalDate().toDateTimeAtStartOfDay(),
-                        holiday.getToDateLocalDate().toDateTime(LocalTime.parse("23:59:59"))
-                ));
-            }
-            while (intervalListContainsDate(holidayInterval, dueRepaymentPeriodDate)) {
-                LocalDate previousDate = dueRepaymentPeriodDate;
-                dueRepaymentPeriodDate = getRepaymentPeriodDate(loanApplicationTerms.getRepaymentPeriodFrequencyType(),
-                        loanApplicationTerms.getRepaymentEvery(), dueRepaymentPeriodDate, loanApplicationTerms.getNthDay(),
-                        loanApplicationTerms.getWeekDayType());
-            }
-        }
+        
         return dueRepaymentPeriodDate;
     }
-    private boolean intervalListContainsDate(List<Interval> intervalList, LocalDate date) {
-        for (Interval interval : intervalList) {
-            if (interval.contains(date.toDateTime(LocalTime.parse("11:59:59")))) {
-                return true;
-            }
-        }
-        return false;
-    }
-    @Override
-    public LocalDate adjustRepaymentDate(final LocalDate dueRepaymentPeriodDate, final LoanApplicationTerms loanApplicationTerms,
-            final HolidayDetailDTO holidayDetailDTO) {
 
-        LocalDate adjustedDate = dueRepaymentPeriodDate;
+    @Override
+    public AdjustedDateDetailsDTO adjustRepaymentDate(final LocalDate dueRepaymentPeriodDate,
+            final LoanApplicationTerms loanApplicationTerms, final HolidayDetailDTO holidayDetailDTO) {
+        final LocalDate adjustedDate = dueRepaymentPeriodDate;
+        return getAdjustedDateDetailsDTO(dueRepaymentPeriodDate, loanApplicationTerms, holidayDetailDTO, adjustedDate);
+    }
 
-        LocalDate nextDueRepaymentPeriodDate = getRepaymentPeriodDate(loanApplicationTerms.getRepaymentPeriodFrequencyType(),
-                loanApplicationTerms.getRepaymentEvery(), adjustedDate, loanApplicationTerms.getNthDay(),
-                loanApplicationTerms.getWeekDayType());
+    private AdjustedDateDetailsDTO getAdjustedDateDetailsDTO(final LocalDate dueRepaymentPeriodDate,
+            final LoanApplicationTerms loanApplicationTerms, final HolidayDetailDTO holidayDetailDTO, final LocalDate adjustedDate) {
+        final boolean isFirstRepayment = false;
+        final LocalDate nextRepaymentPeriodDueDate = generateNextRepaymentDate(adjustedDate, loanApplicationTerms, isFirstRepayment);
+        final AdjustedDateDetailsDTO newAdjustedDateDetailsDTO = new AdjustedDateDetailsDTO(adjustedDate, dueRepaymentPeriodDate,
+                nextRepaymentPeriodDueDate);
+        return recursivelyCheckNonWorkingDaysAndHolidaysAndWorkingDaysExemptionToGenerateNextRepaymentPeriodDate(newAdjustedDateDetailsDTO,
+                loanApplicationTerms, holidayDetailDTO, isFirstRepayment);
+    }
 
-        final RepaymentRescheduleType rescheduleType = RepaymentRescheduleType.fromInt(holidayDetailDTO.getWorkingDays()
-                .getRepaymentReschedulingType());
+    /**
+     * Recursively checking non working days and holidays and working days
+     * exemption to generate next repayment period date Base on the
+     * configuration
+     * 
+     * @param adjustedDateDetailsDTO
+     * @param loanApplicationTerms
+     * @param holidayDetailDTO
+     * @param nextRepaymentPeriodDueDate
+     * @param rescheduleType
+     * @param isFirstRepayment
+     * @return
+     */
+    private AdjustedDateDetailsDTO recursivelyCheckNonWorkingDaysAndHolidaysAndWorkingDaysExemptionToGenerateNextRepaymentPeriodDate(
+            final AdjustedDateDetailsDTO adjustedDateDetailsDTO, final LoanApplicationTerms loanApplicationTerms,
+            final HolidayDetailDTO holidayDetailDTO, final boolean isFirstRepayment) {
+        
+        checkAndUpdateWorkingDayIfRepaymentDateIsNonWorkingDay(adjustedDateDetailsDTO, holidayDetailDTO, loanApplicationTerms,
+                isFirstRepayment);
+        
+        checkAndUpdateWorkingDayIfRepaymentDateIsHolidayDay(adjustedDateDetailsDTO, holidayDetailDTO, loanApplicationTerms,
+                isFirstRepayment);
 
         /**
-         * Fix for https://mifosforge.jira.com/browse/MIFOSX-1357
+         * Check Changed Schedule Date is holiday or is not a working day Then
+         * re-call this method to get the non holiday and working day
          */
-        // recursively check for the next working meeting day.
-        while (WorkingDaysUtil.isNonWorkingDay(holidayDetailDTO.getWorkingDays(), nextDueRepaymentPeriodDate)
-                && rescheduleType == RepaymentRescheduleType.MOVE_TO_NEXT_REPAYMENT_MEETING_DAY) {
-
-            nextDueRepaymentPeriodDate = getRepaymentPeriodDate(loanApplicationTerms.getRepaymentPeriodFrequencyType(),
-                    loanApplicationTerms.getRepaymentEvery(), nextDueRepaymentPeriodDate, loanApplicationTerms.getNthDay(),
-                    loanApplicationTerms.getWeekDayType());
-            nextDueRepaymentPeriodDate = CalendarUtils.adjustDate(nextDueRepaymentPeriodDate, loanApplicationTerms.getSeedDate(),
-                    loanApplicationTerms.getRepaymentPeriodFrequencyType());
-
+        if ((holidayDetailDTO.isHolidayEnabled() && HolidayUtil.getApplicableHoliday(adjustedDateDetailsDTO.getChangedScheduleDate(),
+                holidayDetailDTO.getHolidays()) != null)
+                || WorkingDaysUtil.isNonWorkingDay(holidayDetailDTO.getWorkingDays(), adjustedDateDetailsDTO.getChangedScheduleDate())) {
+            recursivelyCheckNonWorkingDaysAndHolidaysAndWorkingDaysExemptionToGenerateNextRepaymentPeriodDate(adjustedDateDetailsDTO,
+                    loanApplicationTerms, holidayDetailDTO, isFirstRepayment);
         }
-        adjustedDate = WorkingDaysUtil.getOffSetDateIfNonWorkingDay(adjustedDate, nextDueRepaymentPeriodDate,
-                holidayDetailDTO.getWorkingDays());
+        return adjustedDateDetailsDTO;
+    } 
 
+    /**
+     * This method to check and update the working day if repayment date is
+     * holiday
+     * 
+     * @param adjustedDateDetailsDTO
+     * @param holidayDetailDTO
+     * @param loanApplicationTerms
+     * @param isFirstRepayment
+     */
+    private void checkAndUpdateWorkingDayIfRepaymentDateIsHolidayDay(final AdjustedDateDetailsDTO adjustedDateDetailsDTO,
+            final HolidayDetailDTO holidayDetailDTO, final LoanApplicationTerms loanApplicationTerms, final boolean isFirstRepayment) {
         if (holidayDetailDTO.isHolidayEnabled()) {
-            adjustedDate = HolidayUtil.getRepaymentRescheduleDateToIfHoliday(adjustedDate, holidayDetailDTO.getHolidays());
+            Holiday applicableHolidayForNewAdjustedDate = null;
+            while ((applicableHolidayForNewAdjustedDate = HolidayUtil.getApplicableHoliday(adjustedDateDetailsDTO.getChangedScheduleDate(),
+                    holidayDetailDTO.getHolidays())) != null) {
+                if (applicableHolidayForNewAdjustedDate.getReScheduleType().isResheduleToNextRepaymentDate()) {
+                    LocalDate nextRepaymentPeriodDueDate = adjustedDateDetailsDTO.getChangedActualRepaymentDate();
+                    while (!nextRepaymentPeriodDueDate.isAfter(adjustedDateDetailsDTO.getChangedScheduleDate())) {
+                        nextRepaymentPeriodDueDate = generateNextRepaymentDate(nextRepaymentPeriodDueDate, loanApplicationTerms,
+                                isFirstRepayment);
+                    }
+                    adjustedDateDetailsDTO.setChangedScheduleDate(nextRepaymentPeriodDueDate);
+                    adjustedDateDetailsDTO.setNextRepaymentPeriodDueDate(nextRepaymentPeriodDueDate);
+                    adjustedDateDetailsDTO.setChangedActualRepaymentDate(adjustedDateDetailsDTO.getChangedScheduleDate());
+                } else {
+                    HolidayUtil.updateRepaymentRescheduleDateToWorkingDayIfItIsHoliday(adjustedDateDetailsDTO,
+                            applicableHolidayForNewAdjustedDate);
+                }
+            }
         }
+    }
 
-        return adjustedDate;
+    /**
+     * This method to check and update the working day if repayment date is non
+     * working day
+     * 
+     * @param adjustedDateDetailsDTO
+     * @param holidayDetailDTO
+     * @param isFirstRepayment 
+     * @param loanApplicationTerms 
+     */
+    private void checkAndUpdateWorkingDayIfRepaymentDateIsNonWorkingDay(final AdjustedDateDetailsDTO adjustedDateDetailsDTO,
+            final HolidayDetailDTO holidayDetailDTO, final LoanApplicationTerms loanApplicationTerms, final boolean isFirstRepayment) {
+        while (WorkingDaysUtil.isNonWorkingDay(holidayDetailDTO.getWorkingDays(), adjustedDateDetailsDTO.getChangedScheduleDate())) {
+            if (WorkingDaysUtil.getRepaymentRescheduleType(holidayDetailDTO.getWorkingDays(),
+                    adjustedDateDetailsDTO.getChangedScheduleDate()).isMoveToNextRepaymentDay()) {
+                while (WorkingDaysUtil.isNonWorkingDay(holidayDetailDTO.getWorkingDays(),
+                        adjustedDateDetailsDTO.getNextRepaymentPeriodDueDate())
+                        || adjustedDateDetailsDTO.getChangedScheduleDate().isAfter(adjustedDateDetailsDTO.getNextRepaymentPeriodDueDate())) {
+                    final LocalDate nextRepaymentPeriodDueDate = generateNextRepaymentDate(
+                            adjustedDateDetailsDTO.getNextRepaymentPeriodDueDate(), loanApplicationTerms, isFirstRepayment);
+                    adjustedDateDetailsDTO.setNextRepaymentPeriodDueDate(nextRepaymentPeriodDueDate);
+                }
+            }
+            WorkingDaysUtil.updateWorkingDayIfRepaymentDateIsNonWorkingDay(adjustedDateDetailsDTO, holidayDetailDTO.getWorkingDays());
+        }
     }
 
     @Override
-    public LocalDate getRepaymentPeriodDate(final PeriodFrequencyType frequency, final int repaidEvery, final LocalDate startDate,
-            Integer nthDay, DayOfWeekType dayOfWeek) {
+    public LocalDate getRepaymentPeriodDate(final PeriodFrequencyType frequency, final int repaidEvery, final LocalDate startDate) {
         LocalDate dueRepaymentPeriodDate = startDate;
         switch (frequency) {
             case DAYS:
@@ -173,9 +223,6 @@ public class DefaultScheduledDateGenerator implements ScheduledDateGenerator {
             break;
             case MONTHS:
                 dueRepaymentPeriodDate = startDate.plusMonths(repaidEvery);
-                if (!(nthDay == null || dayOfWeek == null || dayOfWeek == DayOfWeekType.INVALID)) {
-                    dueRepaymentPeriodDate = adjustToNthWeekDay(dueRepaymentPeriodDate, nthDay, dayOfWeek.getValue());
-                }
             break;
             case YEARS:
                 dueRepaymentPeriodDate = startDate.plusYears(repaidEvery);
@@ -282,10 +329,10 @@ public class DefaultScheduledDateGenerator implements ScheduledDateGenerator {
         LocalDate generatedDate = loanApplicationTerms.getExpectedDisbursementDate();
         boolean isFirstRepayment = true;
         while (!generatedDate.isAfter(lastRepaymentDate)) {
-            generatedDate = generateNextRepaymentDate(generatedDate, loanApplicationTerms, isFirstRepayment, holidayDetailDTO);
+            generatedDate = generateNextRepaymentDate(generatedDate, loanApplicationTerms, isFirstRepayment);
             isFirstRepayment = false;
         }
-        generatedDate = adjustRepaymentDate(generatedDate, loanApplicationTerms, holidayDetailDTO);
+        generatedDate = adjustRepaymentDate(generatedDate, loanApplicationTerms, holidayDetailDTO).getChangedScheduleDate();
         return generatedDate;
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/fineract/blob/b9017e2b/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 8db5aff..d5f08cb 100644
--- 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
@@ -183,7 +183,7 @@ public final class LoanApplicationTerms {
 
     private Money adjustPrincipalForFlatLoans;
 
-    private final LocalDate seedDate;
+    private LocalDate seedDate;
 
     private final CalendarHistoryDataWrapper calendarHistoryDataWrapper;
 
@@ -1742,5 +1742,9 @@ public final class LoanApplicationTerms {
     public void updateTotalInterestAccounted(Money totalInterestAccounted){
         this.totalInterestAccounted = totalInterestAccounted;
     }
+
+    public void setSeedDate(LocalDate seedDate) {
+        this.seedDate = seedDate;
+    }
     
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/fineract/blob/b9017e2b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/ScheduledDateGenerator.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/ScheduledDateGenerator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/ScheduledDateGenerator.java
index c82301d..2119472 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/ScheduledDateGenerator.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/ScheduledDateGenerator.java
@@ -18,6 +18,7 @@
  */
 package org.apache.fineract.portfolio.loanaccount.loanschedule.domain;
 
+import org.apache.fineract.organisation.workingdays.data.AdjustedDateDetailsDTO;
 import org.apache.fineract.portfolio.calendar.domain.Calendar;
 import org.apache.fineract.portfolio.common.domain.DayOfWeekType;
 import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
@@ -32,14 +33,12 @@ public interface ScheduledDateGenerator {
             final LocalDate firstRepaymentDate, final Calendar loanCalendar, final HolidayDetailDTO holidayDetailDTO,
             final LoanApplicationTerms loanApplicationTerms);
 
-    LocalDate generateNextRepaymentDate(LocalDate lastRepaymentDate, LoanApplicationTerms loanApplicationTerms, boolean isFirstRepayment,
-            final HolidayDetailDTO holidayDetailDTO);
+    LocalDate generateNextRepaymentDate(LocalDate lastRepaymentDate, LoanApplicationTerms loanApplicationTerms, boolean isFirstRepayment);
 
-    LocalDate adjustRepaymentDate(LocalDate dueRepaymentPeriodDate, LoanApplicationTerms loanApplicationTerms,
+    AdjustedDateDetailsDTO  adjustRepaymentDate(LocalDate dueRepaymentPeriodDate, LoanApplicationTerms loanApplicationTerms,
             final HolidayDetailDTO holidayDetailDTO);
 
-    LocalDate getRepaymentPeriodDate(PeriodFrequencyType frequency, int repaidEvery, LocalDate startDate, Integer nthDay,
-            DayOfWeekType dayOfWeek);
+    LocalDate getRepaymentPeriodDate(PeriodFrequencyType frequency, int repaidEvery, LocalDate startDate);
 
     Boolean isDateFallsInSchedule(PeriodFrequencyType frequency, int repaidEvery, LocalDate startDate, LocalDate date);
 

http://git-wip-us.apache.org/repos/asf/fineract/blob/b9017e2b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanReschedulePreviewPlatformServiceImpl.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanReschedulePreviewPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanReschedulePreviewPlatformServiceImpl.java
index e5ab38d..ef64ec3 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanReschedulePreviewPlatformServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanReschedulePreviewPlatformServiceImpl.java
@@ -114,10 +114,10 @@ public class LoanReschedulePreviewPlatformServiceImpl implements LoanRescheduleP
         for (LoanTermVariationsData loanTermVariation : loanApplicationTerms.getLoanTermVariations().getDueDateVariation()) {
             if (rescheduleFromDate.isBefore(loanTermVariation.getTermApplicableFrom())) {
                 LocalDate applicableDate = this.scheduledDateGenerator.generateNextRepaymentDate(rescheduleFromDate, loanApplicationTerms,
-                        false, loanApplicationTerms.getHolidayDetailDTO());
+                        false);
                 if (loanTermVariation.getTermApplicableFrom().equals(applicableDate)) {
                     LocalDate adjustedDate = this.scheduledDateGenerator.generateNextRepaymentDate(adjustedApplicableDate,
-                            loanApplicationTerms, false, loanApplicationTerms.getHolidayDetailDTO());
+                            loanApplicationTerms, false);
                     loanTermVariation.setApplicableFromDate(adjustedDate);
                     loanTermVariationsData.add(loanTermVariation);
                 }

http://git-wip-us.apache.org/repos/asf/fineract/blob/b9017e2b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java
index 977e7ba..ebffa27 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java
@@ -410,9 +410,9 @@ public class LoanRescheduleRequestWritePlatformServiceImpl implements LoanResche
                     } else if (!activeLoanTermVariation.fetchTermApplicaDate().isBefore(fromScheduleDate)) {
                         while (currentScheduleDate.isBefore(activeLoanTermVariation.fetchTermApplicaDate())) {
                             currentScheduleDate = this.scheduledDateGenerator.generateNextRepaymentDate(currentScheduleDate,
-                                    loanApplicationTerms, false, loanApplicationTerms.getHolidayDetailDTO());
+                                    loanApplicationTerms, false);
                             modifiedScheduleDate = this.scheduledDateGenerator.generateNextRepaymentDate(modifiedScheduleDate,
-                                    loanApplicationTerms, false, loanApplicationTerms.getHolidayDetailDTO());
+                                    loanApplicationTerms, false);
                             changeMap.put(currentScheduleDate, modifiedScheduleDate);
                         }
                         if (changeMap.containsKey(activeLoanTermVariation.fetchTermApplicaDate())) {

http://git-wip-us.apache.org/repos/asf/fineract/blob/b9017e2b/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 98f86fc..5744b67 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
@@ -2421,7 +2421,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
             while (!startDate.isAfter(DateUtils.getLocalDateOfTenant())) {
                 scheduleDates.put(frequencyNunber++, startDate.minusDays(diff.intValue()));
                 LocalDate scheduleDate = scheduledDateGenerator.getRepaymentPeriodDate(PeriodFrequencyType.fromInt(feeFrequency),
-                        chargeDefinition.feeInterval(), startDate, null, null);
+                        chargeDefinition.feeInterval(), startDate);
 
                 startDate = scheduleDate;
             }

http://git-wip-us.apache.org/repos/asf/fineract/blob/b9017e2b/fineract-provider/src/main/resources/sql/migrations/core_db/V331__holiday_schema_changes.sql
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/resources/sql/migrations/core_db/V331__holiday_schema_changes.sql b/fineract-provider/src/main/resources/sql/migrations/core_db/V331__holiday_schema_changes.sql
new file mode 100644
index 0000000..94ae19a
--- /dev/null
+++ b/fineract-provider/src/main/resources/sql/migrations/core_db/V331__holiday_schema_changes.sql
@@ -0,0 +1,23 @@
+--
+-- 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.
+--
+
+
+ALTER TABLE m_holiday
+MODIFY COLUMN repayments_rescheduled_to DATETIME NULL DEFAULT NULL,
+ADD COLUMN `rescheduling_type` INT(5) NOT NULL DEFAULT '2';
\ No newline at end of file


[2/2] fineract git commit: Merge branch 'FINERACT-37' into develop

Posted by na...@apache.org.
Merge branch 'FINERACT-37' into develop


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

Branch: refs/heads/develop
Commit: c3a602ced8057bc02cee43dab041f25b8f293c59
Parents: 0373ce4 b9017e2
Author: Nazeer Hussain Shaik <na...@confluxtechnologies.com>
Authored: Thu Jul 20 18:50:02 2017 +0530
Committer: Nazeer Hussain Shaik <na...@confluxtechnologies.com>
Committed: Thu Jul 20 18:50:02 2017 +0530

----------------------------------------------------------------------
 .../holiday/api/HolidayApiConstants.java        |   1 +
 .../holiday/api/HolidaysApiResource.java        |   9 +
 .../organisation/holiday/data/HolidayData.java  |   4 +-
 .../holiday/data/HolidayDataValidator.java      |  22 ++-
 .../organisation/holiday/domain/Holiday.java    |  36 +++-
 .../holiday/domain/RescheduleType.java          |  64 +++++++
 .../holiday/service/HolidayEnumerations.java    |  26 +++
 .../service/HolidayReadPlatformService.java     |   4 +
 .../service/HolidayReadPlatformServiceImpl.java |  16 +-
 .../holiday/service/HolidayUtil.java            |  17 ++
 ...ayWritePlatformServiceJpaRepositoryImpl.java |  68 ++++---
 .../data/AdjustedDateDetailsDTO.java            |  76 ++++++++
 .../domain/RepaymentRescheduleType.java         |   7 +-
 .../workingdays/service/WorkingDaysUtil.java    |  12 ++
 .../calendar/service/CalendarUtils.java         | 108 +++++++++++
 .../domain/AbstractLoanScheduleGenerator.java   |  55 ++----
 .../domain/DefaultScheduledDateGenerator.java   | 179 ++++++++++++-------
 .../domain/LoanApplicationTerms.java            |   6 +-
 .../domain/ScheduledDateGenerator.java          |   9 +-
 ...oanReschedulePreviewPlatformServiceImpl.java |   4 +-
 ...scheduleRequestWritePlatformServiceImpl.java |   4 +-
 ...anWritePlatformServiceJpaRepositoryImpl.java |   2 +-
 .../core_db/V331__holiday_schema_changes.sql    |  23 +++
 23 files changed, 594 insertions(+), 158 deletions(-)
----------------------------------------------------------------------