FINERACT-1958: downpayment periods for disbursements on same day

This commit is contained in:
Ruchi Dhamankar
2023-11-08 18:07:07 +01:00
committed by Adam Saghy
parent f4eee46a43
commit 5c77242005
3 changed files with 280 additions and 19 deletions
@@ -1004,10 +1004,16 @@ public abstract class AbstractCumulativeLoanScheduleGenerator implements LoanSch
BigDecimal downPaymentAmt = BigDecimal.ZERO; BigDecimal downPaymentAmt = BigDecimal.ZERO;
if (loanApplicationTerms.isDownPaymentEnabled()) { if (loanApplicationTerms.isDownPaymentEnabled()) {
final LoanScheduleModelDownPaymentPeriod downPaymentPeriod = createDownPaymentPeriod(loanApplicationTerms, // get list of disbursements done on same day and create down payment periods
scheduleParams, disburseDetail.getKey(), disburseDetail.getValue().getAmount()); List<DisbursementData> disbursementsOnSameDate = loanApplicationTerms.getDisbursementDatas().stream()
periods.add(downPaymentPeriod); .filter(disbursementData -> DateUtils.isEqual(disbursementData.disbursementDate(), disburseDetail.getKey()))
downPaymentAmt = downPaymentPeriod.principalDue(); .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 // updates actual outstanding balance with new
// disbursement detail // disbursement detail
@@ -365,10 +365,16 @@ public abstract class AbstractProgressiveLoanScheduleGenerator implements LoanSc
BigDecimal downPaymentAmt = BigDecimal.ZERO; BigDecimal downPaymentAmt = BigDecimal.ZERO;
if (loanApplicationTerms.isDownPaymentEnabled()) { if (loanApplicationTerms.isDownPaymentEnabled()) {
final LoanScheduleModelDownPaymentPeriod downPaymentPeriod = createDownPaymentPeriod(loanApplicationTerms, // get list of disbursements done on same day and create down payment periods
scheduleParams, disburseDetail.getKey(), disburseDetail.getValue().getAmount()); List<DisbursementData> disbursementsOnSameDate = loanApplicationTerms.getDisbursementDatas().stream()
periods.add(downPaymentPeriod); .filter(disbursementData -> DateUtils.isEqual(disbursementData.disbursementDate(), disburseDetail.getKey()))
downPaymentAmt = downPaymentPeriod.principalDue(); .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 // updates actual outstanding balance with new
// disbursement detail // disbursement detail
@@ -32,11 +32,16 @@ import java.time.LocalDate;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder; import java.time.format.DateTimeFormatterBuilder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.UUID; 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.GetLoanProductsProductIdResponse;
import org.apache.fineract.client.models.GetLoansLoanIdRepaymentPeriod; import org.apache.fineract.client.models.GetLoansLoanIdRepaymentPeriod;
import org.apache.fineract.client.models.GetLoansLoanIdResponse; 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.PostLoansLoanIdTransactionsRequest;
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse; import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType; 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.LoanProductTestBuilder;
import org.apache.fineract.integrationtests.common.loans.LoanTestLifecycleExtension; import org.apache.fineract.integrationtests.common.loans.LoanTestLifecycleExtension;
import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper; 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.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
@@ -549,7 +556,7 @@ public class LoanAccountPaymentAllocationWithOverlappingDownPaymentInstallmentTe
assertNotNull(loanDetails.getRepaymentSchedule()); assertNotNull(loanDetails.getRepaymentSchedule());
// periods // periods
assertEquals(7, loanDetails.getRepaymentSchedule().getPeriods().size()); assertEquals(8, loanDetails.getRepaymentSchedule().getPeriods().size());
// disbursement period [0] // disbursement period [0]
verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(0), LocalDate.of(2023, 3, 3), 200.0); verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(0), LocalDate.of(2023, 3, 3), 200.0);
// down payment period [1] // down payment period [1]
@@ -560,13 +567,16 @@ public class LoanAccountPaymentAllocationWithOverlappingDownPaymentInstallmentTe
// disbursement period [3] // disbursement period [3]
verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(3), LocalDate.of(2023, 4, 3), 200.0); verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(3), LocalDate.of(2023, 4, 3), 200.0);
// down payment period [4] // 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, verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(4), 2, 50.0, 50.0, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0, true,
true, LocalDate.of(2023, 4, 3), LocalDate.of(2023, 4, 3)); LocalDate.of(2023, 4, 3), LocalDate.of(2023, 4, 3));
// regular installment [5] // down payment period [5]
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(5), 3, 225.0, 0.0, 0.0, 225.0, 0.0, 0.0, 0.0, 0.0, verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(5), 3, 50.0, 50.0, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0, true,
false, LocalDate.of(2023, 3, 3), LocalDate.of(2023, 4, 3)); LocalDate.of(2023, 4, 3), LocalDate.of(2023, 4, 3));
// regular installment [6] // 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, 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)); 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 // 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()); assertNotNull(loanDetails.getRepaymentSchedule());
// periods // periods
assertEquals(7, loanDetails.getRepaymentSchedule().getPeriods().size()); assertEquals(8, loanDetails.getRepaymentSchedule().getPeriods().size());
// disbursement period [0] // disbursement period [0]
verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(0), LocalDate.of(2023, 3, 3), 200.0); verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(0), LocalDate.of(2023, 3, 3), 200.0);
// down payment period [1] // down payment period [1]
@@ -590,13 +600,212 @@ public class LoanAccountPaymentAllocationWithOverlappingDownPaymentInstallmentTe
// disbursement period [3] // disbursement period [3]
verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(3), LocalDate.of(2023, 4, 3), 200.0); verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(3), LocalDate.of(2023, 4, 3), 200.0);
// down payment period [4] // 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, verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(4), 2, 50.0, 50.0, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0, true,
true, LocalDate.of(2023, 4, 3), LocalDate.of(2023, 4, 3)); LocalDate.of(2023, 4, 3), LocalDate.of(2023, 4, 3));
// regular installment [5] // down payment period [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(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)); 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] // 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, 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)); false, LocalDate.of(2023, 4, 3), LocalDate.of(2023, 5, 3));
} finally { } finally {
@@ -657,6 +866,46 @@ public class LoanAccountPaymentAllocationWithOverlappingDownPaymentInstallmentTe
return loanTransactionHelper.getLoanProduct(loanProductId); 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, private void checkDownPaymentTransaction(final LocalDate transactionDate, final Float principalPortion, final Float interestPortion,
final Float feePortion, final Float penaltyPortion, final Integer loanID) { final Float feePortion, final Float penaltyPortion, final Integer loanID) {
ArrayList<HashMap> transactions = (ArrayList<HashMap>) loanTransactionHelper.getLoanTransactions(this.requestSpec, ArrayList<HashMap> transactions = (ArrayList<HashMap>) loanTransactionHelper.getLoanTransactions(this.requestSpec,