You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CHANGELOG.md
+11Lines changed: 11 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,6 +8,17 @@
8
8
9
9
---
10
10
11
+
## [2.5.5] - 2025-06-05
12
+
13
+
### Fixed
14
+
15
+
- Reverting some of the changes made in 2.5.2, which sought to eliminate discrepancies caused by small amounts of interest at the end of a schedule.
16
+
The problem was misidentified as being due to interest/principal forgiveness whereas it was actually caused by unusual edge case of having over-refunded
17
+
the customer. A solution has now been implemented by introducing a new balance status `OverRefunded` to describe precisely this scenario and prevent any
18
+
interest being accrued from this point on in a schedule, as the resulting positive balance is not the fault of the customer.
elif principalBalance >0L<Cent>&& previousBalanceStatus = RefundDue then
442
+
OverRefunded
443
+
else
444
+
OpenBalance
437
445
438
446
/// determines whether a schedule is settled within any grace period (e.g. no interest may be due if settlement is made within three days of the advance)
439
447
letisSettledWithinGracePeriod(p:Parameters)=
@@ -500,8 +508,8 @@ module Amortisation =
500
508
501
509
/// determines any payment due on the day
502
510
letcalculatePaymentDue si originalPayment rescheduledPayment extraPaymentsBalance interestPortionL minimumPayment =
503
-
// if the balance is closed or a refund is due, no payment is due
504
-
if si.BalanceStatus = ClosedBalance || si.BalanceStatus = RefundDuethen
511
+
// if the balance is not open, no payment is due
512
+
if si.BalanceStatus <> OpenBalancethen
505
513
0L<Cent>
506
514
// otherwise, calculate the payment due based on scheduled payments and various balances
507
515
else
@@ -606,7 +614,9 @@ module Amortisation =
606
614
=
607
615
letdailyInterestRates= getDailyInterestRates p previousDay currentDay
608
616
609
-
if previous.PrincipalBalance <=0L<Cent>then
617
+
if previous.BalanceStatus = OverRefunded then
618
+
0m<Cent>
619
+
elif previous.PrincipalBalance <=0L<Cent>then
610
620
dailyInterestRates
611
621
|> Array.map (fun dr ->{
612
622
dr with
@@ -629,10 +639,11 @@ module Amortisation =
629
639
initialInterestBalanceM
630
640
actuarialInterestM //this can be higher than the capped actuarial interest because it can include an adjustment that sucks in all the lost interest from rounding
631
641
=
632
-
match interestMethod with
633
-
| Interest.Method.Actuarial -> actuarialInterestM
634
-
| Interest.Method.AddOn when previousBalanceStatus = ClosedBalance ->0m<Cent>
/// ignores small amounts of interest that have accumulated by the last day of the schedule, with the allowance being proportional to the length of the schedule
&& cappedNewInterestM =0m<Cent>// cappedNewInterest check here avoids adding an interest adjustment twice (one for generated payment, one for final payment)
// refine the settlement figure if necessary by subtracting any payment made on the same day, or nullifying it if there are payments pending (settlement cannot be made in this case)
1096
1099
letsettlementFigure=
1097
-
match pendingPaymentTotal, current.PaymentStatus, p.Basic.InterestConfig.Method with
0 commit comments