From f5c91ee28ec49f97c3402bbfe01d07683a7e22cb Mon Sep 17 00:00:00 2001 From: Pramod Nuthakki Date: Tue, 19 Nov 2013 01:20:02 +0530 Subject: [PATCH] enabled percentage of interrest for loans --- .../charge/domain/ChargeCalculationType.java | 7 +++++- ...initionCommandFromApiJsonDeserializer.java | 17 ++++++++----- .../portfolio/loanaccount/domain/Loan.java | 13 +++++++--- .../loanaccount/domain/LoanCharge.java | 25 +++++++++++++++++-- ...oanRepaymentScheduleProcessingWrapper.java | 24 ++++++++++-------- .../service/LoanChargeAssembler.java | 2 +- 6 files changed, 65 insertions(+), 23 deletions(-) diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/domain/ChargeCalculationType.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/domain/ChargeCalculationType.java index e5c4e7e27..92e78543a 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/domain/ChargeCalculationType.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/domain/ChargeCalculationType.java @@ -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() }; } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/serialization/ChargeDefinitionCommandFromApiJsonDeserializer.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/serialization/ChargeDefinitionCommandFromApiJsonDeserializer.java index 6d159829d..9aa6836f8 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/serialization/ChargeDefinitionCommandFromApiJsonDeserializer.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/serialization/ChargeDefinitionCommandFromApiJsonDeserializer.java @@ -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(); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java index 057381352..6d08b5129 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java @@ -691,12 +691,11 @@ public class Loan extends AbstractPersistable { 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 { 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()); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanCharge.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanCharge.java index a106265d5..0a865f903 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanCharge.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanCharge.java @@ -72,6 +72,7 @@ public class LoanCharge extends AbstractPersistable { @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 { 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 { } } } + + 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 update(final JsonCommand command, final BigDecimal amount) { diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanRepaymentScheduleProcessingWrapper.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanRepaymentScheduleProcessingWrapper.java index 058693113..92e6fac95 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanRepaymentScheduleProcessingWrapper.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanRepaymentScheduleProcessingWrapper.java @@ -22,18 +22,22 @@ public class LoanRepaymentScheduleProcessingWrapper { public void reprocess(final MonetaryCurrency currency, final LocalDate disbursementDate, final List repaymentPeriods, final Set 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 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 loanCharges, final MonetaryCurrency currency,LoanRepaymentScheduleInstallment period,int numberOfRepayments) { + final Set 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); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanChargeAssembler.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanChargeAssembler.java index 66f615939..edee75cdf 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanChargeAssembler.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanChargeAssembler.java @@ -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); }