http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/LoanReschedulingWithinCenterTest.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/LoanReschedulingWithinCenterTest.java
 
b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/LoanReschedulingWithinCenterTest.java
index a825bcb..4126f75 100644
--- 
a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/LoanReschedulingWithinCenterTest.java
+++ 
b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/LoanReschedulingWithinCenterTest.java
@@ -111,7 +111,8 @@ public class LoanReschedulingWithinCenterTest {
                 LoanProductTestBuilder.RECALCULATION_COMPOUNDING_METHOD_NONE,
                 
LoanProductTestBuilder.RECALCULATION_STRATEGY_REDUCE_NUMBER_OF_INSTALLMENTS,
                 LoanProductTestBuilder.RECALCULATION_FREQUENCY_TYPE_DAILY, 
"0", recalculationRestFrequencyDate,
-                
LoanProductTestBuilder.INTEREST_APPLICABLE_STRATEGY_ON_PRE_CLOSE_DATE, null, 
isMultiTrancheLoan);
+                
LoanProductTestBuilder.INTEREST_APPLICABLE_STRATEGY_ON_PRE_CLOSE_DATE, null, 
isMultiTrancheLoan, 
+                null, null);
 
         // APPLY FOR TRANCHE LOAN WITH INTEREST RECALCULATION
         final Integer loanId = 
applyForLoanApplicationForInterestRecalculation(clientId, groupId, calendarId, 
loanProductID, disbursalDate,
@@ -222,7 +223,8 @@ public class LoanReschedulingWithinCenterTest {
                 LoanProductTestBuilder.RECALCULATION_COMPOUNDING_METHOD_NONE,
                 
LoanProductTestBuilder.RECALCULATION_STRATEGY_REDUCE_NUMBER_OF_INSTALLMENTS,
                 LoanProductTestBuilder.RECALCULATION_FREQUENCY_TYPE_DAILY, 
"0", recalculationRestFrequencyDate,
-                
LoanProductTestBuilder.INTEREST_APPLICABLE_STRATEGY_ON_PRE_CLOSE_DATE, null, 
isMultiTrancheLoan);
+                
LoanProductTestBuilder.INTEREST_APPLICABLE_STRATEGY_ON_PRE_CLOSE_DATE, null, 
isMultiTrancheLoan, 
+                null, null);
 
         // CREATE TRANCHES
         List<HashMap> createTranches = new ArrayList<>();
@@ -279,14 +281,18 @@ public class LoanReschedulingWithinCenterTest {
             final String interestRecalculationCompoundingMethod, final String 
rescheduleStrategyMethod,
             final String recalculationRestFrequencyType, final String 
recalculationRestFrequencyInterval,
             final String recalculationRestFrequencyDate, final String 
preCloseInterestCalculationStrategy, final Account[] accounts,
-            final boolean isMultiTrancheLoan) {
+            final boolean isMultiTrancheLoan, final Integer 
recalculationRestFrequencyOnDayType, final Integer 
recalculationRestFrequencyDayOfWeekType) {
         final String recalculationCompoundingFrequencyType = null;
         final String recalculationCompoundingFrequencyInterval = null;
         final String recalculationCompoundingFrequencyDate = null;
+        final Integer recalculationCompoundingFrequencyOnDayType = null;
+        final Integer recalculationCompoundingFrequencyDayOfWeekType = null;
         return createLoanProductWithInterestRecalculation(repaymentStrategy, 
interestRecalculationCompoundingMethod,
                 rescheduleStrategyMethod, recalculationRestFrequencyType, 
recalculationRestFrequencyInterval,
                 recalculationRestFrequencyDate, 
recalculationCompoundingFrequencyType, 
recalculationCompoundingFrequencyInterval,
-                recalculationCompoundingFrequencyDate, 
preCloseInterestCalculationStrategy, accounts, null, false, isMultiTrancheLoan);
+                recalculationCompoundingFrequencyDate, 
preCloseInterestCalculationStrategy, accounts, null, false, isMultiTrancheLoan, 
+                recalculationCompoundingFrequencyOnDayType, 
recalculationCompoundingFrequencyDayOfWeekType, 
recalculationRestFrequencyOnDayType, 
+                recalculationRestFrequencyDayOfWeekType);
     }
 
     private Integer createLoanProductWithInterestRecalculation(final String 
repaymentStrategy,
@@ -295,7 +301,10 @@ public class LoanReschedulingWithinCenterTest {
             final String recalculationRestFrequencyDate, final String 
recalculationCompoundingFrequencyType,
             final String recalculationCompoundingFrequencyInterval, final 
String recalculationCompoundingFrequencyDate,
             final String preCloseInterestCalculationStrategy, final Account[] 
accounts, final String chargeId,
-            boolean isArrearsBasedOnOriginalSchedule, final boolean 
isMultiTrancheLoan) {
+            boolean isArrearsBasedOnOriginalSchedule, final boolean 
isMultiTrancheLoan, 
+            final Integer recalculationCompoundingFrequencyOnDayType,
+            final Integer recalculationCompoundingFrequencyDayOfWeekType, 
final Integer recalculationRestFrequencyOnDayType,
+            final Integer recalculationRestFrequencyDayOfWeekType) {
         System.out.println("------------------------------CREATING NEW LOAN 
PRODUCT ---------------------------------------");
         LoanProductTestBuilder builder = new LoanProductTestBuilder()
                 .withPrincipal("10000.00")
@@ -311,9 +320,10 @@ public class LoanReschedulingWithinCenterTest {
                 
.withInterestRecalculationDetails(interestRecalculationCompoundingMethod, 
rescheduleStrategyMethod,
                         preCloseInterestCalculationStrategy)
                 
.withInterestRecalculationRestFrequencyDetails(recalculationRestFrequencyType, 
recalculationRestFrequencyInterval,
-                        recalculationRestFrequencyDate)
+                        recalculationRestFrequencyOnDayType, 
recalculationRestFrequencyDayOfWeekType)
                 
.withInterestRecalculationCompoundingFrequencyDetails(recalculationCompoundingFrequencyType,
-                        recalculationCompoundingFrequencyInterval, 
recalculationCompoundingFrequencyDate);
+                        recalculationCompoundingFrequencyInterval, 
recalculationCompoundingFrequencyOnDayType,
+                        recalculationCompoundingFrequencyDayOfWeekType);
         if (accounts != null) {
             builder = builder.withAccountingRulePeriodicAccrual(accounts);
         }
@@ -356,7 +366,6 @@ public class LoanReschedulingWithinCenterTest {
                 .withInterestCalculationPeriodTypeAsDays() //
                 .withExpectedDisbursementDate(disbursementDate) //
                 .withSubmittedOnDate(disbursementDate) //
-                .withRestFrequencyDate(restStartDate)//
                 .withwithRepaymentStrategy(repaymentStrategy) //
                 .withCharges(charges)//
                 .build(clientID.toString(), groupId.toString(), 
loanProductID.toString(), null);
@@ -389,4 +398,5 @@ public class LoanReschedulingWithinCenterTest {
         date.add(type, addvalue);
         return new ArrayList<>(Arrays.asList(date.get(Calendar.YEAR), 
date.get(Calendar.MONTH) + 1, date.get(Calendar.DAY_OF_MONTH)));
     }
+
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/loans/LoanApplicationTestBuilder.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/loans/LoanApplicationTestBuilder.java
 
b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/loans/LoanApplicationTestBuilder.java
index cfa9c39..50d9cc9 100644
--- 
a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/loans/LoanApplicationTestBuilder.java
+++ 
b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/loans/LoanApplicationTestBuilder.java
@@ -61,8 +61,6 @@ public class LoanApplicationTestBuilder {
     private List<HashMap> disbursementData = null;
     @SuppressWarnings("rawtypes")
     private List<HashMap> charges = new ArrayList<>();
-    private String recalculationRestFrequencyDate = null;
-    private String recalculationCompoundingFrequencyDate = null;
     private String repaymentsStartingFromDate = null;
 
     private String calendarId;
@@ -135,12 +133,6 @@ public class LoanApplicationTestBuilder {
             map.put("maxOutstandingLoanBalance", maxOutstandingLoanBalance);
 
         }
-        if (recalculationRestFrequencyDate != null) {
-            map.put("recalculationRestFrequencyDate", 
recalculationRestFrequencyDate);
-        }
-        if (recalculationCompoundingFrequencyDate != null) {
-            map.put("recalculationCompoundingFrequencyDate", 
recalculationCompoundingFrequencyDate);
-        }
 
         System.out.println("Loan Application request : " + map);
         return new Gson().toJson(map);
@@ -281,15 +273,7 @@ public class LoanApplicationTestBuilder {
         return this;
     }
 
-    public LoanApplicationTestBuilder withRestFrequencyDate(final String 
recalculationRestFrequencyDate) {
-        this.recalculationRestFrequencyDate = recalculationRestFrequencyDate;
-        return this;
-    }
 
-    public LoanApplicationTestBuilder withCompoundingFrequencyDate(final 
String recalculationCompoundingFrequencyDate) {
-        this.recalculationCompoundingFrequencyDate = 
recalculationCompoundingFrequencyDate;
-        return this;
-    }
 
     public LoanApplicationTestBuilder withFirstRepaymentDate(final String 
firstRepaymentDate) {
         this.repaymentsStartingFromDate = firstRepaymentDate;

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java
 
b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java
index 3b4c767..5f90468 100644
--- 
a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java
+++ 
b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java
@@ -104,10 +104,8 @@ public class LoanProductTestBuilder {
     private String rescheduleStrategyMethod = "1";
     private String recalculationRestFrequencyType = "1";
     private String recalculationRestFrequencyInterval = "0";
-    private String recalculationRestFrequencyDate = null;
     private String recalculationCompoundingFrequencyType = null;
     private String recalculationCompoundingFrequencyInterval = null;
-    private String recalculationCompoundingFrequencyDate = null;
     private String minimumDaysBetweenDisbursalAndFirstRepayment = null;
     private Boolean holdGuaranteeFunds = null;
     private String mandatoryGuarantee = null;
@@ -122,6 +120,10 @@ public class LoanProductTestBuilder {
     private Boolean allowVariableInstallments = Boolean.FALSE;
     private Integer minimumGap;
     private Integer maximumGap;
+    private Integer recalculationCompoundingFrequencyOnDayType = null;
+    private Integer recalculationRestFrequencyOnDayType = null;
+    private Integer recalculationCompoundingFrequencyDayOfWeekType = null;
+    private Integer recalculationRestFrequencyDayOfWeekType = null;
 
     public String build(final String chargeId) {
         final HashMap<String, Object> map = new HashMap<>();
@@ -177,16 +179,18 @@ public class LoanProductTestBuilder {
             map.put("rescheduleStrategyMethod", this.rescheduleStrategyMethod);
             map.put("recalculationRestFrequencyType", 
recalculationRestFrequencyType);
             map.put("recalculationRestFrequencyInterval", 
recalculationRestFrequencyInterval);
-            map.put("recalculationRestFrequencyDate", 
recalculationRestFrequencyDate);
             if 
(!RECALCULATION_COMPOUNDING_METHOD_NONE.equals(this.interestRecalculationCompoundingMethod))
 {
                 map.put("recalculationCompoundingFrequencyType", 
recalculationCompoundingFrequencyType);
                 map.put("recalculationCompoundingFrequencyInterval", 
recalculationCompoundingFrequencyInterval);
-                map.put("recalculationCompoundingFrequencyDate", 
recalculationCompoundingFrequencyDate);
             }
             map.put("preClosureInterestCalculationStrategy", 
preCloseInterestCalculationStrategy);
             if (isArrearsBasedOnOriginalSchedule != null) {
                 map.put("isArrearsBasedOnOriginalSchedule", 
isArrearsBasedOnOriginalSchedule);
             }
+            map.put("recalculationCompoundingFrequencyOnDayType", 
this.recalculationCompoundingFrequencyOnDayType);
+            map.put("recalculationCompoundingFrequencyDayOfWeekType", 
this.recalculationCompoundingFrequencyDayOfWeekType);
+            map.put("recalculationRestFrequencyOnDayType", 
this.recalculationRestFrequencyOnDayType);
+            map.put("recalculationRestFrequencyDayOfWeekType", 
this.recalculationRestFrequencyDayOfWeekType);
         }
         if (holdGuaranteeFunds != null) {
             map.put("holdGuaranteeFunds", this.holdGuaranteeFunds);
@@ -437,20 +441,24 @@ public class LoanProductTestBuilder {
     }
 
     public LoanProductTestBuilder 
withInterestRecalculationRestFrequencyDetails(final String 
recalculationRestFrequencyType,
-            final String recalculationRestFrequencyInterval, final String 
recalculationRestFrequencyDate) {
+            final String recalculationRestFrequencyInterval, final Integer 
recalculationRestFrequencyOnDayType,
+            final Integer recalculationRestFrequencyDayOfWeekType) {
         this.isInterestRecalculationEnabled = true;
         this.recalculationRestFrequencyType = recalculationRestFrequencyType;
         this.recalculationRestFrequencyInterval = 
recalculationRestFrequencyInterval;
-        this.recalculationRestFrequencyDate = recalculationRestFrequencyDate;
+        this.recalculationRestFrequencyOnDayType = 
recalculationRestFrequencyOnDayType;
+        this.recalculationRestFrequencyDayOfWeekType = 
recalculationRestFrequencyDayOfWeekType;
         return this;
     }
 
     public LoanProductTestBuilder 
withInterestRecalculationCompoundingFrequencyDetails(final String 
recalculationCompoundingFrequencyType,
-            final String recalculationCompoundingFrequencyInterval, final 
String recalculationCompoundingFrequencyDate) {
+            final String recalculationCompoundingFrequencyInterval, final 
Integer recalculationCompoundingFrequencyOnDayType,
+            final Integer recalculationCompoundingFrequencyDayOfWeekType) {
         this.isInterestRecalculationEnabled = true;
         this.recalculationCompoundingFrequencyType = 
recalculationCompoundingFrequencyType;
         this.recalculationCompoundingFrequencyInterval = 
recalculationCompoundingFrequencyInterval;
-        this.recalculationCompoundingFrequencyDate = 
recalculationCompoundingFrequencyDate;
+        this.recalculationCompoundingFrequencyOnDayType = 
recalculationCompoundingFrequencyOnDayType;
+        this.recalculationCompoundingFrequencyDayOfWeekType = 
recalculationCompoundingFrequencyDayOfWeekType;
         return this;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/domain/JournalEntry.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/domain/JournalEntry.java
 
b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/domain/JournalEntry.java
index 3e499d1..447cb13 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/domain/JournalEntry.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/domain/JournalEntry.java
@@ -173,6 +173,9 @@ public class JournalEntry extends 
AbstractAuditableCustom<AppUser, Long> {
         return this.amount;
     }
 
+    public void setAmount(BigDecimal amount) {
+        this.amount = amount;
+    }
     public void setReversalJournalEntry(final JournalEntry 
reversalJournalEntry) {
         this.reversalJournalEntry = reversalJournalEntry;
     }

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/domain/JournalEntryRepository.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/domain/JournalEntryRepository.java
 
b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/domain/JournalEntryRepository.java
index ab61a70..120b03e 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/domain/JournalEntryRepository.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/domain/JournalEntryRepository.java
@@ -18,6 +18,7 @@
  */
 package org.apache.fineract.accounting.journalentry.domain;
 
+import java.util.Date;
 import java.util.List;
 
 import org.springframework.data.jpa.repository.JpaRepository;
@@ -39,8 +40,13 @@ public interface JournalEntryRepository extends 
JpaRepository<JournalEntry, Long
     
     @Query("from JournalEntry journalEntry where journalEntry.entityId= 
:entityId and journalEntry.entityType = :entityType")    
     List<JournalEntry> 
findProvisioningJournalEntriesByEntityId(@Param("entityId") Long entityId, 
@Param("entityType") Integer entityType) ;
-    
+
     @Query("from JournalEntry journalEntry where journalEntry.transactionId= 
:transactionId and journalEntry.reversed is false and journalEntry.entityType = 
:entityType")
-    List<JournalEntry> findJournalEntries(@Param("transactionId") String 
transactionId, @Param("entityType") Integer entityType) ;
-    
+    List<JournalEntry> findJournalEntries(@Param("transactionId") String 
transactionId, @Param("entityType") Integer entityType);
+
+    @Query("from JournalEntry journalEntry where glAccount.id= :accountId and 
transactionId= :transactionId and transactionDate= :transactionDate"
+            + " and type= :journalEntryType and entityType=1 and entityId= 
:loanId and loanTransaction.id= :loanTransactionId")
+    JournalEntry findLOANJournalEntryWith(@Param("accountId") Long accountId, 
@Param("transactionId") String transactionId,
+            @Param("transactionDate") Date transactionDate, 
@Param("journalEntryType") Integer journalEntryType,
+            @Param("loanId") Long loanId, @Param("loanTransactionId") Long 
loanTransactionId);
 }

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorHelper.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorHelper.java
 
b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorHelper.java
index 3d64581..c7a0c23 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorHelper.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorHelper.java
@@ -781,6 +781,12 @@ public class AccountingProcessorHelper {
             final Long loanProductId, final Long paymentTypeId, final Long 
loanId, final String transactionId, final Date transactionDate,
             final BigDecimal amount, final Boolean isReversal) {
         final GLAccount account = 
getLinkedGLAccountForLoanProduct(loanProductId, accountMappingTypeId, 
paymentTypeId);
+        createCreditJournalEntryOrReversalForLoan(office, currencyCode, 
loanId, transactionId, transactionDate, amount, isReversal, account);
+    }
+
+    public void createCreditJournalEntryOrReversalForLoan(final Office office, 
final String currencyCode, final Long loanId,
+            final String transactionId, final Date transactionDate, final 
BigDecimal amount, final Boolean isReversal,
+            final GLAccount account) {
         if (isReversal) {
             createDebitJournalEntryForLoan(office, currencyCode, account, 
loanId, transactionId, transactionDate, amount);
         } else {
@@ -1070,7 +1076,7 @@ public class AccountingProcessorHelper {
         this.glJournalEntryRepository.save(journalEntry);
     }
 
-    private GLAccount getLinkedGLAccountForLoanProduct(final Long 
loanProductId, final int accountMappingTypeId, final Long paymentTypeId) {
+    public GLAccount getLinkedGLAccountForLoanProduct(final Long 
loanProductId, final int accountMappingTypeId, final Long paymentTypeId) {
         GLAccount glAccount = null;
         if (isOrganizationAccount(accountMappingTypeId)) {
             FinancialActivityAccount financialActivityAccount = 
this.financialActivityAccountRepository

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccrualBasedAccountingProcessorForLoan.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccrualBasedAccountingProcessorForLoan.java
 
b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccrualBasedAccountingProcessorForLoan.java
index 8287b72..7408ac9 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccrualBasedAccountingProcessorForLoan.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccrualBasedAccountingProcessorForLoan.java
@@ -21,12 +21,16 @@ package org.apache.fineract.accounting.journalentry.service;
 import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.Date;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
 
 import org.apache.fineract.accounting.closure.domain.GLClosure;
 import 
org.apache.fineract.accounting.common.AccountingConstants.ACCRUAL_ACCOUNTS_FOR_LOAN;
 import 
org.apache.fineract.accounting.common.AccountingConstants.CASH_ACCOUNTS_FOR_LOAN;
 import 
org.apache.fineract.accounting.common.AccountingConstants.FINANCIAL_ACTIVITY;
+import org.apache.fineract.accounting.glaccount.domain.GLAccount;
 import org.apache.fineract.accounting.journalentry.data.ChargePaymentDTO;
 import org.apache.fineract.accounting.journalentry.data.LoanDTO;
 import org.apache.fineract.accounting.journalentry.data.LoanTransactionDTO;
@@ -88,7 +92,7 @@ public class AccrualBasedAccountingProcessorForLoan 
implements AccountingProcess
                     .getTransactionType().isWaiveCharges())) {
                 createJournalEntriesForRepaymentsAndWriteOffs(loanDTO, 
loanTransactionDTO, office, true, false);
             }
-            
+
             /** Logic for Refunds of Active Loans **/
             else if 
(loanTransactionDTO.getTransactionType().isRefundForActiveLoans()) {
                 createJournalEntriesForRefundForActiveLoan(loanDTO, 
loanTransactionDTO, office);
@@ -193,18 +197,27 @@ public class AccrualBasedAccountingProcessorForLoan 
implements AccountingProcess
 
         BigDecimal totalDebitAmount = new BigDecimal(0);
 
+        Map<GLAccount, BigDecimal> accountMap = new HashMap<>();
+
         // handle principal payment or writeOff (and reversals)
         if (principalAmount != null && 
!(principalAmount.compareTo(BigDecimal.ZERO) == 0)) {
             totalDebitAmount = totalDebitAmount.add(principalAmount);
-            this.helper.createCreditJournalEntryOrReversalForLoan(office, 
currencyCode, ACCRUAL_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO,
-                    loanProductId, paymentTypeId, loanId, transactionId, 
transactionDate, principalAmount, isReversal);
+            GLAccount account = 
this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
+                    ACCRUAL_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO.getValue(), 
paymentTypeId);
+            accountMap.put(account, principalAmount);
         }
 
         // handle interest payment of writeOff (and reversals)
         if (interestAmount != null && 
!(interestAmount.compareTo(BigDecimal.ZERO) == 0)) {
             totalDebitAmount = totalDebitAmount.add(interestAmount);
-            this.helper.createCreditJournalEntryOrReversalForLoan(office, 
currencyCode, ACCRUAL_ACCOUNTS_FOR_LOAN.INTEREST_RECEIVABLE,
-                    loanProductId, paymentTypeId, loanId, transactionId, 
transactionDate, interestAmount, isReversal);
+            GLAccount account = 
this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
+                    ACCRUAL_ACCOUNTS_FOR_LOAN.INTEREST_RECEIVABLE.getValue(), 
paymentTypeId);
+            if (accountMap.containsKey(account)) {
+                BigDecimal amount = 
accountMap.get(account).add(interestAmount);
+                accountMap.put(account, amount);
+            } else {
+                accountMap.put(account, interestAmount);
+            }
         }
 
         // handle fees payment of writeOff (and reversals)
@@ -212,12 +225,23 @@ public class AccrualBasedAccountingProcessorForLoan 
implements AccountingProcess
             totalDebitAmount = totalDebitAmount.add(feesAmount);
 
             if (isIncomeFromFee) {
-                
this.helper.createCreditJournalEntryOrReversalForLoanCharges(office, 
currencyCode,
-                        ACCRUAL_ACCOUNTS_FOR_LOAN.INCOME_FROM_FEES.getValue(), 
loanProductId, loanId, transactionId, transactionDate,
-                        feesAmount, isReversal, 
loanTransactionDTO.getFeePayments());
+                GLAccount account = 
this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
+                        ACCRUAL_ACCOUNTS_FOR_LOAN.INCOME_FROM_FEES.getValue(), 
paymentTypeId);
+                if (accountMap.containsKey(account)) {
+                    BigDecimal amount = 
accountMap.get(account).add(feesAmount);
+                    accountMap.put(account, amount);
+                } else {
+                    accountMap.put(account, feesAmount);
+                }
             } else {
-                this.helper.createCreditJournalEntryOrReversalForLoan(office, 
currencyCode, ACCRUAL_ACCOUNTS_FOR_LOAN.FEES_RECEIVABLE,
-                        loanProductId, paymentTypeId, loanId, transactionId, 
transactionDate, feesAmount, isReversal);
+                GLAccount account = 
this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
+                        ACCRUAL_ACCOUNTS_FOR_LOAN.FEES_RECEIVABLE.getValue(), 
paymentTypeId);
+                if (accountMap.containsKey(account)) {
+                    BigDecimal amount = 
accountMap.get(account).add(feesAmount);
+                    accountMap.put(account, amount);
+                } else {
+                    accountMap.put(account, feesAmount);
+                }
             }
         }
 
@@ -225,19 +249,41 @@ public class AccrualBasedAccountingProcessorForLoan 
implements AccountingProcess
         if (penaltiesAmount != null && 
!(penaltiesAmount.compareTo(BigDecimal.ZERO) == 0)) {
             totalDebitAmount = totalDebitAmount.add(penaltiesAmount);
             if (isIncomeFromFee) {
-                
this.helper.createCreditJournalEntryOrReversalForLoanCharges(office, 
currencyCode,
-                        
ACCRUAL_ACCOUNTS_FOR_LOAN.INCOME_FROM_PENALTIES.getValue(), loanProductId, 
loanId, transactionId, transactionDate,
-                        penaltiesAmount, isReversal, 
loanTransactionDTO.getPenaltyPayments());
+                GLAccount account = 
this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
+                        
ACCRUAL_ACCOUNTS_FOR_LOAN.INCOME_FROM_PENALTIES.getValue(), paymentTypeId);
+                if (accountMap.containsKey(account)) {
+                    BigDecimal amount = 
accountMap.get(account).add(penaltiesAmount);
+                    accountMap.put(account, amount);
+                } else {
+                    accountMap.put(account, penaltiesAmount);
+                }
             } else {
-                this.helper.createCreditJournalEntryOrReversalForLoan(office, 
currencyCode, ACCRUAL_ACCOUNTS_FOR_LOAN.PENALTIES_RECEIVABLE,
-                        loanProductId, paymentTypeId, loanId, transactionId, 
transactionDate, penaltiesAmount, isReversal);
+                GLAccount account = 
this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
+                        
ACCRUAL_ACCOUNTS_FOR_LOAN.PENALTIES_RECEIVABLE.getValue(), paymentTypeId);
+                if (accountMap.containsKey(account)) {
+                    BigDecimal amount = 
accountMap.get(account).add(penaltiesAmount);
+                    accountMap.put(account, amount);
+                } else {
+                    accountMap.put(account, penaltiesAmount);
+                }
             }
         }
-        
+
         if (overPaymentAmount != null && 
!(overPaymentAmount.compareTo(BigDecimal.ZERO) == 0)) {
             totalDebitAmount = totalDebitAmount.add(overPaymentAmount);
-            this.helper.createCreditJournalEntryOrReversalForLoan(office, 
currencyCode, ACCRUAL_ACCOUNTS_FOR_LOAN.OVERPAYMENT, loanProductId,
-                    paymentTypeId, loanId, transactionId, transactionDate, 
overPaymentAmount, isReversal);
+            GLAccount account = 
this.helper.getLinkedGLAccountForLoanProduct(loanProductId,
+                    ACCRUAL_ACCOUNTS_FOR_LOAN.OVERPAYMENT.getValue(), 
paymentTypeId);
+            if (accountMap.containsKey(account)) {
+                BigDecimal amount = 
accountMap.get(account).add(overPaymentAmount);
+                accountMap.put(account, amount);
+            } else {
+                accountMap.put(account, overPaymentAmount);
+            }
+        }
+
+        for (Entry<GLAccount, BigDecimal> entry : accountMap.entrySet()) {
+            this.helper.createCreditJournalEntryOrReversalForLoan(office, 
currencyCode, loanId, transactionId, transactionDate,
+                    entry.getValue(), isReversal, entry.getKey());
         }
 
         /**
@@ -367,6 +413,7 @@ public class AccrualBasedAccountingProcessorForLoan 
implements AccountingProcess
                     paymentTypeId, loanId, transactionId, transactionDate, 
refundAmount, isReversal);
         }
     }
+
     private void createJournalEntriesForRefundForActiveLoan(LoanDTO loanDTO, 
LoanTransactionDTO loanTransactionDTO, Office office) {
         // TODO Auto-generated method stub
         // loan properties
@@ -401,12 +448,13 @@ public class AccrualBasedAccountingProcessorForLoan 
implements AccountingProcess
 
         if (feesAmount != null && !(feesAmount.compareTo(BigDecimal.ZERO) == 
0)) {
             totalDebitAmount = totalDebitAmount.add(feesAmount);
-            
+
             List<ChargePaymentDTO> chargePaymentDTOs = new ArrayList<>();
-            
-            for(ChargePaymentDTO chargePaymentDTO : 
loanTransactionDTO.getFeePayments()) {
-                chargePaymentDTOs.add(new 
ChargePaymentDTO(chargePaymentDTO.getChargeId(), 
chargePaymentDTO.getLoanChargeId(), 
-                        chargePaymentDTO.getAmount().floatValue() < 0 ? 
chargePaymentDTO.getAmount().multiply(new 
BigDecimal(-1)):chargePaymentDTO.getAmount() ));
+
+            for (ChargePaymentDTO chargePaymentDTO : 
loanTransactionDTO.getFeePayments()) {
+                chargePaymentDTOs.add(new 
ChargePaymentDTO(chargePaymentDTO.getChargeId(), 
chargePaymentDTO.getLoanChargeId(),
+                        chargePaymentDTO.getAmount().floatValue() < 0 ? 
chargePaymentDTO.getAmount().multiply(new BigDecimal(-1))
+                                : chargePaymentDTO.getAmount()));
             }
             
this.helper.createCreditJournalEntryOrReversalForLoanCharges(office, 
currencyCode,
                     CASH_ACCOUNTS_FOR_LOAN.INCOME_FROM_FEES.getValue(), 
loanProductId, loanId, transactionId, transactionDate, feesAmount,
@@ -416,12 +464,13 @@ public class AccrualBasedAccountingProcessorForLoan 
implements AccountingProcess
         if (penaltiesAmount != null && 
!(penaltiesAmount.compareTo(BigDecimal.ZERO) == 0)) {
             totalDebitAmount = totalDebitAmount.add(penaltiesAmount);
             List<ChargePaymentDTO> chargePaymentDTOs = new ArrayList<>();
-            
-            for(ChargePaymentDTO chargePaymentDTO : 
loanTransactionDTO.getPenaltyPayments()) {
-                chargePaymentDTOs.add(new 
ChargePaymentDTO(chargePaymentDTO.getChargeId(), 
chargePaymentDTO.getLoanChargeId(), 
-                        chargePaymentDTO.getAmount().floatValue() < 0 ? 
chargePaymentDTO.getAmount().multiply(new 
BigDecimal(-1)):chargePaymentDTO.getAmount() ));
+
+            for (ChargePaymentDTO chargePaymentDTO : 
loanTransactionDTO.getPenaltyPayments()) {
+                chargePaymentDTOs.add(new 
ChargePaymentDTO(chargePaymentDTO.getChargeId(), 
chargePaymentDTO.getLoanChargeId(),
+                        chargePaymentDTO.getAmount().floatValue() < 0 ? 
chargePaymentDTO.getAmount().multiply(new BigDecimal(-1))
+                                : chargePaymentDTO.getAmount()));
             }
-            
+
             
this.helper.createCreditJournalEntryOrReversalForLoanCharges(office, 
currencyCode,
                     CASH_ACCOUNTS_FOR_LOAN.INCOME_FROM_PENALTIES.getValue(), 
loanProductId, loanId, transactionId, transactionDate,
                     penaltiesAmount, !isReversal, chargePaymentDTOs);
@@ -434,8 +483,8 @@ public class AccrualBasedAccountingProcessorForLoan 
implements AccountingProcess
         }
 
         /*** create a single debit entry (or reversal) for the entire amount 
**/
-        this.helper.createDebitJournalEntryOrReversalForLoan(office, 
currencyCode, CASH_ACCOUNTS_FOR_LOAN.FUND_SOURCE.getValue(), loanProductId,
-                paymentTypeId, loanId, transactionId, transactionDate, 
totalDebitAmount, !isReversal);
-     
+        this.helper.createDebitJournalEntryOrReversalForLoan(office, 
currencyCode, CASH_ACCOUNTS_FOR_LOAN.FUND_SOURCE.getValue(),
+                loanProductId, paymentTypeId, loanId, transactionId, 
transactionDate, totalDebitAmount, !isReversal);
+
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/JobName.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/JobName.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/JobName.java
index cec29fb..0580a4c 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/JobName.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/JobName.java
@@ -39,8 +39,9 @@ public enum JobName {
     RECALCULATE_INTEREST_FOR_LOAN("Recalculate Interest For Loans"), //
     GENERATE_RD_SCEHDULE("Generate Mandatory Savings Schedule"), //
     GENERATE_LOANLOSS_PROVISIONING("Generate Loan Loss Provisioning"), //
-    POST_DIVIDENTS_FOR_SHARES("Post Dividends For Shares"),
-    UPDATE_SAVINGS_DORMANT_ACCOUNTS("Update Savings Dormant Accounts");
+    POST_DIVIDENTS_FOR_SHARES("Post Dividends For Shares"), //
+    UPDATE_SAVINGS_DORMANT_ACCOUNTS("Update Savings Dormant Accounts"), //
+    
ADD_PERIODIC_ACCRUAL_ENTRIES_FOR_LOANS_WITH_INCOME_POSTED_AS_TRANSACTIONS("Add 
Accrual Transactions For Loans With Income Posted As Transactions");
 
     private final String name;
 

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/CalendarConstants.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/CalendarConstants.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/CalendarConstants.java
index a15a71b..b96eee5 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/CalendarConstants.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/CalendarConstants.java
@@ -31,7 +31,8 @@ public class CalendarConstants {
                 "typeId"), REPEATING("repeating"), REMIND_BY_ID("remindById"), 
FIRST_REMINDER("firstReminder"), SECOND_REMINDER(
                 "secondReminder"), LOCALE("locale"), 
DATE_FORMAT("dateFormat"), FREQUENCY("frequency"), INTERVAL("interval"), 
REPEATS_ON_DAY(
                 "repeatsOnDay"), 
RESCHEDULE_BASED_ON_MEETING_DATES("reschedulebasedOnMeetingDates"), 
PRESENT_MEETING_DATE(
-                "presentMeetingDate"), 
NEW_MEETING_DATE("newMeetingDate"),MEETING_TIME("meetingtime"),Time_Format("timeFormat"),
 ;
+                "presentMeetingDate"), 
NEW_MEETING_DATE("newMeetingDate"),MEETING_TIME("meetingtime"),Time_Format("timeFormat"),
 REPEATS_ON_NTH_DAY_OF_MONTH("repeatsOnNthDayOfMonth"),
+                
REPEATS_ON_LAST_WEEKDAY_OF_MONTH("repeatsOnLastWeekdayOfMonth"), 
REPEATS_ON_DAY_OF_MONTH("repeatsOnDayOfMonth");
 
         private final String value;
 

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/api/CalendarsApiResource.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/api/CalendarsApiResource.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/api/CalendarsApiResource.java
index f2ac608..418c902 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/api/CalendarsApiResource.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/api/CalendarsApiResource.java
@@ -230,8 +230,9 @@ public class CalendarsApiResource {
         final List<EnumOptionData> remindByOptions = 
this.dropdownReadPlatformService.retrieveCalendarRemindByOptions();
         final List<EnumOptionData> frequencyOptions = 
this.dropdownReadPlatformService.retrieveCalendarFrequencyTypeOptions();
         final List<EnumOptionData> repeatsOnDayOptions = 
this.dropdownReadPlatformService.retrieveCalendarWeekDaysTypeOptions();
+        final List<EnumOptionData> frequencyNthDayTypeOptions = 
this.dropdownReadPlatformService.retrieveCalendarFrequencyNthDayTypeOptions();
         return CalendarData.withTemplateOptions(calendarData, 
entityTypeOptions, calendarTypeOptions, remindByOptions, frequencyOptions,
-                repeatsOnDayOptions);
+                repeatsOnDayOptions, frequencyNthDayTypeOptions);
     }
 
     private CommandWrapper getResourceDetails(final CalendarEntityType type, 
final Long entityId) {

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/data/CalendarData.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/data/CalendarData.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/data/CalendarData.java
index de89923..2c6513a 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/data/CalendarData.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/data/CalendarData.java
@@ -28,6 +28,7 @@ import 
org.apache.fineract.portfolio.calendar.domain.CalendarType;
 import org.apache.fineract.portfolio.calendar.domain.CalendarWeekDaysType;
 import org.apache.fineract.portfolio.calendar.service.CalendarEnumerations;
 import org.apache.fineract.portfolio.calendar.service.CalendarUtils;
+import org.apache.fineract.portfolio.common.domain.NthDayType;
 import org.joda.time.LocalDate;
 import org.joda.time.LocalTime;
 
@@ -53,6 +54,7 @@ public class CalendarData {
     private final EnumOptionData frequency;
     private final Integer interval;
     private final EnumOptionData repeatsOnDay;
+    private final EnumOptionData repeatsOnNthDayOfMonth;
     private final EnumOptionData remindBy;
     private final Integer firstReminder;
     private final Integer secondReminder;
@@ -67,20 +69,24 @@ public class CalendarData {
     private final String createdByUsername;
     private final Long lastUpdatedByUserId;
     private final String lastUpdatedByUsername;
+    private final Integer repeatsOnDayOfMonth;
+
     // template related
     final List<EnumOptionData> entityTypeOptions;
     final List<EnumOptionData> calendarTypeOptions;
     final List<EnumOptionData> remindByOptions;
     final List<EnumOptionData> frequencyOptions;
     final List<EnumOptionData> repeatsOnDayOptions;
+    final List<EnumOptionData> frequencyNthDayTypeOptions;
  
     public static CalendarData instance(final Long id, final Long 
calendarInstanceId, final Long entityId, final EnumOptionData entityType,
             final String title, final String description, final String 
location, final LocalDate startDate, final LocalDate endDate,
             final Integer duration, final EnumOptionData type, final boolean 
repeating, final String recurrence,
-            final EnumOptionData frequency, final Integer interval, final 
EnumOptionData repeatsOnDay, final EnumOptionData remindBy,
-            final Integer firstReminder, final Integer secondReminder, final 
String humanReadable, final LocalDate createdDate,
-            final LocalDate lastUpdatedDate, final Long createdByUserId, final 
String createdByUsername, final Long lastUpdatedByUserId,
-            final String lastUpdatedByUsername, final LocalTime meetingTime) {
+            final EnumOptionData frequency, final Integer interval, final 
EnumOptionData repeatsOnDay,
+            final EnumOptionData repeatsOnNthDayOfMonth, final EnumOptionData 
remindBy, final Integer firstReminder,
+            final Integer secondReminder, final String humanReadable, final 
LocalDate createdDate, final LocalDate lastUpdatedDate,
+            final Long createdByUserId, final String createdByUsername, final 
Long lastUpdatedByUserId, final String lastUpdatedByUsername,
+            final LocalTime meetingTime, final Integer repeatsOnDayOfMonth) {
 
         final Collection<LocalDate> recurringDates = null;
         final Collection<LocalDate> nextTenRecurringDates = null;
@@ -91,12 +97,14 @@ public class CalendarData {
         final List<EnumOptionData> remindByOptions = null;
         final List<EnumOptionData> frequencyOptions = null;
         final List<EnumOptionData> repeatsOnDayOptions = null;
+        final List<EnumOptionData> frequencyNthDayTypeOptions = null;
 
         return new CalendarData(id, calendarInstanceId, entityId, entityType, 
title, description, location, startDate, endDate, duration,
-                type, repeating, recurrence, frequency, interval, 
repeatsOnDay, remindBy, firstReminder, secondReminder, recurringDates,
-                nextTenRecurringDates, humanReadable, 
recentEligibleMeetingDate, createdDate, lastUpdatedDate, createdByUserId,
-                createdByUsername, lastUpdatedByUserId, lastUpdatedByUsername, 
entityTypeOptions, calendarTypeOptions, remindByOptions,
-                frequencyOptions, repeatsOnDayOptions, meetingTime);
+                type, repeating, recurrence, frequency, interval, 
repeatsOnDay, repeatsOnNthDayOfMonth, remindBy, firstReminder,
+                secondReminder, recurringDates, nextTenRecurringDates, 
humanReadable, recentEligibleMeetingDate, createdDate,
+                lastUpdatedDate, createdByUserId, createdByUsername, 
lastUpdatedByUserId, lastUpdatedByUsername, repeatsOnDayOfMonth,
+                entityTypeOptions, calendarTypeOptions, remindByOptions, 
frequencyOptions, repeatsOnDayOptions, meetingTime,
+                frequencyNthDayTypeOptions);
     }
 
     public static CalendarData withRecurringDates(final CalendarData 
calendarData, final Collection<LocalDate> recurringDates,
@@ -104,24 +112,24 @@ public class CalendarData {
         return new CalendarData(calendarData.id, 
calendarData.calendarInstanceId, calendarData.entityId, calendarData.entityType,
                 calendarData.title, calendarData.description, 
calendarData.location, calendarData.startDate, calendarData.endDate,
                 calendarData.duration, calendarData.type, 
calendarData.repeating, calendarData.recurrence, calendarData.frequency,
-                calendarData.interval, calendarData.repeatsOnDay, 
calendarData.remindBy, calendarData.firstReminder,
+                calendarData.interval, calendarData.repeatsOnDay, 
calendarData.repeatsOnNthDayOfMonth, calendarData.remindBy, 
calendarData.firstReminder,
                 calendarData.secondReminder, recurringDates, 
nextTenRecurringDates, calendarData.humanReadable, recentEligibleMeetingDate,
                 calendarData.createdDate, calendarData.lastUpdatedDate, 
calendarData.createdByUserId, calendarData.createdByUsername,
-                calendarData.lastUpdatedByUserId, 
calendarData.lastUpdatedByUsername, calendarData.entityTypeOptions,
+                calendarData.lastUpdatedByUserId, 
calendarData.lastUpdatedByUsername, calendarData.repeatsOnDayOfMonth, 
calendarData.entityTypeOptions,
                 calendarData.calendarTypeOptions, 
calendarData.remindByOptions, calendarData.frequencyOptions,
-                calendarData.repeatsOnDayOptions,calendarData.meetingTime);
+                calendarData.repeatsOnDayOptions, calendarData.meetingTime, 
calendarData.frequencyNthDayTypeOptions);
     }
 
     public static CalendarData withRecentEligibleMeetingDate(final 
CalendarData calendarData, final LocalDate recentEligibleMeetingDate) {
         return new CalendarData(calendarData.id, 
calendarData.calendarInstanceId, calendarData.entityId, calendarData.entityType,
                 calendarData.title, calendarData.description, 
calendarData.location, calendarData.startDate, calendarData.endDate,
                 calendarData.duration, calendarData.type, 
calendarData.repeating, calendarData.recurrence, calendarData.frequency,
-                calendarData.interval, calendarData.repeatsOnDay, 
calendarData.remindBy, calendarData.firstReminder,
+                calendarData.interval, calendarData.repeatsOnDay, 
calendarData.repeatsOnNthDayOfMonth, calendarData.remindBy, 
calendarData.firstReminder,
                 calendarData.secondReminder, calendarData.recurringDates, 
calendarData.nextTenRecurringDates, calendarData.humanReadable,
                 recentEligibleMeetingDate, calendarData.createdDate, 
calendarData.lastUpdatedDate, calendarData.createdByUserId,
                 calendarData.createdByUsername, 
calendarData.lastUpdatedByUserId, calendarData.lastUpdatedByUsername,
-                calendarData.entityTypeOptions, 
calendarData.calendarTypeOptions, calendarData.remindByOptions,
-                calendarData.frequencyOptions, 
calendarData.repeatsOnDayOptions,calendarData.meetingTime);
+                calendarData.repeatsOnDayOfMonth, 
calendarData.entityTypeOptions, calendarData.calendarTypeOptions, 
calendarData.remindByOptions,
+                calendarData.frequencyOptions, 
calendarData.repeatsOnDayOptions,calendarData.meetingTime, 
calendarData.frequencyNthDayTypeOptions);
     }
 
     public static CalendarData sensibleDefaultsForNewCalendarCreation() {
@@ -141,6 +149,7 @@ public class CalendarData {
         final EnumOptionData frequency = 
CalendarEnumerations.calendarFrequencyType(CalendarFrequencyType.DAILY);
         final Integer interval = new Integer(1);
         final EnumOptionData repeatsOnDay = 
CalendarEnumerations.calendarWeekDaysType(CalendarWeekDaysType.MO);
+        final EnumOptionData repeatsOnNthDayOfMonth = 
CalendarEnumerations.calendarFrequencyNthDayType(NthDayType.ONE);
         final EnumOptionData remindBy = 
CalendarEnumerations.calendarRemindBy(CalendarRemindBy.EMAIL);
         final Integer firstReminder = new Integer(0);
         final Integer secondReminder = new Integer(0);
@@ -154,6 +163,7 @@ public class CalendarData {
         final List<EnumOptionData> remindByOptions = null;
         final List<EnumOptionData> frequencyOptions = null;
         final List<EnumOptionData> repeatsOnDayOptions = null;
+        final List<EnumOptionData> frequencyNthDayTypeOptions = null;
 
         final LocalDate createdDate = null;
         final LocalDate lastUpdatedDate = null;
@@ -162,39 +172,44 @@ public class CalendarData {
         final Long lastUpdatedByUserId = null;
         final String lastUpdatedByUsername = null;
         final LocalTime meetingTime = null;
+        final Integer repeatsOnDayOfMonth = null;
 
         return new CalendarData(id, calendarInstanceId, entityId, entityType, 
title, description, location, startDate, endDate, duration,
-                type, repeating, recurrence, frequency, interval, 
repeatsOnDay, remindBy, firstReminder, secondReminder, recurringDates,
-                nextTenRecurringDates, humanReadable, 
recentEligibleMeetingDate, createdDate, lastUpdatedDate, createdByUserId,
-                createdByUsername, lastUpdatedByUserId, lastUpdatedByUsername, 
entityTypeOptions, calendarTypeOptions, remindByOptions,
-                frequencyOptions, repeatsOnDayOptions, meetingTime);
+                type, repeating, recurrence, frequency, interval, 
repeatsOnDay, repeatsOnNthDayOfMonth, remindBy, firstReminder,
+                secondReminder, recurringDates, nextTenRecurringDates, 
humanReadable, recentEligibleMeetingDate, createdDate,
+                lastUpdatedDate, createdByUserId, createdByUsername, 
lastUpdatedByUserId, lastUpdatedByUsername, repeatsOnDayOfMonth,
+                entityTypeOptions, calendarTypeOptions, remindByOptions, 
frequencyOptions, repeatsOnDayOptions, meetingTime,
+                frequencyNthDayTypeOptions);
     }
 
     public static CalendarData withTemplateOptions(final CalendarData 
calendarData, final List<EnumOptionData> entityTypeOptions,
             final List<EnumOptionData> calendarTypeOptions, final 
List<EnumOptionData> remindByOptions,
-            final List<EnumOptionData> repeatsOptions, final 
List<EnumOptionData> repeatsOnDayOptions) {
+            final List<EnumOptionData> repeatsOptions, final 
List<EnumOptionData> repeatsOnDayOptions,
+            final List<EnumOptionData> frequencyNthDayTypeOptions) {
 
         return new CalendarData(calendarData.id, 
calendarData.calendarInstanceId, calendarData.entityId, calendarData.entityType,
                 calendarData.title, calendarData.description, 
calendarData.location, calendarData.startDate, calendarData.endDate,
                 calendarData.duration, calendarData.type, 
calendarData.repeating, calendarData.recurrence, calendarData.frequency,
-                calendarData.interval, calendarData.repeatsOnDay, 
calendarData.remindBy, calendarData.firstReminder,
-                calendarData.secondReminder, calendarData.recurringDates, 
calendarData.nextTenRecurringDates, calendarData.humanReadable,
-                calendarData.recentEligibleMeetingDate, 
calendarData.createdDate, calendarData.lastUpdatedDate,
+                calendarData.interval, calendarData.repeatsOnDay, 
calendarData.repeatsOnNthDayOfMonth, calendarData.remindBy,
+                calendarData.firstReminder, calendarData.secondReminder, 
calendarData.recurringDates, calendarData.nextTenRecurringDates,
+                calendarData.humanReadable, 
calendarData.recentEligibleMeetingDate, calendarData.createdDate, 
calendarData.lastUpdatedDate,
                 calendarData.createdByUserId, calendarData.createdByUsername, 
calendarData.lastUpdatedByUserId,
-                calendarData.lastUpdatedByUsername, entityTypeOptions, 
calendarTypeOptions, remindByOptions, repeatsOptions,
-                repeatsOnDayOptions,calendarData.meetingTime);
+                calendarData.lastUpdatedByUsername, 
calendarData.repeatsOnDayOfMonth, entityTypeOptions, calendarTypeOptions,
+                remindByOptions, repeatsOptions, repeatsOnDayOptions, 
calendarData.meetingTime, frequencyNthDayTypeOptions);
     }
 
     private CalendarData(final Long id, final Long calendarInstanceId, final 
Long entityId, final EnumOptionData entityType,
             final String title, final String description, final String 
location, final LocalDate startDate, final LocalDate endDate,
             final Integer duration, final EnumOptionData type, final boolean 
repeating, final String recurrence,
-            final EnumOptionData frequency, final Integer interval, final 
EnumOptionData repeatsOnDay, final EnumOptionData remindBy,
-            final Integer firstReminder, final Integer secondReminder, final 
Collection<LocalDate> recurringDates,
-            final Collection<LocalDate> nextTenRecurringDates, final String 
humanReadable, final LocalDate recentEligibleMeetingDate,
-            final LocalDate createdDate, final LocalDate lastUpdatedDate, 
final Long createdByUserId, final String createdByUsername,
-            final Long lastUpdatedByUserId, final String 
lastUpdatedByUsername, final List<EnumOptionData> entityTypeOptions,
+            final EnumOptionData frequency, final Integer interval, final 
EnumOptionData repeatsOnDay,
+            final EnumOptionData repeatsOnNthDayOfMonth, final EnumOptionData 
remindBy, final Integer firstReminder,
+            final Integer secondReminder, final Collection<LocalDate> 
recurringDates, final Collection<LocalDate> nextTenRecurringDates,
+            final String humanReadable, final LocalDate 
recentEligibleMeetingDate, final LocalDate createdDate,
+            final LocalDate lastUpdatedDate, final Long createdByUserId, final 
String createdByUsername, final Long lastUpdatedByUserId,
+            final String lastUpdatedByUsername, final Integer 
repeatsOnDayOfMonth, final List<EnumOptionData> entityTypeOptions,
             final List<EnumOptionData> calendarTypeOptions, final 
List<EnumOptionData> remindByOptions,
-            final List<EnumOptionData> repeatsOptions, final 
List<EnumOptionData> repeatsOnDayOptions,final LocalTime meetingTime) {
+            final List<EnumOptionData> repeatsOptions, final 
List<EnumOptionData> repeatsOnDayOptions,final LocalTime meetingTime, 
+            final List<EnumOptionData> frequencyNthDayTypeOptions) {
         this.id = id;
         this.calendarInstanceId = calendarInstanceId;
         this.entityId = entityId;
@@ -211,6 +226,7 @@ public class CalendarData {
         this.frequency = frequency;
         this.interval = interval;
         this.repeatsOnDay = repeatsOnDay;
+        this.repeatsOnNthDayOfMonth = repeatsOnNthDayOfMonth;
         this.remindBy = remindBy;
         this.firstReminder = firstReminder;
         this.secondReminder = secondReminder;
@@ -224,12 +240,14 @@ public class CalendarData {
         this.createdByUsername = createdByUsername;
         this.lastUpdatedByUserId = lastUpdatedByUserId;
         this.lastUpdatedByUsername = lastUpdatedByUsername;
+        this.repeatsOnDayOfMonth = repeatsOnDayOfMonth;
         this.entityTypeOptions = entityTypeOptions;
         this.calendarTypeOptions = calendarTypeOptions;
         this.remindByOptions = remindByOptions;
         this.frequencyOptions = repeatsOptions;
         this.repeatsOnDayOptions = repeatsOnDayOptions;
         this.meetingTime = meetingTime;
+        this.frequencyNthDayTypeOptions = frequencyNthDayTypeOptions;
     }
 
     public Long getId() {
@@ -350,4 +368,10 @@ public class CalendarData {
     public EnumOptionData frequencyType(){
         return this.frequency;
     }
+       public EnumOptionData getRepeatsOnDay() {
+               return this.repeatsOnDay;
+       }
+       public EnumOptionData getRepeatsOnNthDayOfMonth() {
+               return this.repeatsOnNthDayOfMonth;
+       }
 }

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/domain/Calendar.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/domain/Calendar.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/domain/Calendar.java
index f44dfdd..f2fa718 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/domain/Calendar.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/domain/Calendar.java
@@ -48,6 +48,7 @@ import 
org.apache.fineract.portfolio.calendar.CalendarConstants.CALENDAR_SUPPORT
 import org.apache.fineract.portfolio.calendar.exception.CalendarDateException;
 import 
org.apache.fineract.portfolio.calendar.exception.CalendarParameterUpdateNotSupportedException;
 import org.apache.fineract.portfolio.calendar.service.CalendarUtils;
+import org.apache.fineract.portfolio.common.domain.NthDayType;
 import org.apache.fineract.useradministration.domain.AppUser;
 import org.apache.poi.openxml4j.util.Nullable;
 import org.joda.time.LocalDate;
@@ -152,8 +153,9 @@ public class Calendar extends 
AbstractAuditableCustom<AppUser, Long> {
     }
 
     public static Calendar createRepeatingCalendar(final String title, final 
LocalDate startDate, final Integer typeId,
-            final CalendarFrequencyType frequencyType, final Integer interval, 
final Integer repeatsOnDay) {
-        final String recurrence = constructRecurrence(frequencyType, interval, 
repeatsOnDay);
+            final CalendarFrequencyType frequencyType, final Integer interval, 
final Integer repeatsOnDay,
+            final Integer repeatsOnNthDayOfMonth) {
+        final String recurrence = constructRecurrence(frequencyType, interval, 
repeatsOnDay, repeatsOnNthDayOfMonth);
         return createRepeatingCalendar(title, startDate, typeId, recurrence);
     }
 
@@ -245,7 +247,7 @@ public class Calendar extends 
AbstractAuditableCustom<AppUser, Long> {
 
             // TODO cover other recurrence also
 
-            this.recurrence = constructRecurrence(calendarFrequencyType, 
interval, repeatsOnDay);
+            this.recurrence = constructRecurrence(calendarFrequencyType, 
interval, repeatsOnDay, null);
 
         }
 
@@ -422,7 +424,7 @@ public class Calendar extends 
AbstractAuditableCustom<AppUser, Long> {
 
     @SuppressWarnings("null")
     public Map<String, Object> updateRepeatingCalendar(final LocalDate 
calendarStartDate, final CalendarFrequencyType frequencyType,
-            final Integer interval, final Integer repeatsOnDay) {
+            final Integer interval, final Integer repeatsOnDay, final Integer 
repeatsOnNthDay) {
         final Map<String, Object> actualChanges = new LinkedHashMap<>(9);
 
         if (calendarStartDate != null & this.startDate != null) {
@@ -432,7 +434,7 @@ public class Calendar extends 
AbstractAuditableCustom<AppUser, Long> {
             }
         }
 
-        final String newRecurrence = 
Calendar.constructRecurrence(frequencyType, interval, repeatsOnDay);
+        final String newRecurrence = 
Calendar.constructRecurrence(frequencyType, interval, repeatsOnDay, 
repeatsOnNthDay);
         if (!StringUtils.isBlank(this.recurrence) && 
!newRecurrence.equalsIgnoreCase(this.recurrence)) {
             actualChanges.put("recurrence", newRecurrence);
             this.recurrence = newRecurrence;
@@ -568,13 +570,27 @@ public class Calendar extends 
AbstractAuditableCustom<AppUser, Long> {
             if (frequencyType.isWeekly()) {
                 repeatsOnDay = 
command.integerValueOfParameterNamed(CALENDAR_SUPPORTED_PARAMETERS.REPEATS_ON_DAY.getValue());
             }
+            Integer repeatsOnNthDayOfMonth = null;
+            if (frequencyType.isMonthly()) {
+                repeatsOnNthDayOfMonth = 
command.integerValueOfParameterNamed(CALENDAR_SUPPORTED_PARAMETERS.REPEATS_ON_NTH_DAY_OF_MONTH
+                        .getValue());
+                final NthDayType nthDay = 
NthDayType.fromInt(repeatsOnNthDayOfMonth);
+                repeatsOnDay = 
command.integerValueOfParameterNamed(CALENDAR_SUPPORTED_PARAMETERS.REPEATS_ON_LAST_WEEKDAY_OF_MONTH
+                        .getValue());
+                if (nthDay.isOnDay()) {
+                    repeatsOnNthDayOfMonth = 
command.integerValueOfParameterNamed(CALENDAR_SUPPORTED_PARAMETERS.REPEATS_ON_DAY_OF_MONTH
+                            .getValue());
+                    repeatsOnDay = null;
+                }
+            }
 
-            return constructRecurrence(frequencyType, interval, repeatsOnDay);
+            return constructRecurrence(frequencyType, interval, repeatsOnDay, 
repeatsOnNthDayOfMonth);
         }
         return "";
     }
 
-    private static String constructRecurrence(final CalendarFrequencyType 
frequencyType, final Integer interval, final Integer repeatsOnDay) {
+    private static String constructRecurrence(final CalendarFrequencyType 
frequencyType, final Integer interval,
+            final Integer repeatsOnDay, final Integer repeatsOnNthDayOfMonth) {
         final StringBuilder recurrenceBuilder = new StringBuilder(200);
 
         recurrenceBuilder.append("FREQ=");
@@ -584,10 +600,31 @@ public class Calendar extends 
AbstractAuditableCustom<AppUser, Long> {
             recurrenceBuilder.append(interval);
         }
         if (frequencyType.isWeekly()) {
-            final CalendarWeekDaysType weekDays = 
CalendarWeekDaysType.fromInt(repeatsOnDay);
-            if (!weekDays.isInvalid()) {
-                recurrenceBuilder.append(";BYDAY=");
-                recurrenceBuilder.append(weekDays.toString().toUpperCase());
+            if (repeatsOnDay != null) {
+                final CalendarWeekDaysType weekDays = 
CalendarWeekDaysType.fromInt(repeatsOnDay);
+                if (!weekDays.isInvalid()) {
+                    recurrenceBuilder.append(";BYDAY=");
+                    
recurrenceBuilder.append(weekDays.toString().toUpperCase());
+                }
+            }
+        }
+        if (frequencyType.isMonthly()) {
+            if (repeatsOnNthDayOfMonth != null && (repeatsOnDay == null || 
repeatsOnDay == CalendarWeekDaysType.INVALID.getValue())) {
+                if (repeatsOnNthDayOfMonth >= -1 && repeatsOnNthDayOfMonth <= 
28) {
+                    recurrenceBuilder.append(";BYMONTHDAY=");
+                    recurrenceBuilder.append(repeatsOnNthDayOfMonth);
+                }
+            } else if (repeatsOnNthDayOfMonth != null && repeatsOnDay != null 
&& repeatsOnDay != CalendarWeekDaysType.INVALID.getValue()) {
+                final NthDayType nthDay = 
NthDayType.fromInt(repeatsOnNthDayOfMonth);
+                if (!nthDay.isInvalid()) {
+                    recurrenceBuilder.append(";BYSETPOS=");
+                    recurrenceBuilder.append(nthDay.getValue());
+                }
+                final CalendarWeekDaysType weekday = 
CalendarWeekDaysType.fromInt(repeatsOnDay);
+                if (!weekday.isInvalid()) {
+                    recurrenceBuilder.append(";BYDAY=");
+                    recurrenceBuilder.append(weekday.toString().toUpperCase());
+                }
             }
         }
         return recurrenceBuilder.toString();
@@ -611,18 +648,22 @@ public class Calendar extends 
AbstractAuditableCustom<AppUser, Long> {
 
         final CalendarFrequencyType frequencyType = 
CalendarUtils.getFrequency(this.recurrence);
         final Integer interval = new 
Integer(CalendarUtils.getInterval(this.recurrence));
-        final String newRecurrence = 
Calendar.constructRecurrence(frequencyType, interval, startDate.getDayOfWeek());
+        final String newRecurrence = 
Calendar.constructRecurrence(frequencyType, interval, startDate.getDayOfWeek(), 
null);
 
         this.recurrence = newRecurrence;
         this.startDate = startDate.toDate();
         this.endDate = endDate.toDate();
     }
-    
-    public Set<CalendarHistory> getCalendarHistory(){
-       return this.calendarHistory;
+
+    public Set<CalendarHistory> getCalendarHistory() {
+        return this.calendarHistory;
     }
-    
-    public void updateCalendarHistory(final Set<CalendarHistory> 
calendarHistory){
-       this.calendarHistory = calendarHistory;
+
+    public void updateCalendarHistory(final Set<CalendarHistory> 
calendarHistory) {
+        this.calendarHistory = calendarHistory;
+    }
+
+    public void setRecurrence(String recurrence) {
+        this.recurrence = recurrence;
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/domain/CalendarInstance.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/domain/CalendarInstance.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/domain/CalendarInstance.java
index 6c40b04..6ae6c60 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/domain/CalendarInstance.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/domain/CalendarInstance.java
@@ -31,7 +31,7 @@ import 
org.springframework.data.jpa.domain.AbstractPersistable;
 @Table(name = "m_calendar_instance")
 public class CalendarInstance extends AbstractPersistable<Long> {
 
-    @ManyToOne(cascade = CascadeType.ALL)
+    @ManyToOne(cascade = CascadeType.PERSIST)
     @JoinColumn(name = "calendar_id", nullable = false)
     private Calendar calendar;
 

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/serialization/CalendarCommandFromApiJsonDeserializer.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/serialization/CalendarCommandFromApiJsonDeserializer.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/serialization/CalendarCommandFromApiJsonDeserializer.java
index c956afa..fcdd2e2 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/serialization/CalendarCommandFromApiJsonDeserializer.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/serialization/CalendarCommandFromApiJsonDeserializer.java
@@ -37,6 +37,7 @@ import 
org.apache.fineract.portfolio.calendar.domain.CalendarEntityType;
 import org.apache.fineract.portfolio.calendar.domain.CalendarFrequencyType;
 import org.apache.fineract.portfolio.calendar.domain.CalendarRemindBy;
 import org.apache.fineract.portfolio.calendar.domain.CalendarWeekDaysType;
+import org.apache.fineract.portfolio.calendar.service.CalendarUtils;
 import org.joda.time.LocalDate;
 import org.joda.time.LocalDateTime;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -173,6 +174,10 @@ public class CalendarCommandFromApiJsonDeserializer 
extends AbstractFromApiJsonD
                             
CALENDAR_SUPPORTED_PARAMETERS.REPEATS_ON_DAY.getValue(), element);
                     
baseDataValidator.reset().parameter(CALENDAR_SUPPORTED_PARAMETERS.REPEATS_ON_DAY.getValue()).value(repeatsOnDay)
                             
.notBlank().inMinMaxRange(CalendarWeekDaysType.getMinValue(), 
CalendarWeekDaysType.getMaxValue());
+                } else if 
(CalendarFrequencyType.fromInt(frequency).isMonthly()) {
+                    
CalendarUtils.validateNthDayOfMonthFrequency(baseDataValidator,
+                            
CALENDAR_SUPPORTED_PARAMETERS.REPEATS_ON_NTH_DAY_OF_MONTH.getValue(),
+                            
CALENDAR_SUPPORTED_PARAMETERS.REPEATS_ON_LAST_WEEKDAY_OF_MONTH.getValue(), 
element, this.fromApiJsonHelper);
                 }
             }
         }
@@ -305,11 +310,17 @@ public class CalendarCommandFromApiJsonDeserializer 
extends AbstractFromApiJsonD
                             .integerGreaterThanZero();
                 }
 
+                if (CalendarFrequencyType.fromInt(frequency).isWeekly()) {
                 if 
(this.fromApiJsonHelper.parameterExists(CALENDAR_SUPPORTED_PARAMETERS.REPEATS_ON_DAY.getValue(),
 element)) {
                     final Integer repeatsOnDay = 
this.fromApiJsonHelper.extractIntegerSansLocaleNamed(
                             
CALENDAR_SUPPORTED_PARAMETERS.REPEATS_ON_DAY.getValue(), element);
                     
baseDataValidator.reset().parameter(CALENDAR_SUPPORTED_PARAMETERS.REPEATS_ON_DAY.getValue()).value(repeatsOnDay)
                             
.notBlank().inMinMaxRange(CalendarWeekDaysType.getMinValue(), 
CalendarWeekDaysType.getMaxValue());
+                    }
+                } else if 
(CalendarFrequencyType.fromInt(frequency).isMonthly()) {
+                    
CalendarUtils.validateNthDayOfMonthFrequency(baseDataValidator,
+                            
CALENDAR_SUPPORTED_PARAMETERS.REPEATS_ON_NTH_DAY_OF_MONTH.getValue(),
+                            
CALENDAR_SUPPORTED_PARAMETERS.REPEATS_ON_LAST_WEEKDAY_OF_MONTH.getValue(), 
element, this.fromApiJsonHelper);
                 }
             }
         }

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarDropdownReadPlatformService.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarDropdownReadPlatformService.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarDropdownReadPlatformService.java
index 1c95c77..c670643 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarDropdownReadPlatformService.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarDropdownReadPlatformService.java
@@ -33,5 +33,6 @@ public interface CalendarDropdownReadPlatformService {
     List<EnumOptionData> retrieveCalendarFrequencyTypeOptions();
 
     List<EnumOptionData> retrieveCalendarWeekDaysTypeOptions();
+    List<EnumOptionData> retrieveCalendarFrequencyNthDayTypeOptions();
 
 }
\ 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/calendar/service/CalendarDropdownReadPlatformServiceImpl.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarDropdownReadPlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarDropdownReadPlatformServiceImpl.java
index 713a38c..7881180 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarDropdownReadPlatformServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarDropdownReadPlatformServiceImpl.java
@@ -55,4 +55,8 @@ public class CalendarDropdownReadPlatformServiceImpl 
implements CalendarDropdown
     public List<EnumOptionData> retrieveCalendarWeekDaysTypeOptions() {
         return 
CalendarEnumerations.calendarWeekDaysType(CalendarWeekDaysType.values());
     }
+    @Override
+    public List<EnumOptionData> retrieveCalendarFrequencyNthDayTypeOptions() {
+        return CalendarEnumerations.calendarFrequencyNthDayType();
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarEnumerations.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarEnumerations.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarEnumerations.java
index e96dba6..15c74ec 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarEnumerations.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarEnumerations.java
@@ -19,6 +19,7 @@
 package org.apache.fineract.portfolio.calendar.service;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 import org.apache.fineract.infrastructure.core.data.EnumOptionData;
@@ -27,6 +28,7 @@ import 
org.apache.fineract.portfolio.calendar.domain.CalendarFrequencyType;
 import org.apache.fineract.portfolio.calendar.domain.CalendarRemindBy;
 import org.apache.fineract.portfolio.calendar.domain.CalendarType;
 import org.apache.fineract.portfolio.calendar.domain.CalendarWeekDaysType;
+import org.apache.fineract.portfolio.common.domain.NthDayType;
 
 public class CalendarEnumerations {
 
@@ -86,8 +88,11 @@ public class CalendarEnumerations {
     }
 
     public static EnumOptionData calendarFrequencyType(final 
CalendarFrequencyType calendarFrequencyType) {
-        final EnumOptionData optionData = new 
EnumOptionData(calendarFrequencyType.getValue().longValue(), 
calendarFrequencyType.getCode(),
+        EnumOptionData optionData = null;
+        if (!calendarFrequencyType.isInvalid()) {
+            optionData = new 
EnumOptionData(calendarFrequencyType.getValue().longValue(), 
calendarFrequencyType.getCode(),
                 calendarFrequencyType.toString());
+        }
         return optionData;
     }
 
@@ -106,8 +111,11 @@ public class CalendarEnumerations {
     }
 
     public static EnumOptionData calendarWeekDaysType(final 
CalendarWeekDaysType calendarWeekDaysType) {
-        final EnumOptionData optionData = new 
EnumOptionData(calendarWeekDaysType.getValue().longValue(), 
calendarWeekDaysType.getCode(),
+        EnumOptionData optionData = null;
+        if (!calendarWeekDaysType.isInvalid()) {
+            optionData = new 
EnumOptionData(calendarWeekDaysType.getValue().longValue(), 
calendarWeekDaysType.getCode(),
                 calendarWeekDaysType.toString());
+        }
         return optionData;
     }
 
@@ -120,4 +128,19 @@ public class CalendarEnumerations {
         }
         return optionDatas;
     }
+    public static EnumOptionData calendarFrequencyNthDayType(final int id) {
+        return calendarFrequencyNthDayType(NthDayType.fromInt(id));
+    }
+    public static EnumOptionData calendarFrequencyNthDayType(final NthDayType 
calendarFrequencyNthDayType) {
+        final EnumOptionData optionData = new 
EnumOptionData(calendarFrequencyNthDayType.getValue().longValue(), 
calendarFrequencyNthDayType.getCode(),
+                calendarFrequencyNthDayType.toString());
+        return optionData;
+    }
+    public static List<EnumOptionData> calendarFrequencyNthDayType() {
+        final List<EnumOptionData> optionDatas = 
Arrays.asList(calendarFrequencyNthDayType(NthDayType.ONE),
+                       calendarFrequencyNthDayType(NthDayType.TWO), 
calendarFrequencyNthDayType(NthDayType.THREE),
+                       calendarFrequencyNthDayType(NthDayType.FOUR), 
calendarFrequencyNthDayType(NthDayType.LAST), 
+                       calendarFrequencyNthDayType(NthDayType.ONDAY));
+        return optionDatas;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/763cf18b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarReadPlatformServiceImpl.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarReadPlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarReadPlatformServiceImpl.java
index 3b5c37c..c9e7068 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarReadPlatformServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarReadPlatformServiceImpl.java
@@ -89,6 +89,7 @@ public class CalendarReadPlatformServiceImpl implements 
CalendarReadPlatformServ
             final EnumOptionData frequency = 
CalendarEnumerations.calendarFrequencyType(CalendarUtils.getFrequency(recurrence));
             final Integer interval = new 
Integer(CalendarUtils.getInterval(recurrence));
             final EnumOptionData repeatsOnDay = 
CalendarEnumerations.calendarWeekDaysType(CalendarUtils.getRepeatsOnDay(recurrence));
+            final EnumOptionData repeatsOnNthDayOfMonth = 
CalendarEnumerations.calendarFrequencyNthDayType(CalendarUtils.getRepeatsOnNthDayOfMonth(recurrence));
             final Integer remindById = rs.getInt("remindById");
             EnumOptionData remindBy = null;
             if (remindById != null && remindById != 0) {
@@ -100,7 +101,7 @@ public class CalendarReadPlatformServiceImpl implements 
CalendarReadPlatformServ
             if (startDate != null && recurrence != null) {
                 humanReadable = CalendarUtils.getRRuleReadable(startDate, 
recurrence);
             }
-
+            Integer monthOnDay = CalendarUtils.getMonthOnDay(recurrence);
             final LocalDate createdDate = JdbcSupport.getLocalDate(rs, 
"createdDate");
             final LocalDate lastUpdatedDate = JdbcSupport.getLocalDate(rs, 
"updatedDate");
             final Long createdByUserId = rs.getLong("creatingUserId");
@@ -110,9 +111,9 @@ public class CalendarReadPlatformServiceImpl implements 
CalendarReadPlatformServ
             final LocalTime meetingTime = 
JdbcSupport.getLocalTime(rs,"meetingTime");
 
             return CalendarData.instance(id, calendarInstanceId, entityId, 
entityType, title, description, location, startDate, endDate,
-                    duration, type, repeating, recurrence, frequency, 
interval, repeatsOnDay, remindBy, firstReminder, secondReminder,
+                    duration, type, repeating, recurrence, frequency, 
interval, repeatsOnDay, repeatsOnNthDayOfMonth, remindBy, firstReminder, 
secondReminder,
                     humanReadable, createdDate, lastUpdatedDate, 
createdByUserId, createdByUserName, lastUpdatedByUserId,
-                    lastUpdatedByUserName,meetingTime);
+                    lastUpdatedByUserName,meetingTime, monthOnDay);
         }
     }
 
@@ -479,6 +480,8 @@ public class CalendarReadPlatformServiceImpl implements 
CalendarReadPlatformServ
             final EnumOptionData frequency = 
CalendarEnumerations.calendarFrequencyType(CalendarUtils.getFrequency(recurrence));
             final Integer interval = new 
Integer(CalendarUtils.getInterval(recurrence));
             final EnumOptionData repeatsOnDay = 
CalendarEnumerations.calendarWeekDaysType(CalendarUtils.getRepeatsOnDay(recurrence));
+            final EnumOptionData repeatsOnNthDayOfMonth = 
CalendarEnumerations.calendarFrequencyNthDayType(CalendarUtils
+                    .getRepeatsOnNthDayOfMonth(recurrence));
             final Integer remindById = rs.getInt("remindById");
             EnumOptionData remindBy = null;
             if (remindById != null && remindById != 0) {
@@ -498,11 +501,12 @@ public class CalendarReadPlatformServiceImpl implements 
CalendarReadPlatformServ
             final Long lastUpdatedByUserId = null;
             final String lastUpdatedByUserName = null;
             final LocalTime meetingTime = null;
+            Integer monthOnDay = CalendarUtils.getMonthOnDay(recurrence);
 
             return CalendarData.instance(id, calendarInstanceId, entityId, 
entityType, title, description, location, startDate, endDate,
-                    duration, type, repeating, recurrence, frequency, 
interval, repeatsOnDay, remindBy, firstReminder, secondReminder,
-                    humanReadable, createdDate, lastUpdatedDate, 
createdByUserId, createdByUserName, lastUpdatedByUserId,
-                    lastUpdatedByUserName, meetingTime);
+                    duration, type, repeating, recurrence, frequency, 
interval, repeatsOnDay, repeatsOnNthDayOfMonth, remindBy,
+                    firstReminder, secondReminder, humanReadable, createdDate, 
lastUpdatedDate, createdByUserId, createdByUserName,
+                    lastUpdatedByUserId, lastUpdatedByUserName, meetingTime, 
monthOnDay);
         }
     }
     

Reply via email to