Repository navigation
FINERACT-2816: Add monthEndDueDateStrategy and plumbing for loan products and loans - #6588
Conversation
bc39945 to
fdd78da
Compare
fdd78da to
5b1f06e
Compare
|
Align ticket id in commits (FINERACT-2885 vs branch FINERACT-2816) |
5b1f06e to
9825b23
Compare
| && loanApplicationTerms.calculateMaxDateForFixedLength().compareTo(nextRepaymentDate) != 0) { | ||
| nextRepaymentDate = loanApplicationTerms.calculateMaxDateForFixedLength(); | ||
| } | ||
| nextRepaymentDate = adjustRepaymentDate(nextRepaymentDate, loanApplicationTerms, holidayDetailDTO).getChangedScheduleDate(); |
There was a problem hiding this comment.
@Cocoa-Puffs Could you please confirm one AC14 point for progressive loans?
generateRepaymentPeriods still applies adjustRepaymentDate only to the last installment (pre-existing). AC14 says working-day/holiday adjustment then applies “as today” — so intermediate progressive due dates after FIRST_DAY_OF_NEXT_MONTH stay on the strategy date even if that day is non-working, while cumulative would move them.
Example: disbursed 31 Jan 2025, 3 months, FIRST_DAY_OF_NEXT_MONTH, weekdays only / move to next working day. Strategy gives 1 Mar 2025 (Sat); cumulative becomes 3 Mar (testRolledDateIsMovedOffNonWorkingDay), progressive would keep 1 Mar. There is no progressive counterpart of that test in this PR.
Is that the intended behaviour here, or should progressive be aligned with cumulative?
There was a problem hiding this comment.
Good catch. It looks like a genuine error, but since it's pre-existing I would rather have it fixed it in a follow-up PR than with this changeset.
|
@Cocoa-Puffs Please rebase |
|
@Cocoa-Puffs Can you please review the below concerns? 1. Re-aged installments ignore
|
9825b23 to
f76e562
Compare
|
Re-aged installments ignoring FIRST_DAY_OF_NEXT_MONTH I reproduced it before fixing. With a re-age starting 31 Jan, equal-amortization re-age produced 31 Jan, 28 Feb, 31 Mar, while the recalculated-interest path produced 31 Jan, 1 Mar, 31 Mar. Changes: Added a strategy-aware overload ScheduledDateGenerator.getRepaymentPeriodDate(frequency, n, startDate, strategy). For monthly periods it uses MonthlyDueDateResolver.plusMonths; for other frequencies it’s unchanged. Both re-age loops now pass the loan’s strategy. E2E UC9 changing a shared product UC9 now uses its own product, LP2_MONTH_END_DUE_DATE_PRODUCT_CHANGE, through a new step, "Loan product {string} dedicated to this scenario exists with monthEndDueDateStrategy {string}". The step creates the product from the LP2 roll template, or resets its strategy if it already exists, so a failed earlier run can’t leave it in the wrong state. The restore step at the end of UC9 is gone, and LP2_MONTHLY_END_DUE_DATE_ROLL is no longer modified by any scenario. |
|
@Cocoa-Puffs Please review the below: Review: FINERACT-2816 – monthEndDueDateStrategy1. Disbursement / interest-charged-from date on the 1st is unrolled as if it had rolled forward
Example:
The same misreading in 2. Whether a date was rolled is guessed from it being a 1st
The cumulative path keeps chaining from the previous due date. It infers that a 1st was rolled when the seed day is greater than 28 and the previous month is too short. Only due-date variations are treated as exceptions, so any genuine 1st that enters the chain gets misread. Example: Issue #1 has the same root cause. Computing each due date as 3. Fixed-length max date rolls forward on calendar-linked loans
Example: calendar-linked monthly loan with
4. Calendar loans accept a strategy that is then ignored
A loan-level Rejecting it in validation, or not storing it, would avoid misleading API clients. The 5. Changing the product on a loan application keeps the old product's strategy
When a loan application is modified to a different Example: a loan is created under product A ( 6. The due-date variation scan runs before the strategy short-circuit (efficiency)
Check 7.
|
f76e562 to
dacdb45
Compare
dacdb45 to
101b75c
Compare
|
I have reviewed / resolved the concerns. 1. Disbursement on the 1st unrolled. I believe the logic should stay With 5.97 periods would be correct under The comment in 2. Rolled dates inferred from the 1st. It’s chained by design: reschedules restart the chain, and the clamp keeps the original anchor after a reschedule to the 28th or later. Computing 3. Fixed-length max date on calendar loans. Fixed.
4. Calendar loans store an ignored strategy. Keeping both the stored value and the debug log, because the ticket asks for them: AC 8: “log at debug when the attribute is set but superseded by a calendar”; Rejecting the combination was the alternative the ticket considered and decided against. With the fixes in point 3 the value now has no effect anywhere. The Swagger descriptions say it doesn’t apply to loans following a meeting calendar. 5. Product change keeps the old strategy. Fixed. When a modify changes 6. Variation scan before the strategy check. Fixed. 7. Duplicated plusPeriods. Fixed. One 8. Duplicated validator. Fixed. Also found while verifying. Before disbursement, the first due date of a roll-forward loan was derived with plain |
101b75c to
2a8758b
Compare
There was a problem hiding this comment.
Reviewed against the FINERACT-2816 story. The date logic matches the ACs well: one MonthlyDueDateResolver behind both former clamp copies, the anchor is restored through unroll, meeting-calendar loans are left alone with a debug log, and the fixed-length maturity, re-age and EMI-side date paths all use the strategy. The interest behaviour also matches the intended business rule:
- 30/360: a rolled period is still one whole month, so interest per period does not change (
testRolledDueDateKeepsInterestPerPeriodUnder30360, e2e UC3/UC4). - Actual/Actual: a rolled period is a day longer and the next one a day shorter, so interest moves between the two periods (
testRolledDueDateMovesInterestBetweenPeriodsUnderActualActual, worked example on both schedule types).
PR hygiene:
- The PR description is still the empty template, and none of the checklist boxes are ticked.
- There are two commits with the same headline. Please squash them into one
FINERACT-2816: ...commit before merge.
2a8758b to
d743ac4
Compare
…ategy and plumbing for loan products and loans
…ucts and loans - E2E tests
d743ac4 to
d8cb477
Compare
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!
Your assigned reviewer(s) will follow our guidelines for code reviews.