adamsaghy commented on PR #6469:
URL: https://github.com/apache/fineract/pull/6469#issuecomment-5792675978
@Cocoa-Puffs Can you please review the below concerns?
**Regression?**
- recalculateMaturityOnOverpaid moves the maturity earlier when a
non-repayment settles the loan
obligationsMetOn answers "the last repayment the loan needed", which equals
"the day obligations were met" only when a repayment is what met them.
recalculateClosure guards against that — it keeps the one-directional rule
precisely because settlement can be completed by "a discount fee adjustment
that reduces what is owed to what has already been paid".
recalculateMaturityOnOverpaid has no such guard and assigns "in either
direction".
Existing scenario WorkingCapitalDiscountAmortizationAdjustment.feature UC9
hits it exactly:
- 02 Jan: repayment 9900 against 10000 owed → ACTIVE, still owes 100.
- 03 Jan: discount fee adjustment of 500 drops what's owed to 9500 →
OVERPAID by 400. Reprocessing reallocates the 02 Jan repayment to 9500
principal + 400 overpayment, so overpaymentPortion (400) < transactionAmount
(9900) and it qualifies as "had a due portion".
- determineAndTransition correctly stamps maturedOnDate = 03 Jan (it was
null). recalculateSettlementDates(loan, ACTIVE) then takes the overpaid branch
and overwrites it with 02 Jan — a day the loan was ACTIVE and owed 100.
- 04 Jan: the CBR closes the loan. statusBeforeEvent is OVERPAID, so the
bidirectional branch in recalculateClosure sets both closedOnDate and
maturedOnDate to obligationsMetOn = 02 Jan.
Published timeline for UC9 goes from closedOnDate 2026-01-04 /
actualMaturityDate 2026-01-03 to 2026-01-02 / 2026-01-02. UC9 asserts status,
balances and transactions but no timeline fields, which is why CI stays green.
DISCOUNT_FEE_ADJUSTMENT (46) is not in getRepaymentLikeTransactionTypes() — I
checked it isn't aliased to CHARGE_ADJUSTMENT (26) — so the query can never
name the day that actually settled the loan.
Working through the reachable transitions, the bidirectional assignment in
recalculateMaturityOnOverpaid never helps: the case its javadoc cites ("an
extra payment onto an already closed loan") is already covered upstream by
determineAndTransition's if (getMaturedOnDate() == null) guard, and the
backdated-overpayment case (UC18) only needs the date moved later. The same
one-directional rule recalculateClosure uses would be correct in every one of
them. The already-settled branch of recalculateClosure needs the same treatment
— it can't fall back below a maturedOnDate that already records when
obligations were met.
Additional scope introduced?
the credit-balance-refund behaviour change
The CBR path is new in this revision and isn't covered by either title
claim. It changes a published API field:
WorkingCapitalLoanRepaymentOverpayment.feature UC6 had its
timeline.closedOnDate expectation edited from 2026-01-06 (the refund day) to
2026-01-04 (the day obligations were met), and
loan.setMaturedOnDate(transactionDate) became conditional. This also diverges
from core, where DefaultLoanLifecycleStateMachine stamps closedOnDate from the
CBR's own date. The reasoning in the javadoc is coherent, but closedOnDate now
names a day on which the loan's status was OVERPAID rather than closed — worth
explicit product sign-off rather than riding along on a COB-dating fix.
--
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: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]