blob: 0410a8bd6688cdd4a6da47bc83feb6068eeb0bca [file] [log] [blame]
/**
* 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.savings.domain;
import static org.apache.fineract.portfolio.savings.DepositsApiConstants.RECURRING_DEPOSIT_PRODUCT_RESOURCE_NAME;
import static org.apache.fineract.portfolio.savings.DepositsApiConstants.maxDepositTermParamName;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.OneToOne;
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.interestratechart.domain.InterestRateChart;
import org.apache.fineract.portfolio.savings.DepositsApiConstants;
import org.apache.fineract.portfolio.savings.SavingsCompoundingInterestPeriodType;
import org.apache.fineract.portfolio.savings.SavingsInterestCalculationDaysInYearType;
import org.apache.fineract.portfolio.savings.SavingsInterestCalculationType;
import org.apache.fineract.portfolio.savings.SavingsPeriodFrequencyType;
import org.apache.fineract.portfolio.savings.SavingsPostingInterestPeriodType;
@Entity
@DiscriminatorValue("300")
public class RecurringDepositProduct extends FixedDepositProduct {
@OneToOne(mappedBy = "product", cascade = CascadeType.ALL)
private DepositProductRecurringDetail recurringDetail;
protected RecurringDepositProduct() {
super();
}
public static RecurringDepositProduct createNew(final String name, final String shortName, final String description,
final MonetaryCurrency currency, final BigDecimal interestRate,
final SavingsCompoundingInterestPeriodType interestCompoundingPeriodType,
final SavingsPostingInterestPeriodType interestPostingPeriodType, final SavingsInterestCalculationType interestCalculationType,
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final Integer lockinPeriodFrequency,
final SavingsPeriodFrequencyType lockinPeriodFrequencyType, final AccountingRuleType accountingRuleType,
final Set<Charge> charges, final DepositProductTermAndPreClosure productTermAndPreClosure,
final DepositProductRecurringDetail recurringDetail, final Set<InterestRateChart> charts,
BigDecimal minBalanceForInterestCalculation) {
final BigDecimal minRequiredOpeningBalance = null;
final boolean withdrawalFeeApplicableForTransfer = false;
final boolean allowOverdraft = false;
final BigDecimal overdraftLimit = null;
return new RecurringDepositProduct(name, shortName, description, currency, interestRate, interestCompoundingPeriodType,
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeApplicableForTransfer, accountingRuleType, charges,
productTermAndPreClosure, recurringDetail, charts, allowOverdraft, overdraftLimit, minBalanceForInterestCalculation);
}
protected RecurringDepositProduct(final String name, final String shortName, final String description, final MonetaryCurrency currency,
final BigDecimal interestRate, final SavingsCompoundingInterestPeriodType interestCompoundingPeriodType,
final SavingsPostingInterestPeriodType interestPostingPeriodType, final SavingsInterestCalculationType interestCalculationType,
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType,
final boolean withdrawalFeeApplicableForTransfer, final AccountingRuleType accountingRuleType, final Set<Charge> charges,
final DepositProductTermAndPreClosure productTermAndPreClosure, final DepositProductRecurringDetail recurringDetail,
final Set<InterestRateChart> charts, final boolean allowOverdraft, final BigDecimal overdraftLimit,
final BigDecimal minBalanceForInterestCalculation) {
super(name, shortName, description, currency, interestRate, interestCompoundingPeriodType, interestPostingPeriodType,
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
lockinPeriodFrequencyType, withdrawalFeeApplicableForTransfer, accountingRuleType, charges, productTermAndPreClosure,
charts, allowOverdraft, overdraftLimit, minBalanceForInterestCalculation);
this.recurringDetail = recurringDetail;
}
@Override
public Map<String, Object> update(final JsonCommand command) {
final Map<String, Object> actualChanges = new LinkedHashMap<>(10);
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
.resource(RECURRING_DEPOSIT_PRODUCT_RESOURCE_NAME);
actualChanges.putAll(this.update(command, baseDataValidator));
validateDomainRules(baseDataValidator);
throwExceptionIfValidationWarningsExist(dataValidationErrors);
return actualChanges;
}
@Override
protected Map<String, Object> update(final JsonCommand command, final DataValidatorBuilder baseDataValidator) {
final Map<String, Object> actualChanges = new LinkedHashMap<>(10);
actualChanges.putAll(super.update(command, baseDataValidator));
if (this.recurringDetail != null) {
actualChanges.putAll(this.recurringDetail.update(command));
}
return actualChanges;
}
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
}
public DepositProductRecurringDetail depositRecurringDetail() {
return this.recurringDetail;
}
@Override
public void validateDomainRules() {
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
.resource(RECURRING_DEPOSIT_PRODUCT_RESOURCE_NAME);
validateDomainRules(baseDataValidator);
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
private void validateDomainRules(final DataValidatorBuilder baseDataValidator) {
final DepositTermDetail termDetails = this.depositProductTermAndPreClosure().depositTermDetail();
final boolean isMinTermGreaterThanMax = termDetails.isMinDepositTermGreaterThanMaxDepositTerm();
if (isMinTermGreaterThanMax) {
final Integer maxTerm = termDetails.maxDepositTerm();
baseDataValidator.reset().parameter(maxDepositTermParamName).value(maxTerm)
.failWithCodeNoParameterAddedToErrorCode("max.term.lessthan.min.term");
}
if (this.charts != null) {
validateCharts(baseDataValidator);
} else if (this.nominalAnnualInterestRate == null || this.nominalAnnualInterestRate.compareTo(BigDecimal.ZERO) == 0) {
baseDataValidator.reset().parameter(DepositsApiConstants.nominalAnnualInterestRateParamName).value(nominalAnnualInterestRate)
.failWithCodeNoParameterAddedToErrorCode("interest.chart.or.nominal.interest.rate.required");
}
this.validateInterestPostingAndCompoundingPeriodTypes(baseDataValidator);
}
}