Skip to content

FINERACT-2455: WC - No accruals in case no accounting is configured - #6440

Merged
adamsaghy merged 2 commits into
apache:developfrom
openMF:FINERACT-2455/wc-no-accruals-without-accounting
Sep 24, 2026
Merged

adamsaghy merged 2 commits into
apache:developfrom
openMF:FINERACT-2455/wc-no-accruals-without-accounting

Conversation

@oleksii-novikov-onix

Copy link
Copy Markdown
Contributor

Description

Description:

When a Working Capital product has no accounting (NONE), accruals and accrual adjustments should not be created, but discount fee amortization and amortization adjustments should.

Already in develop:

  1. Accruals and accrual adjustments are not created for products without accounting.
  2. Amortization and amortization adjustments are created. Only their journal entries depend on accounting.

This PR adds:

  1. Two remaining places could reach accounting code without checking whether the product has accounting. Both now check it, which matches how regular loans behave.

    • Undo of a discount fee adjustment: accounting code could block it when accounting for the office was closed for the current date, even though the loan has no journal entries.
    • Undo disbursal: no visible difference for these loans, since accruals are not created without accounting. The check keeps the rule consistent.
  2. E2E tests for the cases that had no coverage for products without accounting:

    • amortization adjustment and its undo while accounting is closed;
    • real-time accrual and undo disbursal;
    • accrual on loan closure;
    • final amortization on charge-off.

Checklist

Please make sure these boxes are checked before submitting your pull request - thanks!

  • Write the commit message as per our guidelines
  • 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 for verifying the changes made.
  • Follow our 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". Large changes can be made in a branch, with assistance. Ask for help on the developer mailing list.
  • If merging this PR resolves a JIRA issue, I will mark that issue as resolved and set "Fix Version/s" appropriately.
  • I followed the AI Policy.

Your assigned reviewer(s) will follow our guidelines for code reviews.

@oleksii-novikov-onix
oleksii-novikov-onix force-pushed the FINERACT-2455/wc-no-accruals-without-accounting branch 2 times, most recently from 6874513 to bd41cb4 Compare September 16, 2026 14:19
@oleksii-novikov-onix
oleksii-novikov-onix marked this pull request as ready for review September 18, 2026 13:17
@oleksii-novikov-onix
oleksii-novikov-onix force-pushed the FINERACT-2455/wc-no-accruals-without-accounting branch from 31dd361 to 5232cde Compare September 21, 2026 12:04

@Cocoa-Puffs Cocoa-Puffs left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@adamsaghy

Copy link
Copy Markdown
Contributor

@oleksii-novikov-onix Please review my finding / concern:

AccrualWithDeferredRevenueAmortizationAccountingProcessorForWorkingCapitalLoanTest.java:169 — (low, test-coverage) The unit test is touched only to stub ACC_DEF_REV_AM so existing tests stay green; nothing asserts the new NONE short-circuit. A tenth method added without the guard, or a guard dropped in a refactor, would pass every unit test and only surface as the runtime exception this PR fixes. A test stubbing NONE and asserting verifyNoInteractions(helper, journalEntryRepository) across the interface would close it.

@oleksii-novikov-onix
oleksii-novikov-onix force-pushed the FINERACT-2455/wc-no-accruals-without-accounting branch from 5232cde to 5fa56e7 Compare September 22, 2026 14:58
@oleksii-novikov-onix
oleksii-novikov-onix force-pushed the FINERACT-2455/wc-no-accruals-without-accounting branch from 5fa56e7 to 3ac237b Compare September 23, 2026 05:28
@oleksii-novikov-onix

Copy link
Copy Markdown
Contributor Author

@oleksii-novikov-onix Please review my finding / concern:

AccrualWithDeferredRevenueAmortizationAccountingProcessorForWorkingCapitalLoanTest.java:169 — (low, test-coverage) The unit test is touched only to stub ACC_DEF_REV_AM so existing tests stay green; nothing asserts the new NONE short-circuit. A tenth method added without the guard, or a guard dropped in a refactor, would pass every unit test and only surface as the runtime exception this PR fixes. A test stubbing NONE and asserting verifyNoInteractions(helper, journalEntryRepository) across the interface would close it.

Covered, the test loops over every method of the interface with NONE stubbed and asserts verifyNoInteractions(helper, journalEntryRepository), so a newly added method is caught automatically.

@ruzeynalov
ruzeynalov force-pushed the FINERACT-2455/wc-no-accruals-without-accounting branch from 3ac237b to ebdd96a Compare September 23, 2026 10:23

@galovics galovics left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fix is correct. I traced every accrual entry point (COB, real-time on charge add, closure accruals via accrueOnClosure) - they all go through WorkingCapitalLoanChargeAccrualService and already skip when posting is disabled, so no ACCRUAL transaction can exist on a no-accounting loan. The two callers that were actually missing a check (reverseDiscountFeeAmortizationAdjustments and the accrual reversal in undo disbursal) are covered by the new guard in the processor - the first one was a real bug, since reverseExistingEntries calls checkForBranchClosures before looking up any journal entries, so undoing a discount fee adjustment on a no-accounting loan failed with a 403 if the office's accounting was closed (C106704 reproduces it). No balance or summary field reads accrual transactions, so nothing goes stale when they're skipped.

One design question, not blocking: the description says the two call sites now check whether the product has accounting, but the diff puts the check inside the processor on every entry point, while ~25 other call sites still check isAccrualWithDeferredRevenueAmortization() before calling it. I'd pick one place to own this rule. If the processor owns it (probably better - your reflection test enforces it for every new interface method), let's remove the call-site checks and the accountingEnabled flags passed around in the amortization and reprocessing services; if the call sites keep it, add the check at the two missing ones and leave the processor alone. Having both is how we got the uneven checks in the first place. A follow-up is fine.

Small things: C106708's title says "undo disbursal with a live charge accrual is rejected" but the 403 comes from the disbursement's own reversal before the accrual is reached, so it would fail the same way without an accrual - worth renaming. And a pre-existing edge, not from this PR: accountingRule on a product can be changed while loans have journal entries, which orphans them once every check skips - worth a ticket.

Recommendation: APPROVE

@adamsaghy
adamsaghy merged commit 1f3760d into apache:develop Sep 24, 2026
94 checks passed
@adamsaghy
adamsaghy deleted the FINERACT-2455/wc-no-accruals-without-accounting branch September 24, 2026 15:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants