FINERACT-416 Interest of the whole term

This commit is contained in:
Mexina M Daniel
2017-12-29 15:37:19 +03:00
parent 17fd243ae3
commit 5235b7ebc9
9 changed files with 54 additions and 21 deletions
@@ -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 enum PeriodFrequencyType {
case 3:
repaymentFrequencyType = PeriodFrequencyType.YEARS;
break;
case 4:
repaymentFrequencyType = PeriodFrequencyType.WHOLE_TERM;
break;
}
}
return repaymentFrequencyType;
@@ -82,6 +86,9 @@ public enum PeriodFrequencyType {
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());
}
@@ -40,7 +40,7 @@ public class DropdownReadPlatformServiceImpl implements DropdownReadPlatformServ
public List<EnumOptionData> retrievePeriodFrequencyTypeOptions() {
final List<EnumOptionData> 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;
}
@@ -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 class AprCalculator {
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;
}
}
}
@@ -227,7 +227,7 @@ public class LoanScheduleAssembler {
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 @@ public class LoanScheduleAssembler {
if (firstRepaymentDate.isBefore(minimumFirstRepaymentDate)) { throw new MinDaysBetweenDisbursalAndFirstRepaymentViolationException(
disbursalDate, firstRepaymentDate, minimumDaysBetweenDisbursalAndFirstRepayment); }
}
}
}
@@ -223,6 +223,9 @@ public class LoanProduct extends AbstractPersistableCustom<Long> {
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 class LoanProduct extends AbstractPersistableCustom<Long> {
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 class LoanProduct extends AbstractPersistableCustom<Long> {
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 class LoanProduct extends AbstractPersistableCustom<Long> {
this.isEqualAmortization = isEqualAmortization;
}
}
}
@@ -561,7 +561,8 @@ public class LoanProductRelatedDetail implements LoanProductMinimumRepaymentSche
}
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 class LoanProductRelatedDetail implements LoanProductMinimumRepaymentSche
this.isEqualAmortization = isEqualAmortization;
}
}
}
@@ -513,7 +513,7 @@ public final class LoanProductDataValidator {
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 final class LoanProductDataValidator {
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 @@ public final class LoanProductDataValidator {
}
}
}
}
@@ -132,7 +132,7 @@ public class LoanDropdownReadPlatformServiceImpl implements LoanDropdownReadPlat
public List<EnumOptionData> retrieveInterestRateFrequencyTypeOptions() {
// support for monthly and annual percentage rate (MPR) and (APR)
final List<EnumOptionData> interestRateFrequencyTypeOptions = Arrays.asList(interestRateFrequencyType(PeriodFrequencyType.MONTHS),
interestRateFrequencyType(PeriodFrequencyType.YEARS));
interestRateFrequencyType(PeriodFrequencyType.YEARS), interestRateFrequencyType(PeriodFrequencyType.WHOLE_TERM));
return interestRateFrequencyTypeOptions;
}
@@ -220,4 +220,4 @@ public class LoanDropdownReadPlatformServiceImpl implements LoanDropdownReadPlat
preCloseInterestCalculationStrategy(LoanPreClosureInterestCalculationStrategy.TILL_REST_FREQUENCY_DATE));
return preCloseInterestCalculationStrategyOptions;
}
}
}
@@ -239,6 +239,10 @@ public class LoanEnumerations {
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 class LoanEnumerations {
return optionData;
}
}
}