You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by ad...@apache.org on 2026/10/19 12:58:12 UTC

(fineract) branch maintenance/1.16.0 updated (f2040893cf -> 6da8a989b3)

This is an automated email from the ASF dual-hosted git repository.

adamsaghy pushed a change to branch maintenance/1.16.0
in repository https://gitbox.apache.org/repos/asf/fineract.git


    from f2040893cf FINERACT-2684: Update logback configuration to remove deprecated if condition
     new 85397461e8 FINERACT-2455: WC - Past due days calculation bug
     new 6da8a989b3 FINERACT-2455: updated e2e scenario for validation of WC - Past due days calculation bug

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../features/working-capital-loan-start-dates.adoc |   2 +-
 .../stepdef/common/GlobalConfigurationStepDef.java |   6 +
 .../features/WorkingCapitalDelinquency.feature     | 277 +++++++++++++++++++++
 .../api/WorkingCapitalLoanApiResourceSwagger.java  |   1 +
 ...italLoanDelinquencyRangeScheduleRepository.java |  17 +-
 ...italLoanApplicationReadPlatformServiceImpl.java |   8 +-
 ...italLoanDelinquencyReadPlatformServiceImpl.java |   2 +-
 ...LoanDelinquencyReadPlatformServiceImplTest.java |  13 +
 8 files changed, 319 insertions(+), 7 deletions(-)


(fineract) 01/02: FINERACT-2455: WC - Past due days calculation bug

Posted by ad...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

adamsaghy pushed a commit to branch maintenance/1.16.0
in repository https://gitbox.apache.org/repos/asf/fineract.git

commit 85397461e8fec744b60de46bc0bf4f91708023ac
Author: mariiaKraievska <ri...@gmail.com>
AuthorDate: Mon Oct 12 13:07:34 2026 +0300

    FINERACT-2455: WC - Past due days calculation bug
    
    (cherry picked from commit c7d74f71a58bb6bc2f681a4e03dc2343f8c5c352)
---
 .../features/working-capital-loan-start-dates.adoc |  2 +-
 .../features/WorkingCapitalDelinquency.feature     | 85 ++++++++++++++++++++++
 .../api/WorkingCapitalLoanApiResourceSwagger.java  |  1 +
 ...italLoanDelinquencyRangeScheduleRepository.java | 17 ++++-
 ...italLoanApplicationReadPlatformServiceImpl.java |  8 +-
 ...italLoanDelinquencyReadPlatformServiceImpl.java |  2 +-
 ...LoanDelinquencyReadPlatformServiceImplTest.java | 13 ++++
 7 files changed, 121 insertions(+), 7 deletions(-)

diff --git a/fineract-doc/src/docs/en/chapters/features/working-capital-loan-start-dates.adoc b/fineract-doc/src/docs/en/chapters/features/working-capital-loan-start-dates.adoc
index bd718f20ae..bc2a6a2070 100644
--- a/fineract-doc/src/docs/en/chapters/features/working-capital-loan-start-dates.adoc
+++ b/fineract-doc/src/docs/en/chapters/features/working-capital-loan-start-dates.adoc
@@ -158,7 +158,7 @@ Every WC loan business event carries the same `breach` and `delinquency` blocks
 
 === Delinquency Start Date
 
-* `delinquencyStartDate` is the `fromDate` of the earliest `m_wc_loan_delinquency_range_schedule` row with `min_payment_criteria_met = false` (`findTopByLoanIdAndMinPaymentCriteriaMetFalseOrderByFromDateAsc`), with no grace arithmetic applied.
+* `delinquencyStartDate` is the `fromDate` of the earliest still-open past delinquency-range-schedule period that already carries a positive classified `delinquentDays` (`findOpenPastDuePeriodsOrderByFromDateAsc`: `min_payment_criteria_met` is `null` or `false`, `reset = false`, `to_date` on or before the business date), with no grace arithmetic applied. `null` is included because instant classification can mark a period delinquent before COB evaluates `min_payment_criteria_met`.
 * The delinquency schedule itself is anchored according to `delinquencyStartType`: `LOAN_CREATION` anchors the first period on the loan submitted-on date, while `DISBURSEMENT` (or an unset type) anchors it on the actual disbursement date. This anchor is resolved in `WorkingCapitalLoanDelinquencyRangeScheduleServiceImpl.generateInitialPeriod`.
 * When no delinquent period exists, `delinquencyStartDate` is `null`.
 
diff --git a/fineract-e2e-tests-runner/src/test/resources/features/WorkingCapitalDelinquency.feature b/fineract-e2e-tests-runner/src/test/resources/features/WorkingCapitalDelinquency.feature
index 8f733a2dc3..bb99eb4df7 100644
--- a/fineract-e2e-tests-runner/src/test/resources/features/WorkingCapitalDelinquency.feature
+++ b/fineract-e2e-tests-runner/src/test/resources/features/WorkingCapitalDelinquency.feature
@@ -1430,3 +1430,88 @@ Feature: Working Capital Delinquency
       | 1            | 2026-02-13  |              | D00            | 1              | 30             |
     Then Admin closes the Working Capital loan with all obligations met with a full repayment on "13 February 2026"
 
+  Scenario: Verify pastDueDays when instant classification runs before COB evaluates minPaymentCriteriaMet
+    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 Product with delinquencyGraceDays 3 and delinquencyStartType "DISBURSEMENT" for loan test
+    And Admin creates a working capital loan with the grace days product and the following data:
+      | submittedOnDate | expectedDisbursementDate | principalAmount | totalPaymentVolume | periodPaymentRate |
+      | 01 January 2026 | 01 January 2026          | 9000.0          | 100000.0           | 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"
+    And Admin successfully disburse the Working Capital loan on "01 January 2026" with "9000" EUR transaction amount
+    # Period 1 toDate includes the 3-day grace window (2026-02-02). Advance past it without COB so minPaymentCriteriaMet stays NULL.
+    When Admin sets the business date to "03 February 2026"
+    And Customer makes repayment on "03 February 2026" with 0.01 transaction amount on Working Capital loan
+    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-02-02 | 270.0          | 0.01       | 269.99            | null                  | 269.99           | 1              |
+    And Delinquency Tag History for Working Capital loan has lines:
+      | periodNumber | addedOnDate | liftedOnDate | classification | minimumAgeDays | maximumAgeDays |
+      | 1            | 2026-02-03  |              | D00            | 1              | 30             |
+    And Working capital loan details has the following field values:
+      | delinquent.delinquentAmount   | 269.99     |
+      | delinquent.pastDueDays        | 1          |
+      | delinquencyStartDate          | 2026-01-01 |
+      | delinquencyEffectiveStartDate | 2026-01-04 |
+      | summary.overdueSinceDate      | 2026-02-02 |
+    Then Admin closes the Working Capital loan with a full repayment on "03 February 2026"
+
+  Scenario: Verify pastDueDays for backdated disbursement and partial repayment without COB
+    When Admin sets the business date to "01 April 2026"
+    And Admin creates a client with random data
+    And Admin creates a Working Capital Loan Product with delinquencyGraceDays 3 and delinquencyStartType "DISBURSEMENT" for loan test
+    And Admin creates a working capital loan with the grace days product and the following data:
+      | submittedOnDate | expectedDisbursementDate | principalAmount | totalPaymentVolume | periodPaymentRate |
+      | 01 January 2026 | 01 January 2026          | 9000.0          | 100000.0           | 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"
+    And Admin successfully disburse the Working Capital loan on "01 January 2026" with "9000" EUR transaction amount
+    # Partial repayment 50 days backdated: does not meet the minimum, triggers instant classification while minPaymentCriteriaMet stays NULL
+    And Customer makes repayment on "10 February 2026" with 0.01 transaction amount on Working Capital loan
+    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-02-02 | 270.0          | 0.01       | 269.99            | null                  | 269.99           | 58             |
+    And Delinquency Tag History for Working Capital loan has lines:
+      | periodNumber | addedOnDate | liftedOnDate | classification | minimumAgeDays | maximumAgeDays |
+      | 1            | 2026-04-01  |              | D30            | 31             | 60             |
+    And Working capital loan details has the following field values:
+      | delinquent.delinquentAmount   | 269.99     |
+      | delinquent.pastDueDays        | 58         |
+      | delinquencyStartDate          | 2026-01-01 |
+      | delinquencyEffectiveStartDate | 2026-01-04 |
+      | summary.overdueSinceDate      | 2026-02-02 |
+    Then Admin closes the Working Capital loan with a full repayment on "01 April 2026"
+
+  Scenario: Verify pastDueDays after first COB and subsequent partial repayment on next day
+    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 Product with delinquencyGraceDays 3 and delinquencyStartType "DISBURSEMENT" for loan test
+    And Admin creates a working capital loan with the grace days product and the following data:
+      | submittedOnDate | expectedDisbursementDate | principalAmount | totalPaymentVolume | periodPaymentRate |
+      | 01 January 2026 | 01 January 2026          | 9000.0          | 100000.0           | 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"
+    And Admin successfully disburse the Working Capital loan on "01 January 2026" with "9000" EUR transaction amount
+    When Admin sets the business date to "03 February 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-02-02 | 270.0          | 0.0        | 270.0             | false                 | 270.0            | 1              |
+      | 2            | 2026-02-03 | 2026-03-04 | 270.0          | 0.0        | 270.0             | null                  | null             | null           |
+    And Working capital loan details has the following field values:
+      | delinquent.delinquentAmount   | 270.0      |
+      | delinquent.pastDueDays        | 1          |
+      | delinquencyStartDate          | 2026-01-01 |
+      | delinquencyEffectiveStartDate | 2026-01-04 |
+      | summary.overdueSinceDate      | 2026-02-02 |
+    When Admin sets the business date to "04 February 2026"
+    And Customer makes repayment on "04 February 2026" with 0.01 transaction amount on Working Capital loan
+    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-02-02 | 270.0          | 0.01       | 269.99            | false                 | 269.99           | 2              |
+      | 2            | 2026-02-03 | 2026-03-04 | 270.0          | 0.0        | 270.0             | null                  | null             | null           |
+    And Working capital loan details has the following field values:
+      | delinquent.delinquentAmount   | 269.99     |
+      | delinquent.pastDueDays        | 2          |
+      | delinquencyStartDate          | 2026-01-01 |
+      | delinquencyEffectiveStartDate | 2026-01-04 |
+      | summary.overdueSinceDate      | 2026-02-02 |
+    Then Admin closes the Working Capital loan with a full repayment on "04 February 2026"
diff --git a/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/api/WorkingCapitalLoanApiResourceSwagger.java b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/api/WorkingCapitalLoanApiResourceSwagger.java
index d819cdb77f..90d435393a 100644
--- a/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/api/WorkingCapitalLoanApiResourceSwagger.java
+++ b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/api/WorkingCapitalLoanApiResourceSwagger.java
@@ -396,6 +396,7 @@ public final class WorkingCapitalLoanApiResourceSwagger {
             public BigDecimal totalExpectedRepayment;
             public BigDecimal totalRepayment;
             public BigDecimal totalOutstanding;
+            public LocalDate overdueSinceDate;
         }
 
         @Schema(description = "Working Capital Delinquency Collection Data")
diff --git a/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/repository/WorkingCapitalLoanDelinquencyRangeScheduleRepository.java b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/repository/WorkingCapitalLoanDelinquencyRangeScheduleRepository.java
index 60f834c1a0..3fcf40fa6e 100644
--- a/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/repository/WorkingCapitalLoanDelinquencyRangeScheduleRepository.java
+++ b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/repository/WorkingCapitalLoanDelinquencyRangeScheduleRepository.java
@@ -100,7 +100,22 @@ public interface WorkingCapitalLoanDelinquencyRangeScheduleRepository
 
     List<WorkingCapitalLoanDelinquencyRangeSchedule> findByLoanIdAndToDateIsBeforeOrderByPeriodNumberAsc(Long loanId, LocalDate toDate);
 
-    Optional<WorkingCapitalLoanDelinquencyRangeSchedule> findTopByLoanIdAndMinPaymentCriteriaMetFalseOrderByFromDateAsc(Long loanId);
+    /**
+     * Still-open past periods that already carry a positive classified {@code delinquentDays} value, earliest first.
+     * Includes {@code minPaymentCriteriaMet IS NULL} because instant classification can populate delinquent days before
+     * COB evaluates the period. Reset periods are excluded: they are skipped by classification and must not drive
+     * pastDueDays / delinquency start dates.
+     */
+    @Query("""
+            SELECT s FROM WorkingCapitalLoanDelinquencyRangeSchedule s
+            WHERE s.loan.id = :loanId
+              AND s.toDate <= :businessDate
+              AND (s.minPaymentCriteriaMet IS NULL OR s.minPaymentCriteriaMet = FALSE)
+              AND s.reset = false
+              AND s.delinquentDays > 0
+            ORDER BY s.fromDate ASC""")
+    List<WorkingCapitalLoanDelinquencyRangeSchedule> findOpenPastDuePeriodsOrderByFromDateAsc(@Param("loanId") Long loanId,
+            @Param("businessDate") LocalDate businessDate);
 
     List<WorkingCapitalLoanDelinquencyRangeSchedule> findByLoanIdAndResetIsNotAndToDateBeforeOrderByPeriodNumberAsc(Long id, Boolean reset,
             LocalDate startDate);
diff --git a/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/WorkingCapitalLoanApplicationReadPlatformServiceImpl.java b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/WorkingCapitalLoanApplicationReadPlatformServiceImpl.java
index 90abc20b48..145b36aa06 100644
--- a/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/WorkingCapitalLoanApplicationReadPlatformServiceImpl.java
+++ b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/WorkingCapitalLoanApplicationReadPlatformServiceImpl.java
@@ -244,10 +244,10 @@ public class WorkingCapitalLoanApplicationReadPlatformServiceImpl implements Wor
             data.setBreachEffectiveStartDate(resolveBreachEffectiveStartDate(period, data.getBreachGraceDays()));
         });
 
-        // delinquencyStartDate: fromDate of the earliest delinquent period. The delinquency range schedule bakes the
-        // delinquency grace days into the toDate of its first period, so the fromDate is the raw anchor date.
-        delinquencyRangeScheduleRepository.findTopByLoanIdAndMinPaymentCriteriaMetFalseOrderByFromDateAsc(loan.getId())
-                .ifPresent(period -> {
+        // Same open-past-due definition as pastDueDays: instant classification can mark a period delinquent while
+        // minPaymentCriteriaMet is still NULL (before COB evaluates it), so FALSE-only would leave these empty.
+        delinquencyRangeScheduleRepository.findOpenPastDuePeriodsOrderByFromDateAsc(loan.getId(), ThreadLocalContextUtil.getBusinessDate())
+                .stream().findFirst().ifPresent(period -> {
                     data.setDelinquencyStartDate(period.getFromDate());
                     data.setDelinquencyEffectiveStartDate(resolveDelinquencyEffectiveStartDate(period, data.getDelinquencyGraceDays()));
                     Optional.ofNullable(data.getSummary()).ifPresent(summary -> summary.setOverdueSinceDate(period.getToDate()));
diff --git a/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/WorkingCapitalLoanDelinquencyReadPlatformServiceImpl.java b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/WorkingCapitalLoanDelinquencyReadPlatformServiceImpl.java
index b9dc99a9a0..cc95832abe 100644
--- a/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/WorkingCapitalLoanDelinquencyReadPlatformServiceImpl.java
+++ b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/WorkingCapitalLoanDelinquencyReadPlatformServiceImpl.java
@@ -76,7 +76,7 @@ public class WorkingCapitalLoanDelinquencyReadPlatformServiceImpl implements Wor
             template.setDelinquentPrincipal(delinquentAmount);
         });
 
-        delinquencyRangeScheduleRepository.findTopByLoanIdAndMinPaymentCriteriaMetFalseOrderByFromDateAsc(loanId)
+        delinquencyRangeScheduleRepository.findOpenPastDuePeriodsOrderByFromDateAsc(loanId, businessDate).stream().findFirst()
                 .map(WorkingCapitalLoanDelinquencyRangeSchedule::getDelinquentDays).ifPresent(template::setPastDueDays);
 
         template.setInstallmentLevelDelinquency(list);
diff --git a/fineract-working-capital-loan/src/test/java/org/apache/fineract/portfolio/workingcapitalloan/service/WorkingCapitalLoanDelinquencyReadPlatformServiceImplTest.java b/fineract-working-capital-loan/src/test/java/org/apache/fineract/portfolio/workingcapitalloan/service/WorkingCapitalLoanDelinquencyReadPlatformServiceImplTest.java
index bf119f55c4..af1b8706ca 100644
--- a/fineract-working-capital-loan/src/test/java/org/apache/fineract/portfolio/workingcapitalloan/service/WorkingCapitalLoanDelinquencyReadPlatformServiceImplTest.java
+++ b/fineract-working-capital-loan/src/test/java/org/apache/fineract/portfolio/workingcapitalloan/service/WorkingCapitalLoanDelinquencyReadPlatformServiceImplTest.java
@@ -204,6 +204,19 @@ public class WorkingCapitalLoanDelinquencyReadPlatformServiceImplTest {
         assertThat(result.getDelinquentDays()).isEqualTo(36L);
     }
 
+    @Test
+    void pastDueDays_usesOpenPastDuePeriodWhenMinPaymentCriteriaMetIsStillNull() {
+        final WorkingCapitalLoanDelinquencyRangeSchedule period = period(1L, 1, "269.99");
+        period.setMinPaymentCriteriaMet(null);
+        period.setDelinquentDays(1L);
+        when(delinquencyRangeScheduleRepository.findOpenPastDuePeriodsOrderByFromDateAsc(LOAN_ID, BUSINESS_DATE))
+                .thenReturn(List.of(period));
+
+        final WorkingCapitalLoanCollectionData result = service.getCollectionData(LOAN_ID, BUSINESS_DATE);
+
+        assertThat(result.getPastDueDays()).isEqualTo(1L);
+    }
+
     private WorkingCapitalLoanDelinquencyRangeScheduleTagHistory tag(final WorkingCapitalLoanDelinquencyRangeSchedule period,
             final DelinquencyRange range, final String addedOnDate, final String liftedOnDate, final String outstandingAmount) {
         final WorkingCapitalLoanDelinquencyRangeScheduleTagHistory tag = new WorkingCapitalLoanDelinquencyRangeScheduleTagHistory();


(fineract) 02/02: FINERACT-2455: updated e2e scenario for validation of WC - Past due days calculation bug

Posted by ad...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

adamsaghy pushed a commit to branch maintenance/1.16.0
in repository https://gitbox.apache.org/repos/asf/fineract.git

commit 6da8a989b398cb46537e91d8fe8769655ea1810d
Author: Rustam Zeinalov <tr...@gmail.com>
AuthorDate: Mon Oct 19 12:36:44 2026 +0200

    FINERACT-2455: updated e2e scenario for validation of WC - Past due days calculation bug
    
    (cherry picked from commit 461cb28b22db08f4832937c025e2e7d8f9e9937c)
---
 .../stepdef/common/GlobalConfigurationStepDef.java |   6 +
 .../features/WorkingCapitalDelinquency.feature     | 192 +++++++++++++++++++++
 2 files changed, 198 insertions(+)

diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/common/GlobalConfigurationStepDef.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/common/GlobalConfigurationStepDef.java
index 0536c47752..3e2b735350 100644
--- a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/common/GlobalConfigurationStepDef.java
+++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/common/GlobalConfigurationStepDef.java
@@ -55,6 +55,12 @@ public class GlobalConfigurationStepDef {
         globalConfigurationHelper.enableGlobalConfiguration("enable-business-date", 0L);
     }
 
+    // instant delinquency classification is seeded enabled; restore it even when a scenario fails mid-way
+    @After("@WorkingCapitalInstantDelinquencyConfig")
+    public void restoreInstantDelinquencyConfig() {
+        globalConfigurationHelper.enableGlobalConfiguration("enable-instant-delinquency-calculation", 0L);
+    }
+
     @Given("Global configuration {string} is disabled")
     public void disableGlobalConfiguration(String configKey) {
         globalConfigurationHelper.disableGlobalConfiguration(configKey, 0L);
diff --git a/fineract-e2e-tests-runner/src/test/resources/features/WorkingCapitalDelinquency.feature b/fineract-e2e-tests-runner/src/test/resources/features/WorkingCapitalDelinquency.feature
index bb99eb4df7..f750aac752 100644
--- a/fineract-e2e-tests-runner/src/test/resources/features/WorkingCapitalDelinquency.feature
+++ b/fineract-e2e-tests-runner/src/test/resources/features/WorkingCapitalDelinquency.feature
@@ -1430,6 +1430,7 @@ Feature: Working Capital Delinquency
       | 1            | 2026-02-13  |              | D00            | 1              | 30             |
     Then Admin closes the Working Capital loan with all obligations met with a full repayment on "13 February 2026"
 
+  @TestRailId:C115296
   Scenario: Verify pastDueDays when instant classification runs before COB evaluates minPaymentCriteriaMet
     When Admin sets the business date to "01 January 2026"
     And Admin creates a client with random data
@@ -1456,6 +1457,7 @@ Feature: Working Capital Delinquency
       | summary.overdueSinceDate      | 2026-02-02 |
     Then Admin closes the Working Capital loan with a full repayment on "03 February 2026"
 
+  @TestRailId:C115297
   Scenario: Verify pastDueDays for backdated disbursement and partial repayment without COB
     When Admin sets the business date to "01 April 2026"
     And Admin creates a client with random data
@@ -1481,6 +1483,7 @@ Feature: Working Capital Delinquency
       | summary.overdueSinceDate      | 2026-02-02 |
     Then Admin closes the Working Capital loan with a full repayment on "01 April 2026"
 
+  @TestRailId:C115298
   Scenario: Verify pastDueDays after first COB and subsequent partial repayment on next day
     When Admin sets the business date to "01 January 2026"
     And Admin creates a client with random data
@@ -1515,3 +1518,192 @@ Feature: Working Capital Delinquency
       | delinquencyEffectiveStartDate | 2026-01-04 |
       | summary.overdueSinceDate      | 2026-02-02 |
     Then Admin closes the Working Capital loan with a full repayment on "04 February 2026"
+
+  @TestRailId:C115299
+  Scenario: Verify pastDueDays stays 0 and delinquency start dates stay empty when a backdated repayment meets the minimum before COB
+    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 Product with delinquencyGraceDays 3 and delinquencyStartType "DISBURSEMENT" for loan test
+    And Admin creates a working capital loan with the grace days product and the following data:
+      | submittedOnDate | expectedDisbursementDate | principalAmount | totalPaymentVolume | periodPaymentRate |
+      | 01 January 2026 | 01 January 2026          | 9000.0          | 100000.0           | 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"
+    And Admin successfully disburse the Working Capital loan on "01 January 2026" with "9000" EUR transaction amount
+    # Period 1 (toDate 2026-02-02) is paid in full before COB evaluates it: the repayment itself flips minPaymentCriteriaMet to true, so nothing is past due
+    When Admin sets the business date to "03 February 2026"
+    And Customer makes repayment on "03 February 2026" with 270.0 transaction amount on Working Capital loan
+    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-02-02 | 270.0          | 270.0      | 0.0               | true                  | 0.0              | 0              |
+    And Delinquency Tag History for Working Capital loan has lines:
+      | periodNumber | addedOnDate | liftedOnDate | classification | minimumAgeDays | maximumAgeDays |
+    And Working capital loan details has the following field values:
+      | delinquent.delinquentAmount   | 0.0  |
+      | delinquent.delinquentDays     | 0    |
+      | delinquent.pastDueDays        | 0    |
+      | delinquencyStartDate          | null |
+      | delinquencyEffectiveStartDate | null |
+      | summary.overdueSinceDate      | null |
+    # COB does not re-open the already satisfied period
+    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-02-02 | 270.0          | 270.0      | 0.0               | true                  | 0.0              | 0              |
+      | 2            | 2026-02-03 | 2026-03-04 | 270.0          | 0.0        | 270.0             | null                  | null             | null           |
+    And Working capital loan details has the following field values:
+      | delinquent.pastDueDays        | 0    |
+      | delinquencyStartDate          | null |
+      | delinquencyEffectiveStartDate | null |
+      | summary.overdueSinceDate      | null |
+    Then Admin closes the Working Capital loan with a full repayment on "03 February 2026"
+
+  @TestRailId:C115300
+  Scenario: Verify pastDueDays and delinquency start dates move to the next unevaluated period when a backdated repayment cures the first one before COB
+    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 Product with delinquencyGraceDays 3 and delinquencyStartType "DISBURSEMENT" for loan test
+    And Admin creates a working capital loan with the grace days product and the following data:
+      | submittedOnDate | expectedDisbursementDate | principalAmount | totalPaymentVolume | periodPaymentRate |
+      | 01 January 2026 | 01 January 2026          | 9000.0          | 100000.0           | 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"
+    And Admin successfully disburse the Working Capital loan on "01 January 2026" with "9000" EUR transaction amount
+    When Admin sets the business date to "03 February 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-02-02 | 270.0          | 0.0        | 270.0             | false                 | 270.0            | 1              |
+      | 2            | 2026-02-03 | 2026-03-04 | 270.0          | 0.0        | 270.0             | null                  | null             | null           |
+    # Period 2 expires without COB; the repayment cures period 1 and instant classification marks period 2 delinquent while it is still unevaluated (minPaymentCriteriaMet NULL)
+    When Admin sets the business date to "10 March 2026"
+    And Customer makes repayment on "10 March 2026" with 270.0 transaction amount on Working Capital loan
+    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-02-02 | 270.0          | 270.0      | 0.0               | true                  | 0.0              | 0              |
+      | 2            | 2026-02-03 | 2026-03-04 | 270.0          | 0.0        | 270.0             | null                  | 270.0            | 6              |
+    And Delinquency Tag History for Working Capital loan has lines:
+      | periodNumber | addedOnDate | liftedOnDate | classification | minimumAgeDays | maximumAgeDays |
+      | 2            | 2026-03-10  |              | D00            | 1              | 30             |
+      | 1            | 2026-02-03  | 2026-03-10   | D00            | 1              | 30             |
+    And Working capital loan details has the following field values:
+      | delinquent.delinquentAmount   | 270.0      |
+      | delinquent.delinquentDate     | 2026-03-10 |
+      | delinquent.delinquentDays     | 1          |
+      | delinquent.pastDueDays        | 6          |
+      | delinquencyStartDate          | 2026-02-03 |
+      | delinquencyEffectiveStartDate | null       |
+      | summary.overdueSinceDate      | 2026-03-04 |
+    Then Admin closes the Working Capital loan with a full repayment on "10 March 2026"
+
+  @TestRailId:C115301
+  Scenario: Verify pastDueDays and delinquency start dates survive the undo of the backdated partial repayment made before COB
+    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 Product with delinquencyGraceDays 3 and delinquencyStartType "DISBURSEMENT" for loan test
+    And Admin creates a working capital loan with the grace days product and the following data:
+      | submittedOnDate | expectedDisbursementDate | principalAmount | totalPaymentVolume | periodPaymentRate |
+      | 01 January 2026 | 01 January 2026          | 9000.0          | 100000.0           | 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"
+    And Admin successfully disburse the Working Capital loan on "01 January 2026" with "9000" EUR transaction amount
+    When Admin sets the business date to "03 February 2026"
+    And Customer makes repayment on "03 February 2026" with 0.01 transaction amount on Working Capital loan
+    Then Working capital loan details has the following field values:
+      | delinquent.pastDueDays        | 1          |
+      | delinquencyStartDate          | 2026-01-01 |
+      | delinquencyEffectiveStartDate | 2026-01-04 |
+      | summary.overdueSinceDate      | 2026-02-02 |
+    And Working Capital Loan Delinquency Range Change business event is raised with delinquency data:
+      | delinquencyStartType | delinquencyStartDate | delinquencyEffectiveStartDate | delinquentAmount | totalDelinquentAmount |
+      | DISBURSEMENT         | 2026-01-01           | 2026-01-04                    | 269.99           | 269.99                |
+    # Undo before COB re-opens the period as fully unpaid: it stays past due with the same start dates
+    When Customer undo "1"th working capital transaction made on "03 February 2026"
+    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-02-02 | 270.0          | 0.0        | 270.0             | false                 | 270.0            | 1              |
+      | 2            | 2026-02-03 | 2026-03-04 | 270.0          | 0.0        | 270.0             | null                  | null             | null           |
+    And Delinquency Tag History for Working Capital loan has lines:
+      | periodNumber | addedOnDate | liftedOnDate | classification | minimumAgeDays | maximumAgeDays |
+      | 1            | 2026-02-03  |              | D00            | 1              | 30             |
+    And Working capital loan details has the following field values:
+      | delinquent.delinquentAmount   | 270.0      |
+      | delinquent.pastDueDays        | 1          |
+      | delinquencyStartDate          | 2026-01-01 |
+      | delinquencyEffectiveStartDate | 2026-01-04 |
+      | summary.overdueSinceDate      | 2026-02-02 |
+    Then Admin closes the Working Capital loan with a full repayment on "03 February 2026"
+
+  @TestRailId:C115302
+  Scenario: Verify pastDueDays and delinquency start dates are cleared when the period classified before COB is reset
+    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 Product with delinquencyGraceDays 3 and delinquencyStartType "DISBURSEMENT" for loan test
+    And Admin creates a working capital loan with the grace days product and the following data:
+      | submittedOnDate | expectedDisbursementDate | principalAmount | totalPaymentVolume | periodPaymentRate |
+      | 01 January 2026 | 01 January 2026          | 9000.0          | 100000.0           | 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"
+    And Admin successfully disburse the Working Capital loan on "01 January 2026" with "9000" EUR transaction amount
+    When Admin sets the business date to "03 February 2026"
+    And Customer makes repayment on "03 February 2026" with 0.01 transaction amount on Working Capital loan
+    Then Working capital loan details has the following field values:
+      | delinquent.pastDueDays | 1          |
+      | delinquencyStartDate   | 2026-01-01 |
+    # The reset flags the unevaluated past period: it must no longer drive pastDueDays or the start dates
+    When Admin creates a Working Capital delinquency reset
+    Then Delinquency Tag History for Working Capital loan has lines:
+      | periodNumber | addedOnDate | liftedOnDate | classification | minimumAgeDays | maximumAgeDays |
+      | 1            | 2026-02-03  | 2026-02-03   | D00            | 1              | 30             |
+    And Working capital loan details has the following field values:
+      | delinquent.delinquentAmount   | 0.0  |
+      | delinquent.delinquentDays     | 0    |
+      | delinquent.pastDueDays        | 0    |
+      | delinquencyStartDate          | null |
+      | delinquencyEffectiveStartDate | null |
+      | summary.overdueSinceDate      | null |
+    When Admin runs inline COB job for Working Capital Loan by loanId
+    Then Working capital loan details has the following field values:
+      | delinquent.pastDueDays        | 0    |
+      | delinquencyStartDate          | null |
+      | delinquencyEffectiveStartDate | null |
+      | summary.overdueSinceDate      | null |
+    Then Admin closes the Working Capital loan with a full repayment on "03 February 2026"
+
+  @TestRailId:C115303 @WorkingCapitalInstantDelinquencyConfig
+  Scenario: Verify pastDueDays stays 0 without instant delinquency classification until COB evaluates the period
+    Given Global configuration "enable-instant-delinquency-calculation" is disabled
+    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 Product with delinquencyGraceDays 3 and delinquencyStartType "DISBURSEMENT" for loan test
+    And Admin creates a working capital loan with the grace days product and the following data:
+      | submittedOnDate | expectedDisbursementDate | principalAmount | totalPaymentVolume | periodPaymentRate |
+      | 01 January 2026 | 01 January 2026          | 9000.0          | 100000.0           | 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"
+    And Admin successfully disburse the Working Capital loan on "01 January 2026" with "9000" EUR transaction amount
+    # Without instant classification the repayment leaves delinquentDays NULL: the open past period must not be reported as past due
+    When Admin sets the business date to "03 February 2026"
+    And Customer makes repayment on "03 February 2026" with 0.01 transaction amount on Working Capital loan
+    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-02-02 | 270.0          | 0.01       | 269.99            | null                  | null             | null           |
+    And Working capital loan details has the following field values:
+      | delinquent.delinquentAmount   | 0.0  |
+      | delinquent.delinquentDays     | 0    |
+      | delinquent.pastDueDays        | 0    |
+      | delinquencyStartDate          | null |
+      | delinquencyEffectiveStartDate | null |
+      | summary.overdueSinceDate      | null |
+    # COB evaluates and classifies the period: pastDueDays and the start dates appear together
+    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-02-02 | 270.0          | 0.01       | 269.99            | false                 | 269.99           | 1              |
+      | 2            | 2026-02-03 | 2026-03-04 | 270.0          | 0.0        | 270.0             | null                  | null             | null           |
+    And Delinquency Tag History for Working Capital loan has lines:
+      | periodNumber | addedOnDate | liftedOnDate | classification | minimumAgeDays | maximumAgeDays |
+      | 1            | 2026-02-03  |              | D00            | 1              | 30             |
+    And Working capital loan details has the following field values:
+      | delinquent.delinquentAmount   | 269.99     |
+      | delinquent.pastDueDays        | 1          |
+      | delinquencyStartDate          | 2026-01-01 |
+      | delinquencyEffectiveStartDate | 2026-01-04 |
+      | summary.overdueSinceDate      | 2026-02-02 |
+    Then Admin closes the Working Capital loan with a full repayment on "03 February 2026"
+    And Global configuration "enable-instant-delinquency-calculation" is enabled