You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@fineract.apache.org by "oleksii-novikov-onix (via GitHub)" <gi...@apache.org> on 2026/06/12 11:09:59 UTC

[PR] FINERACT-2455: Add WC Breach pause [fineract]

oleksii-novikov-onix opened a new pull request, #5983:
URL: https://github.com/apache/fineract/pull/5983

   ## Description
   
   Describe the changes made and why they were made. (Ignore if these details are present on the associated Apache Fineract JIRA ticket.)
   
   ## Checklist
   
   Please make sure these boxes are checked before submitting your pull request - thanks!
   
   - [ ] Write the commit message as per [our guidelines](https://github.com/apache/fineract/blob/develop/CONTRIBUTING.md#pull-requests)
   - [ ] Acknowledge that we will not review PRs that are not passing the build _("green")_ - it is your responsibility to get a proposed PR to pass the build, not primarily the project's maintainers.
   - [ ] Create/update [unit or integration tests](https://fineract.apache.org/docs/current/#_testing) for verifying the changes made.
   - [ ] Follow our [coding conventions](https://cwiki.apache.org/confluence/display/FINERACT/Coding+Conventions).
   - [ ] Add required Swagger annotation and update API documentation at fineract-provider/src/main/resources/static/legacy-docs/apiLive.htm with details of any API changes
   - [ ] [This PR must not be a "code dump"](https://cwiki.apache.org/confluence/display/FINERACT/Pull+Request+Size+Limit). Large changes can be made in a branch, with assistance. Ask for help on the [developer mailing list](https://fineract.apache.org/#contribute).
   
   Your assigned reviewer(s) will follow our [guidelines for code reviews](https://cwiki.apache.org/confluence/display/FINERACT/Code+Review+Guide).
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] FINERACT-2455: Add WC Breach pause [fineract]

Posted by "oleksii-novikov-onix (via GitHub)" <gi...@apache.org>.
oleksii-novikov-onix commented on code in PR #5983:
URL: https://github.com/apache/fineract/pull/5983#discussion_r3441406180


##########
fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/WorkingCapitalLoanBreachScheduleServiceImpl.java:
##########
@@ -170,6 +179,66 @@ public List<WorkingCapitalLoanBreachScheduleData> retrieveBreachSchedule(final L
         return mapper.toDataList(periods);
     }
 
+    @Override
+    public void recalculatePeriodsForPauses(final WorkingCapitalLoan loan) {
+        final Optional<WorkingCapitalBreach> breachOpt = getBreachConfig(loan);
+        if (breachOpt.isEmpty()) {
+            return;
+        }
+        final List<WorkingCapitalLoanBreachSchedule> periods = repository.findByLoanIdOrderByPeriodNumberAsc(loan.getId());
+        if (periods.isEmpty()) {
+            return;
+        }
+        final WorkingCapitalBreach breach = breachOpt.get();
+        final List<WorkingCapitalLoanBreachAction> recordedPauses = findRecordedPauses(loan.getId());
+        final LocalDate businessDate = DateUtils.getBusinessLocalDate();
+        LocalDate fromDate = periods.getFirst().getFromDate();
+        for (final WorkingCapitalLoanBreachSchedule period : periods) {
+            period.setFromDate(fromDate);
+            period.setToDate(calculateToDate(fromDate, breach.getBreachFrequency(), breach.getBreachFrequencyType()));
+            applyRecordedPauses(period, recordedPauses);
+            recomputeBreach(period, businessDate);
+            fromDate = period.getToDate().plusDays(1);
+        }
+        repository.saveAll(periods);
+        log.debug("Recalculated breach schedule periods for WC loan {} by replaying {} recorded pauses", loan.getId(),
+                recordedPauses.size());
+    }
+
+    private void recomputeBreach(final WorkingCapitalLoanBreachSchedule period, final LocalDate businessDate) {
+        if (period.getOutstandingAmount().compareTo(BigDecimal.ZERO) == 0) {
+            period.setBreach(false);
+        } else if (businessDate.isAfter(period.getToDate())) {
+            // COB evaluates with effective date businessDate-1, so breach is set only after the toDate has passed
+            period.setBreach(true);
+        } else {
+            period.setBreach(null);
+        }
+    }
+
+    private List<WorkingCapitalLoanBreachAction> findRecordedPauses(final Long loanId) {
+        return breachActionRepository.findByWorkingCapitalLoanIdOrderById(loanId).stream()
+                .filter(action -> WorkingCapitalLoanBreachActionType.PAUSE.equals(action.getAction()))
+                .sorted(Comparator.comparing(WorkingCapitalLoanBreachAction::getStartDate)).toList();
+    }
+
+    private void applyRecordedPauses(final WorkingCapitalLoanBreachSchedule period,
+            final List<WorkingCapitalLoanBreachAction> pauseActions) {
+        for (final WorkingCapitalLoanBreachAction pause : pauseActions) {
+            final LocalDate pauseStart = pause.getStartDate();

Review Comment:
   @ruzeynalov @adamsaghy  The half-open interval (exclusive endDate) is consistent with the delinquency code (which the breach logic mirrors). I will update the fineract-doc accordingly.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] FINERACT-2455: Add WC Breach pause [fineract]

Posted by "adamsaghy (via GitHub)" <gi...@apache.org>.
adamsaghy commented on PR #5983:
URL: https://github.com/apache/fineract/pull/5983#issuecomment-4766397259

   @oleksii-novikov-onix Please rebase.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] FINERACT-2455: Add WC Breach pause [fineract]

Posted by "adamsaghy (via GitHub)" <gi...@apache.org>.
adamsaghy closed pull request #5983: FINERACT-2455: Add WC Breach pause
URL: https://github.com/apache/fineract/pull/5983


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] FINERACT-2455: Add WC Breach pause [fineract]

Posted by "adamsaghy (via GitHub)" <gi...@apache.org>.
adamsaghy commented on code in PR #5983:
URL: https://github.com/apache/fineract/pull/5983#discussion_r3434929777


##########
fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/WorkingCapitalLoanBreachScheduleServiceImpl.java:
##########
@@ -170,6 +179,66 @@ public List<WorkingCapitalLoanBreachScheduleData> retrieveBreachSchedule(final L
         return mapper.toDataList(periods);
     }
 
+    @Override
+    public void recalculatePeriodsForPauses(final WorkingCapitalLoan loan) {
+        final Optional<WorkingCapitalBreach> breachOpt = getBreachConfig(loan);
+        if (breachOpt.isEmpty()) {
+            return;
+        }
+        final List<WorkingCapitalLoanBreachSchedule> periods = repository.findByLoanIdOrderByPeriodNumberAsc(loan.getId());
+        if (periods.isEmpty()) {
+            return;
+        }
+        final WorkingCapitalBreach breach = breachOpt.get();
+        final List<WorkingCapitalLoanBreachAction> recordedPauses = findRecordedPauses(loan.getId());
+        final LocalDate businessDate = DateUtils.getBusinessLocalDate();
+        LocalDate fromDate = periods.getFirst().getFromDate();
+        for (final WorkingCapitalLoanBreachSchedule period : periods) {
+            period.setFromDate(fromDate);
+            period.setToDate(calculateToDate(fromDate, breach.getBreachFrequency(), breach.getBreachFrequencyType()));
+            applyRecordedPauses(period, recordedPauses);
+            recomputeBreach(period, businessDate);
+            fromDate = period.getToDate().plusDays(1);
+        }
+        repository.saveAll(periods);
+        log.debug("Recalculated breach schedule periods for WC loan {} by replaying {} recorded pauses", loan.getId(),
+                recordedPauses.size());
+    }
+
+    private void recomputeBreach(final WorkingCapitalLoanBreachSchedule period, final LocalDate businessDate) {
+        if (period.getOutstandingAmount().compareTo(BigDecimal.ZERO) == 0) {
+            period.setBreach(false);
+        } else if (businessDate.isAfter(period.getToDate())) {
+            // COB evaluates with effective date businessDate-1, so breach is set only after the toDate has passed
+            period.setBreach(true);
+        } else {
+            period.setBreach(null);
+        }
+    }
+
+    private List<WorkingCapitalLoanBreachAction> findRecordedPauses(final Long loanId) {
+        return breachActionRepository.findByWorkingCapitalLoanIdOrderById(loanId).stream()
+                .filter(action -> WorkingCapitalLoanBreachActionType.PAUSE.equals(action.getAction()))
+                .sorted(Comparator.comparing(WorkingCapitalLoanBreachAction::getStartDate)).toList();
+    }
+
+    private void applyRecordedPauses(final WorkingCapitalLoanBreachSchedule period,
+            final List<WorkingCapitalLoanBreachAction> pauseActions) {
+        for (final WorkingCapitalLoanBreachAction pause : pauseActions) {
+            final LocalDate pauseStart = pause.getStartDate();

Review Comment:
   I think start date and end date should be both inclusive, so the diff between them + 1



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] FINERACT-2455: Add WC Breach pause [fineract]

Posted by "oleksii-novikov-onix (via GitHub)" <gi...@apache.org>.
oleksii-novikov-onix commented on code in PR #5983:
URL: https://github.com/apache/fineract/pull/5983#discussion_r3453322549


##########
fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/WorkingCapitalLoanBreachScheduleServiceImpl.java:
##########
@@ -170,6 +179,66 @@ public List<WorkingCapitalLoanBreachScheduleData> retrieveBreachSchedule(final L
         return mapper.toDataList(periods);
     }
 
+    @Override
+    public void recalculatePeriodsForPauses(final WorkingCapitalLoan loan) {
+        final Optional<WorkingCapitalBreach> breachOpt = getBreachConfig(loan);
+        if (breachOpt.isEmpty()) {
+            return;
+        }
+        final List<WorkingCapitalLoanBreachSchedule> periods = repository.findByLoanIdOrderByPeriodNumberAsc(loan.getId());
+        if (periods.isEmpty()) {
+            return;
+        }
+        final WorkingCapitalBreach breach = breachOpt.get();
+        final List<WorkingCapitalLoanBreachAction> recordedPauses = findRecordedPauses(loan.getId());
+        final LocalDate businessDate = DateUtils.getBusinessLocalDate();
+        LocalDate fromDate = periods.getFirst().getFromDate();
+        for (final WorkingCapitalLoanBreachSchedule period : periods) {
+            period.setFromDate(fromDate);
+            period.setToDate(calculateToDate(fromDate, breach.getBreachFrequency(), breach.getBreachFrequencyType()));
+            applyRecordedPauses(period, recordedPauses);
+            recomputeBreach(period, businessDate);
+            fromDate = period.getToDate().plusDays(1);
+        }
+        repository.saveAll(periods);
+        log.debug("Recalculated breach schedule periods for WC loan {} by replaying {} recorded pauses", loan.getId(),
+                recordedPauses.size());
+    }
+
+    private void recomputeBreach(final WorkingCapitalLoanBreachSchedule period, final LocalDate businessDate) {
+        if (period.getOutstandingAmount().compareTo(BigDecimal.ZERO) == 0) {
+            period.setBreach(false);
+        } else if (businessDate.isAfter(period.getToDate())) {
+            // COB evaluates with effective date businessDate-1, so breach is set only after the toDate has passed
+            period.setBreach(true);
+        } else {
+            period.setBreach(null);
+        }
+    }
+
+    private List<WorkingCapitalLoanBreachAction> findRecordedPauses(final Long loanId) {
+        return breachActionRepository.findByWorkingCapitalLoanIdOrderById(loanId).stream()
+                .filter(action -> WorkingCapitalLoanBreachActionType.PAUSE.equals(action.getAction()))
+                .sorted(Comparator.comparing(WorkingCapitalLoanBreachAction::getStartDate)).toList();
+    }
+
+    private void applyRecordedPauses(final WorkingCapitalLoanBreachSchedule period,
+            final List<WorkingCapitalLoanBreachAction> pauseActions) {
+        for (final WorkingCapitalLoanBreachAction pause : pauseActions) {
+            final LocalDate pauseStart = pause.getStartDate();

Review Comment:
   Fixed the implementation: both the start date and end date are now inclusive.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org