FINERACT-1958: Fix down-payment for loan reschedule and for interest bearing loans

This commit is contained in:
Adam Saghy
2023-12-08 10:10:02 +01:00
parent 5b8f15ca95
commit ae77d29be2
20 changed files with 717 additions and 221 deletions
@@ -124,7 +124,7 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 2023", "01 January 2023");
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -192,7 +192,7 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 2023", "01 January 2023");
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -259,7 +259,7 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 2023", "01 January 2023");
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -327,7 +327,7 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 2023", "01 January 2023");
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -414,7 +414,7 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 2023", "01 January 2023");
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -498,7 +498,7 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 2023", "01 January 2023");
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -580,7 +580,7 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 2023", "01 January 2023");
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -666,7 +666,7 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 2023", "01 January 2023");
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -735,7 +735,7 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 2023", "01 January 2023");
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -818,7 +818,7 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 2023", "01 January 2023");
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -878,7 +878,7 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 2023", "01 January 2023");
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -947,7 +947,7 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 2023", "01 January 2023");
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1030,7 +1030,7 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 2023", "01 January 2023");
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1115,7 +1115,7 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 2023", "01 January 2023");
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1197,7 +1197,7 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 2023", "01 January 2023");
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1253,7 +1253,7 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 2023", "01 January 2023");
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1309,7 +1309,7 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 2023", "01 January 2023");
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1365,7 +1365,7 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
runAt("20 February 2023", () -> {
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 2023", "01 January 2023");
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1458,7 +1458,7 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
runAt("20 February 2023", () -> {
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 2023", "01 January 2023");
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1572,7 +1572,7 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
runAt("20 February 2023", () -> {
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 2023", "01 January 2023");
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1645,7 +1645,7 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
Integer localLoanProductId = createLoanProduct("500", "15", "4", true, "25", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.HORIZONTAL, assetAccount, incomeAccount, expenseAccount, overpaymentAccount);
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), localLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 2023", "01 January 2023");
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1724,7 +1724,7 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
Integer localLoanProductId = createLoanProduct("500", "15", "4", true, "25", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.HORIZONTAL, assetAccount, incomeAccount, expenseAccount, overpaymentAccount);
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), localLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 2023", "01 January 2023");
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1815,7 +1815,7 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
Integer localLoanProductId = createLoanProduct("500", "15", "4", true, "25", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.HORIZONTAL, assetAccount, incomeAccount, expenseAccount, overpaymentAccount);
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), localLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 2023", "01 January 2023");
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1881,7 +1881,7 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
Integer localLoanProductId = createLoanProduct("500", "15", "4", true, "25", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.HORIZONTAL, assetAccount, incomeAccount, expenseAccount, overpaymentAccount);
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), localLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 2023", "01 January 2023");
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1960,7 +1960,7 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
Integer localLoanProductId = createLoanProduct("500", "15", "4", true, "25", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.VERTICAL, assetAccount, incomeAccount, expenseAccount, overpaymentAccount);
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), localLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 2023", "01 January 2023");
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -2065,15 +2065,16 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
assertNotNull(localLoanProductId);
CallFailedRuntimeException exception = assertThrows(CallFailedRuntimeException.class,
() -> applyForLoanApplication(client.getClientId(), localLoanProductId, BigDecimal.valueOf(500.0), 45, 15, 3, 0,
"01 January 2023", "01 January 2023", FineractStyleLoanRepaymentScheduleTransactionProcessor.STRATEGY_CODE,
LoanScheduleType.PROGRESSIVE.name(), LoanScheduleProcessingType.VERTICAL.name()));
() -> applyForLoanApplication(client.getClientId(), localLoanProductId, BigDecimal.valueOf(500.0), 45, 15, 3,
BigDecimal.ZERO, "01 January 2023", "01 January 2023",
FineractStyleLoanRepaymentScheduleTransactionProcessor.STRATEGY_CODE, LoanScheduleType.PROGRESSIVE.name(),
LoanScheduleProcessingType.VERTICAL.name()));
assertEquals(400, exception.getResponse().code());
assertTrue(exception.getMessage().contains("supported.only.with.advanced.payment.allocation.strategy"));
exception = assertThrows(CallFailedRuntimeException.class,
() -> applyForLoanApplication(client.getClientId(), localLoanProductId, BigDecimal.valueOf(500.0), 45, 15, 3, 0,
"01 January 2023", "01 January 2023",
() -> applyForLoanApplication(client.getClientId(), localLoanProductId, BigDecimal.valueOf(500.0), 45, 15, 3,
BigDecimal.ZERO, "01 January 2023", "01 January 2023",
AdvancedPaymentScheduleTransactionProcessor.ADVANCED_PAYMENT_ALLOCATION_STRATEGY,
LoanScheduleType.PROGRESSIVE.name(), LoanScheduleProcessingType.HORIZONTAL.name()));
assertEquals(400, exception.getResponse().code());
@@ -2099,7 +2100,7 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
assertNotNull(localLoanProductId);
PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), localLoanProductId, BigDecimal.valueOf(1000), 45,
15, 3, 0, "01 January 2023", "01 January 2023");
15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 16), 333.33, 0.0, 333.33, 0.0, 0.0);
@@ -2128,8 +2129,8 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 2, 15), 333.34, 0.0, 333.34, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
loanResponse = applyForLoanApplication(client.getClientId(), localLoanProductId, BigDecimal.valueOf(1000), 90, 15, 6, 0,
"01 January 2023", "01 January 2023");
loanResponse = applyForLoanApplication(client.getClientId(), localLoanProductId, BigDecimal.valueOf(1000), 90, 15, 6,
BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 16), 166.67, 0.0, 166.67, 0.0, 0.0);
@@ -2187,7 +2188,7 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
assertNotNull(localLoanProductId);
PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), localLoanProductId, BigDecimal.valueOf(1000), 45,
15, 3, 0, "01 January 2023", "01 January 2023");
15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 16), 333.33, 0.0, 333.33, 0.0, 0.0);
@@ -2216,8 +2217,8 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 2, 15), 333.34, 0.0, 333.34, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
loanResponse = applyForLoanApplication(client.getClientId(), localLoanProductId, BigDecimal.valueOf(1000), 90, 15, 6, 0,
"01 January 2023", "01 January 2023");
loanResponse = applyForLoanApplication(client.getClientId(), localLoanProductId, BigDecimal.valueOf(1000), 90, 15, 6,
BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 16), 166.67, 0.0, 166.67, 0.0, 0.0);
@@ -2275,7 +2276,7 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
assertNotNull(localLoanProductId);
PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), localLoanProductId, BigDecimal.valueOf(40.50),
45, 15, 3, 0, "01 January 2023", "01 January 2023");
45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 10.12, 0.0, 10.12, 0.0, 0.0);
@@ -2326,7 +2327,7 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
assertNotNull(localLoanProductId);
PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), localLoanProductId, BigDecimal.valueOf(40.50),
45, 15, 3, 0, "01 January 2023", "01 January 2023");
45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 10.12, 0.0, 10.12, 0.0, 0.0);
@@ -2380,7 +2381,7 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
Integer localLoanProductId = createLoanProduct("1000", "15", "3", true, "25", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.HORIZONTAL, assetAccount, incomeAccount, expenseAccount, overpaymentAccount);
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), localLoanProductId,
BigDecimal.valueOf(1000.0), 45, 15, 3, 0, "01 September 2023", "01 September 2023");
BigDecimal.valueOf(1000.0), 45, 15, 3, BigDecimal.ZERO, "01 September 2023", "01 September 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
@@ -2486,7 +2487,7 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
Integer localLoanProductId = createLoanProduct("1000", "15", "3", true, "25", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.VERTICAL, assetAccount, incomeAccount, expenseAccount, overpaymentAccount);
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), localLoanProductId,
BigDecimal.valueOf(1000.0), 45, 15, 3, 0, "01 September 2023", "01 September 2023");
BigDecimal.valueOf(1000.0), 45, 15, 3, BigDecimal.ZERO, "01 September 2023", "01 September 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
@@ -2591,7 +2592,7 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
Integer localLoanProductId = createLoanProduct("1000", "15", "3", true, "25", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.HORIZONTAL, assetAccount, incomeAccount, expenseAccount, overpaymentAccount);
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), localLoanProductId,
BigDecimal.valueOf(1000.0), 45, 15, 3, 0, "01 September 2023", "01 September 2023");
BigDecimal.valueOf(1000.0), 45, 15, 3, BigDecimal.ZERO, "01 September 2023", "01 September 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
@@ -2696,7 +2697,7 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
Integer localLoanProductId = createLoanProduct("1000", "15", "3", true, "25", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.VERTICAL, assetAccount, incomeAccount, expenseAccount, overpaymentAccount);
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), localLoanProductId,
BigDecimal.valueOf(1000.0), 45, 15, 3, 0, "01 September 2023", "01 September 2023");
BigDecimal.valueOf(1000.0), 45, 15, 3, BigDecimal.ZERO, "01 September 2023", "01 September 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
@@ -2795,7 +2796,7 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
Integer localLoanProductId = createLoanProduct("1000", "15", "3", true, "25", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.HORIZONTAL, assetAccount, incomeAccount, expenseAccount, overpaymentAccount);
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), localLoanProductId,
BigDecimal.valueOf(1000.0), 45, 15, 3, 0, "01 January 2023", "01 January 2023");
BigDecimal.valueOf(1000.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
@@ -2881,7 +2882,7 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
Integer localLoanProductId = createLoanProduct("1000", "15", "3", true, "25", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.HORIZONTAL, assetAccount, incomeAccount, expenseAccount, overpaymentAccount);
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), localLoanProductId,
BigDecimal.valueOf(1000.0), 45, 15, 3, 0, "01 January 2023", "01 January 2023");
BigDecimal.valueOf(1000.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
@@ -2970,7 +2971,7 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
Integer localLoanProductId = createLoanProduct("1000", "15", "3", true, "25", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.HORIZONTAL, assetAccount, incomeAccount, expenseAccount, overpaymentAccount);
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), localLoanProductId,
BigDecimal.valueOf(1000.0), 45, 15, 3, 0, "01 January 2023", "01 January 2023");
BigDecimal.valueOf(1000.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
@@ -3205,7 +3206,7 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
}
private static PostLoansResponse applyForLoanApplication(final Long clientId, final Integer loanProductId, final BigDecimal principal,
final int loanTermFrequency, final int repaymentAfterEvery, final int numberOfRepayments, final int interestRate,
final int loanTermFrequency, final int repaymentAfterEvery, final int numberOfRepayments, final BigDecimal interestRate,
final String expectedDisbursementDate, final String submittedOnDate, String transactionProcessorCode, String loanScheduleType,
String loanScheduleProcessingType) {
LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
@@ -3220,7 +3221,7 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
}
private static PostLoansResponse applyForLoanApplication(final Long clientId, final Integer loanProductId, final BigDecimal principal,
final int loanTermFrequency, final int repaymentAfterEvery, final int numberOfRepayments, final int interestRate,
final int loanTermFrequency, final int repaymentAfterEvery, final int numberOfRepayments, final BigDecimal interestRate,
final String expectedDisbursementDate, final String submittedOnDate) {
LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
return applyForLoanApplication(clientId, loanProductId, principal, loanTermFrequency, repaymentAfterEvery, numberOfRepayments,
@@ -128,14 +128,14 @@ public abstract class BaseLoanIntegrationTest {
.useBorrowerCycle(false)//
.minPrincipal(100.0)//
.principal(1000.0)//
.maxPrincipal(10000.0)//
.maxPrincipal(100000.0)//
.minNumberOfRepayments(1)//
.numberOfRepayments(1)//
.maxNumberOfRepayments(30)//
.isLinkedToFloatingInterestRates(false)//
.minInterestRatePerPeriod((double) 0)//
.interestRatePerPeriod((double) 0)//
.maxInterestRatePerPeriod((double) 0)//
.maxInterestRatePerPeriod((double) 100)//
.interestRateFrequencyType(2)//
.repaymentEvery(30)//
.repaymentFrequencyType(0L)//
@@ -412,8 +412,8 @@ public abstract class BaseLoanIntegrationTest {
PostLoansRequest postLoansRequest = new PostLoansRequest().clientId(clientId).productId(loanProductId)
.expectedDisbursementDate(loanDisbursementDate).dateFormat(DATETIME_PATTERN)
.transactionProcessingStrategyCode(DUE_PENALTY_INTEREST_PRINCIPAL_FEE_IN_ADVANCE_PENALTY_INTEREST_PRINCIPAL_FEE_STRATEGY)
.locale("en").submittedOnDate(loanDisbursementDate).amortizationType(1).interestRatePerPeriod(0)
.interestCalculationPeriodType(1).interestType(0).repaymentFrequencyType(0).repaymentEvery(30).repaymentFrequencyType(0)
.locale("en").submittedOnDate(loanDisbursementDate).amortizationType(1).interestRatePerPeriod(BigDecimal.ZERO)
.interestCalculationPeriodType(1).interestType(0).repaymentEvery(30).repaymentFrequencyType(0)
.numberOfRepayments(numberOfRepayments).loanTermFrequency(numberOfRepayments * 30).loanTermFrequencyType(0)
.maxOutstandingLoanBalance(BigDecimal.valueOf(amount)).principal(BigDecimal.valueOf(amount)).loanType("individual");
if (customizer != null) {
@@ -422,9 +422,9 @@ public abstract class BaseLoanIntegrationTest {
return postLoansRequest;
}
protected PostLoansLoanIdRequest approveLoanRequest(Double amount) {
protected PostLoansLoanIdRequest approveLoanRequest(Double amount, String approvalDate) {
return new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(amount)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("01 January 2023").locale("en");
.approvedOnDate(approvalDate).locale("en");
}
protected Long applyAndApproveLoan(Long clientId, Long loanProductId, String loanDisbursementDate, Double amount,
@@ -438,7 +438,7 @@ public abstract class BaseLoanIntegrationTest {
.applyLoan(applyLoanRequest(clientId, loanProductId, loanDisbursementDate, amount, numberOfRepayments, customizer));
PostLoansLoanIdResponse approvedLoanResult = loanTransactionHelper.approveLoan(postLoansResponse.getResourceId(),
approveLoanRequest(amount));
approveLoanRequest(amount, loanDisbursementDate));
return approvedLoanResult.getLoanId();
}
@@ -8041,9 +8041,9 @@ public class ClientLoanIntegrationTest {
return LOAN_TRANSACTION_HELPER.applyLoan(new PostLoansRequest().clientId(clientId.longValue()).productId(loanProductId)
.expectedDisbursementDate(loanDisbursementDate).dateFormat(DATETIME_PATTERN)
.transactionProcessingStrategyCode(repaymentStrategyCode).locale("en").submittedOnDate(loanDisbursementDate)
.amortizationType(1).interestRatePerPeriod(0).interestCalculationPeriodType(1).interestType(0).repaymentFrequencyType(0)
.repaymentEvery(30).repaymentFrequencyType(0).numberOfRepayments(1).loanTermFrequency(30).loanTermFrequencyType(0)
.principal(BigDecimal.valueOf(1000.0)).loanType("individual"));
.amortizationType(1).interestRatePerPeriod(BigDecimal.ZERO).interestCalculationPeriodType(1).interestType(0)
.repaymentFrequencyType(0).repaymentEvery(30).repaymentFrequencyType(0).numberOfRepayments(1).loanTermFrequency(30)
.loanTermFrequencyType(0).principal(BigDecimal.valueOf(1000.0)).loanType("individual"));
}
private PostLoanProductsRequest createOnePeriod30DaysLongNoInterestPeriodicAccrualProduct() {
@@ -935,10 +935,11 @@ public class ExternalIdSupportIntegrationTest extends IntegrationTest {
"modify",
new PutLoansLoanIdRequest().submittedOnDate("31 August 2022").dateFormat("dd MMMM yyyy").locale("en")
.loanType("individual").productId(loanProductID.longValue()).clientId(client.getClientId()).interestType(0)
.interestCalculationPeriodType(1).interestRatePerPeriod(0).isEqualAmortization(false).loanTermFrequency(30)
.loanTermFrequencyType(0).maxOutstandingLoanBalance(10000L).numberOfRepayments(1).principal(10000L)
.repaymentEvery(30).repaymentFrequencyType(0).transactionProcessingStrategyCode("mifos-standard-strategy")
.expectedDisbursementDate("2 September 2022").amortizationType(1));
.interestCalculationPeriodType(1).interestRatePerPeriod(BigDecimal.ZERO).isEqualAmortization(false)
.loanTermFrequency(30).loanTermFrequencyType(0).maxOutstandingLoanBalance(10000L).numberOfRepayments(1)
.principal(10000L).repaymentEvery(30).repaymentFrequencyType(0)
.transactionProcessingStrategyCode("mifos-standard-strategy").expectedDisbursementDate("2 September 2022")
.amortizationType(1));
assertEquals(loanExternalIdStr2, modifyLoanApplicationResult.getResourceExternalId());
DeleteLoansLoanIdResponse deleteLoanApplicationResult = this.loanTransactionHelper.deleteLoanApplication(loanExternalIdStr2);
@@ -163,8 +163,8 @@ public class LoanChargePaymentWithAdvancedPaymentAllocationTest {
savingsAccountHelper.depositToSavingsAccount(savingsId, "10000", startDate, CommonConstants.RESPONSE_RESOURCE_ID);
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId, 1000L, 45, 15, 3, 0,
"01 January 2023", "01 January 2023");
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId, 1000L, 45, 15, 3,
BigDecimal.ZERO, "01 January 2023", "01 January 2023");
int loanId = loanResponse.getLoanId().intValue();
@@ -266,7 +266,7 @@ public class LoanChargePaymentWithAdvancedPaymentAllocationTest {
}
private static PostLoansResponse applyForLoanApplication(final Long clientId, final Integer loanProductId, final Long principal,
final int loanTermFrequency, final int repaymentAfterEvery, final int numberOfRepayments, final int interestRate,
final int loanTermFrequency, final int repaymentAfterEvery, final int numberOfRepayments, final BigDecimal interestRate,
final String expectedDisbursementDate, final String submittedOnDate) {
log.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
return loanTransactionHelper.applyLoan(new PostLoansRequest().clientId(clientId).productId(loanProductId.longValue())
@@ -71,7 +71,7 @@ public class LoanInstallmentMultiplesOfTest extends BaseLoanIntegrationTest {
PostLoansResponse postLoansResponse = loanTransactionHelper.applyLoan(applicationRequest);
PostLoansLoanIdResponse approvedLoanResult = loanTransactionHelper.approveLoan(postLoansResponse.getResourceId(),
approveLoanRequest(amount));
approveLoanRequest(amount, "01 January 2023"));
Long loanId = approvedLoanResult.getLoanId();
@@ -130,12 +130,12 @@ public class LoanInstallmentMultiplesOfTest extends BaseLoanIntegrationTest {
.interestType(interestType)//
.amortizationType(amortizationType)//
.interestCalculationPeriodType(SAME_AS_REPAYMENT_PERIOD)//
.interestRatePerPeriod(12);
.interestRatePerPeriod(BigDecimal.valueOf(12));
PostLoansResponse postLoansResponse = loanTransactionHelper.applyLoan(applicationRequest);
PostLoansLoanIdResponse approvedLoanResult = loanTransactionHelper.approveLoan(postLoansResponse.getResourceId(),
approveLoanRequest(amount));
approveLoanRequest(amount, "01 January 2023"));
Long loanId = approvedLoanResult.getLoanId();
@@ -193,12 +193,12 @@ public class LoanInstallmentMultiplesOfTest extends BaseLoanIntegrationTest {
.interestType(interestType)//
.amortizationType(amortizationType)//
.interestCalculationPeriodType(SAME_AS_REPAYMENT_PERIOD)//
.interestRatePerPeriod(12);
.interestRatePerPeriod(BigDecimal.valueOf(12));
PostLoansResponse postLoansResponse = loanTransactionHelper.applyLoan(applicationRequest);
PostLoansLoanIdResponse approvedLoanResult = loanTransactionHelper.approveLoan(postLoansResponse.getResourceId(),
approveLoanRequest(amount));
approveLoanRequest(amount, "01 January 2023"));
Long loanId = approvedLoanResult.getLoanId();
@@ -36,13 +36,15 @@ import org.junit.jupiter.api.extension.ExtendWith;
@ExtendWith(LoanTestLifecycleExtension.class)
public class LoanRescheduleTestWithDownpayment extends BaseLoanIntegrationTest {
public static final BigDecimal DOWN_PAYMENT_PERCENTAGE = new BigDecimal(25);
public static final BigDecimal DOWN_PAYMENT_PERCENTAGE_20 = new BigDecimal(20);
public static final BigDecimal DOWN_PAYMENT_PERCENTAGE_25 = new BigDecimal(25);
public static final BigDecimal DOWN_PAYMENT_PERCENTAGE_33 = new BigDecimal(33);
private final LoanRescheduleRequestHelper loanRescheduleRequestHelper = new LoanRescheduleRequestHelper(this.requestSpec,
this.responseSpec);
@Test
public void testRescheduleWithDownpayment() {
public void testRescheduleWithDownPayment() {
runAt("01 January 2023", () -> {
// Create Client
Long clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
@@ -105,6 +107,342 @@ public class LoanRescheduleTestWithDownpayment extends BaseLoanIntegrationTest {
});
}
@Test
public void testRescheduleAddExtraInstallmentsWithDownPayment() {
runAt("01 November 2023", () -> {
// Create Client
Long clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
// Create Loan Product
Long loanProductId = createLoanProductWith33PctDownPayment(true, true);
// Apply and Approve Loan
Long loanId = applyAndApproveLoan(clientId, loanProductId, "02 October 2023", 1000.0, 3);
// Verify Repayment Schedule
verifyRepaymentSchedule(loanId, //
installment(1000.0, null, "02 October 2023"), //
installment(330.0, false, "02 October 2023"), //
installment(223.33, false, "01 November 2023"), //
installment(223.33, false, "01 December 2023"), //
installment(223.34, false, "31 December 2023") //
);
// 1st Disburse Loan
disburseLoan(loanId, BigDecimal.valueOf(1000.00), "02 October 2023");
// verify transactions
verifyTransactions(loanId, //
transaction(330.0, "Down Payment", "02 October 2023"), //
transaction(1000.0, "Disbursement", "02 October 2023") //
);
// Verify Repayment Schedule
verifyRepaymentSchedule(loanId, //
installment(1000.0, null, "02 October 2023"), //
installment(330.0, true, "02 October 2023"), //
installment(223.33, false, "01 November 2023"), //
installment(223.33, false, "01 December 2023"), //
installment(223.34, false, "31 December 2023") //
);
String requestJSON = new LoanRescheduleRequestTestBuilder().updateGraceOnInterest(null).updateGraceOnPrincipal(null)
.updateExtraTerms("2").updateNewInterestRate(null).updateRescheduleFromDate("01 November 2023")
.updateAdjustedDueDate(null).updateSubmittedOnDate("01 November 2023").updateRescheduleReasonId("1")
.build(loanId.toString());
Integer loanRescheduleRequest = loanRescheduleRequestHelper.createLoanRescheduleRequest(requestJSON);
requestJSON = new LoanRescheduleRequestTestBuilder().updateSubmittedOnDate("01 November 2023")
.getApproveLoanRescheduleRequestJSON();
Integer approveLoanRescheduleRequest = loanRescheduleRequestHelper.approveLoanRescheduleRequest(loanRescheduleRequest,
requestJSON);
// Verify Repayment Schedule
verifyRepaymentSchedule(loanId, //
installment(1000.0, null, "02 October 2023"), //
installment(330.0, true, "02 October 2023"), //
installment(134.0, false, "01 November 2023"), //
installment(134.0, false, "01 December 2023"), //
installment(134.0, false, "31 December 2023"), //
installment(134.0, false, "30 January 2024"), //
installment(134.0, false, "29 February 2024") //
);
});
}
@Test
public void testRescheduleAddExtraInstallmentsMultipleDisbursementWithDownPayment() {
runAt("31 December 2023", () -> {
// Create Client
Long clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
// Create Loan Product
Long loanProductId = createLoanProductWith33PctDownPayment(true, true);
// Apply and Approve Loan
Long loanId = applyAndApproveLoan(clientId, loanProductId, "02 October 2023", 1000.0, 3);
// Verify Repayment Schedule
verifyRepaymentSchedule(loanId, //
installment(1000.0, null, "02 October 2023"), //
installment(330.0, false, "02 October 2023"), //
installment(223.33, false, "01 November 2023"), //
installment(223.33, false, "01 December 2023"), //
installment(223.34, false, "31 December 2023") //
);
// 1st Disburse Loan
disburseLoan(loanId, BigDecimal.valueOf(1000.00), "02 October 2023");
// verify transactions
verifyTransactions(loanId, //
transaction(330.0, "Down Payment", "02 October 2023"), //
transaction(1000.0, "Disbursement", "02 October 2023") //
);
// Verify Repayment Schedule
verifyRepaymentSchedule(loanId, //
installment(1000.0, null, "02 October 2023"), //
installment(330.0, true, "02 October 2023"), //
installment(223.33, false, "01 November 2023"), //
installment(223.33, false, "01 December 2023"), //
installment(223.34, false, "31 December 2023") //
);
// 2nd Disburse Loan
disburseLoan(loanId, BigDecimal.valueOf(200.00), "02 December 2023");
// verify transactions
verifyTransactions(loanId, //
transaction(330.0, "Down Payment", "02 October 2023"), //
transaction(1000.0, "Disbursement", "02 October 2023"), //
transaction(200.0, "Disbursement", "02 December 2023"), //
transaction(66.0, "Down Payment", "02 December 2023") //
);
// Verify Repayment Schedule
verifyRepaymentSchedule(loanId, //
installment(1000.0, null, "02 October 2023"), //
installment(330.0, true, "02 October 2023"), //
installment(268.0, false, "01 November 2023"), //
installment(268.0, false, "01 December 2023"), //
installment(200.0, null, "02 December 2023"), //
installment(66.0, false, "02 December 2023"), //
installment(268.0, false, "31 December 2023") //
);
String requestJSON = new LoanRescheduleRequestTestBuilder().updateGraceOnInterest(null).updateGraceOnPrincipal(null)
.updateExtraTerms("2").updateNewInterestRate(null).updateRescheduleFromDate("31 December 2023")
.updateAdjustedDueDate(null).updateSubmittedOnDate("31 December 2023").updateRescheduleReasonId("1")
.build(loanId.toString());
Integer loanRescheduleRequest = loanRescheduleRequestHelper.createLoanRescheduleRequest(requestJSON);
requestJSON = new LoanRescheduleRequestTestBuilder().updateSubmittedOnDate("31 December 2023")
.getApproveLoanRescheduleRequestJSON();
Integer approveLoanRescheduleRequest = loanRescheduleRequestHelper.approveLoanRescheduleRequest(loanRescheduleRequest,
requestJSON);
// Verify Repayment Schedule
verifyRepaymentSchedule(loanId, //
installment(1000.0, null, "02 October 2023"), //
installment(330.0, true, "02 October 2023"), //
installment(268, false, "01 November 2023"), //
installment(268, false, "01 December 2023"), //
installment(200.0, null, "02 December 2023"), //
installment(66.0, false, "02 December 2023"), //
installment(89.33, false, "31 December 2023"), //
installment(89.33, false, "30 January 2024"), //
installment(89.34, false, "29 February 2024") //
);
});
}
@Test
public void testRescheduleAddExtraInstallmentsDisbursementWithDownPaymentWithInterest() {
runAt("01 January 2023", () -> {
// Create Client
Long clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
// Create Loan Product
Long loanProductId = createLoanProductWith20PctDownPaymentWithDecliningBalanceInterest(true, true, 5.0);
// Apply and Approve Loan
Long loanId = applyAndApproveLoan(clientId, loanProductId, "01 January 2023", 15000.0, 6, postLoansRequest -> {
postLoansRequest.interestRatePerPeriod(BigDecimal.valueOf(5));
postLoansRequest.interestRatePerPeriod(BigDecimal.valueOf(5));
postLoansRequest.repaymentEvery(1);
postLoansRequest.loanTermFrequencyType(RepaymentFrequencyType.MONTHS);
postLoansRequest.repaymentFrequencyType(RepaymentFrequencyType.MONTHS);
postLoansRequest.loanTermFrequency(6);
});
// Verify Repayment Schedule
verifyRepaymentSchedule(loanId, //
installment(12000.0, null, "01 January 2023"), //
installment(3000.00, false, "01 January 2023"), //
installment(1764.21, false, "01 February 2023"), //
installment(1852.42, false, "01 March 2023"), //
installment(1945.04, false, "01 April 2023"), //
installment(2042.29, false, "01 May 2023"), //
installment(2144.41, false, "01 June 2023"), //
installment(2251.63, false, "01 July 2023") //
);
// 1st Disburse Loan
disburseLoan(loanId, BigDecimal.valueOf(12000.00), "01 January 2023");
// verify transactions
verifyTransactions(loanId, //
transaction(2400.0, "Down Payment", "01 January 2023"), //
transaction(12000.0, "Disbursement", "01 January 2023") //
);
// Verify Repayment Schedule
verifyRepaymentSchedule(loanId, //
installment(12000.0, null, "01 January 2023"), //
installment(2400.00, true, "01 January 2023"), //
installment(1411.37, false, "01 February 2023"), //
installment(1481.94, false, "01 March 2023"), //
installment(1556.04, false, "01 April 2023"), //
installment(1633.84, false, "01 May 2023"), //
installment(1715.53, false, "01 June 2023"), //
installment(1801.28, false, "01 July 2023") //
);
updateBusinessDate("01 June 2023");
String requestJSON = new LoanRescheduleRequestTestBuilder().updateGraceOnInterest(null).updateGraceOnPrincipal(null)
.updateExtraTerms("2").updateNewInterestRate(null).updateRescheduleFromDate("01 June 2023").updateAdjustedDueDate(null)
.updateSubmittedOnDate("01 June 2023").updateRescheduleReasonId("1").build(loanId.toString());
Integer loanRescheduleRequest = loanRescheduleRequestHelper.createLoanRescheduleRequest(requestJSON);
requestJSON = new LoanRescheduleRequestTestBuilder().updateSubmittedOnDate("01 June 2023")
.getApproveLoanRescheduleRequestJSON();
Integer approveLoanRescheduleRequest = loanRescheduleRequestHelper.approveLoanRescheduleRequest(loanRescheduleRequest,
requestJSON);
// Verify Repayment Schedule
verifyRepaymentSchedule(loanId, //
installment(12000.0, null, "01 January 2023"), //
installment(2400.00, true, "01 January 2023"), //
installment(1411.37, false, "01 February 2023"), //
installment(1481.94, false, "01 March 2023"), //
installment(1556.04, false, "01 April 2023"), //
installment(1633.84, false, "01 May 2023"), //
installment(815.94, false, "01 June 2023"), //
installment(856.74, false, "01 July 2023"), //
installment(899.57, false, "01 August 2023"), //
installment(944.56, false, "01 September 2023") //
);
});
}
@Test
public void testRescheduleAddExtraInstallmentsMultipleDisbursementWithDownPaymentWithInterest() {
runAt("01 January 2023", () -> {
// Create Client
Long clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
// Create Loan Product
Long loanProductId = createLoanProductWith20PctDownPaymentWithDecliningBalanceInterest(true, true, 5.0);
// Apply and Approve Loan
Long loanId = applyAndApproveLoan(clientId, loanProductId, "01 January 2023", 15000.0, 6, postLoansRequest -> {
postLoansRequest.interestRatePerPeriod(BigDecimal.valueOf(5));
postLoansRequest.interestRatePerPeriod(BigDecimal.valueOf(5));
postLoansRequest.repaymentEvery(1);
postLoansRequest.loanTermFrequencyType(RepaymentFrequencyType.MONTHS);
postLoansRequest.repaymentFrequencyType(RepaymentFrequencyType.MONTHS);
postLoansRequest.loanTermFrequency(6);
});
// Verify Repayment Schedule
verifyRepaymentSchedule(loanId, //
installment(12000.0, null, "01 January 2023"), //
installment(3000.00, false, "01 January 2023"), //
installment(1764.21, false, "01 February 2023"), //
installment(1852.42, false, "01 March 2023"), //
installment(1945.04, false, "01 April 2023"), //
installment(2042.29, false, "01 May 2023"), //
installment(2144.41, false, "01 June 2023"), //
installment(2251.63, false, "01 July 2023") //
);
// 1st Disburse Loan
disburseLoan(loanId, BigDecimal.valueOf(12000.00), "01 January 2023");
// verify transactions
verifyTransactions(loanId, //
transaction(2400.0, "Down Payment", "01 January 2023"), //
transaction(12000.0, "Disbursement", "01 January 2023") //
);
// Verify Repayment Schedule
verifyRepaymentSchedule(loanId, //
installment(12000.0, null, "01 January 2023"), //
installment(2400.00, true, "01 January 2023"), //
installment(1411.37, false, "01 February 2023"), //
installment(1481.94, false, "01 March 2023"), //
installment(1556.04, false, "01 April 2023"), //
installment(1633.84, false, "01 May 2023"), //
installment(1715.53, false, "01 June 2023"), //
installment(1801.28, false, "01 July 2023") //
);
updateBusinessDate("02 May 2023");
// 2nd Disburse Loan
disburseLoan(loanId, BigDecimal.valueOf(3000.00), "02 May 2023");
// verify transactions
verifyTransactions(loanId, //
transaction(2400.0, "Down Payment", "01 January 2023"), //
transaction(12000.0, "Disbursement", "01 January 2023"), //
transaction(3000.00, "Disbursement", "02 May 2023"), //
transaction(600.0, "Down Payment", "02 May 2023") //
);
// Verify Repayment Schedule
verifyRepaymentSchedule(loanId, //
installment(12000.0, null, "01 January 2023"), //
installment(2400.00, true, "01 January 2023"), //
installment(1884.21, false, "01 February 2023"), //
installment(1978.42, false, "01 March 2023"), //
installment(2077.34, false, "01 April 2023"), //
installment(2181.21, false, "01 May 2023"), //
installment(3000.0, null, "02 May 2023"), //
installment(600.0, false, "02 May 2023"), //
installment(2174.14, false, "01 June 2023"), //
installment(1704.68, false, "01 July 2023") //
);
updateBusinessDate("01 June 2023");
String requestJSON = new LoanRescheduleRequestTestBuilder().updateGraceOnInterest(null).updateGraceOnPrincipal(null)
.updateExtraTerms("2").updateNewInterestRate(null).updateRescheduleFromDate("01 June 2023").updateAdjustedDueDate(null)
.updateSubmittedOnDate("01 June 2023").updateRescheduleReasonId("1").build(loanId.toString());
Integer loanRescheduleRequest = loanRescheduleRequestHelper.createLoanRescheduleRequest(requestJSON);
requestJSON = new LoanRescheduleRequestTestBuilder().updateSubmittedOnDate("01 June 2023")
.getApproveLoanRescheduleRequestJSON();
Integer approveLoanRescheduleRequest = loanRescheduleRequestHelper.approveLoanRescheduleRequest(loanRescheduleRequest,
requestJSON);
// Verify Repayment Schedule
verifyRepaymentSchedule(loanId, //
installment(12000.0, null, "01 January 2023"), //
installment(2400.00, true, "01 January 2023"), //
installment(1884.21, false, "01 February 2023"), //
installment(1978.42, false, "01 March 2023"), //
installment(2077.34, false, "01 April 2023"), //
installment(2181.21, false, "01 May 2023"), //
installment(3000.0, null, "02 May 2023"), //
installment(600.0, false, "02 May 2023"), //
installment(903.80, false, "01 June 2023"), //
installment(945.12, false, "01 July 2023"), //
installment(992.37, false, "01 August 2023"), //
installment(1037.53, false, "01 September 2023")//
);
});
}
private Long createLoanProductWith25PctDownPayment(boolean autoDownPaymentEnabled, boolean multiDisburseEnabled) {
PostLoanProductsRequest product = createOnePeriod30DaysLongNoInterestPeriodicAccrualProduct();
product.setMultiDisburseLoan(multiDisburseEnabled);
@@ -117,7 +455,7 @@ public class LoanRescheduleTestWithDownpayment extends BaseLoanIntegrationTest {
}
product.setEnableDownPayment(true);
product.setDisbursedAmountPercentageForDownPayment(DOWN_PAYMENT_PERCENTAGE);
product.setDisbursedAmountPercentageForDownPayment(DOWN_PAYMENT_PERCENTAGE_25);
product.setEnableAutoRepaymentForDownPayment(autoDownPaymentEnabled);
PostLoanProductsResponse loanProductResponse = loanProductHelper.createLoanProduct(product);
@@ -128,7 +466,76 @@ public class LoanRescheduleTestWithDownpayment extends BaseLoanIntegrationTest {
assertEquals(TRUE, getLoanProductsProductIdResponse.getEnableDownPayment());
assertNotNull(getLoanProductsProductIdResponse.getDisbursedAmountPercentageForDownPayment());
assertEquals(0, getLoanProductsProductIdResponse.getDisbursedAmountPercentageForDownPayment().compareTo(DOWN_PAYMENT_PERCENTAGE));
assertEquals(0,
getLoanProductsProductIdResponse.getDisbursedAmountPercentageForDownPayment().compareTo(DOWN_PAYMENT_PERCENTAGE_25));
assertEquals(autoDownPaymentEnabled, getLoanProductsProductIdResponse.getEnableAutoRepaymentForDownPayment());
assertEquals(multiDisburseEnabled, getLoanProductsProductIdResponse.getMultiDisburseLoan());
return loanProductId;
}
private Long createLoanProductWith33PctDownPayment(boolean autoDownPaymentEnabled, boolean multiDisburseEnabled) {
PostLoanProductsRequest product = createOnePeriod30DaysLongNoInterestPeriodicAccrualProduct();
product.setMultiDisburseLoan(multiDisburseEnabled);
product.repaymentEvery(1);
product.repaymentFrequencyType(RepaymentFrequencyType.MONTHS.longValue());
product.installmentAmountInMultiplesOf(null);
if (!multiDisburseEnabled) {
product.disallowExpectedDisbursements(null);
product.setAllowApprovedDisbursedAmountsOverApplied(null);
product.overAppliedCalculationType(null);
product.overAppliedNumber(null);
}
product.setEnableDownPayment(true);
product.setDisbursedAmountPercentageForDownPayment(DOWN_PAYMENT_PERCENTAGE_33);
product.setEnableAutoRepaymentForDownPayment(autoDownPaymentEnabled);
PostLoanProductsResponse loanProductResponse = loanProductHelper.createLoanProduct(product);
GetLoanProductsProductIdResponse getLoanProductsProductIdResponse = loanProductHelper
.retrieveLoanProductById(loanProductResponse.getResourceId());
Long loanProductId = loanProductResponse.getResourceId();
assertEquals(TRUE, getLoanProductsProductIdResponse.getEnableDownPayment());
assertNotNull(getLoanProductsProductIdResponse.getDisbursedAmountPercentageForDownPayment());
assertEquals(0,
getLoanProductsProductIdResponse.getDisbursedAmountPercentageForDownPayment().compareTo(DOWN_PAYMENT_PERCENTAGE_33));
assertEquals(autoDownPaymentEnabled, getLoanProductsProductIdResponse.getEnableAutoRepaymentForDownPayment());
assertEquals(multiDisburseEnabled, getLoanProductsProductIdResponse.getMultiDisburseLoan());
return loanProductId;
}
private Long createLoanProductWith20PctDownPaymentWithDecliningBalanceInterest(boolean autoDownPaymentEnabled,
boolean multiDisburseEnabled, double interestRate) {
PostLoanProductsRequest product = createOnePeriod30DaysLongNoInterestPeriodicAccrualProduct();
product.setMultiDisburseLoan(multiDisburseEnabled);
product.repaymentEvery(1);
product.repaymentFrequencyType(RepaymentFrequencyType.MONTHS.longValue());
product.installmentAmountInMultiplesOf(null);
product.interestRatePerPeriod(interestRate);
if (!multiDisburseEnabled) {
product.disallowExpectedDisbursements(null);
product.setAllowApprovedDisbursedAmountsOverApplied(null);
product.overAppliedCalculationType(null);
product.overAppliedNumber(null);
}
product.setEnableDownPayment(true);
product.setDisbursedAmountPercentageForDownPayment(DOWN_PAYMENT_PERCENTAGE_20);
product.setEnableAutoRepaymentForDownPayment(autoDownPaymentEnabled);
PostLoanProductsResponse loanProductResponse = loanProductHelper.createLoanProduct(product);
GetLoanProductsProductIdResponse getLoanProductsProductIdResponse = loanProductHelper
.retrieveLoanProductById(loanProductResponse.getResourceId());
Long loanProductId = loanProductResponse.getResourceId();
assertEquals(TRUE, getLoanProductsProductIdResponse.getEnableDownPayment());
assertNotNull(getLoanProductsProductIdResponse.getDisbursedAmountPercentageForDownPayment());
assertEquals(0,
getLoanProductsProductIdResponse.getDisbursedAmountPercentageForDownPayment().compareTo(DOWN_PAYMENT_PERCENTAGE_20));
assertEquals(autoDownPaymentEnabled, getLoanProductsProductIdResponse.getEnableAutoRepaymentForDownPayment());
assertEquals(multiDisburseEnabled, getLoanProductsProductIdResponse.getMultiDisburseLoan());
return loanProductId;
@@ -446,8 +446,8 @@ public class LoanSpecificDueDateChargeAfterMaturityTest {
.currencyCode("USD").name(Utils.randomStringGenerator("PENALTY_" + Calendar.getInstance().getTimeInMillis(), 5))
.chargeAppliesTo(1).locale("en").active(true));
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId, 1000L, 30, 30, 1, 0,
"01 September 2023", "01 September 2023");
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId, 1000L, 30, 30, 1,
BigDecimal.ZERO, "01 September 2023", "01 September 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
@@ -548,7 +548,7 @@ public class LoanSpecificDueDateChargeAfterMaturityTest {
}
private static PostLoansResponse applyForLoanApplication(final Long clientId, final Integer loanProductId, final Long principal,
final int loanTermFrequency, final int repaymentAfterEvery, final int numberOfRepayments, final int interestRate,
final int loanTermFrequency, final int repaymentAfterEvery, final int numberOfRepayments, final BigDecimal interestRate,
final String expectedDisbursementDate, final String submittedOnDate) {
LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
return loanTransactionHelper.applyLoan(new PostLoansRequest().clientId(clientId).productId(loanProductId.longValue())
@@ -80,7 +80,7 @@ public class LoanWaiveChargeTest extends BaseLoanIntegrationTest {
PostLoansResponse postLoansResponse = loanTransactionHelper.applyLoan(applicationRequest);
PostLoansLoanIdResponse approvedLoanResult = loanTransactionHelper.approveLoan(postLoansResponse.getResourceId(),
approveLoanRequest(amount));
approveLoanRequest(amount, "01 January 2023"));
Long loanId = approvedLoanResult.getLoanId();
appliedLoanId.set(loanId);
@@ -104,8 +104,8 @@ public class RefundForActiveLoansWithAdvancedPaymentAllocationTest {
Integer loanProductId = createLoanProduct("1000", "30", "4", LoanScheduleProcessingType.VERTICAL, assetAccount, incomeAccount,
expenseAccount, overpaymentAccount);
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), loanProductId, 1000L, 90, 30, 3, 0,
"01 January 2023", "01 January 2023");
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), loanProductId, 1000L, 90, 30, 3,
BigDecimal.ZERO, "01 January 2023", "01 January 2023");
int loanId = loanResponse.getLoanId().intValue();
@@ -303,8 +303,8 @@ public class RefundForActiveLoansWithAdvancedPaymentAllocationTest {
Integer loanProductId = createLoanProduct("1000", "30", "4", LoanScheduleProcessingType.HORIZONTAL, assetAccount, incomeAccount,
expenseAccount, overpaymentAccount);
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), loanProductId, 1000L, 90, 30, 3, 0,
"01 January 2023", "01 January 2023");
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), loanProductId, 1000L, 90, 30, 3,
BigDecimal.ZERO, "01 January 2023", "01 January 2023");
int loanId = loanResponse.getLoanId().intValue();
@@ -529,7 +529,7 @@ public class RefundForActiveLoansWithAdvancedPaymentAllocationTest {
}
private static PostLoansResponse applyForLoanApplication(final Long clientId, final Integer loanProductId, final Long principal,
final int loanTermFrequency, final int repaymentAfterEvery, final int numberOfRepayments, final int interestRate,
final int loanTermFrequency, final int repaymentAfterEvery, final int numberOfRepayments, final BigDecimal interestRate,
final String expectedDisbursementDate, final String submittedOnDate) {
log.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
return loanTransactionHelper.applyLoan(new PostLoansRequest().clientId(clientId).productId(loanProductId.longValue())