Merge pull request #672 from pramodn02/MIFOSX-787
enabled percentage of interrest for loans
This commit is contained in:
+6
-1
@@ -29,7 +29,12 @@ public enum ChargeCalculationType {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
public static Object[] validValues() {
|
||||
public static Object[] validValuesForLoan() {
|
||||
return new Integer[] { ChargeCalculationType.FLAT.getValue(), ChargeCalculationType.PERCENT_OF_AMOUNT.getValue(),
|
||||
ChargeCalculationType.PERCENT_OF_AMOUNT_AND_INTEREST.getValue(),ChargeCalculationType.PERCENT_OF_INTEREST.getValue() };
|
||||
}
|
||||
|
||||
public static Object[] validValuesForSavings() {
|
||||
return new Integer[] { ChargeCalculationType.FLAT.getValue(), ChargeCalculationType.PERCENT_OF_AMOUNT.getValue() };
|
||||
}
|
||||
|
||||
|
||||
+11
-6
@@ -67,6 +67,9 @@ public final class ChargeDefinitionCommandFromApiJsonDeserializer {
|
||||
baseDataValidator.reset().parameter("chargeAppliesTo").value(chargeAppliesTo).isOneOfTheseValues(ChargeAppliesTo.validValues());
|
||||
}
|
||||
|
||||
final Integer chargeCalculationType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed("chargeCalculationType", element);
|
||||
baseDataValidator.reset().parameter("chargeCalculationType").value(chargeCalculationType).notNull();
|
||||
|
||||
final ChargeAppliesTo appliesTo = ChargeAppliesTo.fromInt(chargeAppliesTo);
|
||||
if (appliesTo.isLoanCharge()) {
|
||||
// loan applicable validation
|
||||
@@ -81,6 +84,10 @@ public final class ChargeDefinitionCommandFromApiJsonDeserializer {
|
||||
if (chargePaymentMode != null) {
|
||||
baseDataValidator.reset().parameter("chargePaymentMode").value(chargePaymentMode).isOneOfTheseValues(ChargePaymentMode.validValues());
|
||||
}
|
||||
|
||||
if (chargeCalculationType != null) {
|
||||
baseDataValidator.reset().parameter("chargeCalculationType").value(chargeCalculationType).isOneOfTheseValues(ChargeCalculationType.validValuesForLoan());
|
||||
}
|
||||
|
||||
} else if (appliesTo.isSavingsCharge()) {
|
||||
// savings applicable validation
|
||||
@@ -103,6 +110,10 @@ public final class ChargeDefinitionCommandFromApiJsonDeserializer {
|
||||
final MonthDay monthDay = this.fromApiJsonHelper.extractMonthDayNamed("feeOnMonthDay", element);
|
||||
baseDataValidator.reset().parameter("feeOnMonthDay").value(monthDay).notNull();
|
||||
}
|
||||
|
||||
if (chargeCalculationType != null) {
|
||||
baseDataValidator.reset().parameter("chargeCalculationType").value(chargeCalculationType).isOneOfTheseValues(ChargeCalculationType.validValuesForSavings());
|
||||
}
|
||||
}
|
||||
|
||||
final String name = this.fromApiJsonHelper.extractStringNamed("name", element);
|
||||
@@ -124,12 +135,6 @@ public final class ChargeDefinitionCommandFromApiJsonDeserializer {
|
||||
baseDataValidator.reset().parameter("active").value(active).notNull();
|
||||
}
|
||||
|
||||
final Integer chargeCalculationType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed("chargeCalculationType", element);
|
||||
baseDataValidator.reset().parameter("chargeCalculationType").value(chargeCalculationType).notNull();
|
||||
if (chargeCalculationType != null) {
|
||||
baseDataValidator.reset().parameter("chargeCalculationType").value(chargeCalculationType).isOneOfTheseValues(ChargeCalculationType.validValues());
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists("minCap", element)) {
|
||||
final BigDecimal minCap = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed("minCap", element.getAsJsonObject());
|
||||
baseDataValidator.reset().parameter("minCap").value(minCap).notNull().positiveAmount();
|
||||
|
||||
+10
-3
@@ -691,12 +691,11 @@ public class Loan extends AbstractPersistable<Long> {
|
||||
amount = getPrincpal().getAmount();
|
||||
break;
|
||||
case PERCENT_OF_AMOUNT_AND_INTEREST:
|
||||
final BigDecimal totalInterestCharged = this.loanSummaryWrapper.calculateTotalInterestCharged(
|
||||
this.repaymentScheduleInstallments, getCurrency()).getAmount();
|
||||
final BigDecimal totalInterestCharged = getTotalInterest();
|
||||
amount = getPrincpal().getAmount().add(totalInterestCharged);
|
||||
break;
|
||||
case PERCENT_OF_INTEREST:
|
||||
amount = getSummary().getTotalInterestCharged();
|
||||
amount = getTotalInterest();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -704,6 +703,14 @@ public class Loan extends AbstractPersistable<Long> {
|
||||
return amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public BigDecimal getTotalInterest() {
|
||||
return this.loanSummaryWrapper.calculateTotalInterestCharged(
|
||||
this.repaymentScheduleInstallments, getCurrency()).getAmount();
|
||||
}
|
||||
|
||||
private BigDecimal calculatePerInstallmentChargeAmount(final LoanCharge loanCharge) {
|
||||
return calculatePerInstallmentChargeAmount(loanCharge.getChargeCalculation(), loanCharge.getPercentage());
|
||||
}
|
||||
|
||||
+23
-2
@@ -72,6 +72,7 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
||||
@Column(name = "calculation_on_amount", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal amountPercentageAppliedTo;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "charge_amount_or_percentage", scale = 6, precision = 19, nullable = false)
|
||||
private BigDecimal amountOrPercentage;
|
||||
|
||||
@@ -123,10 +124,10 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
||||
amountPercentageAppliedTo = loan.getPrincpal().getAmount();
|
||||
break;
|
||||
case PERCENT_OF_AMOUNT_AND_INTEREST:
|
||||
amountPercentageAppliedTo = loan.getPrincpal().getAmount().add(loan.getSummary().getTotalInterestCharged());
|
||||
amountPercentageAppliedTo = loan.getPrincpal().getAmount().add(loan.getTotalInterest());
|
||||
break;
|
||||
case PERCENT_OF_INTEREST:
|
||||
amountPercentageAppliedTo = loan.getSummary().getTotalInterestCharged();
|
||||
amountPercentageAppliedTo = loan.getTotalInterest();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -367,6 +368,26 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void update(final BigDecimal amount, final LocalDate dueDate, Integer numberOfRepayments){
|
||||
BigDecimal amountPercentageAppliedTo = BigDecimal.ZERO;
|
||||
if(this.loan!=null){
|
||||
switch (ChargeCalculationType.fromInt(this.chargeCalculation)) {
|
||||
case PERCENT_OF_AMOUNT:
|
||||
amountPercentageAppliedTo = loan.getPrincpal().getAmount();
|
||||
break;
|
||||
case PERCENT_OF_AMOUNT_AND_INTEREST:
|
||||
amountPercentageAppliedTo = loan.getPrincpal().getAmount().add(loan.getTotalInterest());
|
||||
break;
|
||||
case PERCENT_OF_INTEREST:
|
||||
amountPercentageAppliedTo = loan.getTotalInterest();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
update(amount, dueDate, amountPercentageAppliedTo, numberOfRepayments, BigDecimal.ZERO);
|
||||
}
|
||||
|
||||
public Map<String, Object> update(final JsonCommand command, final BigDecimal amount) {
|
||||
|
||||
|
||||
+14
-10
@@ -22,18 +22,22 @@ public class LoanRepaymentScheduleProcessingWrapper {
|
||||
public void reprocess(final MonetaryCurrency currency, final LocalDate disbursementDate,
|
||||
final List<LoanRepaymentScheduleInstallment> repaymentPeriods, final Set<LoanCharge> loanCharges) {
|
||||
|
||||
Money totalInterest = Money.zero(currency);
|
||||
for (final LoanRepaymentScheduleInstallment installment : repaymentPeriods) {
|
||||
totalInterest = totalInterest.plus(installment.getInterestCharged(currency));
|
||||
}
|
||||
LocalDate startDate = disbursementDate;
|
||||
for (final LoanRepaymentScheduleInstallment period : repaymentPeriods) {
|
||||
|
||||
final Money feeChargesDueForRepaymentPeriod = cumulativeFeeChargesDueWithin(startDate, period.getDueDate(), loanCharges,
|
||||
currency,period,repaymentPeriods.size());
|
||||
currency,period,repaymentPeriods.size(), totalInterest);
|
||||
final Money feeChargesWaivedForRepaymentPeriod = cumulativeFeeChargesWaivedWithin(startDate, period.getDueDate(), loanCharges,
|
||||
currency);
|
||||
final Money feeChargesWrittenOffForRepaymentPeriod = cumulativeFeeChargesWrittenOffWithin(startDate, period.getDueDate(),
|
||||
loanCharges, currency);
|
||||
|
||||
final Money penaltyChargesDueForRepaymentPeriod = cumulativePenaltyChargesDueWithin(startDate, period.getDueDate(),
|
||||
loanCharges, currency,period,repaymentPeriods.size());
|
||||
loanCharges, currency,period,repaymentPeriods.size(), totalInterest);
|
||||
final Money penaltyChargesWaivedForRepaymentPeriod = cumulativePenaltyChargesWaivedWithin(startDate, period.getDueDate(),
|
||||
loanCharges, currency);
|
||||
final Money penaltyChargesWrittenOffForRepaymentPeriod = cumulativePenaltyChargesWrittenOffWithin(startDate,
|
||||
@@ -48,7 +52,7 @@ public class LoanRepaymentScheduleProcessingWrapper {
|
||||
}
|
||||
|
||||
private Money cumulativeFeeChargesDueWithin(final LocalDate periodStart, final LocalDate periodEnd, final Set<LoanCharge> loanCharges,
|
||||
final MonetaryCurrency monetaryCurrency,LoanRepaymentScheduleInstallment period,int numberOfRepayments) {
|
||||
final MonetaryCurrency monetaryCurrency,LoanRepaymentScheduleInstallment period,int numberOfRepayments,final Money totalInterest) {
|
||||
|
||||
Money cumulative = Money.zero(monetaryCurrency);
|
||||
|
||||
@@ -74,11 +78,11 @@ public class LoanRepaymentScheduleProcessingWrapper {
|
||||
loanCharge.getChargeCalculation().isPercentageBased()) {
|
||||
BigDecimal amount = BigDecimal.ZERO;
|
||||
if (loanCharge.getChargeCalculation().isPercentageOfAmountAndInterest()) {
|
||||
amount = amount.add(period.getLoan().getSummary().getTotalPrincipalDisbursed()).add(period.getLoan().getSummary().getTotalInterestCharged());
|
||||
amount = amount.add(period.getLoan().getPrincpal().getAmount()).add(totalInterest.getAmount());
|
||||
} else if (loanCharge.getChargeCalculation().isPercentageOfInterest()) {
|
||||
amount = amount.add(period.getLoan().getSummary().getTotalInterestCharged());
|
||||
amount = amount.add(totalInterest.getAmount());
|
||||
} else {
|
||||
amount = amount.add(period.getLoan().getSummary().getTotalPrincipalDisbursed());
|
||||
amount = amount.add(period.getLoan().getPrincpal().getAmount());
|
||||
}
|
||||
BigDecimal loanChargeAmt = amount.multiply(loanCharge.getPercentage()).divide(BigDecimal.valueOf(100));
|
||||
cumulative = cumulative.plus(loanChargeAmt);
|
||||
@@ -130,7 +134,7 @@ public class LoanRepaymentScheduleProcessingWrapper {
|
||||
}
|
||||
|
||||
private Money cumulativePenaltyChargesDueWithin(final LocalDate periodStart, final LocalDate periodEnd,
|
||||
final Set<LoanCharge> loanCharges, final MonetaryCurrency currency,LoanRepaymentScheduleInstallment period,int numberOfRepayments) {
|
||||
final Set<LoanCharge> loanCharges, final MonetaryCurrency currency,LoanRepaymentScheduleInstallment period,int numberOfRepayments, Money totalInterest) {
|
||||
|
||||
Money cumulative = Money.zero(currency);
|
||||
|
||||
@@ -156,11 +160,11 @@ public class LoanRepaymentScheduleProcessingWrapper {
|
||||
loanCharge.getChargeCalculation().isPercentageBased()) {
|
||||
BigDecimal amount = BigDecimal.ZERO;
|
||||
if (loanCharge.getChargeCalculation().isPercentageOfAmountAndInterest()) {
|
||||
amount = amount.add(period.getLoan().getSummary().getTotalPrincipalDisbursed()).add(period.getLoan().getSummary().getTotalInterestCharged());
|
||||
amount = amount.add(period.getLoan().getPrincpal().getAmount()).add(totalInterest.getAmount());
|
||||
} else if (loanCharge.getChargeCalculation().isPercentageOfInterest()) {
|
||||
amount = amount.add(period.getLoan().getSummary().getTotalInterestCharged());
|
||||
amount = amount.add(totalInterest.getAmount());
|
||||
} else {
|
||||
amount = amount.add(period.getLoan().getSummary().getTotalPrincipalDisbursed());
|
||||
amount = amount.add(period.getLoan().getPrincpal().getAmount());
|
||||
}
|
||||
BigDecimal loanChargeAmt = amount.multiply(loanCharge.getPercentage()).divide(BigDecimal.valueOf(100));
|
||||
cumulative = cumulative.plus(loanChargeAmt);
|
||||
|
||||
+1
-1
@@ -91,7 +91,7 @@ public class LoanChargeAssembler {
|
||||
final LoanCharge loanCharge = this.loanChargeRepository.findOne(loanChargeId);
|
||||
if (loanCharge == null) { throw new LoanChargeNotFoundException(loanChargeId); }
|
||||
|
||||
loanCharge.update(amount, dueDate, principal, numberOfRepayments, BigDecimal.ZERO);
|
||||
loanCharge.update(amount, dueDate, numberOfRepayments);
|
||||
|
||||
loanCharges.add(loanCharge);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user