This is an automated email from the ASF dual-hosted git repository.
adamsaghy pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git
The following commit(s) were added to refs/heads/develop by this push:
new 5c7724200 FINERACT-1958: downpayment periods for disbursements on same
day
5c7724200 is described below
commit 5c7724200505f60e5c93400820e1502bab8130c4
Author: Ruchi Dhamankar <[email protected]>
AuthorDate: Wed Nov 8 17:57:50 2023 +0530
FINERACT-1958: downpayment periods for disbursements on same day
---
.../AbstractCumulativeLoanScheduleGenerator.java | 14 +-
.../AbstractProgressiveLoanScheduleGenerator.java | 14 +-
...nWithOverlappingDownPaymentInstallmentTest.java | 271 ++++++++++++++++++++-
3 files changed, 280 insertions(+), 19 deletions(-)
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractCumulativeLoanScheduleGenerator.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractCumulativeLoanScheduleGenerator.java
index 236ecb7ed..fd3bf5bf6 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractCumulativeLoanScheduleGenerator.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractCumulativeLoanScheduleGenerator.java
@@ -1004,10 +1004,16 @@ public abstract class
AbstractCumulativeLoanScheduleGenerator implements LoanSch
BigDecimal downPaymentAmt = BigDecimal.ZERO;
if (loanApplicationTerms.isDownPaymentEnabled()) {
- final LoanScheduleModelDownPaymentPeriod downPaymentPeriod
= createDownPaymentPeriod(loanApplicationTerms,
- scheduleParams, disburseDetail.getKey(),
disburseDetail.getValue().getAmount());
- periods.add(downPaymentPeriod);
- downPaymentAmt = downPaymentPeriod.principalDue();
+ // get list of disbursements done on same day and create
down payment periods
+ List<DisbursementData> disbursementsOnSameDate =
loanApplicationTerms.getDisbursementDatas().stream()
+ .filter(disbursementData ->
DateUtils.isEqual(disbursementData.disbursementDate(), disburseDetail.getKey()))
+ .toList();
+ for (DisbursementData disbursementData :
disbursementsOnSameDate) {
+ final LoanScheduleModelDownPaymentPeriod
downPaymentPeriod = createDownPaymentPeriod(loanApplicationTerms,
+ scheduleParams,
disbursementData.disbursementDate(), disbursementData.getPrincipal());
+ periods.add(downPaymentPeriod);
+ downPaymentAmt =
downPaymentAmt.add(downPaymentPeriod.principalDue());
+ }
}
// updates actual outstanding balance with new
// disbursement detail
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractProgressiveLoanScheduleGenerator.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractProgressiveLoanScheduleGenerator.java
index d46b9aa1b..aa0645378 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractProgressiveLoanScheduleGenerator.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractProgressiveLoanScheduleGenerator.java
@@ -365,10 +365,16 @@ public abstract class
AbstractProgressiveLoanScheduleGenerator implements LoanSc
BigDecimal downPaymentAmt = BigDecimal.ZERO;
if (loanApplicationTerms.isDownPaymentEnabled()) {
- final LoanScheduleModelDownPaymentPeriod downPaymentPeriod
= createDownPaymentPeriod(loanApplicationTerms,
- scheduleParams, disburseDetail.getKey(),
disburseDetail.getValue().getAmount());
- periods.add(downPaymentPeriod);
- downPaymentAmt = downPaymentPeriod.principalDue();
+ // get list of disbursements done on same day and create
down payment periods
+ List<DisbursementData> disbursementsOnSameDate =
loanApplicationTerms.getDisbursementDatas().stream()
+ .filter(disbursementData ->
DateUtils.isEqual(disbursementData.disbursementDate(), disburseDetail.getKey()))
+ .toList();
+ for (DisbursementData disbursementData :
disbursementsOnSameDate) {
+ final LoanScheduleModelDownPaymentPeriod
downPaymentPeriod = createDownPaymentPeriod(loanApplicationTerms,
+ scheduleParams,
disbursementData.disbursementDate(), disbursementData.getPrincipal());
+ periods.add(downPaymentPeriod);
+ downPaymentAmt =
downPaymentAmt.add(downPaymentPeriod.principalDue());
+ }
}
// updates actual outstanding balance with new
// disbursement detail
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 4e560a925..9a9ec44a6 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
@@ -32,11 +32,16 @@ import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
+import java.util.List;
import java.util.UUID;
+import java.util.concurrent.atomic.AtomicInteger;
+import org.apache.fineract.client.models.AdvancedPaymentData;
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.PaymentAllocationOrder;
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsRequest;
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
@@ -50,6 +55,8 @@ import
org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuil
import
org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder;
import
org.apache.fineract.integrationtests.common.loans.LoanTestLifecycleExtension;
import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
+import
org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleType;
+import org.apache.fineract.portfolio.loanproduct.domain.PaymentAllocationType;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -549,7 +556,7 @@ public class
LoanAccountPaymentAllocationWithOverlappingDownPaymentInstallmentTe
assertNotNull(loanDetails.getRepaymentSchedule());
// periods
- assertEquals(7,
loanDetails.getRepaymentSchedule().getPeriods().size());
+ assertEquals(8,
loanDetails.getRepaymentSchedule().getPeriods().size());
// disbursement period [0]
verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(0),
LocalDate.of(2023, 3, 3), 200.0);
// down payment period [1]
@@ -560,13 +567,16 @@ public class
LoanAccountPaymentAllocationWithOverlappingDownPaymentInstallmentTe
// 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));
+
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(4), 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));
+ // down payment period [5]
+
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(5), 3,
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 [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, 3, 3), LocalDate.of(2023, 4, 3));
+ // regular installment [7]
+
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(7), 5,
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
@@ -579,7 +589,7 @@ public class
LoanAccountPaymentAllocationWithOverlappingDownPaymentInstallmentTe
assertNotNull(loanDetails.getRepaymentSchedule());
// periods
- assertEquals(7,
loanDetails.getRepaymentSchedule().getPeriods().size());
+ assertEquals(8,
loanDetails.getRepaymentSchedule().getPeriods().size());
// disbursement period [0]
verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(0),
LocalDate.of(2023, 3, 3), 200.0);
// down payment period [1]
@@ -590,13 +600,212 @@ public class
LoanAccountPaymentAllocationWithOverlappingDownPaymentInstallmentTe
// 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,
+
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(4), 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));
+ // down payment period [5]
+
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(5), 3,
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 [6]
+
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(6), 4,
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 [7]
+
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(7), 5,
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);
+ }
+
+ }
+
+ @Test
+ public void
loanAccountWithEnableDownPaymentWithAdvancedPaymentAllocationWithProgressiveScheduleGenerationMultipleDisbursementsOnSameDayTest()
{
+ try {
+
+ // Test with
+ // Enable Down Payment
+ // Disable Auto Repayment For Down Payment
+ // Overlapping down payment and regular installment with multiple
disbursements on same day
+ // Progressive Schedule generation with Advanced Payment Allocation
+
+ // 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();
+
+ String futureInstallmentAllocationRule = "NEXT_INSTALLMENT";
+ AdvancedPaymentData defaultAllocation =
createDefaultPaymentAllocation(futureInstallmentAllocationRule);
+
+ // Loan Product creation with down-payment configuration and
progressive schedule
+ final GetLoanProductsProductIdResponse
getLoanProductsProductResponse =
createLoanProductWithAdvancedPaymentStrategyAndProgressiveLoanSchedule(
+ loanTransactionHelper, enableDownPayment, "25",
enableAutoRepaymentForDownPayment, defaultAllocation);
+
+ 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, "advanced-payment-allocation-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());
+
+ // periods
+ assertEquals(8,
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,
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));
+ // down payment period [5]
+
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(5), 3,
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 [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, 3, 3), LocalDate.of(2023, 4, 3));
+ // regular installment [7]
+
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(7), 5,
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(225.0));
+
+ loanDetails =
loanTransactionHelper.getLoanDetails(loanId.longValue());
+
+ assertNotNull(loanDetails.getRepaymentSchedule());
+
+ // periods
+ assertEquals(8,
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,
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));
+ // down payment period [5]
+
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(5), 3,
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 [6]
+
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(6), 4,
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 [7]
+
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(7), 5,
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 {
@@ -657,6 +866,46 @@ public class
LoanAccountPaymentAllocationWithOverlappingDownPaymentInstallmentTe
return loanTransactionHelper.getLoanProduct(loanProductId);
}
+ private GetLoanProductsProductIdResponse
createLoanProductWithAdvancedPaymentStrategyAndProgressiveLoanSchedule(
+ LoanTransactionHelper loanTransactionHelper, Boolean
enableDownPayment, String disbursedAmountPercentageForDownPayment,
+ boolean enableAutoRepaymentForDownPayment, AdvancedPaymentData...
advancedPaymentData) {
+
+ final String loanProductJSON = new
LoanProductTestBuilder().withPrincipal("1000").withRepaymentTypeAsMonth()
+
.withRepaymentAfterEvery("1").withNumberOfRepayments("2").withRepaymentTypeAsMonth().withinterestRatePerPeriod("0")
+
.withInterestRateFrequencyTypeAsMonths().withAmortizationTypeAsEqualPrincipalPayment().withInterestTypeAsDecliningBalance()
+
.withInterestCalculationPeriodTypeAsRepaymentPeriod(true).withDaysInMonth("30").withDaysInYear("365")
+ .withMoratorium("0",
"0").withMultiDisburse().withDisallowExpectedDisbursements(true)
+ .withEnableDownPayment(enableDownPayment,
disbursedAmountPercentageForDownPayment, enableAutoRepaymentForDownPayment)
+
.addAdvancedPaymentAllocation(advancedPaymentData).withLoanScheduleType(LoanScheduleType.PROGRESSIVE).build(null);
+ final Integer loanProductId =
loanTransactionHelper.getLoanProductId(loanProductJSON);
+ return loanTransactionHelper.getLoanProduct(loanProductId);
+ }
+
+ private AdvancedPaymentData createDefaultPaymentAllocation(String
futureInstallmentAllocationRule) {
+ AdvancedPaymentData advancedPaymentData = new AdvancedPaymentData();
+ advancedPaymentData.setTransactionType("DEFAULT");
+
advancedPaymentData.setFutureInstallmentAllocationRule(futureInstallmentAllocationRule);
+
+ List<PaymentAllocationOrder> paymentAllocationOrders =
getPaymentAllocationOrder(PaymentAllocationType.PAST_DUE_PENALTY,
+ PaymentAllocationType.PAST_DUE_FEE,
PaymentAllocationType.PAST_DUE_PRINCIPAL,
PaymentAllocationType.PAST_DUE_INTEREST,
+ PaymentAllocationType.DUE_PENALTY,
PaymentAllocationType.DUE_FEE, PaymentAllocationType.DUE_PRINCIPAL,
+ PaymentAllocationType.DUE_INTEREST,
PaymentAllocationType.IN_ADVANCE_PENALTY, PaymentAllocationType.IN_ADVANCE_FEE,
+ PaymentAllocationType.IN_ADVANCE_PRINCIPAL,
PaymentAllocationType.IN_ADVANCE_INTEREST);
+
+ advancedPaymentData.setPaymentAllocationOrder(paymentAllocationOrders);
+ return advancedPaymentData;
+ }
+
+ private List<PaymentAllocationOrder>
getPaymentAllocationOrder(PaymentAllocationType... paymentAllocationTypes) {
+ AtomicInteger integer = new AtomicInteger(1);
+ return Arrays.stream(paymentAllocationTypes).map(pat -> {
+ PaymentAllocationOrder paymentAllocationOrder = new
PaymentAllocationOrder();
+ paymentAllocationOrder.setPaymentAllocationRule(pat.name());
+ paymentAllocationOrder.setOrder(integer.getAndIncrement());
+ return paymentAllocationOrder;
+ }).toList();
+ }
+
private void checkDownPaymentTransaction(final LocalDate transactionDate,
final Float principalPortion, final Float interestPortion,
final Float feePortion, final Float penaltyPortion, final Integer
loanID) {
ArrayList<HashMap> transactions = (ArrayList<HashMap>)
loanTransactionHelper.getLoanTransactions(this.requestSpec,