alberto-art3ch commented on PR #6546:
URL: https://github.com/apache/fineract/pull/6546#issuecomment-6345969886

   > @alberto-art3ch Thanks for the updates. I re-reviewed the current head 
(`412bc3a5f4`). The code is close: I found no new correctness bugs, and the 
points from my two earlier rounds are all fixed. What is left is mostly 
follow-ups to @galovics' review.
   > 
   > ### Verified as fixed
   > * `deriveFirstRepaymentDate` has a semi-monthly branch; it respects the 
minimum gap, and a supplied `repaymentsStartingFromDate` must be a due day.
   > * Cumulative EMI with daily interest: with `isForPMT` the nominal period 
is days-in-year / 24.
   > * The `LoanProductData` copy constructor carries both days, so 
`?template=true` returns them.
   > * Re-age (command and preview) only accepts the basic frequencies, so 
`SEMI_MONTHLY` gets a 400.
   > * Product and loan both clear the days when they move to another frequency.
   > * `repaymentEvery` must be 1, and a semi-monthly loan with a `calendarId` 
is rejected.
   > * `calculateLoanSchedule` goes through `validateForCreate`, so bad days 
get a 400 there too.
   > * `SemiMonthlyDueDaysValidator` is shared by the product and loan 
validators.
   > * `toRecurrence` uses `BYSETPOS=1,-1` for second days of 29/30.
   > * Fee frequency stays limited to 0–3, so a charge can't reach the 
`UnsupportedOperationException`.
   > * Changeset renumbered to `0261`, ids in order.
   > 
   > I also checked that working-day and holiday shifts don't make later due 
dates drift: the next due date is generated from the unshifted date, and only 
"reschedule to next repayment date" moves that base, onto a real due day.
   > 
   > ### Still open
   > 1. **Setters (galovics No.6).** The reply says "the days go through the 
constructor; @Setter removed", but that is only true for 
`LoanApplicationTerms`. The days are still set after construction in:
   >    
   >    * `LoanProductAssembler` (~line 360), on the new `LoanProduct`;
   >    * `LoanApplicationTerms.toLoanProductRelatedDetail()` (~line 1794);
   >    * `LoanProductReadPlatformServiceImpl` (~line 617); `LoanProductData` 
gained non-final `@Setter` fields.
   >    
   >    `LoanProductRelatedDetail` keeps its class-level `@Setter`. Every 
construction site sets the days today, so nothing is broken, but the risk 
galovics raised is still there. Please either move the days into 
`LoanProductRelatedDetail.createFrom` and the `LoanProduct` constructor, or 
correct the reply.
   > 2. **galovics No.1** We should not force something onto other products 
where it is not supported (savings, share, etc.)
   > 3. **Per-loan override rationale (galovics No.5).** It was promised in the 
spec. The fineract-doc chapter describes what the override does, but not why it 
is needed.
   > 
   > ### Nit
   > * A product `PUT` that resends `repaymentFrequencyType: 6` without the 
days is rejected with "cannot be blank", even when the product is already 
semi-monthly and has stored days. A loan modify falls back to its stored days 
in the same situation. The doc does state the product rule, but consider 
letting the product fall back to its stored days when the frequency isn't 
changing.
   
   @adamsaghy thanks for re-checking. The three open points and the nit are 
addressed in the new commit:
   
   **1. Setters (galovics No.6).** You're right, my earlier reply only covered 
`LoanApplicationTerms`. The two days are now constructor parameters everywhere: 
`LoanProductRelatedDetail` (constructor and `createFrom`), `LoanProduct`, and 
`LoanProductData` (both fields are `final`, the `@Setter`s are gone). 
`LoanProductAssembler`, `LoanApplicationTerms.toLoanProductRelatedDetail()` and 
the read-service mapper pass them in; there is no post-construction assignment 
left. I left the pre-existing class-level `@Setter` of 
`LoanProductRelatedDetail` alone, since it predates this PR and is used by the 
update path for every other field.
   
   **2. Shared enum (galovics No.1).** I raised it on dev@ (see the screenshot 
attached). I agree a loan-only frequency type is the cleaner shape, but 
`repaymentPeriodFrequencyType` is a `PeriodFrequencyType` across the whole loan 
domain (`LoanProductRelatedDetail`, `LoanApplicationTerms`, the schedule 
generators, EMI/APR calculators, calendar utils), so changing its type is a 
refactor of its own and I'd rather do it in a follow-up PR than grow this one. 
What this PR guarantees is that no other product can be forced into it: every 
savings and deposit validator limits the frequency to `inMinMaxRange(0, 3)`, 
share lock-in does the same, and interest rate charts validate against 
`PeriodFrequencyType.integerValues()`, which excludes 6. The `case 
SEMI_MONTHLY` branches outside loans are therefore unreachable by validation; 
they only exist to keep the switches exhaustive. If you prefer, I can open the 
follow-up ticket now and link it here.
   
   **3. Per-loan override rationale (galovics No.5).** Added to the 
`fineract-doc` chapter: the product carries the default days and the loan the 
days that match the borrower's income; a payroll lender serves employers paying 
on different days (1st & 15th, 10th & 25th, 15th & last day) with otherwise 
identical product terms, so without the override it would need one product per 
pay-day pair. It follows the existing product-defaults / loan-override pattern.
   
   **Nit.** Done: a product `PUT` that resends `repaymentFrequencyType: 6` 
without the days keeps its stored days; the days are only required when the 
frequency actually changes. Integration test 
`aProductThatStaysSemiMonthlyKeepsItsDueDaysWhenTheyAreNotResent` and the doc 
rule updated accordingly.
   
   <img width="1214" height="431" alt="Screenshot 2026-10-22 at 11 31 26 AM" 
src="https://github.com/user-attachments/assets/0fb59773-a579-4740-ab64-d99f0ab67353";
 />
   


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