Fix loan repayment schedule with multidisburse

This commit is contained in:
Jose Alberto Hernandez
2022-09-22 10:58:23 +02:00
committed by Arnold Gálovics
parent c8a084cb97
commit 1521b9dcf6
17 changed files with 237 additions and 290 deletions
@@ -1288,7 +1288,7 @@ public class ClientLoanIntegrationTest {
.withInterestCalculationPeriodTypeSameAsRepaymentPeriod() //
.withExpectedDisbursementDate("20 September 2011") //
.withSubmittedOnDate("20 September 2011") //
.withwithRepaymentStrategy(repaymentStrategy) //
.withRepaymentStrategy(repaymentStrategy) //
.withCollaterals(collaterals).withCharges(charges).build(clientID.toString(), loanProductID.toString(), savingsId);
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
}
@@ -1316,7 +1316,7 @@ public class ClientLoanIntegrationTest {
.withInterestCalculationPeriodTypeSameAsRepaymentPeriod() //
.withExpectedDisbursementDate(fourMonthsfromNow) //
.withSubmittedOnDate(fourMonthsfromNow) //
.withwithRepaymentStrategy(repaymentStrategy) //
.withRepaymentStrategy(repaymentStrategy) //
.withCollaterals(collaterals).withCharges(charges).build(clientID.toString(), loanProductID.toString(), savingsId);
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
}
@@ -4757,7 +4757,7 @@ public class ClientLoanIntegrationTest {
.withInterestCalculationPeriodTypeSameAsRepaymentPeriod() //
.withExpectedDisbursementDate(disbursementDate) //
.withSubmittedOnDate(disbursementDate) //
.withwithRepaymentStrategy(repaymentStrategy) //
.withRepaymentStrategy(repaymentStrategy) //
.withPrincipalGrace(graceOnPrincipalPayment) //
.withInterestGrace(graceOnInterestPayment)//
.withCharges(charges)//
@@ -5816,7 +5816,7 @@ public class ClientLoanIntegrationTest {
.withRepaymentEveryAfter("2")
//
.withAmortizationTypeAsEqualPrincipalPayments().withRepaymentFrequencyTypeAsWeeks()
.withwithRepaymentStrategy(LoanProductTestBuilder.RBI_INDIA_STRATEGY).withInterestTypeAsFlatBalance()
.withRepaymentStrategy(LoanProductTestBuilder.RBI_INDIA_STRATEGY).withInterestTypeAsFlatBalance()
.withInterestCalculationPeriodTypeSameAsRepaymentPeriod().withPrincipalGrace("1").withInterestGrace("1")
.withLoanTermFrequency("4") //
.withLoanTermFrequencyAsMonths() //
@@ -478,7 +478,7 @@ public class DelinquencyBucketsIntegrationTest {
// First Loan Delinquency Classification after Disbursement command
assertEquals(getLoansLoanIdResponse.getDelinquencyRange().getClassification(), classificationExpected);
printRepaymentSchedule(getLoansLoanIdResponse);
loanTransactionHelper.printRepaymentSchedule(getLoansLoanIdResponse);
// Apply a partial repayment
operationDate = Utils.dateFormatter.format(todaysDate);
@@ -660,7 +660,7 @@ public class DelinquencyBucketsIntegrationTest {
// First Loan Delinquency Classification after Disbursement command
assertEquals(getLoansLoanIdResponse.getDelinquencyRange().getClassification(), classificationExpected01);
printRepaymentSchedule(getLoansLoanIdResponse);
loanTransactionHelper.printRepaymentSchedule(getLoansLoanIdResponse);
// Apply a repayment to get a first full paid installment
operationDate = Utils.dateFormatter.format(todaysDate);
@@ -752,7 +752,7 @@ public class DelinquencyBucketsIntegrationTest {
// First Loan Delinquency Classification after Disbursement command
assertEquals(getLoansLoanIdResponse.getDelinquencyRange().getClassification(), classificationExpected);
printRepaymentSchedule(getLoansLoanIdResponse);
loanTransactionHelper.printRepaymentSchedule(getLoansLoanIdResponse);
// Apply a repayment to get a full paid installment
operationDate = Utils.dateFormatter.format(todaysDate);
@@ -176,7 +176,7 @@ public class LoanAuditingIntegrationTest {
.withInterestCalculationPeriodTypeSameAsRepaymentPeriod() //
.withExpectedDisbursementDate(submittedOnDate) //
.withSubmittedOnDate(submittedOnDate) //
.withwithRepaymentStrategy(repaymentStrategy) //
.withRepaymentStrategy(repaymentStrategy) //
.withCharges(charges).build(clientID.toString(), loanProductID.toString(), savingsId);
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
}
@@ -19,6 +19,8 @@
package org.apache.fineract.integrationtests;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import io.restassured.builder.RequestSpecBuilder;
import io.restassured.builder.ResponseSpecBuilder;
@@ -32,6 +34,10 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.client.models.GetLoansLoanIdRepaymentPeriod;
import org.apache.fineract.client.models.GetLoansLoanIdRepaymentSchedule;
import org.apache.fineract.client.models.GetLoansLoanIdResponse;
import org.apache.fineract.integrationtests.common.ClientHelper;
import org.apache.fineract.integrationtests.common.CollateralManagementHelper;
import org.apache.fineract.integrationtests.common.Utils;
@@ -43,17 +49,15 @@ import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Slf4j
@SuppressWarnings({ "rawtypes", "unchecked" })
public class LoanDisbursementDetailsIntegrationTest {
private static final Logger LOG = LoggerFactory.getLogger(LoanDisbursementDetailsIntegrationTest.class);
private ResponseSpecification responseSpec;
private RequestSpecification requestSpec;
private LoanTransactionHelper loanTransactionHelper;
private Integer loanID;
private Integer loanId;
private Integer disbursementId;
final String approveDate = "01 March 2014";
final String expectedDisbursementDate = "01 March 2014";
@@ -80,18 +84,18 @@ public class LoanDisbursementDetailsIntegrationTest {
createTranches.add(this.loanTransactionHelper.createTrancheDetail(id, "01 September 2015", "5000"));
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec, "01 January 2014");
LOG.info("---------------------------------CLIENT CREATED WITH ID---------------------------------------------------{}", clientID);
log.info("---------------------------------CLIENT CREATED WITH ID---------------------------------------------------{}", clientID);
final Integer loanProductID = this.loanTransactionHelper.getLoanProductId(new LoanProductTestBuilder()
.withInterestTypeAsDecliningBalance().withMoratorium("", "").withAmortizationTypeAsEqualInstallments().withTranches(true)
.withInterestCalculationPeriodTypeAsRepaymentPeriod(true).build(null));
LOG.info("----------------------------------LOAN PRODUCT CREATED WITH ID------------------------------------------- {}",
log.info("----------------------------------LOAN PRODUCT CREATED WITH ID------------------------------------------- {}",
loanProductID);
final Integer loanIDWithEmi = applyForLoanApplicationWithEmiAmount(clientID, loanProductID, proposedAmount, createTranches,
installmentAmount);
LOG.info("-----------------------------------LOAN CREATED WITH EMI LOANID------------------------------------------------- {}",
log.info("-----------------------------------LOAN CREATED WITH EMI LOANID------------------------------------------------- {}",
loanIDWithEmi);
HashMap repaymentScheduleWithEmi = (HashMap) this.loanTransactionHelper.getLoanDetail(this.requestSpec, this.responseSpec,
@@ -105,24 +109,23 @@ public class LoanDisbursementDetailsIntegrationTest {
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanIDWithEmi);
LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
LOG.info("-----------------------------------APPROVE LOAN-----------------------------------------------------------");
log.info("-----------------------------------APPROVE LOAN-----------------------------------------------------------");
loanStatusHashMap = this.loanTransactionHelper.approveLoanWithApproveAmount("01 June 2015", "01 June 2015", "10000", loanIDWithEmi,
createTranches);
LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap);
LOG.info(
log.info(
"-----------------------------------MULTI DISBURSAL LOAN WITH EMI APPROVED SUCCESSFULLY---------------------------------------");
final Integer loanIDWithoutEmi = applyForLoanApplicationWithEmiAmount(clientID, loanProductID, proposedAmount, createTranches,
withoutInstallmentAmount);
HashMap repaymentScheduleWithoutEmi = (HashMap) this.loanTransactionHelper.getLoanDetail(this.requestSpec, this.responseSpec,
loanIDWithoutEmi, "repaymentSchedule");
this.loanTransactionHelper.getLoanDetail(this.requestSpec, this.responseSpec, loanIDWithoutEmi, "repaymentSchedule");
ArrayList<HashMap> periods1 = (ArrayList<HashMap>) repaymentScheduleWithEmi.get("periods");
assertEquals(15, periods1.size());
LOG.info("-----------------------------------LOAN CREATED WITHOUT EMI LOANID------------------------------------------------- {}",
log.info("-----------------------------------LOAN CREATED WITHOUT EMI LOANID------------------------------------------------- {}",
loanIDWithoutEmi);
/* To be uncommented once issue MIFOSX-2006 is closed. */
@@ -131,12 +134,12 @@ public class LoanDisbursementDetailsIntegrationTest {
HashMap loanStatusMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanIDWithoutEmi);
LoanStatusChecker.verifyLoanIsPending(loanStatusMap);
LOG.info("-----------------------------------APPROVE LOAN-----------------------------------------------------------");
log.info("-----------------------------------APPROVE LOAN-----------------------------------------------------------");
loanStatusHashMap = this.loanTransactionHelper.approveLoanWithApproveAmount("01 June 2015", "01 June 2015", "10000",
loanIDWithoutEmi, createTranches);
LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap);
LOG.info(
log.info(
"-----------------------------------MULTI DISBURSAL LOAN WITHOUT EMI APPROVED SUCCESSFULLY---------------------------------------");
}
@@ -205,6 +208,7 @@ public class LoanDisbursementDetailsIntegrationTest {
list.add(expectedRepaymentSchedule14);
for (int i = 0; i < list.size(); i++) {
log.info("values {} {} {}", i, periods.get(i), list.get(i));
this.assertRepaymentScheduleValuesWithEMI(periods.get(i), list.get(i), i);
}
}
@@ -213,7 +217,7 @@ public class LoanDisbursementDetailsIntegrationTest {
assertEquals(period.get("dueDate").toString(), expectedRepaymentSchedule.getDueDate());
assertEquals(period.get("principalLoanBalanceOutstanding"), expectedRepaymentSchedule.getPrincipalLoanBalanceOutstanding());
LOG.info("{}", period.get("totalOriginalDueForPeriod").toString());
log.info("{}", period.get("totalOriginalDueForPeriod").toString());
assertEquals(Float.parseFloat(period.get("totalOriginalDueForPeriod").toString()),
expectedRepaymentSchedule.getTotalOriginalDueForPeriod().floatValue(), 0.0f);
@@ -233,103 +237,25 @@ public class LoanDisbursementDetailsIntegrationTest {
}
}
/* Uncomment and modify test builder values once MIFOSX-2006 is closed. */
/*
* private void validateRepaymentScheduleWithoutEMI(ArrayList<HashMap> periods){ LoanDisbursementTestBuilder
* expectedRepaymentSchedule0 = new LoanDisbursementTestBuilder( "[2015, 6, 1]", 0.0f, 0.0f, null, null, 5000.0f,
* null, null, null);
*
* LoanDisbursementTestBuilder expectedRepaymentSchedule1 = new LoanDisbursementTestBuilder( "[2015, 7, 1]", 800.0f,
* 800.0f, 50.0f, 750.0f, 4250.0f, 750.0f, 750.0f, "[2015, 6, 1]");
*
* LoanDisbursementTestBuilder expectedRepaymentSchedule2 = new LoanDisbursementTestBuilder( "[2015, 8, 1]", 800.0f,
* 800.0f, 42.5f, 757.5f, 3492.5f, 757.5f, 757.5f, "[2015, 7, 1]");
*
* LoanDisbursementTestBuilder expectedRepaymentSchedule3 = new LoanDisbursementTestBuilder( "[2015, 9, 1]", 0.0f,
* 0.0f, null, null, 5000.0f, null, null, null);
*
* LoanDisbursementTestBuilder expectedRepaymentSchedule4 = new LoanDisbursementTestBuilder( "[2015, 9, 1]", 800.0f,
* 800.0f, 34.92f, 765.08f, 7727.42f, 765.08f, 765.08f, "[2015, 8, 1]");
*
* LoanDisbursementTestBuilder expectedRepaymentSchedule5 = new LoanDisbursementTestBuilder( "[2015, 10, 1]",
* 800.0f, 800.0f, 77.27f, 722.73f, 7004.69f, 722.73f, 722.73f, "[2015, 9, 1]");
*
* LoanDisbursementTestBuilder expectedRepaymentSchedule6 = new LoanDisbursementTestBuilder( "[2015, 11, 1]",
* 800.0f, 800.0f, 70.05f, 729.95f, 6274.74f, 729.95f, 729.95f, "[2015, 10, 1]");
*
* LoanDisbursementTestBuilder expectedRepaymentSchedule7 = new LoanDisbursementTestBuilder( "[2015, 12, 1]",
* 800.0f, 800.0f, 62.75f, 737.25f, 5537.49f, 737.25f, 737.25f, "[2015, 11, 1]");
*
* LoanDisbursementTestBuilder expectedRepaymentSchedule8 = new LoanDisbursementTestBuilder( "[2016, 1, 1]", 800.0f,
* 800.0f, 55.37f, 744.63f, 4792.86f, 744.63f, 744.63f, "[2015, 12, 1]");
*
* LoanDisbursementTestBuilder expectedRepaymentSchedule9 = new LoanDisbursementTestBuilder( "[2016, 2, 1]", 800.0f,
* 800.0f, 47.93f, 752.07f, 4040.79f, 752.07f, 752.07f, "[2016, 1, 1]");
*
* LoanDisbursementTestBuilder expectedRepaymentSchedule10 = new LoanDisbursementTestBuilder( "[2016, 3, 1]",
* 800.0f, 800.0f, 40.41f, 759.59f, 3281.2f, 759.59f, 759.59f, "[2016, 2, 1]");
*
* LoanDisbursementTestBuilder expectedRepaymentSchedule11 = new LoanDisbursementTestBuilder( "[2016, 4, 1]",
* 800.0f, 800.0f, 32.81f, 767.19f, 2514.01f, 767.19f, 767.19f, "[2016, 3, 1]");
*
* LoanDisbursementTestBuilder expectedRepaymentSchedule12 = new LoanDisbursementTestBuilder( "[2016, 5, 1]",
* 800.0f, 800.0f, 25.14f, 774.86f, 1739.15f, 774.86f, 774.86f, "[2016, 4, 1]");
*
* LoanDisbursementTestBuilder expectedRepaymentSchedule13 = new LoanDisbursementTestBuilder( "[2016, 6, 1]",
* 800.0f, 800.0f, 17.39f, 782.61f, 956.54f, 782.61f, 782.61f, "[2016, 5, 1]");
*
* LoanDisbursementTestBuilder expectedRepaymentSchedule14 = new LoanDisbursementTestBuilder( "[2016, 7, 1]",
* 966.11f, 966.11f, 9.57f, 956.54f, 0.0f, 956.54f, 956.54f, "[2016, 6, 1]");
*
* ArrayList<LoanDisbursementTestBuilder> list = new ArrayList<LoanDisbursementTestBuilder>();
* list.add(expectedRepaymentSchedule0); list.add(expectedRepaymentSchedule1); list.add(expectedRepaymentSchedule2);
* list.add(expectedRepaymentSchedule3); list.add(expectedRepaymentSchedule4); list.add(expectedRepaymentSchedule5);
* list.add(expectedRepaymentSchedule6); list.add(expectedRepaymentSchedule7); list.add(expectedRepaymentSchedule8);
* list.add(expectedRepaymentSchedule9); list.add(expectedRepaymentSchedule10);
* list.add(expectedRepaymentSchedule11); list.add(expectedRepaymentSchedule12);
* list.add(expectedRepaymentSchedule13); list.add(expectedRepaymentSchedule14);
*
* for (int i = 0; i < list.size(); i++) { this.assertRepaymentScheduleValuesWithoutEMI(periods.get(i), list.get(i),
* i); } }
*
* private void assertRepaymentScheduleValuesWithoutEMI(HashMap period, LoanDisbursementTestBuilder
* expectedRepaymentSchedule, int position) {
*
* assertEquals(period.get("dueDate").toString(), expectedRepaymentSchedule.getDueDate());
* assertEquals(period.get("principalLoanBalanceOutstanding"),
* expectedRepaymentSchedule.getPrincipalLoanBalanceOutstanding());
* assertEquals(period.get("totalOriginalDueForPeriod"), expectedRepaymentSchedule.getTotalOriginalDueForPeriod());
* assertEquals(period.get("totalOutstandingForPeriod"), expectedRepaymentSchedule.getTotalOutstandingForPeriod());
*
* if (position != 0 && position != 3) {
*
* assertEquals(period.get("interestOutstanding"), expectedRepaymentSchedule.getInterestOutstanding());
* assertEquals(period.get("principalOutstanding"), expectedRepaymentSchedule.getPrincipalOutstanding());
* assertEquals(period.get("principalDue"), expectedRepaymentSchedule.getPrincipalDue());
* assertEquals(period.get("principalOriginalDue"), expectedRepaymentSchedule.getPrincipalOriginalDue());
* assertEquals(period.get("fromDate").toString(), expectedRepaymentSchedule.getFromDate()); } }
*/
private Integer applyForLoanApplicationWithEmiAmount(final Integer clientID, final Integer loanProductID, final String proposedAmount,
private Integer applyForLoanApplicationWithEmiAmount(final Integer clientId, final Integer loanProductId, final String proposedAmount,
List<HashMap> tranches, final String installmentAmount) {
LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
log.info("----------------APPLYING FOR LOAN APPLICATION");
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
clientID.toString(), collateralId);
clientId.toString(), collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final String loanApplicationJSON = new LoanApplicationTestBuilder()
//
.withPrincipal(proposedAmount)
//
.withLoanTermFrequency("12")
//
.withLoanTermFrequencyAsMonths()
//
.withNumberOfRepayments("12").withRepaymentEveryAfter("1").withRepaymentFrequencyTypeAsMonths() //
final String loanApplicationJSON = new LoanApplicationTestBuilder() //
.withPrincipal(proposedAmount) //
.withLoanTermFrequency("12") //
.withLoanTermFrequencyAsMonths() //
.withNumberOfRepayments("12") //
.withRepaymentEveryAfter("1") //
.withRepaymentFrequencyTypeAsMonths() //
.withInterestRatePerPeriod("1") //
.withExpectedDisbursementDate("01 June 2015") //
.withTranches(tranches) //
@@ -337,12 +263,55 @@ public class LoanDisbursementDetailsIntegrationTest {
.withInterestTypeAsDecliningBalance() //
.withSubmittedOnDate("01 June 2015") //
.withAmortizationTypeAsEqualInstallments() //
.withCollaterals(collaterals).build(clientID.toString(), loanProductID.toString(), null);
.withCollaterals(collaterals).build(clientId.toString(), loanProductId.toString(), null);
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
}
@Test
public void validateEqualInstallmentsForMultiTrancheLoan() {
List<HashMap> emptyTranches = new ArrayList<>();
final String operationDate = "01 January 2014";
final String principal = "1000";
final String disbursedPrincipal = "900";
final Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec, operationDate);
log.info("-----------------CLIENT CREATED WITH ID------------------- {}", clientId);
final String loanProductJSON = new LoanProductTestBuilder().withAmortizationTypeAsEqualInstallments() //
.withInterestTypeAsDecliningBalance().withMoratorium("", "").withInterestCalculationPeriodTypeAsRepaymentPeriod(true)
.withInterestTypeAsDecliningBalance() //
.withMultiDisburse() //
.withDisallowExpectectedDisbursements(true) //
.build(null);
log.info("Product {}", loanProductJSON);
final Integer loanProductId = this.loanTransactionHelper.getLoanProductId(loanProductJSON);
log.info("------------------LOAN PRODUCT CREATED WITH ID----------- {}", loanProductId);
final Integer loanId = applyForMultiTrancheLoanApplication(clientId.toString(), loanProductId.toString(), principal, operationDate);
log.info("-------------------LOAN CREATED WITH loanId----------------- {}", loanId);
this.loanTransactionHelper.approveLoanWithApproveAmount(operationDate, expectedDisbursementDate, principal, loanId, emptyTranches);
log.info("-------------------MULTI DISBURSAL LOAN APPROVED SUCCESSFULLY-------");
GetLoansLoanIdResponse getLoansLoanIdResponse = this.loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
assertNotNull(getLoansLoanIdResponse);
this.loanTransactionHelper.printRepaymentSchedule(getLoansLoanIdResponse);
loanTransactionHelper.disburseLoanWithTransactionAmount(operationDate, loanId, disbursedPrincipal);
log.info("-------------------MULTI DISBURSAL LOAN DISBURSED SUCCESSFULLY-------");
getLoansLoanIdResponse = this.loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
assertNotNull(getLoansLoanIdResponse);
this.loanTransactionHelper.printRepaymentSchedule(getLoansLoanIdResponse);
final Double limit = 2.0;
evaluateEqualInstallmentsForRepaymentSchedule(getLoansLoanIdResponse.getRepaymentSchedule(), limit);
log.info("-----------MULTI DISBURSAL LOAN EQUAL INSTALLMENTS SUCCESSFULLY-------");
}
@Test
public void createApproveAndValidateMultiDisburseLoan() throws ParseException {
@@ -351,28 +320,29 @@ public class LoanDisbursementDetailsIntegrationTest {
createTranches.add(this.loanTransactionHelper.createTrancheDetail(id, "01 March 2014", "1000"));
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec, "01 January 2014");
LOG.info("---------------------------------CLIENT CREATED WITH ID--------------------------------------------------- {}", clientID);
log.info("---------------------------------CLIENT CREATED WITH ID--------------------------------------------------- {}", clientID);
final Integer loanProductID = this.loanTransactionHelper
.getLoanProductId(new LoanProductTestBuilder().withInterestTypeAsDecliningBalance().withTranches(true)
.withInterestCalculationPeriodTypeAsRepaymentPeriod(true).build(null));
LOG.info("----------------------------------LOAN PRODUCT CREATED WITH ID------------------------------------------- {}",
log.info("----------------------------------LOAN PRODUCT CREATED WITH ID------------------------------------------- {}",
loanProductID);
this.loanID = applyForLoanApplicationWithTranches(clientID, loanProductID, proposedAmount, createTranches);
LOG.info("-----------------------------------LOAN CREATED WITH LOANID------------------------------------------------- {}", loanID);
this.loanId = applyForLoanApplicationWithTranches(clientID, loanProductID, proposedAmount, createTranches);
log.info("-----------------------------------LOAN CREATED WITH LOANID------------------------------------------------- {}",
this.loanId);
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, this.loanId);
LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
LOG.info("-----------------------------------APPROVE LOAN-----------------------------------------------------------");
log.info("-----------------------------------APPROVE LOAN-----------------------------------------------------------");
loanStatusHashMap = this.loanTransactionHelper.approveLoanWithApproveAmount(approveDate, expectedDisbursementDate, approvalAmount,
loanID, createTranches);
this.loanId, createTranches);
LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap);
LOG.info("-----------------------------------MULTI DISBURSAL LOAN APPROVED SUCCESSFULLY---------------------------------------");
log.info("-----------------------------------MULTI DISBURSAL LOAN APPROVED SUCCESSFULLY---------------------------------------");
ArrayList<HashMap> disbursementDetails = (ArrayList<HashMap>) this.loanTransactionHelper.getLoanDetail(this.requestSpec,
this.responseSpec, this.loanID, "disbursementDetails");
this.responseSpec, this.loanId, "disbursementDetails");
this.disbursementId = (Integer) disbursementDetails.get(0).get("id");
this.editLoanDisbursementDetails();
}
@@ -386,7 +356,7 @@ public class LoanDisbursementDetailsIntegrationTest {
private void addNewDisbursementDetails() throws ParseException {
List<HashMap> addTranches = new ArrayList<>();
ArrayList<HashMap> disbursementDetails = (ArrayList<HashMap>) this.loanTransactionHelper.getLoanDetail(this.requestSpec,
this.responseSpec, this.loanID, "disbursementDetails");
this.responseSpec, this.loanId, "disbursementDetails");
ArrayList expectedDisbursementDate = (ArrayList) disbursementDetails.get(0).get("expectedDisbursementDate");
String date = formatExpectedDisbursementDate(expectedDisbursementDate.toString());
@@ -397,14 +367,14 @@ public class LoanDisbursementDetailsIntegrationTest {
addTranches.add(this.loanTransactionHelper.createTrancheDetail(id, "04 March 2014", "500"));
/* Add disbursement detail */
this.loanTransactionHelper.addAndDeleteDisbursementDetail(this.loanID, this.approvalAmount, this.expectedDisbursementDate,
this.loanTransactionHelper.addAndDeleteDisbursementDetail(this.loanId, this.approvalAmount, this.expectedDisbursementDate,
addTranches, "");
}
private void deleteDisbursmentDetails() throws ParseException {
List<HashMap> deleteTranches = new ArrayList<>();
ArrayList<HashMap> disbursementDetails = (ArrayList<HashMap>) this.loanTransactionHelper.getLoanDetail(this.requestSpec,
this.responseSpec, this.loanID, "disbursementDetails");
this.responseSpec, this.loanId, "disbursementDetails");
/* Delete the last tranche */
for (int i = 0; i < disbursementDetails.size() - 1; i++) {
ArrayList expectedDisbursementDate = (ArrayList) disbursementDetails.get(i).get("expectedDisbursementDate");
@@ -414,7 +384,7 @@ public class LoanDisbursementDetailsIntegrationTest {
}
/* Add disbursement detail */
this.loanTransactionHelper.addAndDeleteDisbursementDetail(this.loanID, this.approvalAmount, this.expectedDisbursementDate,
this.loanTransactionHelper.addAndDeleteDisbursementDetail(this.loanId, this.approvalAmount, this.expectedDisbursementDate,
deleteTranches, "");
}
@@ -422,11 +392,11 @@ public class LoanDisbursementDetailsIntegrationTest {
String updatedExpectedDisbursementDate = "01 March 2014";
String updatedPrincipal = "900";
/* Update */
this.loanTransactionHelper.editDisbursementDetail(this.loanID, this.disbursementId, this.approvalAmount,
this.loanTransactionHelper.editDisbursementDetail(this.loanId, this.disbursementId, this.approvalAmount,
this.expectedDisbursementDate, updatedExpectedDisbursementDate, updatedPrincipal, "");
/* Validate Edit */
ArrayList<HashMap> disbursementDetails = (ArrayList<HashMap>) this.loanTransactionHelper.getLoanDetail(this.requestSpec,
this.responseSpec, this.loanID, "disbursementDetails");
this.responseSpec, this.loanId, "disbursementDetails");
assertEquals(Float.parseFloat(updatedPrincipal), disbursementDetails.get(0).get("principal"));
ArrayList expectedDisbursementDate = (ArrayList) disbursementDetails.get(0).get("expectedDisbursementDate");
String date = formatExpectedDisbursementDate(expectedDisbursementDate.toString());
@@ -435,7 +405,6 @@ public class LoanDisbursementDetailsIntegrationTest {
}
private String formatExpectedDisbursementDate(String expectedDisbursementDate) throws ParseException {
SimpleDateFormat source = new SimpleDateFormat("[yyyy, MM, dd]");
SimpleDateFormat target = new SimpleDateFormat("dd MMMM yyyy", Locale.US);
String date = target.format(source.parse(expectedDisbursementDate));
@@ -443,35 +412,56 @@ public class LoanDisbursementDetailsIntegrationTest {
return date;
}
private Integer applyForLoanApplicationWithTranches(final Integer clientID, final Integer loanProductID, String principal,
private Integer applyForLoanApplicationWithTranches(final Integer clientId, final Integer loanProductId, String principal,
List<HashMap> tranches) {
LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
log.info("----------------APPLYING FOR LOAN APPLICATION");
List<HashMap> collaterals = new ArrayList<>();
final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(collateralId);
final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec,
clientID.toString(), collateralId);
clientId.toString(), collateralId);
Assertions.assertNotNull(clientCollateralId);
addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
final String loanApplicationJSON = new LoanApplicationTestBuilder()
//
.withPrincipal(principal)
//
.withLoanTermFrequency("5")
//
.withLoanTermFrequencyAsMonths()
//
.withNumberOfRepayments("5").withRepaymentEveryAfter("1").withRepaymentFrequencyTypeAsMonths() //
final String loanApplicationJSON = new LoanApplicationTestBuilder() //
.withPrincipal(principal) //
.withLoanTermFrequency("5") //
.withLoanTermFrequencyAsMonths() //
.withNumberOfRepayments("5") //
.withRepaymentEveryAfter("1") //
.withRepaymentFrequencyTypeAsMonths() //
.withInterestRatePerPeriod("2") //
.withExpectedDisbursementDate("01 March 2014") //
.withTranches(tranches) //
.withInterestTypeAsDecliningBalance() //
.withSubmittedOnDate("01 March 2014") //
.withCollaterals(collaterals).build(clientID.toString(), loanProductID.toString(), null);
.withCollaterals(collaterals).build(clientId.toString(), loanProductId.toString(), null);
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
}
private Integer applyForMultiTrancheLoanApplication(final String clientId, final String loanProductId, String principal,
String operationDate) {
log.info("----------------APPLYING FOR MULTI TRANCHE LOAN APPLICATION");
List<HashMap> emptyData = new ArrayList<>();
final String loanApplicationJSON = new LoanApplicationTestBuilder() //
.withPrincipal(principal) //
.withLoanTermFrequency("3") //
.withLoanTermFrequencyAsMonths() //
.withNumberOfRepayments("3") //
.withRepaymentEveryAfter("1") //
.withRepaymentFrequencyTypeAsMonths() //
.withInterestRatePerPeriod("0") //
.withExpectedDisbursementDate(operationDate) //
.withTranches(emptyData) //
.withInterestTypeAsDecliningBalance() //
.withSubmittedOnDate(operationDate) //
.withCollaterals(emptyData) //
.build(clientId, loanProductId, null);
log.info("Loan account {}", loanApplicationJSON);
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
}
private void addCollaterals(List<HashMap> collaterals, Integer collateralId, BigDecimal quantity) {
collaterals.add(collaterals(collateralId, quantity));
}
@@ -483,4 +473,24 @@ public class LoanDisbursementDetailsIntegrationTest {
return collateral;
}
public void evaluateEqualInstallmentsForRepaymentSchedule(GetLoansLoanIdRepaymentSchedule getLoanRepaymentSchedule, Double limit) {
Double totalOutstandingForPeriod = 0.0;
Double totalInstallmentAmountForPeriod = 0.0;
if (getLoanRepaymentSchedule != null) {
log.info("Loan with {} periods", getLoanRepaymentSchedule.getPeriods().size());
for (GetLoansLoanIdRepaymentPeriod period : getLoanRepaymentSchedule.getPeriods()) {
if (period.getPeriod() != null) {
log.info("Period number {} for due date {} and outstanding {} {}", period.getPeriod(), period.getDueDate(),
period.getTotalOutstandingForPeriod(), period.getTotalInstallmentAmountForPeriod());
if (period.getPeriod() == 1) {
totalOutstandingForPeriod = period.getTotalOutstandingForPeriod();
totalInstallmentAmountForPeriod = period.getTotalInstallmentAmountForPeriod();
} else {
assertTrue(Math.abs(period.getTotalOutstandingForPeriod() - totalOutstandingForPeriod) <= limit);
assertTrue(Math.abs(period.getTotalInstallmentAmountForPeriod() - totalInstallmentAmountForPeriod) <= limit);
}
}
}
}
}
}
@@ -245,7 +245,7 @@ public class LoanRepaymentRescheduleAtDisbursementTest {
.withInterestCalculationPeriodTypeAsDays() //
.withExpectedDisbursementDate(disbursementDate) //
.withSubmittedOnDate(disbursementDate) //
.withwithRepaymentStrategy(repaymentStrategy) //
.withRepaymentStrategy(repaymentStrategy) //
.withCollaterals(collaterals).withCharges(charges)//
.build(clientID.toString(), loanProductID.toString(), null);
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
@@ -204,7 +204,7 @@ public class LoanRescheduleWithAdvancePaymentTest {
.withRepaymentFrequencyTypeAsMonths().withAmortizationTypeAsEqualInstallments().withInterestCalculationPeriodTypeAsDays()
.withInterestRatePerPeriod("12").withInterestTypeAsDecliningBalance().withSubmittedOnDate(submittedDate)
.withExpectedDisbursementDate(submittedDate).withFirstRepaymentDate(firstRepaymentDate)
.withwithRepaymentStrategy(LoanApplicationTestBuilder.INTEREST_PRINCIPAL_PENALTIES_FEES_ORDER_STRATEGY)
.withRepaymentStrategy(LoanApplicationTestBuilder.INTEREST_PRINCIPAL_PENALTIES_FEES_ORDER_STRATEGY)
.withinterestChargedFromDate(submittedDate).build(this.clientId.toString(), this.loanProductId.toString(), null);
this.loanId = this.loanTransactionHelper.getLoanId(loanApplicationJSON);
@@ -318,7 +318,7 @@ public class LoanRescheduleWithAdvancePaymentTest {
.withRepaymentFrequencyTypeAsMonths().withAmortizationTypeAsEqualInstallments().withInterestCalculationPeriodTypeAsDays()
.withInterestRatePerPeriod("12").withInterestTypeAsDecliningBalance().withSubmittedOnDate(submittedDate)
.withExpectedDisbursementDate(submittedDate).withFirstRepaymentDate(firstRepaymentDate)
.withwithRepaymentStrategy(LoanApplicationTestBuilder.INTEREST_PRINCIPAL_PENALTIES_FEES_ORDER_STRATEGY)
.withRepaymentStrategy(LoanApplicationTestBuilder.INTEREST_PRINCIPAL_PENALTIES_FEES_ORDER_STRATEGY)
.withinterestChargedFromDate(submittedDate).build(this.clientId.toString(), this.loanProductId.toString(), null);
this.loanId = this.loanTransactionHelper.getLoanId(loanApplicationJSON);
@@ -409,7 +409,7 @@ public class LoanReschedulingWithinCenterTest {
.withInterestCalculationPeriodTypeAsDays() //
.withExpectedDisbursementDate(disbursementDate) //
.withSubmittedOnDate(disbursementDate) //
.withwithRepaymentStrategy(repaymentStrategy) //
.withRepaymentStrategy(repaymentStrategy) //
.withCollaterals(collaterals).withCharges(charges)//
.build(clientID.toString(), groupId.toString(), loanProductID.toString(), null);
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
@@ -187,7 +187,7 @@ public class LoanTransactionAuditingIntegrationTest {
.withInterestCalculationPeriodTypeSameAsRepaymentPeriod() //
.withExpectedDisbursementDate(submittedOnDate) //
.withSubmittedOnDate(submittedOnDate) //
.withwithRepaymentStrategy(repaymentStrategy) //
.withRepaymentStrategy(repaymentStrategy) //
.withCharges(charges).build(clientID.toString(), loanProductID.toString(), savingsId);
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
}
@@ -335,7 +335,7 @@ public class LoanApplicationTestBuilder {
return this;
}
public LoanApplicationTestBuilder withwithRepaymentStrategy(final String transactionProcessingStrategy) {
public LoanApplicationTestBuilder withRepaymentStrategy(final String transactionProcessingStrategy) {
this.transactionProcessingID = transactionProcessingStrategy;
return this;
}
@@ -98,6 +98,7 @@ public class LoanProductTestBuilder {
private Boolean allowApprovedDisbursedAmountsOverApplied = false;
private String overAppliedCalculationType = null;
private Integer overAppliedNumber = null;
private Boolean isEqualAmortization = false;
private Boolean isInterestRecalculationEnabled = false;
private String daysInYearType = "1";
@@ -168,6 +169,7 @@ public class LoanProductTestBuilder {
map.put("accountingRule", this.accountingRule);
map.put("minPrincipal", this.minPrincipal);
map.put("maxPrincipal", this.maxPrincipal);
map.put("isEqualAmortization", this.isEqualAmortization);
map.put("overdueDaysForNPA", this.overdueDaysForNPA);
if (this.minimumDaysBetweenDisbursalAndFirstRepayment != null) {
map.put("minimumDaysBetweenDisbursalAndFirstRepayment", this.minimumDaysBetweenDisbursalAndFirstRepayment);
@@ -382,6 +384,11 @@ public class LoanProductTestBuilder {
return this;
}
public LoanProductTestBuilder withEqualAmortization(boolean isEqualAmortization) {
this.isEqualAmortization = isEqualAmortization;
return this;
}
public LoanProductTestBuilder withMultiDisburse() {
this.multiDisburseLoan = true;
return this;
@@ -42,6 +42,8 @@ import javax.ws.rs.core.MediaType;
import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.client.models.GetDelinquencyTagHistoryResponse;
import org.apache.fineract.client.models.GetLoanProductsProductIdResponse;
import org.apache.fineract.client.models.GetLoansLoanIdRepaymentPeriod;
import org.apache.fineract.client.models.GetLoansLoanIdRepaymentSchedule;
import org.apache.fineract.client.models.GetLoansLoanIdResponse;
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
import org.apache.fineract.client.util.JSON;
@@ -1062,4 +1064,16 @@ public class LoanTransactionHelper {
"---------------------------------GET A LOAN TRANSACTION ENTITY AUDIT FIELDS---------------------------------------------");
return Utils.performServerGet(requestSpec, responseSpec, GET_LOAN_TRANSACTION_URL, jsonReturn);
}
public void printRepaymentSchedule(GetLoansLoanIdResponse getLoansLoanIdResponse) {
GetLoansLoanIdRepaymentSchedule getLoanRepaymentSchedule = getLoansLoanIdResponse.getRepaymentSchedule();
if (getLoanRepaymentSchedule != null) {
log.info("Loan with {} periods", getLoanRepaymentSchedule.getPeriods().size());
for (GetLoansLoanIdRepaymentPeriod period : getLoanRepaymentSchedule.getPeriods()) {
log.info("Period number {} for due date {} and outstanding {}", period.getPeriod(), period.getDueDate(),
period.getTotalOutstandingForPeriod());
}
}
}
}