diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java index 0489730b034..0290c404f68 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java @@ -1001,7 +1001,7 @@ private void updateBalanceBasedOnDisbursement(final LoanApplicationTerms loanApp periods.add(disbursementPeriod); BigDecimal downPaymentAmt = BigDecimal.ZERO; - if (loanApplicationTerms.isDownPaymentEnabled() && !disburseDetail.getKey().isEqual(scheduledDueDate)) { + if (loanApplicationTerms.isDownPaymentEnabled()) { final LoanScheduleModelDownPaymentPeriod downPaymentPeriod = createDownPaymentPeriod(loanApplicationTerms, scheduleParams, disburseDetail.getKey(), disburseDetail.getValue().getAmount()); periods.add(downPaymentPeriod); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAccountPaymentAllocationWithOverlappingDownPaymentInstallmentTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAccountPaymentAllocationWithOverlappingDownPaymentInstallmentTest.java index 6d2d07ce0c5..e7cd2062e72 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAccountPaymentAllocationWithOverlappingDownPaymentInstallmentTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAccountPaymentAllocationWithOverlappingDownPaymentInstallmentTest.java @@ -35,6 +35,7 @@ import java.util.HashMap; import java.util.UUID; import org.apache.fineract.client.models.GetLoanProductsProductIdResponse; +import org.apache.fineract.client.models.GetLoansLoanIdRepaymentPeriod; import org.apache.fineract.client.models.GetLoansLoanIdResponse; import org.apache.fineract.client.models.PostLoansLoanIdTransactionsRequest; import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse; @@ -49,7 +50,6 @@ import org.apache.fineract.integrationtests.common.loans.LoanTestLifecycleExtension; import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -73,7 +73,6 @@ public void setup() { } @Test - @Disabled("Needs to be fixed the overlapping installment handling first") public void loanAccountWithEnableDownPaymentAndEnableAutoRepaymentForDownPaymentWithOverlappingInstallmentPaymentAllocationTest() { try { @@ -161,33 +160,19 @@ public void loanAccountWithEnableDownPaymentAndEnableAutoRepaymentForDownPayment assertNotNull(loanDetails.getRepaymentSchedule()); - // first period [2023-03-03 to 2023-03-03] down payment installment - assertEquals(1, loanDetails.getRepaymentSchedule().getPeriods().get(1).getPeriod()); - assertEquals(LocalDate.of(2023, 3, 3), loanDetails.getRepaymentSchedule().getPeriods().get(1).getFromDate()); - assertEquals(LocalDate.of(2023, 3, 3), loanDetails.getRepaymentSchedule().getPeriods().get(1).getDueDate()); - assertEquals(125.00, loanDetails.getRepaymentSchedule().getPeriods().get(1).getTotalInstallmentAmountForPeriod()); - assertEquals(125.00, loanDetails.getRepaymentSchedule().getPeriods().get(1).getTotalPaidForPeriod()); - assertEquals(true, loanDetails.getRepaymentSchedule().getPeriods().get(1).getComplete()); - - // second period [2023-03-03 to 2023-04-03] regular installment - assertEquals(2, loanDetails.getRepaymentSchedule().getPeriods().get(2).getPeriod()); - assertEquals(LocalDate.of(2023, 3, 3), loanDetails.getRepaymentSchedule().getPeriods().get(2).getFromDate()); - assertEquals(LocalDate.of(2023, 4, 3), loanDetails.getRepaymentSchedule().getPeriods().get(2).getDueDate()); - assertEquals(187.5, loanDetails.getRepaymentSchedule().getPeriods().get(2).getTotalInstallmentAmountForPeriod()); - assertEquals(0.0, loanDetails.getRepaymentSchedule().getPeriods().get(2).getTotalPaidForPeriod()); - assertEquals(5.15, loanDetails.getRepaymentSchedule().getPeriods().get(2).getFeeChargesDue()); - assertEquals(0.0, loanDetails.getRepaymentSchedule().getPeriods().get(2).getFeeChargesPaid()); - assertEquals(10.0, loanDetails.getRepaymentSchedule().getPeriods().get(2).getPenaltyChargesDue()); - assertEquals(0.0, loanDetails.getRepaymentSchedule().getPeriods().get(2).getPenaltyChargesPaid()); - assertEquals(false, loanDetails.getRepaymentSchedule().getPeriods().get(2).getComplete()); - - // third period [2023-04-03 to 2023-05-03] regular installment - assertEquals(3, loanDetails.getRepaymentSchedule().getPeriods().get(3).getPeriod()); - assertEquals(LocalDate.of(2023, 4, 3), loanDetails.getRepaymentSchedule().getPeriods().get(3).getFromDate()); - assertEquals(LocalDate.of(2023, 5, 3), loanDetails.getRepaymentSchedule().getPeriods().get(3).getDueDate()); - assertEquals(187.5, loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalInstallmentAmountForPeriod()); - assertEquals(0.0, loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalPaidForPeriod()); - assertEquals(false, loanDetails.getRepaymentSchedule().getPeriods().get(3).getComplete()); + // periods + assertEquals(4, loanDetails.getRepaymentSchedule().getPeriods().size()); + // disbursement period [0] + verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(0), LocalDate.of(2023, 3, 3), 500.0); + // down payment period [1] + verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(1), 1, 125.0, 125.0, 125.0, 0.0, 0.0, 0.0, 0.0, 0.0, + true, LocalDate.of(2023, 3, 3), LocalDate.of(2023, 3, 3)); + // regular installment [2] + verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(2), 2, 187.5, 0.0, 0.0, 202.65, 5.15, 0.0, 10.0, 0.0, + false, LocalDate.of(2023, 3, 3), LocalDate.of(2023, 4, 3)); + // regular installment [3] + verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(3), 3, 187.5, 0.0, 0.0, 187.5, 0.0, 0.0, 0.0, 0.0, + false, LocalDate.of(2023, 4, 3), LocalDate.of(2023, 5, 3)); // second disbursement with overlapping installment i.e same due date as regular repayment due date @@ -195,7 +180,7 @@ public void loanAccountWithEnableDownPaymentAndEnableAutoRepaymentForDownPayment BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.BUSINESS_DATE, disbursementDate); loanTransactionHelper.disburseLoanWithTransactionAmount("03 April 2023", loanId, "1000"); - checkDownPaymentTransaction(disbursementDate, 234.85f, 0.0f, 5.15f, 10.0f, loanId); + checkDownPaymentTransaction(disbursementDate, 250.0f, 0.0f, 0.0f, 0.0f, loanId); // verify loan schedule @@ -203,147 +188,53 @@ public void loanAccountWithEnableDownPaymentAndEnableAutoRepaymentForDownPayment assertNotNull(loanDetails.getRepaymentSchedule()); - // verify that overlapping down payment installment is created after regular installment - - // and verify regular repayment type installment gets paid before down payment installment according to - // payment - - // allocation strategy [DEFAULT] - - // first period [2023-03-03 to 2023-03-03] first down payment installment - assertEquals(1, loanDetails.getRepaymentSchedule().getPeriods().get(1).getPeriod()); - assertEquals(LocalDate.of(2023, 3, 3), loanDetails.getRepaymentSchedule().getPeriods().get(1).getFromDate()); - assertEquals(LocalDate.of(2023, 3, 3), loanDetails.getRepaymentSchedule().getPeriods().get(1).getDueDate()); - assertEquals(125.00, loanDetails.getRepaymentSchedule().getPeriods().get(1).getTotalInstallmentAmountForPeriod()); - assertEquals(125.00, loanDetails.getRepaymentSchedule().getPeriods().get(1).getTotalPaidForPeriod()); - assertEquals(true, loanDetails.getRepaymentSchedule().getPeriods().get(1).getComplete()); - - // second period [2023-03-03 to 2023-04-03] regular installment, penalty and fee charges gets paid first - assertEquals(2, loanDetails.getRepaymentSchedule().getPeriods().get(3).getPeriod()); - assertEquals(LocalDate.of(2023, 3, 3), loanDetails.getRepaymentSchedule().getPeriods().get(3).getFromDate()); - assertEquals(LocalDate.of(2023, 4, 3), loanDetails.getRepaymentSchedule().getPeriods().get(3).getDueDate()); - assertEquals(500.00, loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalInstallmentAmountForPeriod()); - assertEquals(250.0, loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalPaidForPeriod()); - assertEquals(265.15, loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalOutstandingForPeriod()); - assertEquals(5.15, loanDetails.getRepaymentSchedule().getPeriods().get(3).getFeeChargesDue()); - assertEquals(5.15, loanDetails.getRepaymentSchedule().getPeriods().get(3).getFeeChargesPaid()); - assertEquals(10.0, loanDetails.getRepaymentSchedule().getPeriods().get(3).getPenaltyChargesDue()); - assertEquals(10.0, loanDetails.getRepaymentSchedule().getPeriods().get(3).getPenaltyChargesPaid()); - assertEquals(false, loanDetails.getRepaymentSchedule().getPeriods().get(3).getComplete()); - - // third period [2023-04-03 to 2023-04-03] overlapping down payment installment - assertEquals(3, loanDetails.getRepaymentSchedule().getPeriods().get(4).getPeriod()); - assertEquals(LocalDate.of(2023, 4, 3), loanDetails.getRepaymentSchedule().getPeriods().get(4).getFromDate()); - assertEquals(LocalDate.of(2023, 4, 3), loanDetails.getRepaymentSchedule().getPeriods().get(4).getDueDate()); - assertEquals(250.0, loanDetails.getRepaymentSchedule().getPeriods().get(4).getTotalInstallmentAmountForPeriod()); - assertEquals(0.0, loanDetails.getRepaymentSchedule().getPeriods().get(4).getTotalPaidForPeriod()); - assertEquals(false, loanDetails.getRepaymentSchedule().getPeriods().get(4).getComplete()); - - // fourth period [2023-04-03 to 2023-05-03] regular installment - assertEquals(4, loanDetails.getRepaymentSchedule().getPeriods().get(5).getPeriod()); - assertEquals(LocalDate.of(2023, 4, 3), loanDetails.getRepaymentSchedule().getPeriods().get(5).getFromDate()); - assertEquals(LocalDate.of(2023, 5, 3), loanDetails.getRepaymentSchedule().getPeriods().get(5).getDueDate()); - assertEquals(625.0, loanDetails.getRepaymentSchedule().getPeriods().get(5).getTotalInstallmentAmountForPeriod()); - assertEquals(0.0, loanDetails.getRepaymentSchedule().getPeriods().get(5).getTotalPaidForPeriod()); - assertEquals(false, loanDetails.getRepaymentSchedule().getPeriods().get(5).getComplete()); + // periods + assertEquals(6, loanDetails.getRepaymentSchedule().getPeriods().size()); + // disbursement period [0] + verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(0), LocalDate.of(2023, 3, 3), 500.0); + // down payment period [1] + verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(1), 1, 125.0, 125.0, 125.0, 0.0, 0.0, 0.0, 0.0, 0.0, + true, LocalDate.of(2023, 3, 3), LocalDate.of(2023, 3, 3)); + // disbursement period [2] + verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(2), LocalDate.of(2023, 4, 3), 1000.0); + // down payment period [3] + verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(3), 2, 250.0, 250.0, 250.0, 0.0, 0.0, 0.0, 0.0, 0.0, + true, LocalDate.of(2023, 4, 3), LocalDate.of(2023, 4, 3)); + // regular installment [4] + verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(4), 3, 562.5, 0.0, 0.0, 577.65, 5.15, 0.0, 10.0, 0.0, + false, LocalDate.of(2023, 3, 3), LocalDate.of(2023, 4, 3)); + // regular installment [5] + verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(5), 4, 562.5, 0.0, 0.0, 562.5, 0.0, 0.0, 0.0, 0.0, + false, LocalDate.of(2023, 4, 3), LocalDate.of(2023, 5, 3)); // make repayment for fully paying and verify that regular installment gets fully paid on 3rd april final PostLoansLoanIdTransactionsResponse repaymentTransaction_1 = loanTransactionHelper.makeLoanRepayment(loanExternalIdStr, new PostLoansLoanIdTransactionsRequest().dateFormat("dd MMMM yyyy").transactionDate("3 April 2023").locale("en") - .transactionAmount(265.15)); + .transactionAmount(577.65)); loanDetails = loanTransactionHelper.getLoanDetails(loanId.longValue()); assertNotNull(loanDetails.getRepaymentSchedule()); - // verify regular installment gets paid off - - // first period [2023-03-03 to 2023-03-03] first down payment installment - assertEquals(1, loanDetails.getRepaymentSchedule().getPeriods().get(1).getPeriod()); - assertEquals(LocalDate.of(2023, 3, 3), loanDetails.getRepaymentSchedule().getPeriods().get(1).getFromDate()); - assertEquals(LocalDate.of(2023, 3, 3), loanDetails.getRepaymentSchedule().getPeriods().get(1).getDueDate()); - assertEquals(125.00, loanDetails.getRepaymentSchedule().getPeriods().get(1).getTotalInstallmentAmountForPeriod()); - assertEquals(125.00, loanDetails.getRepaymentSchedule().getPeriods().get(1).getTotalPaidForPeriod()); - assertEquals(true, loanDetails.getRepaymentSchedule().getPeriods().get(1).getComplete()); - - // second period [2023-03-03 to 2023-04-03] regular installment, penalty and fee charges gets paid first - assertEquals(2, loanDetails.getRepaymentSchedule().getPeriods().get(3).getPeriod()); - assertEquals(LocalDate.of(2023, 3, 3), loanDetails.getRepaymentSchedule().getPeriods().get(3).getFromDate()); - assertEquals(LocalDate.of(2023, 4, 3), loanDetails.getRepaymentSchedule().getPeriods().get(3).getDueDate()); - assertEquals(500.00, loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalInstallmentAmountForPeriod()); - assertEquals(515.15, loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalPaidForPeriod()); - assertEquals(0.0, loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalOutstandingForPeriod()); - assertEquals(5.15, loanDetails.getRepaymentSchedule().getPeriods().get(3).getFeeChargesDue()); - assertEquals(5.15, loanDetails.getRepaymentSchedule().getPeriods().get(3).getFeeChargesPaid()); - assertEquals(10.0, loanDetails.getRepaymentSchedule().getPeriods().get(3).getPenaltyChargesDue()); - assertEquals(10.0, loanDetails.getRepaymentSchedule().getPeriods().get(3).getPenaltyChargesPaid()); - assertEquals(true, loanDetails.getRepaymentSchedule().getPeriods().get(3).getComplete()); - - // third period [2023-04-03 to 2023-04-03] overlapping down payment installment - assertEquals(3, loanDetails.getRepaymentSchedule().getPeriods().get(4).getPeriod()); - assertEquals(LocalDate.of(2023, 4, 3), loanDetails.getRepaymentSchedule().getPeriods().get(4).getFromDate()); - assertEquals(LocalDate.of(2023, 4, 3), loanDetails.getRepaymentSchedule().getPeriods().get(4).getDueDate()); - assertEquals(250.0, loanDetails.getRepaymentSchedule().getPeriods().get(4).getTotalInstallmentAmountForPeriod()); - assertEquals(0.0, loanDetails.getRepaymentSchedule().getPeriods().get(4).getTotalPaidForPeriod()); - assertEquals(false, loanDetails.getRepaymentSchedule().getPeriods().get(4).getComplete()); - - // fourth period [2023-04-03 to 2023-05-03] regular installment - assertEquals(4, loanDetails.getRepaymentSchedule().getPeriods().get(5).getPeriod()); - assertEquals(LocalDate.of(2023, 4, 3), loanDetails.getRepaymentSchedule().getPeriods().get(5).getFromDate()); - assertEquals(LocalDate.of(2023, 5, 3), loanDetails.getRepaymentSchedule().getPeriods().get(5).getDueDate()); - assertEquals(625.0, loanDetails.getRepaymentSchedule().getPeriods().get(5).getTotalInstallmentAmountForPeriod()); - assertEquals(0.0, loanDetails.getRepaymentSchedule().getPeriods().get(5).getTotalPaidForPeriod()); - assertEquals(false, loanDetails.getRepaymentSchedule().getPeriods().get(5).getComplete()); - - // make another repayment of 250 and verify downpayment installment gets paid off on 3rd april - final PostLoansLoanIdTransactionsResponse repaymentTransaction_2 = loanTransactionHelper.makeLoanRepayment(loanExternalIdStr, - new PostLoansLoanIdTransactionsRequest().dateFormat("dd MMMM yyyy").transactionDate("3 April 2023").locale("en") - .transactionAmount(250.00)); - - loanDetails = loanTransactionHelper.getLoanDetails(loanId.longValue()); - - assertNotNull(loanDetails.getRepaymentSchedule()); - - // verify down payment installment gets paid off - - // first period [2023-03-03 to 2023-03-03] first down payment installment - assertEquals(1, loanDetails.getRepaymentSchedule().getPeriods().get(1).getPeriod()); - assertEquals(LocalDate.of(2023, 3, 3), loanDetails.getRepaymentSchedule().getPeriods().get(1).getFromDate()); - assertEquals(LocalDate.of(2023, 3, 3), loanDetails.getRepaymentSchedule().getPeriods().get(1).getDueDate()); - assertEquals(125.00, loanDetails.getRepaymentSchedule().getPeriods().get(1).getTotalInstallmentAmountForPeriod()); - assertEquals(125.00, loanDetails.getRepaymentSchedule().getPeriods().get(1).getTotalPaidForPeriod()); - assertEquals(true, loanDetails.getRepaymentSchedule().getPeriods().get(1).getComplete()); - - // second period [2023-03-03 to 2023-04-03] regular installment, penalty and fee charges gets paid first and - // then principal - assertEquals(2, loanDetails.getRepaymentSchedule().getPeriods().get(3).getPeriod()); - assertEquals(LocalDate.of(2023, 3, 3), loanDetails.getRepaymentSchedule().getPeriods().get(3).getFromDate()); - assertEquals(LocalDate.of(2023, 4, 3), loanDetails.getRepaymentSchedule().getPeriods().get(3).getDueDate()); - assertEquals(500.00, loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalInstallmentAmountForPeriod()); - assertEquals(515.15, loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalPaidForPeriod()); - assertEquals(0.0, loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalOutstandingForPeriod()); - assertEquals(5.15, loanDetails.getRepaymentSchedule().getPeriods().get(3).getFeeChargesDue()); - assertEquals(5.15, loanDetails.getRepaymentSchedule().getPeriods().get(3).getFeeChargesPaid()); - assertEquals(10.0, loanDetails.getRepaymentSchedule().getPeriods().get(3).getPenaltyChargesDue()); - assertEquals(10.0, loanDetails.getRepaymentSchedule().getPeriods().get(3).getPenaltyChargesPaid()); - assertEquals(true, loanDetails.getRepaymentSchedule().getPeriods().get(3).getComplete()); - - // third period [2023-04-03 to 2023-04-03] down payment installment gets paid - assertEquals(3, loanDetails.getRepaymentSchedule().getPeriods().get(4).getPeriod()); - assertEquals(LocalDate.of(2023, 4, 3), loanDetails.getRepaymentSchedule().getPeriods().get(4).getFromDate()); - assertEquals(LocalDate.of(2023, 4, 3), loanDetails.getRepaymentSchedule().getPeriods().get(4).getDueDate()); - assertEquals(250.0, loanDetails.getRepaymentSchedule().getPeriods().get(4).getTotalInstallmentAmountForPeriod()); - assertEquals(250.0, loanDetails.getRepaymentSchedule().getPeriods().get(4).getTotalPaidForPeriod()); - assertEquals(true, loanDetails.getRepaymentSchedule().getPeriods().get(4).getComplete()); - - // fourth period [2023-04-03 to 2023-05-03] regular installment - assertEquals(4, loanDetails.getRepaymentSchedule().getPeriods().get(5).getPeriod()); - assertEquals(LocalDate.of(2023, 4, 3), loanDetails.getRepaymentSchedule().getPeriods().get(5).getFromDate()); - assertEquals(LocalDate.of(2023, 5, 3), loanDetails.getRepaymentSchedule().getPeriods().get(5).getDueDate()); - assertEquals(625.0, loanDetails.getRepaymentSchedule().getPeriods().get(5).getTotalInstallmentAmountForPeriod()); - assertEquals(0.0, loanDetails.getRepaymentSchedule().getPeriods().get(5).getTotalPaidForPeriod()); - assertEquals(false, loanDetails.getRepaymentSchedule().getPeriods().get(5).getComplete()); + // periods + assertEquals(6, loanDetails.getRepaymentSchedule().getPeriods().size()); + // disbursement period [0] + verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(0), LocalDate.of(2023, 3, 3), 500.0); + // down payment period [1] + verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(1), 1, 125.0, 125.0, 125.0, 0.0, 0.0, 0.0, 0.0, 0.0, + true, LocalDate.of(2023, 3, 3), LocalDate.of(2023, 3, 3)); + // disbursement period [2] + verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(2), LocalDate.of(2023, 4, 3), 1000.0); + // down payment period [3] + verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(3), 2, 250.0, 250.0, 250.0, 0.0, 0.0, 0.0, 0.0, 0.0, + true, LocalDate.of(2023, 4, 3), LocalDate.of(2023, 4, 3)); + // regular installment [4] + verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(4), 3, 562.5, 577.65, 562.5, 0.0, 5.15, 5.15, 10.0, + 10.0, true, LocalDate.of(2023, 3, 3), LocalDate.of(2023, 4, 3)); + // regular installment [5] + verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(5), 4, 562.5, 0.0, 0.0, 562.5, 0.0, 0.0, 0.0, 0.0, + false, LocalDate.of(2023, 4, 3), LocalDate.of(2023, 5, 3)); } finally { GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, Boolean.FALSE); @@ -352,7 +243,6 @@ public void loanAccountWithEnableDownPaymentAndEnableAutoRepaymentForDownPayment } @Test - @Disabled("Needs to be fixed the overlapping installment handling first") public void loanAccountWithEnableDownPaymentAndDisableAutoRepaymentForDownPaymentWithOverlappingInstallmentPaymentAllocationTest() { try { @@ -443,33 +333,19 @@ public void loanAccountWithEnableDownPaymentAndDisableAutoRepaymentForDownPaymen assertNotNull(loanDetails.getRepaymentSchedule()); - // first period [2023-03-03 to 2023-03-03] down payment installment - assertEquals(1, loanDetails.getRepaymentSchedule().getPeriods().get(1).getPeriod()); - assertEquals(LocalDate.of(2023, 3, 3), loanDetails.getRepaymentSchedule().getPeriods().get(1).getFromDate()); - assertEquals(LocalDate.of(2023, 3, 3), loanDetails.getRepaymentSchedule().getPeriods().get(1).getDueDate()); - assertEquals(125.00, loanDetails.getRepaymentSchedule().getPeriods().get(1).getTotalInstallmentAmountForPeriod()); - assertEquals(125.00, loanDetails.getRepaymentSchedule().getPeriods().get(1).getTotalPaidForPeriod()); - assertEquals(true, loanDetails.getRepaymentSchedule().getPeriods().get(1).getComplete()); - - // second period [2023-03-03 to 2023-04-03] regular installment - assertEquals(2, loanDetails.getRepaymentSchedule().getPeriods().get(2).getPeriod()); - assertEquals(LocalDate.of(2023, 3, 3), loanDetails.getRepaymentSchedule().getPeriods().get(2).getFromDate()); - assertEquals(LocalDate.of(2023, 4, 3), loanDetails.getRepaymentSchedule().getPeriods().get(2).getDueDate()); - assertEquals(187.5, loanDetails.getRepaymentSchedule().getPeriods().get(2).getTotalInstallmentAmountForPeriod()); - assertEquals(0.0, loanDetails.getRepaymentSchedule().getPeriods().get(2).getTotalPaidForPeriod()); - assertEquals(5.15, loanDetails.getRepaymentSchedule().getPeriods().get(2).getFeeChargesDue()); - assertEquals(0.0, loanDetails.getRepaymentSchedule().getPeriods().get(2).getFeeChargesPaid()); - assertEquals(10.0, loanDetails.getRepaymentSchedule().getPeriods().get(2).getPenaltyChargesDue()); - assertEquals(0.0, loanDetails.getRepaymentSchedule().getPeriods().get(2).getPenaltyChargesPaid()); - assertEquals(false, loanDetails.getRepaymentSchedule().getPeriods().get(2).getComplete()); - - // third period [2023-04-03 to 2023-05-03] regular installment - assertEquals(3, loanDetails.getRepaymentSchedule().getPeriods().get(3).getPeriod()); - assertEquals(LocalDate.of(2023, 4, 3), loanDetails.getRepaymentSchedule().getPeriods().get(3).getFromDate()); - assertEquals(LocalDate.of(2023, 5, 3), loanDetails.getRepaymentSchedule().getPeriods().get(3).getDueDate()); - assertEquals(187.5, loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalInstallmentAmountForPeriod()); - assertEquals(0.0, loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalPaidForPeriod()); - assertEquals(false, loanDetails.getRepaymentSchedule().getPeriods().get(3).getComplete()); + // periods + assertEquals(4, loanDetails.getRepaymentSchedule().getPeriods().size()); + // disbursement period [0] + verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(0), LocalDate.of(2023, 3, 3), 500.0); + // down payment period [1] + verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(1), 1, 125.0, 125.0, 125.0, 0.0, 0.0, 0.0, 0.0, 0.0, + true, LocalDate.of(2023, 3, 3), LocalDate.of(2023, 3, 3)); + // regular installment [2] + verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(2), 2, 187.5, 0.0, 0.0, 202.65, 5.15, 0.0, 10.0, 0.0, + false, LocalDate.of(2023, 3, 3), LocalDate.of(2023, 4, 3)); + // regular installment [3] + verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(3), 3, 187.5, 0.0, 0.0, 187.5, 0.0, 0.0, 0.0, 0.0, + false, LocalDate.of(2023, 4, 3), LocalDate.of(2023, 5, 3)); // second disbursement with overlapping installment i.e same due date as regular repayment due date @@ -488,148 +364,239 @@ public void loanAccountWithEnableDownPaymentAndDisableAutoRepaymentForDownPaymen assertNotNull(loanDetails.getRepaymentSchedule()); - // verify that overlapping down payment installment is created after regular installment - - // and verify regular repayment type installment gets paid before down payment installment according to - // payment - - // allocation strategy - - // first period [2023-03-03 to 2023-03-03] first down payment installment - assertEquals(1, loanDetails.getRepaymentSchedule().getPeriods().get(1).getPeriod()); - assertEquals(LocalDate.of(2023, 3, 3), loanDetails.getRepaymentSchedule().getPeriods().get(1).getFromDate()); - assertEquals(LocalDate.of(2023, 3, 3), loanDetails.getRepaymentSchedule().getPeriods().get(1).getDueDate()); - assertEquals(125.00, loanDetails.getRepaymentSchedule().getPeriods().get(1).getTotalInstallmentAmountForPeriod()); - assertEquals(125.00, loanDetails.getRepaymentSchedule().getPeriods().get(1).getTotalPaidForPeriod()); - assertEquals(true, loanDetails.getRepaymentSchedule().getPeriods().get(1).getComplete()); - - // second period [2023-03-03 to 2023-04-03] regular installment, principal gets paid first - assertEquals(2, loanDetails.getRepaymentSchedule().getPeriods().get(3).getPeriod()); - assertEquals(LocalDate.of(2023, 3, 3), loanDetails.getRepaymentSchedule().getPeriods().get(3).getFromDate()); - assertEquals(LocalDate.of(2023, 4, 3), loanDetails.getRepaymentSchedule().getPeriods().get(3).getDueDate()); - assertEquals(500.00, loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalInstallmentAmountForPeriod()); - assertEquals(250.0, loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalPaidForPeriod()); - assertEquals(250.0, loanDetails.getRepaymentSchedule().getPeriods().get(3).getPrincipalPaid()); - assertEquals(265.15, loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalOutstandingForPeriod()); - assertEquals(5.15, loanDetails.getRepaymentSchedule().getPeriods().get(3).getFeeChargesDue()); - assertEquals(0.0, loanDetails.getRepaymentSchedule().getPeriods().get(3).getFeeChargesPaid()); - assertEquals(10.0, loanDetails.getRepaymentSchedule().getPeriods().get(3).getPenaltyChargesDue()); - assertEquals(0.0, loanDetails.getRepaymentSchedule().getPeriods().get(3).getPenaltyChargesPaid()); - assertEquals(false, loanDetails.getRepaymentSchedule().getPeriods().get(3).getComplete()); - - // third period [2023-04-03 to 2023-04-03] overlapping down payment installment - assertEquals(3, loanDetails.getRepaymentSchedule().getPeriods().get(4).getPeriod()); - assertEquals(LocalDate.of(2023, 4, 3), loanDetails.getRepaymentSchedule().getPeriods().get(4).getFromDate()); - assertEquals(LocalDate.of(2023, 4, 3), loanDetails.getRepaymentSchedule().getPeriods().get(4).getDueDate()); - assertEquals(250.0, loanDetails.getRepaymentSchedule().getPeriods().get(4).getTotalInstallmentAmountForPeriod()); - assertEquals(0.0, loanDetails.getRepaymentSchedule().getPeriods().get(4).getTotalPaidForPeriod()); - assertEquals(false, loanDetails.getRepaymentSchedule().getPeriods().get(4).getComplete()); - - // fourth period [2023-04-03 to 2023-05-03] regular installment - assertEquals(4, loanDetails.getRepaymentSchedule().getPeriods().get(5).getPeriod()); - assertEquals(LocalDate.of(2023, 4, 3), loanDetails.getRepaymentSchedule().getPeriods().get(5).getFromDate()); - assertEquals(LocalDate.of(2023, 5, 3), loanDetails.getRepaymentSchedule().getPeriods().get(5).getDueDate()); - assertEquals(625.0, loanDetails.getRepaymentSchedule().getPeriods().get(5).getTotalInstallmentAmountForPeriod()); - assertEquals(0.0, loanDetails.getRepaymentSchedule().getPeriods().get(5).getTotalPaidForPeriod()); - assertEquals(false, loanDetails.getRepaymentSchedule().getPeriods().get(5).getComplete()); + // periods + assertEquals(6, loanDetails.getRepaymentSchedule().getPeriods().size()); + // disbursement period [0] + verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(0), LocalDate.of(2023, 3, 3), 500.0); + // down payment period [1] + verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(1), 1, 125.0, 125.0, 125.0, 0.0, 0.0, 0.0, 0.0, 0.0, + true, LocalDate.of(2023, 3, 3), LocalDate.of(2023, 3, 3)); + // disbursement period [2] + verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(2), LocalDate.of(2023, 4, 3), 1000.0); + // down payment period [3] + verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(3), 2, 250.0, 250.0, 250.0, 0.0, 0.0, 0.0, 0.0, 0.0, + true, LocalDate.of(2023, 4, 3), LocalDate.of(2023, 4, 3)); + // regular installment [4] + verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(4), 3, 562.5, 0.0, 0.0, 577.65, 5.15, 0.0, 10.0, 0.0, + false, LocalDate.of(2023, 3, 3), LocalDate.of(2023, 4, 3)); + // regular installment [5] + verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(5), 4, 562.5, 0.0, 0.0, 562.5, 0.0, 0.0, 0.0, 0.0, + false, LocalDate.of(2023, 4, 3), LocalDate.of(2023, 5, 3)); // make repayment for fully paying and verify that regular installment gets fully paid on 3rd april final PostLoansLoanIdTransactionsResponse repaymentTransaction_2 = loanTransactionHelper.makeLoanRepayment(loanExternalIdStr, new PostLoansLoanIdTransactionsRequest().dateFormat("dd MMMM yyyy").transactionDate("3 April 2023").locale("en") - .transactionAmount(265.15)); + .transactionAmount(577.65)); + + loanDetails = loanTransactionHelper.getLoanDetails(loanId.longValue()); + + assertNotNull(loanDetails.getRepaymentSchedule()); + + // periods + assertEquals(6, loanDetails.getRepaymentSchedule().getPeriods().size()); + // disbursement period [0] + verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(0), LocalDate.of(2023, 3, 3), 500.0); + // down payment period [1] + verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(1), 1, 125.0, 125.0, 125.0, 0.0, 0.0, 0.0, 0.0, 0.0, + true, LocalDate.of(2023, 3, 3), LocalDate.of(2023, 3, 3)); + // disbursement period [2] + verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(2), LocalDate.of(2023, 4, 3), 1000.0); + // down payment period [3] + verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(3), 2, 250.0, 250.0, 250.0, 0.0, 0.0, 0.0, 0.0, 0.0, + true, LocalDate.of(2023, 4, 3), LocalDate.of(2023, 4, 3)); + // regular installment [4] + verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(4), 3, 562.5, 577.65, 562.5, 0.0, 5.15, 5.15, 10.0, + 10.0, true, LocalDate.of(2023, 3, 3), LocalDate.of(2023, 4, 3)); + // regular installment [5] + verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(5), 4, 562.5, 0.0, 0.0, 562.5, 0.0, 0.0, 0.0, 0.0, + false, LocalDate.of(2023, 4, 3), LocalDate.of(2023, 5, 3)); + + } finally { + GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, Boolean.FALSE); + } + + } + + @Test + public void loanAccountWithEnableDownPaymentAndDisableAutoRepaymentForDownPaymentWithOverlappingInstallmentForMultipleDisbursementsOnSameDayTest() { + try { + + // Test with + // Enable Down Payment + // Disable Auto Repayment For Down Payment + // Overlapping down payment and regular installment with multiple disbursements on same day + + // Set business date + LocalDate disbursementDate = LocalDate.of(2023, 3, 3); + + GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, Boolean.TRUE); + BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.BUSINESS_DATE, disbursementDate); + + // Loan ExternalId + String loanExternalIdStr = UUID.randomUUID().toString(); + + // down-payment configuration + Boolean enableDownPayment = true; + BigDecimal disbursedAmountPercentageForDownPayment = BigDecimal.valueOf(25); + Boolean enableAutoRepaymentForDownPayment = false; + + final Integer clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId().intValue(); + + // Loan Product creation with down-payment configuration + final GetLoanProductsProductIdResponse getLoanProductsProductResponse = createLoanProductWithEnableDownPaymentAndMultipleDisbursements( + loanTransactionHelper, enableDownPayment, "25", enableAutoRepaymentForDownPayment); + + assertNotNull(getLoanProductsProductResponse); + assertEquals(enableDownPayment, getLoanProductsProductResponse.getEnableDownPayment()); + assertEquals(0, getLoanProductsProductResponse.getDisbursedAmountPercentageForDownPayment() + .compareTo(disbursedAmountPercentageForDownPayment)); + assertEquals(enableAutoRepaymentForDownPayment, getLoanProductsProductResponse.getEnableAutoRepaymentForDownPayment()); + + // create loan account + + final Integer loanId = createLoanAccountMultipleRepaymentsDisbursement(clientId, getLoanProductsProductResponse.getId(), + loanExternalIdStr, LoanProductTestBuilder.DEFAULT_STRATEGY); + + // Retrieve Loan with loanId + + GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanId.longValue()); + + // verify down-payment details for Loan + assertNotNull(loanDetails); + assertEquals(enableDownPayment, loanDetails.getEnableDownPayment()); + assertEquals(0, loanDetails.getDisbursedAmountPercentageForDownPayment().compareTo(disbursedAmountPercentageForDownPayment)); + assertEquals(enableAutoRepaymentForDownPayment, loanDetails.getEnableAutoRepaymentForDownPayment()); + + // first disbursement + loanTransactionHelper.disburseLoanWithTransactionAmount("03 March 2023", loanId, "200"); + + // make repayment on 3rd March + final PostLoansLoanIdTransactionsResponse repaymentTransaction = loanTransactionHelper.makeLoanRepayment(loanExternalIdStr, + new PostLoansLoanIdTransactionsRequest().dateFormat("dd MMMM yyyy").transactionDate("3 March 2023").locale("en") + .transactionAmount(50.0)); + + // verify loan schedule + + loanDetails = loanTransactionHelper.getLoanDetails(loanId.longValue()); + + assertNotNull(loanDetails.getRepaymentSchedule()); + + // periods + assertEquals(4, loanDetails.getRepaymentSchedule().getPeriods().size()); + // disbursement period [0] + verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(0), LocalDate.of(2023, 3, 3), 200.0); + // down payment period [1] + verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(1), 1, 50.0, 50.0, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0, true, + LocalDate.of(2023, 3, 3), LocalDate.of(2023, 3, 3)); + // regular installment [2] + verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(2), 2, 75.0, 0.0, 0.0, 75.0, 0.0, 0.0, 0.0, 0.0, false, + LocalDate.of(2023, 3, 3), LocalDate.of(2023, 4, 3)); + // regular installment [3] + verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(3), 3, 75.0, 0.0, 0.0, 75.0, 0.0, 0.0, 0.0, 0.0, false, + LocalDate.of(2023, 4, 3), LocalDate.of(2023, 5, 3)); + + // second disbursement with overlapping installment i.e same due date as regular repayment due date + + disbursementDate = LocalDate.of(2023, 4, 3); + BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.BUSINESS_DATE, disbursementDate); + loanTransactionHelper.disburseLoanWithTransactionAmount("03 April 2023", loanId, "200"); + + // make repayment on 3rd April + final PostLoansLoanIdTransactionsResponse repaymentTransaction_1 = loanTransactionHelper.makeLoanRepayment(loanExternalIdStr, + new PostLoansLoanIdTransactionsRequest().dateFormat("dd MMMM yyyy").transactionDate("3 April 2023").locale("en") + .transactionAmount(50.0)); + + // verify loan schedule + + loanDetails = loanTransactionHelper.getLoanDetails(loanId.longValue()); + + assertNotNull(loanDetails.getRepaymentSchedule()); + + // periods + assertEquals(6, loanDetails.getRepaymentSchedule().getPeriods().size()); + // disbursement period [0] + verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(0), LocalDate.of(2023, 3, 3), 200.0); + // down payment period [1] + verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(1), 1, 50.0, 50.0, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0, true, + LocalDate.of(2023, 3, 3), LocalDate.of(2023, 3, 3)); + // disbursement period [2] + verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(2), LocalDate.of(2023, 4, 3), 200.0); + // down payment period [3] + verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(3), 2, 50.0, 50.0, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0, true, + LocalDate.of(2023, 4, 3), LocalDate.of(2023, 4, 3)); + // regular installment [4] + verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(4), 3, 150.0, 0.0, 0.0, 150.0, 0.0, 0.0, 0.0, 0.0, + false, LocalDate.of(2023, 3, 3), LocalDate.of(2023, 4, 3)); + // regular installment [5] + verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(5), 4, 150.0, 0.0, 0.0, 150.0, 0.0, 0.0, 0.0, 0.0, + false, LocalDate.of(2023, 4, 3), LocalDate.of(2023, 5, 3)); + + // same day third disbursement with overlapping installment i.e same due date as regular repayment due date + // 3-April + loanTransactionHelper.disburseLoanWithTransactionAmount("03 April 2023", loanId, "200"); + + // make repayment on 3rd April + final PostLoansLoanIdTransactionsResponse repaymentTransaction_2 = loanTransactionHelper.makeLoanRepayment(loanExternalIdStr, + new PostLoansLoanIdTransactionsRequest().dateFormat("dd MMMM yyyy").transactionDate("3 April 2023").locale("en") + .transactionAmount(50.0)); + + // verify loan schedule loanDetails = loanTransactionHelper.getLoanDetails(loanId.longValue()); assertNotNull(loanDetails.getRepaymentSchedule()); - // verify regular installment gets paid off - - // first period [2023-03-03 to 2023-03-03] first down payment installment - assertEquals(1, loanDetails.getRepaymentSchedule().getPeriods().get(1).getPeriod()); - assertEquals(LocalDate.of(2023, 3, 3), loanDetails.getRepaymentSchedule().getPeriods().get(1).getFromDate()); - assertEquals(LocalDate.of(2023, 3, 3), loanDetails.getRepaymentSchedule().getPeriods().get(1).getDueDate()); - assertEquals(125.00, loanDetails.getRepaymentSchedule().getPeriods().get(1).getTotalInstallmentAmountForPeriod()); - assertEquals(125.00, loanDetails.getRepaymentSchedule().getPeriods().get(1).getTotalPaidForPeriod()); - assertEquals(true, loanDetails.getRepaymentSchedule().getPeriods().get(1).getComplete()); - - // second period [2023-03-03 to 2023-04-03] regular installment, principal gets paid first - assertEquals(2, loanDetails.getRepaymentSchedule().getPeriods().get(3).getPeriod()); - assertEquals(LocalDate.of(2023, 3, 3), loanDetails.getRepaymentSchedule().getPeriods().get(3).getFromDate()); - assertEquals(LocalDate.of(2023, 4, 3), loanDetails.getRepaymentSchedule().getPeriods().get(3).getDueDate()); - assertEquals(500.00, loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalInstallmentAmountForPeriod()); - assertEquals(515.15, loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalPaidForPeriod()); - assertEquals(0.0, loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalOutstandingForPeriod()); - assertEquals(500.0, loanDetails.getRepaymentSchedule().getPeriods().get(3).getPrincipalPaid()); - assertEquals(5.15, loanDetails.getRepaymentSchedule().getPeriods().get(3).getFeeChargesDue()); - assertEquals(5.15, loanDetails.getRepaymentSchedule().getPeriods().get(3).getFeeChargesPaid()); - assertEquals(10.0, loanDetails.getRepaymentSchedule().getPeriods().get(3).getPenaltyChargesDue()); - assertEquals(10.0, loanDetails.getRepaymentSchedule().getPeriods().get(3).getPenaltyChargesPaid()); - assertEquals(true, loanDetails.getRepaymentSchedule().getPeriods().get(3).getComplete()); - - // third period [2023-04-03 to 2023-04-03] overlapping down payment installment - assertEquals(3, loanDetails.getRepaymentSchedule().getPeriods().get(4).getPeriod()); - assertEquals(LocalDate.of(2023, 4, 3), loanDetails.getRepaymentSchedule().getPeriods().get(4).getFromDate()); - assertEquals(LocalDate.of(2023, 4, 3), loanDetails.getRepaymentSchedule().getPeriods().get(4).getDueDate()); - assertEquals(250.0, loanDetails.getRepaymentSchedule().getPeriods().get(4).getTotalInstallmentAmountForPeriod()); - assertEquals(0.0, loanDetails.getRepaymentSchedule().getPeriods().get(4).getTotalPaidForPeriod()); - assertEquals(false, loanDetails.getRepaymentSchedule().getPeriods().get(4).getComplete()); - - // fourth period [2023-04-03 to 2023-05-03] regular installment - assertEquals(4, loanDetails.getRepaymentSchedule().getPeriods().get(5).getPeriod()); - assertEquals(LocalDate.of(2023, 4, 3), loanDetails.getRepaymentSchedule().getPeriods().get(5).getFromDate()); - assertEquals(LocalDate.of(2023, 5, 3), loanDetails.getRepaymentSchedule().getPeriods().get(5).getDueDate()); - assertEquals(625.0, loanDetails.getRepaymentSchedule().getPeriods().get(5).getTotalInstallmentAmountForPeriod()); - assertEquals(0.0, loanDetails.getRepaymentSchedule().getPeriods().get(5).getTotalPaidForPeriod()); - assertEquals(false, loanDetails.getRepaymentSchedule().getPeriods().get(5).getComplete()); - - // make another repayment of 250 and verify downpayment installment gets paid off on 3rd april + // periods + assertEquals(7, loanDetails.getRepaymentSchedule().getPeriods().size()); + // disbursement period [0] + verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(0), LocalDate.of(2023, 3, 3), 200.0); + // down payment period [1] + verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(1), 1, 50.0, 50.0, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0, true, + LocalDate.of(2023, 3, 3), LocalDate.of(2023, 3, 3)); + // disbursement period [2] + verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(2), LocalDate.of(2023, 4, 3), 200.0); + // disbursement period [3] + verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(3), LocalDate.of(2023, 4, 3), 200.0); + // down payment period [4] + verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(4), 2, 100.0, 100.0, 100.0, 0.0, 0.0, 0.0, 0.0, 0.0, + true, LocalDate.of(2023, 4, 3), LocalDate.of(2023, 4, 3)); + // regular installment [5] + verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(5), 3, 225.0, 0.0, 0.0, 225.0, 0.0, 0.0, 0.0, 0.0, + false, LocalDate.of(2023, 3, 3), LocalDate.of(2023, 4, 3)); + // regular installment [6] + verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(6), 4, 225.0, 0.0, 0.0, 225.0, 0.0, 0.0, 0.0, 0.0, + false, LocalDate.of(2023, 4, 3), LocalDate.of(2023, 5, 3)); + + // make repayment for fully paying and verify that regular installment gets fully paid on 3rd april final PostLoansLoanIdTransactionsResponse repaymentTransaction_3 = loanTransactionHelper.makeLoanRepayment(loanExternalIdStr, new PostLoansLoanIdTransactionsRequest().dateFormat("dd MMMM yyyy").transactionDate("3 April 2023").locale("en") - .transactionAmount(250.00)); + .transactionAmount(225.0)); loanDetails = loanTransactionHelper.getLoanDetails(loanId.longValue()); assertNotNull(loanDetails.getRepaymentSchedule()); - // verify down payment installment gets paid off - - // first period [2023-03-03 to 2023-03-03] first down payment installment - assertEquals(1, loanDetails.getRepaymentSchedule().getPeriods().get(1).getPeriod()); - assertEquals(LocalDate.of(2023, 3, 3), loanDetails.getRepaymentSchedule().getPeriods().get(1).getFromDate()); - assertEquals(LocalDate.of(2023, 3, 3), loanDetails.getRepaymentSchedule().getPeriods().get(1).getDueDate()); - assertEquals(125.00, loanDetails.getRepaymentSchedule().getPeriods().get(1).getTotalInstallmentAmountForPeriod()); - assertEquals(125.00, loanDetails.getRepaymentSchedule().getPeriods().get(1).getTotalPaidForPeriod()); - assertEquals(true, loanDetails.getRepaymentSchedule().getPeriods().get(1).getComplete()); - - // second period [2023-03-03 to 2023-04-03] regular installment, principal gets paid first - assertEquals(2, loanDetails.getRepaymentSchedule().getPeriods().get(3).getPeriod()); - assertEquals(LocalDate.of(2023, 3, 3), loanDetails.getRepaymentSchedule().getPeriods().get(3).getFromDate()); - assertEquals(LocalDate.of(2023, 4, 3), loanDetails.getRepaymentSchedule().getPeriods().get(3).getDueDate()); - assertEquals(500.00, loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalInstallmentAmountForPeriod()); - assertEquals(515.15, loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalPaidForPeriod()); - assertEquals(0.0, loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalOutstandingForPeriod()); - assertEquals(5.15, loanDetails.getRepaymentSchedule().getPeriods().get(3).getFeeChargesDue()); - assertEquals(5.15, loanDetails.getRepaymentSchedule().getPeriods().get(3).getFeeChargesPaid()); - assertEquals(10.0, loanDetails.getRepaymentSchedule().getPeriods().get(3).getPenaltyChargesDue()); - assertEquals(10.0, loanDetails.getRepaymentSchedule().getPeriods().get(3).getPenaltyChargesPaid()); - assertEquals(true, loanDetails.getRepaymentSchedule().getPeriods().get(3).getComplete()); - - // third period [2023-04-03 to 2023-04-03] down payment installment gets paid - assertEquals(3, loanDetails.getRepaymentSchedule().getPeriods().get(4).getPeriod()); - assertEquals(LocalDate.of(2023, 4, 3), loanDetails.getRepaymentSchedule().getPeriods().get(4).getFromDate()); - assertEquals(LocalDate.of(2023, 4, 3), loanDetails.getRepaymentSchedule().getPeriods().get(4).getDueDate()); - assertEquals(250.0, loanDetails.getRepaymentSchedule().getPeriods().get(4).getTotalInstallmentAmountForPeriod()); - assertEquals(250.0, loanDetails.getRepaymentSchedule().getPeriods().get(4).getTotalPaidForPeriod()); - assertEquals(true, loanDetails.getRepaymentSchedule().getPeriods().get(4).getComplete()); - - // fourth period [2023-04-03 to 2023-05-03] regular installment - assertEquals(4, loanDetails.getRepaymentSchedule().getPeriods().get(5).getPeriod()); - assertEquals(LocalDate.of(2023, 4, 3), loanDetails.getRepaymentSchedule().getPeriods().get(5).getFromDate()); - assertEquals(LocalDate.of(2023, 5, 3), loanDetails.getRepaymentSchedule().getPeriods().get(5).getDueDate()); - assertEquals(625.0, loanDetails.getRepaymentSchedule().getPeriods().get(5).getTotalInstallmentAmountForPeriod()); - assertEquals(0.0, loanDetails.getRepaymentSchedule().getPeriods().get(5).getTotalPaidForPeriod()); - assertEquals(false, loanDetails.getRepaymentSchedule().getPeriods().get(5).getComplete()); + // periods + assertEquals(7, loanDetails.getRepaymentSchedule().getPeriods().size()); + // disbursement period [0] + verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(0), LocalDate.of(2023, 3, 3), 200.0); + // down payment period [1] + verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(1), 1, 50.0, 50.0, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0, true, + LocalDate.of(2023, 3, 3), LocalDate.of(2023, 3, 3)); + // disbursement period [2] + verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(2), LocalDate.of(2023, 4, 3), 200.0); + // disbursement period [3] + verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(3), LocalDate.of(2023, 4, 3), 200.0); + // down payment period [4] + verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(4), 2, 100.0, 100.0, 100.0, 0.0, 0.0, 0.0, 0.0, 0.0, + true, LocalDate.of(2023, 4, 3), LocalDate.of(2023, 4, 3)); + // regular installment [5] + verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(5), 3, 225.0, 225.0, 225.0, 0.0, 0.0, 0.0, 0.0, 0.0, + true, LocalDate.of(2023, 3, 3), LocalDate.of(2023, 4, 3)); + // regular installment [6] + verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(6), 4, 225.0, 0.0, 0.0, 225.0, 0.0, 0.0, 0.0, 0.0, + false, LocalDate.of(2023, 4, 3), LocalDate.of(2023, 5, 3)); } finally { GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, Boolean.FALSE); @@ -637,6 +604,28 @@ public void loanAccountWithEnableDownPaymentAndDisableAutoRepaymentForDownPaymen } + private void verifyDisbursementPeriod(GetLoansLoanIdRepaymentPeriod period, LocalDate disbursementDate, double disbursedAmount) { + assertEquals(disbursementDate, period.getDueDate()); + assertEquals(disbursedAmount, period.getPrincipalLoanBalanceOutstanding()); + } + + private void verifyPeriodDetails(GetLoansLoanIdRepaymentPeriod period, Integer periodNumber, double periodAmount, + double periodAmountPaid, double principalPaid, double outstandingAmount, double feeDue, double feePaid, double penaltyDue, + double penaltyPaid, boolean isComplete, LocalDate periodFromDate, LocalDate periodDueDate) { + assertEquals(periodNumber, period.getPeriod()); + assertEquals(periodFromDate, period.getFromDate()); + assertEquals(periodDueDate, period.getDueDate()); + assertEquals(periodAmount, period.getTotalInstallmentAmountForPeriod()); + assertEquals(periodAmountPaid, period.getTotalPaidForPeriod()); + assertEquals(principalPaid, period.getPrincipalPaid()); + assertEquals(outstandingAmount, period.getTotalOutstandingForPeriod()); + assertEquals(feeDue, period.getFeeChargesDue()); + assertEquals(feePaid, period.getFeeChargesPaid()); + assertEquals(penaltyDue, period.getPenaltyChargesDue()); + assertEquals(penaltyPaid, period.getPenaltyChargesPaid()); + assertEquals(isComplete, period.getComplete()); + } + private Integer createLoanAccountMultipleRepaymentsDisbursement(final Integer clientID, final Long loanProductID, final String externalId, final String repaymentStartegy) {