Skip to content

FINERACT-2455: Working Capital Loan - Recovery payment transaction - #6301

Open
alberto-art3ch wants to merge 1 commit into
apache:developfrom
openMF:FINERACT-2455/working-capital-loan-recovery-payment
Open

FINERACT-2455: Working Capital Loan - Recovery payment transaction#6301
alberto-art3ch wants to merge 1 commit into
apache:developfrom
openMF:FINERACT-2455/working-capital-loan-recovery-payment

Conversation

@alberto-art3ch

Copy link
Copy Markdown
Contributor

Description

We are adding the Recovery Payment to Working Capital Loans (?command=recoveryPayment, reversible via the generic transaction undo)

The collections after a write-off book as Dr Fund Source / Cr Income from Recovery, the loan stays CLOSED_WRITTEN_OFF and its balance stays zeroed.

Each recovery is capped by the remaining recoverable amount rather than the gross written off — diverging from term loans, where successive recoveries can exceed the booked loss — and undo write-off is blocked while any recovery stands. Read model and template updated.

FINERACT-2455

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.

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

@alberto-art3ch
alberto-art3ch force-pushed the FINERACT-2455/working-capital-loan-recovery-payment branch from 0a47c97 to 42f9e7b Compare August 21, 2026 01:23
@alberto-art3ch
alberto-art3ch marked this pull request as ready for review August 21, 2026 01:24

@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.

Went back over the money-critical paths specifically - recovery-cap race, transaction boundaries, authorization, rounding - since this is a new feature that moves money. All of it holds up:

  • The recovery cap is read and written inside one transaction, and WorkingCapitalLoanBalance carries @Version, so two concurrent recovery payments can't both pass - the loser gets an optimistic-lock failure rather than an over-recovery.
  • Command handler and write service are both @Transactional, transaction/balance/journal entries commit or roll back together.
  • Authorization goes through the command framework (RECOVERYPAYMENT_WORKINGCAPITALLOAN), not just the migration seeding a permission row - confirmed the write service is actually gated by it.
  • Rounding/locale handling matches the rest of the module (same MathContext, same Locale.US parsing as disbursement/repayment) - nothing new introduced here.
  • Liquibase migration only inserts config rows with MARK_RAN preconditions, no deletes - follows the write-off PR's pattern correctly.

A few things worth addressing as follow-ups, not blockers:

  1. undoRecoveryPayment doesn't emit the generic WorkingCapitalLoanTransactionReversedBusinessEvent that every other WC reversal emits alongside its specific event - a consumer reconciling reversals generically will miss recovery reversals.
  2. No unit test for the write service itself (WorkingCapitalLoanRecoveryPaymentWriteServiceImpl) - the PR has good unit coverage for the balance math and validation, but the actual balance-mutation/JE-posting/event-emission logic is only covered by integration/e2e tests, which don't run in the fast build. The write-off feature has a dedicated unit test for its write service; a mirror of that would be good here.
  3. Two stranded Javadoc blocks left over from the diff (AccrualWithDeferredRevenueAmortizationAccountingProcessorForWorkingCapitalLoan and WorkingCapitalLoanDataValidator) - worth a quick cleanup pass.
  4. MathUtil.subtract(...).max(BigDecimal.ZERO) on the undo path isn't null-safe if the first argument were ever null, and it silently floors at zero rather than failing if totalRecovered were ever less than the reversed amount - unreachable today given the NOT NULL/default-0 columns, but worth the nullToZero idiom used elsewhere in the class for consistency, and I'd rather this fail loudly than clamp silently on a money path.

Recommendation: APPROVE

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.

2 participants