Merge branch 'organizationstart' into develop
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/AccountingScenarioIntegrationTest.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/AccountingScenarioIntegrationTest.java
index ef020bc..0e40d74 100644
--- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/AccountingScenarioIntegrationTest.java
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/AccountingScenarioIntegrationTest.java
@@ -521,6 +521,7 @@
         System.out.println("------------------------------CREATING NEW FIXED DEPOSIT PRODUCT ---------------------------------------");
         FixedDepositProductHelper fixedDepositProductHelper = new FixedDepositProductHelper(this.requestSpec, this.responseSpec);
         final String fixedDepositProductJSON = fixedDepositProductHelper //
+                .withPeriodRangeChart()//
                 .withAccountingRuleAsCashBased(accounts).build(validFrom, validTo);
         return FixedDepositProductHelper.createFixedDepositProduct(fixedDepositProductJSON, requestSpec, responseSpec);
     }
@@ -529,7 +530,7 @@
             final String validTo, final String submittedOnDate, final String penalInterestType) {
         System.out.println("--------------------------------APPLYING FOR FIXED DEPOSIT ACCOUNT --------------------------------");
         final String fixedDepositApplicationJSON = new FixedDepositAccountHelper(this.requestSpec, this.responseSpec) //
-                .withSubmittedOnDate(submittedOnDate).build(clientID, productID, validFrom, validTo, penalInterestType);
+                .withSubmittedOnDate(submittedOnDate).build(clientID, productID, penalInterestType);
         return this.fixedDepositAccountHelper
                 .applyFixedDepositApplication(fixedDepositApplicationJSON, this.requestSpec, this.responseSpec);
     }
@@ -538,6 +539,7 @@
         System.out.println("------------------------------CREATING NEW RECURRING DEPOSIT PRODUCT ---------------------------------------");
         RecurringDepositProductHelper recurringDepositProductHelper = new RecurringDepositProductHelper(this.requestSpec, this.responseSpec);
         final String recurringDepositProductJSON = recurringDepositProductHelper //
+                .withPeriodRangeChart()//
                 .withAccountingRuleAsCashBased(accounts).build(validFrom, validTo);
         return RecurringDepositProductHelper.createRecurringDepositProduct(recurringDepositProductJSON, requestSpec, responseSpec);
     }
@@ -548,7 +550,7 @@
         final String recurringDepositApplicationJSON = new RecurringDepositAccountHelper(this.requestSpec, this.responseSpec)
                 //
                 .withSubmittedOnDate(submittedOnDate).withExpectedFirstDepositOnDate(expectedFirstDepositOnDate)
-                .build(clientID, productID, validFrom, validTo, penalInterestType);
+                .build(clientID, productID, penalInterestType);
         return this.recurringDepositAccountHelper.applyRecurringDepositApplication(recurringDepositApplicationJSON, this.requestSpec,
                 this.responseSpec);
     }
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/FixedDepositTest.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/FixedDepositTest.java
index 3d6a4ef..fa638bc 100644
--- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/FixedDepositTest.java
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/FixedDepositTest.java
@@ -114,8 +114,8 @@
     }
 
     /***
-     * Test case for Fixed Deposit Account premature closure with
-     * transaction type withdrawal and Cash Based accounting enabled
+     * Test case for Fixed Deposit Account premature closure with transaction
+     * type withdrawal and Cash Based accounting enabled
      */
     @Test
     public void testFixedDepositAccountWithPrematureClosureTypeWithdrawal() {
@@ -123,7 +123,7 @@
         this.accountHelper = new AccountHelper(this.requestSpec, this.responseSpec);
         this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec);
         this.fixedDepositAccountHelper = new FixedDepositAccountHelper(this.requestSpec, this.responseSpec);
-        
+
         /***
          * Create GL Accounts for product account mapping
          */
@@ -170,8 +170,8 @@
         /***
          * Apply for FD account with created product and verify status
          */
-        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), VALID_FROM,
-                VALID_TO, SUBMITTED_ON_DATE, WHOLE_TERM);
+        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), SUBMITTED_ON_DATE,
+                WHOLE_TERM);
         Assert.assertNotNull(fixedDepositAccountId);
 
         HashMap fixedDepositAccountStatusHashMap = FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec,
@@ -189,11 +189,11 @@
          */
         fixedDepositAccountStatusHashMap = this.fixedDepositAccountHelper.activateFixedDeposit(fixedDepositAccountId, ACTIVATION_DATE);
         FixedDepositAccountStatusChecker.verifyFixedDepositIsActive(fixedDepositAccountStatusHashMap);
-        
+
         HashMap accountSummary = this.fixedDepositAccountHelper.getFixedDepositSummary(fixedDepositAccountId);
 
         Float depositAmount = (Float) accountSummary.get("totalDeposits");
-        
+
         /***
          * Verify journal entries posted for initial deposit transaction which
          * happened at activation time
@@ -214,7 +214,7 @@
          */
         Integer transactionIdForPostInterest = this.fixedDepositAccountHelper.postInterestForFixedDeposit(fixedDepositAccountId);
         Assert.assertNotNull(transactionIdForPostInterest);
-        
+
         accountSummary = this.fixedDepositAccountHelper.getFixedDepositSummary(fixedDepositAccountId);
         Float totalInterestPosted = (Float) accountSummary.get("totalInterestPosted");
 
@@ -252,6 +252,165 @@
                 JournalEntry.TransactionType.DEBIT));
 
     }
+    
+    @Test
+    public void testFixedDepositAccountWithPeriodInterestRateChart() {
+        final String chartToUse = "period";
+        final String depositAmount = "10000";
+        final String depositPeriod = "12";
+        final Float interestRate = new Float(6.0);
+        testFixedDepositAccountForInterestRate(chartToUse, depositAmount, depositPeriod, interestRate);
+    }
+    
+    @Test
+    public void testFixedDepositAccountWithPeriodInterestRateChart_AMOUNT_VARIATION() {
+        final String chartToUse = "period";
+        final String depositAmount = "2000";
+        final String depositPeriod = "12";
+        final Float interestRate = new Float(6.0);
+        testFixedDepositAccountForInterestRate(chartToUse, depositAmount, depositPeriod, interestRate);
+    }
+    
+    @Test
+    public void testFixedDepositAccountWithPeriodInterestRateChart_PERIOD_VARIATION() {
+        final String chartToUse = "period";
+        final String depositAmount = "10000";
+        final String depositPeriod = "18";
+        final Float interestRate = new Float(7.0);
+        testFixedDepositAccountForInterestRate(chartToUse, depositAmount, depositPeriod, interestRate);
+    }
+    
+    @Test
+    public void testFixedDepositAccountWithAmountInterestRateChart() {
+        final String chartToUse = "amount";
+        final String depositAmount = "10000";
+        final String depositPeriod = "12";
+        final Float interestRate = new Float(7.0);
+        testFixedDepositAccountForInterestRate(chartToUse, depositAmount, depositPeriod, interestRate);
+    }
+    
+    @Test
+    public void testFixedDepositAccountWithAmountInterestRateChart_AMOUNT_VARIATION() {
+        final String chartToUse = "amount";
+        final String depositAmount = "5000";
+        final String depositPeriod = "12";
+        final Float interestRate = new Float(5.0);
+        testFixedDepositAccountForInterestRate(chartToUse, depositAmount, depositPeriod, interestRate);
+    }
+    
+    @Test
+    public void testFixedDepositAccountWithAmountInterestRateChart_PERIOD_VARIATION() {
+        final String chartToUse = "amount";
+        final String depositAmount = "10000";
+        final String depositPeriod = "26";
+        final Float interestRate = new Float(7.0);
+        testFixedDepositAccountForInterestRate(chartToUse, depositAmount, depositPeriod, interestRate);
+    }
+
+    @Test
+    public void testFixedDepositAccountWithPeriodAndAmountInterestRateChart() {
+        final String chartToUse = "period_amount";
+        final String depositAmount = "10000";
+        final String depositPeriod = "12";
+        final Float interestRate = new Float(7.0);
+        testFixedDepositAccountForInterestRate(chartToUse, depositAmount, depositPeriod, interestRate);
+    }
+    
+    @Test
+    public void testFixedDepositAccountWithPeriodAndAmountInterestRateChart_AMOUNT_VARIATION() {
+        final String chartToUse = "period_amount";
+        final String depositAmount = "5000";
+        final String depositPeriod = "12";
+        final Float interestRate = new Float(6.0);
+        testFixedDepositAccountForInterestRate(chartToUse, depositAmount, depositPeriod, interestRate);
+    }
+    
+    @Test
+    public void testFixedDepositAccountWithPeriodAndAmountInterestRateChart_PERIOD_VARIATION() {
+        final String chartToUse = "period_amount";
+        final String depositAmount = "10000";
+        final String depositPeriod = "20";
+        final Float interestRate = new Float(9.0);
+        testFixedDepositAccountForInterestRate(chartToUse, depositAmount, depositPeriod, interestRate);
+    }
+    
+    @Test
+    public void testFixedDepositAccountWithAmountAndPeriodInterestRateChart() {
+        final String chartToUse = "amount_period";
+        final String depositAmount = "10000";
+        final String depositPeriod = "12";
+        final Float interestRate = new Float(8.0);
+        testFixedDepositAccountForInterestRate(chartToUse, depositAmount, depositPeriod, interestRate);
+    }
+    
+    @Test
+    public void testFixedDepositAccountWithAmountAndPeriodInterestRateChart_AMOUNT_VARIATION() {
+        final String chartToUse = "amount_period";
+        final String depositAmount = "5000";
+        final String depositPeriod = "12";
+        final Float interestRate = new Float(6.0);
+        testFixedDepositAccountForInterestRate(chartToUse, depositAmount, depositPeriod, interestRate);
+    }
+    
+    @Test
+    public void testFixedDepositAccountWithAmountAndPeriodInterestRateChart_PERIOD_VARIATION() {
+        final String chartToUse = "amount_period";
+        final String depositAmount = "10000";
+        final String depositPeriod = "6";
+        final Float interestRate = new Float(7.0);
+        testFixedDepositAccountForInterestRate(chartToUse, depositAmount, depositPeriod, interestRate);
+    }
+
+    private void testFixedDepositAccountForInterestRate(final String chartToUse, final String depositAmount, final String depositPeriod,
+            final Float interestRate) {
+        this.fixedDepositProductHelper = new FixedDepositProductHelper(this.requestSpec, this.responseSpec);
+        this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec);
+        this.fixedDepositAccountHelper = new FixedDepositAccountHelper(this.requestSpec, this.responseSpec);
+
+        final String VALID_FROM = "01 March 2014";
+        final String VALID_TO = "01 March 2016";
+
+        final String SUBMITTED_ON_DATE = "01 March 2015";
+        final String APPROVED_ON_DATE = "01 March 2015";
+        final String ACTIVATION_DATE = "01 March 2015";
+
+        Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec);
+        Assert.assertNotNull(clientId);
+
+        /***
+         * Create FD product with CashBased accounting enabled
+         */
+        final String accountingRule = NONE;
+        Integer fixedDepositProductId = createFixedDepositProduct(VALID_FROM, VALID_TO, accountingRule, chartToUse);
+        Assert.assertNotNull(fixedDepositProductId);
+
+        /***
+         * Apply for FD account with created product and verify status
+         */
+        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), SUBMITTED_ON_DATE,
+                WHOLE_TERM, depositAmount, depositPeriod);
+        Assert.assertNotNull(fixedDepositAccountId);
+
+        HashMap fixedDepositAccountStatusHashMap = FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec,
+                this.responseSpec, fixedDepositAccountId.toString());
+        FixedDepositAccountStatusChecker.verifyFixedDepositIsPending(fixedDepositAccountStatusHashMap);
+
+        /***
+         * Approve the FD account and verify whether account is approved
+         */
+        fixedDepositAccountStatusHashMap = this.fixedDepositAccountHelper.approveFixedDeposit(fixedDepositAccountId, APPROVED_ON_DATE);
+        FixedDepositAccountStatusChecker.verifyFixedDepositIsApproved(fixedDepositAccountStatusHashMap);
+
+        /***
+         * Activate the FD Account and verify whether account is activated
+         */
+        fixedDepositAccountStatusHashMap = this.fixedDepositAccountHelper.activateFixedDeposit(fixedDepositAccountId, ACTIVATION_DATE);
+        FixedDepositAccountStatusChecker.verifyFixedDepositIsActive(fixedDepositAccountStatusHashMap);
+
+        HashMap accountSummary = this.fixedDepositAccountHelper.getFixedDepositDetails(fixedDepositAccountId);
+
+        Assert.assertEquals(interestRate, accountSummary.get("nominalAnnualInterestRate"));
+    }
 
     /***
      * Test case for FD Account premature closure with transaction transfers to
@@ -263,7 +422,7 @@
         this.accountHelper = new AccountHelper(this.requestSpec, this.responseSpec);
         this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec);
         this.fixedDepositAccountHelper = new FixedDepositAccountHelper(this.requestSpec, this.responseSpec);
-        
+
         /***
          * Create GL Accounts for product account mapping
          */
@@ -295,7 +454,7 @@
         todaysDate.add(Calendar.DATE, numberOfDaysLeft);
         final String INTEREST_POSTED_DATE = dateFormat.format(todaysDate.getTime());
         final String CLOSED_ON_DATE = dateFormat.format(Calendar.getInstance().getTime());
-        
+
         Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec);
         Assert.assertNotNull(clientId);
 
@@ -326,8 +485,8 @@
                 incomeAccount, expenseAccount);
         Assert.assertNotNull(fixedDepositProductId);
 
-        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), VALID_FROM,
-                VALID_TO, SUBMITTED_ON_DATE, WHOLE_TERM);
+        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), SUBMITTED_ON_DATE,
+                WHOLE_TERM);
         Assert.assertNotNull(fixedDepositAccountId);
 
         HashMap fixedDepositAccountStatusHashMap = FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec,
@@ -343,7 +502,7 @@
         HashMap accountSummary = this.fixedDepositAccountHelper.getFixedDepositSummary(fixedDepositAccountId);
 
         Float depositAmount = (Float) accountSummary.get("totalDeposits");
-        
+
         /***
          * Verify journal entries posted for initial deposit transaction which
          * happened at activation time
@@ -375,10 +534,10 @@
         final JournalEntry[] liablilityAccountEntry = { new JournalEntry(totalInterestPosted, JournalEntry.TransactionType.CREDIT) };
         this.journalEntryHelper.checkJournalEntryForAssetAccount(expenseAccount, INTEREST_POSTED_DATE, expenseAccountEntry);
         this.journalEntryHelper.checkJournalEntryForLiabilityAccount(liabilityAccount, INTEREST_POSTED_DATE, liablilityAccountEntry);
-        
+
         HashMap savingsSummaryBefore = this.savingsAccountHelper.getSavingsSummary(savingsId);
         Float balanceBefore = (Float) savingsSummaryBefore.get("accountBalance");
-        
+
         /***
          * Retrieve mapped financial account for liability transfer
          */
@@ -412,7 +571,7 @@
 
         this.journalEntryHelper.checkJournalEntryForAssetAccount(financialAccount, CLOSED_ON_DATE, new JournalEntry(prematurityAmount,
                 JournalEntry.TransactionType.DEBIT), new JournalEntry(prematurityAmount, JournalEntry.TransactionType.CREDIT));
-        
+
         HashMap savingsSummaryAfter = this.savingsAccountHelper.getSavingsSummary(savingsId);
         Float balanceAfter = (Float) savingsSummaryAfter.get("accountBalance");
         Float expectedSavingsBalance = balanceBefore + prematurityAmount;
@@ -422,8 +581,8 @@
     }
 
     /***
-     * Test case for Fixed Deposit Account premature closure with
-     * transaction type ReInvest and Cash Based accounting enabled
+     * Test case for Fixed Deposit Account premature closure with transaction
+     * type ReInvest and Cash Based accounting enabled
      */
     @Test
     public void testFixedDepositAccountWithPrematureClosureTypeReinvest() {
@@ -459,7 +618,7 @@
         final String APPROVED_ON_DATE = dateFormat.format(todaysDate.getTime());
         final String ACTIVATION_DATE = dateFormat.format(todaysDate.getTime());
         final String MONTH_DAY = monthDayFormat.format(todaysDate.getTime());
-        
+
         Integer currentDate = new Integer(currentDateFormat.format(todaysDate.getTime()));
         Integer daysInMonth = todaysDate.getActualMaximum(Calendar.DATE);
         Integer numberOfDaysLeft = (daysInMonth - currentDate) + 1;
@@ -478,8 +637,8 @@
                 incomeAccount, expenseAccount);
         Assert.assertNotNull(fixedDepositProductId);
 
-        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), VALID_FROM,
-                VALID_TO, SUBMITTED_ON_DATE, WHOLE_TERM);
+        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), SUBMITTED_ON_DATE,
+                WHOLE_TERM);
         Assert.assertNotNull(fixedDepositAccountId);
 
         HashMap fixedDepositAccountStatusHashMap = FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec,
@@ -491,11 +650,11 @@
 
         fixedDepositAccountStatusHashMap = this.fixedDepositAccountHelper.activateFixedDeposit(fixedDepositAccountId, ACTIVATION_DATE);
         FixedDepositAccountStatusChecker.verifyFixedDepositIsActive(fixedDepositAccountStatusHashMap);
-        
+
         HashMap accountSummary = this.fixedDepositAccountHelper.getFixedDepositSummary(fixedDepositAccountId);
 
         Float depositAmount = (Float) accountSummary.get("totalDeposits");
-        
+
         /***
          * Verify journal entries posted for initial deposit transaction which
          * happened at activation time
@@ -564,8 +723,8 @@
         HashMap fixedDepositProductData = this.fixedDepositProductHelper.retrieveFixedDepositProductById(this.requestSpec,
                 this.responseSpec, fixedDepositProductId.toString());
 
-        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), VALID_FROM,
-                VALID_TO, SUBMITTED_ON_DATE, WHOLE_TERM);
+        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), SUBMITTED_ON_DATE,
+                WHOLE_TERM);
         Assert.assertNotNull(fixedDepositAccountId);
 
         todaysDate.add(Calendar.DATE, -1);
@@ -603,8 +762,8 @@
         Integer fixedDepositProductId = createFixedDepositProduct(VALID_FROM, VALID_TO, accountingRule);
         Assert.assertNotNull(fixedDepositProductId);
 
-        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), VALID_FROM,
-                VALID_TO, SUBMITTED_ON_DATE, WHOLE_TERM);
+        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), SUBMITTED_ON_DATE,
+                WHOLE_TERM);
         Assert.assertNotNull(fixedDepositAccountId);
 
         HashMap fixedDepositAccountStatusHashMap = FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec,
@@ -646,8 +805,8 @@
         Integer fixedDepositProductId = createFixedDepositProduct(VALID_FROM, VALID_TO, accountingRule);
         Assert.assertNotNull(fixedDepositProductId);
 
-        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), VALID_FROM,
-                VALID_TO, SUBMITTED_ON_DATE, WHOLE_TERM);
+        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), SUBMITTED_ON_DATE,
+                WHOLE_TERM);
         Assert.assertNotNull(fixedDepositAccountId);
 
         HashMap fixedDepositAccountStatusHashMap = FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec,
@@ -687,8 +846,8 @@
         Integer fixedDepositProductId = createFixedDepositProduct(VALID_FROM, VALID_TO, accountingRule);
         Assert.assertNotNull(fixedDepositProductId);
 
-        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), VALID_FROM,
-                VALID_TO, SUBMITTED_ON_DATE, WHOLE_TERM);
+        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), SUBMITTED_ON_DATE,
+                WHOLE_TERM);
         Assert.assertNotNull(fixedDepositAccountId);
 
         HashMap fixedDepositAccountStatusHashMap = FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec,
@@ -726,8 +885,8 @@
         Integer fixedDepositProductId = createFixedDepositProduct(VALID_FROM, VALID_TO, accountingRule);
         Assert.assertNotNull(fixedDepositProductId);
 
-        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), VALID_FROM,
-                VALID_TO, SUBMITTED_ON_DATE, WHOLE_TERM);
+        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), SUBMITTED_ON_DATE,
+                WHOLE_TERM);
         Assert.assertNotNull(fixedDepositAccountId);
 
         HashMap fixedDepositAccountStatusHashMap = FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec,
@@ -769,8 +928,8 @@
         Integer fixedDepositProductId = createFixedDepositProduct(VALID_FROM, VALID_TO, accountingRule);
         Assert.assertNotNull(fixedDepositProductId);
 
-        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), VALID_FROM,
-                VALID_TO, SUBMITTED_ON_DATE, WHOLE_TERM);
+        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), SUBMITTED_ON_DATE,
+                WHOLE_TERM);
         Assert.assertNotNull(fixedDepositAccountId);
 
         HashMap fixedDepositAccountStatusHashMap = FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec,
@@ -839,8 +998,8 @@
         Integer fixedDepositProductId = createFixedDepositProduct(VALID_FROM, VALID_TO, accountingRule);
         Assert.assertNotNull(fixedDepositProductId);
 
-        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), VALID_FROM,
-                VALID_TO, SUBMITTED_ON_DATE, WHOLE_TERM);
+        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), SUBMITTED_ON_DATE,
+                WHOLE_TERM);
         Assert.assertNotNull(fixedDepositAccountId);
 
         HashMap modificationsHashMap = this.fixedDepositAccountHelper.updateInterestCalculationConfigForFixedDeposit(clientId.toString(),
@@ -916,8 +1075,8 @@
         Integer fixedDepositProductId = createFixedDepositProduct(VALID_FROM, VALID_TO, accountingRule);
         Assert.assertNotNull(fixedDepositProductId);
 
-        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), VALID_FROM,
-                VALID_TO, SUBMITTED_ON_DATE, WHOLE_TERM);
+        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), SUBMITTED_ON_DATE,
+                WHOLE_TERM);
         Assert.assertNotNull(fixedDepositAccountId);
 
         HashMap fixedDepositAccountStatusHashMap = FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec,
@@ -1020,8 +1179,8 @@
         Integer fixedDepositProductId = createFixedDepositProduct(VALID_FROM, VALID_TO, accountingRule);
         Assert.assertNotNull(fixedDepositProductId);
 
-        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), VALID_FROM,
-                VALID_TO, SUBMITTED_ON_DATE, WHOLE_TERM);
+        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), SUBMITTED_ON_DATE,
+                WHOLE_TERM);
         Assert.assertNotNull(fixedDepositAccountId);
 
         HashMap modificationsHashMap = this.fixedDepositAccountHelper.updateInterestCalculationConfigForFixedDeposit(clientId.toString(),
@@ -1128,8 +1287,8 @@
         Integer fixedDepositProductId = createFixedDepositProduct(VALID_FROM, VALID_TO, accountingRule);
         Assert.assertNotNull(fixedDepositProductId);
 
-        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), VALID_FROM,
-                VALID_TO, SUBMITTED_ON_DATE, TILL_PREMATURE_WITHDRAWAL);
+        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), SUBMITTED_ON_DATE,
+                TILL_PREMATURE_WITHDRAWAL);
         Assert.assertNotNull(fixedDepositAccountId);
 
         HashMap fixedDepositAccountStatusHashMap = FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec,
@@ -1240,8 +1399,8 @@
         Integer fixedDepositProductId = createFixedDepositProduct(VALID_FROM, VALID_TO, accountingRule);
         Assert.assertNotNull(fixedDepositProductId);
 
-        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), VALID_FROM,
-                VALID_TO, SUBMITTED_ON_DATE, TILL_PREMATURE_WITHDRAWAL);
+        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), SUBMITTED_ON_DATE,
+                TILL_PREMATURE_WITHDRAWAL);
         Assert.assertNotNull(fixedDepositAccountId);
 
         HashMap modificationsHashMap = this.fixedDepositAccountHelper.updateInterestCalculationConfigForFixedDeposit(clientId.toString(),
@@ -1352,8 +1511,8 @@
         Integer fixedDepositProductId = createFixedDepositProduct(VALID_FROM, VALID_TO, accountingRule);
         Assert.assertNotNull(fixedDepositProductId);
 
-        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), VALID_FROM,
-                VALID_TO, SUBMITTED_ON_DATE, WHOLE_TERM);
+        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), SUBMITTED_ON_DATE,
+                WHOLE_TERM);
         Assert.assertNotNull(fixedDepositAccountId);
 
         HashMap modificationsHashMap = this.fixedDepositAccountHelper.updateInterestCalculationConfigForFixedDeposit(clientId.toString(),
@@ -1421,7 +1580,7 @@
         final String ACTIVATION_DATE = dateFormat.format(todaysDate.getTime());
         final String MONTH_DAY = monthDayFormat.format(todaysDate.getTime());
 
-        System.out.println("Submitted Date:"+SUBMITTED_ON_DATE);
+        System.out.println("Submitted Date:" + SUBMITTED_ON_DATE);
         Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec);
         Assert.assertNotNull(clientId);
 
@@ -1429,8 +1588,8 @@
         Integer fixedDepositProductId = createFixedDepositProduct(VALID_FROM, VALID_TO, accountingRule);
         Assert.assertNotNull(fixedDepositProductId);
 
-        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), VALID_FROM,
-                VALID_TO, SUBMITTED_ON_DATE, WHOLE_TERM);
+        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), SUBMITTED_ON_DATE,
+                WHOLE_TERM);
         Assert.assertNotNull(fixedDepositAccountId);
 
         HashMap modificationsHashMap = this.fixedDepositAccountHelper.updateInterestCalculationConfigForFixedDeposit(clientId.toString(),
@@ -1509,8 +1668,8 @@
         Integer fixedDepositProductId = createFixedDepositProduct(VALID_FROM, VALID_TO, accountingRule);
         Assert.assertNotNull(fixedDepositProductId);
 
-        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), VALID_FROM,
-                VALID_TO, SUBMITTED_ON_DATE, WHOLE_TERM);
+        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), SUBMITTED_ON_DATE,
+                WHOLE_TERM);
         Assert.assertNotNull(fixedDepositAccountId);
 
         HashMap modificationsHashMap = this.fixedDepositAccountHelper.updateInterestCalculationConfigForFixedDeposit(clientId.toString(),
@@ -1593,8 +1752,8 @@
         Integer fixedDepositProductId = createFixedDepositProduct(VALID_FROM, VALID_TO, accountingRule);
         Assert.assertNotNull(fixedDepositProductId);
 
-        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), VALID_FROM,
-                VALID_TO, SUBMITTED_ON_DATE, WHOLE_TERM);
+        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), SUBMITTED_ON_DATE,
+                WHOLE_TERM);
         Assert.assertNotNull(fixedDepositAccountId);
 
         HashMap modificationsHashMap = this.fixedDepositAccountHelper.updateInterestCalculationConfigForFixedDeposit(clientId.toString(),
@@ -1678,8 +1837,8 @@
         Integer fixedDepositProductId = createFixedDepositProduct(VALID_FROM, VALID_TO, accountingRule);
         Assert.assertNotNull(fixedDepositProductId);
 
-        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), VALID_FROM,
-                VALID_TO, SUBMITTED_ON_DATE, WHOLE_TERM);
+        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), SUBMITTED_ON_DATE,
+                WHOLE_TERM);
         Assert.assertNotNull(fixedDepositAccountId);
 
         HashMap modificationsHashMap = this.fixedDepositAccountHelper.updateInterestCalculationConfigForFixedDeposit(clientId.toString(),
@@ -1760,8 +1919,8 @@
         Integer fixedDepositProductId = createFixedDepositProduct(VALID_FROM, VALID_TO, accountingRule);
         Assert.assertNotNull(fixedDepositProductId);
 
-        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), VALID_FROM,
-                VALID_TO, SUBMITTED_ON_DATE, WHOLE_TERM);
+        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), SUBMITTED_ON_DATE,
+                WHOLE_TERM);
         Assert.assertNotNull(fixedDepositAccountId);
 
         HashMap modificationsHashMap = this.fixedDepositAccountHelper.updateInterestCalculationConfigForFixedDeposit(clientId.toString(),
@@ -1842,8 +2001,8 @@
         Integer fixedDepositProductId = createFixedDepositProduct(VALID_FROM, VALID_TO, accountingRule);
         Assert.assertNotNull(fixedDepositProductId);
 
-        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), VALID_FROM,
-                VALID_TO, SUBMITTED_ON_DATE, WHOLE_TERM);
+        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), SUBMITTED_ON_DATE,
+                WHOLE_TERM);
         Assert.assertNotNull(fixedDepositAccountId);
 
         HashMap modificationsHashMap = this.fixedDepositAccountHelper.updateInterestCalculationConfigForFixedDeposit(clientId.toString(),
@@ -1923,8 +2082,8 @@
         Integer fixedDepositProductId = createFixedDepositProduct(VALID_FROM, VALID_TO, accountingRule);
         Assert.assertNotNull(fixedDepositProductId);
 
-        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), VALID_FROM,
-                VALID_TO, SUBMITTED_ON_DATE, WHOLE_TERM);
+        Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), SUBMITTED_ON_DATE,
+                WHOLE_TERM);
         Assert.assertNotNull(fixedDepositAccountId);
 
         HashMap modificationsHashMap = this.fixedDepositAccountHelper.updateInterestCalculationConfigForFixedDeposit(clientId.toString(),
@@ -1975,16 +2134,58 @@
         } else if (accountingRule.equals(NONE)) {
             fixedDepositProductHelper = fixedDepositProductHelper.withAccountingRuleAsNone();
         }
+        final String fixedDepositProductJSON = fixedDepositProductHelper.withPeriodRangeChart() //
+                .build(validFrom, validTo);
+        return FixedDepositProductHelper.createFixedDepositProduct(fixedDepositProductJSON, requestSpec, responseSpec);
+    }
+
+    private Integer createFixedDepositProduct(final String validFrom, final String validTo, final String accountingRule,
+            final String chartToBePicked, Account... accounts) {
+        System.out.println("------------------------------CREATING NEW FIXED DEPOSIT PRODUCT ---------------------------------------");
+        FixedDepositProductHelper fixedDepositProductHelper = new FixedDepositProductHelper(this.requestSpec, this.responseSpec);
+        if (accountingRule.equals(CASH_BASED)) {
+            fixedDepositProductHelper = fixedDepositProductHelper.withAccountingRuleAsCashBased(accounts);
+        } else if (accountingRule.equals(NONE)) {
+            fixedDepositProductHelper = fixedDepositProductHelper.withAccountingRuleAsNone();
+        }
+        switch (chartToBePicked) {
+            case "period":
+                fixedDepositProductHelper = fixedDepositProductHelper.withPeriodRangeChart();
+            break;
+            case "amount":
+                fixedDepositProductHelper = fixedDepositProductHelper.withAmountRangeChart();
+            break;
+            case "period_amount":
+                fixedDepositProductHelper = fixedDepositProductHelper.withPeriodAndAmountRangeChart();
+            break;
+            case "amount_period":
+                fixedDepositProductHelper = fixedDepositProductHelper.withAmountAndPeriodRangeChart();
+            break;
+            default:
+            break;
+        }
+
         final String fixedDepositProductJSON = fixedDepositProductHelper //
                 .build(validFrom, validTo);
         return FixedDepositProductHelper.createFixedDepositProduct(fixedDepositProductJSON, requestSpec, responseSpec);
     }
 
-    private Integer applyForFixedDepositApplication(final String clientID, final String productID, final String validFrom,
-            final String validTo, final String submittedOnDate, final String penalInterestType) {
+    private Integer applyForFixedDepositApplication(final String clientID, final String productID, final String submittedOnDate,
+            final String penalInterestType) {
         System.out.println("--------------------------------APPLYING FOR FIXED DEPOSIT ACCOUNT --------------------------------");
         final String fixedDepositApplicationJSON = new FixedDepositAccountHelper(this.requestSpec, this.responseSpec) //
-                .withSubmittedOnDate(submittedOnDate).build(clientID, productID, validFrom, validTo, penalInterestType);
+                .withSubmittedOnDate(submittedOnDate).build(clientID, productID, penalInterestType);
+        return this.fixedDepositAccountHelper
+                .applyFixedDepositApplication(fixedDepositApplicationJSON, this.requestSpec, this.responseSpec);
+    }
+
+    private Integer applyForFixedDepositApplication(final String clientID, final String productID, final String submittedOnDate,
+            final String penalInterestType, final String depositAmount, final String depositPeriod) {
+        System.out.println("--------------------------------APPLYING FOR FIXED DEPOSIT ACCOUNT --------------------------------");
+        final String fixedDepositApplicationJSON = new FixedDepositAccountHelper(this.requestSpec, this.responseSpec)
+                //
+                .withSubmittedOnDate(submittedOnDate).withDepositPeriod(depositPeriod).withDepositAmount(depositAmount)
+                .build(clientID, productID, penalInterestType);
         return this.fixedDepositAccountHelper
                 .applyFixedDepositApplication(fixedDepositApplicationJSON, this.requestSpec, this.responseSpec);
     }
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/RecurringDepositTest.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/RecurringDepositTest.java
index b9fd152..1d52aec 100644
--- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/RecurringDepositTest.java
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/RecurringDepositTest.java
@@ -2496,6 +2496,169 @@
 
     }
 
+    @Test
+    public void testRecurringDepositAccountWithPeriodInterestRateChart() {
+        final String chartToUse = "period";
+        final String depositAmount = "1000";
+        final String depositPeriod = "12";
+        final Float interestRate = new Float(6.0);
+        testFixedDepositAccountForInterestRate(chartToUse, depositAmount, depositPeriod, interestRate);
+    }
+    
+    @Test
+    public void testRecurringDepositAccountWithPeriodInterestRateChart_AMOUNT_VARIATION() {
+        final String chartToUse = "period";
+        final String depositAmount = "10000";
+        final String depositPeriod = "12";
+        final Float interestRate = new Float(6.0);
+        testFixedDepositAccountForInterestRate(chartToUse, depositAmount, depositPeriod, interestRate);
+    }
+    
+    @Test
+    public void testRecurringDepositAccountWithPeriodInterestRateChart_PERIOD_VARIATION() {
+        final String chartToUse = "period";
+        final String depositAmount = "1000";
+        final String depositPeriod = "18";
+        final Float interestRate = new Float(7.0);
+        testFixedDepositAccountForInterestRate(chartToUse, depositAmount, depositPeriod, interestRate);
+    }
+    
+    @Test
+    public void testRecurringDepositAccountWithAmountInterestRateChart() {
+        final String chartToUse = "amount";
+        final String depositAmount = "1000";
+        final String depositPeriod = "12";
+        final Float interestRate = new Float(8.0);
+        testFixedDepositAccountForInterestRate(chartToUse, depositAmount, depositPeriod, interestRate);
+    }
+    
+    @Test
+    public void testRecurringDepositAccountWithAmountInterestRateChart_AMOUNT_VARIATION() {
+        final String chartToUse = "amount";
+        final String depositAmount = "500";
+        final String depositPeriod = "12";
+        final Float interestRate = new Float(7.0);
+        testFixedDepositAccountForInterestRate(chartToUse, depositAmount, depositPeriod, interestRate);
+    }
+    
+    @Test
+    public void testRecurringDepositAccountWithAmountInterestRateChart_PERIOD_VARIATION() {
+        final String chartToUse = "amount";
+        final String depositAmount = "500";
+        final String depositPeriod = "10";
+        final Float interestRate = new Float(5.0);
+        testFixedDepositAccountForInterestRate(chartToUse, depositAmount, depositPeriod, interestRate);
+    }
+    
+    @Test
+    public void testRecurringDepositAccountWithPeriodAndAmountInterestRateChart() {
+        final String chartToUse = "period_amount";
+        final String depositAmount = "1000";
+        final String depositPeriod = "12";
+        final Float interestRate = new Float(7.0);
+        testFixedDepositAccountForInterestRate(chartToUse, depositAmount, depositPeriod, interestRate);
+    }
+    
+    @Test
+    public void testRecurringDepositAccountWithPeriodAndAmountInterestRateChart_AMOUNT_VARIATION() {
+        final String chartToUse = "period_amount";
+        final String depositAmount = "400";
+        final String depositPeriod = "12";
+        final Float interestRate = new Float(6.0);
+        testFixedDepositAccountForInterestRate(chartToUse, depositAmount, depositPeriod, interestRate);
+    }
+    
+    @Test
+    public void testRecurringDepositAccountWithPeriodAndAmountInterestRateChart_PERIOD_VARIATION() {
+        final String chartToUse = "period_amount";
+        final String depositAmount = "1000";
+        final String depositPeriod = "14";
+        final Float interestRate = new Float(8.0);
+        testFixedDepositAccountForInterestRate(chartToUse, depositAmount, depositPeriod, interestRate);
+    }
+    
+    @Test
+    public void testRecurringDepositAccountWithAmountAndPeriodInterestRateChart() {
+        final String chartToUse = "amount_period";
+        final String depositAmount = "1000";
+        final String depositPeriod = "12";
+        final Float interestRate = new Float(8.0);
+        testFixedDepositAccountForInterestRate(chartToUse, depositAmount, depositPeriod, interestRate);
+    }
+    
+    @Test
+    public void testRecurringDepositAccountWithAmountAndPeriodInterestRateChart_AMOUNT_VARIATION() {
+        final String chartToUse = "amount_period";
+        final String depositAmount = "100";
+        final String depositPeriod = "12";
+        final Float interestRate = new Float(6.0);
+        testFixedDepositAccountForInterestRate(chartToUse, depositAmount, depositPeriod, interestRate);
+    }
+    
+    @Test
+    public void testRecurringDepositAccountWithAmountAndPeriodInterestRateChart_PERIOD_VARIATION() {
+        final String chartToUse = "amount_period";
+        final String depositAmount = "1000";
+        final String depositPeriod = "6";
+        final Float interestRate = new Float(7.0);
+        testFixedDepositAccountForInterestRate(chartToUse, depositAmount, depositPeriod, interestRate);
+    }
+
+    private void testFixedDepositAccountForInterestRate(final String chartToUse, final String depositAmount, final String depositPeriod,
+            final Float interestRate) {
+        this.recurringDepositProductHelper = new RecurringDepositProductHelper(this.requestSpec, this.responseSpec);
+        this.accountHelper = new AccountHelper(this.requestSpec, this.responseSpec);
+        this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec);
+        this.recurringDepositAccountHelper = new RecurringDepositAccountHelper(this.requestSpec, this.responseSpec);
+
+        final String VALID_FROM = "01 March 2014";
+        final String VALID_TO = "01 March 2016";
+
+        final String SUBMITTED_ON_DATE = "01 March 2015";
+        final String APPROVED_ON_DATE = "01 March 2015";
+        final String ACTIVATION_DATE = "01 March 2015";
+
+        Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec);
+        Assert.assertNotNull(clientId);
+
+        /***
+         * Create FD product with CashBased accounting enabled
+         */
+        final String accountingRule = NONE;
+        Integer recurringDepositProductId = createRecurringDepositProduct(VALID_FROM, VALID_TO, accountingRule, chartToUse);
+        Assert.assertNotNull(recurringDepositProductId);
+
+        /***
+         * Apply for FD account with created product and verify status
+         */
+        Integer recurringDepositAccountId = applyForRecurringDepositApplication(clientId.toString(), recurringDepositProductId.toString(),
+                VALID_FROM, VALID_TO, SUBMITTED_ON_DATE, WHOLE_TERM, SUBMITTED_ON_DATE, depositAmount, depositPeriod);
+        Assert.assertNotNull(recurringDepositAccountId);
+
+        HashMap recurringDepositAccountStatusHashMap = RecurringDepositAccountStatusChecker.getStatusOfRecurringDepositAccount(
+                this.requestSpec, this.responseSpec, recurringDepositAccountId.toString());
+        RecurringDepositAccountStatusChecker.verifyRecurringDepositIsPending(recurringDepositAccountStatusHashMap);
+
+        /***
+         * Approve the RD account and verify whether account is approved
+         */
+        recurringDepositAccountStatusHashMap = this.recurringDepositAccountHelper.approveRecurringDeposit(recurringDepositAccountId,
+                APPROVED_ON_DATE);
+        RecurringDepositAccountStatusChecker.verifyRecurringDepositIsApproved(recurringDepositAccountStatusHashMap);
+
+        /***
+         * Activate the RD Account and verify whether account is activated
+         */
+        recurringDepositAccountStatusHashMap = this.recurringDepositAccountHelper.activateRecurringDeposit(recurringDepositAccountId,
+                ACTIVATION_DATE);
+        RecurringDepositAccountStatusChecker.verifyRecurringDepositIsActive(recurringDepositAccountStatusHashMap);
+
+        HashMap recurringDepositAccountData = this.recurringDepositAccountHelper.getRecurringDepositAccountById(this.requestSpec,
+                this.responseSpec, recurringDepositAccountId);
+
+        Assert.assertEquals(interestRate, recurringDepositAccountData.get("nominalAnnualInterestRate"));
+    }
+
     private Integer createRecurringDepositProduct(final String validFrom, final String validTo, final String accountingRule,
             Account... accounts) {
         System.out.println("------------------------------CREATING NEW RECURRING DEPOSIT PRODUCT ---------------------------------------");
@@ -2505,6 +2668,36 @@
         } else if (accountingRule.equals(NONE)) {
             recurringDepositProductHelper = recurringDepositProductHelper.withAccountingRuleAsNone();
         }
+        final String recurringDepositProductJSON = recurringDepositProductHelper.withPeriodRangeChart().build(validFrom, validTo);
+        return RecurringDepositProductHelper.createRecurringDepositProduct(recurringDepositProductJSON, requestSpec, responseSpec);
+    }
+
+    private Integer createRecurringDepositProduct(final String validFrom, final String validTo, final String accountingRule,
+            final String chartToBePicked, Account... accounts) {
+        System.out.println("------------------------------CREATING NEW RECURRING DEPOSIT PRODUCT ---------------------------------------");
+        RecurringDepositProductHelper recurringDepositProductHelper = new RecurringDepositProductHelper(this.requestSpec, this.responseSpec);
+        if (accountingRule.equals(CASH_BASED)) {
+            recurringDepositProductHelper = recurringDepositProductHelper.withAccountingRuleAsCashBased(accounts);
+        } else if (accountingRule.equals(NONE)) {
+            recurringDepositProductHelper = recurringDepositProductHelper.withAccountingRuleAsNone();
+        }
+
+        switch (chartToBePicked) {
+            case "period":
+                recurringDepositProductHelper = recurringDepositProductHelper.withPeriodRangeChart();
+            break;
+            case "amount":
+                recurringDepositProductHelper = recurringDepositProductHelper.withAmountRangeChart();
+            break;
+            case "period_amount":
+                recurringDepositProductHelper = recurringDepositProductHelper.withPeriodAndAmountRangeChart();
+            break;
+            case "amount_period":
+                recurringDepositProductHelper = recurringDepositProductHelper.withAmountAndPeriodRangeChart();
+            break;
+            default:
+            break;
+        }
         final String recurringDepositProductJSON = recurringDepositProductHelper.build(validFrom, validTo);
         return RecurringDepositProductHelper.createRecurringDepositProduct(recurringDepositProductJSON, requestSpec, responseSpec);
     }
@@ -2514,7 +2707,18 @@
         System.out.println("--------------------------------APPLYING FOR RECURRING DEPOSIT ACCOUNT --------------------------------");
         final String recurringDepositApplicationJSON = new RecurringDepositAccountHelper(this.requestSpec, this.responseSpec)
                 .withSubmittedOnDate(submittedOnDate).withExpectedFirstDepositOnDate(expectedFirstDepositOnDate)
-                .build(clientID, productID, validFrom, validTo, penalInterestType);
+                .build(clientID, productID, penalInterestType);
+        return this.recurringDepositAccountHelper.applyRecurringDepositApplication(recurringDepositApplicationJSON, this.requestSpec,
+                this.responseSpec);
+    }
+
+    private Integer applyForRecurringDepositApplication(final String clientID, final String productID, final String validFrom,
+            final String validTo, final String submittedOnDate, final String penalInterestType, final String expectedFirstDepositOnDate,
+            final String depositAmount, final String depositPeriod) {
+        System.out.println("--------------------------------APPLYING FOR RECURRING DEPOSIT ACCOUNT --------------------------------");
+        final String recurringDepositApplicationJSON = new RecurringDepositAccountHelper(this.requestSpec, this.responseSpec)
+                .withSubmittedOnDate(submittedOnDate).withExpectedFirstDepositOnDate(expectedFirstDepositOnDate)
+                .withDepositPeriod(depositPeriod).withMandatoryDepositAmount(depositAmount).build(clientID, productID, penalInterestType);
         return this.recurringDepositAccountHelper.applyRecurringDepositApplication(recurringDepositApplicationJSON, this.requestSpec,
                 this.responseSpec);
     }
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/SchedulerJobsTestResults.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/SchedulerJobsTestResults.java
index 985889a..cc6b3c8 100644
--- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/SchedulerJobsTestResults.java
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/SchedulerJobsTestResults.java
@@ -892,6 +892,7 @@
         FixedDepositProductHelper fixedDepositProductHelper = new FixedDepositProductHelper(this.requestSpec, this.responseSpec);
         final String fixedDepositProductJSON = fixedDepositProductHelper //
                 // .withAccountingRuleAsCashBased(accounts)
+                .withPeriodRangeChart()//
                 .build(validFrom, validTo);
         return FixedDepositProductHelper.createFixedDepositProduct(fixedDepositProductJSON, requestSpec, responseSpec);
     }
@@ -904,7 +905,7 @@
                 //
                 .withSubmittedOnDate(submittedOnDate).withSavings(savingsId).transferInterest(true)
                 .withLockinPeriodFrequency("1", FixedDepositAccountHelper.DAYS)
-                .build(clientID, productID, validFrom, validTo, penalInterestType);
+                .build(clientID, productID, penalInterestType);
         return fixedDepositAccountHelper.applyFixedDepositApplication(fixedDepositApplicationJSON, this.requestSpec, this.responseSpec);
     }
 
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/fixeddeposit/FixedDepositAccountHelper.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/fixeddeposit/FixedDepositAccountHelper.java
index fa48717..64bd4c8 100644
--- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/fixeddeposit/FixedDepositAccountHelper.java
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/fixeddeposit/FixedDepositAccountHelper.java
@@ -72,6 +72,7 @@
     private static final String DAYS_360 = "360";
     private static final String DAYS_365 = "365";
     public final static String depositAmount = "100000";
+    private String newDepositAmount = null;
 
     private String interestCompoundingPeriodType = MONTHLY;
     private String interestPostingPeriodType = MONTHLY;
@@ -90,64 +91,15 @@
     private final boolean isActiveChart = true;
     private final String currencyCode = USD;
 
-    private final String depositPeriod = "14";
+    private String depositPeriod = "14";
     private final String depositPeriodFrequencyId = MONTHS;
     private String submittedOnDate = "";
     private String savingsId = null;
     private boolean transferInterest = false;
 
-    public String build(final String clientId, final String productId, final String validFrom, final String validTo,
-            final String penalInterestType) {
+    public String build(final String clientId, final String productId, final String penalInterestType) {
         final HashMap<String, Object> map = new HashMap<>();
 
-        List<HashMap<String, String>> chartSlabs = new ArrayList<HashMap<String, String>>();
-        HashMap<String, String> chartSlabsMap1 = new HashMap<>();
-        chartSlabsMap1.put("description", "First");
-        chartSlabsMap1.put("periodType", MONTHS);
-        chartSlabsMap1.put("fromPeriod", "1");
-        chartSlabsMap1.put("toPeriod", "6");
-        chartSlabsMap1.put("annualInterestRate", "5");
-        chartSlabsMap1.put("locale", LOCALE);
-        chartSlabs.add(0, chartSlabsMap1);
-
-        HashMap<String, String> chartSlabsMap2 = new HashMap<>();
-        chartSlabsMap2.put("description", "Second");
-        chartSlabsMap2.put("periodType", MONTHS);
-        chartSlabsMap2.put("fromPeriod", "7");
-        chartSlabsMap2.put("toPeriod", "12");
-        chartSlabsMap2.put("annualInterestRate", "6");
-        chartSlabsMap2.put("locale", LOCALE);
-        chartSlabs.add(1, chartSlabsMap2);
-
-        HashMap<String, String> chartSlabsMap3 = new HashMap<>();
-        chartSlabsMap3.put("description", "Third");
-        chartSlabsMap3.put("periodType", MONTHS);
-        chartSlabsMap3.put("fromPeriod", "13");
-        chartSlabsMap3.put("toPeriod", "18");
-        chartSlabsMap3.put("annualInterestRate", "7");
-        chartSlabsMap3.put("locale", LOCALE);
-        chartSlabs.add(2, chartSlabsMap3);
-
-        HashMap<String, String> chartSlabsMap4 = new HashMap<>();
-        chartSlabsMap4.put("description", "Fourth");
-        chartSlabsMap4.put("periodType", MONTHS);
-        chartSlabsMap4.put("fromPeriod", "19");
-        chartSlabsMap4.put("toPeriod", "24");
-        chartSlabsMap4.put("annualInterestRate", "8");
-        chartSlabsMap4.put("locale", LOCALE);
-        chartSlabs.add(3, chartSlabsMap4);
-
-        List<HashMap<String, Object>> charts = new ArrayList<HashMap<String, Object>>();
-        HashMap<String, Object> chartsMap = new HashMap<>();
-        chartsMap.put("fromDate", validFrom);
-        chartsMap.put("endDate", validTo);
-        chartsMap.put("dateFormat", "dd MMMM yyyy");
-        chartsMap.put("locale", LOCALE);
-        chartsMap.put("isActiveChart", this.isActiveChart);
-        chartsMap.put("chartSlabs", chartSlabs);
-        charts.add(chartsMap);
-
-        map.put("charts", charts);
         map.put("productId", productId);
         map.put("clientId", clientId);
         map.put("interestCalculationDaysInYearType", this.interestCalculationDaysInYearType);
@@ -169,7 +121,7 @@
         map.put("inMultiplesOfDepositTermTypeId", this.inMultiplesOfDepositTermTypeId);
         map.put("preClosurePenalInterest", this.preClosurePenalInterest);
         map.put("preClosurePenalInterestOnTypeId", penalInterestType);
-        map.put("depositAmount", depositAmount);
+        map.put("depositAmount", getDepositAmount());
         map.put("depositPeriod", this.depositPeriod);
         map.put("depositPeriodFrequencyId", this.depositPeriodFrequencyId);
         map.put("submittedOnDate", this.submittedOnDate);
@@ -196,8 +148,16 @@
     }
 
     public HashMap getFixedDepositSummary(final Integer accountID) {
+        return getFixedDepositDetails(accountID, "summary");
+    }
+
+    public HashMap getFixedDepositDetails(final Integer accountID) {
+        return getFixedDepositDetails(accountID, "");
+    }
+
+    private HashMap getFixedDepositDetails(final Integer accountID, final String jsonAttributeToGetBack) {
         final String URL = FIXED_DEPOSIT_ACCOUNT_URL + "/" + accountID + "?" + Utils.TENANT_IDENTIFIER;
-        final HashMap response = Utils.performServerGet(requestSpec, responseSpec, URL, "summary");
+        final HashMap response = Utils.performServerGet(requestSpec, responseSpec, URL, jsonAttributeToGetBack);
         return response;
     }
 
@@ -251,7 +211,7 @@
 
         final String fixedDepositApplicationJSON = new FixedDepositAccountHelper(this.requestSpec, this.responseSpec) //
                 .withSubmittedOnDate(submittedOnDate) //
-                .build(clientID, productID, validFrom, validTo, penalInterestType);
+                .build(clientID, productID, penalInterestType);
 
         return Utils.performServerPut(this.requestSpec, this.responseSpec, FIXED_DEPOSIT_ACCOUNT_URL + "/" + accountID + "?"
                 + Utils.TENANT_IDENTIFIER, fixedDepositApplicationJSON, CommonConstants.RESPONSE_CHANGES);
@@ -268,7 +228,7 @@
                 .withInterestCalculationPeriodType(interestCalculationType) //
                 .withInterestCompoundingPeriodType(interestCompoundingPeriodType) //
                 .withInterestPostingPeriodType(interestPostingPeriodType) //
-                .build(clientID, productID, validFrom, validTo, penalInterestType);
+                .build(clientID, productID, penalInterestType);
 
         return Utils.performServerPut(this.requestSpec, this.responseSpec, FIXED_DEPOSIT_ACCOUNT_URL + "/" + accountID + "?"
                 + Utils.TENANT_IDENTIFIER, fixedDepositApplicationJSON, CommonConstants.RESPONSE_CHANGES);
@@ -487,4 +447,19 @@
         this.lockinPeriodFrequency = lockinPeriodFrequency;
         return this;
     }
+
+    public FixedDepositAccountHelper withDepositPeriod(final String depositPeriod) {
+        this.depositPeriod = depositPeriod;
+        return this;
+    }
+
+    public FixedDepositAccountHelper withDepositAmount(final String depositAmount) {
+        this.newDepositAmount = depositAmount;
+        return this;
+    }
+
+    private String getDepositAmount() {
+        if (this.newDepositAmount == null) { return depositAmount; }
+        return this.newDepositAmount;
+    }
 }
\ No newline at end of file
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/fixeddeposit/FixedDepositProductHelper.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/fixeddeposit/FixedDepositProductHelper.java
index 2703340..b20b6f9 100644
--- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/fixeddeposit/FixedDepositProductHelper.java
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/fixeddeposit/FixedDepositProductHelper.java
@@ -97,10 +97,60 @@
     private final String currencyCode = USD;
     private final String interestCalculationDaysInYearType = DAYS_365;
     private Account[] accountList = null;
+    private List<HashMap<String, String>> chartSlabs = null;
+    private boolean isPrimaryGroupingByAmount = false;
 
     public String build(final String validFrom, final String validTo) {
         final HashMap<String, Object> map = new HashMap<>();
 
+        List<HashMap<String, Object>> charts = new ArrayList<HashMap<String, Object>>();
+        HashMap<String, Object> chartsMap = new HashMap<>();
+        chartsMap.put("fromDate", validFrom);
+        chartsMap.put("endDate", validTo);
+        chartsMap.put("dateFormat", "dd MMMM yyyy");
+        chartsMap.put("locale", LOCALE);
+        chartsMap.put("chartSlabs", this.chartSlabs);
+        chartsMap.put("isPrimaryGroupingByAmount", this.isPrimaryGroupingByAmount);
+        charts.add(chartsMap);
+
+        map.put("charts", charts);
+        map.put("name", this.name);
+        map.put("shortName", this.shortName);
+        map.put("description", this.description);
+        map.put("currencyCode", this.currencyCode);
+        map.put("interestCalculationDaysInYearType", this.interestCalculationDaysInYearType);
+        map.put("locale", LOCALE);
+        map.put("digitsAfterDecimal", DIGITS_AFTER_DECIMAL);
+        map.put("inMultiplesOf", IN_MULTIPLES_OF);
+        map.put("interestCalculationType", this.interestCalculationType);
+        map.put("interestCompoundingPeriodType", this.interestCompoundingPeriodType);
+        map.put("interestPostingPeriodType", this.interestPostingPeriodType);
+        map.put("accountingRule", this.accountingRule);
+        map.put("lockinPeriodFrequency", this.lockinPeriodFrequency);
+        map.put("lockinPeriodFrequencyType", this.lockingPeriodFrequencyType);
+        map.put("preClosurePenalApplicable", "true");
+        map.put("minDepositTermTypeId", this.minDepositTermTypeId);
+        map.put("minDepositTerm", this.minDepositTerm);
+        map.put("maxDepositTermTypeId", this.maxDepositTermTypeId);
+        map.put("maxDepositTerm", this.maxDepositTerm);
+        map.put("depositAmount", this.depositAmount);
+        map.put("preClosurePenalApplicable", this.preClosurePenalApplicable);
+        map.put("inMultiplesOfDepositTerm", this.inMultiplesOfDepositTerm);
+        map.put("inMultiplesOfDepositTermTypeId", this.inMultiplesOfDepositTermTypeId);
+        map.put("preClosurePenalInterest", this.preClosurePenalInterest);
+        map.put("preClosurePenalInterestOnTypeId", this.preClosurePenalInterestOnTypeId);
+        
+
+        if (this.accountingRule.equals(CASH_BASED)) {
+            map.putAll(getAccountMappingForCashBased());
+        }
+
+        String FixedDepositProductCreateJson = new Gson().toJson(map);
+        System.out.println(FixedDepositProductCreateJson);
+        return FixedDepositProductCreateJson;
+    }
+
+    public List<HashMap<String, String>> constructChartSlabWithPeriodRange() {
         List<HashMap<String, String>> chartSlabs = new ArrayList<HashMap<String, String>>();
         HashMap<String, String> chartSlabsMap1 = new HashMap<>();
         chartSlabsMap1.put("description", "First");
@@ -133,54 +183,172 @@
         chartSlabsMap4.put("description", "Fourth");
         chartSlabsMap4.put("periodType", MONTHS);
         chartSlabsMap4.put("fromPeriod", "19");
-        chartSlabsMap4.put("toPeriod", "24");
+        chartSlabsMap4.put("annualInterestRate", "8");
+        chartSlabsMap4.put("locale", LOCALE);
+        chartSlabs.add(3, chartSlabsMap4);
+        return chartSlabs;
+    }
+
+    public List<HashMap<String, String>> constructChartSlabWithPeriodAndAmountRange() {
+        List<HashMap<String, String>> chartSlabs = new ArrayList<HashMap<String, String>>();
+        HashMap<String, String> chartSlabsMap1 = new HashMap<>();
+        chartSlabsMap1.put("description", "First");
+        chartSlabsMap1.put("periodType", MONTHS);
+        chartSlabsMap1.put("fromPeriod", "1");
+        chartSlabsMap1.put("toPeriod", "6");
+        chartSlabsMap1.put("amountRangeFrom", "1");
+        chartSlabsMap1.put("amountRangeTo", "5000");
+        chartSlabsMap1.put("annualInterestRate", "5");
+        chartSlabsMap1.put("locale", LOCALE);
+        chartSlabs.add(0, chartSlabsMap1);
+
+        HashMap<String, String> chartSlabsMap1_1 = new HashMap<>();
+        chartSlabsMap1_1.put("description", "First");
+        chartSlabsMap1_1.put("periodType", MONTHS);
+        chartSlabsMap1_1.put("fromPeriod", "1");
+        chartSlabsMap1_1.put("toPeriod", "6");
+        chartSlabsMap1_1.put("amountRangeFrom", "5001");
+        chartSlabsMap1_1.put("annualInterestRate", "6");
+        chartSlabsMap1_1.put("locale", LOCALE);
+        chartSlabs.add(0, chartSlabsMap1_1);
+
+        HashMap<String, String> chartSlabsMap2 = new HashMap<>();
+        chartSlabsMap2.put("description", "Second");
+        chartSlabsMap2.put("periodType", MONTHS);
+        chartSlabsMap2.put("fromPeriod", "7");
+        chartSlabsMap2.put("toPeriod", "12");
+        chartSlabsMap2.put("amountRangeFrom", "1");
+        chartSlabsMap2.put("amountRangeTo", "5000");
+        chartSlabsMap2.put("annualInterestRate", "6");
+        chartSlabsMap2.put("locale", LOCALE);
+        chartSlabs.add(1, chartSlabsMap2);
+
+        HashMap<String, String> chartSlabsMap2_2 = new HashMap<>();
+        chartSlabsMap2_2.put("description", "Second");
+        chartSlabsMap2_2.put("periodType", MONTHS);
+        chartSlabsMap2_2.put("fromPeriod", "7");
+        chartSlabsMap2_2.put("toPeriod", "12");
+        chartSlabsMap2_2.put("amountRangeFrom", "5001");
+        chartSlabsMap2_2.put("annualInterestRate", "7");
+        chartSlabsMap2_2.put("locale", LOCALE);
+        chartSlabs.add(1, chartSlabsMap2_2);
+
+        HashMap<String, String> chartSlabsMap3 = new HashMap<>();
+        chartSlabsMap3.put("description", "Third");
+        chartSlabsMap3.put("periodType", MONTHS);
+        chartSlabsMap3.put("fromPeriod", "13");
+        chartSlabsMap3.put("toPeriod", "18");
+        chartSlabsMap3.put("amountRangeFrom", "1");
+        chartSlabsMap3.put("amountRangeTo", "5000");
+        chartSlabsMap3.put("annualInterestRate", "7");
+        chartSlabsMap3.put("locale", LOCALE);
+        chartSlabs.add(2, chartSlabsMap3);
+
+        HashMap<String, String> chartSlabsMap3_1 = new HashMap<>();
+        chartSlabsMap3_1.put("description", "Third");
+        chartSlabsMap3_1.put("periodType", MONTHS);
+        chartSlabsMap3_1.put("fromPeriod", "13");
+        chartSlabsMap3_1.put("toPeriod", "18");
+        chartSlabsMap3_1.put("amountRangeFrom", "5001");
+        chartSlabsMap3_1.put("annualInterestRate", "8");
+        chartSlabsMap3_1.put("locale", LOCALE);
+        chartSlabs.add(2, chartSlabsMap3_1);
+
+        HashMap<String, String> chartSlabsMap4 = new HashMap<>();
+        chartSlabsMap4.put("description", "Fourth");
+        chartSlabsMap4.put("periodType", MONTHS);
+        chartSlabsMap4.put("fromPeriod", "19");
+        chartSlabsMap4.put("amountRangeFrom", "1");
+        chartSlabsMap4.put("amountRangeTo", "5000");
         chartSlabsMap4.put("annualInterestRate", "8");
         chartSlabsMap4.put("locale", LOCALE);
         chartSlabs.add(3, chartSlabsMap4);
 
-        List<HashMap<String, Object>> charts = new ArrayList<HashMap<String, Object>>();
-        HashMap<String, Object> chartsMap = new HashMap<>();
-        chartsMap.put("fromDate", validFrom);
-        chartsMap.put("endDate", validTo);
-        chartsMap.put("dateFormat", "dd MMMM yyyy");
-        chartsMap.put("locale", LOCALE);
-        chartsMap.put("chartSlabs", chartSlabs);
-        charts.add(chartsMap);
+        HashMap<String, String> chartSlabsMap4_1 = new HashMap<>();
+        chartSlabsMap4_1.put("description", "Fourth");
+        chartSlabsMap4_1.put("periodType", MONTHS);
+        chartSlabsMap4_1.put("fromPeriod", "19");
+        chartSlabsMap4_1.put("amountRangeFrom", "5001");
+        chartSlabsMap4_1.put("annualInterestRate", "9");
+        chartSlabsMap4_1.put("locale", LOCALE);
+        chartSlabs.add(3, chartSlabsMap4_1);
 
-        map.put("charts", charts);
-        map.put("name", this.name);
-        map.put("shortName", this.shortName);
-        map.put("description", this.description);
-        map.put("currencyCode", this.currencyCode);
-        map.put("interestCalculationDaysInYearType", this.interestCalculationDaysInYearType);
-        map.put("locale", LOCALE);
-        map.put("digitsAfterDecimal", DIGITS_AFTER_DECIMAL);
-        map.put("inMultiplesOf", IN_MULTIPLES_OF);
-        map.put("interestCalculationType", this.interestCalculationType);
-        map.put("interestCompoundingPeriodType", this.interestCompoundingPeriodType);
-        map.put("interestPostingPeriodType", this.interestPostingPeriodType);
-        map.put("accountingRule", this.accountingRule);
-        map.put("lockinPeriodFrequency", this.lockinPeriodFrequency);
-        map.put("lockinPeriodFrequencyType", this.lockingPeriodFrequencyType);
-        map.put("preClosurePenalApplicable", "true");
-        map.put("minDepositTermTypeId", this.minDepositTermTypeId);
-        map.put("minDepositTerm", this.minDepositTerm);
-        map.put("maxDepositTermTypeId", this.maxDepositTermTypeId);
-        map.put("maxDepositTerm", this.maxDepositTerm);
-        map.put("depositAmount", this.depositAmount);
-        map.put("preClosurePenalApplicable", this.preClosurePenalApplicable);
-        map.put("inMultiplesOfDepositTerm", this.inMultiplesOfDepositTerm);
-        map.put("inMultiplesOfDepositTermTypeId", this.inMultiplesOfDepositTermTypeId);
-        map.put("preClosurePenalInterest", this.preClosurePenalInterest);
-        map.put("preClosurePenalInterestOnTypeId", this.preClosurePenalInterestOnTypeId);
+        return chartSlabs;
+    }
 
-        if (this.accountingRule.equals(CASH_BASED)) {
-            map.putAll(getAccountMappingForCashBased());
-        }
+    public List<HashMap<String, String>> constructChartSlabWithAmountAndPeriodRange() {
+        this.isPrimaryGroupingByAmount = true;
+        List<HashMap<String, String>> chartSlabs = new ArrayList<HashMap<String, String>>();
+        HashMap<String, String> chartSlabsMap1 = new HashMap<>();
+        chartSlabsMap1.put("description", "First");
+        chartSlabsMap1.put("periodType", MONTHS);
+        chartSlabsMap1.put("amountRangeFrom", "1");
+        chartSlabsMap1.put("amountRangeTo", "5000");
+        chartSlabsMap1.put("fromPeriod", "1");
+        chartSlabsMap1.put("toPeriod", "6");
+        chartSlabsMap1.put("annualInterestRate", "5");
+        chartSlabsMap1.put("locale", LOCALE);
+        chartSlabs.add(0, chartSlabsMap1);
 
-        String FixedDepositProductCreateJson = new Gson().toJson(map);
-        System.out.println(FixedDepositProductCreateJson);
-        return FixedDepositProductCreateJson;
+        HashMap<String, String> chartSlabsMap2 = new HashMap<>();
+        chartSlabsMap2.put("description", "Second");
+        chartSlabsMap2.put("periodType", MONTHS);
+        chartSlabsMap2.put("fromPeriod", "7");
+        chartSlabsMap2.put("amountRangeFrom", "1");
+        chartSlabsMap2.put("amountRangeTo", "5000");
+        chartSlabsMap2.put("annualInterestRate", "6");
+        chartSlabsMap2.put("locale", LOCALE);
+        chartSlabs.add(1, chartSlabsMap2);
+
+        HashMap<String, String> chartSlabsMap3 = new HashMap<>();
+        chartSlabsMap3.put("description", "Third");
+        chartSlabsMap3.put("periodType", MONTHS);
+        chartSlabsMap3.put("fromPeriod", "1");
+        chartSlabsMap3.put("toPeriod", "6");
+        chartSlabsMap3.put("amountRangeFrom", "5001");
+        chartSlabsMap3.put("annualInterestRate", "7");
+        chartSlabsMap3.put("locale", LOCALE);
+        chartSlabs.add(2, chartSlabsMap3);
+
+        HashMap<String, String> chartSlabsMap4 = new HashMap<>();
+        chartSlabsMap4.put("description", "Fourth");
+        chartSlabsMap4.put("periodType", MONTHS);
+        chartSlabsMap4.put("fromPeriod", "7");
+        chartSlabsMap4.put("amountRangeFrom", "5001");
+        chartSlabsMap4.put("annualInterestRate", "8");
+        chartSlabsMap4.put("locale", LOCALE);
+        chartSlabs.add(3, chartSlabsMap4);
+
+        return chartSlabs;
+    }
+
+    public List<HashMap<String, String>> constructChartSlabWithAmountRange() {
+        this.isPrimaryGroupingByAmount = true;
+        List<HashMap<String, String>> chartSlabs = new ArrayList<HashMap<String, String>>();
+        HashMap<String, String> chartSlabsMap1 = new HashMap<>();
+        chartSlabsMap1.put("description", "First");
+        chartSlabsMap1.put("amountRangeFrom", "1");
+        chartSlabsMap1.put("amountRangeTo", "5000");
+        chartSlabsMap1.put("annualInterestRate", "5");
+        chartSlabsMap1.put("locale", LOCALE);
+        chartSlabs.add(0, chartSlabsMap1);
+
+        HashMap<String, String> chartSlabsMap3 = new HashMap<>();
+        chartSlabsMap3.put("description", "Third");
+        chartSlabsMap3.put("amountRangeFrom", "5001");
+        chartSlabsMap3.put("amountRangeTo", "10000");
+        chartSlabsMap3.put("annualInterestRate", "7");
+        chartSlabsMap3.put("locale", LOCALE);
+        chartSlabs.add(1, chartSlabsMap3);
+
+        HashMap<String, String> chartSlabsMap4 = new HashMap<>();
+        chartSlabsMap4.put("description", "Fourth");
+        chartSlabsMap4.put("amountRangeFrom", "10001");
+        chartSlabsMap4.put("annualInterestRate", "8");
+        chartSlabsMap4.put("locale", LOCALE);
+        chartSlabs.add(2, chartSlabsMap4);
+
+        return chartSlabs;
     }
 
     public FixedDepositProductHelper withAccountingRuleAsNone() {
@@ -194,6 +362,26 @@
         return this;
     }
 
+    public FixedDepositProductHelper withPeriodRangeChart() {
+        this.chartSlabs = constructChartSlabWithPeriodRange();
+        return this;
+    }
+
+    public FixedDepositProductHelper withPeriodAndAmountRangeChart() {
+        this.chartSlabs = constructChartSlabWithPeriodAndAmountRange();
+        return this;
+    }
+
+    public FixedDepositProductHelper withAmountRangeChart() {
+        this.chartSlabs = constructChartSlabWithAmountRange();
+        return this;
+    }
+
+    public FixedDepositProductHelper withAmountAndPeriodRangeChart() {
+        this.chartSlabs = constructChartSlabWithAmountAndPeriodRange();
+        return this;
+    }
+
     private Map<String, String> getAccountMappingForCashBased() {
         final Map<String, String> map = new HashMap<>();
         if (accountList != null) {
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/recurringdeposit/RecurringDepositAccountHelper.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/recurringdeposit/RecurringDepositAccountHelper.java
index 5ec7cfd..d556cd8 100644
--- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/recurringdeposit/RecurringDepositAccountHelper.java
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/recurringdeposit/RecurringDepositAccountHelper.java
@@ -28,6 +28,7 @@
 
 import org.apache.fineract.integrationtests.common.CommonConstants;
 import org.apache.fineract.integrationtests.common.Utils;
+import org.apache.fineract.integrationtests.common.fixeddeposit.FixedDepositAccountHelper;
 
 import com.google.gson.Gson;
 import com.jayway.restassured.specification.RequestSpecification;
@@ -99,67 +100,18 @@
     private final String currencyCode = USD;
     private String interestCalculationDaysInYearType = DAYS_365;
     private final String depositAmount = "2000";
-    private final String depositPeriod = "14";
+    private String depositPeriod = "14";
     private final String depositPeriodFrequencyId = MONTHS;
     private final String recurringFrequency = "1";
     private final String recurringFrequencyType = MONTHS;
-    private final String mandatoryRecommendedDepositAmount = "2000";
+    private String mandatoryRecommendedDepositAmount = "2000";
     private String submittedOnDate = "";
     private String expectedFirstDepositOnDate = "";
     private boolean isCalendarInherited = false;
 
-    public String build(final String clientId, final String productId, final String validFrom, final String validTo,
-            final String penalInterestType) {
+    public String build(final String clientId, final String productId, final String penalInterestType) {
         final HashMap<String, Object> map = new HashMap<>();
 
-        List<HashMap<String, String>> chartSlabs = new ArrayList<HashMap<String, String>>();
-        HashMap<String, String> chartSlabsMap1 = new HashMap<>();
-        chartSlabsMap1.put("description", "First");
-        chartSlabsMap1.put("periodType", MONTHS);
-        chartSlabsMap1.put("fromPeriod", "1");
-        chartSlabsMap1.put("toPeriod", "6");
-        chartSlabsMap1.put("annualInterestRate", "5");
-        chartSlabsMap1.put("locale", LOCALE);
-        chartSlabs.add(0, chartSlabsMap1);
-
-        HashMap<String, String> chartSlabsMap2 = new HashMap<>();
-        chartSlabsMap2.put("description", "Second");
-        chartSlabsMap2.put("periodType", MONTHS);
-        chartSlabsMap2.put("fromPeriod", "7");
-        chartSlabsMap2.put("toPeriod", "12");
-        chartSlabsMap2.put("annualInterestRate", "6");
-        chartSlabsMap2.put("locale", LOCALE);
-        chartSlabs.add(1, chartSlabsMap2);
-
-        HashMap<String, String> chartSlabsMap3 = new HashMap<>();
-        chartSlabsMap3.put("description", "Third");
-        chartSlabsMap3.put("periodType", MONTHS);
-        chartSlabsMap3.put("fromPeriod", "13");
-        chartSlabsMap3.put("toPeriod", "18");
-        chartSlabsMap3.put("annualInterestRate", "7");
-        chartSlabsMap3.put("locale", LOCALE);
-        chartSlabs.add(2, chartSlabsMap3);
-
-        HashMap<String, String> chartSlabsMap4 = new HashMap<>();
-        chartSlabsMap4.put("description", "Fourth");
-        chartSlabsMap4.put("periodType", MONTHS);
-        chartSlabsMap4.put("fromPeriod", "19");
-        chartSlabsMap4.put("toPeriod", "24");
-        chartSlabsMap4.put("annualInterestRate", "8");
-        chartSlabsMap4.put("locale", LOCALE);
-        chartSlabs.add(3, chartSlabsMap4);
-
-        List<HashMap<String, Object>> charts = new ArrayList<HashMap<String, Object>>();
-        HashMap<String, Object> chartsMap = new HashMap<>();
-        chartsMap.put("fromDate", validFrom);
-        chartsMap.put("endDate", validTo);
-        chartsMap.put("dateFormat", "dd MMMM yyyy");
-        chartsMap.put("locale", LOCALE);
-        chartsMap.put("isActiveChart", this.isActiveChart);
-        chartsMap.put("chartSlabs", chartSlabs);
-        charts.add(chartsMap);
-
-        map.put("charts", charts);
         map.put("productId", productId);
         map.put("clientId", clientId);
         map.put("interestCalculationDaysInYearType", this.interestCalculationDaysInYearType);
@@ -231,8 +183,8 @@
         return annualInterestRate;
     }
 
-    public static Float getPrincipalAfterCompoundingInterest(Calendar currentDate, Float principal, Float depositAmount, Integer depositPeriod,
-            double interestPerDay, Integer compoundingInterval, Integer postingInterval) {
+    public static Float getPrincipalAfterCompoundingInterest(Calendar currentDate, Float principal, Float depositAmount,
+            Integer depositPeriod, double interestPerDay, Integer compoundingInterval, Integer postingInterval) {
 
         Float totalInterest = 0.0f;
         Float interestEarned = 0.0f;
@@ -274,7 +226,7 @@
         final String EXPECTED_FIRST_DEPOSIT_ON_ON_DATE = SUBMITTED_ON_DATE;
         final String recurringDepositApplicationJSON = new RecurringDepositAccountHelper(this.requestSpec, this.responseSpec)
                 .withSubmittedOnDate(SUBMITTED_ON_DATE).withExpectedFirstDepositOnDate(EXPECTED_FIRST_DEPOSIT_ON_ON_DATE)
-                .build(clientID, productID, validFrom, validTo, penalInterestType);
+                .build(clientID, productID, penalInterestType);
 
         return Utils.performServerPut(this.requestSpec, this.responseSpec, RECURRING_DEPOSIT_ACCOUNT_URL + "/" + accountID + "?"
                 + Utils.TENANT_IDENTIFIER, recurringDepositApplicationJSON, CommonConstants.RESPONSE_CHANGES);
@@ -292,7 +244,7 @@
                 .withInterestCompoundingPeriodType(interestCompoundingPeriodType) //
                 .withInterestPostingPeriodType(interestPostingPeriodType) //
                 .withExpectedFirstDepositOnDate(expectedFirstDepositOnDate) //
-                .build(clientID, productID, validFrom, validTo, penalInterestType);
+                .build(clientID, productID, penalInterestType);
 
         return Utils.performServerPut(this.requestSpec, this.responseSpec, RECURRING_DEPOSIT_ACCOUNT_URL + "/" + accountID + "?"
                 + Utils.TENANT_IDENTIFIER, recurringDepositApplicationJSON, CommonConstants.RESPONSE_CHANGES);
@@ -552,5 +504,15 @@
         this.interestPostingPeriodType = interestPostingPeriodTypeId;
         return this;
     }
+    
+    public RecurringDepositAccountHelper withDepositPeriod(final String depositPeriod) {
+        this.depositPeriod = depositPeriod;
+        return this;
+    }
+
+    public RecurringDepositAccountHelper withMandatoryDepositAmount(final String depositAmount) {
+        this.mandatoryRecommendedDepositAmount = depositAmount;
+        return this;
+    }
 
 }
\ No newline at end of file
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/recurringdeposit/RecurringDepositProductHelper.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/recurringdeposit/RecurringDepositProductHelper.java
index 71a92f8..16dc1d2 100644
--- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/recurringdeposit/RecurringDepositProductHelper.java
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/recurringdeposit/RecurringDepositProductHelper.java
@@ -25,6 +25,7 @@
 
 import org.apache.fineract.integrationtests.common.Utils;
 import org.apache.fineract.integrationtests.common.accounting.Account;
+import org.apache.fineract.integrationtests.common.fixeddeposit.FixedDepositProductHelper;
 
 import com.google.gson.Gson;
 import com.jayway.restassured.specification.RequestSpecification;
@@ -95,47 +96,12 @@
     private final String minDepositAmount = "100";
     private final String maxDepositAmount = "1000000";
     private Account[] accountList = null;
+    private List<HashMap<String, String>> chartSlabs = null;
+    private boolean isPrimaryGroupingByAmount = false;
 
     public String build(final String validFrom, final String validTo) {
         final HashMap<String, Object> map = new HashMap<>();
 
-        List<HashMap<String, String>> chartSlabs = new ArrayList<HashMap<String, String>>();
-        HashMap<String, String> chartSlabsMap1 = new HashMap<>();
-        chartSlabsMap1.put("description", "First");
-        chartSlabsMap1.put("periodType", MONTHS);
-        chartSlabsMap1.put("fromPeriod", "1");
-        chartSlabsMap1.put("toPeriod", "6");
-        chartSlabsMap1.put("annualInterestRate", "5");
-        chartSlabsMap1.put("locale", LOCALE);
-        chartSlabs.add(0, chartSlabsMap1);
-
-        HashMap<String, String> chartSlabsMap2 = new HashMap<>();
-        chartSlabsMap2.put("description", "Second");
-        chartSlabsMap2.put("periodType", MONTHS);
-        chartSlabsMap2.put("fromPeriod", "7");
-        chartSlabsMap2.put("toPeriod", "12");
-        chartSlabsMap2.put("annualInterestRate", "6");
-        chartSlabsMap2.put("locale", LOCALE);
-        chartSlabs.add(1, chartSlabsMap2);
-
-        HashMap<String, String> chartSlabsMap3 = new HashMap<>();
-        chartSlabsMap3.put("description", "Third");
-        chartSlabsMap3.put("periodType", MONTHS);
-        chartSlabsMap3.put("fromPeriod", "13");
-        chartSlabsMap3.put("toPeriod", "18");
-        chartSlabsMap3.put("annualInterestRate", "7");
-        chartSlabsMap3.put("locale", LOCALE);
-        chartSlabs.add(2, chartSlabsMap3);
-
-        HashMap<String, String> chartSlabsMap4 = new HashMap<>();
-        chartSlabsMap4.put("description", "Fourth");
-        chartSlabsMap4.put("periodType", MONTHS);
-        chartSlabsMap4.put("fromPeriod", "19");
-        chartSlabsMap4.put("toPeriod", "24");
-        chartSlabsMap4.put("annualInterestRate", "8");
-        chartSlabsMap4.put("locale", LOCALE);
-        chartSlabs.add(3, chartSlabsMap4);
-
         List<HashMap<String, Object>> charts = new ArrayList<HashMap<String, Object>>();
         HashMap<String, Object> chartsMap = new HashMap<>();
         chartsMap.put("fromDate", validFrom);
@@ -143,6 +109,7 @@
         chartsMap.put("dateFormat", "dd MMMM yyyy");
         chartsMap.put("locale", LOCALE);
         chartsMap.put("chartSlabs", chartSlabs);
+        chartsMap.put("isPrimaryGroupingByAmount", this.isPrimaryGroupingByAmount);
         charts.add(chartsMap);
 
         map.put("charts", charts);
@@ -198,6 +165,26 @@
         return this;
     }
 
+    public RecurringDepositProductHelper withPeriodRangeChart() {
+        this.chartSlabs = constructChartSlabWithPeriodRange();
+        return this;
+    }
+
+    public RecurringDepositProductHelper withPeriodAndAmountRangeChart() {
+        this.chartSlabs = constructChartSlabWithPeriodAndAmountRange();
+        return this;
+    }
+
+    public RecurringDepositProductHelper withAmountRangeChart() {
+        this.chartSlabs = constructChartSlabWithAmountRange();
+        return this;
+    }
+
+    public RecurringDepositProductHelper withAmountAndPeriodRangeChart() {
+        this.chartSlabs = constructChartSlabWithAmountAndPeriodRange();
+        return this;
+    }
+
     private Map<String, String> getAccountMappingForCashBased() {
         final Map<String, String> map = new HashMap<>();
         if (accountList != null) {
@@ -256,4 +243,205 @@
         return response;
     }
 
+    public List<HashMap<String, String>> constructChartSlabWithPeriodRange() {
+        List<HashMap<String, String>> chartSlabs = new ArrayList<HashMap<String, String>>();
+        HashMap<String, String> chartSlabsMap1 = new HashMap<>();
+        chartSlabsMap1.put("description", "First");
+        chartSlabsMap1.put("periodType", MONTHS);
+        chartSlabsMap1.put("fromPeriod", "1");
+        chartSlabsMap1.put("toPeriod", "6");
+        chartSlabsMap1.put("annualInterestRate", "5");
+        chartSlabsMap1.put("locale", LOCALE);
+        chartSlabs.add(0, chartSlabsMap1);
+
+        HashMap<String, String> chartSlabsMap2 = new HashMap<>();
+        chartSlabsMap2.put("description", "Second");
+        chartSlabsMap2.put("periodType", MONTHS);
+        chartSlabsMap2.put("fromPeriod", "7");
+        chartSlabsMap2.put("toPeriod", "12");
+        chartSlabsMap2.put("annualInterestRate", "6");
+        chartSlabsMap2.put("locale", LOCALE);
+        chartSlabs.add(1, chartSlabsMap2);
+
+        HashMap<String, String> chartSlabsMap3 = new HashMap<>();
+        chartSlabsMap3.put("description", "Third");
+        chartSlabsMap3.put("periodType", MONTHS);
+        chartSlabsMap3.put("fromPeriod", "13");
+        chartSlabsMap3.put("toPeriod", "18");
+        chartSlabsMap3.put("annualInterestRate", "7");
+        chartSlabsMap3.put("locale", LOCALE);
+        chartSlabs.add(2, chartSlabsMap3);
+
+        HashMap<String, String> chartSlabsMap4 = new HashMap<>();
+        chartSlabsMap4.put("description", "Fourth");
+        chartSlabsMap4.put("periodType", MONTHS);
+        chartSlabsMap4.put("fromPeriod", "19");
+        chartSlabsMap4.put("annualInterestRate", "8");
+        chartSlabsMap4.put("locale", LOCALE);
+        chartSlabs.add(3, chartSlabsMap4);
+        return chartSlabs;
+    }
+
+    public List<HashMap<String, String>> constructChartSlabWithPeriodAndAmountRange() {
+        List<HashMap<String, String>> chartSlabs = new ArrayList<HashMap<String, String>>();
+        HashMap<String, String> chartSlabsMap1 = new HashMap<>();
+        chartSlabsMap1.put("description", "First");
+        chartSlabsMap1.put("periodType", MONTHS);
+        chartSlabsMap1.put("fromPeriod", "1");
+        chartSlabsMap1.put("toPeriod", "6");
+        chartSlabsMap1.put("amountRangeFrom", "1");
+        chartSlabsMap1.put("amountRangeTo", "5000");
+        chartSlabsMap1.put("annualInterestRate", "5");
+        chartSlabsMap1.put("locale", LOCALE);
+        chartSlabs.add(0, chartSlabsMap1);
+
+        HashMap<String, String> chartSlabsMap1_1 = new HashMap<>();
+        chartSlabsMap1_1.put("description", "First");
+        chartSlabsMap1_1.put("periodType", MONTHS);
+        chartSlabsMap1_1.put("fromPeriod", "1");
+        chartSlabsMap1_1.put("toPeriod", "6");
+        chartSlabsMap1_1.put("amountRangeFrom", "5001");
+        chartSlabsMap1_1.put("annualInterestRate", "6");
+        chartSlabsMap1_1.put("locale", LOCALE);
+        chartSlabs.add(0, chartSlabsMap1_1);
+
+        HashMap<String, String> chartSlabsMap2 = new HashMap<>();
+        chartSlabsMap2.put("description", "Second");
+        chartSlabsMap2.put("periodType", MONTHS);
+        chartSlabsMap2.put("fromPeriod", "7");
+        chartSlabsMap2.put("toPeriod", "12");
+        chartSlabsMap2.put("amountRangeFrom", "1");
+        chartSlabsMap2.put("amountRangeTo", "5000");
+        chartSlabsMap2.put("annualInterestRate", "6");
+        chartSlabsMap2.put("locale", LOCALE);
+        chartSlabs.add(1, chartSlabsMap2);
+
+        HashMap<String, String> chartSlabsMap2_2 = new HashMap<>();
+        chartSlabsMap2_2.put("description", "Second");
+        chartSlabsMap2_2.put("periodType", MONTHS);
+        chartSlabsMap2_2.put("fromPeriod", "7");
+        chartSlabsMap2_2.put("toPeriod", "12");
+        chartSlabsMap2_2.put("amountRangeFrom", "5001");
+        chartSlabsMap2_2.put("annualInterestRate", "7");
+        chartSlabsMap2_2.put("locale", LOCALE);
+        chartSlabs.add(1, chartSlabsMap2_2);
+
+        HashMap<String, String> chartSlabsMap3 = new HashMap<>();
+        chartSlabsMap3.put("description", "Third");
+        chartSlabsMap3.put("periodType", MONTHS);
+        chartSlabsMap3.put("fromPeriod", "13");
+        chartSlabsMap3.put("toPeriod", "18");
+        chartSlabsMap3.put("amountRangeFrom", "1");
+        chartSlabsMap3.put("amountRangeTo", "5000");
+        chartSlabsMap3.put("annualInterestRate", "7");
+        chartSlabsMap3.put("locale", LOCALE);
+        chartSlabs.add(2, chartSlabsMap3);
+
+        HashMap<String, String> chartSlabsMap3_1 = new HashMap<>();
+        chartSlabsMap3_1.put("description", "Third");
+        chartSlabsMap3_1.put("periodType", MONTHS);
+        chartSlabsMap3_1.put("fromPeriod", "13");
+        chartSlabsMap3_1.put("toPeriod", "18");
+        chartSlabsMap3_1.put("amountRangeFrom", "5001");
+        chartSlabsMap3_1.put("annualInterestRate", "8");
+        chartSlabsMap3_1.put("locale", LOCALE);
+        chartSlabs.add(2, chartSlabsMap3_1);
+
+        HashMap<String, String> chartSlabsMap4 = new HashMap<>();
+        chartSlabsMap4.put("description", "Fourth");
+        chartSlabsMap4.put("periodType", MONTHS);
+        chartSlabsMap4.put("fromPeriod", "19");
+        chartSlabsMap4.put("amountRangeFrom", "1");
+        chartSlabsMap4.put("amountRangeTo", "5000");
+        chartSlabsMap4.put("annualInterestRate", "8");
+        chartSlabsMap4.put("locale", LOCALE);
+        chartSlabs.add(3, chartSlabsMap4);
+
+        HashMap<String, String> chartSlabsMap4_1 = new HashMap<>();
+        chartSlabsMap4_1.put("description", "Fourth");
+        chartSlabsMap4_1.put("periodType", MONTHS);
+        chartSlabsMap4_1.put("fromPeriod", "19");
+        chartSlabsMap4_1.put("amountRangeFrom", "5001");
+        chartSlabsMap4_1.put("annualInterestRate", "9");
+        chartSlabsMap4_1.put("locale", LOCALE);
+        chartSlabs.add(3, chartSlabsMap4_1);
+
+        return chartSlabs;
+    }
+
+    public List<HashMap<String, String>> constructChartSlabWithAmountAndPeriodRange() {
+        this.isPrimaryGroupingByAmount = true;
+        List<HashMap<String, String>> chartSlabs = new ArrayList<HashMap<String, String>>();
+        HashMap<String, String> chartSlabsMap1 = new HashMap<>();
+        chartSlabsMap1.put("description", "First");
+        chartSlabsMap1.put("periodType", MONTHS);
+        chartSlabsMap1.put("amountRangeFrom", "1");
+        chartSlabsMap1.put("amountRangeTo", "5000");
+        chartSlabsMap1.put("fromPeriod", "1");
+        chartSlabsMap1.put("toPeriod", "6");
+        chartSlabsMap1.put("annualInterestRate", "5");
+        chartSlabsMap1.put("locale", LOCALE);
+        chartSlabs.add(0, chartSlabsMap1);
+
+        HashMap<String, String> chartSlabsMap2 = new HashMap<>();
+        chartSlabsMap2.put("description", "Second");
+        chartSlabsMap2.put("periodType", MONTHS);
+        chartSlabsMap2.put("fromPeriod", "7");
+        chartSlabsMap2.put("amountRangeFrom", "1");
+        chartSlabsMap2.put("amountRangeTo", "5000");
+        chartSlabsMap2.put("annualInterestRate", "6");
+        chartSlabsMap2.put("locale", LOCALE);
+        chartSlabs.add(1, chartSlabsMap2);
+
+        HashMap<String, String> chartSlabsMap3 = new HashMap<>();
+        chartSlabsMap3.put("description", "Third");
+        chartSlabsMap3.put("periodType", MONTHS);
+        chartSlabsMap3.put("fromPeriod", "1");
+        chartSlabsMap3.put("toPeriod", "6");
+        chartSlabsMap3.put("amountRangeFrom", "5001");
+        chartSlabsMap3.put("annualInterestRate", "7");
+        chartSlabsMap3.put("locale", LOCALE);
+        chartSlabs.add(2, chartSlabsMap3);
+
+        HashMap<String, String> chartSlabsMap4 = new HashMap<>();
+        chartSlabsMap4.put("description", "Fourth");
+        chartSlabsMap4.put("periodType", MONTHS);
+        chartSlabsMap4.put("fromPeriod", "7");
+        chartSlabsMap4.put("amountRangeFrom", "5001");
+        chartSlabsMap4.put("annualInterestRate", "8");
+        chartSlabsMap4.put("locale", LOCALE);
+        chartSlabs.add(3, chartSlabsMap4);
+
+        return chartSlabs;
+    }
+
+    public List<HashMap<String, String>> constructChartSlabWithAmountRange() {
+        this.isPrimaryGroupingByAmount = true;
+        List<HashMap<String, String>> chartSlabs = new ArrayList<HashMap<String, String>>();
+        HashMap<String, String> chartSlabsMap1 = new HashMap<>();
+        chartSlabsMap1.put("description", "First");
+        chartSlabsMap1.put("amountRangeFrom", "1");
+        chartSlabsMap1.put("amountRangeTo", "5000");
+        chartSlabsMap1.put("annualInterestRate", "5");
+        chartSlabsMap1.put("locale", LOCALE);
+        chartSlabs.add(0, chartSlabsMap1);
+
+        HashMap<String, String> chartSlabsMap3 = new HashMap<>();
+        chartSlabsMap3.put("description", "Third");
+        chartSlabsMap3.put("amountRangeFrom", "5001");
+        chartSlabsMap3.put("amountRangeTo", "10000");
+        chartSlabsMap3.put("annualInterestRate", "7");
+        chartSlabsMap3.put("locale", LOCALE);
+        chartSlabs.add(1, chartSlabsMap3);
+
+        HashMap<String, String> chartSlabsMap4 = new HashMap<>();
+        chartSlabsMap4.put("description", "Fourth");
+        chartSlabsMap4.put("amountRangeFrom", "10001");
+        chartSlabsMap4.put("annualInterestRate", "8");
+        chartSlabsMap4.put("locale", LOCALE);
+        chartSlabs.add(2, chartSlabsMap4);
+
+        return chartSlabs;
+    }
+
 }
\ No newline at end of file
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 98e8096..52d072d 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
@@ -142,7 +142,12 @@
 
     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);
+        return createRepeatingCalendar(title, startDate, typeId, recurrence);
+    }
 
+    public static Calendar createRepeatingCalendar(final String title, final LocalDate startDate, final Integer typeId,
+            final String recurrence) {
         final String description = null;
         final String location = null;
         final LocalDate endDate = null;
@@ -151,8 +156,6 @@
         final Integer remindById = null;
         final Integer firstReminder = null;
         final Integer secondReminder = null;
-        final String recurrence = constructRecurrence(frequencyType, interval, repeatsOnDay);
-
         return new Calendar(title, description, location, startDate, endDate, duration, typeId, repeating, recurrence, remindById,
                 firstReminder, secondReminder);
     }
@@ -233,7 +236,7 @@
 
     }
 
-    public Map<String, Object> update(final JsonCommand command, final Boolean areActiveEntitiesSynced ) {
+    public Map<String, Object> update(final JsonCommand command, final Boolean areActiveEntitiesSynced) {
 
         final Map<String, Object> actualChanges = new LinkedHashMap<>(9);
 
@@ -345,7 +348,7 @@
              * calendar then do not allow to change meeting frequency
              */
 
-            if ( areActiveEntitiesSynced && !CalendarUtils.isFrequencySame(this.recurrence, newRecurrence)) {
+            if (areActiveEntitiesSynced && !CalendarUtils.isFrequencySame(this.recurrence, newRecurrence)) {
                 final String defaultUserMessage = "Update of meeting frequency is not supported";
                 throw new CalendarParameterUpdateNotSupportedException("meeting.frequency", defaultUserMessage);
             }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/InterestRateChartApiConstants.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/InterestRateChartApiConstants.java
index 7bce4ee..20f760b 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/InterestRateChartApiConstants.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/InterestRateChartApiConstants.java
@@ -44,6 +44,7 @@
     public static final String endDateParamName = "endDate";
     public static final String productIdParamName = "productId";
     public static final String productNameParamName = "productName";
+    public static final String isPrimaryGroupingByAmountParamName = "isPrimaryGroupingByAmount";
 
     // interest rate chart Slabs parameters
 //    public static final String periodTypeParamName = "periodType";
@@ -63,13 +64,14 @@
     public static final String deleteParamName = "delete";
 
     public static final Set<String> INTERESTRATE_CHART_CREATE_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(localeParamName,
-            dateFormatParamName, nameParamName, descriptionParamName, fromDateParamName, endDateParamName, productIdParamName,
-            chartSlabs));
+            dateFormatParamName, nameParamName, descriptionParamName, fromDateParamName, endDateParamName, productIdParamName, chartSlabs,
+            isPrimaryGroupingByAmountParamName));
 
     public static final Set<String> INTERESTRATE_CHART_UPDATE_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(localeParamName,
             dateFormatParamName, idParamName, nameParamName, descriptionParamName, fromDateParamName, endDateParamName, chartSlabs,
-            deleteParamName));
+            deleteParamName, isPrimaryGroupingByAmountParamName));
 
     public static final Set<String> INTERESTRATE_CHART_RESPONSE_DATA_PARAMETERS = new HashSet<>(Arrays.asList(localeParamName,
-            dateFormatParamName, idParamName, nameParamName, descriptionParamName, fromDateParamName, endDateParamName, chartSlabs));
+            dateFormatParamName, idParamName, nameParamName, descriptionParamName, fromDateParamName, endDateParamName, chartSlabs,
+            isPrimaryGroupingByAmountParamName));
 }
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/data/InterestRateChartData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/data/InterestRateChartData.java
index f7aef96..1b31287 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/data/InterestRateChartData.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/data/InterestRateChartData.java
@@ -18,9 +18,8 @@
  */
 package org.apache.fineract.portfolio.interestratechart.data;
 
+import java.util.ArrayList;
 import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
 
 import org.apache.fineract.infrastructure.codes.data.CodeValueData;
 import org.apache.fineract.infrastructure.core.data.EnumOptionData;
@@ -38,9 +37,10 @@
     private final LocalDate endDate;
     private final Long productId;
     private final String productName;
+    private final boolean isPrimaryGroupingByAmount;
 
     // associations
-    private Set<InterestRateChartSlabData> chartSlabs;
+    private Collection<InterestRateChartSlabData> chartSlabs;
 
     // template
     private final Collection<EnumOptionData> periodTypes;
@@ -53,9 +53,9 @@
     private final Collection<CodeValueData> clientClassificationOptions;
 
     public static InterestRateChartData instance(Long id, String name, String description, LocalDate fromDate, LocalDate endDate,
-            Long savingsProductId, String savingsProductName) {
+            boolean isPrimaryGroupingByAmount, Long savingsProductId, String savingsProductName) {
         Collection<EnumOptionData> periodTypes = null;
-        Set<InterestRateChartSlabData> chartSlabs = null;
+        Collection<InterestRateChartSlabData> chartSlabs = null;
         final Collection<EnumOptionData> entityTypeOptions = null;
         final Collection<EnumOptionData> attributeNameOptions = null;
         final Collection<EnumOptionData> conditionTypeOptions = null;
@@ -63,17 +63,18 @@
         final Collection<CodeValueData> genderOptions = null;
         final Collection<CodeValueData> clientTypeOptions = null;
         final Collection<CodeValueData> clientClassificationOptions = null;
-        return new InterestRateChartData(id, name, description, fromDate, endDate, savingsProductId, savingsProductName, chartSlabs,
-                periodTypes, entityTypeOptions, attributeNameOptions, conditionTypeOptions, incentiveTypeOptions, genderOptions,
-                clientTypeOptions, clientClassificationOptions);
+        return new InterestRateChartData(id, name, description, fromDate, endDate, isPrimaryGroupingByAmount, savingsProductId,
+                savingsProductName, chartSlabs, periodTypes, entityTypeOptions, attributeNameOptions, conditionTypeOptions,
+                incentiveTypeOptions, genderOptions, clientTypeOptions, clientClassificationOptions);
     }
 
-    public static InterestRateChartData withSlabs(InterestRateChartData interestRateChartData, Set<InterestRateChartSlabData> chartSlabs) {
+    public static InterestRateChartData withSlabs(InterestRateChartData interestRateChartData, Collection<InterestRateChartSlabData> chartSlabs) {
         return new InterestRateChartData(interestRateChartData.id, interestRateChartData.name, interestRateChartData.description,
-                interestRateChartData.fromDate, interestRateChartData.endDate, interestRateChartData.productId,
-                interestRateChartData.productName, chartSlabs, interestRateChartData.periodTypes, interestRateChartData.entityTypeOptions,
-                interestRateChartData.attributeNameOptions, interestRateChartData.conditionTypeOptions,
-                interestRateChartData.incentiveTypeOptions, interestRateChartData.genderOptions, interestRateChartData.clientTypeOptions,
+                interestRateChartData.fromDate, interestRateChartData.endDate, interestRateChartData.isPrimaryGroupingByAmount,
+                interestRateChartData.productId, interestRateChartData.productName, chartSlabs, interestRateChartData.periodTypes,
+                interestRateChartData.entityTypeOptions, interestRateChartData.attributeNameOptions,
+                interestRateChartData.conditionTypeOptions, interestRateChartData.incentiveTypeOptions,
+                interestRateChartData.genderOptions, interestRateChartData.clientTypeOptions,
                 interestRateChartData.clientClassificationOptions);
     }
 
@@ -83,9 +84,10 @@
             final Collection<CodeValueData> genderOptions, final Collection<CodeValueData> clientTypeOptions,
             final Collection<CodeValueData> clientClassificationOptions) {
         return new InterestRateChartData(interestRateChartData.id, interestRateChartData.name, interestRateChartData.description,
-                interestRateChartData.fromDate, interestRateChartData.endDate, interestRateChartData.productId,
-                interestRateChartData.productName, interestRateChartData.chartSlabs, periodTypes, entityTypeOptions, attributeNameOptions,
-                conditionTypeOptions, incentiveTypeOptions, genderOptions, clientTypeOptions, clientClassificationOptions);
+                interestRateChartData.fromDate, interestRateChartData.endDate, interestRateChartData.isPrimaryGroupingByAmount,
+                interestRateChartData.productId, interestRateChartData.productName, interestRateChartData.chartSlabs, periodTypes,
+                entityTypeOptions, attributeNameOptions, conditionTypeOptions, incentiveTypeOptions, genderOptions, clientTypeOptions,
+                clientClassificationOptions);
     }
 
     public static InterestRateChartData template(Collection<EnumOptionData> periodTypes,
@@ -98,26 +100,28 @@
         final String description = null;
         final LocalDate fromDate = null;
         final LocalDate endDate = null;
+        final boolean isPrimaryGroupingByAmount = false;
         final Long savingsProductId = null;
         final String savingsProductName = null;
-        final Set<InterestRateChartSlabData> chartSlabs = null;
+        final Collection<InterestRateChartSlabData> chartSlabs = null;
 
-        return new InterestRateChartData(id, name, description, fromDate, endDate, savingsProductId, savingsProductName, chartSlabs,
-                periodTypes, entityTypeOptions, attributeNameOptions, conditionTypeOptions, incentiveTypeOptions, genderOptions,
-                clientTypeOptions, clientClassificationOptions);
+        return new InterestRateChartData(id, name, description, fromDate, endDate, isPrimaryGroupingByAmount, savingsProductId,
+                savingsProductName, chartSlabs, periodTypes, entityTypeOptions, attributeNameOptions, conditionTypeOptions,
+                incentiveTypeOptions, genderOptions, clientTypeOptions, clientClassificationOptions);
     }
 
-    private InterestRateChartData(Long id, String name, String description, LocalDate fromDate, LocalDate endDate, Long savingsProductId,
-            String savingsProductName, Set<InterestRateChartSlabData> chartSlabs, Collection<EnumOptionData> periodTypes,
-            final Collection<EnumOptionData> entityTypeOptions, final Collection<EnumOptionData> attributeNameOptions,
-            final Collection<EnumOptionData> conditionTypeOptions, final Collection<EnumOptionData> incentiveTypeOptions,
-            final Collection<CodeValueData> genderOptions, final Collection<CodeValueData> clientTypeOptions,
-            final Collection<CodeValueData> clientClassificationOptions) {
+    private InterestRateChartData(Long id, String name, String description, LocalDate fromDate, LocalDate endDate,
+            boolean isPrimaryGroupingByAmount, Long savingsProductId, String savingsProductName, Collection<InterestRateChartSlabData> chartSlabs,
+            Collection<EnumOptionData> periodTypes, final Collection<EnumOptionData> entityTypeOptions,
+            final Collection<EnumOptionData> attributeNameOptions, final Collection<EnumOptionData> conditionTypeOptions,
+            final Collection<EnumOptionData> incentiveTypeOptions, final Collection<CodeValueData> genderOptions,
+            final Collection<CodeValueData> clientTypeOptions, final Collection<CodeValueData> clientClassificationOptions) {
         this.id = id;
         this.name = name;
         this.description = description;
         this.fromDate = fromDate;
         this.endDate = endDate;
+        this.isPrimaryGroupingByAmount = isPrimaryGroupingByAmount;
         this.chartSlabs = chartSlabs;
         this.productId = savingsProductId;
         this.productName = savingsProductName;
@@ -133,7 +137,7 @@
 
     public void addChartSlab(final InterestRateChartSlabData chartSlab) {
         if (this.chartSlabs == null) {
-            this.chartSlabs = new HashSet<>();
+            this.chartSlabs = new ArrayList<>();
         }
 
         this.chartSlabs.add(chartSlab);
@@ -159,7 +163,7 @@
         return this.description;
     }
 
-    public Set<InterestRateChartSlabData> chartSlabs() {
+    public Collection<InterestRateChartSlabData> chartSlabs() {
         return this.chartSlabs;
     }
 
@@ -195,4 +199,9 @@
         return this.clientClassificationOptions;
     }
 
+    
+    public boolean isPrimaryGroupingByAmount() {
+        return this.isPrimaryGroupingByAmount;
+    }
+
 }
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/data/InterestRateChartDataValidator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/data/InterestRateChartDataValidator.java
index 04c4d22..a325175 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/data/InterestRateChartDataValidator.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/data/InterestRateChartDataValidator.java
@@ -26,6 +26,7 @@
 import static org.apache.fineract.portfolio.interestratechart.InterestRateChartApiConstants.endDateParamName;
 import static org.apache.fineract.portfolio.interestratechart.InterestRateChartApiConstants.fromDateParamName;
 import static org.apache.fineract.portfolio.interestratechart.InterestRateChartApiConstants.idParamName;
+import static org.apache.fineract.portfolio.interestratechart.InterestRateChartApiConstants.isPrimaryGroupingByAmountParamName;
 import static org.apache.fineract.portfolio.interestratechart.InterestRateChartApiConstants.nameParamName;
 import static org.apache.fineract.portfolio.interestratechart.InterestRateChartApiConstants.productIdParamName;
 
@@ -98,6 +99,11 @@
             toDate = this.fromApiJsonHelper.extractLocalDateNamed(endDateParamName, element);
             baseDataValidator.reset().parameter(endDateParamName).value(toDate).notNull();
         }
+        
+        Boolean isPrimaryGroupingByAmount = this.fromApiJsonHelper.extractBooleanNamed(isPrimaryGroupingByAmountParamName, element);
+        if (isPrimaryGroupingByAmount == null) {
+            isPrimaryGroupingByAmount = false;
+        }
 
         if (fromDate != null && toDate != null) {
             if (fromDate.isAfter(toDate)) {
@@ -106,7 +112,7 @@
         }
 
         // validate chart Slabs
-        validateChartSlabs(element, baseDataValidator);
+        validateChartSlabs(element, baseDataValidator, isPrimaryGroupingByAmount);
     }
 
     public void validateUpdate(final String json) {
@@ -151,6 +157,11 @@
             toDate = this.fromApiJsonHelper.extractLocalDateNamed(endDateParamName, element);
             baseDataValidator.reset().parameter(endDateParamName).value(toDate).notNull();
         }
+        
+        Boolean isPrimaryGroupingByAmount = this.fromApiJsonHelper.extractBooleanNamed(isPrimaryGroupingByAmountParamName, element);
+        if (isPrimaryGroupingByAmount == null) {
+            isPrimaryGroupingByAmount = false;
+        }
 
         if (fromDate != null && toDate != null) {
             if (fromDate.isAfter(toDate)) {
@@ -158,7 +169,7 @@
             }
         }
 
-        validateChartSlabs(element, baseDataValidator);
+        validateChartSlabs(element, baseDataValidator, isPrimaryGroupingByAmount);
 
     }
 
@@ -166,7 +177,7 @@
         if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
     }
 
-    private void validateChartSlabs(JsonElement element, DataValidatorBuilder baseDataValidator) {
+    private void validateChartSlabs(JsonElement element, DataValidatorBuilder baseDataValidator,final boolean isPrimaryGroupingByAmount) {
 
         if (element.isJsonObject()) {
             final JsonObject topLevelJsonElement = element.getAsJsonObject();
@@ -178,9 +189,9 @@
                     if (this.fromApiJsonHelper.parameterExists(idParamName, interstRateChartElement)) {
                         final Long id = this.fromApiJsonHelper.extractLongNamed(idParamName, interstRateChartElement);
                         baseDataValidator.reset().parameter(idParamName).value(id).notNull().integerGreaterThanZero();
-                        this.chartSlabDataValidator.validateChartSlabsUpdate(interstRateChartElement, baseDataValidator, locale);
+                        this.chartSlabDataValidator.validateChartSlabsUpdate(interstRateChartElement, baseDataValidator, locale, isPrimaryGroupingByAmount);
                     } else {
-                        this.chartSlabDataValidator.validateChartSlabsCreate(interstRateChartElement, baseDataValidator, locale);
+                        this.chartSlabDataValidator.validateChartSlabsCreate(interstRateChartElement, baseDataValidator, locale, isPrimaryGroupingByAmount);
                     }
                 }
             }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/data/InterestRateChartSlabDataValidator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/data/InterestRateChartSlabDataValidator.java
index 45b0ba4..fa7f26a 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/data/InterestRateChartSlabDataValidator.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/data/InterestRateChartSlabDataValidator.java
@@ -84,12 +84,14 @@
         final String currencyCode = this.fromApiJsonHelper.extractStringNamed(currencyCodeParamName, element);
         baseDataValidator.reset().parameter(currencyCodeParamName).value(currencyCode).notBlank().notExceedingLengthOf(3);
 
-        validateChartSlabsCreate(element, baseDataValidator, locale);
+        final Boolean isPrimaryGroupingByAmount = null;
+        validateChartSlabsCreate(element, baseDataValidator, locale, isPrimaryGroupingByAmount);
 
         throwExceptionIfValidationWarningsExist(dataValidationErrors);
     }
 
-    public void validateChartSlabsCreate(final JsonElement element, final DataValidatorBuilder baseDataValidator, final Locale locale) {
+    public void validateChartSlabsCreate(final JsonElement element, final DataValidatorBuilder baseDataValidator, final Locale locale,
+            final Boolean isPrimaryGroupingByAmount) {
 
         if (this.fromApiJsonHelper.parameterExists(descriptionParamName, element)) {
             final String description = this.fromApiJsonHelper.extractStringNamed(descriptionParamName, element);
@@ -97,17 +99,25 @@
         }
 
         final Integer periodType = this.fromApiJsonHelper.extractIntegerNamed(periodTypeParamName, element, locale);
-        baseDataValidator.reset().parameter(periodTypeParamName).value(periodType).notNull()
-                .isOneOfTheseValues(PeriodFrequencyType.integerValues());
-
+        if (this.fromApiJsonHelper.parameterExists(periodTypeParamName, element)) {
+            baseDataValidator.reset().parameter(periodTypeParamName).value(periodType)
+                    .isOneOfTheseValues(PeriodFrequencyType.integerValues());
+        }
         Integer toPeriod = null;
 
         final Integer fromPeriod = this.fromApiJsonHelper.extractIntegerNamed(fromPeriodParamName, element, locale);
-        baseDataValidator.reset().parameter(fromPeriodParamName).value(fromPeriod).notNull().integerZeroOrGreater();
+        if (this.fromApiJsonHelper.parameterExists(fromPeriodParamName, element)) {
+            baseDataValidator.reset().parameter(fromPeriodParamName).value(fromPeriod).integerZeroOrGreater();
+        }
+
+        if ((isPrimaryGroupingByAmount != null && !isPrimaryGroupingByAmount) || (periodType != null || fromPeriod != null)) {
+            baseDataValidator.reset().parameter(periodTypeParamName).value(periodType).notNull();
+            baseDataValidator.reset().parameter(fromPeriodParamName).value(fromPeriod).notNull();
+        }
 
         if (this.fromApiJsonHelper.parameterExists(toPeriodParamName, element)) {
             toPeriod = this.fromApiJsonHelper.extractIntegerNamed(toPeriodParamName, element, locale);
-            baseDataValidator.reset().parameter(toPeriodParamName).value(toPeriod).notNull().integerZeroOrGreater();
+            baseDataValidator.reset().parameter(toPeriodParamName).value(toPeriod).integerGreaterThanZero();
         }
 
         if (fromPeriod != null && toPeriod != null) {
@@ -115,21 +125,26 @@
                 baseDataValidator.parameter(fromPeriodParamName).value(fromPeriod).failWithCode("fromperiod.greater.than.to.period");
             }
         }
-        BigDecimal amountRangeFrom = null;
-        BigDecimal amountRangeTo = null;
+        final BigDecimal amountRangeFrom = this.fromApiJsonHelper.extractBigDecimalNamed(amountRangeFromParamName, element, locale);
+        final BigDecimal amountRangeTo = this.fromApiJsonHelper.extractBigDecimalNamed(amountRangeToParamName, element, locale);
         if (this.fromApiJsonHelper.parameterExists(amountRangeFromParamName, element)) {
-            amountRangeFrom = this.fromApiJsonHelper.extractBigDecimalNamed(amountRangeFromParamName, element, locale);
-            baseDataValidator.reset().parameter(amountRangeFromParamName).value(amountRangeFrom).notNull().positiveAmount();
+            baseDataValidator.reset().parameter(amountRangeFromParamName).value(amountRangeFrom).zeroOrPositiveAmount();
+            if (isPrimaryGroupingByAmount != null && isPrimaryGroupingByAmount) {
+                baseDataValidator.reset().parameter(amountRangeFromParamName).value(amountRangeFrom).notNull();
+            }
         }
 
         if (this.fromApiJsonHelper.parameterExists(amountRangeToParamName, element)) {
-            amountRangeTo = this.fromApiJsonHelper.extractBigDecimalNamed(amountRangeToParamName, element, locale);
-            baseDataValidator.reset().parameter(amountRangeToParamName).value(amountRangeTo).notNull().positiveAmount();
+            baseDataValidator.reset().parameter(amountRangeToParamName).value(amountRangeTo).positiveAmount();
+        }
+
+        if (amountRangeFrom == null && fromPeriod == null) {
+            baseDataValidator.failWithCodeNoParameterAddedToErrorCode("fromperiod.or.amountRangeFrom.required");
         }
 
         if (amountRangeFrom != null && amountRangeTo != null) {
             if (amountRangeFrom.compareTo(amountRangeTo) > 1) {
-                baseDataValidator.parameter(fromPeriodParamName).value(fromPeriod).failWithCode("fromperiod.greater.than.toperiod");
+                baseDataValidator.parameter(amountRangeFromParamName).value(fromPeriod).failWithCode("from.amount.greater.than.to.amount");
             }
         }
 
@@ -152,12 +167,14 @@
         final JsonElement element = this.fromApiJsonHelper.parse(json);
         final JsonObject objectElement = element.getAsJsonObject();
         final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(objectElement);
-        validateChartSlabsUpdate(element, baseDataValidator, locale);
+        final Boolean isPrimaryGroupingByAmount = null;
+        validateChartSlabsUpdate(element, baseDataValidator, locale, isPrimaryGroupingByAmount);
 
         throwExceptionIfValidationWarningsExist(dataValidationErrors);
     }
 
-    public void validateChartSlabsUpdate(final JsonElement element, final DataValidatorBuilder baseDataValidator, final Locale locale) {
+    public void validateChartSlabsUpdate(final JsonElement element, final DataValidatorBuilder baseDataValidator, final Locale locale,
+            final Boolean isPrimaryGroupingByAmount) {
 
         if (this.fromApiJsonHelper.parameterExists(descriptionParamName, element)) {
             final String description = this.fromApiJsonHelper.extractStringNamed(descriptionParamName, element);
@@ -166,8 +183,12 @@
 
         if (this.fromApiJsonHelper.parameterExists(periodTypeParamName, element)) {
             final Integer periodType = this.fromApiJsonHelper.extractIntegerNamed(periodTypeParamName, element, locale);
-            baseDataValidator.reset().parameter(periodTypeParamName).value(periodType).notNull()
+            baseDataValidator.reset().parameter(periodTypeParamName).value(periodType)
                     .isOneOfTheseValues(PeriodFrequencyType.integerValues());
+            if (isPrimaryGroupingByAmount != null && !isPrimaryGroupingByAmount) {
+                baseDataValidator.reset().parameter(periodTypeParamName).value(periodType).notNull();
+            }
+
         }
 
         Integer fromPeriod = null;
@@ -175,12 +196,15 @@
 
         if (this.fromApiJsonHelper.parameterExists(fromPeriodParamName, element)) {
             fromPeriod = this.fromApiJsonHelper.extractIntegerNamed(fromPeriodParamName, element, locale);
-            baseDataValidator.reset().parameter(fromPeriodParamName).value(fromPeriod).notNull().integerGreaterThanNumber(-1);
+            baseDataValidator.reset().parameter(fromPeriodParamName).value(fromPeriod).integerZeroOrGreater();
+            if (isPrimaryGroupingByAmount != null && !isPrimaryGroupingByAmount) {
+                baseDataValidator.reset().parameter(fromPeriodParamName).value(fromPeriod).notNull();
+            }
         }
 
         if (this.fromApiJsonHelper.parameterExists(toPeriodParamName, element)) {
             toPeriod = this.fromApiJsonHelper.extractIntegerNamed(toPeriodParamName, element, locale);
-            baseDataValidator.reset().parameter(toPeriodParamName).value(toPeriod).notNull().integerGreaterThanNumber(-1);
+            baseDataValidator.reset().parameter(toPeriodParamName).value(toPeriod).integerGreaterThanZero();
         }
 
         if (fromPeriod != null && toPeriod != null) {
@@ -192,12 +216,15 @@
         BigDecimal amountRangeTo = null;
         if (this.fromApiJsonHelper.parameterExists(amountRangeFromParamName, element)) {
             amountRangeFrom = this.fromApiJsonHelper.extractBigDecimalNamed(amountRangeFromParamName, element, locale);
-            baseDataValidator.reset().parameter(amountRangeFromParamName).value(amountRangeFrom).notNull().positiveAmount();
+            baseDataValidator.reset().parameter(amountRangeFromParamName).value(amountRangeFrom).zeroOrPositiveAmount();
+            if (isPrimaryGroupingByAmount != null && isPrimaryGroupingByAmount) {
+                baseDataValidator.reset().parameter(amountRangeFromParamName).value(amountRangeFrom).notNull();
+            }
         }
 
         if (this.fromApiJsonHelper.parameterExists(amountRangeToParamName, element)) {
             amountRangeTo = this.fromApiJsonHelper.extractBigDecimalNamed(amountRangeToParamName, element, locale);
-            baseDataValidator.reset().parameter(amountRangeToParamName).value(amountRangeTo).notNull().positiveAmount();
+            baseDataValidator.reset().parameter(amountRangeToParamName).value(amountRangeTo).positiveAmount();
         }
 
         if (amountRangeFrom != null && amountRangeTo != null) {
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/domain/InterestRateChart.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/domain/InterestRateChart.java
index 428acb3..3537106 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/domain/InterestRateChart.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/domain/InterestRateChart.java
@@ -51,6 +51,7 @@
 import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
 import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
 import org.apache.fineract.portfolio.interestratechart.InterestRateChartApiConstants;
+import org.apache.fineract.portfolio.interestratechart.InterestRateChartSlabApiConstants;
 import org.apache.fineract.portfolio.savings.SavingsPeriodFrequencyType;
 import org.joda.time.LocalDate;
 import org.springframework.data.jpa.domain.AbstractPersistable;
@@ -82,12 +83,11 @@
         final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
         final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
                 .resource(INTERESTRATE_CHART_RESOURCE_NAME);
-
+        this.chartFields = chartFields;
         // validate before setting the other fields
         this.validateChartSlabs(baseDataValidator);
         this.throwExceptionIfValidationWarningsExist(dataValidationErrors);
 
-        this.chartFields = chartFields;
         this.addChartSlabs(interestRateChartSlabs);
 
     }
@@ -97,22 +97,85 @@
 
         Integer tmpPeriodType = null;
         List<InterestRateChartSlab> chartSlabsList = new ArrayList<>(chartSlabs);
+        boolean isPrimaryGroupingByAmount = this.chartFields.isPrimaryGroupingByAmount();
+        chartSlabsList.sort(new InterestRateChartSlabComparator<InterestRateChartSlab>(isPrimaryGroupingByAmount));
+        boolean isPeriodChart = !isPrimaryGroupingByAmount;
+        boolean isAmountChart = isPrimaryGroupingByAmount;
 
         for (int i = 0; i < chartSlabsList.size(); i++) {
             InterestRateChartSlab iSlabs = chartSlabsList.get(i);
-            if (tmpPeriodType == null) {
+            if (!iSlabs.slabFields().isValidChart(isPrimaryGroupingByAmount)) {
+                if (isPrimaryGroupingByAmount) {
+                    baseDataValidator.parameter(InterestRateChartSlabApiConstants.amountRangeFromParamName).failWithCode("cannot.be.blank");
+                } else {
+                    baseDataValidator.parameter(InterestRateChartSlabApiConstants.fromPeriodParamName).failWithCode("cannot.be.blank");
+                }
+
+            } else if (i > 0) {
+                if (isPeriodChart ^ iSlabs.slabFields().fromPeriod() != null) {
+                    baseDataValidator.failWithCodeNoParameterAddedToErrorCode("chart.slabs.period.range.incomplete");
+                    isPeriodChart = isPeriodChart || iSlabs.slabFields().fromPeriod() != null;
+                }
+                if (isAmountChart ^ iSlabs.slabFields().getAmountRangeFrom() != null) {
+                    baseDataValidator.failWithCodeNoParameterAddedToErrorCode("chart.slabs.amount.range.incomplete");
+                    isAmountChart = isAmountChart || iSlabs.slabFields().getAmountRangeFrom() != null;
+                }
+            }
+
+            if (i == 0) {
                 tmpPeriodType = iSlabs.slabFields().periodType();
-            } else if (!iSlabs.slabFields().periodType().equals(tmpPeriodType)) {
+                if (iSlabs.slabFields().isNotProperChartStart()) {
+                    baseDataValidator.failWithCodeNoParameterAddedToErrorCode("chart.slabs.range.start.incorrect", iSlabs.slabFields()
+                            .fromPeriod(), iSlabs.slabFields().getAmountRangeFrom());
+                }
+                isAmountChart = isAmountChart || iSlabs.slabFields().getAmountRangeFrom() != null;
+                isPeriodChart = isPeriodChart || iSlabs.slabFields().fromPeriod() != null;
+            } else if (iSlabs.slabFields().periodType() != null && !iSlabs.slabFields().periodType().equals(tmpPeriodType)) {
                 baseDataValidator.parameter(periodTypeParamName).value(iSlabs.slabFields().periodType())
                         .failWithCode("period.type.is.not.same", tmpPeriodType);
             }
-            for (int j = i + 1; j < chartSlabsList.size(); j++) {
-                InterestRateChartSlab jSlabs = chartSlabsList.get(j);
-                if (iSlabs.slabFields().isPeriodOverlapping(jSlabs.slabFields())) {
-                    baseDataValidator
-                            .failWithCodeNoParameterAddedToErrorCode("chart.slabs.period.overlapping", iSlabs.slabFields().fromPeriod(),
-                                    iSlabs.slabFields().toPeriod(), jSlabs.slabFields().fromPeriod(), jSlabs.slabFields().toPeriod());
+            if (i + 1 < chartSlabsList.size()) {
+                InterestRateChartSlab nextSlabs = chartSlabsList.get(i + 1);
+                if (iSlabs.slabFields().isValidChart(isPrimaryGroupingByAmount)
+                        && nextSlabs.slabFields().isValidChart(isPrimaryGroupingByAmount)) {
+                    if (iSlabs.slabFields().isRateChartOverlapping(nextSlabs.slabFields(), isPrimaryGroupingByAmount)) {
+                        baseDataValidator.failWithCodeNoParameterAddedToErrorCode("chart.slabs.range.overlapping", iSlabs.slabFields()
+                                .fromPeriod(), iSlabs.slabFields().toPeriod(), nextSlabs.slabFields().fromPeriod(), nextSlabs.slabFields()
+                                .toPeriod(), iSlabs.slabFields().getAmountRangeFrom(), iSlabs.slabFields().getAmountRangeTo(), nextSlabs
+                                .slabFields().getAmountRangeFrom(), nextSlabs.slabFields().getAmountRangeTo());
+                    } else if (iSlabs.slabFields().isRateChartHasGap(nextSlabs.slabFields(), isPrimaryGroupingByAmount)) {
+                        baseDataValidator.failWithCodeNoParameterAddedToErrorCode("chart.slabs.range.has.gap", iSlabs.slabFields()
+                                .fromPeriod(), iSlabs.slabFields().toPeriod(), nextSlabs.slabFields().fromPeriod(), nextSlabs.slabFields()
+                                .toPeriod(), iSlabs.slabFields().getAmountRangeFrom(), iSlabs.slabFields().getAmountRangeTo(), nextSlabs
+                                .slabFields().getAmountRangeFrom(), nextSlabs.slabFields().getAmountRangeTo());
+                    }
+                    if (isPrimaryGroupingByAmount) {
+                        if (!iSlabs.slabFields().isAmountSame(nextSlabs.slabFields())) {
+                            if (InterestRateChartSlabFields.isNotProperPeriodStart(nextSlabs.slabFields())) {
+                                baseDataValidator.failWithCodeNoParameterAddedToErrorCode("chart.slabs.period.range.start.incorrect",
+                                        nextSlabs.slabFields().toPeriod());
+                            }
+                            if (iSlabs.slabFields().toPeriod() != null) {
+                                baseDataValidator.failWithCodeNoParameterAddedToErrorCode("chart.slabs.period.range.end.incorrect", iSlabs
+                                        .slabFields().toPeriod());
+                            }
+
+                        }
+                    } else if (!iSlabs.slabFields().isPeriodsSame(nextSlabs.slabFields())) {
+                        if (InterestRateChartSlabFields.isNotProperAmountStart(nextSlabs.slabFields())) {
+                            baseDataValidator.failWithCodeNoParameterAddedToErrorCode("chart.slabs.amount.range.start.incorrect", nextSlabs
+                                    .slabFields().getAmountRangeFrom());
+                        }
+                        if (iSlabs.slabFields().getAmountRangeTo() != null) {
+                            baseDataValidator.failWithCodeNoParameterAddedToErrorCode("chart.slabs.amount.range.end.incorrect", iSlabs
+                                    .slabFields().getAmountRangeTo());
+                        }
+
+                    }
                 }
+            } else if (iSlabs.slabFields().isNotProperPriodEnd()) {
+                baseDataValidator.failWithCodeNoParameterAddedToErrorCode("chart.slabs.range.end.incorrect",
+                        iSlabs.slabFields().toPeriod(), iSlabs.slabFields().getAmountRangeTo());
             }
         }
     }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/domain/InterestRateChartFields.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/domain/InterestRateChartFields.java
index ca1f1b0..2b7b7a8 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/domain/InterestRateChartFields.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/domain/InterestRateChartFields.java
@@ -24,6 +24,7 @@
 import static org.apache.fineract.portfolio.interestratechart.InterestRateChartApiConstants.fromDateParamName;
 import static org.apache.fineract.portfolio.interestratechart.InterestRateChartApiConstants.localeParamName;
 import static org.apache.fineract.portfolio.interestratechart.InterestRateChartApiConstants.nameParamName;
+import static org.apache.fineract.portfolio.interestratechart.InterestRateChartApiConstants.isPrimaryGroupingByAmountParamName;
 
 import java.util.Date;
 import java.util.Map;
@@ -56,19 +57,24 @@
     @Column(name = "end_date", nullable = false)
     private Date endDate;
 
+    @Column(name = "is_primary_grouping_by_amount", nullable = false)
+    private boolean isPrimaryGroupingByAmount;
+
     protected InterestRateChartFields() {
         //
     }
 
-    public static InterestRateChartFields createNew(String name, String description, LocalDate fromDate, LocalDate toDate) {
-        return new InterestRateChartFields(name, description, fromDate, toDate);
+    public static InterestRateChartFields createNew(String name, String description, LocalDate fromDate, LocalDate toDate,
+            boolean isPrimaryGroupingByAmount) {
+        return new InterestRateChartFields(name, description, fromDate, toDate, isPrimaryGroupingByAmount);
     }
 
-    private InterestRateChartFields(String name, String description, LocalDate fromDate, LocalDate toDate) {
+    private InterestRateChartFields(String name, String description, LocalDate fromDate, LocalDate toDate, boolean isPrimaryGroupingByAmount) {
         this.name = name;
         this.description = description;
         this.fromDate = fromDate.toDate();
         this.endDate = (toDate == null) ? null : toDate.toDate();
+        this.isPrimaryGroupingByAmount = isPrimaryGroupingByAmount;
     }
 
     public void update(JsonCommand command, final Map<String, Object> actualChanges, final DataValidatorBuilder baseDataValidator) {
@@ -106,6 +112,12 @@
             this.endDate = newValue.toDate();
         }
 
+        if (command.isChangeInBooleanParameterNamed(isPrimaryGroupingByAmountParamName, this.isPrimaryGroupingByAmount)) {
+            final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(isPrimaryGroupingByAmountParamName);
+            actualChanges.put(isPrimaryGroupingByAmountParamName, newValue);
+            this.isPrimaryGroupingByAmount = newValue;
+        }
+
         if (isFromDateAfterToDate()) {
             baseDataValidator.parameter(fromDateParamName).value(fromDate).failWithCode("from.date.is.after.to.date");
         }
@@ -144,20 +156,22 @@
         final LocalDate thatFromDate = that.getFromDateAsLocalDate();
         LocalDate thatEndDate = that.getEndDateAsLocalDate();
         thatEndDate = thatEndDate == null ? DateUtils.getLocalDateOfTenant() : thatEndDate;
-        
+
         final LocalDateInterval thisInterval = LocalDateInterval.create(thisFromDate, thisEndDate);
         final LocalDateInterval thatInterval = LocalDateInterval.create(thatFromDate, thatEndDate);
-        
-        if(thisInterval.containsPortionOf(thatInterval) || thatInterval.containsPortionOf(thisInterval)){
-            return true;
-        }
+
+        if (thisInterval.containsPortionOf(thatInterval) || thatInterval.containsPortionOf(thisInterval)) { return true; }
         return false;// no overlapping
     }
-    
-    public boolean isApplicableChartFor(final LocalDate target){
+
+    public boolean isApplicableChartFor(final LocalDate target) {
         final LocalDate endDate = this.endDate == null ? DateUtils.getLocalDateOfTenant() : this.getEndDateAsLocalDate();
         final LocalDateInterval interval = LocalDateInterval.create(getFromDateAsLocalDate(), endDate);
         return interval.contains(target);
     }
 
+    public boolean isPrimaryGroupingByAmount() {
+        return this.isPrimaryGroupingByAmount;
+    }
+
 }
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/domain/InterestRateChartSlabComparator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/domain/InterestRateChartSlabComparator.java
new file mode 100644
index 0000000..19f4147
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/domain/InterestRateChartSlabComparator.java
@@ -0,0 +1,92 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.interestratechart.domain;
+
+import java.math.BigDecimal;
+import java.util.Comparator;
+
+import org.apache.fineract.portfolio.savings.domain.DepositAccountInterestRateChartSlabs;
+
+/**
+ * Sort InterestRateChartSlab by input range 
+ */
+public class InterestRateChartSlabComparator<T> implements Comparator<T> {
+
+    private final boolean isPrimaryGroupingByAmount;
+
+    public InterestRateChartSlabComparator(final boolean isPrimaryGroupingByAmount) {
+        this.isPrimaryGroupingByAmount = isPrimaryGroupingByAmount;
+    }
+
+    @Override
+    public int compare(final T o1, final T o2) {
+        int compareResult = 0;
+        InterestRateChartSlabFields slabs1 = null;
+        InterestRateChartSlabFields slabs2 = null;
+        if (o1 instanceof InterestRateChartSlab) {
+            slabs1 = ((InterestRateChartSlab) o1).slabFields();
+            slabs2 = ((InterestRateChartSlab) o2).slabFields();
+        } else if (o1 instanceof DepositAccountInterestRateChartSlabs) {
+            slabs1 = ((DepositAccountInterestRateChartSlabs) o1).slabFields();
+            slabs2 = ((DepositAccountInterestRateChartSlabs) o2).slabFields();
+        } else {
+            return compareResult;
+        }
+
+        if (slabs1.isPeriodsSame(slabs2) && slabs1.isAmountSame(slabs2)) {
+            compareResult = 0;
+        } else {
+            if (isPrimaryGroupingByAmount) {
+                if (slabs1.isAmountSame(slabs2)) {
+                    compareResult = comparePeriods(slabs1, slabs2);
+                } else {
+                    compareResult = compareAmounts(slabs1, slabs2);
+                }
+            } else {
+                if (slabs1.isPeriodsSame(slabs2)) {
+                    compareResult = compareAmounts(slabs1, slabs2);
+                } else {
+                    compareResult = comparePeriods(slabs1, slabs2);
+                }
+            }
+        }
+        return compareResult;
+    }
+
+    private int comparePeriods(final InterestRateChartSlabFields slabs1, InterestRateChartSlabFields slabs2) {
+        int compareResult = 0;
+        Integer periodFrom1 = slabs1.fromPeriod();
+        Integer periodFrom2 = slabs2.fromPeriod();
+        if (periodFrom1 != null && periodFrom2 != null) {
+            compareResult = periodFrom1.compareTo(periodFrom2);
+        }
+        return compareResult;
+    }
+
+    private int compareAmounts(final InterestRateChartSlabFields slabs1, InterestRateChartSlabFields slabs2) {
+        int compareResult = 0;
+        BigDecimal amountFrom1 = slabs1.getAmountRangeFrom();
+        BigDecimal amountFrom2 = slabs2.getAmountRangeFrom();
+        if (amountFrom1 != null && amountFrom2 != null) {
+            compareResult = amountFrom1.compareTo(amountFrom2);
+        }
+        return compareResult;
+    }
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/domain/InterestRateChartSlabFields.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/domain/InterestRateChartSlabFields.java
index 334772c..b8c00de 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/domain/InterestRateChartSlabFields.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/domain/InterestRateChartSlabFields.java
@@ -51,15 +51,23 @@
     @Column(name = "period_type_enum", nullable = false)
     private Integer periodType;
 
-    @Column(name = "from_period", nullable = false)
+    @Column(name = "from_period")
     private Integer fromPeriod;
 
-    @Column(name = "to_period", nullable = true)
+    @Column(name = "to_period")
     private Integer toPeriod;
 
     @Column(name = "amount_range_from", scale = 6, precision = 19)
     private BigDecimal amountRangeFrom;
 
+    public BigDecimal getAmountRangeFrom() {
+        return this.amountRangeFrom;
+    }
+
+    public BigDecimal getAmountRangeTo() {
+        return this.amountRangeTo;
+    }
+
     @Column(name = "amount_range_to", scale = 6, precision = 19)
     private BigDecimal amountRangeTo;
 
@@ -84,7 +92,7 @@
             final Integer fromPeriod, final Integer toPeriod, final BigDecimal amountRangeFrom, final BigDecimal amountRangeTo,
             final BigDecimal annualInterestRate, final String currencyCode) {
         this.description = description;
-        this.periodType = (periodFrequencyType == null) ? null : periodFrequencyType.getValue();
+        this.periodType = (periodFrequencyType == null || periodFrequencyType.isInvalid()) ? null : periodFrequencyType.getValue();
         this.fromPeriod = fromPeriod;
         this.toPeriod = toPeriod;
         this.amountRangeFrom = amountRangeFrom;
@@ -183,17 +191,129 @@
         return this.toPeriod;
     }
 
-    public boolean isPeriodOverlapping(final InterestRateChartSlabFields that) {
-        if (that.toPeriod == null) {
-            if (this.toPeriod == null) { return true; }
-            return that.fromPeriod <= this.toPeriod;
+    public boolean isRateChartHasGap(final InterestRateChartSlabFields that, final boolean isPrimaryGroupingByAmount) {
+        boolean isPeriodSame = isPeriodsSame(that);
+        boolean isAmountSame = isAmountSame(that);
+        boolean hasPeriods = this.fromPeriod != null || that.fromPeriod != null;
+        boolean hasAmounts = this.amountRangeFrom != null || that.amountRangeFrom != null;
+        if (isPrimaryGroupingByAmount) {
+            if (isAmountSame) {
+                if (hasPeriods) {
+                    if (this.toPeriod == null) { return true; }
+                    return isNotProperPeriodStart(that.fromPeriod);
+                }
+            } else {
+                return isNotProperAmountStart(that.amountRangeFrom) || isNotProperPeriodStart(that);
+            }
+        } else {
+            if (isPeriodSame) {
+                if (hasAmounts) {
+                    if (this.amountRangeTo == null) { return true; }
+                    return isNotProperAmountStart(that.amountRangeFrom);
+                }
+            } else {
+                return isNotProperPeriodStart(that.fromPeriod) || isNotProperAmountStart(that);
+            }
         }
+        return false;
+    }
+
+    public boolean isValidChart(boolean isPrimaryGroupingByAmount) {
+        return (!isPrimaryGroupingByAmount && this.fromPeriod != null) || (isPrimaryGroupingByAmount && this.amountRangeFrom != null);
+    }
+
+    public boolean isNotProperChartStart() {
+        return isNotProperPeriodStart(this) || isNotProperAmountStart(this);
+    }
+
+    public static boolean isNotProperAmountStart(final InterestRateChartSlabFields interestRateChartSlabFields) {
+        return interestRateChartSlabFields.amountRangeFrom != null
+                && (interestRateChartSlabFields.amountRangeFrom.compareTo(BigDecimal.ONE) != 0 && interestRateChartSlabFields.amountRangeFrom
+                        .compareTo(BigDecimal.ZERO) != 0);
+    }
+
+    private boolean isNotProperAmountStart(final BigDecimal amount) {
+        return this.amountRangeTo == null || (amount != null && amount.compareTo(this.amountRangeTo.add(BigDecimal.ONE)) != 0);
+    }
+
+    private boolean isNotProperPeriodStart(final Integer period) {
+        return this.toPeriod == null || (period != null && period.compareTo(this.toPeriod + 1) != 0);
+    }
+
+    public static boolean isNotProperPeriodStart(InterestRateChartSlabFields interestRateChartSlabFields) {
+        return interestRateChartSlabFields.fromPeriod != null
+                && !(interestRateChartSlabFields.fromPeriod.equals(1) || interestRateChartSlabFields.fromPeriod.equals(0));
+    }
+
+    public boolean isNotProperPriodEnd() {
+        return !(this.toPeriod == null && this.amountRangeTo == null);
+
+    }
+
+    public boolean isRateChartOverlapping(final InterestRateChartSlabFields that, final boolean isPrimaryGroupingByAmount) {
+        boolean isPeriodOverLapping = isPeriodOverlapping(that);
+        boolean isAmountOverLapping = isAmountOverlapping(that);
+        boolean isPeriodSame = isPeriodsSame(that);
+        boolean isAmountSame = isAmountSame(that);
+        boolean isOverlapping = false;
+        if (isPrimaryGroupingByAmount) {
+            isOverlapping = (isAmountOverLapping && !isAmountSame) || (isPeriodOverLapping && isAmountSame);
+        } else {
+            isOverlapping = (isPeriodOverLapping && !isPeriodSame) || (isAmountOverLapping && isPeriodSame);
+        }
+
+        return isOverlapping;
+    }
+
+    private boolean isPeriodOverlapping(final InterestRateChartSlabFields that) {
+        if (isIntegerSame(that.toPeriod, this.toPeriod)) {
+            return true;
+        } else if (isIntegerSame(that.fromPeriod, this.fromPeriod)) {
+            return true;
+        } else if (this.toPeriod == null) {
+            return true;
+        } else if (that.toPeriod == null) { return that.fromPeriod <= this.toPeriod; }
         return this.fromPeriod <= that.toPeriod && that.fromPeriod <= this.toPeriod;
     }
 
+    private boolean isAmountOverlapping(final InterestRateChartSlabFields that) {
+        if (isBigDecimalSame(that.amountRangeFrom, this.amountRangeFrom)) {
+            return true;
+        } else if (isBigDecimalSame(that.amountRangeTo, this.amountRangeTo)) {
+            return true;
+        } else if (this.amountRangeTo == null) {
+            return true;
+        } else if (that.amountRangeTo == null) { return that.amountRangeFrom.compareTo(this.amountRangeTo) < 1; }
+        return this.amountRangeFrom.compareTo(that.amountRangeTo) < 1 && that.amountRangeFrom.compareTo(this.amountRangeTo) < 1;
+    }
+
+    public boolean isAmountSame(final InterestRateChartSlabFields that) {
+        return isBigDecimalSame(this.amountRangeFrom, that.amountRangeFrom) && isBigDecimalSame(this.amountRangeTo, that.amountRangeTo);
+    }
+
+    public boolean isPeriodsSame(final InterestRateChartSlabFields that) {
+        return isIntegerSame(this.fromPeriod, that.fromPeriod) && isIntegerSame(this.toPeriod, that.toPeriod);
+    }
+
+    public boolean isIntegerSame(final Integer obj1, final Integer obj2) {
+        if (obj1 == null || obj2 == null) {
+            if (obj1 == obj2) { return true; }
+            return false;
+        }
+        return obj1.equals(obj2);
+    }
+
+    public boolean isBigDecimalSame(final BigDecimal obj1, final BigDecimal obj2) {
+        if (obj1 == null || obj2 == null) {
+            if (obj1 == obj2) { return true; }
+            return false;
+        }
+        return obj1.compareTo(obj2) == 0;
+    }
+
     public boolean isBetweenPeriod(final LocalDate periodStartDate, final LocalDate periodEndDate) {
         final Integer compare = depositPeriod(periodStartDate, periodEndDate);
-        return (compare < this.fromPeriod || (this.toPeriod != null && compare > this.toPeriod)) ? false : true;
+        return isPeriodBetween(compare);
     }
 
     public boolean isAmountRangeProvided() {
@@ -233,8 +353,16 @@
             returnValue = depositAmount.compareTo(amountRangeFrom) >= 0 && depositAmount.compareTo(amountRangeTo) <= 0;
         } else if (amountRangeFrom != null) {
             returnValue = depositAmount.compareTo(amountRangeFrom) >= 0;
-        } else if (amountRangeTo != null) {
-            returnValue = depositAmount.compareTo(amountRangeTo) <= 0;
+        }
+        return returnValue;
+    }
+
+    public boolean isPeriodBetween(final Integer periods) {
+        boolean returnValue = true;
+        if (fromPeriod != null && toPeriod != null) {
+            returnValue = periods.compareTo(fromPeriod) >= 0 && periods.compareTo(toPeriod) <= 0;
+        } else if (fromPeriod != null) {
+            returnValue = periods.compareTo(fromPeriod) >= 0;
         }
         return returnValue;
     }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/service/InterestRateChartAssembler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/service/InterestRateChartAssembler.java
index a2a65db..a7f29e3 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/service/InterestRateChartAssembler.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/service/InterestRateChartAssembler.java
@@ -22,6 +22,7 @@
 import static org.apache.fineract.portfolio.interestratechart.InterestRateChartApiConstants.descriptionParamName;
 import static org.apache.fineract.portfolio.interestratechart.InterestRateChartApiConstants.endDateParamName;
 import static org.apache.fineract.portfolio.interestratechart.InterestRateChartApiConstants.fromDateParamName;
+import static org.apache.fineract.portfolio.interestratechart.InterestRateChartApiConstants.isPrimaryGroupingByAmountParamName;
 import static org.apache.fineract.portfolio.interestratechart.InterestRateChartApiConstants.nameParamName;
 import static org.apache.fineract.portfolio.interestratechart.InterestRateChartSlabApiConstants.currencyCodeParamName;
 
@@ -65,33 +66,38 @@
      * request
      */
     public InterestRateChart assembleFrom(final JsonCommand command) {
-
-        final JsonElement element = command.parsedJson();
         final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
-        @SuppressWarnings("unused")
         final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
                 .resource(INTERESTRATE_CHART_RESOURCE_NAME);
+        final JsonElement element = command.parsedJson();
         final String currencyCode = this.fromApiJsonHelper.extractStringNamed(currencyCodeParamName, element);
-        final InterestRateChart newChart = this.assembleFrom(element, currencyCode);
-
+        final InterestRateChart newChart = this.assembleFrom(element, currencyCode, baseDataValidator);
         throwExceptionIfValidationWarningsExist(dataValidationErrors);
         return newChart;
     }
 
-    public InterestRateChart assembleFrom(final JsonElement element, final String currencyCode) {
+    private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
+        if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
+    }
+
+    public InterestRateChart assembleFrom(final JsonElement element, final String currencyCode, final DataValidatorBuilder baseDataValidator) {
 
         final String name = this.fromApiJsonHelper.extractStringNamed(nameParamName, element);
         final String description = this.fromApiJsonHelper.extractStringNamed(descriptionParamName, element);
         final LocalDate fromDate = this.fromApiJsonHelper.extractLocalDateNamed(fromDateParamName, element);
         final LocalDate toDate = this.fromApiJsonHelper.extractLocalDateNamed(endDateParamName, element);
-        
+        Boolean isPrimaryGroupingByAmount = this.fromApiJsonHelper.extractBooleanNamed(isPrimaryGroupingByAmountParamName, element);
+        if (isPrimaryGroupingByAmount == null) {
+            isPrimaryGroupingByAmount = false;
+        }
 
         // assemble chart Slabs
-        final Collection<InterestRateChartSlab> newChartSlabs = this.chartSlabAssembler.assembleChartSlabsFrom(element,
-                currencyCode);
+        final Collection<InterestRateChartSlab> newChartSlabs = this.chartSlabAssembler.assembleChartSlabsFrom(element, currencyCode);
 
-        final InterestRateChartFields fields = InterestRateChartFields.createNew(name, description, fromDate, toDate);
+        final InterestRateChartFields fields = InterestRateChartFields.createNew(name, description, fromDate, toDate,
+                isPrimaryGroupingByAmount);
         final InterestRateChart newChart = InterestRateChart.createNew(fields, newChartSlabs);
+        newChart.validateChartSlabs(baseDataValidator);
         return newChart;
     }
 
@@ -100,8 +106,4 @@
                 .findOneWithNotFoundDetection(interestRateChartId);
         return interestRateChart;
     }
-
-    private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
-        if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
-    }
 }
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/service/InterestRateChartReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/service/InterestRateChartReadPlatformServiceImpl.java
index 86eefad..d03e502 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/service/InterestRateChartReadPlatformServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/service/InterestRateChartReadPlatformServiceImpl.java
@@ -86,8 +86,21 @@
     @Override
     public Collection<InterestRateChartData> retrieveAllWithSlabs(Long productId) {
         this.context.authenticatedUser();
-        String sql = "select " + this.chartExtractor.schema() + " where sp.id = ? order by irc.id, ircd.id";
-        return this.jdbcTemplate.query(sql, this.chartExtractor, new Object[] { productId });
+        StringBuilder sql = new StringBuilder();
+        sql.append("select ");
+        sql.append(this.chartExtractor.schema());
+        sql.append(" where sp.id = ? order by irc.id, ");
+        sql.append("CASE ");
+        sql.append("WHEN isPrimaryGroupingByAmount then ircd.amount_range_from ");
+        sql.append("WHEN isPrimaryGroupingByAmount then ircd.amount_range_to ");
+        sql.append("END,");
+        sql.append("ircd.from_period, ircd.to_period,");
+        sql.append("CASE ");
+        sql.append("WHEN !isPrimaryGroupingByAmount then ircd.amount_range_from ");
+        sql.append("WHEN !isPrimaryGroupingByAmount then ircd.amount_range_to ");
+        sql.append("END");
+        
+        return this.jdbcTemplate.query(sql.toString(), this.chartExtractor, new Object[] { productId });
     }
 
     @Override
@@ -177,6 +190,7 @@
             sqlBuilder
                     .append("irc.id as ircId, irc.name as ircName, irc.description as ircDescription,")
                     .append("irc.from_date as ircFromDate, irc.end_date as ircEndDate, ")
+                    .append("irc.is_primary_grouping_by_amount as isPrimaryGroupingByAmount, ")
                     .append("ircd.id as ircdId, ircd.description as ircdDescription, ircd.period_type_enum ircdPeriodTypeId, ")
                     .append("ircd.from_period as ircdFromPeriod, ircd.to_period as ircdToPeriod, ircd.amount_range_from as ircdAmountRangeFrom, ")
                     .append("ircd.amount_range_to as ircdAmountRangeTo, ircd.annual_interest_rate as ircdAnnualInterestRate, ")
@@ -239,6 +253,7 @@
 
             sqlBuilder.append("irc.id as ircId, irc.name as ircName, irc.description as ircDescription, ")
                     .append("irc.from_date as ircFromDate, irc.end_date as ircEndDate, ")
+                    .append("irc.is_primary_grouping_by_amount as isPrimaryGroupingByAmount, ")
                     .append("sp.id as savingsProductId, sp.name as savingsProductName ").append("from ")
                     .append("m_interest_rate_chart irc ")
                     .append("left join m_deposit_product_interest_rate_chart dpirc on irc.id=dpirc.interest_rate_chart_id ")
@@ -253,10 +268,11 @@
             final String description = rs.getString("ircDescription");
             final LocalDate fromDate = JdbcSupport.getLocalDate(rs, "ircFromDate");
             final LocalDate endDate = JdbcSupport.getLocalDate(rs, "ircEndDate");
+            final boolean isPrimaryGroupingByAmount = rs.getBoolean("isPrimaryGroupingByAmount");
             final Long savingsProductId = JdbcSupport.getLongDefaultToNullIfZero(rs, "savingsProductId");
             final String savingsProductName = rs.getString("savingsProductName");
 
-            return InterestRateChartData.instance(id, name, description, fromDate, endDate, savingsProductId, savingsProductName);
+            return InterestRateChartData.instance(id, name, description, fromDate, endDate, isPrimaryGroupingByAmount, savingsProductId, savingsProductName);
         }
 
     }
@@ -299,7 +315,10 @@
             final Integer fromPeriod = JdbcSupport.getInteger(rs, "ircdFromPeriod");
             final Integer toPeriod = JdbcSupport.getInteger(rs, "ircdToPeriod");
             final Integer periodTypeId = JdbcSupport.getInteger(rs, "ircdPeriodTypeId");
-            final EnumOptionData periodType = InterestRateChartEnumerations.periodType(periodTypeId);
+            EnumOptionData periodType = null;
+            if (periodTypeId != null) {
+                periodType = InterestRateChartEnumerations.periodType(periodTypeId);
+            }
             final BigDecimal amountRangeFrom = rs.getBigDecimal("ircdAmountRangeFrom");
             final BigDecimal amountRangeTo = rs.getBigDecimal("ircdAmountRangeTo");
             final BigDecimal annualInterestRate = rs.getBigDecimal("ircdAnnualInterestRate");
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/DepositAccountInterestRateChartData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/DepositAccountInterestRateChartData.java
index 7b78f03..735f95d 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/DepositAccountInterestRateChartData.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/DepositAccountInterestRateChartData.java
@@ -18,9 +18,8 @@
  */
 package org.apache.fineract.portfolio.savings.data;
 
+import java.util.ArrayList;
 import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
 
 import org.apache.fineract.infrastructure.codes.data.CodeValueData;
 import org.apache.fineract.infrastructure.core.data.EnumOptionData;
@@ -38,10 +37,11 @@
     private final String description;
     private final LocalDate fromDate;
     private final LocalDate endDate;
+    private final boolean isPrimaryGroupingByAmount;
     private final Long accountId;
     private final String accountNumber;
     // associations
-    private Set<DepositAccountInterestRateChartSlabData> chartSlabs;
+    private Collection<DepositAccountInterestRateChartSlabData> chartSlabs;
 
     // template
     private final Collection<EnumOptionData> periodTypes;
@@ -54,8 +54,8 @@
     private final Collection<CodeValueData> clientClassificationOptions;
 
     public static DepositAccountInterestRateChartData instance(Long id, String name, String description, LocalDate fromDate,
-            LocalDate endDate, Long accountId, String accountNumber, Set<DepositAccountInterestRateChartSlabData> chartSlabs,
-            Collection<EnumOptionData> periodTypes) {
+            LocalDate endDate, boolean isPrimaryGroupingByAmount, Long accountId, String accountNumber,
+            Collection<DepositAccountInterestRateChartSlabData> chartSlabs, Collection<EnumOptionData> periodTypes) {
 
         final Collection<EnumOptionData> entityTypeOptions = null;
         final Collection<EnumOptionData> attributeNameOptions = null;
@@ -64,17 +64,17 @@
         final Collection<CodeValueData> genderOptions = null;
         final Collection<CodeValueData> clientTypeOptions = null;
         final Collection<CodeValueData> clientClassificationOptions = null;
-        return new DepositAccountInterestRateChartData(id, name, description, fromDate, endDate, accountId, accountNumber, chartSlabs,
-                periodTypes, entityTypeOptions, attributeNameOptions, conditionTypeOptions, incentiveTypeOptions, genderOptions,
-                clientTypeOptions, clientClassificationOptions);
+        return new DepositAccountInterestRateChartData(id, name, description, fromDate, endDate, isPrimaryGroupingByAmount, accountId,
+                accountNumber, chartSlabs, periodTypes, entityTypeOptions, attributeNameOptions, conditionTypeOptions,
+                incentiveTypeOptions, genderOptions, clientTypeOptions, clientClassificationOptions);
     }
 
     public static DepositAccountInterestRateChartData from(InterestRateChartData productChartData) {
         final Long id = null;
         final Long accountId = null;
         final String accountNumber = null;
-        Set<DepositAccountInterestRateChartSlabData> fromProdChartSlabs = new HashSet<>();
-        Set<InterestRateChartSlabData> productChartSlabDatas = productChartData.chartSlabs();
+        Collection<DepositAccountInterestRateChartSlabData> fromProdChartSlabs = new ArrayList<>();
+        Collection<InterestRateChartSlabData> productChartSlabDatas = productChartData.chartSlabs();
         if (productChartSlabDatas != null) {
             for (InterestRateChartSlabData productChartSlabData : productChartSlabDatas) {
                 fromProdChartSlabs.add(DepositAccountInterestRateChartSlabData.from(productChartSlabData));
@@ -82,20 +82,20 @@
         }
 
         return new DepositAccountInterestRateChartData(id, productChartData.name(), productChartData.description(),
-                productChartData.fromDate(), productChartData.endDate(), accountId, accountNumber, fromProdChartSlabs,
-                productChartData.periodTypes(), productChartData.entityTypeOptions(), productChartData.attributeNameOptions(),
-                productChartData.conditionTypeOptions(), productChartData.incentiveTypeOptions(), productChartData.genderOptions(),
-                productChartData.clientTypeOptions(), productChartData.clientClassificationOptions());
+                productChartData.fromDate(), productChartData.endDate(), productChartData.isPrimaryGroupingByAmount(), accountId,
+                accountNumber, fromProdChartSlabs, productChartData.periodTypes(), productChartData.entityTypeOptions(),
+                productChartData.attributeNameOptions(), productChartData.conditionTypeOptions(), productChartData.incentiveTypeOptions(),
+                productChartData.genderOptions(), productChartData.clientTypeOptions(), productChartData.clientClassificationOptions());
     }
 
     public static DepositAccountInterestRateChartData withSlabs(DepositAccountInterestRateChartData interestRateChartData,
-            Set<DepositAccountInterestRateChartSlabData> chartSlabs) {
+            Collection<DepositAccountInterestRateChartSlabData> chartSlabs) {
         return new DepositAccountInterestRateChartData(interestRateChartData.id, interestRateChartData.name,
                 interestRateChartData.description, interestRateChartData.fromDate, interestRateChartData.endDate,
-                interestRateChartData.accountId, interestRateChartData.accountNumber, chartSlabs, interestRateChartData.periodTypes,
-                interestRateChartData.entityTypeOptions, interestRateChartData.attributeNameOptions,
-                interestRateChartData.conditionTypeOptions, interestRateChartData.incentiveTypeOptions,
-                interestRateChartData.genderOptions, interestRateChartData.clientTypeOptions,
+                interestRateChartData.isPrimaryGroupingByAmount, interestRateChartData.accountId, interestRateChartData.accountNumber,
+                chartSlabs, interestRateChartData.periodTypes, interestRateChartData.entityTypeOptions,
+                interestRateChartData.attributeNameOptions, interestRateChartData.conditionTypeOptions,
+                interestRateChartData.incentiveTypeOptions, interestRateChartData.genderOptions, interestRateChartData.clientTypeOptions,
                 interestRateChartData.clientClassificationOptions);
     }
 
@@ -106,9 +106,9 @@
             final Collection<CodeValueData> clientTypeOptions, final Collection<CodeValueData> clientClassificationOptions) {
         return new DepositAccountInterestRateChartData(interestRateChartData.id, interestRateChartData.name,
                 interestRateChartData.description, interestRateChartData.fromDate, interestRateChartData.endDate,
-                interestRateChartData.accountId, interestRateChartData.accountNumber, interestRateChartData.chartSlabs, periodTypes,
-                entityTypeOptions, attributeNameOptions, conditionTypeOptions, incentiveTypeOptions, genderOptions, clientTypeOptions,
-                clientClassificationOptions);
+                interestRateChartData.isPrimaryGroupingByAmount, interestRateChartData.accountId, interestRateChartData.accountNumber,
+                interestRateChartData.chartSlabs, periodTypes, entityTypeOptions, attributeNameOptions, conditionTypeOptions,
+                incentiveTypeOptions, genderOptions, clientTypeOptions, clientClassificationOptions);
     }
 
     public static DepositAccountInterestRateChartData template(Collection<EnumOptionData> periodTypes,
@@ -123,23 +123,26 @@
         final LocalDate endDate = null;
         final Long accountId = null;
         final String accountNumber = null;
-        final Set<DepositAccountInterestRateChartSlabData> chartSlabs = null;
-        return new DepositAccountInterestRateChartData(id, name, description, fromDate, endDate, accountId, accountNumber, chartSlabs,
-                periodTypes, entityTypeOptions, attributeNameOptions, conditionTypeOptions, incentiveTypeOptions, genderOptions,
-                clientTypeOptions, clientClassificationOptions);
+        final boolean isPrimaryGroupingByAmount = false;
+        final Collection<DepositAccountInterestRateChartSlabData> chartSlabs = null;
+        return new DepositAccountInterestRateChartData(id, name, description, fromDate, endDate, isPrimaryGroupingByAmount, accountId,
+                accountNumber, chartSlabs, periodTypes, entityTypeOptions, attributeNameOptions, conditionTypeOptions,
+                incentiveTypeOptions, genderOptions, clientTypeOptions, clientClassificationOptions);
     }
 
     private DepositAccountInterestRateChartData(Long id, String name, String description, LocalDate fromDate, LocalDate endDate,
-            Long accountId, String accountNumber, Set<DepositAccountInterestRateChartSlabData> chartSlabs,
-            Collection<EnumOptionData> periodTypes, final Collection<EnumOptionData> entityTypeOptions,
-            final Collection<EnumOptionData> attributeNameOptions, final Collection<EnumOptionData> conditionTypeOptions,
-            final Collection<EnumOptionData> incentiveTypeOptions, final Collection<CodeValueData> genderOptions,
-            final Collection<CodeValueData> clientTypeOptions, final Collection<CodeValueData> clientClassificationOptions) {
+            final boolean isPrimaryGroupingByAmount, Long accountId, String accountNumber,
+            Collection<DepositAccountInterestRateChartSlabData> chartSlabs, Collection<EnumOptionData> periodTypes,
+            final Collection<EnumOptionData> entityTypeOptions, final Collection<EnumOptionData> attributeNameOptions,
+            final Collection<EnumOptionData> conditionTypeOptions, final Collection<EnumOptionData> incentiveTypeOptions,
+            final Collection<CodeValueData> genderOptions, final Collection<CodeValueData> clientTypeOptions,
+            final Collection<CodeValueData> clientClassificationOptions) {
         this.id = id;
         this.name = name;
         this.description = description;
         this.fromDate = fromDate;
         this.endDate = endDate;
+        this.isPrimaryGroupingByAmount = isPrimaryGroupingByAmount;
         this.chartSlabs = chartSlabs;
         this.accountId = accountId;
         this.accountNumber = accountNumber;
@@ -155,7 +158,7 @@
 
     public void addChartSlab(final DepositAccountInterestRateChartSlabData chartSlab) {
         if (this.chartSlabs == null) {
-            this.chartSlabs = new HashSet<>();
+            this.chartSlabs = new ArrayList<>();
         }
 
         this.chartSlabs.add(chartSlab);
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountDomainServiceJpa.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountDomainServiceJpa.java
index ffaf648..0f2a1fa 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountDomainServiceJpa.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountDomainServiceJpa.java
@@ -35,16 +35,24 @@
 import org.apache.fineract.infrastructure.accountnumberformat.domain.EntityAccountType;
 import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
 import org.apache.fineract.infrastructure.core.api.JsonCommand;
+import org.apache.fineract.infrastructure.core.exception.GeneralPlatformDomainRuleException;
 import org.apache.fineract.infrastructure.core.service.DateUtils;
 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.Money;
 import org.apache.fineract.portfolio.account.PortfolioAccountType;
 import org.apache.fineract.portfolio.account.data.AccountTransferDTO;
 import org.apache.fineract.portfolio.account.domain.AccountTransferType;
 import org.apache.fineract.portfolio.account.service.AccountTransfersWritePlatformService;
+import org.apache.fineract.portfolio.calendar.domain.Calendar;
+import org.apache.fineract.portfolio.calendar.domain.CalendarEntityType;
+import org.apache.fineract.portfolio.calendar.domain.CalendarFrequencyType;
+import org.apache.fineract.portfolio.calendar.domain.CalendarInstance;
+import org.apache.fineract.portfolio.calendar.domain.CalendarInstanceRepository;
+import org.apache.fineract.portfolio.calendar.domain.CalendarType;
+import org.apache.fineract.portfolio.calendar.service.CalendarUtils;
 import org.apache.fineract.portfolio.client.domain.AccountNumberGenerator;
+import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
 import org.apache.fineract.portfolio.paymentdetail.domain.PaymentDetail;
 import org.apache.fineract.portfolio.savings.DepositAccountOnClosureType;
 import org.apache.fineract.portfolio.savings.DepositAccountType;
@@ -71,6 +79,7 @@
     private final AccountTransfersWritePlatformService accountTransfersWritePlatformService;
     private final ConfigurationDomainService configurationDomainService;
     private final AccountNumberFormatRepositoryWrapper accountNumberFormatRepository;
+    private final CalendarInstanceRepository calendarInstanceRepository;
 
     @Autowired
     public DepositAccountDomainServiceJpa(final SavingsAccountRepositoryWrapper savingsAccountRepository,
@@ -79,7 +88,8 @@
             final DepositAccountAssembler depositAccountAssembler, final SavingsAccountDomainService savingsAccountDomainService,
             final AccountTransfersWritePlatformService accountTransfersWritePlatformService,
             final ConfigurationDomainService configurationDomainService,
-            final AccountNumberFormatRepositoryWrapper accountNumberFormatRepository) {
+            final AccountNumberFormatRepositoryWrapper accountNumberFormatRepository,
+            final CalendarInstanceRepository calendarInstanceRepository) {
         this.savingsAccountRepository = savingsAccountRepository;
         this.applicationCurrencyRepositoryWrapper = applicationCurrencyRepositoryWrapper;
         this.journalEntryWritePlatformService = journalEntryWritePlatformService;
@@ -89,6 +99,7 @@
         this.accountTransfersWritePlatformService = accountTransfersWritePlatformService;
         this.configurationDomainService = configurationDomainService;
         this.accountNumberFormatRepository = accountNumberFormatRepository;
+        this.calendarInstanceRepository = calendarInstanceRepository;
     }
 
     @Transactional
@@ -129,6 +140,7 @@
         boolean isAccountTransfer = false;
         final boolean isPreMatureClosure = false;
         final MathContext mc = MathContext.DECIMAL64;
+        account.updateDepositAmount(transactionAmount);
         final SavingsAccountTransaction deposit = this.savingsAccountDomainService.handleDeposit(account, fmt, transactionDate,
                 transactionAmount, paymentDetail, isAccountTransfer, isRegularTransaction);
 
@@ -241,18 +253,15 @@
         if (onClosureType.isReinvest()) {
             RecurringDepositAccount reinvestedDeposit = account.reInvest(transactionAmount);
             depositAccountAssembler.assignSavingAccountHelpers(reinvestedDeposit);
-            reinvestedDeposit.updateMaturityDateAndAmount(mc, isPreMatureClosure, isSavingsInterestPostingAtCurrentPeriodEnd,
-                    financialYearBeginningMonth);
-            reinvestedDeposit.processAccountUponActivation(fmt, user);
-            reinvestedDeposit.updateMaturityDateAndAmount(mc, isPreMatureClosure, isSavingsInterestPostingAtCurrentPeriodEnd,
-                    financialYearBeginningMonth);
             this.savingsAccountRepository.save(reinvestedDeposit);
-
-            Money amountForDeposit = reinvestedDeposit.activateWithBalance();
-            if (amountForDeposit.isGreaterThanZero()) {
-                handleRDDeposit(reinvestedDeposit, fmt, reinvestedDeposit.getActivationLocalDate(), amountForDeposit.getAmount(),
-                        paymentDetail, isRegularTransaction);
-            }
+            final CalendarInstance calendarInstance = getCalendarInstance(account, reinvestedDeposit);
+            this.calendarInstanceRepository.save(calendarInstance);
+            final Calendar calendar = calendarInstance.getCalendar();
+            final PeriodFrequencyType frequencyType = CalendarFrequencyType.from(CalendarUtils.getFrequency(calendar.getRecurrence()));
+            Integer frequency = CalendarUtils.getInterval(calendar.getRecurrence());
+            frequency = frequency == -1 ? 1 : frequency;
+            reinvestedDeposit.generateSchedule(frequencyType, frequency, calendar);
+            reinvestedDeposit.processAccountUponActivation(fmt, user);
             reinvestedDeposit.updateMaturityDateAndAmount(mc, isPreMatureClosure, isSavingsInterestPostingAtCurrentPeriodEnd,
                     financialYearBeginningMonth);
             this.savingsAccountRepository.save(reinvestedDeposit);
@@ -292,6 +301,31 @@
         return savingsTransactionId;
     }
 
+    private CalendarInstance getCalendarInstance(final RecurringDepositAccount account, RecurringDepositAccount reinvestedDeposit) {
+        CalendarInstance calendarInstance = null;
+        CalendarInstance parentCalendarInstance = this.calendarInstanceRepository.findByEntityIdAndEntityTypeIdAndCalendarTypeId(
+                account.getId(), CalendarEntityType.SAVINGS.getValue(), CalendarType.COLLECTION.getValue());
+        if (account.isCalendarInherited()) {
+            calendarInstance = CalendarInstance.from(parentCalendarInstance.getCalendar(), account.getId(),
+                    CalendarEntityType.SAVINGS.getValue());
+        } else {
+            LocalDate calendarStartDate = reinvestedDeposit.depositStartDate();
+            Calendar parentCalendar = parentCalendarInstance.getCalendar();
+            final String recurrence = parentCalendar.getRecurrence();
+            final String title = "recurring_savings_" + reinvestedDeposit.getId();
+            final Calendar calendar = Calendar.createRepeatingCalendar(title, calendarStartDate, CalendarType.COLLECTION.getValue(),
+                    recurrence);
+            calendarInstance = CalendarInstance.from(calendar, reinvestedDeposit.getId(), CalendarEntityType.SAVINGS.getValue());
+        }
+        if (calendarInstance == null) {
+            final String defaultUserMessage = "No valid recurring details available for recurring depost account creation.";
+            throw new GeneralPlatformDomainRuleException(
+                    "error.msg.recurring.deposit.account.cannot.create.no.valid.recurring.details.available", defaultUserMessage,
+                    account.clientId());
+        }
+        return calendarInstance;
+    }
+
     private void autoGenerateAccountNumber(final SavingsAccount account) {
         if (account.isAccountNumberRequiresAutoGeneration()) {
             final AccountNumberFormat accountNumberFormat = this.accountNumberFormatRepository.findByAccountType(EntityAccountType.SAVINGS);
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountInterestRateChart.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountInterestRateChart.java
index 25aab57..7365b0f 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountInterestRateChart.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountInterestRateChart.java
@@ -92,6 +92,7 @@
         if (this.chartSlabs == null) {
             this.chartSlabs = new HashSet<>();
         }
+
         return this.chartSlabs;
     }
 
@@ -153,4 +154,8 @@
 
         return effectiveInterestRate;
     }
+
+    public boolean isPrimaryGroupingByAmount() {
+        return this.chartFields.isPrimaryGroupingByAmount();
+    }
 }
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositProductAssembler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositProductAssembler.java
index 83b0e10..dcd446c 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositProductAssembler.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositProductAssembler.java
@@ -18,6 +18,8 @@
  */
 package org.apache.fineract.portfolio.savings.domain;
 
+import static org.apache.fineract.portfolio.savings.DepositsApiConstants.FIXED_DEPOSIT_PRODUCT_RESOURCE_NAME;
+import static org.apache.fineract.portfolio.savings.DepositsApiConstants.RECURRING_DEPOSIT_PRODUCT_RESOURCE_NAME;
 import static org.apache.fineract.portfolio.savings.DepositsApiConstants.adjustAdvanceTowardsFuturePaymentsParamName;
 import static org.apache.fineract.portfolio.savings.DepositsApiConstants.allowWithdrawalParamName;
 import static org.apache.fineract.portfolio.savings.DepositsApiConstants.chartsParamName;
@@ -52,11 +54,16 @@
 import static org.apache.fineract.portfolio.savings.SavingsApiConstants.shortNameParamName;
 
 import java.math.BigDecimal;
+import java.util.ArrayList;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
 
 import org.apache.fineract.accounting.common.AccountingRuleType;
 import org.apache.fineract.infrastructure.core.api.JsonCommand;
+import org.apache.fineract.infrastructure.core.data.ApiParameterError;
+import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
+import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
 import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
 import org.apache.fineract.portfolio.charge.domain.Charge;
 import org.apache.fineract.portfolio.charge.domain.ChargeRepositoryWrapper;
@@ -147,7 +154,11 @@
         // Savings product charges
         final Set<Charge> charges = assembleListOfSavingsProductCharges(command, currencyCode);
         // Interest rate charts
-        final Set<InterestRateChart> charts = assembleListOfCharts(command, currency.getCode());
+        final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
+        final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
+                .resource(FIXED_DEPOSIT_PRODUCT_RESOURCE_NAME);
+        final Set<InterestRateChart> charts = assembleListOfCharts(command, currency.getCode(), baseDataValidator);
+        throwExceptionIfValidationWarningsExist(dataValidationErrors);
         if (interestRate == null) {
             interestRate = BigDecimal.ZERO;
         }
@@ -164,6 +175,10 @@
         return fixedDepositProduct;
     }
 
+    private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
+        if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
+    }
+
     public RecurringDepositProduct assembleRecurringDepositProduct(final JsonCommand command) {
 
         final String name = command.stringValueOfParameterNamed(nameParamName);
@@ -225,7 +240,11 @@
         // Savings product charges
         final Set<Charge> charges = assembleListOfSavingsProductCharges(command, currencyCode);
         // Interest rate charts
-        final Set<InterestRateChart> charts = assembleListOfCharts(command, currency.getCode());
+        final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
+        final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
+                .resource(RECURRING_DEPOSIT_PRODUCT_RESOURCE_NAME);
+        final Set<InterestRateChart> charts = assembleListOfCharts(command, currency.getCode(), baseDataValidator);
+        throwExceptionIfValidationWarningsExist(dataValidationErrors);
 
         if (interestRate == null) {
             interestRate = BigDecimal.ZERO;
@@ -435,15 +454,14 @@
         return charges;
     }
 
-    private Set<InterestRateChart> assembleListOfCharts(JsonCommand command, String currencyCode) {
+    private Set<InterestRateChart> assembleListOfCharts(JsonCommand command, String currencyCode, DataValidatorBuilder baseDataValidator) {
         final Set<InterestRateChart> charts = new HashSet<>();
-
         if (command.parameterExists(chartsParamName)) {
             final JsonArray chartsArray = command.arrayOfParameterNamed(chartsParamName);
             if (chartsArray != null) {
                 for (int i = 0; i < chartsArray.size(); i++) {
                     final JsonObject interstRateChartElement = chartsArray.get(i).getAsJsonObject();
-                    InterestRateChart chart = this.chartAssembler.assembleFrom(interstRateChartElement, currencyCode);
+                    InterestRateChart chart = this.chartAssembler.assembleFrom(interstRateChartElement, currencyCode, baseDataValidator);
                     charts.add(chart);
                 }
             }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/FixedDepositProduct.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/FixedDepositProduct.java
index 5ab9cea..9e4e075 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/FixedDepositProduct.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/FixedDepositProduct.java
@@ -198,7 +198,7 @@
                         }
                     } else {
                         // assemble chart
-                        final InterestRateChart newChart = this.chartAssembler.assembleFrom(chartElement, this.currency().getCode());
+                        final InterestRateChart newChart = this.chartAssembler.assembleFrom(chartElement, this.currency().getCode(), baseDataValidator);
                         this.addChart(newChart);
                     }
                 }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/RecurringDepositAccount.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/RecurringDepositAccount.java
index 0d6f857..1bf4e52 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/RecurringDepositAccount.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/RecurringDepositAccount.java
@@ -174,12 +174,29 @@
         final Map<String, Object> termAndPreClosureChanges = accountTermAndPreClosure.update(command, baseDataValidator);
         actualChanges.putAll(termAndPreClosureChanges);
         recurringDetail.update(command);
-
         validateDomainRules(baseDataValidator);
         super.validateInterestPostingAndCompoundingPeriodTypes(baseDataValidator);
         if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
     }
 
+    private void updateDepositAmount() {
+        BigDecimal recurringAmount = getRecurringDetail().mandatoryRecommendedDepositAmount();
+        Integer numberOfDepositPeriods = depositScheduleInstallments().size();
+        if (this.accountTermAndPreClosure.depositPeriod() != null && recurringAmount != null && numberOfDepositPeriods != null) {
+            BigDecimal depositAmount = Money.of(product.currency(), recurringAmount).multipliedBy(numberOfDepositPeriods)
+                    .plus(this.minRequiredOpeningBalance).getAmount();
+            accountTermAndPreClosure.updateDepositAmount(depositAmount);
+        } else if (accountTermAndPreClosure.depositAmount() == null) {
+            accountTermAndPreClosure.updateDepositAmount(Money.zero(product.currency()).getAmount());
+        }
+    }
+
+    public void updateDepositAmount(final BigDecimal depositAmount) {
+        if (this.accountTermAndPreClosure.depositPeriod() == null) {
+            accountTermAndPreClosure.updateDepositAmount(accountTermAndPreClosure.depositAmount().add(depositAmount));
+        }
+    }
+
     @Override
     protected BigDecimal getEffectiveInterestRateAsFraction(final MathContext mc, final LocalDate interestPostingUpToDate) {
         boolean isPreMatureClosure = false;
@@ -207,7 +224,7 @@
         }
 
         if (depositCloseDate == null) {
-            depositCloseDate = LocalDate.now();
+            depositCloseDate = DateUtils.getLocalDateOfTenant();
         }
 
         final BigDecimal depositAmount = accountTermAndPreClosure.depositAmount();
@@ -966,8 +983,8 @@
                         .failWithCode("deposit.period.must.be.greater.than.lock.in.period",
                                 "Deposit period must be greater than account lock-in period.");
             }
-        }
 
+        }
         if (firstDepositDateBeforeAccountSubmittedOrActivationDate()) {
             baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode(
                     "expected.first.deposit.date.must.be.after.account.submitted.or.activation.date");
@@ -989,7 +1006,7 @@
         final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
                 .resource(RECURRING_DEPOSIT_ACCOUNT_RESOURCE_NAME);
         LocalDate maturityDate = calculateMaturityDate();
-        if (this.chart != null && maturityDate != null) {
+        if (this.chart != null) {
             final LocalDate chartFromDate = this.chart.getFromDateAsLocalDate();
             LocalDate chartEndDate = this.chart.getEndDateAsLocalDate();
             chartEndDate = chartEndDate == null ? DateUtils.getLocalDateOfTenant() : chartEndDate;
@@ -999,7 +1016,11 @@
                 baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("no.valid.interest.rate.slab.available.for.date.range");
             }
 
-            final BigDecimal maturityAmount = this.accountTermAndPreClosure.maturityAmount();
+            if (maturityDate == null) {
+                maturityDate = DateUtils.getLocalDateOfTenant();
+            }
+
+            final BigDecimal maturityAmount = this.accountTermAndPreClosure.depositAmount();
             BigDecimal applicableInterestRate = this.chart.getApplicableInterestRate(maturityAmount, depositStartDate(), maturityDate,
                     this.client);
 
@@ -1012,7 +1033,7 @@
             baseDataValidator.reset().parameter(DepositsApiConstants.nominalAnnualInterestRateParamName).value(nominalAnnualInterestRate)
                     .failWithCodeNoParameterAddedToErrorCode("interest.chart.or.nominal.interest.rate.required");
         }
-
+        if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
         /**
          * final boolean recurringFrequencyBeforeDepositPeriod =
          * recurringFrequencyBeforeDepositPeriod();
@@ -1117,6 +1138,7 @@
             installmentDate = DepositAccountUtils.calculateNextDepositDate(installmentDate, frequency, recurringEvery);
             installmentNumber += 1;
         }
+        updateDepositAmount();
     }
 
     private LocalDate calcualteScheduleTillDate(final PeriodFrequencyType frequency, final Integer recurringEvery) {
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountInterestRateChartReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountInterestRateChartReadPlatformServiceImpl.java
index 1adb84b..451cc70 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountInterestRateChartReadPlatformServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountInterestRateChartReadPlatformServiceImpl.java
@@ -90,8 +90,20 @@
     @Override
     public DepositAccountInterestRateChartData retrieveOneWithSlabs(Long chartId) {
         this.context.authenticatedUser();
-        final String sql = "select " + this.chartExtractor.schema() + " where irc.id = ? order by ircd.id asc";
-        Collection<DepositAccountInterestRateChartData> chartDatas = this.jdbcTemplate.query(sql, this.chartExtractor,
+        StringBuilder sql = new StringBuilder();
+        sql.append("select ");
+        sql.append(this.chartExtractor.schema());
+        sql.append(" where irc.id = ? order by irc.id asc, ");
+        sql.append("CASE ");
+        sql.append("WHEN isPrimaryGroupingByAmount then ircd.amount_range_from ");
+        sql.append("WHEN isPrimaryGroupingByAmount then ircd.amount_range_to ");
+        sql.append("END,");
+        sql.append("ircd.from_period, ircd.to_period,");
+        sql.append("CASE ");
+        sql.append("WHEN !isPrimaryGroupingByAmount then ircd.amount_range_from ");
+        sql.append("WHEN !isPrimaryGroupingByAmount then ircd.amount_range_to ");
+        sql.append("END");
+        Collection<DepositAccountInterestRateChartData> chartDatas = this.jdbcTemplate.query(sql.toString(), this.chartExtractor,
                 new Object[] { chartId });
         if (chartDatas == null || chartDatas.isEmpty()) { throw new DepositAccountInterestRateChartNotFoundException(chartId); }
 
@@ -122,8 +134,21 @@
     @Override
     public DepositAccountInterestRateChartData retrieveOneWithSlabsOnAccountId(Long accountId) {
         this.context.authenticatedUser();
-        final String sql = "select " + this.chartExtractor.schema() + " where irc.savings_account_id = ? order by ircd.id asc";
-        Collection<DepositAccountInterestRateChartData> chartDatas = this.jdbcTemplate.query(sql, this.chartExtractor,
+        StringBuilder sql = new StringBuilder();
+        sql.append("select ");
+        sql.append(this.chartExtractor.schema());
+        sql.append(" where irc.savings_account_id = ? order by irc.id asc, ");
+        sql.append("CASE ");
+        sql.append("WHEN isPrimaryGroupingByAmount then ircd.amount_range_from ");
+        sql.append("WHEN isPrimaryGroupingByAmount then ircd.amount_range_to ");
+        sql.append("END,");
+        sql.append("ircd.from_period, ircd.to_period,");
+        sql.append("CASE ");
+        sql.append("WHEN !isPrimaryGroupingByAmount then ircd.amount_range_from ");
+        sql.append("WHEN !isPrimaryGroupingByAmount then ircd.amount_range_to ");
+        sql.append("END");
+
+        Collection<DepositAccountInterestRateChartData> chartDatas = this.jdbcTemplate.query(sql.toString(), this.chartExtractor,
                 new Object[] { accountId });
         if (chartDatas == null || chartDatas.isEmpty()) { throw new DepositAccountInterestRateChartNotFoundException(accountId); }
 
@@ -167,6 +192,7 @@
             sqlBuilder
                     .append("irc.id as ircId, irc.name as ircName, irc.description as ircDescription,")
                     .append("irc.from_date as ircFromDate, irc.end_date as ircEndDate, ")
+                    .append("irc.is_primary_grouping_by_amount as isPrimaryGroupingByAmount,")
                     .append("ircd.id as ircdId, ircd.description as ircdDescription, ircd.period_type_enum ircdPeriodTypeId, ")
                     .append("ircd.from_period as ircdFromPeriod, ircd.to_period as ircdToPeriod, ircd.amount_range_from as ircdAmountRangeFrom, ")
                     .append("ircd.amount_range_to as ircdAmountRangeTo, ircd.annual_interest_rate as ircdAnnualInterestRate, ")
@@ -231,6 +257,7 @@
 
             sqlBuilder.append("irc.id as ircId, irc.name as ircName, irc.description as ircDescription, ")
                     .append("irc.from_date as ircFromDate, irc.end_date as ircEndDate, ")
+                    .append("irc.is_primary_grouping_by_amount as isPrimaryGroupingByAmount,")
                     .append("sa.id as accountId, sa.account_no as accountNumber ").append("from ")
                     .append("m_savings_account_interest_rate_chart irc left join m_savings_account sa on irc.savings_account_id=sa.id ");
             this.schemaSql = sqlBuilder.toString();
@@ -243,12 +270,13 @@
             final String description = rs.getString("ircDescription");
             final LocalDate fromDate = JdbcSupport.getLocalDate(rs, "ircFromDate");
             final LocalDate endDate = JdbcSupport.getLocalDate(rs, "ircEndDate");
+            final boolean isPrimaryGroupingByAmount = rs.getBoolean("isPrimaryGroupingByAmount");
             final Long accountId = rs.getLong("accountId");
             final String accountNumber = rs.getString("accountNumber");
             final Collection<EnumOptionData> periodTypes = InterestRateChartEnumerations.periodType(PeriodFrequencyType.values());
 
-            return DepositAccountInterestRateChartData.instance(id, name, description, fromDate, endDate, accountId, accountNumber, null,
-                    periodTypes);
+            return DepositAccountInterestRateChartData.instance(id, name, description, fromDate, endDate, isPrimaryGroupingByAmount,
+                    accountId, accountNumber, null, periodTypes);
         }
 
     }
diff --git a/fineract-provider/src/main/resources/sql/migrations/core_db/V293__interest_rate_chart_support_for_amounts.sql b/fineract-provider/src/main/resources/sql/migrations/core_db/V293__interest_rate_chart_support_for_amounts.sql
new file mode 100644
index 0000000..ccd4028
--- /dev/null
+++ b/fineract-provider/src/main/resources/sql/migrations/core_db/V293__interest_rate_chart_support_for_amounts.sql
@@ -0,0 +1,13 @@
+ALTER TABLE `m_interest_rate_slab`
+	CHANGE COLUMN `from_period` `from_period` INT(11) NULL DEFAULT NULL,
+	CHANGE COLUMN `period_type_enum` `period_type_enum` SMALLINT(5) NULL DEFAULT NULL ;
+	
+ALTER TABLE `m_interest_rate_chart`
+	ADD COLUMN `is_primary_grouping_by_amount` TINYINT(1) NOT NULL DEFAULT '0';
+	
+ALTER TABLE `m_savings_account_interest_rate_chart`
+	ADD COLUMN `is_primary_grouping_by_amount` TINYINT NOT NULL DEFAULT '0'	;
+	
+ALTER TABLE `m_savings_account_interest_rate_slab`
+	CHANGE COLUMN `period_type_enum` `period_type_enum` SMALLINT(5) NULL DEFAULT NULL,
+	CHANGE COLUMN `from_period` `from_period` INT(11) NULL DEFAULT NULL;	
\ No newline at end of file