http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleModelDisbursementPeriod.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleModelDisbursementPeriod.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleModelDisbursementPeriod.java
index acb33a8..87d2332 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleModelDisbursementPeriod.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleModelDisbursementPeriod.java
@@ -19,8 +19,10 @@
 package org.apache.fineract.portfolio.loanaccount.loanschedule.domain;
 
 import java.math.BigDecimal;
+import java.util.List;
 
 import org.apache.fineract.organisation.monetary.domain.Money;
+import 
org.apache.fineract.portfolio.loanaccount.domain.LoanInterestRecalcualtionAdditionalDetails;
 import 
org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanSchedulePeriodData;
 import org.joda.time.LocalDate;
 
@@ -122,4 +124,8 @@ public final class LoanScheduleModelDisbursementPeriod 
implements LoanScheduleMo
     public void addInterestAmount(@SuppressWarnings("unused") Money 
principalDue) {
         return;
     }
+    @Override
+    public List<LoanInterestRecalcualtionAdditionalDetails> 
getLoanCompoundingDetails() {
+        return null;
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleModelPeriod.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleModelPeriod.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleModelPeriod.java
index 7792416..db67677 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleModelPeriod.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleModelPeriod.java
@@ -19,8 +19,10 @@
 package org.apache.fineract.portfolio.loanaccount.loanschedule.domain;
 
 import java.math.BigDecimal;
+import java.util.List;
 
 import org.apache.fineract.organisation.monetary.domain.Money;
+import 
org.apache.fineract.portfolio.loanaccount.domain.LoanInterestRecalcualtionAdditionalDetails;
 import 
org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanSchedulePeriodData;
 import org.joda.time.LocalDate;
 
@@ -51,4 +53,5 @@ public interface LoanScheduleModelPeriod {
     void addPrincipalAmount(Money principalDue);
     
     void addInterestAmount(Money interestDue);
+    List<LoanInterestRecalcualtionAdditionalDetails> 
getLoanCompoundingDetails();
 }

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleModelRepaymentPeriod.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleModelRepaymentPeriod.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleModelRepaymentPeriod.java
index 5b8208e..201e7ca 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleModelRepaymentPeriod.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleModelRepaymentPeriod.java
@@ -19,8 +19,11 @@
 package org.apache.fineract.portfolio.loanaccount.loanschedule.domain;
 
 import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
 
 import org.apache.fineract.organisation.monetary.domain.Money;
+import 
org.apache.fineract.portfolio.loanaccount.domain.LoanInterestRecalcualtionAdditionalDetails;
 import 
org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanSchedulePeriodData;
 import org.joda.time.LocalDate;
 
@@ -40,6 +43,7 @@ public final class LoanScheduleModelRepaymentPeriod 
implements LoanScheduleModel
     private Money penaltyChargesDue;
     private Money totalDue;
     private final boolean recalculatedInterestComponent;
+    private final List<LoanInterestRecalcualtionAdditionalDetails> 
loanCompoundingDetails = new ArrayList<>();
 
     public static LoanScheduleModelRepaymentPeriod repayment(final int 
periodNumber, final LocalDate startDate,
             final LocalDate scheduledDueDate, final Money principalDue, final 
Money outstandingLoanBalance, final Money interestDue,
@@ -154,4 +158,8 @@ public final class LoanScheduleModelRepaymentPeriod 
implements LoanScheduleModel
         this.interestDue = this.interestDue.plus(interestDue);
         this.totalDue = this.totalDue.plus(principalDue);
     }
+    @Override
+    public List<LoanInterestRecalcualtionAdditionalDetails> 
getLoanCompoundingDetails() {
+        return this.loanCompoundingDetails;
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/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 3761ce0..c82301d 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.portfolio.calendar.domain.Calendar;
 import org.apache.fineract.portfolio.common.domain.DayOfWeekType;
 import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
 import org.apache.fineract.portfolio.loanaccount.data.HolidayDetailDTO;
@@ -28,7 +29,8 @@ public interface ScheduledDateGenerator {
     LocalDate getLastRepaymentDate(LoanApplicationTerms loanApplicationTerms, 
final HolidayDetailDTO holidayDetailDTO);
 
     LocalDate 
idealDisbursementDateBasedOnFirstRepaymentDate(PeriodFrequencyType 
repaymentPeriodFrequencyType, int repaidEvery,
-            final LocalDate firstRepaymentDate);
+            final LocalDate firstRepaymentDate, final Calendar loanCalendar, 
final HolidayDetailDTO holidayDetailDTO,
+            final LoanApplicationTerms loanApplicationTerms);
 
     LocalDate generateNextRepaymentDate(LocalDate lastRepaymentDate, 
LoanApplicationTerms loanApplicationTerms, boolean isFirstRepayment,
             final HolidayDetailDTO holidayDetailDTO);

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java
index 56248ec..b86f2a7 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java
@@ -68,6 +68,7 @@ import 
org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper;
 import org.apache.fineract.portfolio.common.domain.DayOfWeekType;
 import org.apache.fineract.portfolio.common.domain.DaysInMonthType;
 import org.apache.fineract.portfolio.common.domain.DaysInYearType;
+import org.apache.fineract.portfolio.common.domain.NthDayType;
 import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
 import org.apache.fineract.portfolio.floatingrates.data.FloatingRateDTO;
 import org.apache.fineract.portfolio.floatingrates.data.FloatingRatePeriodData;
@@ -115,7 +116,6 @@ import 
org.apache.fineract.portfolio.loanproduct.service.LoanEnumerations;
 import org.apache.fineract.useradministration.domain.AppUser;
 import org.joda.time.Days;
 import org.joda.time.LocalDate;
-import org.joda.time.LocalTime;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
@@ -256,6 +256,12 @@ public class LoanScheduleAssembler {
             final PeriodFrequencyType meetingPeriodFrequency = 
CalendarUtils.getMeetingPeriodFrequencyType(calendar.getRecurrence());
             
validateRepaymentFrequencyIsSameAsMeetingFrequency(meetingPeriodFrequency.getValue(),
 repaymentFrequencyType,
                     CalendarUtils.getInterval(calendar.getRecurrence()), 
repaymentEvery);
+        } else {
+            if (repaymentPeriodFrequencyType == PeriodFrequencyType.MONTHS && 
nthDay != null && nthDay != NthDayType.INVALID.getValue()) {
+                LocalDate calendarStartDate = repaymentsStartingFromDate;
+                if (calendarStartDate == null) calendarStartDate = 
expectedDisbursementDate;
+                calendar = createLoanCalendar(calendarStartDate, 
repaymentEvery, CalendarFrequencyType.MONTHLY, dayOfWeek, nthDay);
+            }
         }
 
         /*
@@ -306,7 +312,8 @@ public class LoanScheduleAssembler {
         final Integer graceOnInterestPayment = 
this.fromApiJsonHelper.extractIntegerWithLocaleNamed("graceOnInterestPayment", 
element);
         final Integer graceOnInterestCharged = 
this.fromApiJsonHelper.extractIntegerWithLocaleNamed("graceOnInterestCharged", 
element);
         final LocalDate interestChargedFromDate = 
this.fromApiJsonHelper.extractLocalDateNamed("interestChargedFromDate", 
element);
-        final Boolean isInterestChargedFromDateSameAsDisbursalDateEnabled = 
this.configurationDomainService.isInterestChargedFromDateSameAsDisbursementDate();
+        final Boolean isInterestChargedFromDateSameAsDisbursalDateEnabled = 
this.configurationDomainService
+                .isInterestChargedFromDateSameAsDisbursementDate();
 
         final Integer graceOnArrearsAgeing = 
this.fromApiJsonHelper.extractIntegerWithLocaleNamed(
                 LoanProductConstants.graceOnArrearsAgeingParameterName, 
element);
@@ -334,39 +341,47 @@ public class LoanScheduleAssembler {
         CalendarInstance restCalendarInstance = null;
         RecalculationFrequencyType compoundingFrequencyType = null;
         CalendarInstance compoundingCalendarInstance = null;
+        InterestRecalculationCompoundingMethod compoundingMethod = null;
+        boolean allowCompoundingOnEod = false;
         if (isInterestRecalculationEnabled) {
             LoanProductInterestRecalculationDetails 
loanProductInterestRecalculationDetails = loanProduct
                     .getProductInterestRecalculationDetails();
             recalculationFrequencyType = 
loanProductInterestRecalculationDetails.getRestFrequencyType();
+            Integer repeatsOnDay = null;
+            Integer recalculationFrequencyNthDay = 
loanProductInterestRecalculationDetails.getRestFrequencyOnDay();
+            if (recalculationFrequencyNthDay == null) {
+                recalculationFrequencyNthDay = 
loanProductInterestRecalculationDetails.getRestFrequencyNthDay();
+                repeatsOnDay = 
loanProductInterestRecalculationDetails.getRestFrequencyWeekday();
+            }
+            Integer frequency = 
loanProductInterestRecalculationDetails.getRestInterval();
             if (recalculationFrequencyType.isSameAsRepayment()) {
                 restCalendarInstance = 
createCalendarForSameAsRepayment(repaymentEvery, repaymentPeriodFrequencyType,
                         expectedDisbursementDate);
             } else {
-                LocalDate calendarStartDate = 
this.fromApiJsonHelper.extractLocalDateNamed(
-                        
LoanProductConstants.recalculationRestFrequencyDateParamName, element);
-                if (calendarStartDate == null) {
-                    calendarStartDate = expectedDisbursementDate;
-                }
+                LocalDate calendarStartDate = expectedDisbursementDate;
                 restCalendarInstance = 
createInterestRecalculationCalendarInstance(calendarStartDate, 
recalculationFrequencyType,
-                        
loanProductInterestRecalculationDetails.getRestInterval());
+                        frequency, recalculationFrequencyNthDay, repeatsOnDay);
             }
-            InterestRecalculationCompoundingMethod compoundingMethod = 
InterestRecalculationCompoundingMethod
-                    
.fromInt(loanProductInterestRecalculationDetails.getInterestRecalculationCompoundingMethod());
+            compoundingMethod = 
InterestRecalculationCompoundingMethod.fromInt(loanProductInterestRecalculationDetails
+                    .getInterestRecalculationCompoundingMethod());
             if (compoundingMethod.isCompoundingEnabled()) {
+                Integer compoundingRepeatsOnDay = null;
+                Integer recalculationCompoundingFrequencyNthDay = 
loanProductInterestRecalculationDetails.getCompoundingFrequencyOnDay();
+                if (recalculationCompoundingFrequencyNthDay == null) {
+                    recalculationCompoundingFrequencyNthDay = 
loanProductInterestRecalculationDetails.getCompoundingFrequencyNthDay();
+                    compoundingRepeatsOnDay = 
loanProductInterestRecalculationDetails.getCompoundingFrequencyWeekday();
+                }
                 compoundingFrequencyType = 
loanProductInterestRecalculationDetails.getCompoundingFrequencyType();
                 if (compoundingFrequencyType.isSameAsRepayment()) {
                     compoundingCalendarInstance = 
createCalendarForSameAsRepayment(repaymentEvery, repaymentPeriodFrequencyType,
                             expectedDisbursementDate);
                 } else {
-                    LocalDate calendarStartDate = 
this.fromApiJsonHelper.extractLocalDateNamed(
-                            
LoanProductConstants.recalculationCompoundingFrequencyDateParamName, element);
-                    if (calendarStartDate == null) {
-                        calendarStartDate = expectedDisbursementDate;
-                    }
+                    LocalDate calendarStartDate = expectedDisbursementDate;
                     compoundingCalendarInstance = 
createInterestRecalculationCalendarInstance(calendarStartDate, 
compoundingFrequencyType,
-                            
loanProductInterestRecalculationDetails.getCompoundingInterval());
+                            
loanProductInterestRecalculationDetails.getCompoundingInterval(), 
recalculationCompoundingFrequencyNthDay,
+                            compoundingRepeatsOnDay);
                 }
-
+                allowCompoundingOnEod = 
loanProductInterestRecalculationDetails.allowCompoundingOnEod();
             }
         }
 
@@ -405,6 +420,21 @@ public class LoanScheduleAssembler {
             }
         }
 
+        final Long clientId = 
this.fromApiJsonHelper.extractLongNamed("clientId", element);
+        Client client = null;
+        Long officeId = null;
+        if (clientId != null) {
+            client = 
this.clientRepository.findOneWithNotFoundDetection(clientId);
+            officeId = client.getOffice().getId();
+        } else if (groupId != null) {
+            group = this.groupRepository.findOneWithNotFoundDetection(groupId);
+            officeId = group.getOffice().getId();
+        }
+        final boolean isHolidayEnabled = 
this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled();
+        final List<Holiday> holidays = 
this.holidayRepository.findByOfficeIdAndGreaterThanDate(officeId, 
expectedDisbursementDate.toDate(),
+                HolidayStatusType.ACTIVE.getValue());
+        final WorkingDays workingDays = this.workingDaysRepository.findOne();
+        HolidayDetailDTO detailDTO = new HolidayDetailDTO(isHolidayEnabled, 
holidays, workingDays);
         return LoanApplicationTerms.assembleFrom(applicationCurrency, 
loanTermFrequency, loanTermPeriodFrequencyType, numberOfRepayments,
                 repaymentEvery, repaymentPeriodFrequencyType, nthDay, 
weekDayType, amortizationMethod, interestMethod,
                 interestRatePerPeriod, interestRatePeriodFrequencyType, 
annualNominalInterestRate, interestCalculationPeriodMethod,
@@ -412,21 +442,24 @@ public class LoanScheduleAssembler {
                 calculatedRepaymentsStartingFromDate, graceOnPrincipalPayment, 
recurringMoratoriumOnPrincipalPeriods, graceOnInterestPayment, 
graceOnInterestCharged,
                 interestChargedFromDate, inArrearsToleranceMoney, 
loanProduct.isMultiDisburseLoan(), emiAmount, disbursementDatas,
                 maxOutstandingBalance, graceOnArrearsAgeing, daysInMonthType, 
daysInYearType, isInterestRecalculationEnabled,
-                recalculationFrequencyType, restCalendarInstance, 
compoundingCalendarInstance, compoundingFrequencyType,
+                recalculationFrequencyType, restCalendarInstance, 
compoundingMethod, compoundingCalendarInstance, compoundingFrequencyType,
                 principalThresholdForLastInstalment, 
installmentAmountInMultiplesOf, 
loanProduct.preCloseInterestCalculationStrategy(),
-                calendar, BigDecimal.ZERO, loanTermVariations, 
isInterestChargedFromDateSameAsDisbursalDateEnabled,numberOfDays, 
isSkipMeetingOnFirstDay);
+                calendar, BigDecimal.ZERO, loanTermVariations, 
isInterestChargedFromDateSameAsDisbursalDateEnabled,numberOfDays, 
isSkipMeetingOnFirstDay, detailDTO,
+                allowCompoundingOnEod);
 }
 
     private CalendarInstance createCalendarForSameAsRepayment(final Integer 
repaymentEvery,
             final PeriodFrequencyType repaymentPeriodFrequencyType, final 
LocalDate expectedDisbursementDate) {
-
+        final Integer recalculationFrequencyNthDay = null;
+        final Integer repeatsOnDay = expectedDisbursementDate.getDayOfWeek();
         CalendarInstance restCalendarInstance = 
createInterestRecalculationCalendarInstance(expectedDisbursementDate, 
repaymentEvery,
-                CalendarFrequencyType.from(repaymentPeriodFrequencyType));
+                CalendarFrequencyType.from(repaymentPeriodFrequencyType), 
recalculationFrequencyNthDay, repeatsOnDay);
         return restCalendarInstance;
     }
 
     private CalendarInstance createInterestRecalculationCalendarInstance(final 
LocalDate calendarStartDate,
-            final RecalculationFrequencyType recalculationFrequencyType, final 
Integer frequency) {
+            final RecalculationFrequencyType recalculationFrequencyType, final 
Integer frequency,
+            final Integer recalculationFrequencyNthDay, final Integer 
repeatsOnDay) {
 
         CalendarFrequencyType calendarFrequencyType = 
CalendarFrequencyType.INVALID;
         switch (recalculationFrequencyType) {
@@ -443,18 +476,26 @@ public class LoanScheduleAssembler {
             break;
         }
 
-        return createInterestRecalculationCalendarInstance(calendarStartDate, 
frequency, calendarFrequencyType);
+        return createInterestRecalculationCalendarInstance(calendarStartDate, 
frequency, calendarFrequencyType,
+                recalculationFrequencyNthDay, repeatsOnDay);
     }
 
     private CalendarInstance createInterestRecalculationCalendarInstance(final 
LocalDate calendarStartDate, final Integer frequency,
-            CalendarFrequencyType calendarFrequencyType) {
-        final Integer repeatsOnDay = calendarStartDate.getDayOfWeek();
+            CalendarFrequencyType calendarFrequencyType, final Integer 
recalculationFrequencyNthDay, final Integer repeatsOnDay) {
         final String title = "loan_recalculation_detail";
         final Calendar calendar = Calendar.createRepeatingCalendar(title, 
calendarStartDate, CalendarType.COLLECTION.getValue(),
-                calendarFrequencyType, frequency, repeatsOnDay);
+                calendarFrequencyType, frequency, repeatsOnDay, 
recalculationFrequencyNthDay);
         return CalendarInstance.from(calendar, null, 
CalendarEntityType.LOAN_RECALCULATION_REST_DETAIL.getValue());
     }
 
+    private Calendar createLoanCalendar(final LocalDate calendarStartDate, 
final Integer frequency,
+            CalendarFrequencyType calendarFrequencyType, final Integer 
repeatsOnDay, final Integer repeatsOnNthDayOfMonth) {
+        final String title = "loan_schedule";
+        final Calendar calendar = Calendar.createRepeatingCalendar(title, 
calendarStartDate, CalendarType.COLLECTION.getValue(),
+                calendarFrequencyType, frequency, repeatsOnDay, 
repeatsOnNthDayOfMonth);
+        return calendar;
+    }
+
     private List<DisbursementData> fetchDisbursementData(final JsonObject 
command) {
         final Locale locale = 
this.fromApiJsonHelper.extractLocaleParameter(command);
         final String dateFormat = 
this.fromApiJsonHelper.extractDateFormatParameter(command);
@@ -559,7 +600,7 @@ public class LoanScheduleAssembler {
 
         
validateDisbursementDateIsOnNonWorkingDay(loanApplicationTerms.getExpectedDisbursementDate(),
 workingDays);
         
validateDisbursementDateIsOnHoliday(loanApplicationTerms.getExpectedDisbursementDate(),
 isHolidayEnabled, holidays);
-        
+
         Set<LoanDisbursementDetails> loanDisbursementDetails = 
this.loanUtilService.fetchDisbursementData(element.getAsJsonObject());
 
         return assembleLoanScheduleFrom(loanApplicationTerms, 
isHolidayEnabled, holidays, workingDays, element, loanDisbursementDetails);
@@ -996,10 +1037,10 @@ public class LoanScheduleAssembler {
         final LocalDate 
dateBasedOnMinimumDaysBetweenDisbursalAndFirstRepayment = 
expectedDisbursementDate
                 .plusDays(minimumDaysBetweenDisbursalAndFirstRepayment);
 
-        if ((loanType.isJLGAccount() || loanType.isGroupAccount()) && calendar 
!= null) {
+        if (calendar != null) {
 
             final LocalDate refernceDateForCalculatingFirstRepaymentDate = 
expectedDisbursementDate;
-            derivedFirstRepayment = 
deriveFirstRepaymentDateForJLGLoans(repaymentEvery, expectedDisbursementDate,
+            derivedFirstRepayment = 
deriveFirstRepaymentDateForLoans(repaymentEvery, expectedDisbursementDate,
                     refernceDateForCalculatingFirstRepaymentDate, 
repaymentPeriodFrequencyType,
                     minimumDaysBetweenDisbursalAndFirstRepayment, calendar);
 
@@ -1027,7 +1068,7 @@ public class LoanScheduleAssembler {
         return derivedFirstRepayment;
     }
 
-    private LocalDate deriveFirstRepaymentDateForJLGLoans(final Integer 
repaymentEvery, final LocalDate expectedDisbursementDate,
+    private LocalDate deriveFirstRepaymentDateForLoans(final Integer 
repaymentEvery, final LocalDate expectedDisbursementDate,
             final LocalDate refernceDateForCalculatingFirstRepaymentDate, 
final PeriodFrequencyType repaymentPeriodFrequencyType,
             final Integer minimumDaysBetweenDisbursalAndFirstRepayment, final 
Calendar calendar) {
         boolean isMeetingSkipOnFirstDayOfMonth = 
configurationDomainService.isSkippingMeetingOnFirstDayOfMonthEnabled();
@@ -1036,7 +1077,7 @@ public class LoanScheduleAssembler {
         final LocalDate derivedFirstRepayment = 
CalendarUtils.getFirstRepaymentMeetingDate(calendar,
                 refernceDateForCalculatingFirstRepaymentDate, repaymentEvery, 
frequency, isMeetingSkipOnFirstDayOfMonth, numberOfDays);
         final LocalDate minimumFirstRepaymentDate = 
expectedDisbursementDate.plusDays(minimumDaysBetweenDisbursalAndFirstRepayment);
-        return minimumFirstRepaymentDate.isBefore(derivedFirstRepayment) ? 
derivedFirstRepayment : deriveFirstRepaymentDateForJLGLoans(
+        return minimumFirstRepaymentDate.isBefore(derivedFirstRepayment) ? 
derivedFirstRepayment : deriveFirstRepaymentDateForLoans(
                 repaymentEvery, expectedDisbursementDate, 
derivedFirstRepayment, repaymentPeriodFrequencyType,
                 minimumDaysBetweenDisbursalAndFirstRepayment, calendar);
     }

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/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 9ab13ee..3a008ab 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
@@ -63,6 +63,7 @@ import 
org.apache.fineract.portfolio.loanaccount.domain.DefaultLoanLifecycleStat
 import org.apache.fineract.portfolio.loanaccount.domain.Loan;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanInstallmentCharge;
+import 
org.apache.fineract.portfolio.loanaccount.domain.LoanInterestRecalcualtionAdditionalDetails;
 import 
org.apache.fineract.portfolio.loanaccount.domain.LoanLifecycleStateMachine;
 import 
org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository;
@@ -370,13 +371,13 @@ public class 
LoanRescheduleRequestWritePlatformServiceImpl implements LoanResche
                 final Collection<LoanRescheduleModelRepaymentPeriod> periods = 
loanRescheduleModel.getPeriods();
                 List<LoanRepaymentScheduleInstallment> 
repaymentScheduleInstallments = loan.getRepaymentScheduleInstallments();
                 Collection<LoanCharge> waiveLoanCharges = new ArrayList<>();
-
+                final List<LoanInterestRecalcualtionAdditionalDetails> 
compoundingDetails = null;
                 for (LoanRescheduleModelRepaymentPeriod period : periods) {
 
                     if (period.isNew()) {
                         LoanRepaymentScheduleInstallment 
repaymentScheduleInstallment = new LoanRepaymentScheduleInstallment(loan,
                                 period.periodNumber(), 
period.periodFromDate(), period.periodDueDate(), period.principalDue(),
-                                period.interestDue(), BigDecimal.ZERO, 
BigDecimal.ZERO, false);
+                                period.interestDue(), BigDecimal.ZERO, 
BigDecimal.ZERO, false, compoundingDetails);
 
                         
repaymentScheduleInstallments.add(repaymentScheduleInstallment);
                     }

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/CalculateLoanScheduleQueryFromApiJsonHelper.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/CalculateLoanScheduleQueryFromApiJsonHelper.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/CalculateLoanScheduleQueryFromApiJsonHelper.java
index 48a5c51..a03fe9b 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/CalculateLoanScheduleQueryFromApiJsonHelper.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/CalculateLoanScheduleQueryFromApiJsonHelper.java
@@ -46,18 +46,29 @@ public final class 
CalculateLoanScheduleQueryFromApiJsonHelper {
     /**
      * The parameters supported for this command.
      */
-    final Set<String> supportedParameters = new HashSet<>(Arrays.asList("id", 
"clientId", "groupId", "loanType", "calendarId", "productId",
-            "accountNo", "externalId", "fundId", "loanOfficerId", 
"loanPurposeId", "transactionProcessingStrategyId", "principal",
-            "inArrearsTolerance", "interestRatePerPeriod", "repaymentEvery", 
"numberOfRepayments", "loanTermFrequency",
-            "loanTermFrequencyType", "repaymentFrequencyType", 
"amortizationType", "interestType", "interestCalculationPeriodType",
-            
LoanProductConstants.allowPartialPeriodInterestCalcualtionParamName, 
"interestRateFrequencyType", "expectedDisbursementDate",
-            "repaymentsStartingFromDate", "graceOnPrincipalPayment", 
"recurringMoratoriumOnPrincipalPeriods", "graceOnInterestPayment", 
"graceOnInterestCharged",
-            "interestChargedFromDate", "submittedOnDate", "submittedOnNote", 
"locale", "dateFormat", "charges", "collateral",
-            "syncDisbursementWithMeeting", "linkAccountId", 
LoanApiConstants.disbursementDataParameterName,
+    final Set<String> supportedParameters = new 
HashSet<>(Arrays.asList(LoanApiConstants.idParameterName,
+            LoanApiConstants.clientIdParameterName, 
LoanApiConstants.groupIdParameterName, LoanApiConstants.loanTypeParameterName,
+            LoanApiConstants.calendarIdParameterName, 
LoanApiConstants.productIdParameterName, 
LoanApiConstants.accountNoParameterName,
+            LoanApiConstants.externalIdParameterName, 
LoanApiConstants.fundIdParameterName, 
LoanApiConstants.loanOfficerIdParameterName,
+            LoanApiConstants.loanPurposeIdParameterName, 
LoanApiConstants.transactionProcessingStrategyIdParameterName,
+            LoanApiConstants.principalParamName, 
LoanApiConstants.inArrearsToleranceParameterName,
+            LoanApiConstants.interestRatePerPeriodParameterName, 
LoanApiConstants.repaymentEveryParameterName,
+            LoanApiConstants.numberOfRepaymentsParameterName, 
LoanApiConstants.loanTermFrequencyParameterName,
+            LoanApiConstants.loanTermFrequencyTypeParameterName, 
LoanApiConstants.repaymentFrequencyTypeParameterName,
+            LoanApiConstants.amortizationTypeParameterName, 
LoanApiConstants.interestTypeParameterName,
+            LoanApiConstants.interestCalculationPeriodTypeParameterName,
+            
LoanProductConstants.allowPartialPeriodInterestCalcualtionParamName, 
LoanApiConstants.interestRateFrequencyTypeParameterName,
+            LoanApiConstants.disbursementDateParameterName, 
LoanApiConstants.repaymentsStartingFromDateParameterName,
+            LoanApiConstants.graceOnPrincipalPaymentParameterName, 
LoanApiConstants.graceOnInterestPaymentParameterName,
+            LoanApiConstants.graceOnInterestChargedParameterName, 
LoanApiConstants.interestChargedFromDateParameterName,
+            LoanApiConstants.submittedOnDateParameterName, 
LoanApiConstants.submittedOnNoteParameterName,
+            LoanApiConstants.localeParameterName, 
LoanApiConstants.dateFormatParameterName, LoanApiConstants.chargesParameterName,
+            LoanApiConstants.collateralParameterName, 
LoanApiConstants.syncDisbursementWithMeetingParameterName,
+            LoanApiConstants.linkAccountIdParameterName, 
LoanApiConstants.disbursementDataParameterName,
             LoanApiConstants.emiAmountParameterName, 
LoanApiConstants.maxOutstandingBalanceParameterName,
-            LoanProductConstants.graceOnArrearsAgeingParameterName, 
LoanProductConstants.recalculationRestFrequencyDateParamName,
-            "createStandingInstructionAtDisbursement", 
LoanApiConstants.isFloatingInterestRateParameterName,
-            LoanApiConstants.interestRateDifferentialParameterName));
+            LoanProductConstants.graceOnArrearsAgeingParameterName, 
LoanApiConstants.createStandingInstructionAtDisbursementParameterName,
+            LoanApiConstants.isFloatingInterestRateParameterName, 
LoanApiConstants.interestRateDifferentialParameterName,
+            LoanApiConstants.repaymentFrequencyNthDayTypeParameterName, 
LoanApiConstants.repaymentFrequencyDayOfWeekTypeParameterName));
 
     private final FromJsonHelper fromApiJsonHelper;
 

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonHelper.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonHelper.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonHelper.java
index 6b2c4c4..0eaf4af 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonHelper.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonHelper.java
@@ -36,10 +36,10 @@ import 
org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidati
 import 
org.apache.fineract.infrastructure.core.exception.UnsupportedParameterException;
 import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
 import org.apache.fineract.portfolio.accountdetails.domain.AccountType;
+import org.apache.fineract.portfolio.calendar.service.CalendarUtils;
 import org.apache.fineract.portfolio.loanaccount.api.LoanApiConstants;
 import org.apache.fineract.portfolio.loanaccount.domain.Loan;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
-import 
org.apache.fineract.portfolio.loanaccount.domain.LoanInterestRecalculationDetails;
 import org.apache.fineract.portfolio.loanproduct.LoanProductConstants;
 import 
org.apache.fineract.portfolio.loanproduct.domain.InterestCalculationPeriodMethod;
 import org.apache.fineract.portfolio.loanproduct.domain.InterestMethod;
@@ -60,34 +60,38 @@ public final class LoanApplicationCommandFromApiJsonHelper {
     /**
      * The parameters supported for this command.
      */
-    final Set<String> supportedParameters = new 
HashSet<>(Arrays.asList("dateFormat", "locale", "id", "clientId", "groupId", 
"loanType",
-            "productId", "principal", "loanTermFrequency", 
"loanTermFrequencyType", "numberOfRepayments", "repaymentEvery",
-            "repaymentFrequencyType", "repaymentFrequencyNthDayType", 
"repaymentFrequencyDayOfWeekType", "interestRatePerPeriod",
-            "amortizationType", "interestType", 
LoanApiConstants.isFloatingInterestRate, 
LoanApiConstants.interestRateDifferential,
-            "interestCalculationPeriodType", 
LoanProductConstants.allowPartialPeriodInterestCalcualtionParamName,
-            "interestRateFrequencyType", "expectedDisbursementDate", 
"repaymentsStartingFromDate",
-            "graceOnPrincipalPayment",
-            "recurringMoratoriumOnPrincipalPeriods",
-            "graceOnInterestPayment",
-            "graceOnInterestCharged",
-            "interestChargedFromDate",
-            "submittedOnDate",
-            "submittedOnNote",
-            "accountNo",
-            "externalId",
-            "fundId",
-            "loanOfficerId", // optional
-            "loanPurposeId",
-            "inArrearsTolerance",
-            "charges",
-            "collateral", // optional
-            "transactionProcessingStrategyId", // settings
-            "calendarId", // optional
-            "syncDisbursementWithMeeting",// optional
-            "linkAccountId", LoanApiConstants.disbursementDataParameterName, 
LoanApiConstants.emiAmountParameterName,
-            LoanApiConstants.maxOutstandingBalanceParameterName, 
LoanProductConstants.graceOnArrearsAgeingParameterName,
-            LoanProductConstants.recalculationRestFrequencyDateParamName,
-            
LoanProductConstants.recalculationCompoundingFrequencyDateParamName, 
"createStandingInstructionAtDisbursement"));
+    final Set<String> supportedParameters = new 
HashSet<>(Arrays.asList(LoanApiConstants.dateFormatParameterName,
+            LoanApiConstants.localeParameterName, 
LoanApiConstants.idParameterName, LoanApiConstants.clientIdParameterName,
+            LoanApiConstants.groupIdParameterName, 
LoanApiConstants.loanTypeParameterName, LoanApiConstants.productIdParameterName,
+            LoanApiConstants.principalParamName, 
LoanApiConstants.loanTermFrequencyParameterName,
+            LoanApiConstants.loanTermFrequencyTypeParameterName, 
LoanApiConstants.numberOfRepaymentsParameterName,
+            LoanApiConstants.repaymentEveryParameterName, 
LoanApiConstants.repaymentFrequencyTypeParameterName,
+            LoanApiConstants.repaymentFrequencyNthDayTypeParameterName, 
LoanApiConstants.repaymentFrequencyDayOfWeekTypeParameterName,
+            LoanApiConstants.interestRatePerPeriodParameterName, 
LoanApiConstants.amortizationTypeParameterName,
+            LoanApiConstants.interestTypeParameterName, 
LoanApiConstants.isFloatingInterestRate, 
LoanApiConstants.interestRateDifferential,
+            LoanApiConstants.interestCalculationPeriodTypeParameterName,
+            
LoanProductConstants.allowPartialPeriodInterestCalcualtionParamName, 
LoanApiConstants.interestRateFrequencyTypeParameterName,
+            LoanApiConstants.disbursementDateParameterName, 
LoanApiConstants.repaymentsStartingFromDateParameterName,
+            LoanApiConstants.graceOnPrincipalPaymentParameterName,
+            LoanApiConstants.graceOnInterestPaymentParameterName,
+            LoanApiConstants.graceOnInterestChargedParameterName,
+            LoanApiConstants.interestChargedFromDateParameterName,
+            LoanApiConstants.submittedOnDateParameterName,
+            LoanApiConstants.submittedOnNoteParameterName,
+            LoanApiConstants.accountNoParameterName,
+            LoanApiConstants.externalIdParameterName,
+            LoanApiConstants.fundIdParameterName,
+            LoanApiConstants.loanOfficerIdParameterName, // optional
+            LoanApiConstants.loanPurposeIdParameterName,
+            LoanApiConstants.inArrearsToleranceParameterName,
+            LoanApiConstants.chargesParameterName,
+            LoanApiConstants.collateralParameterName, // optional
+            LoanApiConstants.transactionProcessingStrategyIdParameterName, // 
settings
+            LoanApiConstants.calendarIdParameterName, // optional
+            LoanApiConstants.syncDisbursementWithMeetingParameterName,// 
optional
+            LoanApiConstants.linkAccountIdParameterName, 
LoanApiConstants.disbursementDataParameterName,
+            LoanApiConstants.emiAmountParameterName, 
LoanApiConstants.maxOutstandingBalanceParameterName,
+            LoanProductConstants.graceOnArrearsAgeingParameterName, 
LoanApiConstants.createStandingInstructionAtDisbursementParameterName));
 
     private final FromJsonHelper fromApiJsonHelper;
     private final CalculateLoanScheduleQueryFromApiJsonHelper apiJsonHelper;
@@ -214,6 +218,10 @@ public final class LoanApplicationCommandFromApiJsonHelper 
{
         
baseDataValidator.reset().parameter(repaymentEveryFrequencyTypeParameterName).value(repaymentEveryType).notNull()
                 .inMinMaxRange(0, 3);
 
+        final String repaymentFrequencyNthDayTypeParameterName = 
"repaymentFrequencyNthDayType";
+        final String repaymentFrequencyDayOfWeekTypeParameterName = 
"repaymentFrequencyDayOfWeekType";
+        CalendarUtils.validateNthDayOfMonthFrequency(baseDataValidator, 
repaymentFrequencyNthDayTypeParameterName,
+                repaymentFrequencyDayOfWeekTypeParameterName, element, 
this.fromApiJsonHelper);
         final String interestTypeParameterName = "interestType";
         final Integer interestType = 
this.fromApiJsonHelper.extractIntegerSansLocaleNamed(interestTypeParameterName, 
element);
         
baseDataValidator.reset().parameter(interestTypeParameterName).value(interestType).notNull().inMinMaxRange(0,
 1);
@@ -591,6 +599,10 @@ public final class LoanApplicationCommandFromApiJsonHelper 
{
                     element);
             
baseDataValidator.reset().parameter(repaymentEveryTypeParameterName).value(repaymentEveryType).notNull().inMinMaxRange(0,
 3);
         }
+        final String repaymentFrequencyNthDayTypeParameterName = 
"repaymentFrequencyNthDayType";
+        final String repaymentFrequencyDayOfWeekTypeParameterName = 
"repaymentFrequencyDayOfWeekType";
+        CalendarUtils.validateNthDayOfMonthFrequency(baseDataValidator, 
repaymentFrequencyNthDayTypeParameterName,
+                repaymentFrequencyDayOfWeekTypeParameterName, element, 
this.fromApiJsonHelper);
 
         final String interestTypeParameterName = "interestType";
         Integer interestType = null;
@@ -1095,14 +1107,6 @@ public final class 
LoanApplicationCommandFromApiJsonHelper {
 
     }
 
-    public void validateRecalcuationFrequency(final LocalDate 
recalculationFrequencyDate, final LocalDate expectedDisbursementDate,
-            final List<ApiParameterError> dataValidationErrors, final String 
paramName) {
-
-        final DataValidatorBuilder baseDataValidator = new 
DataValidatorBuilder(dataValidationErrors).resource("loan");
-        
baseDataValidator.reset().parameter(paramName).value(recalculationFrequencyDate).notNull()
-                .validateDateBeforeOrEqual(expectedDisbursementDate);
-    }
-
     public void validateLoanCharges(final Set<LoanCharge> charges, final 
List<ApiParameterError> dataValidationErrors) {
         if (charges == null) { return; }
         final DataValidatorBuilder baseDataValidator = new 
DataValidatorBuilder(dataValidationErrors).resource("loan");
@@ -1139,32 +1143,11 @@ public final class 
LoanApplicationCommandFromApiJsonHelper {
 
     public void validateLoanForInterestRecalculation(final Loan loan) {
         final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
-        LoanInterestRecalculationDetails interestRecalculationDetails = 
loan.loanInterestRecalculationDetails();
-        if 
(!interestRecalculationDetails.getRestFrequencyType().isSameAsRepayment()) {
-            String paramName = 
LoanProductConstants.recalculationRestFrequencyDateParamName;
-            
validateRecalcuationFrequency(interestRecalculationDetails.getRestFrequencyLocalDate(),
 loan.getExpectedDisbursedOnLocalDate(),
-                    dataValidationErrors, paramName);
-        }
-
-        if 
(interestRecalculationDetails.getInterestRecalculationCompoundingMethod().isCompoundingEnabled()
-                && 
!interestRecalculationDetails.getCompoundingFrequencyType().isSameAsRepayment())
 {
-            String paramName = 
LoanProductConstants.recalculationCompoundingFrequencyDateParamName;
-            
validateCompoundingFrequency(interestRecalculationDetails.getCompoundingFrequencyLocalDate(),
-                    loan.getExpectedDisbursedOnLocalDate(), 
dataValidationErrors, paramName);
-        }
 
         validateLoanCharges(loan.charges(), dataValidationErrors);
         if (!dataValidationErrors.isEmpty()) { throw new 
PlatformApiDataValidationException(dataValidationErrors); }
     }
 
-    public void validateCompoundingFrequency(final LocalDate 
recalculationFrequencyDate, final LocalDate expectedDisbursementDate,
-            final List<ApiParameterError> dataValidationErrors, final String 
paramName) {
-
-        final DataValidatorBuilder baseDataValidator = new 
DataValidatorBuilder(dataValidationErrors).resource("loan");
-        
baseDataValidator.reset().parameter(paramName).value(recalculationFrequencyDate).notNull()
-                .validateDateForEqual(expectedDisbursementDate);
-    }
-
     private void validatePartialPeriodSupport(final Integer 
interestCalculationPeriodType, final DataValidatorBuilder baseDataValidator,
             final JsonElement element, final LoanProduct loanProduct) {
         if (interestCalculationPeriodType != null) {

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualPlatformService.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualPlatformService.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualPlatformService.java
index 8f48eeb..277fdd8 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualPlatformService.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualPlatformService.java
@@ -33,5 +33,6 @@ public interface LoanAccrualPlatformService {
     void addAccrualAccounting() throws JobExecutionException;
 
     void addPeriodicAccruals() throws JobExecutionException;
+    void addPeriodicAccrualsForLoansWithIncomePostedAsTransactions() throws 
JobExecutionException;
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualPlatformServiceImpl.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualPlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualPlatformServiceImpl.java
index a790f4e..7365d15 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualPlatformServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualPlatformServiceImpl.java
@@ -117,4 +117,24 @@ public class LoanAccrualPlatformServiceImpl implements 
LoanAccrualPlatformServic
         return sb.toString();
     }
 
+    @Override
+    @CronTarget(jobName = 
JobName.ADD_PERIODIC_ACCRUAL_ENTRIES_FOR_LOANS_WITH_INCOME_POSTED_AS_TRANSACTIONS)
+    public void addPeriodicAccrualsForLoansWithIncomePostedAsTransactions() 
throws JobExecutionException {
+        Collection<Long> loanIds = 
this.loanReadPlatformService.retrieveLoanIdsWithPendingIncomePostingTransactions();
+        if(loanIds != null && loanIds.size() > 0){
+            StringBuilder sb = new StringBuilder();
+            for (Long loanId : loanIds) {
+                try {
+                    
this.loanAccrualWritePlatformService.addIncomeAndAccrualTransactions(loanId);
+                } catch (Exception e) {
+                    Throwable realCause = e;
+                    if (e.getCause() != null) {
+                        realCause = e.getCause();
+                    }
+                    sb.append("failed to add income and accrual transaction 
for loan " + loanId + " with message " + realCause.getMessage());
+                }
+            }
+            if (sb.length() > 0) { throw new 
JobExecutionException(sb.toString()); }
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualWritePlatformService.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualWritePlatformService.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualWritePlatformService.java
index 1e63a7c..1044279 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualWritePlatformService.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualWritePlatformService.java
@@ -29,4 +29,5 @@ public interface LoanAccrualWritePlatformService {
 
     void addPeriodicAccruals(LocalDate tilldate, Long loanId, 
Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas) throws Exception;
 
+    void addIncomeAndAccrualTransactions(Long loanId) throws Exception;
 }

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualWritePlatformServiceImpl.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualWritePlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualWritePlatformServiceImpl.java
index 79c54ff..5ac0b64 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualWritePlatformServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualWritePlatformServiceImpl.java
@@ -32,15 +32,22 @@ import javax.sql.DataSource;
 import 
org.apache.fineract.accounting.journalentry.service.JournalEntryWritePlatformService;
 import org.apache.fineract.infrastructure.core.service.DateUtils;
 import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
+import org.apache.fineract.organisation.monetary.domain.ApplicationCurrency;
+import 
org.apache.fineract.organisation.monetary.domain.ApplicationCurrencyRepositoryWrapper;
+import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
 import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
 import org.apache.fineract.portfolio.loanaccount.data.LoanChargeData;
 import 
org.apache.fineract.portfolio.loanaccount.data.LoanInstallmentChargeData;
 import org.apache.fineract.portfolio.loanaccount.data.LoanScheduleAccrualData;
 import org.apache.fineract.portfolio.loanaccount.data.LoanTransactionData;
 import org.apache.fineract.portfolio.loanaccount.data.LoanTransactionEnumData;
+import org.apache.fineract.portfolio.loanaccount.domain.Loan;
+import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType;
+import 
org.apache.fineract.portfolio.loanaccount.exception.LoanNotFoundException;
 import 
org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanSchedulePeriodData;
 import org.apache.fineract.portfolio.loanproduct.service.LoanEnumerations;
+import org.apache.fineract.useradministration.domain.AppUserRepositoryWrapper;
 import org.joda.time.Days;
 import org.joda.time.LocalDate;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -56,16 +63,23 @@ public class LoanAccrualWritePlatformServiceImpl implements 
LoanAccrualWritePlat
     private final JdbcTemplate jdbcTemplate;
     private final DataSource dataSource;
     private final JournalEntryWritePlatformService 
journalEntryWritePlatformService;
+    private final AppUserRepositoryWrapper userRepository;
+    private final LoanRepository loanRepository;
+    private final ApplicationCurrencyRepositoryWrapper 
applicationCurrencyRepository;
 
     @Autowired
     public LoanAccrualWritePlatformServiceImpl(final RoutingDataSource 
dataSource, final LoanReadPlatformService loanReadPlatformService,
             final JournalEntryWritePlatformService 
journalEntryWritePlatformService,
-            final LoanChargeReadPlatformService loanChargeReadPlatformService) 
{
+            final LoanChargeReadPlatformService loanChargeReadPlatformService, 
final AppUserRepositoryWrapper userRepository,
+            final LoanRepository loanRepository, final 
ApplicationCurrencyRepositoryWrapper applicationCurrencyRepository) {
         this.loanReadPlatformService = loanReadPlatformService;
         this.dataSource = dataSource;
         this.jdbcTemplate = new JdbcTemplate(this.dataSource);
         this.journalEntryWritePlatformService = 
journalEntryWritePlatformService;
         this.loanChargeReadPlatformService = loanChargeReadPlatformService;
+        this.userRepository = userRepository;
+        this.loanRepository = loanRepository;
+        this.applicationCurrencyRepository = applicationCurrencyRepository;
     }
 
     @Override
@@ -469,4 +483,29 @@ public class LoanAccrualWritePlatformServiceImpl 
implements LoanAccrualWritePlat
         accrualData.updateAccruableIncome(interestIncome);
     }
 
+    @Override
+    @Transactional
+    public void addIncomeAndAccrualTransactions(Long loanId) throws Exception {
+        if (loanId != null) {
+            Loan loan = this.loanRepository.findOne(loanId);
+            if (loan == null) { throw new LoanNotFoundException(loanId); }
+            final List<Long> existingTransactionIds = new ArrayList<>();
+            final List<Long> existingReversedTransactionIds = new 
ArrayList<>();
+            existingTransactionIds.addAll(loan.findExistingTransactionIds());
+            
existingReversedTransactionIds.addAll(loan.findExistingReversedTransactionIds());
+            
loan.processIncomeTransactions(this.userRepository.fetchSystemUser());
+            this.loanRepository.saveAndFlush(loan);
+            postJournalEntries(loan, existingTransactionIds, 
existingReversedTransactionIds);
+        }
+    }
+
+    private void postJournalEntries(final Loan loan, final List<Long> 
existingTransactionIds,
+            final List<Long> existingReversedTransactionIds) {
+        final MonetaryCurrency currency = loan.getCurrency();
+        final ApplicationCurrency applicationCurrency = 
this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency);
+        boolean isAccountTransfer = false;
+        final Map<String, Object> accountingBridgeData = 
loan.deriveAccountingBridgeData(applicationCurrency.toData(),
+                existingTransactionIds, existingReversedTransactionIds, 
isAccountTransfer);
+        
this.journalEntryWritePlatformService.createJournalEntriesForLoan(accountingBridgeData);
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java
index 8d5ce19..0bcdd09 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java
@@ -55,6 +55,7 @@ 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.CalendarNotFoundException;
+import 
org.apache.fineract.portfolio.calendar.service.CalendarReadPlatformService;
 import org.apache.fineract.portfolio.charge.domain.Charge;
 import org.apache.fineract.portfolio.client.domain.AccountNumberGenerator;
 import org.apache.fineract.portfolio.client.domain.Client;
@@ -64,6 +65,7 @@ import 
org.apache.fineract.portfolio.collateral.domain.LoanCollateral;
 import org.apache.fineract.portfolio.collateral.service.CollateralAssembler;
 import 
org.apache.fineract.portfolio.common.BusinessEventNotificationConstants.BUSINESS_ENTITY;
 import 
org.apache.fineract.portfolio.common.BusinessEventNotificationConstants.BUSINESS_EVENTS;
+import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
 import 
org.apache.fineract.portfolio.common.service.BusinessEventNotifierService;
 import org.apache.fineract.portfolio.fund.domain.Fund;
 import org.apache.fineract.portfolio.group.domain.Group;
@@ -88,6 +90,7 @@ import 
org.apache.fineract.portfolio.loanaccount.exception.LoanApplicationNotInS
 import 
org.apache.fineract.portfolio.loanaccount.exception.LoanApplicationNotInSubmittedAndPendingApprovalStateCannotBeModified;
 import 
org.apache.fineract.portfolio.loanaccount.exception.LoanNotFoundException;
 import 
org.apache.fineract.portfolio.loanaccount.loanschedule.domain.AprCalculator;
+import 
org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanApplicationTerms;
 import 
org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleModel;
 import 
org.apache.fineract.portfolio.loanaccount.loanschedule.service.LoanScheduleAssembler;
 import 
org.apache.fineract.portfolio.loanaccount.loanschedule.service.LoanScheduleCalculationPlatformService;
@@ -108,7 +111,6 @@ import 
org.apache.fineract.portfolio.savings.domain.SavingsAccount;
 import org.apache.fineract.portfolio.savings.domain.SavingsAccountAssembler;
 import org.apache.fineract.useradministration.domain.AppUser;
 import org.joda.time.LocalDate;
-import org.joda.time.LocalTime;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -153,6 +155,7 @@ public class 
LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
     private final ConfigurationDomainService configurationDomainService;
     private final LoanScheduleAssembler loanScheduleAssembler;
     private final LoanUtilService loanUtilService;
+    private final CalendarReadPlatformService calendarReadPlatformService;
 
     @Autowired
     public LoanApplicationWritePlatformServiceJpaRepositoryImpl(final 
PlatformSecurityContext context, final FromJsonHelper fromJsonHelper,
@@ -171,7 +174,8 @@ public class 
LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
             final LoanReadPlatformService loanReadPlatformService,
             final AccountNumberFormatRepositoryWrapper 
accountNumberFormatRepository,
             final BusinessEventNotifierService businessEventNotifierService, 
final ConfigurationDomainService configurationDomainService,
-            final LoanScheduleAssembler loanScheduleAssembler, final 
LoanUtilService loanUtilService) {
+            final LoanScheduleAssembler loanScheduleAssembler, final 
LoanUtilService loanUtilService, 
+            final CalendarReadPlatformService calendarReadPlatformService) {
         this.context = context;
         this.fromJsonHelper = fromJsonHelper;
         this.loanApplicationTransitionApiJsonValidator = 
loanApplicationTransitionApiJsonValidator;
@@ -201,6 +205,7 @@ public class 
LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
         this.configurationDomainService = configurationDomainService;
         this.loanScheduleAssembler = loanScheduleAssembler;
         this.loanUtilService = loanUtilService;
+        this.calendarReadPlatformService = calendarReadPlatformService;
     }
 
     private LoanLifecycleStateMachine defaultLoanLifecycleStateMachine() {
@@ -288,6 +293,26 @@ public class 
LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
                 final CalendarInstance calendarInstance = new 
CalendarInstance(calendar, newLoanApplication.getId(),
                         CalendarEntityType.LOANS.getValue());
                 this.calendarInstanceRepository.save(calendarInstance);
+            } else {
+                final LoanApplicationTerms loanApplicationTerms = 
this.loanScheduleAssembler.assembleLoanTerms(command.parsedJson());
+                final Integer repaymentFrequencyNthDayType = 
command.integerValueOfParameterNamed("repaymentFrequencyNthDayType");
+                if (loanApplicationTerms.getRepaymentPeriodFrequencyType() == 
PeriodFrequencyType.MONTHS
+                        && repaymentFrequencyNthDayType != null) {
+                    final String title = "loan_schedule_" + 
newLoanApplication.getId();
+                    LocalDate calendarStartDate = 
loanApplicationTerms.getRepaymentsStartingFromLocalDate();
+                    if (calendarStartDate == null) calendarStartDate = 
loanApplicationTerms.getExpectedDisbursementDate();
+                    final CalendarFrequencyType calendarFrequencyType = 
CalendarFrequencyType.MONTHLY;
+                    final Integer frequency = 
loanApplicationTerms.getRepaymentEvery();
+                    final Integer repeatsOnDay = 
loanApplicationTerms.getWeekDayType().getValue();
+                    final Integer repeatsOnNthDayOfMonth = 
loanApplicationTerms.getNthDay();
+                    final Integer calendarEntityType = 
CalendarEntityType.LOANS.getValue();
+                    final Calendar loanCalendar = 
Calendar.createRepeatingCalendar(title, calendarStartDate,
+                            CalendarType.COLLECTION.getValue(), 
calendarFrequencyType, frequency, repeatsOnDay, repeatsOnNthDayOfMonth);
+                    this.calendarRepository.save(loanCalendar);
+                    final CalendarInstance calendarInstance = 
CalendarInstance.from(loanCalendar, newLoanApplication.getId(),
+                            calendarEntityType);
+                    this.calendarInstanceRepository.save(calendarInstance);
+                }
             }
 
             // Save linked account information
@@ -357,43 +382,49 @@ public class 
LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
 
     private void 
createAndPersistCalendarInstanceForInterestRecalculation(final Loan loan) {
 
-        LocalDate calendarStartDate = 
loan.loanInterestRecalculationDetails().getRestFrequencyLocalDate();
-        if (calendarStartDate == null) {
-            calendarStartDate = loan.getExpectedDisbursedOnLocalDate();
-        }
-        final Integer repeatsOnDay = calendarStartDate.getDayOfWeek();
+        LocalDate calendarStartDate = loan.getExpectedDisbursedOnLocalDate();
+        Integer repeatsOnDay = null;
         final RecalculationFrequencyType recalculationFrequencyType = 
loan.loanInterestRecalculationDetails().getRestFrequencyType();
+        Integer recalculationFrequencyNthDay = 
loan.loanInterestRecalculationDetails().getRestFrequencyOnDay();
+        if (recalculationFrequencyNthDay == null) {
+            recalculationFrequencyNthDay = 
loan.loanInterestRecalculationDetails().getRestFrequencyNthDay();
+            repeatsOnDay = 
loan.loanInterestRecalculationDetails().getRestFrequencyWeekday();
+        }
 
         Integer frequency = 
loan.loanInterestRecalculationDetails().getRestInterval();
         CalendarEntityType calendarEntityType = 
CalendarEntityType.LOAN_RECALCULATION_REST_DETAIL;
         final String title = "loan_recalculation_detail_" + 
loan.loanInterestRecalculationDetails().getId();
 
-        createCalendar(loan, calendarStartDate, repeatsOnDay, 
recalculationFrequencyType, frequency, calendarEntityType, title);
+        createCalendar(loan, calendarStartDate, recalculationFrequencyNthDay, 
repeatsOnDay, recalculationFrequencyType, frequency,
+                calendarEntityType, title);
 
         if 
(loan.loanInterestRecalculationDetails().getInterestRecalculationCompoundingMethod().isCompoundingEnabled())
 {
-            LocalDate compoundingStartDate = 
loan.loanInterestRecalculationDetails().getCompoundingFrequencyLocalDate();
-            if (compoundingStartDate == null) {
-                compoundingStartDate = loan.getExpectedDisbursedOnLocalDate();
-            }
-            final Integer compoundingRepeatsOnDay = 
compoundingStartDate.getDayOfWeek();
+            LocalDate compoundingStartDate = 
loan.getExpectedDisbursedOnLocalDate();
+            Integer compoundingRepeatsOnDay = null;
             final RecalculationFrequencyType 
recalculationCompoundingFrequencyType = loan.loanInterestRecalculationDetails()
                     .getCompoundingFrequencyType();
+            Integer recalculationCompoundingFrequencyNthDay = 
loan.loanInterestRecalculationDetails().getCompoundingFrequencyOnDay();
+            if (recalculationCompoundingFrequencyNthDay == null) {
+                recalculationCompoundingFrequencyNthDay = 
loan.loanInterestRecalculationDetails().getCompoundingFrequencyNthDay();
+                compoundingRepeatsOnDay = 
loan.loanInterestRecalculationDetails().getCompoundingFrequencyWeekday();
+            }
 
             Integer compoundingFrequency = 
loan.loanInterestRecalculationDetails().getCompoundingInterval();
             CalendarEntityType compoundingCalendarEntityType = 
CalendarEntityType.LOAN_RECALCULATION_COMPOUNDING_DETAIL;
             final String compoundingCalendarTitle = 
"loan_recalculation_detail_compounding_frequency"
                     + loan.loanInterestRecalculationDetails().getId();
 
-            createCalendar(loan, compoundingStartDate, 
compoundingRepeatsOnDay, recalculationCompoundingFrequencyType,
-                    compoundingFrequency, compoundingCalendarEntityType, 
compoundingCalendarTitle);
+            createCalendar(loan, compoundingStartDate, 
recalculationCompoundingFrequencyNthDay, compoundingRepeatsOnDay,
+                    recalculationCompoundingFrequencyType, 
compoundingFrequency, compoundingCalendarEntityType, compoundingCalendarTitle);
         }
 
     }
 
-    private void createCalendar(final Loan loan, LocalDate calendarStartDate, 
final Integer repeatsOnDay,
-            final RecalculationFrequencyType recalculationFrequencyType, 
Integer frequency, CalendarEntityType calendarEntityType,
-            final String title) {
+    private void createCalendar(final Loan loan, LocalDate calendarStartDate, 
Integer recalculationFrequencyNthDay,
+            final Integer repeatsOnDay, final RecalculationFrequencyType 
recalculationFrequencyType, Integer frequency,
+            CalendarEntityType calendarEntityType, final String title) {
         CalendarFrequencyType calendarFrequencyType = 
CalendarFrequencyType.INVALID;
+        Integer updatedRepeatsOnDay = repeatsOnDay;
         switch (recalculationFrequencyType) {
             case DAILY:
                 calendarFrequencyType = CalendarFrequencyType.DAILY;
@@ -405,6 +436,9 @@ public class 
LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
                 frequency = loan.repaymentScheduleDetail().getRepayEvery();
                 calendarFrequencyType = 
CalendarFrequencyType.from(loan.repaymentScheduleDetail().getRepaymentPeriodFrequencyType());
                 calendarStartDate = loan.getExpectedDisbursedOnLocalDate();
+                if (updatedRepeatsOnDay == null) {
+                    updatedRepeatsOnDay = calendarStartDate.getDayOfWeek();
+                }
             break;
             case WEEKLY:
                 calendarFrequencyType = CalendarFrequencyType.WEEKLY;
@@ -414,71 +448,12 @@ public class 
LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
         }
          
         final Calendar calendar = Calendar.createRepeatingCalendar(title, 
calendarStartDate, CalendarType.COLLECTION.getValue(),
-                calendarFrequencyType, frequency, repeatsOnDay);
+                calendarFrequencyType, frequency, updatedRepeatsOnDay, 
recalculationFrequencyNthDay);
         final CalendarInstance calendarInstance = 
CalendarInstance.from(calendar, loan.loanInterestRecalculationDetails().getId(),
                 calendarEntityType.getValue());
         this.calendarInstanceRepository.save(calendarInstance);
     }
 
-    private void updateRestCalendarDetailsForInterestRecalculation(final 
CalendarInstance calendarInstance, final Loan loan) {
-
-        Calendar interestRecalculationRecurrings = 
calendarInstance.getCalendar();
-        LocalDate calendarStartDate = 
loan.loanInterestRecalculationDetails().getRestFrequencyLocalDate();
-        if (calendarStartDate == null) {
-            calendarStartDate = loan.getExpectedDisbursedOnLocalDate();
-        }
-        final Integer repeatsOnDay = calendarStartDate.getDayOfWeek();
-        final RecalculationFrequencyType recalculationFrequencyType = 
loan.loanInterestRecalculationDetails().getRestFrequencyType();
-
-        Integer frequency = 
loan.loanInterestRecalculationDetails().getRestInterval();
-
-        updateCalendar(loan, interestRecalculationRecurrings, 
calendarStartDate, repeatsOnDay, recalculationFrequencyType, frequency);
-
-    }
-
-    private void 
updateCompoundingCalendarDetailsForInterestRecalculation(final CalendarInstance 
calendarInstance, final Loan loan) {
-
-        Calendar interestRecalculationRecurrings = 
calendarInstance.getCalendar();
-        LocalDate calendarStartDate = 
loan.loanInterestRecalculationDetails().getCompoundingFrequencyLocalDate();
-        if (calendarStartDate == null) {
-            calendarStartDate = loan.getExpectedDisbursedOnLocalDate();
-        }
-        final Integer repeatsOnDay = calendarStartDate.getDayOfWeek();
-        final RecalculationFrequencyType recalculationFrequencyType = 
loan.loanInterestRecalculationDetails().getCompoundingFrequencyType();
-
-        Integer frequency = 
loan.loanInterestRecalculationDetails().getCompoundingInterval();
-
-        updateCalendar(loan, interestRecalculationRecurrings, 
calendarStartDate, repeatsOnDay, recalculationFrequencyType, frequency);
-
-    }
-
-    private void updateCalendar(final Loan loan, Calendar 
interestRecalculationRecurrings, LocalDate calendarStartDate,
-            final Integer repeatsOnDay, final RecalculationFrequencyType 
recalculationFrequencyType, Integer frequency) {
-        CalendarFrequencyType calendarFrequencyType = 
CalendarFrequencyType.INVALID;
-        switch (recalculationFrequencyType) {
-            case DAILY:
-                calendarFrequencyType = CalendarFrequencyType.DAILY;
-            break;
-
-            case MONTHLY:
-                calendarFrequencyType = CalendarFrequencyType.MONTHLY;
-            break;
-            case SAME_AS_REPAYMENT_PERIOD:
-                calendarStartDate = loan.getExpectedDisbursedOnLocalDate();
-                frequency = loan.repaymentScheduleDetail().getRepayEvery();
-                calendarFrequencyType = 
CalendarFrequencyType.from(loan.repaymentScheduleDetail().getRepaymentPeriodFrequencyType());
-            break;
-            case WEEKLY:
-                calendarFrequencyType = CalendarFrequencyType.WEEKLY;
-            break;
-            default:
-            break;
-        }
-
-        
interestRecalculationRecurrings.updateRepeatingCalendar(calendarStartDate, 
calendarFrequencyType, frequency, repeatsOnDay);
-        this.calendarRepository.save(interestRecalculationRecurrings);
-    }
-
     @Transactional
     @Override
     public CommandProcessingResult modifyApplication(final Long loanId, final 
JsonCommand command) {
@@ -551,7 +526,7 @@ public class 
LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
                     }
                 }
             }
-            
+
             final Set<LoanCollateral> possiblyModifedLoanCollateralItems = 
this.loanCollateralAssembler
                     .fromParsedJson(command.parsedJson());
 
@@ -700,6 +675,11 @@ public class 
LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
                 // loan
                 if (ciList != null && !ciList.isEmpty()) {
                     final CalendarInstance calendarInstance = ciList.get(0);
+                    final boolean isCalendarAssociatedWithEntity = 
this.calendarReadPlatformService.isCalendarAssociatedWithEntity(calendarInstance
+                            .getEntityId(), 
calendarInstance.getCalendar().getId(), 
CalendarEntityType.LOANS.getValue().longValue());
+                    if (isCalendarAssociatedWithEntity) {
+                        
this.calendarRepository.delete(calendarInstance.getCalendar());
+                    }
                     if (calendarInstance.getCalendar().getId() != 
calendar.getId()) {
                         calendarInstance.updateCalendar(calendar);
                         
this.calendarInstanceRepository.saveAndFlush(calendarInstance);
@@ -711,9 +691,65 @@ public class 
LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
                     this.calendarInstanceRepository.save(calendarInstance);
                 }
 
-            } else if (ciList != null && !ciList.isEmpty()) {
-                final CalendarInstance calendarInstance = ciList.get(0);
-                this.calendarInstanceRepository.delete(calendarInstance);
+            } else {
+                if (ciList != null && !ciList.isEmpty()) {
+                    final CalendarInstance existingCalendarInstance = 
ciList.get(0);
+                    final boolean isCalendarAssociatedWithEntity = 
this.calendarReadPlatformService.isCalendarAssociatedWithEntity(
+                            existingCalendarInstance.getEntityId(), 
existingCalendarInstance.getCalendar().getId(),
+                            CalendarEntityType.GROUPS.getValue().longValue());
+                    if (isCalendarAssociatedWithEntity) {
+                        
this.calendarInstanceRepository.delete(existingCalendarInstance);
+                    }
+                }
+                if (changes.containsKey("repaymentFrequencyNthDayType") || 
changes.containsKey("repaymentFrequencyDayOfWeekType")) {
+                    if (changes.get("repaymentFrequencyNthDayType") == null) {
+                        if (ciList != null && !ciList.isEmpty()) {
+                            final CalendarInstance calendarInstance = 
ciList.get(0);
+                            final boolean isCalendarAssociatedWithEntity = 
this.calendarReadPlatformService.isCalendarAssociatedWithEntity(
+                                    calendarInstance.getEntityId(), 
calendarInstance.getCalendar().getId(), 
CalendarEntityType.LOANS.getValue().longValue());
+                            if (isCalendarAssociatedWithEntity) {
+                                
this.calendarInstanceRepository.delete(calendarInstance);
+                                
this.calendarRepository.delete(calendarInstance.getCalendar());
+                            }
+                        }
+                    } else {
+                        Integer repaymentFrequencyTypeInt = 
command.integerValueOfParameterNamed("repaymentFrequencyType");
+                        if (repaymentFrequencyTypeInt != null) {
+                            if 
(PeriodFrequencyType.fromInt(repaymentFrequencyTypeInt) == 
PeriodFrequencyType.MONTHS) {
+                                final String title = "loan_schedule_" + 
existingLoanApplication.getId();
+                                final Integer typeId = 
CalendarType.COLLECTION.getValue();
+                                final CalendarFrequencyType 
repaymentFrequencyType = CalendarFrequencyType.MONTHLY;
+                                final Integer interval = 
command.integerValueOfParameterNamed("repaymentEvery");
+                                LocalDate startDate = 
command.localDateValueOfParameterNamed("repaymentsStartingFromDate");
+                                if (startDate == null) startDate = 
command.localDateValueOfParameterNamed("expectedDisbursementDate");
+                                final Calendar newCalendar = 
Calendar.createRepeatingCalendar(title, startDate, typeId,
+                                        repaymentFrequencyType, interval, 
(Integer) changes.get("repaymentFrequencyDayOfWeekType"),
+                                        (Integer) 
changes.get("repaymentFrequencyNthDayType"));
+                                if (ciList != null && !ciList.isEmpty()) {
+                                    final CalendarInstance calendarInstance = 
ciList.get(0);
+                                    final boolean 
isCalendarAssociatedWithEntity = 
this.calendarReadPlatformService.isCalendarAssociatedWithEntity(
+                                            calendarInstance.getEntityId(), 
calendarInstance.getCalendar().getId(), 
CalendarEntityType.LOANS.getValue().longValue());
+                                    if (isCalendarAssociatedWithEntity) {
+                                        final Calendar existingCalendar = 
calendarInstance.getCalendar();
+                                        if (existingCalendar != null) {
+                                            String existingRecurrence = 
existingCalendar.getRecurrence();
+                                            if 
(!existingRecurrence.equals(newCalendar.getRecurrence())) {
+                                                
existingCalendar.setRecurrence(newCalendar.getRecurrence());
+                                                
this.calendarRepository.save(existingCalendar);
+                                            }
+                                        }
+                                    }
+                                } else {
+                                    this.calendarRepository.save(newCalendar);
+                                    final Integer calendarEntityType = 
CalendarEntityType.LOANS.getValue();
+                                    final CalendarInstance calendarInstance = 
new CalendarInstance(newCalendar,
+                                            existingLoanApplication.getId(), 
calendarEntityType);
+                                    
this.calendarInstanceRepository.save(calendarInstance);
+                                }
+                            }
+                        }
+                    }
+                }
             }
 
             // Save linked account information
@@ -776,20 +812,7 @@ public class 
LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
                 
this.fromApiJsonDeserializer.validateLoanForInterestRecalculation(existingLoanApplication);
                 if 
(changes.containsKey(LoanProductConstants.isInterestRecalculationEnabledParameterName))
 {
                     
createAndPersistCalendarInstanceForInterestRecalculation(existingLoanApplication);
-                } else {
-                    if 
(changes.containsKey(LoanProductConstants.recalculationRestFrequencyDateParamName))
 {
 
-                        CalendarInstance calendarInstance = 
this.calendarInstanceRepository.findByEntityIdAndEntityTypeIdAndCalendarTypeId(
-                                
existingLoanApplication.loanInterestRecalculationDetailId(),
-                                
CalendarEntityType.LOAN_RECALCULATION_REST_DETAIL.getValue(), 
CalendarType.COLLECTION.getValue());
-                        
updateRestCalendarDetailsForInterestRecalculation(calendarInstance, 
existingLoanApplication);
-                    }
-                    if 
(changes.containsKey(LoanProductConstants.recalculationCompoundingFrequencyDateParamName))
 {
-                        CalendarInstance calendarInstance = 
this.calendarInstanceRepository.findByEntityIdAndEntityTypeIdAndCalendarTypeId(
-                                
existingLoanApplication.loanInterestRecalculationDetailId(),
-                                
CalendarEntityType.LOAN_RECALCULATION_COMPOUNDING_DETAIL.getValue(), 
CalendarType.COLLECTION.getValue());
-                        
updateCompoundingCalendarDetailsForInterestRecalculation(calendarInstance, 
existingLoanApplication);
-                    }
                 }
 
             }

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAssembler.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAssembler.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAssembler.java
index 755a751..93df756 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAssembler.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAssembler.java
@@ -70,7 +70,6 @@ import 
org.apache.fineract.portfolio.loanaccount.exception.MultiDisbursementData
 import 
org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanApplicationTerms;
 import 
org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleModel;
 import 
org.apache.fineract.portfolio.loanaccount.loanschedule.service.LoanScheduleAssembler;
-import org.apache.fineract.portfolio.loanproduct.LoanProductConstants;
 import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
 import 
org.apache.fineract.portfolio.loanproduct.domain.LoanProductRelatedDetail;
 import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRepository;
@@ -82,6 +81,7 @@ import org.apache.fineract.useradministration.domain.AppUser;
 import org.joda.time.LocalDate;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+
 import com.google.gson.JsonElement;
 
 @Service
@@ -282,10 +282,6 @@ public class LoanAssembler {
             }
         }
 
-        final LocalDate recalculationRestFrequencyDate = 
this.fromApiJsonHelper.extractLocalDateNamed(
-                LoanProductConstants.recalculationRestFrequencyDateParamName, 
element);
-        final LocalDate recalculationCompoundingFrequencyDate = 
this.fromApiJsonHelper.extractLocalDateNamed(
-                
LoanProductConstants.recalculationCompoundingFrequencyDateParamName, element);
 
         final LoanApplicationTerms loanApplicationTerms = 
this.loanScheduleAssembler.assembleLoanTerms(element);
         final boolean isHolidayEnabled = 
this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled();
@@ -297,8 +293,7 @@ public class LoanAssembler {
         final LoanScheduleModel loanScheduleModel = 
this.loanScheduleAssembler.assembleLoanScheduleFrom(loanApplicationTerms,
                 isHolidayEnabled, holidays, workingDays, 
element,disbursementDetails);
         loanApplication.loanApplicationSubmittal(currentUser, 
loanScheduleModel, loanApplicationTerms, defaultLoanLifecycleStateMachine(),
-                submittedOnDate, externalId, allowTransactionsOnHoliday, 
holidays, workingDays, allowTransactionsOnNonWorkingDay,
-                recalculationRestFrequencyDate, 
recalculationCompoundingFrequencyDate);
+                submittedOnDate, externalId, allowTransactionsOnHoliday, 
holidays, workingDays, allowTransactionsOnNonWorkingDay);
 
         return loanApplication;
     }

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformService.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformService.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformService.java
index e41860d..f6df4e4 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformService.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformService.java
@@ -126,4 +126,5 @@ public interface LoanReadPlatformService {
     LoanTransactionData retrieveRefundByCashTemplate(Long loanId);
     
     Collection<InterestRatePeriodData> retrieveLoanInterestRatePeriodData(Long 
loanId);
+    Collection<Long> retrieveLoanIdsWithPendingIncomePostingTransactions();
 }
\ No newline at end of file

Reply via email to