FINERACT-2162: Chargeback implementation for progressive interest recalculation enabled loan.

This commit is contained in:
Janos Meszaros
2025-02-14 15:16:59 +01:00
committed by Adam Saghy
parent 22f7972f60
commit cdbf0df571
23 changed files with 2303 additions and 176 deletions
@@ -65,6 +65,7 @@ import org.apache.fineract.client.models.GetLoansLoanIdRepaymentPeriod;
import org.apache.fineract.client.models.GetLoansLoanIdResponse;
import org.apache.fineract.client.models.GetLoansLoanIdStatus;
import org.apache.fineract.client.models.GetLoansLoanIdTransactions;
import org.apache.fineract.client.models.GetLoansLoanIdTransactionsTemplateResponse;
import org.apache.fineract.client.models.JournalEntryTransactionItem;
import org.apache.fineract.client.models.PaymentAllocationOrder;
import org.apache.fineract.client.models.PostChargesResponse;
@@ -268,6 +269,25 @@ public abstract class BaseLoanIntegrationTest extends IntegrationTest {
Assertions.assertTrue(actualValue);
}
protected GetLoansLoanIdTransactionsTemplateResponse getPrepayAmount(Long loanId, String date) {
return ok(fineractClient().loanTransactions.retrieveTransactionTemplate(loanId, "prepayLoan", DATETIME_PATTERN, date, "en"));
}
protected Long verifyPrepayAmountByRepayment(Long loanId, String date) {
GetLoansLoanIdTransactionsTemplateResponse prepayAmount = getPrepayAmount(loanId, date);
Double amountToPrepayLoan = prepayAmount.getAmount();
Long repaymentId = null;
if (amountToPrepayLoan != null && amountToPrepayLoan > 0) {
PostLoansLoanIdTransactionsResponse repayment = loanTransactionHelper.makeLoanRepayment(loanId, "repayment", date,
amountToPrepayLoan);
Assertions.assertNotNull(repayment);
Assertions.assertNotNull(repayment.getResourceId());
repaymentId = repayment.getResourceId();
}
verifyLoanStatus(loanId, LoanStatus.CLOSED_OBLIGATIONS_MET);
return repaymentId;
}
private String getNonByPassUserAuthKey(RequestSpecification requestSpec, ResponseSpecification responseSpec) {
// creates the user
UserHelper.getSimpleUserWithoutBypassPermission(requestSpec, responseSpec);
@@ -673,6 +693,7 @@ public abstract class BaseLoanIntegrationTest extends IntegrationTest {
}
protected void disburseLoan(Long loanId, BigDecimal amount, String date) {
log.info("Disbursing loan with id {} with amount {}", loanId, amount);
loanTransactionHelper.disburseLoan(loanId, new PostLoansLoanIdRequest().actualDisbursementDate(date).dateFormat(DATETIME_PATTERN)
.transactionAmount(amount).locale("en"));
}
@@ -1110,7 +1131,7 @@ public abstract class BaseLoanIntegrationTest extends IntegrationTest {
}
protected Installment unpaidInstallment(double principalAmount, double interestAmount, String dueDate) {
Double amount = principalAmount + interestAmount;
Double amount = BigDecimal.valueOf(principalAmount).add(BigDecimal.valueOf(interestAmount)).doubleValue();
return new Installment(principalAmount, interestAmount, null, null, amount, false, dueDate, null, null);
}
@@ -1161,6 +1182,10 @@ public abstract class BaseLoanIntegrationTest extends IntegrationTest {
assertEquals(actualMaturityDate, loanDetails.getTimeline().getActualMaturityDate());
}
protected void verifyLoanStatus(GetLoansLoanIdResponse loanDetails, LoanStatus loanStatus) {
assertEquals(loanStatus.getCode(), loanDetails.getStatus().getCode());
}
protected void verifyLoanStatus(long loanId, LoanStatus loanStatus) {
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanId);
@@ -30,12 +30,17 @@ import io.restassured.builder.ResponseSpecBuilder;
import io.restassured.http.ContentType;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Stream;
import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.client.models.AdvancedPaymentData;
import org.apache.fineract.client.models.CreditAllocationData;
import org.apache.fineract.client.models.CreditAllocationOrder;
import org.apache.fineract.client.models.GetDelinquencyBucketsResponse;
import org.apache.fineract.client.models.GetDelinquencyRangesResponse;
import org.apache.fineract.client.models.GetLoanProductsProductIdResponse;
@@ -45,6 +50,8 @@ import org.apache.fineract.client.models.GetLoansLoanIdResponse;
import org.apache.fineract.client.models.GetLoansLoanIdTransactions;
import org.apache.fineract.client.models.GetLoansLoanIdTransactionsTransactionIdResponse;
import org.apache.fineract.client.models.PaymentAllocationOrder;
import org.apache.fineract.client.models.PostClientsResponse;
import org.apache.fineract.client.models.PostLoanProductsResponse;
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
import org.apache.fineract.client.models.PutGlobalConfigurationsRequest;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
@@ -58,14 +65,20 @@ import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuil
import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder;
import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
import org.apache.fineract.integrationtests.common.products.DelinquencyBucketsHelper;
import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus;
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleType;
import org.apache.fineract.portfolio.loanproduct.domain.PaymentAllocationType;
import org.junit.experimental.runners.Enclosed;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Named;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.runner.RunWith;
@RunWith(Enclosed.class)
@Slf4j
public class LoanTransactionChargebackTest extends BaseLoanIntegrationTest {
@@ -80,6 +93,7 @@ public class LoanTransactionChargebackTest extends BaseLoanIntegrationTest {
private final String amountVal = "1000";
private LocalDate todaysDate;
private String operationDate;
private static Long clientId;
@BeforeEach
public void setup() {
@@ -93,6 +107,8 @@ public class LoanTransactionChargebackTest extends BaseLoanIntegrationTest {
this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec);
this.journalEntryHelper = new JournalEntryHelper(requestSpec, responseSpec);
this.accountHelper = new AccountHelper(requestSpec, responseSpec);
PostClientsResponse client = new ClientHelper(requestSpec, responseSpec).createClient(ClientHelper.defaultClientCreationRequest());
clientId = client.getResourceId();
this.todaysDate = Utils.getLocalDateOfTenant();
this.operationDate = Utils.dateFormatter.format(this.todaysDate);
@@ -592,6 +608,789 @@ public class LoanTransactionChargebackTest extends BaseLoanIntegrationTest {
}
}
@Nested
public class ProgressiveInterestBearingLoanWithInterestRecalculationTest {
Long applyApproveDisburseLoan(Long loanProductId) {
AtomicReference<Long> loanIdRef = new AtomicReference<>();
runAt("1 January 2024", () -> {
Long loanId = applyAndApproveProgressiveLoan(clientId, loanProductId, "1 January 2024", 100.0, 7.0, 6, null);
loanIdRef.set(loanId);
disburseLoan(loanId, BigDecimal.valueOf(100.0), "01 January 2024");
});
return loanIdRef.get();
}
List<CreditAllocationData> chargebackCreditAllocationOrders(List<String> allocationIds) {
List<CreditAllocationOrder> creditAllocationOrders = new ArrayList<>(allocationIds.size());
for (int i = 0; i < allocationIds.size(); i++) {
String allocationId = allocationIds.get(i);
creditAllocationOrders.add(new CreditAllocationOrder().order(i + 1).creditAllocationRule(allocationId));
}
return List.of(new CreditAllocationData().transactionType("CHARGEBACK").creditAllocationOrder(creditAllocationOrders));
}
@Nested
public class WithoutChargebackAllocation {
final PostLoanProductsResponse loanProductWithoutChargebackAllocation = loanProductHelper
.createLoanProduct(create4IProgressive().isInterestRecalculationEnabled(true).daysInYearType(DaysInYearType.DAYS_360)
.daysInMonthType(DaysInMonthType.DAYS_30));
@Test
public void testS1FullChargebackBeforeMaturityDate() {
final Long loanId = applyApproveDisburseLoan(loanProductWithoutChargebackAllocation.getResourceId());
runAt("1 February 2024", () -> {
loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "01 February 2024", 17.01);
});
runAt("1 March 2024", () -> {
Long repaymentId = loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "01 March 2024", 17.01).getResourceId();
verifyRepaymentSchedule(loanId, //
installment(100.0, null, "01 January 2024"), //
fullyRepaidInstallment(16.43, 0.58, "01 February 2024"), //
fullyRepaidInstallment(16.52, 0.49, "01 March 2024"), //
unpaidInstallment(16.62, 0.39, "01 April 2024"), //
unpaidInstallment(16.72, 0.29, "01 May 2024"), //
unpaidInstallment(16.81, 0.20, "01 June 2024"), //
unpaidInstallment(16.9, 0.10, "01 July 2024") //
); //
addChargebackForLoan(loanId, repaymentId, 17.01);
verifyRepaymentSchedule(loanId, //
installment(100.0, null, "01 January 2024"), //
fullyRepaidInstallment(16.43, 0.58, "01 February 2024"), //
fullyRepaidInstallment(16.52, 0.49, "01 March 2024"), //
unpaidInstallment(33.53, 0.49, "01 April 2024"), //
unpaidInstallment(16.72, 0.29, "01 May 2024"), //
unpaidInstallment(16.81, 0.20, "01 June 2024"), //
unpaidInstallment(17.0, 0.10, "01 July 2024") //
); //
Long prepayId = verifyPrepayAmountByRepayment(loanId, "1 March 2024");
loanTransactionHelper.reverseLoanTransaction(loanId, prepayId, "1 March 2024");
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanId);
verifyLoanStatus(loanDetails, LoanStatus.ACTIVE);
});
}
@Test
public void testS2AndS3PartialChargebackThenFullChargebackBeforeMaturityDate() {
final Long loanId = applyApproveDisburseLoan(loanProductWithoutChargebackAllocation.getResourceId());
AtomicReference<Long> repaymentFebruaryRef = new AtomicReference<>();
runAt("1 February 2024", () -> {
PostLoansLoanIdTransactionsResponse repayment = loanTransactionHelper.makeLoanRepayment(loanId, "Repayment",
"01 February 2024", 17.01);
repaymentFebruaryRef.set(repayment.getResourceId());
});
runAt("1 March 2024", () -> {
Long repaymentId = loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "01 March 2024", 17.01).getResourceId();
verifyRepaymentSchedule(loanId, //
installment(100.0, null, "01 January 2024"), //
fullyRepaidInstallment(16.43, 0.58, "01 February 2024"), //
fullyRepaidInstallment(16.52, 0.49, "01 March 2024"), //
unpaidInstallment(16.62, 0.39, "01 April 2024"), //
unpaidInstallment(16.72, 0.29, "01 May 2024"), //
unpaidInstallment(16.81, 0.20, "01 June 2024"), //
unpaidInstallment(16.9, 0.10, "01 July 2024") //
); //
addChargebackForLoan(loanId, repaymentFebruaryRef.get(), 15.0);
verifyRepaymentSchedule(loanId, //
installment(100.0, null, "01 January 2024"), //
fullyRepaidInstallment(16.43, 0.58, "01 February 2024"), //
fullyRepaidInstallment(16.52, 0.49, "01 March 2024"), //
unpaidInstallment(31.53, 0.48, "01 April 2024"), //
unpaidInstallment(16.72, 0.29, "01 May 2024"), //
unpaidInstallment(16.81, 0.20, "01 June 2024"), //
unpaidInstallment(16.99, 0.10, "01 July 2024") //
); //
addChargebackForLoan(loanId, repaymentId, 17.01);
verifyRepaymentSchedule(loanId, //
installment(100.0, null, "01 January 2024"), //
fullyRepaidInstallment(16.43, 0.58, "01 February 2024"), //
fullyRepaidInstallment(16.52, 0.49, "01 March 2024"), //
unpaidInstallment(48.44, 0.58, "01 April 2024"), //
unpaidInstallment(16.71, 0.30, "01 May 2024"), //
unpaidInstallment(16.81, 0.20, "01 June 2024"), //
unpaidInstallment(17.10, 0.10, "01 July 2024") //
); //
Long prepayId = verifyPrepayAmountByRepayment(loanId, "1 March 2024");
loanTransactionHelper.reverseLoanTransaction(loanId, prepayId, "1 March 2024");
});
}
@Test
public void testS4FullChargebackMiddleOfRepaymentPeriodBeforeMaturityDate() {
final Long loanId = applyApproveDisburseLoan(loanProductWithoutChargebackAllocation.getResourceId());
AtomicReference<Long> repaymentMarchId = new AtomicReference<>();
runAt("1 February 2024", () -> {
loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "01 February 2024", 17.01);
});
runAt("1 March 2024", () -> {
repaymentMarchId
.set(loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "01 March 2024", 17.01).getResourceId());
verifyRepaymentSchedule(loanId, //
installment(100.0, null, "01 January 2024"), //
fullyRepaidInstallment(16.43, 0.58, "01 February 2024"), //
fullyRepaidInstallment(16.52, 0.49, "01 March 2024"), //
unpaidInstallment(16.62, 0.39, "01 April 2024"), //
unpaidInstallment(16.72, 0.29, "01 May 2024"), //
unpaidInstallment(16.81, 0.20, "01 June 2024"), //
unpaidInstallment(16.9, 0.10, "01 July 2024") //
); //
});
runAt("15 March 2024", () -> {
addChargebackForLoan(loanId, repaymentMarchId.get(), 17.01);
verifyRepaymentSchedule(loanId, //
installment(100.0, null, "01 January 2024"), //
fullyRepaidInstallment(16.43, 0.58, "01 February 2024"), //
fullyRepaidInstallment(16.52, 0.49, "01 March 2024"), //
unpaidInstallment(33.57, 0.45, "01 April 2024"), //
unpaidInstallment(16.72, 0.29, "01 May 2024"), //
unpaidInstallment(16.81, 0.20, "01 June 2024"), //
unpaidInstallment(16.96, 0.10, "01 July 2024") //
); //
Long repaymentId = verifyPrepayAmountByRepayment(loanId, "15 March 2024");
loanTransactionHelper.reverseLoanTransaction(loanId, repaymentId, "15 March 2024");
});
}
@Test
public void testS7ChargebacksOnMaturityDate() {
final Long loanId = applyApproveDisburseLoan(loanProductWithoutChargebackAllocation.getResourceId());
runAt("1 February 2024", () -> {
loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "01 February 2024", 17.01);
});
runAt("1 March 2024", () -> {
loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "01 March 2024", 17.01);
});
runAt("1 April 2024", () -> {
loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "01 April 2024", 17.01);
});
runAt("1 May 2024", () -> {
loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "01 May 2024", 17.01);
});
AtomicReference<Long> repaymentJuneRef = new AtomicReference<>();
runAt("1 June 2024", () -> {
PostLoansLoanIdTransactionsResponse repayment = loanTransactionHelper.makeLoanRepayment(loanId, "Repayment",
"01 June 2024", 17.01);
repaymentJuneRef.set(repayment.getResourceId());
});
AtomicReference<Long> repaymentJulyRef = new AtomicReference<>();
runAt("1 July 2024", () -> {
PostLoansLoanIdTransactionsResponse repayment = loanTransactionHelper.makeLoanRepayment(loanId, "Repayment",
"01 July 2024", 17.00);
repaymentJulyRef.set(repayment.getResourceId());
verifyRepaymentSchedule(loanId, //
installment(100.0, null, "01 January 2024"), //
fullyRepaidInstallment(16.43, 0.58, "01 February 2024"), //
fullyRepaidInstallment(16.52, 0.49, "01 March 2024"), //
fullyRepaidInstallment(16.62, 0.39, "01 April 2024"), //
fullyRepaidInstallment(16.72, 0.29, "01 May 2024"), //
fullyRepaidInstallment(16.81, 0.20, "01 June 2024"), //
fullyRepaidInstallment(16.9, 0.10, "01 July 2024") //
); //
addChargebackForLoan(loanId, repaymentJulyRef.get(), 17.00);
verifyRepaymentSchedule(loanId, //
installment(100.0, null, "01 January 2024"), //
fullyRepaidInstallment(16.43, 0.58, "01 February 2024"), //
fullyRepaidInstallment(16.52, 0.49, "01 March 2024"), //
fullyRepaidInstallment(16.62, 0.39, "01 April 2024"), //
fullyRepaidInstallment(16.72, 0.29, "01 May 2024"), //
fullyRepaidInstallment(16.81, 0.20, "01 June 2024"), //
installment(33.9, 0.10, 17.0, false, "01 July 2024") //
); //
Long repaymentId = verifyPrepayAmountByRepayment(loanId, "01 July 2024");
loanTransactionHelper.reverseLoanTransaction(loanId, repaymentId, "01 July 2024");
});
}
@Test
public void testS5AndS6ChargebacksAfterMaturityDateVerifyNPlus1ThPeriod() {
final Long loanId = applyApproveDisburseLoan(loanProductWithoutChargebackAllocation.getResourceId());
runAt("1 February 2024", () -> {
loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "01 February 2024", 17.01);
});
runAt("1 March 2024", () -> {
loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "01 March 2024", 17.01);
});
runAt("1 April 2024", () -> {
loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "01 April 2024", 17.01);
});
runAt("1 May 2024", () -> {
loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "01 May 2024", 17.01);
});
AtomicReference<Long> repaymentJuneRef = new AtomicReference<>();
runAt("1 June 2024", () -> {
PostLoansLoanIdTransactionsResponse repayment = loanTransactionHelper.makeLoanRepayment(loanId, "Repayment",
"01 June 2024", 17.01);
repaymentJuneRef.set(repayment.getResourceId());
});
AtomicReference<Long> repaymentJulyRef = new AtomicReference<>();
runAt("1 July 2024", () -> {
PostLoansLoanIdTransactionsResponse repayment = loanTransactionHelper.makeLoanRepayment(loanId, "Repayment",
"01 July 2024", 17.00);
repaymentJulyRef.set(repayment.getResourceId());
verifyRepaymentSchedule(loanId, //
installment(100.0, null, "01 January 2024"), //
fullyRepaidInstallment(16.43, 0.58, "01 February 2024"), //
fullyRepaidInstallment(16.52, 0.49, "01 March 2024"), //
fullyRepaidInstallment(16.62, 0.39, "01 April 2024"), //
fullyRepaidInstallment(16.72, 0.29, "01 May 2024"), //
fullyRepaidInstallment(16.81, 0.20, "01 June 2024"), //
fullyRepaidInstallment(16.9, 0.10, "01 July 2024") //
); //
});
runAt("15 July 2024", () -> {
addChargebackForLoan(loanId, repaymentJuneRef.get(), 17.01);
verifyRepaymentSchedule(loanId, //
installment(100.0, null, "01 January 2024"), //
fullyRepaidInstallment(16.43, 0.58, "01 February 2024"), //
fullyRepaidInstallment(16.52, 0.49, "01 March 2024"), //
fullyRepaidInstallment(16.62, 0.39, "01 April 2024"), //
fullyRepaidInstallment(16.72, 0.29, "01 May 2024"), //
fullyRepaidInstallment(16.81, 0.20, "01 June 2024"), //
fullyRepaidInstallment(16.9, 0.10, "01 July 2024"), //
unpaidInstallment(17.01, 0.0, "15 July 2024") //
); //
});
runAt("30 July 2024", () -> {
addChargebackForLoan(loanId, repaymentJulyRef.get(), 17.00);
verifyRepaymentSchedule(loanId, //
installment(100.0, null, "01 January 2024"), //
fullyRepaidInstallment(16.43, 0.58, "01 February 2024"), //
fullyRepaidInstallment(16.52, 0.49, "01 March 2024"), //
fullyRepaidInstallment(16.62, 0.39, "01 April 2024"), //
fullyRepaidInstallment(16.72, 0.29, "01 May 2024"), //
fullyRepaidInstallment(16.81, 0.20, "01 June 2024"), //
fullyRepaidInstallment(16.9, 0.10, "01 July 2024"), //
unpaidInstallment(34.01, 0.0, "30 July 2024") //
); //
Long repaymentId = verifyPrepayAmountByRepayment(loanId, "30 July 2024");
loanTransactionHelper.reverseLoanTransaction(loanId, repaymentId, "30 July 2024");
});
}
}
@Nested
public class WithChargebackAllocationPrincipalInterestFeesPenalties {
final PostLoanProductsResponse loanProductWithChargebackAllocationPrincipalInterestFeesPenalties = loanProductHelper
.createLoanProduct(create4IProgressive().isInterestRecalculationEnabled(true).daysInYearType(DaysInYearType.DAYS_360)
.daysInMonthType(DaysInMonthType.DAYS_30)
.creditAllocation(chargebackCreditAllocationOrders(List.of("PRINCIPAL", "PENALTY", "FEE", "INTEREST"))));
@Test
public void testS1FullChargebackBeforeMaturityDate() {
final Long loanId = applyApproveDisburseLoan(
loanProductWithChargebackAllocationPrincipalInterestFeesPenalties.getResourceId());
runAt("1 February 2024", () -> {
loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "01 February 2024", 17.01);
});
runAt("1 March 2024", () -> {
Long repaymentId = loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "01 March 2024", 17.01).getResourceId();
verifyRepaymentSchedule(loanId, //
installment(100.0, null, "01 January 2024"), //
fullyRepaidInstallment(16.43, 0.58, "01 February 2024"), //
fullyRepaidInstallment(16.52, 0.49, "01 March 2024"), //
unpaidInstallment(16.62, 0.39, "01 April 2024"), //
unpaidInstallment(16.72, 0.29, "01 May 2024"), //
unpaidInstallment(16.81, 0.20, "01 June 2024"), //
unpaidInstallment(16.9, 0.10, "01 July 2024") //
); //
verifyTransactions(loanId,
new TransactionExt(100.0, "Disbursement", "01 January 2024", 100.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, false),
new TransactionExt(17.01, "Repayment", "01 February 2024", 83.57, 16.43, 0.58, 0.0, 0.0, 0.0, 0.0, false),
new TransactionExt(17.01, "Repayment", "01 March 2024", 67.05, 16.52, 0.49, 0.0, 0.0, 0.0, 0.0, false));
addChargebackForLoan(loanId, repaymentId, 17.01);
verifyRepaymentSchedule(loanId, //
installment(100.0, null, "01 January 2024"), //
fullyRepaidInstallment(16.43, 0.58, "01 February 2024"), //
fullyRepaidInstallment(16.52, 0.49, "01 March 2024"), //
unpaidInstallment(33.04, 0.98, "01 April 2024"), //
unpaidInstallment(16.72, 0.29, "01 May 2024"), //
unpaidInstallment(16.81, 0.20, "01 June 2024"), //
unpaidInstallment(17.0, 0.10, "01 July 2024") //
); //
verifyTransactions(loanId,
new TransactionExt(100.0, "Disbursement", "01 January 2024", 100.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, false),
new TransactionExt(17.01, "Repayment", "01 February 2024", 83.57, 16.43, 0.58, 0.0, 0.0, 0.0, 0.0, false),
new TransactionExt(17.01, "Repayment", "01 March 2024", 67.05, 16.52, 0.49, 0.0, 0.0, 0.0, 0.0, false),
new TransactionExt(17.01, "Chargeback", "01 March 2024", 83.57, 16.52, 0.49, 0.0, 0.0, 0.0, 0.0, false));
Long prepayId = verifyPrepayAmountByRepayment(loanId, "1 March 2024");
loanTransactionHelper.reverseLoanTransaction(loanId, prepayId, "1 March 2024");
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanId);
verifyLoanStatus(loanDetails, LoanStatus.ACTIVE);
});
}
@Test
public void testS2AndS3PartialChargebackThenFullChargebackBeforeMaturityDate() {
final Long loanId = applyApproveDisburseLoan(
loanProductWithChargebackAllocationPrincipalInterestFeesPenalties.getResourceId());
AtomicReference<Long> repaymentFebruaryRef = new AtomicReference<>();
runAt("1 February 2024", () -> {
PostLoansLoanIdTransactionsResponse repayment = loanTransactionHelper.makeLoanRepayment(loanId, "Repayment",
"01 February 2024", 17.01);
repaymentFebruaryRef.set(repayment.getResourceId());
});
runAt("1 March 2024", () -> {
runAt("1 March 2024", () -> {
Long repaymentMarchId = loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "01 March 2024", 17.01)
.getResourceId();
verifyRepaymentSchedule(loanId, //
installment(100.0, null, "01 January 2024"), //
fullyRepaidInstallment(16.43, 0.58, "01 February 2024"), //
fullyRepaidInstallment(16.52, 0.49, "01 March 2024"), //
unpaidInstallment(16.62, 0.39, "01 April 2024"), //
unpaidInstallment(16.72, 0.29, "01 May 2024"), //
unpaidInstallment(16.81, 0.20, "01 June 2024"), //
unpaidInstallment(16.9, 0.10, "01 July 2024") //
); //
verifyTransactions(loanId,
new TransactionExt(100.0, "Disbursement", "01 January 2024", 100.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, false),
new TransactionExt(17.01, "Repayment", "01 February 2024", 83.57, 16.43, 0.58, 0.0, 0.0, 0.0, 0.0, false),
new TransactionExt(17.01, "Repayment", "01 March 2024", 67.05, 16.52, 0.49, 0.0, 0.0, 0.0, 0.0, false));
addChargebackForLoan(loanId, repaymentFebruaryRef.get(), 15.0);
verifyTransactions(loanId,
new TransactionExt(100.0, "Disbursement", "01 January 2024", 100.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, false),
new TransactionExt(17.01, "Repayment", "01 February 2024", 83.57, 16.43, 0.58, 0.0, 0.0, 0.0, 0.0, false),
new TransactionExt(17.01, "Repayment", "01 March 2024", 67.05, 16.52, 0.49, 0.0, 0.0, 0.0, 0.0, false),
new TransactionExt(15.00, "Chargeback", "01 March 2024", 82.05, 15.0, 0.0, 0.0, 0.0, 0.0, 0.0, false));
verifyRepaymentSchedule(loanId, //
installment(100.0, null, "01 January 2024"), //
fullyRepaidInstallment(16.43, 0.58, "01 February 2024"), //
fullyRepaidInstallment(16.52, 0.49, "01 March 2024"), //
unpaidInstallment(31.53, 0.48, "01 April 2024"), //
unpaidInstallment(16.72, 0.29, "01 May 2024"), //
unpaidInstallment(16.81, 0.20, "01 June 2024"), //
unpaidInstallment(16.99, 0.10, "01 July 2024") //
); //
addChargebackForLoan(loanId, repaymentMarchId, 17.01);
verifyTransactions(loanId,
new TransactionExt(100.0, "Disbursement", "01 January 2024", 100.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, false),
new TransactionExt(17.01, "Repayment", "01 February 2024", 83.57, 16.43, 0.58, 0.0, 0.0, 0.0, 0.0, false),
new TransactionExt(17.01, "Repayment", "01 March 2024", 67.05, 16.52, 0.49, 0.0, 0.0, 0.0, 0.0, false),
new TransactionExt(15.00, "Chargeback", "01 March 2024", 82.05, 15.0, 0.0, 0.0, 0.0, 0.0, 0.0, false),
new TransactionExt(17.01, "Chargeback", "01 March 2024", 98.57, 16.52, 0.49, 0.0, 0.0, 0.0, 0.0, false));
verifyRepaymentSchedule(loanId, //
installment(100.0, null, "01 January 2024"), //
fullyRepaidInstallment(16.43, 0.58, "01 February 2024"), //
fullyRepaidInstallment(16.52, 0.49, "01 March 2024"), //
unpaidInstallment(47.96, 1.06, "01 April 2024"), //
unpaidInstallment(16.71, 0.30, "01 May 2024"), //
unpaidInstallment(16.81, 0.20, "01 June 2024"), //
unpaidInstallment(17.09, 0.10, "01 July 2024") //
); //
Long prepayId = verifyPrepayAmountByRepayment(loanId, "1 March 2024");
loanTransactionHelper.reverseLoanTransaction(loanId, prepayId, "1 March 2024");
});
});
}
@Test
public void testS4FullChargebackMiddleOfRepaymentPeriodBeforeMaturityDate() {
final Long loanId = applyApproveDisburseLoan(
loanProductWithChargebackAllocationPrincipalInterestFeesPenalties.getResourceId());
AtomicReference<Long> repaymentMarchId = new AtomicReference<>();
runAt("1 February 2024", () -> {
loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "01 February 2024", 17.01);
});
runAt("1 March 2024", () -> {
repaymentMarchId
.set(loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "01 March 2024", 17.01).getResourceId());
});
runAt("15 March 2024", () -> {
verifyRepaymentSchedule(loanId, //
installment(100.0, null, "01 January 2024"), //
fullyRepaidInstallment(16.43, 0.58, "01 February 2024"), //
fullyRepaidInstallment(16.52, 0.49, "01 March 2024"), //
unpaidInstallment(16.62, 0.39, "01 April 2024"), //
unpaidInstallment(16.72, 0.29, "01 May 2024"), //
unpaidInstallment(16.81, 0.20, "01 June 2024"), //
unpaidInstallment(16.9, 0.10, "01 July 2024") //
);
verifyTransactions(loanId,
new TransactionExt(100.0, "Disbursement", "01 January 2024", 100.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, false),
new TransactionExt(17.01, "Repayment", "01 February 2024", 83.57, 16.43, 0.58, 0.0, 0.0, 0.0, 0.0, false),
new TransactionExt(17.01, "Repayment", "01 March 2024", 67.05, 16.52, 0.49, 0.0, 0.0, 0.0, 0.0, false));
addChargebackForLoan(loanId, repaymentMarchId.get(), 17.01);
verifyRepaymentSchedule(loanId, //
installment(100.0, null, "01 January 2024"), //
fullyRepaidInstallment(16.43, 0.58, "01 February 2024"), //
fullyRepaidInstallment(16.52, 0.49, "01 March 2024"), //
unpaidInstallment(33.08, 0.94, "01 April 2024"), //
unpaidInstallment(16.72, 0.29, "01 May 2024"), //
unpaidInstallment(16.81, 0.20, "01 June 2024"), //
unpaidInstallment(16.96, 0.10, "01 July 2024") //
); //
verifyTransactions(loanId,
new TransactionExt(100.0, "Disbursement", "01 January 2024", 100.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, false),
new TransactionExt(17.01, "Repayment", "01 February 2024", 83.57, 16.43, 0.58, 0.0, 0.0, 0.0, 0.0, false),
new TransactionExt(17.01, "Repayment", "01 March 2024", 67.05, 16.52, 0.49, 0.0, 0.0, 0.0, 0.0, false),
new TransactionExt(17.01, "Chargeback", "15 March 2024", 83.57, 16.52, 0.49, 0.0, 0.0, 0.0, 0.0, false));
Long repaymentId = verifyPrepayAmountByRepayment(loanId, "15 March 2024");
loanTransactionHelper.reverseLoanTransaction(loanId, repaymentId, "15 March 2024");
});
}
@Test
public void testS5AndS6ChargebacksAfterMaturityDateVerifyNPlus1ThPeriod() {
final Long loanId = applyApproveDisburseLoan(
loanProductWithChargebackAllocationPrincipalInterestFeesPenalties.getResourceId());
runAt("1 February 2024", () -> {
loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "01 February 2024", 17.01);
});
runAt("1 March 2024", () -> {
loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "01 March 2024", 17.01);
});
runAt("1 April 2024", () -> {
loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "01 April 2024", 17.01);
});
runAt("1 May 2024", () -> {
loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "01 May 2024", 17.01);
});
AtomicReference<Long> repaymentJuneRef = new AtomicReference<>();
runAt("1 June 2024", () -> {
PostLoansLoanIdTransactionsResponse repayment = loanTransactionHelper.makeLoanRepayment(loanId, "Repayment",
"01 June 2024", 17.01);
repaymentJuneRef.set(repayment.getResourceId());
});
AtomicReference<Long> repaymentJulyRef = new AtomicReference<>();
runAt("1 July 2024", () -> {
PostLoansLoanIdTransactionsResponse repayment = loanTransactionHelper.makeLoanRepayment(loanId, "Repayment",
"01 July 2024", 17.00);
repaymentJulyRef.set(repayment.getResourceId());
verifyRepaymentSchedule(loanId, //
installment(100.0, null, "01 January 2024"), //
fullyRepaidInstallment(16.43, 0.58, "01 February 2024"), //
fullyRepaidInstallment(16.52, 0.49, "01 March 2024"), //
fullyRepaidInstallment(16.62, 0.39, "01 April 2024"), //
fullyRepaidInstallment(16.72, 0.29, "01 May 2024"), //
fullyRepaidInstallment(16.81, 0.20, "01 June 2024"), //
fullyRepaidInstallment(16.9, 0.10, "01 July 2024") //
); //
});
runAt("15 July 2024", () -> {
addChargebackForLoan(loanId, repaymentJuneRef.get(), 17.01);
verifyRepaymentSchedule(loanId, //
installment(100.0, null, "01 January 2024"), //
fullyRepaidInstallment(16.43, 0.58, "01 February 2024"), //
fullyRepaidInstallment(16.52, 0.49, "01 March 2024"), //
fullyRepaidInstallment(16.62, 0.39, "01 April 2024"), //
fullyRepaidInstallment(16.72, 0.29, "01 May 2024"), //
fullyRepaidInstallment(16.81, 0.20, "01 June 2024"), //
fullyRepaidInstallment(16.9, 0.10, "01 July 2024"), //
unpaidInstallment(16.81, 0.2, "15 July 2024") //
); //
});
runAt("30 July 2024", () -> {
addChargebackForLoan(loanId, repaymentJulyRef.get(), 17.00);
verifyRepaymentSchedule(loanId, //
installment(100.0, null, "01 January 2024"), //
fullyRepaidInstallment(16.43, 0.58, "01 February 2024"), //
fullyRepaidInstallment(16.52, 0.49, "01 March 2024"), //
fullyRepaidInstallment(16.62, 0.39, "01 April 2024"), //
fullyRepaidInstallment(16.72, 0.29, "01 May 2024"), //
fullyRepaidInstallment(16.81, 0.20, "01 June 2024"), //
fullyRepaidInstallment(16.9, 0.10, "01 July 2024"), //
unpaidInstallment(33.71, 0.3, "30 July 2024") //
); //
Long repaymentId = verifyPrepayAmountByRepayment(loanId, "30 July 2024");
loanTransactionHelper.reverseLoanTransaction(loanId, repaymentId, "30 July 2024");
});
}
}
@Nested
public class WithChargebackAllocationInterestFeesPenaltiesPrincipal {
final PostLoanProductsResponse loanProductWithChargebackAllocationInterestFeesPenaltiesPrincipal = loanProductHelper
.createLoanProduct(create4IProgressive().isInterestRecalculationEnabled(true).daysInYearType(DaysInYearType.DAYS_360)
.daysInMonthType(DaysInMonthType.DAYS_30)
.creditAllocation(chargebackCreditAllocationOrders(List.of("PENALTY", "FEE", "INTEREST", "PRINCIPAL"))));
@Test
public void testS1FullChargebackBeforeMaturityDate() {
final Long loanId = applyApproveDisburseLoan(
loanProductWithChargebackAllocationInterestFeesPenaltiesPrincipal.getResourceId());
runAt("1 February 2024", () -> {
loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "01 February 2024", 17.01);
});
runAt("1 March 2024", () -> {
Long repaymentId = loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "01 March 2024", 17.01).getResourceId();
verifyRepaymentSchedule(loanId, //
installment(100.0, null, "01 January 2024"), //
fullyRepaidInstallment(16.43, 0.58, "01 February 2024"), //
fullyRepaidInstallment(16.52, 0.49, "01 March 2024"), //
unpaidInstallment(16.62, 0.39, "01 April 2024"), //
unpaidInstallment(16.72, 0.29, "01 May 2024"), //
unpaidInstallment(16.81, 0.20, "01 June 2024"), //
unpaidInstallment(16.9, 0.10, "01 July 2024") //
); //
verifyTransactions(loanId,
new TransactionExt(100.0, "Disbursement", "01 January 2024", 100.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, false),
new TransactionExt(17.01, "Repayment", "01 February 2024", 83.57, 16.43, 0.58, 0.0, 0.0, 0.0, 0.0, false),
new TransactionExt(17.01, "Repayment", "01 March 2024", 67.05, 16.52, 0.49, 0.0, 0.0, 0.0, 0.0, false));
addChargebackForLoan(loanId, repaymentId, 17.01);
verifyRepaymentSchedule(loanId, //
installment(100.0, null, "01 January 2024"), //
fullyRepaidInstallment(16.43, 0.58, "01 February 2024"), //
fullyRepaidInstallment(16.52, 0.49, "01 March 2024"), //
unpaidInstallment(33.04, 0.98, "01 April 2024"), //
unpaidInstallment(16.72, 0.29, "01 May 2024"), //
unpaidInstallment(16.81, 0.20, "01 June 2024"), //
unpaidInstallment(17.0, 0.10, "01 July 2024") //
); //
verifyTransactions(loanId,
new TransactionExt(100.0, "Disbursement", "01 January 2024", 100.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, false),
new TransactionExt(17.01, "Repayment", "01 February 2024", 83.57, 16.43, 0.58, 0.0, 0.0, 0.0, 0.0, false),
new TransactionExt(17.01, "Repayment", "01 March 2024", 67.05, 16.52, 0.49, 0.0, 0.0, 0.0, 0.0, false),
new TransactionExt(17.01, "Chargeback", "01 March 2024", 83.57, 16.52, 0.49, 0.0, 0.0, 0.0, 0.0, false));
Long prepayId = verifyPrepayAmountByRepayment(loanId, "1 March 2024");
loanTransactionHelper.reverseLoanTransaction(loanId, prepayId, "1 March 2024");
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanId);
verifyLoanStatus(loanDetails, LoanStatus.ACTIVE);
});
}
@Test
public void testS2AndS3PartialChargebackThenFullChargebackBeforeMaturityDate() {
final Long loanId = applyApproveDisburseLoan(
loanProductWithChargebackAllocationInterestFeesPenaltiesPrincipal.getResourceId());
AtomicReference<Long> repaymentFebruaryRef = new AtomicReference<>();
runAt("1 February 2024", () -> {
PostLoansLoanIdTransactionsResponse repayment = loanTransactionHelper.makeLoanRepayment(loanId, "Repayment",
"01 February 2024", 17.01);
repaymentFebruaryRef.set(repayment.getResourceId());
});
runAt("1 March 2024", () -> {
Long repaymentMarchId = loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "01 March 2024", 17.01)
.getResourceId();
verifyRepaymentSchedule(loanId, //
installment(100.0, null, "01 January 2024"), //
fullyRepaidInstallment(16.43, 0.58, "01 February 2024"), //
fullyRepaidInstallment(16.52, 0.49, "01 March 2024"), //
unpaidInstallment(16.62, 0.39, "01 April 2024"), //
unpaidInstallment(16.72, 0.29, "01 May 2024"), //
unpaidInstallment(16.81, 0.20, "01 June 2024"), //
unpaidInstallment(16.9, 0.10, "01 July 2024") //
); //
verifyTransactions(loanId,
new TransactionExt(100.0, "Disbursement", "01 January 2024", 100.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, false),
new TransactionExt(17.01, "Repayment", "01 February 2024", 83.57, 16.43, 0.58, 0.0, 0.0, 0.0, 0.0, false),
new TransactionExt(17.01, "Repayment", "01 March 2024", 67.05, 16.52, 0.49, 0.0, 0.0, 0.0, 0.0, false));
addChargebackForLoan(loanId, repaymentFebruaryRef.get(), 15.0);
verifyTransactions(loanId,
new TransactionExt(100.0, "Disbursement", "01 January 2024", 100.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, false),
new TransactionExt(17.01, "Repayment", "01 February 2024", 83.57, 16.43, 0.58, 0.0, 0.0, 0.0, 0.0, false),
new TransactionExt(17.01, "Repayment", "01 March 2024", 67.05, 16.52, 0.49, 0.0, 0.0, 0.0, 0.0, false),
new TransactionExt(15.00, "Chargeback", "01 March 2024", 81.47, 14.42, 0.58, 0.0, 0.0, 0.0, 0.0, false));
verifyRepaymentSchedule(loanId, //
installment(100.0, null, "01 January 2024"), //
fullyRepaidInstallment(16.43, 0.58, "01 February 2024"), //
fullyRepaidInstallment(16.52, 0.49, "01 March 2024"), //
unpaidInstallment(30.95, 1.06, "01 April 2024"), //
unpaidInstallment(16.72, 0.29, "01 May 2024"), //
unpaidInstallment(16.81, 0.20, "01 June 2024"), //
unpaidInstallment(16.99, 0.10, "01 July 2024") //
); //
addChargebackForLoan(loanId, repaymentMarchId, 17.01);
verifyTransactions(loanId,
new TransactionExt(100.0, "Disbursement", "01 January 2024", 100.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, false),
new TransactionExt(17.01, "Repayment", "01 February 2024", 83.57, 16.43, 0.58, 0.0, 0.0, 0.0, 0.0, false),
new TransactionExt(17.01, "Repayment", "01 March 2024", 67.05, 16.52, 0.49, 0.0, 0.0, 0.0, 0.0, false),
new TransactionExt(15.00, "Chargeback", "01 March 2024", 81.47, 14.42, 0.58, 0.0, 0.0, 0.0, 0.0, false),
new TransactionExt(17.01, "Chargeback", "01 March 2024", 97.99, 16.52, 0.49, 0.0, 0.0, 0.0, 0.0, false));
verifyRepaymentSchedule(loanId, //
installment(100.0, null, "01 January 2024"), //
fullyRepaidInstallment(16.43, 0.58, "01 February 2024"), //
fullyRepaidInstallment(16.52, 0.49, "01 March 2024"), //
unpaidInstallment(47.38, 1.64, "01 April 2024"), //
unpaidInstallment(16.71, 0.30, "01 May 2024"), //
unpaidInstallment(16.81, 0.20, "01 June 2024"), //
unpaidInstallment(17.09, 0.10, "01 July 2024") //
); //
Long prepayId = verifyPrepayAmountByRepayment(loanId, "1 March 2024");
loanTransactionHelper.reverseLoanTransaction(loanId, prepayId, "1 March 2024");
});
}
@Test
public void testS4FullChargebackMiddleOfRepaymentPeriodBeforeMaturityDate() {
final Long loanId = applyApproveDisburseLoan(
loanProductWithChargebackAllocationInterestFeesPenaltiesPrincipal.getResourceId());
AtomicReference<Long> repaymentMarchId = new AtomicReference<>();
runAt("1 February 2024", () -> {
loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "01 February 2024", 17.01);
});
runAt("1 March 2024", () -> {
repaymentMarchId
.set(loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "01 March 2024", 17.01).getResourceId());
});
runAt("15 March 2024", () -> {
verifyRepaymentSchedule(loanId, //
installment(100.0, null, "01 January 2024"), //
fullyRepaidInstallment(16.43, 0.58, "01 February 2024"), //
fullyRepaidInstallment(16.52, 0.49, "01 March 2024"), //
unpaidInstallment(16.62, 0.39, "01 April 2024"), //
unpaidInstallment(16.72, 0.29, "01 May 2024"), //
unpaidInstallment(16.81, 0.20, "01 June 2024"), //
unpaidInstallment(16.9, 0.10, "01 July 2024") //
);
verifyTransactions(loanId,
new TransactionExt(100.0, "Disbursement", "01 January 2024", 100.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, false),
new TransactionExt(17.01, "Repayment", "01 February 2024", 83.57, 16.43, 0.58, 0.0, 0.0, 0.0, 0.0, false),
new TransactionExt(17.01, "Repayment", "01 March 2024", 67.05, 16.52, 0.49, 0.0, 0.0, 0.0, 0.0, false));
addChargebackForLoan(loanId, repaymentMarchId.get(), 17.01);
verifyRepaymentSchedule(loanId, //
installment(100.0, null, "01 January 2024"), //
fullyRepaidInstallment(16.43, 0.58, "01 February 2024"), //
fullyRepaidInstallment(16.52, 0.49, "01 March 2024"), //
unpaidInstallment(33.08, 0.94, "01 April 2024"), //
unpaidInstallment(16.72, 0.29, "01 May 2024"), //
unpaidInstallment(16.81, 0.20, "01 June 2024"), //
unpaidInstallment(16.96, 0.10, "01 July 2024") //
); //
verifyTransactions(loanId,
new TransactionExt(100.0, "Disbursement", "01 January 2024", 100.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, false),
new TransactionExt(17.01, "Repayment", "01 February 2024", 83.57, 16.43, 0.58, 0.0, 0.0, 0.0, 0.0, false),
new TransactionExt(17.01, "Repayment", "01 March 2024", 67.05, 16.52, 0.49, 0.0, 0.0, 0.0, 0.0, false),
new TransactionExt(17.01, "Chargeback", "15 March 2024", 83.57, 16.52, 0.49, 0.0, 0.0, 0.0, 0.0, false));
Long repaymentId = verifyPrepayAmountByRepayment(loanId, "15 March 2024");
loanTransactionHelper.reverseLoanTransaction(loanId, repaymentId, "15 March 2024");
});
}
@Test
public void testS5AndS6ChargebacksAfterMaturityDateVerifyNPlus1ThPeriod() {
final Long loanId = applyApproveDisburseLoan(
loanProductWithChargebackAllocationInterestFeesPenaltiesPrincipal.getResourceId());
runAt("1 February 2024", () -> {
loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "01 February 2024", 17.01);
});
runAt("1 March 2024", () -> {
loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "01 March 2024", 17.01);
});
runAt("1 April 2024", () -> {
loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "01 April 2024", 17.01);
});
runAt("1 May 2024", () -> {
loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "01 May 2024", 17.01);
});
AtomicReference<Long> repaymentJuneRef = new AtomicReference<>();
runAt("1 June 2024", () -> {
PostLoansLoanIdTransactionsResponse repayment = loanTransactionHelper.makeLoanRepayment(loanId, "Repayment",
"01 June 2024", 17.01);
repaymentJuneRef.set(repayment.getResourceId());
});
AtomicReference<Long> repaymentJulyRef = new AtomicReference<>();
runAt("1 July 2024", () -> {
PostLoansLoanIdTransactionsResponse repayment = loanTransactionHelper.makeLoanRepayment(loanId, "Repayment",
"01 July 2024", 17.00);
repaymentJulyRef.set(repayment.getResourceId());
verifyRepaymentSchedule(loanId, //
installment(100.0, null, "01 January 2024"), //
fullyRepaidInstallment(16.43, 0.58, "01 February 2024"), //
fullyRepaidInstallment(16.52, 0.49, "01 March 2024"), //
fullyRepaidInstallment(16.62, 0.39, "01 April 2024"), //
fullyRepaidInstallment(16.72, 0.29, "01 May 2024"), //
fullyRepaidInstallment(16.81, 0.20, "01 June 2024"), //
fullyRepaidInstallment(16.9, 0.10, "01 July 2024") //
); //
});
runAt("15 July 2024", () -> {
addChargebackForLoan(loanId, repaymentJuneRef.get(), 17.01);
// TODO verify TRANSACTIONS!!!!
verifyRepaymentSchedule(loanId, //
installment(100.0, null, "01 January 2024"), //
fullyRepaidInstallment(16.43, 0.58, "01 February 2024"), //
fullyRepaidInstallment(16.52, 0.49, "01 March 2024"), //
fullyRepaidInstallment(16.62, 0.39, "01 April 2024"), //
fullyRepaidInstallment(16.72, 0.29, "01 May 2024"), //
fullyRepaidInstallment(16.81, 0.20, "01 June 2024"), //
fullyRepaidInstallment(16.9, 0.10, "01 July 2024"), //
unpaidInstallment(16.81, 0.2, "15 July 2024") //
); //
});
runAt("30 July 2024", () -> {
addChargebackForLoan(loanId, repaymentJulyRef.get(), 17.00);
// TODO verify TRANSACTIONS!!!!
verifyRepaymentSchedule(loanId, //
installment(100.0, null, "01 January 2024"), //
fullyRepaidInstallment(16.43, 0.58, "01 February 2024"), //
fullyRepaidInstallment(16.52, 0.49, "01 March 2024"), //
fullyRepaidInstallment(16.62, 0.39, "01 April 2024"), //
fullyRepaidInstallment(16.72, 0.29, "01 May 2024"), //
fullyRepaidInstallment(16.81, 0.20, "01 June 2024"), //
fullyRepaidInstallment(16.9, 0.10, "01 July 2024"), //
unpaidInstallment(33.71, 0.3, "30 July 2024") //
); //
Long repaymentId = verifyPrepayAmountByRepayment(loanId, "30 July 2024");
loanTransactionHelper.reverseLoanTransaction(loanId, repaymentId, "30 July 2024");
});
}
@Test
public void testS7ChargebacksOnMaturityDate() {
final Long loanId = applyApproveDisburseLoan(
loanProductWithChargebackAllocationInterestFeesPenaltiesPrincipal.getResourceId());
runAt("1 February 2024", () -> {
loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "01 February 2024", 17.01);
});
runAt("1 March 2024", () -> {
loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "01 March 2024", 17.01);
});
runAt("1 April 2024", () -> {
loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "01 April 2024", 17.01);
});
runAt("1 May 2024", () -> {
loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "01 May 2024", 17.01);
});
AtomicReference<Long> repaymentJuneRef = new AtomicReference<>();
runAt("1 June 2024", () -> {
PostLoansLoanIdTransactionsResponse repayment = loanTransactionHelper.makeLoanRepayment(loanId, "Repayment",
"01 June 2024", 17.01);
repaymentJuneRef.set(repayment.getResourceId());
});
AtomicReference<Long> repaymentJulyRef = new AtomicReference<>();
runAt("1 July 2024", () -> {
PostLoansLoanIdTransactionsResponse repayment = loanTransactionHelper.makeLoanRepayment(loanId, "Repayment",
"01 July 2024", 17.00);
repaymentJulyRef.set(repayment.getResourceId());
verifyRepaymentSchedule(loanId, //
installment(100.0, null, "01 January 2024"), //
fullyRepaidInstallment(16.43, 0.58, "01 February 2024"), //
fullyRepaidInstallment(16.52, 0.49, "01 March 2024"), //
fullyRepaidInstallment(16.62, 0.39, "01 April 2024"), //
fullyRepaidInstallment(16.72, 0.29, "01 May 2024"), //
fullyRepaidInstallment(16.81, 0.20, "01 June 2024"), //
fullyRepaidInstallment(16.9, 0.10, "01 July 2024") //
); //
addChargebackForLoan(loanId, repaymentJulyRef.get(), 17.00);
verifyRepaymentSchedule(loanId, //
installment(100.0, null, "01 January 2024"), //
fullyRepaidInstallment(16.43, 0.58, "01 February 2024"), //
fullyRepaidInstallment(16.52, 0.49, "01 March 2024"), //
fullyRepaidInstallment(16.62, 0.39, "01 April 2024"), //
fullyRepaidInstallment(16.72, 0.29, "01 May 2024"), //
fullyRepaidInstallment(16.81, 0.20, "01 June 2024"), //
installment(33.8, 0.20, 17.0, false, "01 July 2024") //
); //
Long repaymentId = verifyPrepayAmountByRepayment(loanId, "01 July 2024");
loanTransactionHelper.reverseLoanTransaction(loanId, repaymentId, "01 July 2024");
});
runAt("2 July 2024", () -> {
executeInlineCOB(loanId);
});
}
}
}
private Integer createAccounts(final Integer daysToSubtract, final Integer numberOfRepayments, final boolean withJournalEntries,
LoanProductTestBuilder loanProductTestBuilder) {
// Delinquency Bucket