From 5235b7ebc9a7d0a6df9b7e6bd485720af041a575 Mon Sep 17 00:00:00 2001 From: Mexina M Daniel Date: Fri, 29 Dec 2017 15:37:19 +0300 Subject: [PATCH] FINERACT-416 Interest of the whole term --- .../common/domain/PeriodFrequencyType.java | 9 +++++- .../DropdownReadPlatformServiceImpl.java | 2 +- .../loanschedule/domain/AprCalculator.java | 29 +++++++++++++++---- .../service/LoanScheduleAssembler.java | 4 +-- .../loanproduct/domain/LoanProduct.java | 10 ++++--- .../domain/LoanProductRelatedDetail.java | 5 ++-- .../LoanProductDataValidator.java | 6 ++-- .../LoanDropdownReadPlatformServiceImpl.java | 4 +-- .../loanproduct/service/LoanEnumerations.java | 6 +++- 9 files changed, 54 insertions(+), 21 deletions(-) diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/common/domain/PeriodFrequencyType.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/common/domain/PeriodFrequencyType.java index fba62079531..6a60233e552 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/common/domain/PeriodFrequencyType.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/common/domain/PeriodFrequencyType.java @@ -27,7 +27,8 @@ public enum PeriodFrequencyType { WEEKS(1, "periodFrequencyType.weeks"), // MONTHS(2, "periodFrequencyType.months"), // YEARS(3, "periodFrequencyType.years"), // - INVALID(4, "periodFrequencyType.invalid"); + WHOLE_TERM(4, "periodFrequencyType.whole_term"), // + INVALID(5, "periodFrequencyType.invalid"); private final Integer value; private final String code; @@ -61,6 +62,9 @@ public static PeriodFrequencyType fromInt(final Integer frequency) { case 3: repaymentFrequencyType = PeriodFrequencyType.YEARS; break; + case 4: + repaymentFrequencyType = PeriodFrequencyType.WHOLE_TERM; + break; } } return repaymentFrequencyType; @@ -82,6 +86,9 @@ public boolean isDaily() { return this.value.equals(PeriodFrequencyType.DAYS.getValue()); } + public boolean isWholeTerm() { + return this.value.equals(PeriodFrequencyType.WHOLE_TERM.getValue()); + } public boolean isInvalid() { return this.value.equals(PeriodFrequencyType.INVALID.getValue()); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/common/service/DropdownReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/common/service/DropdownReadPlatformServiceImpl.java index 948328d4c90..40a664b69ad 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/common/service/DropdownReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/common/service/DropdownReadPlatformServiceImpl.java @@ -40,7 +40,7 @@ public class DropdownReadPlatformServiceImpl implements DropdownReadPlatformServ public List retrievePeriodFrequencyTypeOptions() { final List loanTermFrequencyOptions = Arrays.asList(termFrequencyType(PeriodFrequencyType.DAYS, "frequency"), termFrequencyType(PeriodFrequencyType.WEEKS, "frequency"), termFrequencyType(PeriodFrequencyType.MONTHS, "frequency"), - termFrequencyType(PeriodFrequencyType.YEARS, "frequency")); + termFrequencyType(PeriodFrequencyType.YEARS, "frequency"), termFrequencyType(PeriodFrequencyType.WHOLE_TERM, "frequency")); return loanTermFrequencyOptions; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AprCalculator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AprCalculator.java index 730949b7e57..d60eceb60d9 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AprCalculator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AprCalculator.java @@ -19,14 +19,14 @@ package org.apache.fineract.portfolio.loanaccount.loanschedule.domain; import java.math.BigDecimal; - +import java.math.RoundingMode; import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType; import org.springframework.stereotype.Component; @Component public class AprCalculator { - public BigDecimal calculateFrom(final PeriodFrequencyType interestPeriodFrequencyType, final BigDecimal interestRatePerPeriod) { + public BigDecimal calculateFrom(final PeriodFrequencyType interestPeriodFrequencyType, final BigDecimal interestRatePerPeriod, final Integer numberOfRepayments, final Integer repaymentEvery, final PeriodFrequencyType repaymentPeriodFrequencyType) { BigDecimal defaultAnnualNominalInterestRate = BigDecimal.ZERO; switch (interestPeriodFrequencyType) { case DAYS: @@ -41,10 +41,29 @@ public BigDecimal calculateFrom(final PeriodFrequencyType interestPeriodFrequenc case YEARS: defaultAnnualNominalInterestRate = interestRatePerPeriod.multiply(BigDecimal.valueOf(1)); break; + case WHOLE_TERM: + final BigDecimal ratePerPeriod = interestRatePerPeriod.divide(BigDecimal.valueOf(numberOfRepayments*repaymentEvery), 8, RoundingMode.HALF_UP); + + switch (repaymentPeriodFrequencyType) { + case DAYS: + defaultAnnualNominalInterestRate = ratePerPeriod.multiply(BigDecimal.valueOf(365)); + break; + case WEEKS: + defaultAnnualNominalInterestRate = ratePerPeriod.multiply(BigDecimal.valueOf(52)); + break; + case MONTHS: + defaultAnnualNominalInterestRate = ratePerPeriod.multiply(BigDecimal.valueOf(12)); + break; + case YEARS: + defaultAnnualNominalInterestRate = ratePerPeriod.multiply(BigDecimal.valueOf(1)); + break; + } + break; case INVALID: break; } + + return defaultAnnualNominalInterestRate; + } - return defaultAnnualNominalInterestRate; - } -} \ No newline at end of file +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java index c3f48a8503e..69c0310b0c3 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java @@ -227,7 +227,7 @@ private LoanApplicationTerms assembleLoanApplicationTermsFrom(final JsonElement BigDecimal annualNominalInterestRate = BigDecimal.ZERO; if (interestRatePerPeriod != null) { - annualNominalInterestRate = this.aprCalculator.calculateFrom(interestRatePeriodFrequencyType, interestRatePerPeriod); + annualNominalInterestRate = this.aprCalculator.calculateFrom(interestRatePeriodFrequencyType, interestRatePerPeriod, numberOfRepayments, repaymentEvery, repaymentPeriodFrequencyType); } // disbursement details @@ -1106,4 +1106,4 @@ private void validateMinimumDaysBetweenDisbursalAndFirstRepayment(final LocalDat if (firstRepaymentDate.isBefore(minimumFirstRepaymentDate)) { throw new MinDaysBetweenDisbursalAndFirstRepaymentViolationException( disbursalDate, firstRepaymentDate, minimumDaysBetweenDisbursalAndFirstRepayment); } } -} \ No newline at end of file +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProduct.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProduct.java index 443dd4f28ad..723166c4fdf 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProduct.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProduct.java @@ -223,6 +223,9 @@ public static LoanProduct assembleFromJson(final Fund fund, final LoanTransactio Integer minimumGapBetweenInstallments = null; Integer maximumGapBetweenInstallments = null; + + final Integer repaymentEvery = command.integerValueOfParameterNamed("repaymentEvery"); + final Integer numberOfRepayments = command.integerValueOfParameterNamed("numberOfRepayments"); final Boolean isLinkedToFloatingInterestRates = command.booleanObjectValueOfParameterNamed("isLinkedToFloatingInterestRates"); if (isLinkedToFloatingInterestRates != null && isLinkedToFloatingInterestRates) { interestRateDifferential = command.bigDecimalValueOfParameterNamed("interestRateDifferential"); @@ -236,7 +239,8 @@ public static LoanProduct assembleFromJson(final Fund fund, final LoanTransactio interestRatePerPeriod = command.bigDecimalValueOfParameterNamed("interestRatePerPeriod"); minInterestRatePerPeriod = command.bigDecimalValueOfParameterNamed("minInterestRatePerPeriod"); maxInterestRatePerPeriod = command.bigDecimalValueOfParameterNamed("maxInterestRatePerPeriod"); - annualInterestRate = aprCalculator.calculateFrom(interestFrequencyType, interestRatePerPeriod); + annualInterestRate = aprCalculator.calculateFrom(interestFrequencyType, interestRatePerPeriod, numberOfRepayments, repaymentEvery, repaymentFrequencyType); + } final Boolean isVariableInstallmentsAllowed = command @@ -246,8 +250,6 @@ public static LoanProduct assembleFromJson(final Fund fund, final LoanTransactio maximumGapBetweenInstallments = command.integerValueOfParameterNamed(LoanProductConstants.maximumGapBetweenInstallments); } - final Integer repaymentEvery = command.integerValueOfParameterNamed("repaymentEvery"); - final Integer numberOfRepayments = command.integerValueOfParameterNamed("numberOfRepayments"); final Integer minNumberOfRepayments = command.integerValueOfParameterNamed("minNumberOfRepayments"); final Integer maxNumberOfRepayments = command.integerValueOfParameterNamed("maxNumberOfRepayments"); final BigDecimal inArrearsTolerance = command.bigDecimalValueOfParameterNamed("inArrearsTolerance"); @@ -1380,4 +1382,4 @@ public void setEqualAmortization(boolean isEqualAmortization) { this.isEqualAmortization = isEqualAmortization; } -} \ No newline at end of file +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProductRelatedDetail.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProductRelatedDetail.java index 25ce67d5275..76b57fb59f2 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProductRelatedDetail.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProductRelatedDetail.java @@ -561,7 +561,8 @@ private Integer defaultToZeroIfNull(final Integer value) { } private void updateInterestRateDerivedFields(final AprCalculator aprCalculator) { - this.annualNominalInterestRate = aprCalculator.calculateFrom(this.interestPeriodFrequencyType, this.nominalInterestRatePerPeriod); + this.annualNominalInterestRate = aprCalculator.calculateFrom(this.interestPeriodFrequencyType, this.nominalInterestRatePerPeriod, this.numberOfRepayments, this.repayEvery, this.repaymentPeriodFrequencyType); + } public boolean hasCurrencyCodeOf(final String currencyCode) { @@ -667,4 +668,4 @@ public void setEqualAmortization(boolean isEqualAmortization) { this.isEqualAmortization = isEqualAmortization; } -} \ No newline at end of file +} 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 04bfa7f0636..56446d0a8cb 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 @@ -513,7 +513,7 @@ public void validateForCreate(final String json) { final Integer interestRateFrequencyType = this.fromApiJsonHelper.extractIntegerNamed("interestRateFrequencyType", element, Locale.getDefault()); - baseDataValidator.reset().parameter("interestRateFrequencyType").value(interestRateFrequencyType).notNull().inMinMaxRange(0, 3); + baseDataValidator.reset().parameter("interestRateFrequencyType").value(interestRateFrequencyType).notNull().inMinMaxRange(0, 4); } // Guarantee Funds @@ -1368,7 +1368,7 @@ public void validateForUpdate(final String json, final LoanProduct loanProduct) interestRateFrequencyType = this.fromApiJsonHelper.extractIntegerNamed("interestRateFrequencyType", element, Locale.getDefault()); } - baseDataValidator.reset().parameter("interestRateFrequencyType").value(interestRateFrequencyType).notNull().inMinMaxRange(0, 3); + baseDataValidator.reset().parameter("interestRateFrequencyType").value(interestRateFrequencyType).notNull().inMinMaxRange(0, 4); } // Guarantee Funds @@ -2101,4 +2101,4 @@ private void validatePartialPeriodSupport(final Integer interestCalculationPerio } } -} \ No newline at end of file +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanDropdownReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanDropdownReadPlatformServiceImpl.java index b82763ff15f..aad2eb576cd 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanDropdownReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanDropdownReadPlatformServiceImpl.java @@ -132,7 +132,7 @@ public List retrieveRepaymentFrequencyOptionsForDaysOfWeek() { public List retrieveInterestRateFrequencyTypeOptions() { // support for monthly and annual percentage rate (MPR) and (APR) final List interestRateFrequencyTypeOptions = Arrays.asList(interestRateFrequencyType(PeriodFrequencyType.MONTHS), - interestRateFrequencyType(PeriodFrequencyType.YEARS)); + interestRateFrequencyType(PeriodFrequencyType.YEARS), interestRateFrequencyType(PeriodFrequencyType.WHOLE_TERM)); return interestRateFrequencyTypeOptions; } @@ -220,4 +220,4 @@ public List retrivePreCloseInterestCalculationStrategyOptions() preCloseInterestCalculationStrategy(LoanPreClosureInterestCalculationStrategy.TILL_REST_FREQUENCY_DATE)); return preCloseInterestCalculationStrategyOptions; } -} \ No newline at end of file +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanEnumerations.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanEnumerations.java index 18c90586045..638e011bd44 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanEnumerations.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanEnumerations.java @@ -239,6 +239,10 @@ public static EnumOptionData interestRateFrequencyType(final PeriodFrequencyType optionData = new EnumOptionData(PeriodFrequencyType.YEARS.getValue().longValue(), codePrefix + PeriodFrequencyType.YEARS.getCode(), "Per year"); break; + case WHOLE_TERM: + optionData = new EnumOptionData(PeriodFrequencyType.WHOLE_TERM.getValue().longValue(), codePrefix + + PeriodFrequencyType.WHOLE_TERM.getCode(), "Whole term"); + break; default: optionData = new EnumOptionData(PeriodFrequencyType.INVALID.getValue().longValue(), PeriodFrequencyType.INVALID.getCode(), "Invalid"); @@ -726,4 +730,4 @@ public static EnumOptionData preCloseInterestCalculationStrategy(final LoanPreCl return optionData; } -} \ No newline at end of file +}