This is an automated email from the ASF dual-hosted git repository.
adamsaghy pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git
The following commit(s) were added to refs/heads/develop by this push:
new 6526e101a FINERACT-1992: Backdated delinquency pause
6526e101a is described below
commit 6526e101a1e74283f85e7eb8cc2706b70ad17eea
Author: Ruchi Dhamankar <[email protected]>
AuthorDate: Tue Dec 12 21:21:10 2023 +0530
FINERACT-1992: Backdated delinquency pause
---
.../DelinquencyWritePlatformServiceImpl.java | 22 +++-
.../DelinquencyActionParseAndValidator.java | 14 ++-
.../DelinquencyActionParseAndValidatorTest.java | 31 ++++-
.../DelinquencyActionIntegrationTests.java | 140 ++++++++++++++++++++-
4 files changed, 195 insertions(+), 12 deletions(-)
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/DelinquencyWritePlatformServiceImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/DelinquencyWritePlatformServiceImpl.java
index c92693d34..23a0f0cda 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/DelinquencyWritePlatformServiceImpl.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/DelinquencyWritePlatformServiceImpl.java
@@ -39,6 +39,7 @@ import
org.apache.fineract.infrastructure.event.business.service.BusinessEventNo
import org.apache.fineract.portfolio.delinquency.api.DelinquencyApiConstants;
import org.apache.fineract.portfolio.delinquency.data.DelinquencyBucketData;
import org.apache.fineract.portfolio.delinquency.data.DelinquencyRangeData;
+import org.apache.fineract.portfolio.delinquency.domain.DelinquencyAction;
import org.apache.fineract.portfolio.delinquency.domain.DelinquencyBucket;
import
org.apache.fineract.portfolio.delinquency.domain.DelinquencyBucketMappings;
import
org.apache.fineract.portfolio.delinquency.domain.DelinquencyBucketMappingsRepository;
@@ -230,8 +231,12 @@ public class DelinquencyWritePlatformServiceImpl
implements DelinquencyWritePlat
savedDelinquencyList, businessDate);
parsedDelinquencyAction.setLoan(loan);
-
LoanDelinquencyAction saved =
loanDelinquencyActionRepository.saveAndFlush(parsedDelinquencyAction);
+ // if backdated pause recalculate delinquency data
+ if (DateUtils.isBefore(parsedDelinquencyAction.getStartDate(),
businessDate)
+ &&
DelinquencyAction.PAUSE.equals(parsedDelinquencyAction.getAction())) {
+ recalculateLoanDelinquencyData(loan);
+ }
businessEventNotifierService.notifyPostBusinessEvent(new
LoanAccountDelinquencyPauseChangedBusinessEvent(loan));
return new
CommandProcessingResultBuilder().withCommandId(command.commandId()) //
.withEntityId(saved.getId()) //
@@ -242,6 +247,21 @@ public class DelinquencyWritePlatformServiceImpl
implements DelinquencyWritePlat
.build();
}
+ private void recalculateLoanDelinquencyData(Loan loan) {
+ List<LoanDelinquencyAction> savedDelinquencyList =
delinquencyReadPlatformService.retrieveLoanDelinquencyActions(loan.getId());
+ List<LoanDelinquencyActionData> effectiveDelinquencyList =
delinquencyEffectivePauseHelper
+ .calculateEffectiveDelinquencyList(savedDelinquencyList);
+
+ CollectionData loanDelinquencyData =
loanDelinquencyDomainService.getOverdueCollectionData(loan,
effectiveDelinquencyList);
+ LoanScheduleDelinquencyData loanScheduleDelinquencyData = new
LoanScheduleDelinquencyData(loan.getId(),
+ loanDelinquencyData.getDelinquentDate(),
loanDelinquencyData.getDelinquentDays(), loan);
+ if (loanScheduleDelinquencyData.getOverdueDays() > 0) {
+ applyDelinquencyTagToLoan(loanScheduleDelinquencyData,
effectiveDelinquencyList);
+ } else {
+ removeDelinquencyTagToLoan(loan);
+ }
+ }
+
@Override
public void removeDelinquencyTagToLoan(final Loan loan) {
if (loan.isEnableInstallmentLevelDelinquency()) {
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/validator/DelinquencyActionParseAndValidator.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/validator/DelinquencyActionParseAndValidator.java
index 380785c90..a9779d9b1 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/validator/DelinquencyActionParseAndValidator.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/validator/DelinquencyActionParseAndValidator.java
@@ -56,7 +56,8 @@ public class DelinquencyActionParseAndValidator extends
ParseAndValidator {
validateLoanIsActive(loan);
if
(DelinquencyAction.PAUSE.equals(parsedDelinquencyAction.getAction())) {
validateBothStartAndEndDatesAreProvided(parsedDelinquencyAction);
- validatePauseStartAndEndDate(parsedDelinquencyAction,
businessDate);
+ validatePauseStartAndEndDate(parsedDelinquencyAction);
+
validatePauseStartDateNotBeforeDisbursementDate(parsedDelinquencyAction,
loan.getDisbursementDate());
validatePauseShallNotOverlap(parsedDelinquencyAction,
effectiveDelinquencyList);
} else if
(DelinquencyAction.RESUME.equals(parsedDelinquencyAction.getAction())) {
validateResumeStartDate(parsedDelinquencyAction, businessDate);
@@ -117,15 +118,18 @@ public class DelinquencyActionParseAndValidator extends
ParseAndValidator {
}
}
- private void validatePauseStartAndEndDate(LoanDelinquencyAction
parsedDelinquencyAction, LocalDate businessDate) {
+ private void validatePauseStartAndEndDate(LoanDelinquencyAction
parsedDelinquencyAction) {
if
(parsedDelinquencyAction.getStartDate().equals(parsedDelinquencyAction.getEndDate()))
{
raiseValidationError("loan-delinquency-action-invalid-start-date-and-end-date",
"Delinquency pause period must be at least one day");
}
+ }
- if (businessDate.isAfter(parsedDelinquencyAction.getStartDate())) {
- raiseValidationError("loan-delinquency-action-invalid-start-date",
"Start date of pause period must be in the future",
- START_DATE);
+ private void
validatePauseStartDateNotBeforeDisbursementDate(LoanDelinquencyAction
parsedDelinquencyAction,
+ LocalDate firstDisbursalDate) {
+ if
(firstDisbursalDate.isAfter(parsedDelinquencyAction.getStartDate())) {
+ raiseValidationError("loan-delinquency-action-invalid-start-date",
+ "Start date of pause period must be after first disbursal
date", START_DATE);
}
}
diff --git
a/fineract-provider/src/test/java/org/apache/fineract/portfolio/delinquency/validator/DelinquencyActionParseAndValidatorTest.java
b/fineract-provider/src/test/java/org/apache/fineract/portfolio/delinquency/validator/DelinquencyActionParseAndValidatorTest.java
index 2c1d3638f..4b4b0f5f9 100644
---
a/fineract-provider/src/test/java/org/apache/fineract/portfolio/delinquency/validator/DelinquencyActionParseAndValidatorTest.java
+++
b/fineract-provider/src/test/java/org/apache/fineract/portfolio/delinquency/validator/DelinquencyActionParseAndValidatorTest.java
@@ -65,6 +65,7 @@ class DelinquencyActionParseAndValidatorTest {
public void testParseAndValidationIsOKForPause() throws
JsonProcessingException {
Loan loan = Mockito.mock(Loan.class);
Mockito.when(loan.getStatus()).thenReturn(LoanStatus.ACTIVE);
+ Mockito.when(loan.getDisbursementDate()).thenReturn(localDate("07
September 2022"));
JsonCommand command = delinquencyAction("pause", "09 September 2022",
"19 September 2022");
@@ -96,6 +97,7 @@ class DelinquencyActionParseAndValidatorTest {
public void testPauseBothStartAndEndDateIsOverlappingWithAnActivePause()
throws JsonProcessingException {
Loan loan = Mockito.mock(Loan.class);
Mockito.when(loan.getStatus()).thenReturn(LoanStatus.ACTIVE);
+ Mockito.when(loan.getDisbursementDate()).thenReturn(localDate("07
September 2022"));
List<LoanDelinquencyAction> existing =
List.of(loanDelinquencyAction(PAUSE, "14 September 2022", "22 September 2022"));
JsonCommand command = delinquencyAction("pause", "09 September 2022",
"15 September 2022");
@@ -111,6 +113,7 @@ class DelinquencyActionParseAndValidatorTest {
public void testPauseStartIsOverlappingWithAnActivePause() throws
JsonProcessingException {
Loan loan = Mockito.mock(Loan.class);
Mockito.when(loan.getStatus()).thenReturn(LoanStatus.ACTIVE);
+ Mockito.when(loan.getDisbursementDate()).thenReturn(localDate("11
September 2022"));
List<LoanDelinquencyAction> existing =
List.of(loanDelinquencyAction(PAUSE, "14 September 2022", "22 September 2022"));
JsonCommand command = delinquencyAction("pause", "15 September 2022",
"23 September 2022");
@@ -126,7 +129,7 @@ class DelinquencyActionParseAndValidatorTest {
public void testNewPauseEndIsOverlappingWithExistingPause() throws
JsonProcessingException {
Loan loan = Mockito.mock(Loan.class);
Mockito.when(loan.getStatus()).thenReturn(LoanStatus.ACTIVE);
-
+ Mockito.when(loan.getDisbursementDate()).thenReturn(localDate("11
September 2022"));
List<LoanDelinquencyAction> existing =
List.of(loanDelinquencyAction(PAUSE, "15 September 2022", "22 September 2022"));
JsonCommand command = delinquencyAction("pause", "13 September 2022",
"20 September 2022");
List<LoanDelinquencyActionData> effectiveList =
List.of(loanDelinquencyActionData(existing.get(0)));
@@ -141,6 +144,7 @@ class DelinquencyActionParseAndValidatorTest {
public void testNewPauseIsOverlappingWithExistingPauseBecauseSameDates()
throws JsonProcessingException {
Loan loan = Mockito.mock(Loan.class);
Mockito.when(loan.getStatus()).thenReturn(LoanStatus.ACTIVE);
+ Mockito.when(loan.getDisbursementDate()).thenReturn(localDate("11
September 2022"));
List<LoanDelinquencyAction> existing =
List.of(loanDelinquencyAction(PAUSE, "15 September 2022", "22 September 2022"));
JsonCommand command = delinquencyAction("pause", "15 September 2022",
"22 September 2022");
@@ -156,6 +160,7 @@ class DelinquencyActionParseAndValidatorTest {
public void testNewPauseIsNotOverlappingBecauseThereWasAResume() throws
JsonProcessingException {
Loan loan = Mockito.mock(Loan.class);
Mockito.when(loan.getStatus()).thenReturn(LoanStatus.ACTIVE);
+ Mockito.when(loan.getDisbursementDate()).thenReturn(localDate("11
September 2022"));
JsonCommand command = delinquencyAction("pause", "18 September 2022",
"20 September 2022");
@@ -269,13 +274,15 @@ class DelinquencyActionParseAndValidatorTest {
}
@Test
- public void testValidationErrorPausePeriodMustBeInFuture() throws
JsonProcessingException {
+ public void testValidationErrorPausePeriodMustNotBeBeforeDisbursement()
throws JsonProcessingException {
Loan loan = Mockito.mock(Loan.class);
Mockito.when(loan.getStatus()).thenReturn(LoanStatus.ACTIVE);
+ Mockito.when(loan.getDisbursementDate()).thenReturn(localDate("11
September 2022"));
JsonCommand command = delinquencyAction("pause", "08 September 2022",
"09 September 2022");
- assertPlatformValidationException("Start date of pause period must be
in the future", "loan-delinquency-action-invalid-start-date",
+ assertPlatformValidationException("Start date of pause period must be
after first disbursal date",
+ "loan-delinquency-action-invalid-start-date",
() -> underTest.validateAndParseUpdate(command, loan,
List.of(), localDate("09 September 2022")));
}
@@ -308,6 +315,7 @@ class DelinquencyActionParseAndValidatorTest {
public void testNewPausePeriodStartingOnExistingEndDate() throws
JsonProcessingException {
Loan loan = Mockito.mock(Loan.class);
Mockito.when(loan.getStatus()).thenReturn(LoanStatus.ACTIVE);
+ Mockito.when(loan.getDisbursementDate()).thenReturn(localDate("11
September 2022"));
JsonCommand command = delinquencyAction("pause", "18 September 2022",
"20 September 2022");
@@ -324,6 +332,7 @@ class DelinquencyActionParseAndValidatorTest {
public void testNewPauseEndingOnExistingStartDate() throws
JsonProcessingException {
Loan loan = Mockito.mock(Loan.class);
Mockito.when(loan.getStatus()).thenReturn(LoanStatus.ACTIVE);
+ Mockito.when(loan.getDisbursementDate()).thenReturn(localDate("11
September 2022"));
JsonCommand command = delinquencyAction("pause", "18 September 2022",
"20 September 2022");
@@ -340,6 +349,7 @@ class DelinquencyActionParseAndValidatorTest {
public void testNewPausePeriodStartingOnExistingEffectiveEndDate() throws
JsonProcessingException {
Loan loan = Mockito.mock(Loan.class);
Mockito.when(loan.getStatus()).thenReturn(LoanStatus.ACTIVE);
+ Mockito.when(loan.getDisbursementDate()).thenReturn(localDate("11
September 2022"));
JsonCommand command = delinquencyAction("pause", "18 September 2022",
"20 September 2022");
@@ -355,6 +365,21 @@ class DelinquencyActionParseAndValidatorTest {
Assertions.assertEquals(localDate("20 September 2022"),
parsedDelinquencyAction.getEndDate());
}
+ @Test
+ public void testParseAndValidationIsOKForBackdatedPause() throws
JsonProcessingException {
+ Loan loan = Mockito.mock(Loan.class);
+ Mockito.when(loan.getStatus()).thenReturn(LoanStatus.ACTIVE);
+ Mockito.when(loan.getDisbursementDate()).thenReturn(localDate("07
September 2022"));
+
+ JsonCommand command = delinquencyAction("pause", "08 September 2022",
"19 September 2022");
+
+ LoanDelinquencyAction parsedDelinquencyAction =
underTest.validateAndParseUpdate(command, loan, List.of(),
+ localDate("09 September 2022"));
+ Assertions.assertEquals(PAUSE, parsedDelinquencyAction.getAction());
+ Assertions.assertEquals(localDate("08 September 2022"),
parsedDelinquencyAction.getStartDate());
+ Assertions.assertEquals(localDate("19 September 2022"),
parsedDelinquencyAction.getEndDate());
+ }
+
@NotNull
private JsonCommand delinquencyAction(@Nullable String action, @Nullable
String startDate, @Nullable String endDate)
throws JsonProcessingException {
diff --git
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/DelinquencyActionIntegrationTests.java
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/DelinquencyActionIntegrationTests.java
index ac409adae..f7c8284fb 100644
---
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/DelinquencyActionIntegrationTests.java
+++
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/DelinquencyActionIntegrationTests.java
@@ -22,6 +22,7 @@ import static java.lang.Boolean.TRUE;
import static
org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType.BUSINESS_DATE;
import static
org.apache.fineract.portfolio.delinquency.domain.DelinquencyAction.PAUSE;
import static
org.apache.fineract.portfolio.delinquency.domain.DelinquencyAction.RESUME;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -32,11 +33,14 @@ import java.time.LocalDate;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
+import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.tuple.Pair;
import org.apache.fineract.client.models.BusinessDateRequest;
import org.apache.fineract.client.models.GetDelinquencyActionsResponse;
import org.apache.fineract.client.models.GetLoanProductsProductIdResponse;
import org.apache.fineract.client.models.GetLoansLoanIdDelinquencyPausePeriod;
+import
org.apache.fineract.client.models.GetLoansLoanIdLoanInstallmentLevelDelinquency;
import org.apache.fineract.client.models.GetLoansLoanIdResponse;
import org.apache.fineract.client.models.PostLoanProductsRequest;
import org.apache.fineract.client.models.PostLoanProductsResponse;
@@ -44,6 +48,7 @@ import
org.apache.fineract.client.models.PostLoansDelinquencyActionResponse;
import org.apache.fineract.client.util.CallFailedRuntimeException;
import org.apache.fineract.integrationtests.common.ClientHelper;
import
org.apache.fineract.integrationtests.common.loans.LoanTestLifecycleExtension;
+import
org.apache.fineract.integrationtests.common.products.DelinquencyBucketsHelper;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -201,7 +206,7 @@ public class DelinquencyActionIntegrationTests extends
BaseLoanIntegrationTest {
}
@Test
- public void testValidationErrorIsThrownWhenCreatingActionInThePast() {
+ public void
testValidationErrorIsThrownWhenCreatingPauseActionWithBackdatedStartDateBeforeDisbursement()
{
runAt("01 January 2023", () -> {
// Create Client
Long clientId =
clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
@@ -215,10 +220,80 @@ public class DelinquencyActionIntegrationTests extends
BaseLoanIntegrationTest {
// Disburse Loan
disburseLoan(loanId, BigDecimal.valueOf(1000.00), "01 January
2023");
- // Create Delinquency Pause for the Loan in the past
+ // Create Delinquency Pause for the Loan before disbursement date
CallFailedRuntimeException exception =
assertThrows(CallFailedRuntimeException.class,
() ->
loanTransactionHelper.createLoanDelinquencyAction(loanId, PAUSE, "05 December
2022", "15 January 2023"));
- assertTrue(exception.getMessage().contains("Start date of pause
period must be in the future"));
+ assertTrue(exception.getMessage().contains("Start date of pause
period must be after first disbursal date"));
+ });
+ }
+
+ @Test
+ public void testCreateAndVerifyBackdatedPauseDelinquencyAction() {
+ runAt("30 January 2023", () -> {
+ // Create Client
+ Long clientId =
clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
+
+ // Create Loan Product
+ Long loanProductId = createLoanProductWith25PctDownPayment(true,
true);
+
+ // Apply and Approve Loan
+ Long loanId = applyAndApproveLoan(clientId, loanProductId, "25
December 2022", 1500.0, 3,
+ req -> req.submittedOnDate("25 December 2022"));
+
+ // Disburse Loan
+ disburseLoan(loanId, BigDecimal.valueOf(1000.00), "25 December
2022");
+
+ // Create Delinquency Pause for the Loan in the past
+ PostLoansDelinquencyActionResponse response =
loanTransactionHelper.createLoanDelinquencyAction(loanId, PAUSE,
+ "28 January 2023", "15 February 2023");
+
+ List<GetDelinquencyActionsResponse> loanDelinquencyActions =
loanTransactionHelper.getLoanDelinquencyActions(loanId);
+ Assertions.assertNotNull(loanDelinquencyActions);
+ Assertions.assertEquals(1, loanDelinquencyActions.size());
+ Assertions.assertEquals("PAUSE",
loanDelinquencyActions.get(0).getAction());
+ Assertions.assertEquals(LocalDate.parse("28 January 2023",
dateTimeFormatter), loanDelinquencyActions.get(0).getStartDate());
+ Assertions.assertEquals(LocalDate.parse("15 February 2023",
dateTimeFormatter), loanDelinquencyActions.get(0).getEndDate());
+
+ // Validate Active Delinquency Pause Period on Loan
+ validateLoanDelinquencyPausePeriods(loanId, pausePeriods("28
January 2023", "15 February 2023", true));
+ });
+ }
+
+ @Test
+ public void
testVerifyLoanDelinquencyRecalculationForBackdatedPauseDelinquencyAction() {
+ runAt("30 January 2023", () -> {
+ // Create Client
+ Long clientId =
clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
+
+ // Create Loan Product
+ Long loanProductId =
createLoanProductWith25PctDownPaymentAndDelinquencyBucket(true, true, true);
+
+ // Apply and Approve Loan
+ Long loanId = applyAndApproveLoan(clientId, loanProductId, "25
December 2022", 1500.0, 3,
+ req -> req.submittedOnDate("25 December 2022"));
+
+ // Disburse Loan
+ disburseLoan(loanId, BigDecimal.valueOf(1000.00), "25 December
2022");
+
+ // Loan delinquency data before backdated pause
+ verifyLoanDelinquencyData(loanId, 6, new
InstallmentDelinquencyData(4, 10, BigDecimal.valueOf(250.0)));
+
+ // Create Delinquency Pause for the Loan in the past
+ PostLoansDelinquencyActionResponse response =
loanTransactionHelper.createLoanDelinquencyAction(loanId, PAUSE,
+ "27 January 2023", "15 February 2023");
+
+ List<GetDelinquencyActionsResponse> loanDelinquencyActions =
loanTransactionHelper.getLoanDelinquencyActions(loanId);
+ Assertions.assertNotNull(loanDelinquencyActions);
+ Assertions.assertEquals(1, loanDelinquencyActions.size());
+ Assertions.assertEquals("PAUSE",
loanDelinquencyActions.get(0).getAction());
+ Assertions.assertEquals(LocalDate.parse("27 January 2023",
dateTimeFormatter), loanDelinquencyActions.get(0).getStartDate());
+ Assertions.assertEquals(LocalDate.parse("15 February 2023",
dateTimeFormatter), loanDelinquencyActions.get(0).getEndDate());
+
+ // Loan delinquency data calculation after backdated pause
+ verifyLoanDelinquencyData(loanId, 3, new
InstallmentDelinquencyData(1, 3, BigDecimal.valueOf(250.0)));
+
+ // Validate Active Delinquency Pause Period on Loan
+ validateLoanDelinquencyPausePeriods(loanId, pausePeriods("27
January 2023", "15 February 2023", true));
});
}
@@ -265,6 +340,24 @@ public class DelinquencyActionIntegrationTests extends
BaseLoanIntegrationTest {
return pausePeriod;
}
+ private void verifyLoanDelinquencyData(Long loanId, Integer
loanLevelDelinquentDays,
+ InstallmentDelinquencyData...
expectedInstallmentLevelInstallmentDelinquencyData) {
+ GetLoansLoanIdResponse loan =
loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId.intValue());
+ Assertions.assertNotNull(loan.getDelinquent());
+ List<GetLoansLoanIdLoanInstallmentLevelDelinquency>
installmentLevelDelinquency = loan.getDelinquent()
+ .getInstallmentLevelDelinquency();
+
+
assertThat(loan.getDelinquent().getDelinquentDays()).isEqualTo(loanLevelDelinquentDays);
+
+ assertThat(installmentLevelDelinquency.get(0).getMaximumAgeDays())
+
.isEqualTo(expectedInstallmentLevelInstallmentDelinquencyData[0].maxAgeDays);
+ assertThat(installmentLevelDelinquency.get(0).getMinimumAgeDays())
+
.isEqualTo(expectedInstallmentLevelInstallmentDelinquencyData[0].minAgeDays);
+ assertThat(installmentLevelDelinquency.get(0).getDelinquentAmount())
+
.isEqualByComparingTo(expectedInstallmentLevelInstallmentDelinquencyData[0].delinquentAmount);
+
+ }
+
private Long createLoanProductWith25PctDownPayment(boolean
autoDownPaymentEnabled, boolean multiDisburseEnabled) {
PostLoanProductsRequest product =
createOnePeriod30DaysLongNoInterestPeriodicAccrualProduct();
product.setMultiDisburseLoan(multiDisburseEnabled);
@@ -294,4 +387,45 @@ public class DelinquencyActionIntegrationTests extends
BaseLoanIntegrationTest {
return loanProductId;
}
+ private Long
createLoanProductWith25PctDownPaymentAndDelinquencyBucket(boolean
autoDownPaymentEnabled, boolean multiDisburseEnabled,
+ boolean installmentLevelDelinquencyEnabled) {
+ // Create DelinquencyBuckets
+ Integer delinquencyBucketId =
DelinquencyBucketsHelper.createDelinquencyBucket(requestSpec, responseSpec,
List.of(//
+ Pair.of(1, 3), //
+ Pair.of(4, 10), //
+ Pair.of(11, 60), //
+ Pair.of(61, null)//
+ ));
+ PostLoanProductsRequest product =
createOnePeriod30DaysLongNoInterestPeriodicAccrualProduct();
+ product.setDelinquencyBucketId(delinquencyBucketId.longValue());
+ product.setMultiDisburseLoan(multiDisburseEnabled);
+ product.setEnableDownPayment(true);
+
+
product.setDisbursedAmountPercentageForDownPayment(DOWN_PAYMENT_PERCENTAGE);
+ product.setEnableAutoRepaymentForDownPayment(autoDownPaymentEnabled);
+
product.setEnableInstallmentLevelDelinquency(installmentLevelDelinquencyEnabled);
+
+ 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));
+ assertEquals(autoDownPaymentEnabled,
getLoanProductsProductIdResponse.getEnableAutoRepaymentForDownPayment());
+ assertEquals(multiDisburseEnabled,
getLoanProductsProductIdResponse.getMultiDisburseLoan());
+ return loanProductId;
+
+ }
+
+ @AllArgsConstructor
+ public static class InstallmentDelinquencyData {
+
+ Integer minAgeDays;
+ Integer maxAgeDays;
+ BigDecimal delinquentAmount;
+ }
+
}