Merge pull request #962 from pramodn02/MIFOSX-1272
MIFOSX-1272 : added recalculation of charges for diff disburse amount
This commit is contained in:
+59
@@ -189,6 +189,65 @@ public class ClientLoanIntegrationTest {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@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<HashMap> charges = new ArrayList<HashMap>();
|
||||||
|
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<HashMap> loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
|
||||||
|
HashMap disbursementDetail = loanSchedule.get(0);
|
||||||
|
|
||||||
|
List<HashMap> 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
|
@Test
|
||||||
public void testLoanCharges_SPECIFIED_DUE_DATE_FEE() {
|
public void testLoanCharges_SPECIFIED_DUE_DATE_FEE() {
|
||||||
this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec);
|
this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec);
|
||||||
|
|||||||
+13
-6
@@ -83,11 +83,15 @@ public class LoanTransactionHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public HashMap disburseLoan(final String date, final Integer loanID) {
|
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) {
|
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) {
|
public HashMap undoDisbursal(final Integer loanID) {
|
||||||
@@ -107,9 +111,9 @@ public class LoanTransactionHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Integer waiveInterestAndReturnTransactionId(final String date, final String amountToBeWaived, final Integer loanID) {
|
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),
|
Integer resourceId = Utils.performServerPost(this.requestSpec, this.responseSpec,
|
||||||
getWaiveBodyAsJSON(date, amountToBeWaived), "resourceId");
|
createLoanTransactionURL(WAIVE_INTEREST_COMMAND, loanID), getWaiveBodyAsJSON(date, amountToBeWaived), "resourceId");
|
||||||
return resourceId;
|
return resourceId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public HashMap makeRepayment(final String date, final Float amountToBePaid, final Integer loanID) {
|
public HashMap makeRepayment(final String date, final Float amountToBePaid, final Integer loanID) {
|
||||||
@@ -161,12 +165,15 @@ public class LoanTransactionHelper {
|
|||||||
return (Integer) response.get("resourceId");
|
return (Integer) response.get("resourceId");
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getDisburseLoanAsJSON(final String actualDisbursementDate) {
|
private String getDisburseLoanAsJSON(final String actualDisbursementDate, final String transactionAmount) {
|
||||||
final HashMap<String, String> map = new HashMap<String, String>();
|
final HashMap<String, String> map = new HashMap<String, String>();
|
||||||
map.put("locale", "en");
|
map.put("locale", "en");
|
||||||
map.put("dateFormat", "dd MMMM yyyy");
|
map.put("dateFormat", "dd MMMM yyyy");
|
||||||
map.put("actualDisbursementDate", actualDisbursementDate);
|
map.put("actualDisbursementDate", actualDisbursementDate);
|
||||||
map.put("note", "DISBURSE NOTE");
|
map.put("note", "DISBURSE NOTE");
|
||||||
|
if (transactionAmount != null) {
|
||||||
|
map.put("transactionAmount", transactionAmount);
|
||||||
|
}
|
||||||
return new Gson().toJson(map);
|
return new Gson().toJson(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+43
-39
@@ -1200,23 +1200,7 @@ public class Loan extends AbstractPersistable<Long> {
|
|||||||
actualChanges.put("recalculateLoanSchedule", true);
|
actualChanges.put("recalculateLoanSchedule", true);
|
||||||
|
|
||||||
for (final LoanCharge loanCharge : possiblyModifedLoanCharges) {
|
for (final LoanCharge loanCharge : possiblyModifedLoanCharges) {
|
||||||
final BigDecimal amount = calculateAmountPercentageAppliedTo(loanCharge);
|
recalculateLoanCharge(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());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1276,6 +1260,26 @@ public class Loan extends AbstractPersistable<Long> {
|
|||||||
return actualChanges;
|
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<String, Object> actualChanges) {
|
private void updateDisbursementDetails(final JsonCommand command, final Map<String, Object> actualChanges) {
|
||||||
|
|
||||||
List<Long> list = fetchDisbursementIds();
|
List<Long> list = fetchDisbursementIds();
|
||||||
@@ -1470,23 +1474,7 @@ public class Loan extends AbstractPersistable<Long> {
|
|||||||
|
|
||||||
// charges are optional
|
// charges are optional
|
||||||
for (final LoanCharge loanCharge : charges()) {
|
for (final LoanCharge loanCharge : charges()) {
|
||||||
final BigDecimal amount = calculateAmountPercentageAppliedTo(loanCharge);
|
recalculateLoanCharge(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());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateSummaryWithTotalFeeChargesDueAtDisbursement(deriveSumTotalOfChargesDueAtDisbursement());
|
updateSummaryWithTotalFeeChargesDueAtDisbursement(deriveSumTotalOfChargesDueAtDisbursement());
|
||||||
@@ -1722,7 +1710,6 @@ public class Loan extends AbstractPersistable<Long> {
|
|||||||
validateDisbursementDateIsOnNonWorkingDay(workingDays, allowTransactionsOnNonWorkingDay);
|
validateDisbursementDateIsOnNonWorkingDay(workingDays, allowTransactionsOnNonWorkingDay);
|
||||||
validateDisbursementDateIsOnHoliday(allowTransactionsOnHoliday, holidays);
|
validateDisbursementDateIsOnHoliday(allowTransactionsOnHoliday, holidays);
|
||||||
|
|
||||||
handleDisbursementTransaction(actualDisbursementDate);
|
|
||||||
BigDecimal emiAmount = command.bigDecimalValueOfParameterNamed(LoanApiConstants.emiAmountParameterName);
|
BigDecimal emiAmount = command.bigDecimalValueOfParameterNamed(LoanApiConstants.emiAmountParameterName);
|
||||||
boolean isEmiAmountChanged = false;
|
boolean isEmiAmountChanged = false;
|
||||||
if (this.loanProduct.isMultiDisburseLoan() && emiAmount != null && emiAmount.compareTo(retriveLastEmiAmount()) != 0) {
|
if (this.loanProduct.isMultiDisburseLoan() && emiAmount != null && emiAmount.compareTo(retriveLastEmiAmount()) != 0) {
|
||||||
@@ -1734,11 +1721,17 @@ public class Loan extends AbstractPersistable<Long> {
|
|||||||
if (isRepaymentScheduleRegenerationRequiredForDisbursement(actualDisbursementDate) || recalculateSchedule || isEmiAmountChanged) {
|
if (isRepaymentScheduleRegenerationRequiredForDisbursement(actualDisbursementDate) || recalculateSchedule || isEmiAmountChanged) {
|
||||||
regenerateRepaymentSchedule(loanScheduleFactory, currency, calculatedRepaymentsStartingFromDate, isHolidayEnabled, holidays,
|
regenerateRepaymentSchedule(loanScheduleFactory, currency, calculatedRepaymentsStartingFromDate, isHolidayEnabled, holidays,
|
||||||
workingDays);
|
workingDays);
|
||||||
updateLoanRepaymentPeriodsDerivedFields(actualDisbursementDate);
|
if (recalculateSchedule) {
|
||||||
} else {
|
Set<LoanCharge> charges = this.charges();
|
||||||
updateLoanRepaymentPeriodsDerivedFields(actualDisbursementDate);
|
for (LoanCharge loanCharge : charges) {
|
||||||
updateLoanSummaryDerivedFields();
|
recalculateLoanCharge(loanCharge);
|
||||||
|
}
|
||||||
|
updateSummaryWithTotalFeeChargesDueAtDisbursement(deriveSumTotalOfChargesDueAtDisbursement());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
updateLoanRepaymentPeriodsDerivedFields(actualDisbursementDate);
|
||||||
|
updateLoanSummaryDerivedFields();
|
||||||
|
handleDisbursementTransaction(actualDisbursementDate);
|
||||||
|
|
||||||
final Money interestApplied = Money.of(getCurrency(), this.summary.getTotalInterestCharged());
|
final Money interestApplied = Money.of(getCurrency(), this.summary.getTotalInterestCharged());
|
||||||
|
|
||||||
@@ -2104,6 +2097,13 @@ public class Loan extends AbstractPersistable<Long> {
|
|||||||
|
|
||||||
regenerateRepaymentSchedule(loanScheduleFactory, applicationCurrency, calculatedRepaymentsStartingFromDate,
|
regenerateRepaymentSchedule(loanScheduleFactory, applicationCurrency, calculatedRepaymentsStartingFromDate,
|
||||||
isHolidayEnabled, holidays, workingDays);
|
isHolidayEnabled, holidays, workingDays);
|
||||||
|
if(isDisbueseAmtChanged){
|
||||||
|
Set<LoanCharge> charges = charges();
|
||||||
|
for (LoanCharge loanCharge : charges) {
|
||||||
|
recalculateLoanCharge(loanCharge);
|
||||||
|
}
|
||||||
|
updateSummaryWithTotalFeeChargesDueAtDisbursement(deriveSumTotalOfChargesDueAtDisbursement());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actualChanges.put("actualDisbursementDate", "");
|
actualChanges.put("actualDisbursementDate", "");
|
||||||
@@ -3843,4 +3843,8 @@ public class Loan extends AbstractPersistable<Long> {
|
|||||||
return installment;
|
return installment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BigDecimal getApprovedPrincipal() {
|
||||||
|
return this.approvedPrincipal;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user