From 9c9c91b44ab1c2fbb5d5c35a8f2a4b83a450daf7 Mon Sep 17 00:00:00 2001 From: Pramod Nuthakki Date: Wed, 18 Jun 2014 11:50:51 +0530 Subject: [PATCH] MIFOSX-1272 : added recalculation of charges for diff disburse amount --- .../ClientLoanIntegrationTest.java | 59 +++++++++++++ .../common/loans/LoanTransactionHelper.java | 23 ++++-- .../portfolio/loanaccount/domain/Loan.java | 82 ++++++++++--------- 3 files changed, 117 insertions(+), 47 deletions(-) diff --git a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ClientLoanIntegrationTest.java b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ClientLoanIntegrationTest.java index bf3993334..e604c6ded 100644 --- a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ClientLoanIntegrationTest.java +++ b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ClientLoanIntegrationTest.java @@ -188,6 +188,65 @@ public class ClientLoanIntegrationTest { validateNumberForEqual("0.0", String.valueOf(disbursementDetail.get("feeChargesDue"))); } + + @Test + public void testLoanCharges_DISBURSEMENT_FEE_WITH_AMOUNT_CHANGE() { + this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec); + + final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + final Integer loanProductID = createLoanProduct(false, NONE); + + List charges = new ArrayList(); + Integer amountPercentage = ChargesHelper.createCharges(requestSpec, responseSpec, + ChargesHelper.getLoanDisbursementJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_PERCENTAGE_AMOUNT, "1")); + addCharges(charges, amountPercentage, "1", null); + Integer amountPlusInterestPercentage = ChargesHelper.createCharges(requestSpec, responseSpec, + ChargesHelper.getLoanDisbursementJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_PERCENTAGE_AMOUNT_AND_INTEREST, "1")); + addCharges(charges, amountPlusInterestPercentage, "1", null); + Integer interestPercentage = ChargesHelper.createCharges(requestSpec, responseSpec, + ChargesHelper.getLoanDisbursementJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_PERCENTAGE_INTEREST, "1")); + addCharges(charges, interestPercentage, "1", null); + + final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00"); + Assert.assertNotNull(loanID); + + HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); + LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap); + + ArrayList loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID); + HashMap disbursementDetail = loanSchedule.get(0); + + List loanCharges = this.loanTransactionHelper.getLoanCharges(loanID); + + validateCharge(amountPercentage, loanCharges, "1.0", "120.0", "0.0", "0.0"); + validateCharge(interestPercentage, loanCharges, "1.0", "6.06", "0.0", "0.0"); + validateCharge(amountPlusInterestPercentage, loanCharges, "1.0", "126.06", "0.0", "0.0"); + validateNumberForEqual("252.12", String.valueOf(disbursementDetail.get("feeChargesDue"))); + + System.out.println("-----------------------------------APPROVE LOAN-----------------------------------------"); + loanStatusHashMap = this.loanTransactionHelper.approveLoan("20 September 2011", loanID); + LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap); + LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap); + + // DISBURSE + loanStatusHashMap = this.loanTransactionHelper.disburseLoan("20 September 2011", loanID,"10000"); + System.out.println("DISBURSE " + loanStatusHashMap); + LoanStatusChecker.verifyLoanIsActive(loanStatusHashMap); + + loanCharges = this.loanTransactionHelper.getLoanCharges(loanID); + loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID); + disbursementDetail = loanSchedule.get(0); + + validateCharge(amountPercentage, loanCharges, "1.0", "0.0", "100.0", "0.0"); + validateCharge(interestPercentage, loanCharges, "1.0", "0.0", "5.05", "0.0"); + validateCharge(amountPlusInterestPercentage, loanCharges, "1.0", "0.0", "105.05", "0.0"); + validateNumberForEqual("210.1", String.valueOf(disbursementDetail.get("feeChargesDue"))); + + + } + + @Test public void testLoanCharges_SPECIFIED_DUE_DATE_FEE() { diff --git a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/loans/LoanTransactionHelper.java b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/loans/LoanTransactionHelper.java index c255c3ea7..370bea9e8 100644 --- a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/loans/LoanTransactionHelper.java +++ b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/loans/LoanTransactionHelper.java @@ -83,11 +83,15 @@ public class LoanTransactionHelper { } public HashMap disburseLoan(final String date, final Integer loanID) { - return performLoanTransaction(createLoanOperationURL(DISBURSE_LOAN_COMMAND, loanID), getDisburseLoanAsJSON(date)); + return performLoanTransaction(createLoanOperationURL(DISBURSE_LOAN_COMMAND, loanID), getDisburseLoanAsJSON(date, null)); } - + + public HashMap disburseLoan(final String date, final Integer loanID, final String disburseAmt) { + return performLoanTransaction(createLoanOperationURL(DISBURSE_LOAN_COMMAND, loanID), getDisburseLoanAsJSON(date, disburseAmt)); + } + public HashMap disburseLoanToSavings(final String date, final Integer loanID) { - return performLoanTransaction(createLoanOperationURL(DISBURSE_LOAN_TO_SAVINGS_COMMAND, loanID), getDisburseLoanAsJSON(date)); + return performLoanTransaction(createLoanOperationURL(DISBURSE_LOAN_TO_SAVINGS_COMMAND, loanID), getDisburseLoanAsJSON(date, null)); } public HashMap undoDisbursal(final Integer loanID) { @@ -105,11 +109,11 @@ public class LoanTransactionHelper { public HashMap waiveInterest(final String date, final String amountToBeWaived, final Integer loanID) { return performLoanTransaction(createLoanTransactionURL(WAIVE_INTEREST_COMMAND, loanID), getWaiveBodyAsJSON(date, amountToBeWaived)); } - + public Integer waiveInterestAndReturnTransactionId(final String date, final String amountToBeWaived, final Integer loanID) { - Integer resourceId = Utils.performServerPost(this.requestSpec, this.responseSpec, createLoanTransactionURL(WAIVE_INTEREST_COMMAND, loanID), - getWaiveBodyAsJSON(date, amountToBeWaived), "resourceId"); - return resourceId; + Integer resourceId = Utils.performServerPost(this.requestSpec, this.responseSpec, + createLoanTransactionURL(WAIVE_INTEREST_COMMAND, loanID), getWaiveBodyAsJSON(date, amountToBeWaived), "resourceId"); + return resourceId; } public HashMap makeRepayment(final String date, final Float amountToBePaid, final Integer loanID) { @@ -161,12 +165,15 @@ public class LoanTransactionHelper { return (Integer) response.get("resourceId"); } - private String getDisburseLoanAsJSON(final String actualDisbursementDate) { + private String getDisburseLoanAsJSON(final String actualDisbursementDate, final String transactionAmount) { final HashMap map = new HashMap(); map.put("locale", "en"); map.put("dateFormat", "dd MMMM yyyy"); map.put("actualDisbursementDate", actualDisbursementDate); map.put("note", "DISBURSE NOTE"); + if (transactionAmount != null) { + map.put("transactionAmount", transactionAmount); + } return new Gson().toJson(map); } 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 cbfda9d08..3bf2a4935 100755 --- 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 @@ -1200,23 +1200,7 @@ public class Loan extends AbstractPersistable { actualChanges.put("recalculateLoanSchedule", true); for (final LoanCharge loanCharge : possiblyModifedLoanCharges) { - final BigDecimal amount = calculateAmountPercentageAppliedTo(loanCharge); - BigDecimal chargeAmt = BigDecimal.ZERO; - BigDecimal totalChargeAmt = BigDecimal.ZERO; - if (loanCharge.getChargeCalculation().isPercentageBased()) { - chargeAmt = loanCharge.getPercentage(); - if (loanCharge.isInstalmentFee()) { - totalChargeAmt = calculatePerInstallmentChargeAmount(loanCharge); - } - } else { - chargeAmt = loanCharge.amount(); - if (loanCharge.isInstalmentFee()) { - chargeAmt = chargeAmt.divide(BigDecimal.valueOf(repaymentScheduleDetail().getNumberOfRepayments())); - } - } - loanCharge.update(chargeAmt, loanCharge.getDueLocalDate(), amount, repaymentScheduleDetail().getNumberOfRepayments(), - totalChargeAmt); - validateChargeHasValidSpecifiedDateIfApplicable(loanCharge, getDisbursementDate(), getLastRepaymentPeriodDueDate()); + recalculateLoanCharge(loanCharge); } } @@ -1276,6 +1260,26 @@ public class Loan extends AbstractPersistable { return actualChanges; } + private void recalculateLoanCharge(final LoanCharge loanCharge) { + final BigDecimal amount = calculateAmountPercentageAppliedTo(loanCharge); + BigDecimal chargeAmt = BigDecimal.ZERO; + BigDecimal totalChargeAmt = BigDecimal.ZERO; + if (loanCharge.getChargeCalculation().isPercentageBased()) { + chargeAmt = loanCharge.getPercentage(); + if (loanCharge.isInstalmentFee()) { + totalChargeAmt = calculatePerInstallmentChargeAmount(loanCharge); + } + } else { + chargeAmt = loanCharge.amount(); + if (loanCharge.isInstalmentFee()) { + chargeAmt = chargeAmt.divide(BigDecimal.valueOf(repaymentScheduleDetail().getNumberOfRepayments())); + } + } + loanCharge.update(chargeAmt, loanCharge.getDueLocalDate(), amount, repaymentScheduleDetail().getNumberOfRepayments(), + totalChargeAmt); + validateChargeHasValidSpecifiedDateIfApplicable(loanCharge, getDisbursementDate(), getLastRepaymentPeriodDueDate()); + } + private void updateDisbursementDetails(final JsonCommand command, final Map actualChanges) { List list = fetchDisbursementIds(); @@ -1470,23 +1474,7 @@ public class Loan extends AbstractPersistable { // charges are optional for (final LoanCharge loanCharge : charges()) { - final BigDecimal amount = calculateAmountPercentageAppliedTo(loanCharge); - BigDecimal chargeAmt = BigDecimal.ZERO; - BigDecimal totalChargeAmt = BigDecimal.ZERO; - if (loanCharge.getChargeCalculation().isPercentageBased()) { - chargeAmt = loanCharge.getPercentage(); - if (loanCharge.isInstalmentFee()) { - totalChargeAmt = calculatePerInstallmentChargeAmount(loanCharge); - } - } else { - chargeAmt = loanCharge.amount(); - if (loanCharge.isInstalmentFee()) { - chargeAmt = chargeAmt.divide(BigDecimal.valueOf(repaymentScheduleDetail().getNumberOfRepayments())); - } - } - loanCharge.update(chargeAmt, loanCharge.getDueLocalDate(), amount, repaymentScheduleDetail().getNumberOfRepayments(), - totalChargeAmt); - validateChargeHasValidSpecifiedDateIfApplicable(loanCharge, getDisbursementDate(), getLastRepaymentPeriodDueDate()); + recalculateLoanCharge(loanCharge); } updateSummaryWithTotalFeeChargesDueAtDisbursement(deriveSumTotalOfChargesDueAtDisbursement()); @@ -1722,7 +1710,6 @@ public class Loan extends AbstractPersistable { validateDisbursementDateIsOnNonWorkingDay(workingDays, allowTransactionsOnNonWorkingDay); validateDisbursementDateIsOnHoliday(allowTransactionsOnHoliday, holidays); - handleDisbursementTransaction(actualDisbursementDate); BigDecimal emiAmount = command.bigDecimalValueOfParameterNamed(LoanApiConstants.emiAmountParameterName); boolean isEmiAmountChanged = false; if (this.loanProduct.isMultiDisburseLoan() && emiAmount != null && emiAmount.compareTo(retriveLastEmiAmount()) != 0) { @@ -1734,11 +1721,17 @@ public class Loan extends AbstractPersistable { if (isRepaymentScheduleRegenerationRequiredForDisbursement(actualDisbursementDate) || recalculateSchedule || isEmiAmountChanged) { regenerateRepaymentSchedule(loanScheduleFactory, currency, calculatedRepaymentsStartingFromDate, isHolidayEnabled, holidays, workingDays); - updateLoanRepaymentPeriodsDerivedFields(actualDisbursementDate); - } else { - updateLoanRepaymentPeriodsDerivedFields(actualDisbursementDate); - updateLoanSummaryDerivedFields(); + if (recalculateSchedule) { + Set charges = this.charges(); + for (LoanCharge loanCharge : charges) { + recalculateLoanCharge(loanCharge); + } + updateSummaryWithTotalFeeChargesDueAtDisbursement(deriveSumTotalOfChargesDueAtDisbursement()); + } } + updateLoanRepaymentPeriodsDerivedFields(actualDisbursementDate); + updateLoanSummaryDerivedFields(); + handleDisbursementTransaction(actualDisbursementDate); final Money interestApplied = Money.of(getCurrency(), this.summary.getTotalInterestCharged()); @@ -2104,6 +2097,13 @@ public class Loan extends AbstractPersistable { regenerateRepaymentSchedule(loanScheduleFactory, applicationCurrency, calculatedRepaymentsStartingFromDate, isHolidayEnabled, holidays, workingDays); + if(isDisbueseAmtChanged){ + Set charges = charges(); + for (LoanCharge loanCharge : charges) { + recalculateLoanCharge(loanCharge); + } + updateSummaryWithTotalFeeChargesDueAtDisbursement(deriveSumTotalOfChargesDueAtDisbursement()); + } } actualChanges.put("actualDisbursementDate", ""); @@ -3843,4 +3843,8 @@ public class Loan extends AbstractPersistable { return installment; } + public BigDecimal getApprovedPrincipal() { + return this.approvedPrincipal; + } + } \ No newline at end of file