Skip to content

Commit 8a4a1d0

Browse files
committed
FINERACT-2455: WC - Delinquency Management - Delinquency days & Delinquency Bucket handling
- create SetWorkingCapitalLoanDelinquencyTagsBusinessStep - create ENABLE_INSTANT_DELINQUENCY_CALCULATION - Delinquency Classification for Working Capital Loans
1 parent 59cf29a commit 8a4a1d0

File tree

32 files changed

+1380
-22
lines changed

32 files changed

+1380
-22
lines changed

fineract-core/src/main/java/org/apache/fineract/infrastructure/configuration/api/GlobalConfigurationConstants.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ public final class GlobalConfigurationConstants {
8181
public static final String ALLOWED_LOAN_STATUSES_OF_DELAYED_SETTLEMENT_FOR_EXTERNAL_ASSET_TRANSFER = "allowed-loan-statuses-of-delayed-settlement-for-external-asset-transfer";
8282
public static final String MAX_LOGIN_RETRY_ATTEMPTS = "max-login-retry-attempts";
8383
public static final String ENABLE_ORIGINATOR_CREATION_DURING_LOAN_APPLICATION = "enable-originator-creation-during-loan-application";
84+
public static final String ENABLE_INSTANT_DELINQUENCY_CALCULATION = "enable-instant-delinquency-calculation";
8485
public static final String PASSWORD_REUSE_CHECK_HISTORY_COUNT = "password-reuse-check-history-count";
8586
public static final String FORCE_WITHDRAWAL_ON_SAVINGS_ACCOUNT = "allow-force-withdrawal-on-savings-account";
8687
public static final String FORCE_WITHDRAWAL_ON_SAVINGS_ACCOUNT_LIMIT = "force-withdrawal-on-savings-account-limit";

fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/WorkingCapitalLoanAccountStepDef.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,9 @@ public void checkDisbursementData(String actualDisbursementDate, String transact
646646
.orElseThrow(() -> new RuntimeException(""));
647647
String formattedDate = disbursementDetails.getActualDisbursementDate().format(FORMATTER);
648648
assertThat(formattedDate).isEqualTo(actualDisbursementDate);
649+
log.info(
650+
"Verified working capital loan disbursement was successful for loan ID: {} with actual disbursement date: {} and amount: {}",
651+
loanId, actualDisbursementDate, disbursementDetails.getActualAmount());
649652
assertThat(disbursementDetails.getActualAmount().compareTo(new BigDecimal(transactionAmount))).isEqualTo(0);
650653
}
651654

@@ -863,6 +866,12 @@ private void createWorkingCapitalLoanAccount(final List<String> loanData) {
863866
final PostWorkingCapitalLoansResponse response = ok(
864867
() -> fineractClient.workingCapitalLoans().submitWorkingCapitalLoanApplication(loansRequest));
865868
testContext().set(TestContextKey.LOAN_CREATE_RESPONSE, response);
869+
List<Long> loanIds = testContext().get(TestContextKey.WC_LOAN_IDS);
870+
if (loanIds == null) {
871+
loanIds = new ArrayList<>();
872+
testContext().set(TestContextKey.WC_LOAN_IDS, loanIds);
873+
}
874+
loanIds.add(response.getLoanId());
866875
log.info("Working Capital Loan created with ID: {}", response.getLoanId());
867876
}
868877

fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/WorkingCapitalStepDef.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import io.cucumber.java.en.Then;
2727
import io.cucumber.java.en.When;
2828
import java.math.BigDecimal;
29+
import java.time.LocalDate;
2930
import java.util.List;
3031
import java.util.Map;
3132
import java.util.UUID;
@@ -38,13 +39,16 @@
3839
import org.apache.fineract.client.models.DeleteWorkingCapitalLoanProductsProductIdResponse;
3940
import org.apache.fineract.client.models.GetConfigurableAttributes;
4041
import org.apache.fineract.client.models.GetPaymentAllocation;
42+
import org.apache.fineract.client.models.GetWorkingCapitalLoanDelinquencyRangeScheduleTagHistoryResponse;
4143
import org.apache.fineract.client.models.GetWorkingCapitalLoanProductsProductIdResponse;
4244
import org.apache.fineract.client.models.GetWorkingCapitalLoanProductsResponse;
4345
import org.apache.fineract.client.models.GetWorkingCapitalLoanProductsTemplateResponse;
46+
import org.apache.fineract.client.models.InternalWorkingCapitalLoanPaymentRequest;
4447
import org.apache.fineract.client.models.PostAllowAttributeOverrides;
4548
import org.apache.fineract.client.models.PostWorkingCapitalLoanProductsRequest;
4649
import org.apache.fineract.client.models.PostWorkingCapitalLoanProductsRequest.AccountingRuleEnum;
4750
import org.apache.fineract.client.models.PostWorkingCapitalLoanProductsResponse;
51+
import org.apache.fineract.client.models.PostWorkingCapitalLoansResponse;
4852
import org.apache.fineract.client.models.PutWorkingCapitalLoanProductsProductIdRequest;
4953
import org.apache.fineract.client.models.PutWorkingCapitalLoanProductsProductIdResponse;
5054
import org.apache.fineract.client.models.StringEnumOptionData;
@@ -59,6 +63,7 @@
5963
import org.apache.fineract.test.stepdef.AbstractStepDef;
6064
import org.apache.fineract.test.support.TestContextKey;
6165
import org.assertj.core.api.SoftAssertions;
66+
import org.junit.jupiter.api.Assertions;
6267

6368
@Slf4j
6469
@RequiredArgsConstructor
@@ -719,6 +724,40 @@ private void assertGLAccountMappingId(final Map<String, ?> mappings, final Strin
719724
assertions.assertAll();
720725
}
721726

727+
@When("make Internal Payment {string} on {string}")
728+
public void internalPayWCLoan(String amount, String transactionDate) {
729+
PostWorkingCapitalLoansResponse workingCapitalLoanProductsResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
730+
Long resourceId = workingCapitalLoanProductsResponse.getResourceId();
731+
fineractFeignClient.workingCapitalLoans().payment(resourceId, new InternalWorkingCapitalLoanPaymentRequest()
732+
.amount(BigDecimal.valueOf(Double.parseDouble(amount))).transactionDate(LocalDate.parse(transactionDate)));
733+
}
734+
735+
@Then("Delinquency Tag History for WC Loan has lines:")
736+
public void checkDelinquencyHistory(final DataTable table) {
737+
PostWorkingCapitalLoansResponse workingCapitalLoanProductsResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
738+
Long resourceId = workingCapitalLoanProductsResponse.getResourceId();
739+
List<GetWorkingCapitalLoanDelinquencyRangeScheduleTagHistoryResponse> actualLines = ok(
740+
() -> fineractFeignClient.workingCapitalLoans().getDelinquencyRangeScheduleTagHistoryById(resourceId));
741+
log.info("Loan {}", actualLines);
742+
List<List<String>> rows = table.asLists();
743+
Assertions.assertEquals(rows.size() - 1, actualLines.size());
744+
for (int i = 0; i < rows.size() - 1; i++) {
745+
GetWorkingCapitalLoanDelinquencyRangeScheduleTagHistoryResponse actual = actualLines.get(i);
746+
Assertions.assertNotNull(actual);
747+
List<String> expected = rows.get(i + 1);
748+
Assertions.assertEquals(expected.get(0), actual.getPeriodNumber() != null ? actual.getPeriodNumber().toString() : null);
749+
Assertions.assertEquals(expected.get(1), actual.getAddedOnDate() != null ? actual.getAddedOnDate().toString() : null);
750+
Assertions.assertEquals(expected.get(2), actual.getLiftedOnDate() != null ? actual.getLiftedOnDate().toString() : null);
751+
752+
Assertions.assertNotNull(actual.getDelinquencyRange());
753+
Assertions.assertEquals(expected.get(3), actual.getDelinquencyRange().getClassification());
754+
Assertions.assertEquals(expected.get(4), actual.getDelinquencyRange().getMinimumAgeDays() == null ? null
755+
: actual.getDelinquencyRange().getMinimumAgeDays().toString());
756+
Assertions.assertEquals(expected.get(5), actual.getDelinquencyRange().getMaximumAgeDays() == null ? null
757+
: actual.getDelinquencyRange().getMaximumAgeDays().toString());
758+
}
759+
}
760+
722761
public PostWorkingCapitalLoanProductsResponse createWorkingCapitalLoanProduct(
723762
PostWorkingCapitalLoanProductsRequest workingCapitalProductRequest) {
724763
String workingCapitalProductName = workingCapitalProductRequest.getName();

fineract-e2e-tests-runner/src/test/resources/features/WorkingCapitalDelinquency.feature

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,3 +182,104 @@ Feature: Working Capital Delinquency
182182
#TODO check amounts in case of repayment
183183
@Skip @TestRailId:tempX
184184
Scenario: Verify working capital loan delinquency range schedule - UCXX: delinquency range schedule with repayments
185+
186+
187+
188+
@TestRailId:CXXXXX1
189+
Scenario: Working Capital Loan COB + Delinquency UC1
190+
When Admin sets the business date to "01 January 2026"
191+
And Admin creates a client with random data
192+
And Admin creates a working capital loan with the following data:
193+
| LoanProduct | submittedOnDate | expectedDisbursementDate | principalAmount | totalPayment | periodPaymentRate | discount |
194+
| WCLP | 01 January 2026 | 01 January 2026 | 100 | 100 | 1 | 0 |
195+
Then Working capital loan creation was successful
196+
And Working capital loan account has the correct data:
197+
| product.name | submittedOnDate | expectedDisbursementDate | status | principal | approvedPrincipal | totalPayment | periodPaymentRate | discount |
198+
| WCLP | 2026-01-01 | 2026-01-01 | Submitted and pending approval | 100.0 | 0.0 | 100.0 | 1.0 | 0.0 |
199+
Then Admin successfully approves the working capital loan on "01 January 2026" with "100" amount and expected disbursement date on "01 January 2026"
200+
Then Admin successfully disburse the Working Capital loan on "01 January 2026" with "100" EUR transaction amount
201+
Then Working Capital loan status will be "ACTIVE"
202+
Then Verify Working Capital loan disbursement was successful on "01 January 2026" with "100" EUR transaction amount
203+
And Working capital loan account has the correct data:
204+
| product.name | submittedOnDate | expectedDisbursementDate | status | principal | approvedPrincipal | totalPayment | periodPaymentRate | discount |
205+
| WCLP | 2026-01-01 | 2026-01-01 | Active | 100.0 | 100.0 | 100.0 | 1.0 | 0.0 |
206+
When Admin sets the business date to "02 January 2026"
207+
And Admin runs inline COB job for Working Capital Loan
208+
## Should be ok
209+
Then Delinquency Tag History for WC Loan has lines:
210+
| rangeId | getAddedOnDate | liftedOnDate | classification | minimumAgeDays | maximumAgeDays |
211+
212+
When Admin sets the business date to "30 January 2026"
213+
And Admin runs inline COB job for Working Capital Loan
214+
## Should be ok
215+
Then Delinquency Tag History for WC Loan has lines:
216+
| rangeId | getAddedOnDate | liftedOnDate | classification | minimumAgeDays | maximumAgeDays |
217+
218+
When Admin sets the business date to "31 January 2026"
219+
And Admin runs inline COB job for Working Capital Loan
220+
## Should be delinquent for 1 days and Delinquency range 1
221+
Then Delinquency Tag History for WC Loan has lines:
222+
| rangeId | getAddedOnDate | liftedOnDate | classification | minimumAgeDays | maximumAgeDays |
223+
| 1 | 2026-01-31 | | D00 | 1 | 30 |
224+
225+
When Admin sets the business date to "01 April 2026"
226+
And Admin runs inline COB job for Working Capital Loan
227+
Then Delinquency Tag History for WC Loan has lines:
228+
| rangeId | getAddedOnDate | liftedOnDate | classification | minimumAgeDays | maximumAgeDays |
229+
| 1 | 2026-04-01 | | D60 | 61 | 90 |
230+
| 2 | 2026-04-01 | | D30 | 31 | 60 |
231+
| 3 | 2026-04-01 | | D00 | 1 | 30 |
232+
| 1 | 2026-03-02 | | D30 | 31 | 60 |
233+
| 2 | 2026-03-02 | | D00 | 1 | 30 |
234+
| 1 | 2026-01-31 | | D00 | 1 | 30 |
235+
236+
@TestRailId:CXXXXX2
237+
Scenario: Working Capital Loan COB + Delinquency UC2
238+
When Admin sets the business date to "01 December 2020"
239+
And Admin creates a client with random data
240+
And Admin creates a working capital loan with the following data:
241+
| LoanProduct | submittedOnDate | expectedDisbursementDate | principalAmount | totalPayment | periodPaymentRate | discount |
242+
| WCLP | 01 December 2020 | 01 December 2020 | 1800 | 1800 | 1 | 0 |
243+
Then Working capital loan creation was successful
244+
And Working capital loan account has the correct data:
245+
| product.name | submittedOnDate | expectedDisbursementDate | status | principal | approvedPrincipal | totalPayment | periodPaymentRate | discount |
246+
| WCLP | 2020-12-01 | 2020-12-01 | Submitted and pending approval | 1800.0 | 0.0 | 1800.0 | 1.0 | 0.0 |
247+
Then Admin successfully approves the working capital loan on "01 December 2020" with "1800" amount and expected disbursement date on "01 December 2020"
248+
Then Admin successfully disburse the Working Capital loan on "01 December 2020" with "1800" EUR transaction amount
249+
Then Working Capital loan status will be "ACTIVE"
250+
Then Verify Working Capital loan disbursement was successful on "01 December 2020" with "1800" EUR transaction amount
251+
And Working capital loan account has the correct data:
252+
| product.name | submittedOnDate | expectedDisbursementDate | status | principal | approvedPrincipal | totalPayment | periodPaymentRate | discount |
253+
| WCLP |2020-12-01 | 2020-12-01 | Active | 1800.0 | 1800.0 | 1800.0 | 1.0 | 0.0 |
254+
When Admin sets the business date to "02 December 2020"
255+
And Admin runs inline COB job for Working Capital Loan
256+
## Should be ok
257+
When Admin sets the business date to "05 December 2020"
258+
And Admin runs inline COB job for Working Capital Loan
259+
When make Internal Payment "30.0" on "2020-12-05"
260+
261+
Then Delinquency Tag History for WC Loan has lines:
262+
| rangeId | getAddedOnDate | liftedOnDate | classification | minimumAgeDays | maximumAgeDays |
263+
264+
When Admin sets the business date to "01 January 2021"
265+
And Admin runs inline COB job for Working Capital Loan
266+
## Should be ok
267+
Then Delinquency Tag History for WC Loan has lines:
268+
| rangeId | getAddedOnDate | liftedOnDate | classification | minimumAgeDays | maximumAgeDays |
269+
| 1 | 2020-12-31 | | D00 | 1 | 30 |
270+
271+
When Admin sets the business date to "06 January 2021"
272+
And Admin runs inline COB job for Working Capital Loan
273+
Then Delinquency Tag History for WC Loan has lines:
274+
| rangeId | getAddedOnDate | liftedOnDate | classification | minimumAgeDays | maximumAgeDays |
275+
| 1 | 2020-12-31 | | D00 | 1 | 30 |
276+
When make Internal Payment "54.0" on "2021-01-06"
277+
Then Delinquency Tag History for WC Loan has lines:
278+
| rangeId | getAddedOnDate | liftedOnDate | classification | minimumAgeDays | maximumAgeDays |
279+
| 1 | 2020-12-31 | 2021-01-06 | D00 | 1 | 30 |
280+
281+
When Admin sets the business date to "07 January 2021"
282+
And Admin runs inline COB job for Working Capital Loan
283+
Then Delinquency Tag History for WC Loan has lines:
284+
| rangeId | getAddedOnDate | liftedOnDate | classification | minimumAgeDays | maximumAgeDays |
285+
| 1 | 2020-12-31 | 2021-01-06 | D00 | 1 | 30 |

fineract-e2e-tests-runner/src/test/resources/features/WorkingCapitalProductLoanAccount.feature

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1226,4 +1226,3 @@ Feature: WorkingCapitalLoanAccount
12261226
| WCLP_DISCOUNT | 2026-01-01 | 2026-01-01 | Active | 145.0 | 100.0 | 100.0 | 1.0 | 45.0 |
12271227
# --- add discount after disbursement is forbidden as discount is already added --- #
12281228
Then Update discount with "10" amount on Working Capital loan account failed due to already added discount before disbursement
1229-

fineract-e2e-tests-runner/src/test/resources/features/WorkingCapital_COB.feature

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ Feature: Working Capital COB Job
88
Scenario: Verify WC COB job registration, default business step, and scheduler metadata
99
Then Admin checks that configured business jobs contain "WORKING_CAPITAL_LOAN_CLOSE_OF_BUSINESS"
1010
Then Admin verifies configured business steps for "WORKING_CAPITAL_LOAN_CLOSE_OF_BUSINESS" match:
11-
| stepName | order |
12-
| DUMMY_BUSINESS_STEP | 1 |
13-
| WC_DELINQUENCY_RANGE_SCHEDULE | 2 |
11+
| stepName | order |
12+
| DUMMY_BUSINESS_STEP | 1 |
13+
| WC_DELINQUENCY_RANGE_SCHEDULE | 2 |
14+
| WC_LOAN_DELINQUENCY_CLASSIFICATION | 3 |
1415
Then Admin verifies scheduler job "WC_COB" has display name "Working Capital Loan COB"
1516
Then Admin verifies scheduler job "WC_COB" has active status "false"
1617

0 commit comments

Comments
 (0)