diff --git a/fineract-avro-schemas/src/main/avro/loan/v1/CollectionDataV1.avsc b/fineract-avro-schemas/src/main/avro/loan/v1/CollectionDataV1.avsc index af515e59302..22c3c086abf 100644 --- a/fineract-avro-schemas/src/main/avro/loan/v1/CollectionDataV1.avsc +++ b/fineract-avro-schemas/src/main/avro/loan/v1/CollectionDataV1.avsc @@ -27,6 +27,14 @@ "int" ] }, + { + "default": null, + "name": "pastDueDate", + "type": [ + "null", + "string" + ] + }, { "default": null, "name": "nextPaymentDueDate", diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/InlineCOBStepDef.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/InlineCOBStepDef.java index 82f82e8a263..032dd96a4c5 100644 --- a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/InlineCOBStepDef.java +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/InlineCOBStepDef.java @@ -19,6 +19,7 @@ package org.apache.fineract.test.stepdef.loan; import static org.apache.fineract.client.feign.util.FeignCalls.ok; +import static org.assertj.core.api.Assertions.assertThat; import io.cucumber.java.en.Then; import io.cucumber.java.en.When; @@ -30,10 +31,12 @@ import org.apache.fineract.client.models.PostLoansResponse; import org.apache.fineract.test.messaging.EventAssertion; import org.apache.fineract.test.messaging.event.assetexternalization.LoanAccountCustomSnapshotEvent; +import org.apache.fineract.test.messaging.event.loan.LoanBalanceChangedEvent; import org.apache.fineract.test.messaging.event.loan.repayment.LoanRepaymentDueEvent; import org.apache.fineract.test.messaging.event.loan.repayment.LoanRepaymentOverdueEvent; import org.apache.fineract.test.stepdef.AbstractStepDef; import org.apache.fineract.test.support.TestContextKey; +import org.junit.jupiter.api.Assertions; import org.springframework.beans.factory.annotation.Autowired; public class InlineCOBStepDef extends AbstractStepDef { @@ -49,6 +52,7 @@ public class InlineCOBStepDef extends AbstractStepDef { @When("Admin runs inline COB job for Loan") public void runInlineCOB() throws IOException { PostLoansResponse loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE); + Assertions.assertNotNull(loanResponse); long loanId = loanResponse.getLoanId(); InlineJobRequest inlineJobRequest = new InlineJobRequest().addLoanIdsItem(loanId); @@ -59,6 +63,7 @@ public void runInlineCOB() throws IOException { @Then("Loan Repayment Due Business Event is created") public void checkLoanRepaymentDueBusinessEventCreated() { PostLoansResponse loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE); + Assertions.assertNotNull(loanResponse); long loanId = loanResponse.getLoanId(); eventAssertion.assertEventRaised(LoanRepaymentDueEvent.class, loanId); @@ -67,6 +72,7 @@ public void checkLoanRepaymentDueBusinessEventCreated() { @Then("Loan Repayment Overdue Business Event is created") public void checkLoanRepaymentOverdueBusinessEventCreated() { PostLoansResponse loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE); + Assertions.assertNotNull(loanResponse); long loanId = loanResponse.getLoanId(); eventAssertion.assertEventRaised(LoanRepaymentOverdueEvent.class, loanId); @@ -75,9 +81,26 @@ public void checkLoanRepaymentOverdueBusinessEventCreated() { @Then("LoanAccountCustomSnapshotBusinessEvent is created with business date {string}") public void checkLoanRepaymentDueBusinessEventCreatedWithBusinessDate(String expectedBusinessDate) { PostLoansResponse loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE); + Assertions.assertNotNull(loanResponse); long loanId = loanResponse.getLoanId(); LocalDate expectedBusinessDateParsed = LocalDate.parse(expectedBusinessDate, FORMATTER); eventAssertion.assertEvent(LoanAccountCustomSnapshotEvent.class, loanId).isRaisedOnBusinessDate(expectedBusinessDateParsed); } + + @Then("LoanBalanceChangedBusinessEvent has pastDueDate {string}") + public void checkLoanBalanceChangedBusinessEventHasPastDueDate(final String expectedPastDueDate) { + final PostLoansResponse loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE); + Assertions.assertNotNull(loanResponse); + final long loanId = loanResponse.getLoanId(); + + final String expectedPastDueDateValue = "null".equals(expectedPastDueDate) ? null : expectedPastDueDate; + + eventAssertion.assertEvent(LoanBalanceChangedEvent.class, loanId).extractingData(loanAccountDataV1 -> { + final String actualPastDueDate = loanAccountDataV1.getDelinquent() == null ? null + : loanAccountDataV1.getDelinquent().getPastDueDate(); + assertThat(actualPastDueDate).as("pastDueDate in LoanBalanceChangedBusinessEvent").isEqualTo(expectedPastDueDateValue); + return null; + }); + } } diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/LoanDelinquencyStepDef.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/LoanDelinquencyStepDef.java index 786d754341e..23e9735751c 100644 --- a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/LoanDelinquencyStepDef.java +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/LoanDelinquencyStepDef.java @@ -25,7 +25,6 @@ import io.cucumber.datatable.DataTable; import io.cucumber.java.en.Then; import io.cucumber.java.en.When; -import java.io.IOException; import java.math.BigDecimal; import java.math.RoundingMode; import java.time.format.DateTimeFormatter; @@ -34,6 +33,7 @@ import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.fineract.avro.loan.v1.LoanAccountDelinquencyRangeDataV1; import org.apache.fineract.avro.loan.v1.LoanInstallmentDelinquencyBucketDataV1; @@ -59,27 +59,19 @@ import org.apache.fineract.test.messaging.event.loan.delinquency.LoanDelinquencyRangeChangeEvent; import org.apache.fineract.test.stepdef.AbstractStepDef; import org.apache.fineract.test.support.TestContextKey; -import org.springframework.beans.factory.annotation.Autowired; @Slf4j +@RequiredArgsConstructor public class LoanDelinquencyStepDef extends AbstractStepDef { public static final String DATE_FORMAT = "dd MMMM yyyy"; public static final String DEFAULT_LOCALE = "en"; public static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern(DATE_FORMAT); - private static final String PWD_USER_WITH_ROLE = "1234567890Aa!"; - @Autowired - private FineractFeignClient fineractClient; - - @Autowired - private ApiProperties apiProperties; - - @Autowired - private EventAssertion eventAssertion; - - @Autowired - private EventCheckHelper eventCheckHelper; + private final FineractFeignClient fineractClient; + private final ApiProperties apiProperties; + private final EventAssertion eventAssertion; + private final EventCheckHelper eventCheckHelper; private FineractFeignClient createClientForUser(String username, String password) { String baseUrl = apiProperties.getBaseUrl(); @@ -93,9 +85,9 @@ private FineractFeignClient createClientForUser(String username, String password } @Then("Admin checks that delinquency range is: {string} and has delinquentDate {string}") - public void checkDelinquencyRange(String range, String delinquentDateExpected) throws IOException { + public void checkDelinquencyRange(String range, String delinquentDateExpected) { PostLoansResponse loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE); - long loanId = loanResponse.getLoanId(); + Long loanId = loanResponse.getLoanId(); GetLoansLoanIdResponse loanDetails = ok(() -> fineractClient.loans().retrieveLoan(loanId, Map.of("associations", "collection"))); Integer loanStatus = loanDetails.getStatus().getId(); @@ -122,11 +114,10 @@ public void checkDelinquencyRange(String range, String delinquentDateExpected) t } @Then("Admin checks that {string}th delinquency range is: {string} and added on: {string} and has delinquentDate {string}") - public void checkDelinquencyRange(String nthInList, String range, String addedOnDate, String delinquentDateExpected) - throws IOException { + public void checkDelinquencyRange(String nthInList, String range, String addedOnDate, String delinquentDateExpected) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_FORMAT); PostLoansResponse loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE); - long loanId = loanResponse.getLoanId(); + Long loanId = loanResponse.getLoanId(); String delinquentDateExpectedValue = "".equals(delinquentDateExpected) ? null : delinquentDateExpected; eventAssertion.assertEvent(LoanDelinquencyRangeChangeEvent.class, loanId) @@ -155,12 +146,12 @@ public void checkDelinquencyRange(String nthInList, String range, String addedOn } @Then("Loan delinquency history has the following details:") - public void delinquencyHistoryCheck(DataTable table) throws IOException { + public void delinquencyHistoryCheck(DataTable table) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_FORMAT); List> dataExpected = table.asLists(); PostLoansResponse loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE); - long loanId = loanResponse.getLoanId(); + Long loanId = loanResponse.getLoanId(); List body = ok(() -> fineractClient.loans().getDelinquencyTagHistory(loanId)); @@ -188,9 +179,9 @@ public void delinquencyHistoryCheck(DataTable table) throws IOException { } @When("Admin initiate a DELINQUENCY PAUSE with startDate: {string} and endDate: {string}") - public void delinquencyPause(String startDate, String endDate) throws IOException { + public void delinquencyPause(String startDate, String endDate) { PostLoansResponse loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE); - long loanId = loanResponse.getLoanId(); + Long loanId = loanResponse.getLoanId(); PostLoansDelinquencyActionRequest request = new PostLoansDelinquencyActionRequest()// .action("pause")// @@ -205,9 +196,9 @@ public void delinquencyPause(String startDate, String endDate) throws IOExceptio } @When("Created user with CREATE_DELINQUENCY_ACTION permission initiate a DELINQUENCY PAUSE with startDate: {string} and endDate: {string}") - public void delinquencyPauseWithCreatedUser(String startDate, String endDate) throws IOException { + public void delinquencyPauseWithCreatedUser(String startDate, String endDate) { PostLoansResponse loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE); - long loanId = loanResponse.getLoanId(); + Long loanId = loanResponse.getLoanId(); PostLoansDelinquencyActionRequest request = new PostLoansDelinquencyActionRequest()// .action("pause")// @@ -226,9 +217,9 @@ public void delinquencyPauseWithCreatedUser(String startDate, String endDate) th } @Then("Created user with no CREATE_DELINQUENCY_ACTION permission gets an error when initiate a DELINQUENCY PAUSE with startDate: {string} and endDate: {string}") - public void delinquencyPauseWithCreatedUserNOPermissionError(String startDate, String endDate) throws IOException { + public void delinquencyPauseWithCreatedUserNOPermissionError(String startDate, String endDate) { PostLoansResponse loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE); - long loanId = loanResponse.getLoanId(); + Long loanId = loanResponse.getLoanId(); int errorCodeExpected = 403; String errorMessageExpected = "User has no authority to CREATE delinquency_actions"; @@ -257,9 +248,9 @@ public void delinquencyPauseWithCreatedUserNOPermissionError(String startDate, S } @When("Admin initiate a DELINQUENCY RESUME with startDate: {string}") - public void delinquencyResume(String startDate) throws IOException { + public void delinquencyResume(String startDate) { PostLoansResponse loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE); - long loanId = loanResponse.getLoanId(); + Long loanId = loanResponse.getLoanId(); PostLoansDelinquencyActionRequest request = new PostLoansDelinquencyActionRequest()// .action("resume")// @@ -273,10 +264,10 @@ public void delinquencyResume(String startDate) throws IOException { } @When("Admin initiate a DELINQUENCY PAUSE by loanExternalId with startDate: {string} and endDate: {string}") - public void delinquencyPauseByLoanExternalId(String startDate, String endDate) throws IOException { + public void delinquencyPauseByLoanExternalId(String startDate, String endDate) { PostLoansResponse loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE); String loanExternalId = loanResponse.getResourceExternalId(); - long loanId = loanResponse.getLoanId(); + Long loanId = loanResponse.getLoanId(); PostLoansDelinquencyActionRequest request = new PostLoansDelinquencyActionRequest()// .action("pause")// @@ -292,10 +283,10 @@ public void delinquencyPauseByLoanExternalId(String startDate, String endDate) t } @When("Admin initiate a DELINQUENCY RESUME by loanExternalId with startDate: {string}") - public void delinquencyResumeByLoanExternalId(String startDate) throws IOException { + public void delinquencyResumeByLoanExternalId(String startDate) { PostLoansResponse loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE); String loanExternalId = loanResponse.getResourceExternalId(); - long loanId = loanResponse.getLoanId(); + Long loanId = loanResponse.getLoanId(); PostLoansDelinquencyActionRequest request = new PostLoansDelinquencyActionRequest()// .action("resume")// @@ -310,9 +301,9 @@ public void delinquencyResumeByLoanExternalId(String startDate) throws IOExcepti } @Then("Delinquency-actions have the following data:") - public void getDelinquencyActionData(DataTable table) throws IOException { + public void getDelinquencyActionData(DataTable table) { PostLoansResponse loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE); - long loanId = loanResponse.getLoanId(); + Long loanId = loanResponse.getLoanId(); List> data = table.asLists(); int nrOfLinesExpected = data.size() - 1; @@ -341,9 +332,9 @@ public void getDelinquencyActionData(DataTable table) throws IOException { } @Then("Initiating a delinquency-action other than PAUSE or RESUME in action field results an error - startDate: {string}, endDate: {string}") - public void actionFieldError(String startDate, String endDate) throws IOException { + public void actionFieldError(String startDate, String endDate) { PostLoansResponse loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE); - long loanId = loanResponse.getLoanId(); + Long loanId = loanResponse.getLoanId(); PostLoansDelinquencyActionRequest request = new PostLoansDelinquencyActionRequest()// .action("TEST")// @@ -358,9 +349,9 @@ public void actionFieldError(String startDate, String endDate) throws IOExceptio } @Then("Initiating a DELINQUENCY PAUSE with startDate before the actual business date results an error - startDate: {string}, endDate: {string}") - public void delinquencyPauseStartDateError(String startDate, String endDate) throws IOException { + public void delinquencyPauseStartDateError(String startDate, String endDate) { PostLoansResponse loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE); - long loanId = loanResponse.getLoanId(); + Long loanId = loanResponse.getLoanId(); PostLoansDelinquencyActionRequest request = new PostLoansDelinquencyActionRequest()// .action("pause")// @@ -375,9 +366,9 @@ public void delinquencyPauseStartDateError(String startDate, String endDate) thr } @Then("Initiating a DELINQUENCY PAUSE on a non-active loan results an error - startDate: {string}, endDate: {string}") - public void delinquencyPauseNonActiveLoanError(String startDate, String endDate) throws IOException { + public void delinquencyPauseNonActiveLoanError(String startDate, String endDate) { PostLoansResponse loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE); - long loanId = loanResponse.getLoanId(); + Long loanId = loanResponse.getLoanId(); PostLoansDelinquencyActionRequest request = new PostLoansDelinquencyActionRequest()// .action("pause")// @@ -392,9 +383,9 @@ public void delinquencyPauseNonActiveLoanError(String startDate, String endDate) } @Then("Initiating a DELINQUENCY RESUME on a non-active loan results an error - startDate: {string}") - public void delinquencyResumeNonActiveLoanError(String startDate) throws IOException { + public void delinquencyResumeNonActiveLoanError(String startDate) { PostLoansResponse loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE); - long loanId = loanResponse.getLoanId(); + Long loanId = loanResponse.getLoanId(); PostLoansDelinquencyActionRequest request = new PostLoansDelinquencyActionRequest()// .action("resume")// @@ -408,9 +399,9 @@ public void delinquencyResumeNonActiveLoanError(String startDate) throws IOExcep } @Then("Overlapping PAUSE periods result an error - startDate: {string}, endDate: {string}") - public void delinquencyPauseOverlappingError(String startDate, String endDate) throws IOException { + public void delinquencyPauseOverlappingError(String startDate, String endDate) { PostLoansResponse loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE); - long loanId = loanResponse.getLoanId(); + Long loanId = loanResponse.getLoanId(); PostLoansDelinquencyActionRequest request = new PostLoansDelinquencyActionRequest()// .action("pause")// @@ -425,9 +416,9 @@ public void delinquencyPauseOverlappingError(String startDate, String endDate) t } @Then("Initiating a DELINQUENCY RESUME without an active PAUSE period results an error - startDate: {string}") - public void delinquencyResumeWithoutPauseError(String startDate) throws IOException { + public void delinquencyResumeWithoutPauseError(String startDate) { PostLoansResponse loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE); - long loanId = loanResponse.getLoanId(); + Long loanId = loanResponse.getLoanId(); PostLoansDelinquencyActionRequest request = new PostLoansDelinquencyActionRequest()// .action("resume")// @@ -441,9 +432,9 @@ public void delinquencyResumeWithoutPauseError(String startDate) throws IOExcept } @Then("Initiating a DELINQUENCY RESUME with start date other than actual business date results an error - startDate: {string}") - public void delinquencyResumeStartDateError(String startDate) throws IOException { + public void delinquencyResumeStartDateError(String startDate) { PostLoansResponse loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE); - long loanId = loanResponse.getLoanId(); + Long loanId = loanResponse.getLoanId(); PostLoansDelinquencyActionRequest request = new PostLoansDelinquencyActionRequest()// .action("resume")// @@ -457,9 +448,9 @@ public void delinquencyResumeStartDateError(String startDate) throws IOException } @Then("Initiating a DELINQUENCY RESUME with an endDate results an error - startDate: {string}, endDate: {string}") - public void delinquencyResumeWithEndDateError(String startDate, String endDate) throws IOException { + public void delinquencyResumeWithEndDateError(String startDate, String endDate) { PostLoansResponse loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE); - long loanId = loanResponse.getLoanId(); + Long loanId = loanResponse.getLoanId(); PostLoansDelinquencyActionRequest request = new PostLoansDelinquencyActionRequest()// .action("resume")// @@ -474,17 +465,17 @@ public void delinquencyResumeWithEndDateError(String startDate, String endDate) } @Then("Installment level delinquency event has correct data") - public void installmentLevelDelinquencyEventCheck() throws IOException { + public void installmentLevelDelinquencyEventCheck() { PostLoansResponse loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE); - long loanId = loanResponse.getLoanId(); + Long loanId = loanResponse.getLoanId(); eventCheckHelper.installmentLevelDelinquencyRangeChangeEventCheck(loanId); } @Then("INSTALLMENT level delinquency is null") - public void installmentLevelDelinquencyNull() throws IOException { + public void installmentLevelDelinquencyNull() { PostLoansResponse loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE); - long loanId = loanResponse.getLoanId(); + Long loanId = loanResponse.getLoanId(); GetLoansLoanIdResponse loanDetails = ok(() -> fineractClient.loans().retrieveLoan(loanId, Map.of("associations", "collection"))); List installmentLevelDelinquency = loanDetails.getDelinquent() @@ -493,12 +484,12 @@ public void installmentLevelDelinquencyNull() throws IOException { } @Then("Loan has the following LOAN level delinquency data:") - public void loanDelinquencyDataCheck(DataTable table) throws IOException { + public void loanDelinquencyDataCheck(DataTable table) { PostLoansResponse loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE); - long loanId = loanResponse.getLoanId(); + Long loanId = loanResponse.getLoanId(); List expectedValuesList = table.asLists().get(1); - DelinquencyRange expectedDelinquencyRange = DelinquencyRange.valueOf(expectedValuesList.get(0)); + DelinquencyRange expectedDelinquencyRange = DelinquencyRange.valueOf(expectedValuesList.getFirst()); String expectedDelinquencyRangeValue = expectedDelinquencyRange.getValue(); expectedValuesList.set(0, expectedDelinquencyRangeValue); @@ -506,23 +497,37 @@ public void loanDelinquencyDataCheck(DataTable table) throws IOException { String actualDelinquencyRangeValue = loanDetails.getDelinquencyRange() == null ? "NO_DELINQUENCY" : loanDetails.getDelinquencyRange().getClassification(); GetLoansLoanIdDelinquencySummary delinquent = loanDetails.getDelinquent(); + assertThat(delinquent).isNotNull(); String delinquentAmount = delinquent.getDelinquentAmount() == null ? null : new Utils.DoubleFormatter(delinquent.getDelinquentAmount().doubleValue()).format(); - List actualValuesList = List.of(actualDelinquencyRangeValue, delinquentAmount, - delinquent.getDelinquentDate() == null ? "null" : FORMATTER.format(delinquent.getDelinquentDate()), - delinquent.getDelinquentDays().toString(), delinquent.getPastDueDays().toString()); + + assertThat(actualDelinquencyRangeValue).isNotNull(); + assertThat(delinquentAmount).isNotNull(); + assertThat(delinquent.getDelinquentDays()).isNotNull(); + assertThat(delinquent.getPastDueDays()).isNotNull(); + List actualValuesList; + if (expectedValuesList.size() == 6) { + actualValuesList = List.of(actualDelinquencyRangeValue, delinquentAmount, + delinquent.getDelinquentDate() == null ? "null" : FORMATTER.format(delinquent.getDelinquentDate()), + delinquent.getPastDueDate() == null ? "null" : FORMATTER.format(delinquent.getPastDueDate()), + delinquent.getDelinquentDays().toString(), delinquent.getPastDueDays().toString()); + } else { + actualValuesList = List.of(actualDelinquencyRangeValue, delinquentAmount, + delinquent.getDelinquentDate() == null ? "null" : FORMATTER.format(delinquent.getDelinquentDate()), + delinquent.getDelinquentDays().toString(), delinquent.getPastDueDays().toString()); + } assertThat(actualValuesList).as(ErrorMessageHelper.wrongValueInLoanLevelDelinquencyData(actualValuesList, expectedValuesList)) .isEqualTo(expectedValuesList); } @Then("Loan has the following LOAN level next payment due data:") - public void loanNextPaymentDataCheck(DataTable table) throws IOException { + public void loanNextPaymentDataCheck(DataTable table) { PostLoansResponse loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE); - long loanId = loanResponse.getLoanId(); + Long loanId = loanResponse.getLoanId(); List expectedValuesList = table.asLists().get(1); - DelinquencyRange expectedDelinquencyRange = DelinquencyRange.valueOf(expectedValuesList.get(0)); + DelinquencyRange expectedDelinquencyRange = DelinquencyRange.valueOf(expectedValuesList.getFirst()); String expectedDelinquencyRangeValue = expectedDelinquencyRange.getValue(); expectedValuesList.set(0, expectedDelinquencyRangeValue); @@ -543,9 +548,9 @@ public void loanNextPaymentDataCheck(DataTable table) throws IOException { } @Then("Loan has the following INSTALLMENT level delinquency data:") - public void loanDelinquencyInstallmentLevelDataCheck(DataTable table) throws IOException { + public void loanDelinquencyInstallmentLevelDataCheck(DataTable table) { PostLoansResponse loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE); - long loanId = loanResponse.getLoanId(); + Long loanId = loanResponse.getLoanId(); GetLoansLoanIdResponse loanDetails = ok(() -> fineractClient.loans().retrieveLoan(loanId, Map.of("associations", "collection"))); List installmentLevelDelinquency = loanDetails.getDelinquent() @@ -572,9 +577,9 @@ public void loanDelinquencyInstallmentLevelDataCheck(DataTable table) throws IOE } @Then("Loan Delinquency pause periods has the following data:") - public void loanDelinquencyPauseDataCheck(DataTable table) throws IOException { + public void loanDelinquencyPauseDataCheck(DataTable table) { PostLoansResponse loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE); - long loanId = loanResponse.getLoanId(); + Long loanId = loanResponse.getLoanId(); List> expectedData = table.asLists(); GetLoansLoanIdResponse loanDetails = ok(() -> fineractClient.loans().retrieveLoan(loanId, Map.of("associations", "collection"))); @@ -598,9 +603,9 @@ public void loanDelinquencyPauseDataCheck(DataTable table) throws IOException { } @Then("Loan details delinquent.nextPaymentDueDate will be {string}") - public void nextPaymentDueDateCheck(String expectedDate) throws IOException { + public void nextPaymentDueDateCheck(String expectedDate) { PostLoansResponse loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE); - long loanId = loanResponse.getLoanId(); + Long loanId = loanResponse.getLoanId(); GetLoansLoanIdResponse loanDetails = ok(() -> fineractClient.loans().retrieveLoan(loanId, Map.of("associations", "collection"))); String actualDate = FORMATTER.format(loanDetails.getDelinquent().getNextPaymentDueDate()); @@ -611,7 +616,7 @@ public void nextPaymentDueDateCheck(String expectedDate) throws IOException { @Then("LoanAccountDelinquencyRangeDataV1 has delinquencyRange field with value {string}") public void checkDelinquencyRangeInEvent(String expectedRange) { PostLoansResponse loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE); - long loanId = loanResponse.getLoanId(); + Long loanId = loanResponse.getLoanId(); DelinquencyRange expectedDelinquencyRange = DelinquencyRange.valueOf(expectedRange); String expectedDelinquencyRangeValue = expectedDelinquencyRange.getValue(); @@ -627,9 +632,9 @@ public void checkDelinquencyRangeInEvent(String expectedRange) { } @Then("LoanDelinquencyRangeChangeBusinessEvent has the same Delinquency range, date and amount as in LoanDetails on both loan- and installment-level") - public void checkDelinquencyRangeInEvent() throws IOException { + public void checkDelinquencyRangeInEvent() { PostLoansResponse loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE); - long loanId = loanResponse.getLoanId(); + Long loanId = loanResponse.getLoanId(); GetLoansLoanIdResponse loanDetails = ok(() -> fineractClient.loans().retrieveLoan(loanId, Map.of("associations", "collection"))); DelinquencyRangeData delinquencyRange = loanDetails.getDelinquencyRange(); @@ -699,18 +704,17 @@ public void checkDelinquencyRangeInEvent() throws IOException { } @Then("In Loan details delinquent.lastRepaymentAmount is {int} EUR with lastRepaymentDate {string}") - public void delinquentLastRepaymentAmountCheck(int expectedLastRepaymentAmount, String expectedLastRepaymentDate) throws IOException { + public void delinquentLastRepaymentAmountCheck(int expectedLastRepaymentAmount, String expectedLastRepaymentDate) { PostLoansResponse loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE); - long loanId = loanResponse.getLoanId(); + Long loanId = loanResponse.getLoanId(); GetLoansLoanIdResponse loanDetails = ok(() -> fineractClient.loans().retrieveLoan(loanId, Map.of("associations", "collection"))); - Double expectedLastRepaymentAmount1 = Double.valueOf(expectedLastRepaymentAmount); Double actualLastRepaymentAmount = loanDetails.getDelinquent().getLastRepaymentAmount().doubleValue(); String actualLastRepaymentDate = FORMATTER.format(loanDetails.getDelinquent().getLastRepaymentDate()); assertThat(actualLastRepaymentAmount)// - .as(ErrorMessageHelper.wrongDataInDelinquentLastRepaymentAmount(actualLastRepaymentAmount, expectedLastRepaymentAmount1))// + .as(ErrorMessageHelper.wrongDataInDelinquentLastRepaymentAmount(actualLastRepaymentAmount, actualLastRepaymentAmount))// .isEqualTo(expectedLastRepaymentAmount);// assertThat(actualLastRepaymentDate)// .as(ErrorMessageHelper.wrongDataInDelinquentLastRepaymentDate(actualLastRepaymentDate, expectedLastRepaymentDate))// @@ -751,7 +755,7 @@ private void errorMessageAssertationFeign(long loanId, PostLoansDelinquencyActio @Then("LoanDelinquencyRangeChangeBusinessEvent is created") public void checkLoanDelinquencyRangeChangeBusinessEventCreated() { PostLoansResponse loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE); - long loanId = loanResponse.getLoanId(); + Long loanId = loanResponse.getLoanId(); eventAssertion.assertEventRaised(LoanDelinquencyRangeChangeEvent.class, loanId); } diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/LoanStepDef.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/LoanStepDef.java index ecfd1bd8890..c7c1887d7f6 100644 --- a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/LoanStepDef.java +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/LoanStepDef.java @@ -1622,6 +1622,7 @@ public void disburseLoan(String actualDisbursementDate, String transactionAmount .isEqualTo(statusExpected);// eventCheckHelper.disburseLoanEventCheck(loanId); eventCheckHelper.loanDisbursalTransactionEventCheck(loanDisburseResponse); + eventCheckHelper.loanBalanceChangedEventCheck(loanId); } @And("Admin successfully add disbursement detail to the loan on {string} with {double} EUR transaction amount") diff --git a/fineract-e2e-tests-runner/src/test/resources/features/LoanDelinquency.feature b/fineract-e2e-tests-runner/src/test/resources/features/LoanDelinquency.feature index b3444a6d681..6204135ce61 100644 --- a/fineract-e2e-tests-runner/src/test/resources/features/LoanDelinquency.feature +++ b/fineract-e2e-tests-runner/src/test/resources/features/LoanDelinquency.feature @@ -2176,3 +2176,96 @@ Feature: LoanDelinquency And Loan has the following LOAN level delinquency data: | classification | delinquentAmount | delinquentDate | delinquentDays | pastDueDays | | RANGE_90 | 666.68 | 06 February 2025 | 98 | 103 | + + @TestRailId:C4619 + Scenario: Verify that pastDueDate is returned correctly for overdue loan + When Admin sets the business date to "01 October 2023" + When Admin creates a client with random data + When Admin creates a fully customized loan with the following data: + | LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy | + | LP2_DOWNPAYMENT_ADV_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL_INSTALLMENT_LEVEL_DELINQUENCY | 01 October 2023 | 1000 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION | + And Admin successfully approves the loan on "01 October 2023" with "1000" amount and expected disbursement date on "01 October 2023" + When Admin successfully disburse the loan on "01 October 2023" with "1000" EUR transaction amount + When Admin sets the business date to "10 October 2023" + When Admin runs inline COB job for Loan + Then Loan has the following LOAN level delinquency data: + | classification | delinquentAmount | delinquentDate | pastDueDate | delinquentDays | pastDueDays | + | RANGE_3 | 250.0 | 04 October 2023 | 01 October 2023 | 6 | 9 | + + @TestRailId:C4620 + Scenario: Verify that pastDueDate is null when loan has no overdue + When Admin sets the business date to "01 October 2023" + When Admin creates a client with random data + When Admin creates a fully customized loan with the following data: + | LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy | + | LP2_DOWNPAYMENT_ADV_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL_INSTALLMENT_LEVEL_DELINQUENCY | 01 October 2023 | 1000 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION | + And Admin successfully approves the loan on "01 October 2023" with "1000" amount and expected disbursement date on "01 October 2023" + When Admin successfully disburse the loan on "01 October 2023" with "1000" EUR transaction amount + And Customer makes "AUTOPAY" repayment on "01 October 2023" with 250 EUR transaction amount + When Admin runs inline COB job for Loan + Then Loan has the following LOAN level delinquency data: + | classification | delinquentAmount | delinquentDate | pastDueDate | delinquentDays | pastDueDays | + | NO_DELINQUENCY | 0.0 | null | null | 0 | 0 | + + @TestRailId:C4621 + Scenario: Verify that pastDueDate equals chargeback date when chargeback creates overdue + When Admin sets the business date to "01 October 2023" + When Admin creates a client with random data + When Admin creates a fully customized loan with the following data: + | LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy | + | LP2_DOWNPAYMENT_ADV_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL_INSTALLMENT_LEVEL_DELINQUENCY | 01 October 2023 | 1000 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION | + And Admin successfully approves the loan on "01 October 2023" with "1000" amount and expected disbursement date on "01 October 2023" + When Admin successfully disburse the loan on "01 October 2023" with "1000" EUR transaction amount + And Customer makes "AUTOPAY" repayment on "01 October 2023" with 250 EUR transaction amount + When Admin sets the business date to "05 October 2023" + When Admin makes "REPAYMENT_ADJUSTMENT_CHARGEBACK" chargeback with 250 EUR transaction amount + When Admin sets the business date to "10 October 2023" + When Admin runs inline COB job for Loan + Then Loan has the following LOAN level delinquency data: + | classification | delinquentAmount | delinquentDate | pastDueDate | delinquentDays | pastDueDays | + | RANGE_1 | 250.0 | 08 October 2023 | 05 October 2023 | 2 | 5 | + + @TestRailId:C4622 + Scenario: Verify that pastDueDate is present in LoanBalanceChangedBusinessEvent for overdue loan + When Admin sets the business date to "01 October 2023" + When Admin creates a client with random data + When Admin creates a fully customized loan with the following data: + | LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy | + | LP2_ADV_CUSTOM_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL | 01 October 2023 | 1000 | 7 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION | + And Admin successfully approves the loan on "01 October 2023" with "1000" amount and expected disbursement date on "01 October 2023" + When Admin successfully disburse the loan on "01 October 2023" with "1000" EUR transaction amount + When Admin sets the business date to "20 October 2023" + And Create an interest pause period with start date "25 October 2023" and end date "30 October 2023" + And LoanBalanceChangedBusinessEvent has pastDueDate "2023-10-16" + + @TestRailId:C4623 + Scenario: Verify that pastDueDate is null in LoanBalanceChangedBusinessEvent when loan has no overdue + When Admin sets the business date to "01 October 2023" + When Admin creates a client with random data + When Admin creates a fully customized loan with the following data: + | LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy | + | LP2_ADV_CUSTOM_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL | 01 October 2023 | 1000 | 7 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION | + And Admin successfully approves the loan on "01 October 2023" with "1000" amount and expected disbursement date on "01 October 2023" + When Admin successfully disburse the loan on "01 October 2023" with "1000" EUR transaction amount + When Admin sets the business date to "16 October 2023" + And Customer makes "AUTOPAY" repayment on "16 October 2023" with 335.28 EUR transaction amount + When Admin sets the business date to "20 October 2023" + And Create an interest pause period with start date "25 October 2023" and end date "30 October 2023" + And LoanBalanceChangedBusinessEvent has pastDueDate "null" + + @TestRailId:C4624 + Scenario: Verify that pastDueDate is present in LoanBalanceChangedBusinessEvent and equals chargeback date when chargeback creates overdue + When Admin sets the business date to "01 October 2023" + When Admin creates a client with random data + When Admin creates a fully customized loan with the following data: + | LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy | + | LP2_ADV_CUSTOM_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL | 01 October 2023 | 1000 | 7 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION | + And Admin successfully approves the loan on "01 October 2023" with "1000" amount and expected disbursement date on "01 October 2023" + When Admin successfully disburse the loan on "01 October 2023" with "1000" EUR transaction amount + When Admin sets the business date to "16 October 2023" + And Customer makes "AUTOPAY" repayment on "16 October 2023" with 335.28 EUR transaction amount + When Admin sets the business date to "20 October 2023" + When Admin makes "REPAYMENT_ADJUSTMENT_CHARGEBACK" chargeback with 335.28 EUR transaction amount + When Admin sets the business date to "25 October 2023" + And Create an interest pause period with start date "25 October 2023" and end date "30 October 2023" + Then LoanBalanceChangedBusinessEvent has pastDueDate "2023-10-20" diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/delinquency/service/LoanDelinquencyDomainServiceImpl.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/delinquency/service/LoanDelinquencyDomainServiceImpl.java index e4fc1eb187f..53d3f244d75 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/delinquency/service/LoanDelinquencyDomainServiceImpl.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/delinquency/service/LoanDelinquencyDomainServiceImpl.java @@ -126,6 +126,7 @@ public CollectionData getOverdueCollectionData(final Loan loan, final List installmentsCollection = new HashMap<>(); @@ -240,11 +240,12 @@ public void test_ApplyDelinquencyTagToLoan_ExecutesDelinquencyApplication_InTheR LocalDate overDueSinceDate = DateUtils.getBusinessLocalDate().minusDays(2); LoanScheduleDelinquencyData loanScheduleDelinquencyData = new LoanScheduleDelinquencyData(1L, overDueSinceDate, 1L, loanForProcessing); - CollectionData collectionData = new CollectionData(zeroAmount, zeroAmount, 2L, null, zeroAmount, 2L, overDueSinceDate, zeroAmount, - null, null, null, null, null, null, zeroAmount, zeroAmount, zeroAmount, zeroAmount); + CollectionData collectionData = new CollectionData(zeroAmount, zeroAmount, 2L, overDueSinceDate, null, zeroAmount, 2L, + overDueSinceDate, zeroAmount, null, null, null, null, null, null, zeroAmount, zeroAmount, zeroAmount, zeroAmount); - CollectionData installmentCollectionData = new CollectionData(zeroAmount, zeroAmount, 2L, null, zeroAmount, 2L, overDueSinceDate, - installmentPrincipalAmount, null, null, null, null, null, null, zeroAmount, zeroAmount, zeroAmount, zeroAmount); + CollectionData installmentCollectionData = new CollectionData(zeroAmount, zeroAmount, 2L, overDueSinceDate, null, zeroAmount, 2L, + overDueSinceDate, installmentPrincipalAmount, null, null, null, null, null, null, zeroAmount, zeroAmount, zeroAmount, + zeroAmount); Map installmentsCollection = new HashMap<>(); installmentsCollection.put(1L, installmentCollectionData); @@ -369,11 +370,12 @@ public void givenLoanAccountWithOverdueInstallmentAndEnableInstallmentThenDelinq LoanScheduleDelinquencyData loanScheduleDelinquencyData = new LoanScheduleDelinquencyData(1L, overDueSinceDate, 1L, loanForProcessing); - CollectionData collectionData = new CollectionData(zeroAmount, zeroAmount, 2L, null, zeroAmount, 2L, overDueSinceDate, zeroAmount, - null, null, null, null, null, null, zeroAmount, zeroAmount, zeroAmount, zeroAmount); + CollectionData collectionData = new CollectionData(zeroAmount, zeroAmount, 2L, overDueSinceDate, null, zeroAmount, 2L, + overDueSinceDate, zeroAmount, null, null, null, null, null, null, zeroAmount, zeroAmount, zeroAmount, zeroAmount); - CollectionData installmentCollectionData = new CollectionData(zeroAmount, zeroAmount, 2L, null, zeroAmount, 2L, overDueSinceDate, - installmentPrincipalAmount, null, null, null, null, null, null, zeroAmount, zeroAmount, zeroAmount, zeroAmount); + CollectionData installmentCollectionData = new CollectionData(zeroAmount, zeroAmount, 2L, overDueSinceDate, null, zeroAmount, 2L, + overDueSinceDate, installmentPrincipalAmount, null, null, null, null, null, null, zeroAmount, zeroAmount, zeroAmount, + zeroAmount); Map installmentsCollection = new HashMap<>(); installmentsCollection.put(1L, installmentCollectionData); @@ -446,11 +448,12 @@ public void givenLoanAccountWithOverdueInstallmentAndEnableInstallmentThenDelinq LocalDate overDueSinceDate = DateUtils.getBusinessLocalDate().minusDays(29); LoanScheduleDelinquencyData loanScheduleDelinquencyData = new LoanScheduleDelinquencyData(1L, overDueSinceDate, 1L, loanForProcessing); - CollectionData collectionData = new CollectionData(zeroAmount, zeroAmount, 29L, null, zeroAmount, 29L, overDueSinceDate, zeroAmount, - null, null, null, null, null, null, zeroAmount, zeroAmount, zeroAmount, zeroAmount); + CollectionData collectionData = new CollectionData(zeroAmount, zeroAmount, 29L, overDueSinceDate, null, zeroAmount, 29L, + overDueSinceDate, zeroAmount, null, null, null, null, null, null, zeroAmount, zeroAmount, zeroAmount, zeroAmount); - CollectionData installmentCollectionData = new CollectionData(zeroAmount, zeroAmount, 29L, null, zeroAmount, 29L, overDueSinceDate, - installmentPrincipalAmount, null, null, null, null, null, null, zeroAmount, zeroAmount, zeroAmount, zeroAmount); + CollectionData installmentCollectionData = new CollectionData(zeroAmount, zeroAmount, 29L, overDueSinceDate, null, zeroAmount, 29L, + overDueSinceDate, installmentPrincipalAmount, null, null, null, null, null, null, zeroAmount, zeroAmount, zeroAmount, + zeroAmount); Map installmentsCollection = new HashMap<>(); installmentsCollection.put(1L, installmentCollectionData); @@ -534,14 +537,14 @@ public void givenLoanAccountWithOverdueInstallmentsAndEnableInstallmentThenDelin LocalDate overDueSinceDate = DateUtils.getBusinessLocalDate().minusDays(29); LoanScheduleDelinquencyData loanScheduleDelinquencyData = new LoanScheduleDelinquencyData(1L, overDueSinceDate, 1L, loanForProcessing); - CollectionData collectionData = new CollectionData(zeroAmount, zeroAmount, 29L, null, zeroAmount, 29L, overDueSinceDate, zeroAmount, - null, null, null, null, null, null, zeroAmount, zeroAmount, zeroAmount, zeroAmount); + CollectionData collectionData = new CollectionData(zeroAmount, zeroAmount, 29L, overDueSinceDate, null, zeroAmount, 29L, + overDueSinceDate, zeroAmount, null, null, null, null, null, null, zeroAmount, zeroAmount, zeroAmount, zeroAmount); - CollectionData installmentCollectionData_1 = new CollectionData(zeroAmount, zeroAmount, 29L, null, zeroAmount, 29L, - overDueSinceDate, installmentPrincipalAmount, null, null, null, null, null, null, zeroAmount, zeroAmount, zeroAmount, + CollectionData installmentCollectionData_1 = new CollectionData(zeroAmount, zeroAmount, 29L, overDueSinceDate, null, zeroAmount, + 29L, overDueSinceDate, installmentPrincipalAmount, null, null, null, null, null, null, zeroAmount, zeroAmount, zeroAmount, zeroAmount); - CollectionData installmentCollectionData_2 = new CollectionData(zeroAmount, zeroAmount, 0L, null, zeroAmount, 0L, null, + CollectionData installmentCollectionData_2 = new CollectionData(zeroAmount, zeroAmount, 0L, null, null, zeroAmount, 0L, null, installmentPrincipalAmount, null, null, null, null, null, null, zeroAmount, zeroAmount, zeroAmount, zeroAmount); Map installmentsCollection = new HashMap<>(); diff --git a/fineract-provider/src/test/java/org/apache/fineract/portfolio/deliquency/LoanDelinquencyDomainServiceTest.java b/fineract-provider/src/test/java/org/apache/fineract/portfolio/deliquency/LoanDelinquencyDomainServiceTest.java index cd213cbf469..112d9b984f2 100644 --- a/fineract-provider/src/test/java/org/apache/fineract/portfolio/deliquency/LoanDelinquencyDomainServiceTest.java +++ b/fineract-provider/src/test/java/org/apache/fineract/portfolio/deliquency/LoanDelinquencyDomainServiceTest.java @@ -139,6 +139,7 @@ public void givenLoanAccountWithoutOverdueThenCalculateDelinquentData() { // then assertEquals(0L, collectionData.getDelinquentDays()); assertEquals(null, collectionData.getDelinquentDate()); + assertEquals(null, collectionData.getPastDueDate()); assertEquals(collectionData.getDelinquentDays(), collectionData.getPastDueDays()); } @@ -170,6 +171,7 @@ public void givenLoanAccountWithOverdueThenCalculateDelinquentData() { // then assertEquals(daysDiff, collectionData.getDelinquentDays()); assertEquals(dueDate, collectionData.getDelinquentDate()); + assertEquals(dueDate, collectionData.getPastDueDate()); assertEquals(collectionData.getDelinquentDays(), collectionData.getPastDueDays()); } @@ -206,6 +208,7 @@ public void givenLoanAccountWithoutOverdueWithChargebackThenCalculateDelinquentD // then assertEquals(0L, collectionData.getDelinquentDays()); assertEquals(null, collectionData.getDelinquentDate()); + assertEquals(null, collectionData.getPastDueDate()); assertEquals(collectionData.getDelinquentDays(), collectionData.getPastDueDays()); } @@ -248,10 +251,12 @@ public void givenLoanInstallmentWithOverdueEnableInstallmentDelinquencyThenCalcu assertEquals(daysDiff, loanCollectionData.getDelinquentDays()); assertEquals(dueDate, loanCollectionData.getDelinquentDate()); + assertEquals(dueDate, loanCollectionData.getPastDueDate()); assertEquals(loanCollectionData.getDelinquentDays(), loanCollectionData.getPastDueDays()); assertEquals(daysDiff, installmentCollectionData.getDelinquentDays()); assertEquals(dueDate, installmentCollectionData.getDelinquentDate()); + assertEquals(dueDate, installmentCollectionData.getPastDueDate()); assertEquals(installmentCollectionData.getDelinquentDays(), installmentCollectionData.getPastDueDays()); } @@ -301,11 +306,13 @@ public void givenLoanInstallmentWithoutOverdueWithChargebackAndEnableInstallment assertEquals(daysDiff, loanCollectionData.getDelinquentDays()); assertEquals(transactionDate, loanCollectionData.getDelinquentDate()); + assertEquals(transactionDate, loanCollectionData.getPastDueDate()); assertEquals(loanCollectionData.getDelinquentDays(), loanCollectionData.getPastDueDays()); // then assertEquals(daysDiff, installmentCollectionData.getDelinquentDays()); assertEquals(transactionDate, installmentCollectionData.getDelinquentDate()); + assertEquals(transactionDate, installmentCollectionData.getPastDueDate()); assertEquals(installmentCollectionData.getDelinquentDays(), installmentCollectionData.getPastDueDays()); assertEquals(0, principal.compareTo(installmentCollectionData.getDelinquentAmount())); @@ -353,6 +360,7 @@ public void givenPausePeriodThenInstallmentDelinquentDaysOnlyIncludeOverlap() { CollectionData loanCollectionData = collectionData.getLoanCollectionData(); assertEquals(35L, loanCollectionData.getDelinquentDays()); assertEquals(LocalDate.of(2022, 1, 16), loanCollectionData.getDelinquentDate()); + assertEquals(LocalDate.of(2022, 1, 16), loanCollectionData.getPastDueDate()); Map installments = collectionData.getLoanInstallmentsCollectionData(); assertNotNull(installments); @@ -408,6 +416,7 @@ public void givenMultipleInstallmentsAndPauseThenDelinquencyDaysDistributePerIns CollectionData loanCollectionData = delinquencyData.getLoanCollectionData(); assertEquals(16L, loanCollectionData.getDelinquentDays()); assertEquals(LocalDate.of(2022, 1, 10), loanCollectionData.getDelinquentDate()); + assertEquals(LocalDate.of(2022, 1, 10), loanCollectionData.getPastDueDate()); Map installmentData = delinquencyData.getLoanInstallmentsCollectionData(); assertEquals(3, installmentData.size());