[
https://issues.apache.org/jira/browse/FINERACT-2946?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Adam Saghy resolved FINERACT-2946.
----------------------------------
Resolution: Fixed
> Loan reschedule preview with a grace on principal randomly returns a wrong
> schedule with a balloon last installment
> -------------------------------------------------------------------------------------------------------------------
>
> Key: FINERACT-2946
> URL: https://issues.apache.org/jira/browse/FINERACT-2946
> Project: Apache Fineract
> Issue Type: Bug
> Components: Loan
> Reporter: Foo Developer
> Assignee: Foo Developer
> Priority: Major
> Fix For: 1.16.0
>
>
> h3. Summary
> The loan reschedule preview ({{GET
> /rescheduleloans/\{id\}?command=previewLoanReschedule}}) for a request with a
> grace on principal returns one of two different schedules for the same
> request. Which one comes back varies from call to call. One of them is wrong:
> it amortises the remaining principal over the grace periods too and ends in a
> large balloon installment, so the preview can disagree with the schedule that
> approval then applies.
> h3. Steps to reproduce
> # Create and disburse a loan: 12,000 principal, 1% interest per month, 12
> monthly installments, declining balance, equal installments.
> # Pay the first installment.
> # Create a reschedule request from the next unpaid installment with a grace
> on principal of 2:
> {code:json}
> {
> "loanId": <loanId>,
> "rescheduleFromDate": "<due date of an unpaid installment>",
> "graceOnPrincipal": 2,
> "rescheduleReasonId": <code value id>,
> "submittedOnDate": "<business date>",
> "dateFormat": "dd MMMM yyyy",
> "locale": "en"
> }
> {code}
> # {{GET /rescheduleloans/\{requestId\}?command=previewLoanReschedule}}, then
> reject the request.
> # Repeat steps 3 and 4 several times on the same running server.
> h3. Expected
> Every preview returns the same schedule, the one approval produces: the
> remaining principal is amortised over the installments after the grace plus
> the extension (about 1,066.18 per installment in this example).
> h3. Actual
> The installment amount after the grace alternates between the correct annuity
> and a smaller one (about 897.21 in this example), followed by a balloon last
> installment (about 2,665.08).
> h3. Root cause
> A grace on principal creates two term variations with the same applicable
> date: {{GRACE_ON_PRINCIPAL}} and its child {{EXTEND_REPAYMENT_PERIOD}}.
> * {{LoanTermVariationsData.compareTo}} orders only by applicable date (plus
> due-date/insert-installment first), so it returns 0 for these two. The sort
> is stable, so the generator sees them in input order.
> * For a preview, the input order is the iteration order of
> {{LoanRescheduleRequest.loanRescheduleRequestToTermVariationMappings}}, a
> {{HashSet}} whose element type does not override {{hashCode}}, so the order
> is effectively random.
> * In
> {{AbstractCumulativeLoanScheduleGenerator.applyExceptionLoanTermVariations}},
> {{EXTEND_REPAYMENT_PERIOD}} calls {{adjustInstallmentOrPrincipalAmount}},
> which recalculates the fixed installment from
> {{calculateNumberOfRemainingPrincipalPaymentPeriods}}. That only discounts
> the principal-grace periods registered so far. When the extension is
> processed before its grace, the grace periods are not discounted and the
> installment is amortised over too many periods.
> Approval builds its variations from {{Loan.loanTermVariations}}
> ({{@OrderBy("termApplicableFrom, id")}}), where the grace is always first, so
> approval is deterministic and correct. Only the preview is affected.
> h3. Proposed fix
> Give same-date ties in {{LoanTermVariationsData.compareTo}} a deterministic
> order:
> # due-date and insert-installment variations (keep their existing first
> place);
> # grace on principal and grace on interest;
> # extend repayment period;
> # everything else.
> This is the order approval already gets from the id ordering, so preview and
> approval agree.
> h3. Tests
> A new unit test, {{LoanTermVariationsDataTest}}, covering the same-date
> tie-breaks (grace before extend in either input order, due-date and
> insert-installment still first, different dates still ordered by date).
--
This message was sent by Atlassian Jira
(v8.20.10#820010)