Skip to content

Commit

Permalink
Merge pull request apache#436 from MexinaD/FINERACT-416
Browse files Browse the repository at this point in the history
FINERACT-416 Interest of the whole term
  • Loading branch information
MexinaD authored Nov 22, 2018
2 parents d4abf17 + 5235b7e commit ccaec28
Show file tree
Hide file tree
Showing 9 changed files with 54 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -1106,4 +1106,4 @@ private void validateMinimumDaysBetweenDisbursalAndFirstRepayment(final LocalDat
if (firstRepaymentDate.isBefore(minimumFirstRepaymentDate)) { throw new MinDaysBetweenDisbursalAndFirstRepaymentViolationException(
disbursalDate, firstRepaymentDate, minimumDaysBetweenDisbursalAndFirstRepayment); }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand All @@ -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
Expand All @@ -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");
Expand Down Expand Up @@ -1380,4 +1382,4 @@ public void setEqualAmortization(boolean isEqualAmortization) {
this.isEqualAmortization = isEqualAmortization;
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -667,4 +668,4 @@ public void setEqualAmortization(boolean isEqualAmortization) {
this.isEqualAmortization = isEqualAmortization;
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -2101,4 +2101,4 @@ private void validatePartialPeriodSupport(final Integer interestCalculationPerio

}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ public List<EnumOptionData> retrieveRepaymentFrequencyOptionsForDaysOfWeek() {
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;
}

Expand Down Expand Up @@ -220,4 +220,4 @@ public List<EnumOptionData> retrivePreCloseInterestCalculationStrategyOptions()
preCloseInterestCalculationStrategy(LoanPreClosureInterestCalculationStrategy.TILL_REST_FREQUENCY_DATE));
return preCloseInterestCalculationStrategyOptions;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -726,4 +730,4 @@ public static EnumOptionData preCloseInterestCalculationStrategy(final LoanPreCl
return optionData;
}

}
}

0 comments on commit ccaec28

Please sign in to comment.