From cd830b674cc9bbcafdd15959fb9a8f6e962415f1 Mon Sep 17 00:00:00 2001 From: Jose Alberto Hernandez Date: Fri, 24 Apr 2026 14:36:44 -0500 Subject: [PATCH 1/2] FINERACT-2421: Working Capital Delinquency pause different calculation --- .../WorkingCapitalDelinquencyPause.feature | 54 +++++++++++++++++++ ...anDelinquencyRangeScheduleServiceImpl.java | 25 +++++++++ 2 files changed, 79 insertions(+) diff --git a/fineract-e2e-tests-runner/src/test/resources/features/WorkingCapitalDelinquencyPause.feature b/fineract-e2e-tests-runner/src/test/resources/features/WorkingCapitalDelinquencyPause.feature index de997a39bf8..48ae140e6ac 100644 --- a/fineract-e2e-tests-runner/src/test/resources/features/WorkingCapitalDelinquencyPause.feature +++ b/fineract-e2e-tests-runner/src/test/resources/features/WorkingCapitalDelinquencyPause.feature @@ -200,6 +200,60 @@ Feature: Working Capital Delinquency Pause | 1 | 2026-01-01 | 2026-03-12 | 270.0 | 0.0 | 270.0 | false | 270.0 | 3 | | 2 | 2026-03-13 | 2026-04-11 | 270.0 | 0.0 | 270.0 | null | null | null | + @TestRailId:C74485-1 + Scenario: Verify working capital loan delinquency pause - UC6: delinquency pause in the middle of first period with pause overlapping to second period + When Admin sets the business date to "01 January 2026" + And Admin creates a client with random data + And Admin creates a working capital loan with the following data: + | LoanProduct | submittedOnDate | expectedDisbursementDate | principalAmount | totalPayment | periodPaymentRate | discount | + | WCLP | 01 January 2026 | 01 January 2026 | 9000 | 100000 | 18 | 0 | + And Admin successfully approves the working capital loan on "01 January 2026" with "9000" amount and expected disbursement date on "01 January 2026" + Then Working capital loan approval was successful + And Working capital loan account has the correct data: + | product.name | submittedOnDate | expectedDisbursementDate | status | principal | approvedPrincipal | totalPayment | periodPaymentRate | discount | + | WCLP | 2026-01-01 | 2026-01-01 | Approved | 9000.0 | 9000.0 | 100000.0 | 18.0 | 0.0 | + When Admin successfully disburse the Working Capital loan on "01 January 2026" with "9000" EUR transaction amount + Then Working Capital loan status will be "ACTIVE" + And Verify Working Capital loan disbursement was successful on "01 January 2026" with "9000" EUR transaction amount + And Working capital loan account has the correct data: + | product.name | submittedOnDate | expectedDisbursementDate | status | principal | approvedPrincipal | totalPayment | periodPaymentRate | discount | + | WCLP | 2026-01-01 | 2026-01-01 | Active | 9000.0 | 9000.0 | 100000.0 | 18.0 | 0.0 | + When Admin runs inline COB job for Working Capital Loan by loanId + Then Working Capital loan delinquency range schedule has the following data: + | periodNumber | fromDate | toDate | expectedAmount | paidAmount | outstandingAmount | minPaymentCriteriaMet | delinquentAmount | delinquentDays | + | 1 | 2026-01-01 | 2026-01-30 | 270.0 | 0.0 | 270.0 | null | null | null | + When Admin sets the business date to "15 January 2026" + And Admin runs inline COB job for Working Capital Loan by loanId + And Admin initiate a Working Capital loan delinquency pause with startDate "15 January 2026" and endDate "25 February 2026" + Then Working Capital loan delinquency action has the following data: + | action | startDate | endDate | + | PAUSE | 2026-01-15 | 2026-02-25 | + And Working Capital loan delinquency range schedule has the following data: + | periodNumber | fromDate | toDate | expectedAmount | paidAmount | outstandingAmount | minPaymentCriteriaMet | delinquentAmount | delinquentDays | + | 1 | 2026-01-01 | 2026-03-12 | 270.0 | 0.0 | 270.0 | null | null | null | + And Admin initiate a Working Capital loan delinquency pause with startDate "16 April 2026" and endDate "23 April 2026" + When Admin sets the business date to "13 March 2026" + And Admin runs inline COB job for Working Capital Loan by loanId + And Admin initiate a Working Capital loan delinquency pause with startDate "13 March 2026" and endDate "17 March 2026" + When Admin sets the business date to "20 March 2026" + And Admin runs inline COB job for Working Capital Loan by loanId + Then Working Capital loan delinquency action has the following data: + | action | startDate | endDate | + | PAUSE | 2026-01-15 | 2026-02-25 | + | PAUSE | 2026-04-16 | 2026-04-23 | + | PAUSE | 2026-03-13 | 2026-03-17 | + And Working Capital loan delinquency range schedule has the following data: + | periodNumber | fromDate | toDate | expectedAmount | paidAmount | outstandingAmount | minPaymentCriteriaMet | delinquentAmount | delinquentDays | + | 1 | 2026-01-01 | 2026-03-12 | 270.0 | 0.0 | 270.0 | false | 270.0 | 8 | + | 2 | 2026-03-13 | 2026-04-15 | 270.0 | 0.0 | 270.0 | null | null | null | + When Admin sets the business date to "30 April 2026" + And Admin runs inline COB job for Working Capital Loan by loanId + Then Working Capital loan delinquency range schedule has the following data: + | periodNumber | fromDate | toDate | expectedAmount | paidAmount | outstandingAmount | minPaymentCriteriaMet | delinquentAmount | delinquentDays | + | 1 | 2026-01-01 | 2026-03-12 | 270.0 | 0.0 | 270.0 | false | 270.0 | 49 | + | 2 | 2026-03-13 | 2026-04-15 | 270.0 | 0.0 | 270.0 | false | 270.0 | 15 | + | 3 | 2026-04-16 | 2026-05-22 | 270.0 | 0.0 | 270.0 | null | null | null | + @TestRailId:C74486 Scenario: Verify working capital loan delinquency pause - UC7: backdated delinquency pause to an already evaluated period results an error (Negative) When Admin sets the business date to "01 January 2026" diff --git a/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/WorkingCapitalLoanDelinquencyRangeScheduleServiceImpl.java b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/WorkingCapitalLoanDelinquencyRangeScheduleServiceImpl.java index f785d45ada3..9119991a19c 100644 --- a/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/WorkingCapitalLoanDelinquencyRangeScheduleServiceImpl.java +++ b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/WorkingCapitalLoanDelinquencyRangeScheduleServiceImpl.java @@ -112,6 +112,8 @@ public void generateNextPeriodIfNeeded(WorkingCapitalLoan loan, LocalDate busine final DelinquencyFrequencyType effectiveFreqType = latestReschedule.map(WorkingCapitalLoanDelinquencyAction::getFrequencyType) .orElse(rule.getFrequencyType()); + final List recordedPauses = findAllPauseActions(loan.getId()); + WorkingCapitalLoanDelinquencyRangeSchedule latestPeriod = latestPeriodOpt.get(); while (!latestPeriod.getToDate().isAfter(businessDate)) { final LocalDate newFromDate = latestPeriod.getToDate().plusDays(1); @@ -128,6 +130,8 @@ public void generateNextPeriodIfNeeded(WorkingCapitalLoan loan, LocalDate busine nextPeriod.setOutstandingAmount(expectedAmount); nextPeriod.setMinPaymentCriteriaMet(null); + applyRecordedPauses(nextPeriod, recordedPauses); + latestPeriod = loanDelinquencyRangeScheduleRepository.saveAndFlush(nextPeriod); log.debug("Generated next delinquency range schedule period {} for WC loan {}", nextPeriod.getPeriodNumber(), loan.getId()); } @@ -260,6 +264,27 @@ private Optional findLatestRescheduleAction return loanDelinquencyActionRepository.findTopByWorkingCapitalLoanIdAndActionOrderByIdDesc(loanId, DelinquencyAction.RESCHEDULE); } + private List findAllPauseActions(final Long loanId) { + return loanDelinquencyActionRepository.findByWorkingCapitalLoanIdOrderById(loanId).stream() + .filter(a -> DelinquencyAction.PAUSE.equals(a.getAction())).toList(); + } + + private void applyRecordedPauses(final WorkingCapitalLoanDelinquencyRangeSchedule period, + final List pauseActions) { + for (final WorkingCapitalLoanDelinquencyAction pause : pauseActions) { + final LocalDate pauseStart = pause.getStartDate(); + final LocalDate pauseEnd = pause.getEndDate(); + // Apply only if the pause overlaps this period's date range + if (pauseEnd.isAfter(period.getFromDate()) && !pauseStart.isAfter(period.getToDate())) { + final long pauseDays = ChronoUnit.DAYS.between(pauseStart, pauseEnd); + period.setToDate(period.getToDate().plusDays(pauseDays)); + if (period.getFromDate().isAfter(pauseStart)) { + period.setFromDate(period.getFromDate().plusDays(pauseDays)); + } + } + } + } + @Override public void rescheduleMinimumPayment(final WorkingCapitalLoan loan, final WorkingCapitalLoanDelinquencyAction rescheduleAction) { final LocalDate businessDate = DateUtils.getBusinessLocalDate(); From 35419821765373ca3112fd029d38070dc98cc4ec Mon Sep 17 00:00:00 2001 From: MarianaDmytrivBinariks Date: Mon, 27 Apr 2026 11:31:47 +0300 Subject: [PATCH 2/2] FINERACT-2421: e2e test scenarios for delinquency pause --- .../WorkingCapitalDelinquencyPause.feature | 91 ++++++++++++++++++- 1 file changed, 89 insertions(+), 2 deletions(-) diff --git a/fineract-e2e-tests-runner/src/test/resources/features/WorkingCapitalDelinquencyPause.feature b/fineract-e2e-tests-runner/src/test/resources/features/WorkingCapitalDelinquencyPause.feature index 48ae140e6ac..55870d6eba2 100644 --- a/fineract-e2e-tests-runner/src/test/resources/features/WorkingCapitalDelinquencyPause.feature +++ b/fineract-e2e-tests-runner/src/test/resources/features/WorkingCapitalDelinquencyPause.feature @@ -200,8 +200,8 @@ Feature: Working Capital Delinquency Pause | 1 | 2026-01-01 | 2026-03-12 | 270.0 | 0.0 | 270.0 | false | 270.0 | 3 | | 2 | 2026-03-13 | 2026-04-11 | 270.0 | 0.0 | 270.0 | null | null | null | - @TestRailId:C74485-1 - Scenario: Verify working capital loan delinquency pause - UC6: delinquency pause in the middle of first period with pause overlapping to second period + @TestRailId:C78810 + Scenario: Verify working capital loan delinquency pause - UC6.1: delinquency pause in the middle of first period with future pauses overlapping to a few periods When Admin sets the business date to "01 January 2026" And Admin creates a client with random data And Admin creates a working capital loan with the following data: @@ -235,6 +235,15 @@ Feature: Working Capital Delinquency Pause When Admin sets the business date to "13 March 2026" And Admin runs inline COB job for Working Capital Loan by loanId And Admin initiate a Working Capital loan delinquency pause with startDate "13 March 2026" and endDate "17 March 2026" + Then Working Capital loan delinquency action has the following data: + | action | startDate | endDate | + | PAUSE | 2026-01-15 | 2026-02-25 | + | PAUSE | 2026-04-16 | 2026-04-23 | + | PAUSE | 2026-03-13 | 2026-03-17 | + And Working Capital loan delinquency range schedule has the following data: + | periodNumber | fromDate | toDate | expectedAmount | paidAmount | outstandingAmount | minPaymentCriteriaMet | delinquentAmount | delinquentDays | + | 1 | 2026-01-01 | 2026-03-12 | 270.0 | 0.0 | 270.0 | false | 270.0 | 1 | + | 2 | 2026-03-13 | 2026-04-15 | 270.0 | 0.0 | 270.0 | null | null | null | When Admin sets the business date to "20 March 2026" And Admin runs inline COB job for Working Capital Loan by loanId Then Working Capital loan delinquency action has the following data: @@ -254,6 +263,84 @@ Feature: Working Capital Delinquency Pause | 2 | 2026-03-13 | 2026-04-15 | 270.0 | 0.0 | 270.0 | false | 270.0 | 15 | | 3 | 2026-04-16 | 2026-05-22 | 270.0 | 0.0 | 270.0 | null | null | null | + @TestRailId:C78811 + Scenario: Verify working capital loan delinquency pause - UC6.2: delinquency pause in the middle of first period with pauses overlapping to a few periods + When Admin sets the business date to "01 January 2026" + And Admin creates a client with random data + And Admin creates a working capital loan with the following data: + | LoanProduct | submittedOnDate | expectedDisbursementDate | principalAmount | totalPayment | periodPaymentRate | discount | + | WCLP | 01 January 2026 | 01 January 2026 | 9000 | 100000 | 18 | 0 | + And Admin successfully approves the working capital loan on "01 January 2026" with "9000" amount and expected disbursement date on "01 January 2026" + Then Working capital loan approval was successful + And Working capital loan account has the correct data: + | product.name | submittedOnDate | expectedDisbursementDate | status | principal | approvedPrincipal | totalPayment | periodPaymentRate | discount | + | WCLP | 2026-01-01 | 2026-01-01 | Approved | 9000.0 | 9000.0 | 100000.0 | 18.0 | 0.0 | + When Admin successfully disburse the Working Capital loan on "01 January 2026" with "9000" EUR transaction amount + Then Working Capital loan status will be "ACTIVE" + And Verify Working Capital loan disbursement was successful on "01 January 2026" with "9000" EUR transaction amount + And Working capital loan account has the correct data: + | product.name | submittedOnDate | expectedDisbursementDate | status | principal | approvedPrincipal | totalPayment | periodPaymentRate | discount | + | WCLP | 2026-01-01 | 2026-01-01 | Active | 9000.0 | 9000.0 | 100000.0 | 18.0 | 0.0 | + When Admin runs inline COB job for Working Capital Loan by loanId + Then Working Capital loan delinquency range schedule has the following data: + | periodNumber | fromDate | toDate | expectedAmount | paidAmount | outstandingAmount | minPaymentCriteriaMet | delinquentAmount | delinquentDays | + | 1 | 2026-01-01 | 2026-01-30 | 270.0 | 0.0 | 270.0 | null | null | null | + When Admin sets the business date to "15 January 2026" + And Admin runs inline COB job for Working Capital Loan by loanId + And Admin initiate a Working Capital loan delinquency pause with startDate "15 January 2026" and endDate "25 February 2026" + Then Working Capital loan delinquency action has the following data: + | action | startDate | endDate | + | PAUSE | 2026-01-15 | 2026-02-25 | + And Working Capital loan delinquency range schedule has the following data: + | periodNumber | fromDate | toDate | expectedAmount | paidAmount | outstandingAmount | minPaymentCriteriaMet | delinquentAmount | delinquentDays | + | 1 | 2026-01-01 | 2026-03-12 | 270.0 | 0.0 | 270.0 | null | null | null | + When Admin sets the business date to "13 March 2026" + And Admin runs inline COB job for Working Capital Loan by loanId + Then Working Capital loan delinquency action has the following data: + | action | startDate | endDate | + | PAUSE | 2026-01-15 | 2026-02-25 | + And Working Capital loan delinquency range schedule has the following data: + | periodNumber | fromDate | toDate | expectedAmount | paidAmount | outstandingAmount | minPaymentCriteriaMet | delinquentAmount | delinquentDays | + | 1 | 2026-01-01 | 2026-03-12 | 270.0 | 0.0 | 270.0 | false | 270.0 | 1 | + | 2 | 2026-03-13 | 2026-04-11 | 270.0 | 0.0 | 270.0 | null | null | null | + And Admin initiate a Working Capital loan delinquency pause with startDate "13 March 2026" and endDate "17 March 2026" + Then Working Capital loan delinquency action has the following data: + | action | startDate | endDate | + | PAUSE | 2026-01-15 | 2026-02-25 | + | PAUSE | 2026-03-13 | 2026-03-17 | + When Admin sets the business date to "20 March 2026" + And Admin runs inline COB job for Working Capital Loan by loanId + Then Working Capital loan delinquency action has the following data: + | action | startDate | endDate | + | PAUSE | 2026-01-15 | 2026-02-25 | + | PAUSE | 2026-03-13 | 2026-03-17 | + And Working Capital loan delinquency range schedule has the following data: + | periodNumber | fromDate | toDate | expectedAmount | paidAmount | outstandingAmount | minPaymentCriteriaMet | delinquentAmount | delinquentDays | + | 1 | 2026-01-01 | 2026-03-12 | 270.0 | 0.0 | 270.0 | false | 270.0 | 8 | + | 2 | 2026-03-13 | 2026-04-15 | 270.0 | 0.0 | 270.0 | null | null | null | + When Admin sets the business date to "30 April 2026" + And Admin runs inline COB job for Working Capital Loan by loanId + Then Working Capital loan delinquency action has the following data: + | action | startDate | endDate | + | PAUSE | 2026-01-15 | 2026-02-25 | + | PAUSE | 2026-03-13 | 2026-03-17 | + Then Working Capital loan delinquency range schedule has the following data: + | periodNumber | fromDate | toDate | expectedAmount | paidAmount | outstandingAmount | minPaymentCriteriaMet | delinquentAmount | delinquentDays | + | 1 | 2026-01-01 | 2026-03-12 | 270.0 | 0.0 | 270.0 | false | 270.0 | 49 | + | 2 | 2026-03-13 | 2026-04-15 | 270.0 | 0.0 | 270.0 | false | 270.0 | 15 | + | 3 | 2026-04-16 | 2026-05-15 | 270.0 | 0.0 | 270.0 | null | null | null | + And Admin initiate a Working Capital loan delinquency pause with startDate "16 April 2026" and endDate "23 April 2026" + Then Working Capital loan delinquency action has the following data: + | action | startDate | endDate | + | PAUSE | 2026-01-15 | 2026-02-25 | + | PAUSE | 2026-03-13 | 2026-03-17 | + | PAUSE | 2026-04-16 | 2026-04-23 | + Then Working Capital loan delinquency range schedule has the following data: + | periodNumber | fromDate | toDate | expectedAmount | paidAmount | outstandingAmount | minPaymentCriteriaMet | delinquentAmount | delinquentDays | + | 1 | 2026-01-01 | 2026-03-12 | 270.0 | 0.0 | 270.0 | false | 270.0 | 49 | + | 2 | 2026-03-13 | 2026-04-15 | 270.0 | 0.0 | 270.0 | false | 270.0 | 15 | + | 3 | 2026-04-16 | 2026-05-22 | 270.0 | 0.0 | 270.0 | null | null | null | + @TestRailId:C74486 Scenario: Verify working capital loan delinquency pause - UC7: backdated delinquency pause to an already evaluated period results an error (Negative) When Admin sets the business date to "01 January 2026"