Repository: incubator-fineract
Updated Branches:
  refs/heads/develop 14499a26f -> 37dfe1a0b


http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/37dfe1a0/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/DepositAccountInterestRateChartData.java
----------------------------------------------------------------------
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 @@ public class DepositAccountInterestRateChartData {
     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 @@ public class DepositAccountInterestRateChartData {
     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 @@ public class DepositAccountInterestRateChartData {
         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 @@ public class DepositAccountInterestRateChartData {
         }
 
         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 @@ public class DepositAccountInterestRateChartData {
             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 @@ public class DepositAccountInterestRateChartData {
         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 class DepositAccountInterestRateChartData {
 
     public void addChartSlab(final DepositAccountInterestRateChartSlabData 
chartSlab) {
         if (this.chartSlabs == null) {
-            this.chartSlabs = new HashSet<>();
+            this.chartSlabs = new ArrayList<>();
         }
 
         this.chartSlabs.add(chartSlab);

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/37dfe1a0/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountDomainServiceJpa.java
----------------------------------------------------------------------
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.AccountNumb
 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 @@ public class DepositAccountDomainServiceJpa implements 
DepositAccountDomainServi
     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 @@ public class DepositAccountDomainServiceJpa implements 
DepositAccountDomainServi
             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 @@ public class DepositAccountDomainServiceJpa implements 
DepositAccountDomainServi
         this.accountTransfersWritePlatformService = 
accountTransfersWritePlatformService;
         this.configurationDomainService = configurationDomainService;
         this.accountNumberFormatRepository = accountNumberFormatRepository;
+        this.calendarInstanceRepository = calendarInstanceRepository;
     }
 
     @Transactional
@@ -129,6 +140,7 @@ public class DepositAccountDomainServiceJpa implements 
DepositAccountDomainServi
         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 @@ public class DepositAccountDomainServiceJpa implements 
DepositAccountDomainServi
         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 @@ public class DepositAccountDomainServiceJpa implements 
DepositAccountDomainServi
         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);

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/37dfe1a0/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositAccountInterestRateChart.java
----------------------------------------------------------------------
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 @@ public class DepositAccountInterestRateChart extends 
AbstractPersistable<Long> {
         if (this.chartSlabs == null) {
             this.chartSlabs = new HashSet<>();
         }
+
         return this.chartSlabs;
     }
 
@@ -153,4 +154,8 @@ public class DepositAccountInterestRateChart extends 
AbstractPersistable<Long> {
 
         return effectiveInterestRate;
     }
+
+    public boolean isPrimaryGroupingByAmount() {
+        return this.chartFields.isPrimaryGroupingByAmount();
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/37dfe1a0/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/DepositProductAssembler.java
----------------------------------------------------------------------
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.nominalA
 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 @@ public class DepositProductAssembler {
         // 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 @@ public class DepositProductAssembler {
         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 @@ public class DepositProductAssembler {
         // 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 @@ public class DepositProductAssembler {
         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);
                 }
             }

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/37dfe1a0/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/FixedDepositProduct.java
----------------------------------------------------------------------
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 @@ public class FixedDepositProduct extends SavingsProduct {
                         }
                     } 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);
                     }
                 }

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/37dfe1a0/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/RecurringDepositAccount.java
----------------------------------------------------------------------
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 @@ public class RecurringDepositAccount extends 
SavingsAccount {
         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 @@ public class RecurringDepositAccount extends SavingsAccount 
{
         }
 
         if (depositCloseDate == null) {
-            depositCloseDate = LocalDate.now();
+            depositCloseDate = DateUtils.getLocalDateOfTenant();
         }
 
         final BigDecimal depositAmount = 
accountTermAndPreClosure.depositAmount();
@@ -966,8 +983,8 @@ public class RecurringDepositAccount extends SavingsAccount 
{
                         
.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 @@ public class RecurringDepositAccount extends 
SavingsAccount {
         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 @@ public class RecurringDepositAccount extends 
SavingsAccount {
                 
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 @@ public class RecurringDepositAccount extends 
SavingsAccount {
             
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 @@ public class RecurringDepositAccount extends 
SavingsAccount {
             installmentDate = 
DepositAccountUtils.calculateNextDepositDate(installmentDate, frequency, 
recurringEvery);
             installmentNumber += 1;
         }
+        updateDepositAmount();
     }
 
     private LocalDate calcualteScheduleTillDate(final PeriodFrequencyType 
frequency, final Integer recurringEvery) {

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/37dfe1a0/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountInterestRateChartReadPlatformServiceImpl.java
----------------------------------------------------------------------
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 @@ public class 
DepositAccountInterestRateChartReadPlatformServiceImpl implements D
     @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 @@ public class 
DepositAccountInterestRateChartReadPlatformServiceImpl implements D
     @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 @@ public class 
DepositAccountInterestRateChartReadPlatformServiceImpl implements D
             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 @@ public class 
DepositAccountInterestRateChartReadPlatformServiceImpl implements D
 
             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 @@ public class 
DepositAccountInterestRateChartReadPlatformServiceImpl implements D
             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);
         }
 
     }

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/37dfe1a0/fineract-provider/src/main/resources/sql/migrations/core_db/V293__interest_rate_chart_support_for_amounts.sql
----------------------------------------------------------------------
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


Reply via email to