Repository: fineract Updated Branches: refs/heads/develop b2aeb81be -> fdac5fa6e
http://git-wip-us.apache.org/repos/asf/fineract/blob/2e00bff5/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/serialization/LoanProductDataValidator.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/serialization/LoanProductDataValidator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/serialization/LoanProductDataValidator.java index 8eb132c..04bfa7f 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/serialization/LoanProductDataValidator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/serialization/LoanProductDataValidator.java @@ -45,9 +45,9 @@ import org.apache.fineract.portfolio.loanproduct.domain.InterestMethod; import org.apache.fineract.portfolio.loanproduct.domain.InterestRecalculationCompoundingMethod; import org.apache.fineract.portfolio.loanproduct.domain.LoanPreClosureInterestCalculationStrategy; import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct; -import org.apache.fineract.portfolio.loanproduct.domain.LoanProductConfigurableAttributes; import org.apache.fineract.portfolio.loanproduct.domain.LoanProductValueConditionType; import org.apache.fineract.portfolio.loanproduct.domain.RecalculationFrequencyType; +import org.apache.fineract.portfolio.loanproduct.exception.EqualAmortizationUnsupportedFeatureException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -108,7 +108,7 @@ public final class LoanProductDataValidator { LoanProductConstants.recalculationRestFrequencyWeekdayParamName, LoanProductConstants.recalculationRestFrequencyNthDayParamName, LoanProductConstants.recalculationRestFrequencyOnDayParamName, LoanProductConstants.isCompoundingToBePostedAsTransactionParamName, LoanProductConstants.allowCompoundingOnEodParamName, - LoanProductConstants.canUseForTopup)); + LoanProductConstants.canUseForTopup, LoanProductConstants.isEqualAmortizationParam)); private static final String[] supportedloanConfigurableAttributes = {LoanProductConstants.amortizationTypeParamName, LoanProductConstants.interestTypeParamName, LoanProductConstants.transactionProcessingStrategyIdParamName, @@ -148,6 +148,13 @@ public final class LoanProductDataValidator { final Long fundId = this.fromApiJsonHelper.extractLongNamed("fundId", element); baseDataValidator.reset().parameter("fundId").value(fundId).ignoreIfNull().integerGreaterThanZero(); } + + boolean isEqualAmortization = false; + if (this.fromApiJsonHelper.parameterExists(LoanProductConstants.isEqualAmortizationParam, element)) { + isEqualAmortization = this.fromApiJsonHelper.extractBooleanNamed(LoanProductConstants.isEqualAmortizationParam, element); + baseDataValidator.reset().parameter(LoanProductConstants.isEqualAmortizationParam).value(isEqualAmortization).ignoreIfNull() + .validateForBooleanValue(); + } if (this.fromApiJsonHelper.parameterExists(LoanProductConstants.minimumDaysBetweenDisbursalAndFirstRepayment, element)) { final Long minimumDaysBetweenDisbursalAndFirstRepayment = this.fromApiJsonHelper.extractLongNamed( @@ -314,6 +321,8 @@ public final class LoanProductDataValidator { if (isInterestRecalculationEnabled != null) { if (isInterestRecalculationEnabled.booleanValue()) { + if (isEqualAmortization) { throw new EqualAmortizationUnsupportedFeatureException("interest.recalculation", + "interest recalculation"); } validateInterestRecalculationParams(element, baseDataValidator, null); } } @@ -321,7 +330,9 @@ public final class LoanProductDataValidator { // interest rates if (this.fromApiJsonHelper.parameterExists("isLinkedToFloatingInterestRates", element) && this.fromApiJsonHelper.extractBooleanNamed("isLinkedToFloatingInterestRates", element) == true) { - if (this.fromApiJsonHelper.parameterExists("interestRatePerPeriod", element)) { + if (isEqualAmortization) { throw new EqualAmortizationUnsupportedFeatureException("floating.interest.rate", + "floating interest rate"); } + if (this.fromApiJsonHelper.parameterExists("interestRatePerPeriod", element)) { baseDataValidator .reset() .parameter("interestRatePerPeriod") @@ -641,6 +652,13 @@ public final class LoanProductDataValidator { private void validateVariableInstallmentSettings(final DataValidatorBuilder baseDataValidator, final JsonElement element) { if (this.fromApiJsonHelper.parameterExists(LoanProductConstants.allowVariableInstallmentsParamName, element) && this.fromApiJsonHelper.extractBooleanNamed(LoanProductConstants.allowVariableInstallmentsParamName, element)) { + + boolean isEqualAmortization = false; + if (this.fromApiJsonHelper.parameterExists(LoanProductConstants.isEqualAmortizationParam, element)) { + isEqualAmortization = this.fromApiJsonHelper.extractBooleanNamed(LoanProductConstants.isEqualAmortizationParam, element); + } + if (isEqualAmortization) { throw new EqualAmortizationUnsupportedFeatureException("variable.installment", + "variable installment"); } Long minimumGapBetweenInstallments = null; if (this.fromApiJsonHelper.parameterExists(LoanProductConstants.minimumGapBetweenInstallments, element)) { @@ -721,6 +739,13 @@ public final class LoanProductDataValidator { baseDataValidator.reset().parameter(LoanProductConstants.multiDisburseLoanParameterName).value(multiDisburseLoan) .ignoreIfNull().validateForBooleanValue(); } + + boolean isEqualAmortization = false; + if (this.fromApiJsonHelper.parameterExists(LoanProductConstants.isEqualAmortizationParam, element)) { + isEqualAmortization = this.fromApiJsonHelper.extractBooleanNamed(LoanProductConstants.isEqualAmortizationParam, element); + } + if (isEqualAmortization && multiDisburseLoan) { throw new EqualAmortizationUnsupportedFeatureException("tranche.disbursal", + "tranche disbursal"); } if (multiDisburseLoan) { if (this.fromApiJsonHelper.parameterExists(LoanProductConstants.outstandingLoanBalanceParameterName, element)) { @@ -1114,6 +1139,13 @@ public final class LoanProductDataValidator { baseDataValidator.reset().parameter(LoanProductConstants.accountMovesOutOfNPAOnlyOnArrearsCompletionParamName) .value(npaChangeConfig).notNull().isOneOfTheseValues(true, false); } + + boolean isEqualAmortization = loanProduct.isEqualAmortization(); + if (this.fromApiJsonHelper.parameterExists(LoanProductConstants.isEqualAmortizationParam, element)) { + isEqualAmortization = this.fromApiJsonHelper.extractBooleanNamed(LoanProductConstants.isEqualAmortizationParam, element); + baseDataValidator.reset().parameter(LoanProductConstants.isEqualAmortizationParam).value(isEqualAmortization).ignoreIfNull() + .validateForBooleanValue(); + } // Interest recalculation settings Boolean isInterestRecalculationEnabled = loanProduct.isInterestRecalculationEnabled(); @@ -1126,6 +1158,8 @@ public final class LoanProductDataValidator { if (isInterestRecalculationEnabled != null) { if (isInterestRecalculationEnabled) { + if (isEqualAmortization) { throw new EqualAmortizationUnsupportedFeatureException("interest.recalculation", + "interest recalculation"); } validateInterestRecalculationParams(element, baseDataValidator, loanProduct); } } @@ -1136,6 +1170,9 @@ public final class LoanProductDataValidator { isLinkedToFloatingInterestRates = this.fromApiJsonHelper.extractBooleanNamed("isLinkedToFloatingInterestRates", element); } if (isLinkedToFloatingInterestRates) { + if(isEqualAmortization){ + throw new EqualAmortizationUnsupportedFeatureException("floating.interest.rate", "floating interest rate"); + } if (this.fromApiJsonHelper.parameterExists("interestRatePerPeriod", element)) { baseDataValidator .reset() http://git-wip-us.apache.org/repos/asf/fineract/blob/2e00bff5/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformServiceImpl.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformServiceImpl.java index 078d74f..00808fa 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformServiceImpl.java @@ -227,7 +227,7 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo + "lp.allow_variabe_installments as isVariableIntallmentsAllowed, " + "lvi.minimum_gap as minimumGap, " + "lvi.maximum_gap as maximumGap, " - + "lp.can_use_for_topup as canUseForTopup " + + "lp.can_use_for_topup as canUseForTopup, lp.is_equal_amortization as isEqualAmortization " + " from m_product_loan lp " + " left join m_fund f on f.id = lp.fund_id " + " left join m_product_loan_recalculation_details lpr on lpr.product_id=lp.id " @@ -308,7 +308,8 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo final int amortizationTypeId = JdbcSupport.getInteger(rs, "amortizationMethod"); final EnumOptionData amortizationType = LoanEnumerations.amortizationType(amortizationTypeId); - + final boolean isEqualAmortization = rs.getBoolean("isEqualAmortization"); + final Integer interestRateFrequencyTypeId = JdbcSupport.getInteger(rs, "interestRatePerPeriodFreq"); final EnumOptionData interestRateFrequencyType = LoanEnumerations.interestRateFrequencyType(interestRateFrequencyTypeId); @@ -464,7 +465,7 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo installmentAmountInMultiplesOf, allowAttributeOverrides, isLinkedToFloatingInterestRates, floatingRateId, floatingRateName, interestRateDifferential, minDifferentialLendingRate, defaultDifferentialLendingRate, maxDifferentialLendingRate, isFloatingInterestRateCalculationAllowed, isVariableIntallmentsAllowed, minimumGap, - maximumGap, syncExpectedWithDisbursementDate, canUseForTopup); + maximumGap, syncExpectedWithDisbursementDate, canUseForTopup, isEqualAmortization); } } http://git-wip-us.apache.org/repos/asf/fineract/blob/2e00bff5/fineract-provider/src/main/resources/sql/migrations/core_db/V337__equal_amortization.sql ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/resources/sql/migrations/core_db/V337__equal_amortization.sql b/fineract-provider/src/main/resources/sql/migrations/core_db/V337__equal_amortization.sql new file mode 100644 index 0000000..a32ccf4 --- /dev/null +++ b/fineract-provider/src/main/resources/sql/migrations/core_db/V337__equal_amortization.sql @@ -0,0 +1,21 @@ +-- +-- 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. +-- + +ALTER TABLE `m_product_loan` ADD COLUMN `is_equal_amortization` TINYINT(1) NOT NULL DEFAULT '0'; +ALTER TABLE `m_loan` ADD COLUMN `is_equal_amortization` TINYINT(1) NOT NULL DEFAULT '0'; \ No newline at end of file http://git-wip-us.apache.org/repos/asf/fineract/blob/2e00bff5/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/LoanProductRelatedDetailTestHelper.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/LoanProductRelatedDetailTestHelper.java b/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/LoanProductRelatedDetailTestHelper.java index c429578..c202ae9 100644 --- a/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/LoanProductRelatedDetailTestHelper.java +++ b/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/LoanProductRelatedDetailTestHelper.java @@ -153,10 +153,10 @@ public class LoanProductRelatedDetailTestHelper { final Integer daysInYearType = DaysInYearType.ACTUAL.getValue(); final boolean isInterestRecalculationEnabled = false; final boolean considerPartialPeriodInterest = false; - + final boolean isEqualAmortization = false; return new LoanProductRelatedDetail(currency, defaultPrincipal, defaultNominalInterestRatePerPeriod, interestPeriodFrequencyType, defaultAnnualNominalInterestRate, interestMethod, interestCalculationPeriodMethod, considerPartialPeriodInterest, repayEvery, repaymentFrequencyType, defaultNumberOfRepayments, graceOnPrincipalPayment, recurringMoratoriumOnPrincipalPeriods, graceOnInterestPayment, graceOnInterestCharged, - amortizationMethod, inArrearsTolerance, graceOnArrearsAgeing, daysInMonthType, daysInYearType, isInterestRecalculationEnabled); + amortizationMethod, inArrearsTolerance, graceOnArrearsAgeing, daysInMonthType, daysInYearType, isInterestRecalculationEnabled, isEqualAmortization); } } \ No newline at end of file