Foo Developer created FINERACT-3034:
---------------------------------------
Summary: Loan reschedule after a 'reschedule to next repayment
date' holiday pulls every later due date back one period
Key: FINERACT-3034
URL: https://issues.apache.org/jira/browse/FINERACT-3034
Project: Apache Fineract
Issue Type: Bug
Components: Loan
Reporter: Foo Developer
Assignee: Foo Developer
h3. Steps to reproduce
# Set the global configuration {{reschedule-repayments-on-holidays}} to
{{true}}. Business date 30 October 2026.
# Create and activate a holiday for the office from 30 December 2026 to 05
January 2027 with {{reschedulingType}} = 1 (reschedule to next repayment date).
# Create, approve and disburse a cumulative loan on 30 October 2026: principal
12,000, 12 monthly repayments, 1% interest per month, declining balance, equal
installments.
The schedule is generated correctly: installment 2 is moved from 30 December
2026 to 30 January 2027, installment 3 falls on 28 February 2027 and the
maturity is 30 November 2027.
# Create a loan reschedule request with {{rescheduleFromDate}} 28 February 2027
and {{graceOnPrincipal}} 1:
{code:json} POST /fineract-provider/api/v1/rescheduleloans
{
"loanId": <loanId>,
"rescheduleFromDate": "28 February 2027",
"submittedOnDate": "30 October 2026",
"rescheduleReasonId": <codeValueId>,
"graceOnPrincipal": 1,
"dateFormat": "dd MMMM yyyy",
"locale": "en"
}
{code}
# {{GET
/fineract-provider/api/v1/rescheduleloans/<requestId>?command=previewLoanReschedule}}
h3. Expected
Installments 1 and 2 are unchanged. Installment 3 keeps its due date of 28
February 2027 and carries the principal grace (principal 0). The due dates of
the later installments are unchanged, and one installment is added at the end,
on 30 December 2027.
h3. Actual
>From the reschedule point on, every due date is one period early:
* Installment 3 runs from 30 January 2027 to 30 January 2027, a zero-length
period, and is charged its full amount.
* The principal grace lands on installment 4 (due 28 February 2027), one
installment too late.
* Every later due date is one month early, so the added installment 13 falls on
the old maturity date (30 November 2027) and the maturity does not move.
Approving the request stores this schedule.
h3. Root cause
In {{AbstractCumulativeLoanScheduleGenerator}}, the full generation
({{generate(..)}}) advances the repayment chain from
{{AdjustedDateDetailsDTO.getChangedActualRepaymentDate()}}. For a "reschedule
to next repayment date" holiday,
{{DefaultScheduledDateGenerator.checkAndUpdateWorkingDayIfRepaymentDateIsHolidayDay}}
sets that value to the date the installment was moved to, so the next
installment is generated from the moved date.
The retained-installment loop of {{rescheduleNextInstallments(..)}} calls the
same {{adjustRepaymentDate(..)}} but reads only {{getChangedScheduleDate()}},
so {{actualRepaymentDate}} stays on the unmoved date. That value is passed to
{{LoanScheduleParams.createLoanScheduleParamsForPartialUpdate(..)}}, so the
regenerated periods start one period behind the existing schedule. Every
regeneration path that goes through {{rescheduleNextInstallments}} is affected,
including loan reschedule preview and approve.
h3. Proposed fix
In the retained-installment loop of {{rescheduleNextInstallments(..)}}, keep
the {{AdjustedDateDetailsDTO}} and also set {{actualRepaymentDate =
adjustedDateDetailsDTO.getChangedActualRepaymentDate()}}, as the full
generation does. For a specific-date holiday or a non-working-day move, the
changed actual repayment date equals the input date, so those cases are
unchanged.
h3. Test
An integration test reproducing the scenario above: holiday with reschedule to
next repayment date, then a reschedule request with a principal grace. It
asserts that the previewed due dates keep the holiday move.
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)