mariowise opened a new pull request, #6773:
URL: https://github.com/apache/fineract/pull/6773

   ### Steps
   
   1. Create a bullet loan: principal 100,000, grace on principal for the first 
11 of 12 monthly repayments, actual days, 360-day year, 20%.
   2. Disburse on 1 January 2026.
   3. Reschedule the interest rate to 15% from 1 May 2026.
   4. Read the interest due on the repayment for 1 June 2026.
   
   ### Actual
   
   June bills **1,291.49**. The missing **0.18** is unrecognized interest and 
is carried forward. Later grace rows do the same whenever that month's accrual 
is above the installment solved for the reschedule, and the balloon collects 
the accumulated difference.
   
   `100,000 × 15% × 31 ÷ 360 = 1,291.67`.
   
   ### Expected
   
   Each principal-grace row bills the interest that period accrued. June bills 
1,291.67, unrecognized interest on that row is 0, and the balloon bills only 
its own month of interest plus the 100,000 principal.
   
   An amortizing loan is unchanged: its installment is already principal plus 
interest, so one period of interest fits inside it. A 30-day month (`rate ÷ 
12`) is also unchanged, because the solved installment is already above that 
flat accrual.
   
   ### Cause
   
   `calculateEMIValueAndRateFactorsForDecliningBalanceInterestMethod` solves 
one equal installment and writes it onto every related period, then 
`applyPrincipalMoratoriumIfRequired` copies `getDueInterest()` onto each grace 
row.
   
   `getDueInterest()` is already `min(calculated interest, installment)`. At 
origination the solved installment is the full annuity, which is larger than 
one month of interest, so the grace row gets the full accrual. After a rate 
change the new installment can be smaller than a 31-day accrual. Grace then 
copies the smaller number.
   
   The outstanding balance also has to be refreshed while walking the grace 
rows. The solved installment is still charging a little principal on earlier 
rows in the slice, so the next row accrues on a balance slightly under the real 
outstanding and its calculated interest is already short before the cap is 
applied.
   
   ### Fix
   
   For each in-slice grace period, in due-date order:
   
   1. Refresh that row's outstanding balance from the previous row.
   2. Set the installment to `getCalculatedDueInterest()` (the uncapped 
accrual, including any unrecognized interest already carried in).
   3. Do not lower the installment below principal and interest already paid, 
net of credits.
   
   The row stays principal-grace, so principal due stays 0. The installment for 
the remaining amortizing period is solved again afterwards. With one period 
left, that is principal plus that period's own accrual.


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