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
