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]

Reply via email to