Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,147 @@ 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: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:
| 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"
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:
| 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: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"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ public void generateNextPeriodIfNeeded(WorkingCapitalLoan loan, LocalDate busine
final DelinquencyFrequencyType effectiveFreqType = latestReschedule.map(WorkingCapitalLoanDelinquencyAction::getFrequencyType)
.orElse(rule.getFrequencyType());

final List<WorkingCapitalLoanDelinquencyAction> recordedPauses = findAllPauseActions(loan.getId());

WorkingCapitalLoanDelinquencyRangeSchedule latestPeriod = latestPeriodOpt.get();
while (!latestPeriod.getToDate().isAfter(businessDate)) {
final LocalDate newFromDate = latestPeriod.getToDate().plusDays(1);
Expand All @@ -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());
}
Expand Down Expand Up @@ -260,6 +264,27 @@ private Optional<WorkingCapitalLoanDelinquencyAction> findLatestRescheduleAction
return loanDelinquencyActionRepository.findTopByWorkingCapitalLoanIdAndActionOrderByIdDesc(loanId, DelinquencyAction.RESCHEDULE);
}

private List<WorkingCapitalLoanDelinquencyAction> 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<WorkingCapitalLoanDelinquencyAction> 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();
Expand Down
Loading