FINERACT-1981: Fix interest calculation when applies multi disbursement
This commit is contained in:
committed by
Adam Saghy
parent
6e6ac8ffd6
commit
8ab9c9ea9a
@@ -4082,10 +4082,10 @@ Feature: EMI calculation and repayment schedule checks for interest bearing loan
|
||||
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| | | 01 January 2024 | | 750.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||
| | | 01 January 2024 | | 250.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||
| 1 | 31 | 01 February 2024 | 22 January 2024 | 750.54 | 249.46 | 5.68 | 0.0 | 0.0 | 255.14 | 255.14 | 255.14 | 0.0 | 0.0 |
|
||||
| 2 | 29 | 01 March 2024 | 22 January 2024 | 495.4 | 255.14 | 0.0 | 0.0 | 0.0 | 255.14 | 255.14 | 255.14 | 0.0 | 0.0 |
|
||||
| 3 | 31 | 01 April 2024 | 22 January 2024 | 240.26 | 255.14 | 0.0 | 0.0 | 0.0 | 255.14 | 255.14 | 255.14 | 0.0 | 0.0 |
|
||||
| 4 | 30 | 01 May 2024 | 22 January 2024 | 0.0 | 240.26 | 0.0 | 0.0 | 0.0 | 240.26 | 240.26 | 240.26 | 0.0 | 0.0 |
|
||||
| 1 | 31 | 01 February 2024 | 22 January 2024 | 750.53 | 249.47 | 5.68 | 0.0 | 0.0 | 255.15 | 255.15 | 255.15 | 0.0 | 0.0 |
|
||||
| 2 | 29 | 01 March 2024 | 22 January 2024 | 495.38 | 255.15 | 0.0 | 0.0 | 0.0 | 255.15 | 255.15 | 255.15 | 0.0 | 0.0 |
|
||||
| 3 | 31 | 01 April 2024 | 22 January 2024 | 240.23 | 255.15 | 0.0 | 0.0 | 0.0 | 255.15 | 255.15 | 255.15 | 0.0 | 0.0 |
|
||||
| 4 | 30 | 01 May 2024 | 22 January 2024 | 0.0 | 240.23 | 0.0 | 0.0 | 0.0 | 240.23 | 240.23 | 240.23 | 0.0 | 0.0 |
|
||||
Then Loan Repayment schedule has the following data in Total row:
|
||||
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| 1000.0 | 5.68 | 0.0 | 0.0 | 1005.68 | 1005.68 | 1005.68 | 0.0 | 0.0 |
|
||||
@@ -4354,10 +4354,10 @@ Feature: EMI calculation and repayment schedule checks for interest bearing loan
|
||||
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| | | 01 January 2024 | | 250.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||
| | | 01 January 2024 | | 750.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||
| 1 | 31 | 01 February 2024 | | 753.25 | 246.75 | 8.39 | 0.0 | 0.0 | 255.14 | 0.0 | 0.0 | 0.0 | 255.14 |
|
||||
| 2 | 29 | 01 March 2024 | | 504.02 | 249.23 | 5.91 | 0.0 | 0.0 | 255.14 | 0.0 | 0.0 | 0.0 | 255.14 |
|
||||
| 3 | 31 | 01 April 2024 | | 253.11 | 250.91 | 4.23 | 0.0 | 0.0 | 255.14 | 0.0 | 0.0 | 0.0 | 255.14 |
|
||||
| 4 | 30 | 01 May 2024 | | 0.0 | 253.11 | 2.05 | 0.0 | 0.0 | 255.16 | 0.0 | 0.0 | 0.0 | 255.16 |
|
||||
| 1 | 31 | 01 February 2024 | | 753.24 | 246.76 | 8.39 | 0.0 | 0.0 | 255.15 | 0.0 | 0.0 | 0.0 | 255.15 |
|
||||
| 2 | 29 | 01 March 2024 | | 504.0 | 249.24 | 5.91 | 0.0 | 0.0 | 255.15 | 0.0 | 0.0 | 0.0 | 255.15 |
|
||||
| 3 | 31 | 01 April 2024 | | 253.08 | 250.92 | 4.23 | 0.0 | 0.0 | 255.15 | 0.0 | 0.0 | 0.0 | 255.15 |
|
||||
| 4 | 30 | 01 May 2024 | | 0.0 | 253.08 | 2.05 | 0.0 | 0.0 | 255.13 | 0.0 | 0.0 | 0.0 | 255.13 |
|
||||
Then Loan Repayment schedule has the following data in Total row:
|
||||
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| 1000.0 | 20.58 | 0.0 | 0.0 | 1020.58 | 0.0 | 0.0 | 0.0 | 1020.58 |
|
||||
@@ -4371,10 +4371,10 @@ Feature: EMI calculation and repayment schedule checks for interest bearing loan
|
||||
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| | | 01 January 2024 | | 250.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||
| | | 01 January 2024 | | 750.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||
| 1 | 31 | 01 February 2024 | 22 January 2024 | 750.54 | 249.46 | 5.68 | 0.0 | 0.0 | 255.14 | 255.14 | 255.14 | 0.0 | 0.0 |
|
||||
| 2 | 29 | 01 March 2024 | | 500.7 | 249.84 | 5.3 | 0.0 | 0.0 | 255.14 | 247.7 | 247.7 | 0.0 | 7.44 |
|
||||
| 3 | 31 | 01 April 2024 | | 249.76 | 250.94 | 4.2 | 0.0 | 0.0 | 255.14 | 0.0 | 0.0 | 0.0 | 255.14 |
|
||||
| 4 | 30 | 01 May 2024 | | 0.0 | 249.76 | 2.03 | 0.0 | 0.0 | 251.79 | 0.0 | 0.0 | 0.0 | 251.79 |
|
||||
| 1 | 31 | 01 February 2024 | 22 January 2024 | 750.53 | 249.47 | 5.68 | 0.0 | 0.0 | 255.15 | 255.15 | 255.15 | 0.0 | 0.0 |
|
||||
| 2 | 29 | 01 March 2024 | | 500.68 | 249.85 | 5.3 | 0.0 | 0.0 | 255.15 | 247.69 | 247.69 | 0.0 | 7.46 |
|
||||
| 3 | 31 | 01 April 2024 | | 249.73 | 250.95 | 4.2 | 0.0 | 0.0 | 255.15 | 0.0 | 0.0 | 0.0 | 255.15 |
|
||||
| 4 | 30 | 01 May 2024 | | 0.0 | 249.73 | 2.03 | 0.0 | 0.0 | 251.76 | 0.0 | 0.0 | 0.0 | 251.76 |
|
||||
Then Loan Repayment schedule has the following data in Total row:
|
||||
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| 1000.0 | 17.21 | 0.0 | 0.0 | 1017.21 | 502.84 | 502.84 | 0.0 | 514.37 |
|
||||
@@ -4385,19 +4385,19 @@ Feature: EMI calculation and repayment schedule checks for interest bearing loan
|
||||
| 22 January 2024 | Payout Refund | 500.0 | 494.32 | 5.68 | 0.0 | 0.0 | 505.68 | false | false |
|
||||
| 22 January 2024 | Interest Refund | 2.84 | 2.84 | 0.0 | 0.0 | 0.0 | 502.84 | false | false |
|
||||
When Admin sets the business date to "01 March 2024"
|
||||
And Customer makes "AUTOPAY" repayment on "01 March 2024" with 7.44 EUR transaction amount
|
||||
And Customer makes "AUTOPAY" repayment on "01 March 2024" with 7.46 EUR transaction amount
|
||||
When Admin sets the business date to "01 April 2024"
|
||||
And Customer makes "AUTOPAY" repayment on "01 April 2024" with 255.14 EUR transaction amount
|
||||
And Customer makes "AUTOPAY" repayment on "01 April 2024" with 255.15 EUR transaction amount
|
||||
When Admin sets the business date to "01 May 2024"
|
||||
And Customer makes "AUTOPAY" repayment on "01 May 2024" with 251.79 EUR transaction amount
|
||||
And Customer makes "AUTOPAY" repayment on "01 May 2024" with 251.76 EUR transaction amount
|
||||
Then Loan Repayment schedule has 4 periods, with the following data for periods:
|
||||
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| | | 01 January 2024 | | 250.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||
| | | 01 January 2024 | | 750.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||
| 1 | 31 | 01 February 2024 | 22 January 2024 | 750.54 | 249.46 | 5.68 | 0.0 | 0.0 | 255.14 | 255.14 | 255.14 | 0.0 | 0.0 |
|
||||
| 2 | 29 | 01 March 2024 | 01 March 2024 | 500.7 | 249.84 | 5.3 | 0.0 | 0.0 | 255.14 | 255.14 | 247.7 | 0.0 | 0.0 |
|
||||
| 3 | 31 | 01 April 2024 | 01 April 2024 | 249.76 | 250.94 | 4.2 | 0.0 | 0.0 | 255.14 | 255.14 | 0.0 | 0.0 | 0.0 |
|
||||
| 4 | 30 | 01 May 2024 | 01 May 2024 | 0.0 | 249.76 | 2.03 | 0.0 | 0.0 | 251.79 | 251.79 | 0.0 | 0.0 | 0.0 |
|
||||
| 1 | 31 | 01 February 2024 | 22 January 2024 | 750.53 | 249.47 | 5.68 | 0.0 | 0.0 | 255.15 | 255.15 | 255.15 | 0.0 | 0.0 |
|
||||
| 2 | 29 | 01 March 2024 | 01 March 2024 | 500.68 | 249.85 | 5.3 | 0.0 | 0.0 | 255.15 | 255.15 | 247.69 | 0.0 | 0.0 |
|
||||
| 3 | 31 | 01 April 2024 | 01 April 2024 | 249.73 | 250.95 | 4.2 | 0.0 | 0.0 | 255.15 | 255.15 | 0.0 | 0.0 | 0.0 |
|
||||
| 4 | 30 | 01 May 2024 | 01 May 2024 | 0.0 | 249.73 | 2.03 | 0.0 | 0.0 | 251.76 | 251.76 | 0.0 | 0.0 | 0.0 |
|
||||
Then Loan Repayment schedule has the following data in Total row:
|
||||
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| 1000.0 | 17.21 | 0.0 | 0.0 | 1017.21 | 1017.21 | 502.84 | 0.0 | 0.0 |
|
||||
@@ -4407,9 +4407,9 @@ Feature: EMI calculation and repayment schedule checks for interest bearing loan
|
||||
| 01 January 2024 | Disbursement | 750.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false | false |
|
||||
| 22 January 2024 | Payout Refund | 500.0 | 494.32 | 5.68 | 0.0 | 0.0 | 505.68 | false | false |
|
||||
| 22 January 2024 | Interest Refund | 2.84 | 2.84 | 0.0 | 0.0 | 0.0 | 502.84 | false | false |
|
||||
| 01 March 2024 | Repayment | 7.44 | 2.14 | 5.3 | 0.0 | 0.0 | 500.7 | false | false |
|
||||
| 01 April 2024 | Repayment | 255.14 | 250.94 | 4.2 | 0.0 | 0.0 | 249.76 | false | false |
|
||||
| 01 May 2024 | Repayment | 251.79 | 249.76 | 2.03 | 0.0 | 0.0 | 0.0 | false | false |
|
||||
| 01 March 2024 | Repayment | 7.46 | 2.16 | 5.3 | 0.0 | 0.0 | 500.68 | false | false |
|
||||
| 01 April 2024 | Repayment | 255.15 | 250.95 | 4.2 | 0.0 | 0.0 | 249.73 | false | false |
|
||||
| 01 May 2024 | Repayment | 251.76 | 249.73 | 2.03 | 0.0 | 0.0 | 0.0 | false | false |
|
||||
| 01 May 2024 | Accrual | 17.21 | 0.0 | 17.21 | 0.0 | 0.0 | 0.0 | false | false |
|
||||
Then Loan status will be "CLOSED_OBLIGATIONS_MET"
|
||||
|
||||
@@ -4430,10 +4430,10 @@ Feature: EMI calculation and repayment schedule checks for interest bearing loan
|
||||
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| | | 01 January 2024 | | 250.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||
| | | 07 January 2024 | | 750.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||
| 1 | 31 | 01 February 2024 | 22 January 2024 | 749.64 | 250.36 | 4.47 | 0.0 | 0.0 | 254.83 | 254.83 | 254.83 | 0.0 | 0.0 |
|
||||
| 2 | 29 | 01 March 2024 | | 500.11 | 249.53 | 5.3 | 0.0 | 0.0 | 254.83 | 247.61 | 247.61 | 0.0 | 7.22 |
|
||||
| 3 | 31 | 01 April 2024 | | 249.47 | 250.64 | 4.19 | 0.0 | 0.0 | 254.83 | 0.0 | 0.0 | 0.0 | 254.83 |
|
||||
| 4 | 30 | 01 May 2024 | | 0.0 | 249.47 | 2.02 | 0.0 | 0.0 | 251.49 | 0.0 | 0.0 | 0.0 | 251.49 |
|
||||
| 1 | 31 | 01 February 2024 | 22 January 2024 | 749.63 | 250.37 | 4.47 | 0.0 | 0.0 | 254.84 | 254.84 | 254.84 | 0.0 | 0.0 |
|
||||
| 2 | 29 | 01 March 2024 | | 500.09 | 249.54 | 5.3 | 0.0 | 0.0 | 254.84 | 247.6 | 247.6 | 0.0 | 7.24 |
|
||||
| 3 | 31 | 01 April 2024 | | 249.44 | 250.65 | 4.19 | 0.0 | 0.0 | 254.84 | 0.0 | 0.0 | 0.0 | 254.84 |
|
||||
| 4 | 30 | 01 May 2024 | | 0.0 | 249.44 | 2.02 | 0.0 | 0.0 | 251.46 | 0.0 | 0.0 | 0.0 | 251.46 |
|
||||
Then Loan Repayment schedule has the following data in Total row:
|
||||
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| 1000.0 | 15.98 | 0.0 | 0.0 | 1015.98 | 502.44 | 502.44 | 0.0 | 513.54 |
|
||||
@@ -4444,19 +4444,19 @@ Feature: EMI calculation and repayment schedule checks for interest bearing loan
|
||||
| 22 January 2024 | Merchant Issued Refund | 500.0 | 495.53 | 4.47 | 0.0 | 0.0 | 504.47 | false | false |
|
||||
| 22 January 2024 | Interest Refund | 2.44 | 2.44 | 0.0 | 0.0 | 0.0 | 502.03 | false | false |
|
||||
When Admin sets the business date to "01 March 2024"
|
||||
And Customer makes "AUTOPAY" repayment on "01 March 2024" with 7.22 EUR transaction amount
|
||||
And Customer makes "AUTOPAY" repayment on "01 March 2024" with 7.24 EUR transaction amount
|
||||
When Admin sets the business date to "01 April 2024"
|
||||
And Customer makes "AUTOPAY" repayment on "01 April 2024" with 254.83 EUR transaction amount
|
||||
And Customer makes "AUTOPAY" repayment on "01 April 2024" with 254.84 EUR transaction amount
|
||||
When Admin sets the business date to "01 May 2024"
|
||||
And Customer makes "AUTOPAY" repayment on "01 May 2024" with 251.49 EUR transaction amount
|
||||
And Customer makes "AUTOPAY" repayment on "01 May 2024" with 251.46 EUR transaction amount
|
||||
Then Loan Repayment schedule has 4 periods, with the following data for periods:
|
||||
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| | | 01 January 2024 | | 250.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||
| | | 07 January 2024 | | 750.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||
| 1 | 31 | 01 February 2024 | 22 January 2024 | 749.64 | 250.36 | 4.47 | 0.0 | 0.0 | 254.83 | 254.83 | 254.83 | 0.0 | 0.0 |
|
||||
| 2 | 29 | 01 March 2024 | 01 March 2024 | 500.11 | 249.53 | 5.3 | 0.0 | 0.0 | 254.83 | 254.83 | 247.61 | 0.0 | 0.0 |
|
||||
| 3 | 31 | 01 April 2024 | 01 April 2024 | 249.47 | 250.64 | 4.19 | 0.0 | 0.0 | 254.83 | 254.83 | 0.0 | 0.0 | 0.0 |
|
||||
| 4 | 30 | 01 May 2024 | 01 May 2024 | 0.0 | 249.47 | 2.02 | 0.0 | 0.0 | 251.49 | 251.49 | 0.0 | 0.0 | 0.0 |
|
||||
| 1 | 31 | 01 February 2024 | 22 January 2024 | 749.63 | 250.37 | 4.47 | 0.0 | 0.0 | 254.84 | 254.84 | 254.84 | 0.0 | 0.0 |
|
||||
| 2 | 29 | 01 March 2024 | 01 March 2024 | 500.09 | 249.54 | 5.3 | 0.0 | 0.0 | 254.84 | 254.84 | 247.6 | 0.0 | 0.0 |
|
||||
| 3 | 31 | 01 April 2024 | 01 April 2024 | 249.44 | 250.65 | 4.19 | 0.0 | 0.0 | 254.84 | 254.84 | 0.0 | 0.0 | 0.0 |
|
||||
| 4 | 30 | 01 May 2024 | 01 May 2024 | 0.0 | 249.44 | 2.02 | 0.0 | 0.0 | 251.46 | 251.46 | 0.0 | 0.0 | 0.0 |
|
||||
Then Loan Repayment schedule has the following data in Total row:
|
||||
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| 1000.0 | 15.98 | 0.0 | 0.0 | 1015.98 | 1015.98 | 502.44 | 0.0 | 0.0 |
|
||||
@@ -4466,9 +4466,9 @@ Feature: EMI calculation and repayment schedule checks for interest bearing loan
|
||||
| 07 January 2024 | Disbursement | 750.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false | false |
|
||||
| 22 January 2024 | Merchant Issued Refund | 500.0 | 495.53 | 4.47 | 0.0 | 0.0 | 504.47 | false | false |
|
||||
| 22 January 2024 | Interest Refund | 2.44 | 2.44 | 0.0 | 0.0 | 0.0 | 502.03 | false | false |
|
||||
| 01 March 2024 | Repayment | 7.22 | 1.92 | 5.3 | 0.0 | 0.0 | 500.11 | false | false |
|
||||
| 01 April 2024 | Repayment | 254.83 | 250.64 | 4.19 | 0.0 | 0.0 | 249.47 | false | false |
|
||||
| 01 May 2024 | Repayment | 251.49 | 249.47 | 2.02 | 0.0 | 0.0 | 0.0 | false | false |
|
||||
| 01 March 2024 | Repayment | 7.24 | 1.94 | 5.3 | 0.0 | 0.0 | 500.09 | false | false |
|
||||
| 01 April 2024 | Repayment | 254.84 | 250.65 | 4.19 | 0.0 | 0.0 | 249.44 | false | false |
|
||||
| 01 May 2024 | Repayment | 251.46 | 249.44 | 2.02 | 0.0 | 0.0 | 0.0 | false | false |
|
||||
| 01 May 2024 | Accrual | 15.98 | 0.0 | 15.98 | 0.0 | 0.0 | 0.0 | false | false |
|
||||
Then Loan status will be "CLOSED_OBLIGATIONS_MET"
|
||||
|
||||
@@ -4487,10 +4487,10 @@ Feature: EMI calculation and repayment schedule checks for interest bearing loan
|
||||
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| | | 01 January 2024 | | 250.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||
| | | 07 January 2024 | | 750.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||
| 1 | 31 | 01 February 2024 | | 752.34 | 247.66 | 7.17 | 0.0 | 0.0 | 254.83 | 0.0 | 0.0 | 0.0 | 254.83 |
|
||||
| 2 | 29 | 01 March 2024 | | 503.41 | 248.93 | 5.9 | 0.0 | 0.0 | 254.83 | 0.0 | 0.0 | 0.0 | 254.83 |
|
||||
| 3 | 31 | 01 April 2024 | | 252.8 | 250.61 | 4.22 | 0.0 | 0.0 | 254.83 | 0.0 | 0.0 | 0.0 | 254.83 |
|
||||
| 4 | 30 | 01 May 2024 | | 0.0 | 252.8 | 2.05 | 0.0 | 0.0 | 254.85 | 0.0 | 0.0 | 0.0 | 254.85 |
|
||||
| 1 | 31 | 01 February 2024 | | 752.33 | 247.67 | 7.17 | 0.0 | 0.0 | 254.84 | 0.0 | 0.0 | 0.0 | 254.84 |
|
||||
| 2 | 29 | 01 March 2024 | | 503.39 | 248.94 | 5.9 | 0.0 | 0.0 | 254.84 | 0.0 | 0.0 | 0.0 | 254.84 |
|
||||
| 3 | 31 | 01 April 2024 | | 252.77 | 250.62 | 4.22 | 0.0 | 0.0 | 254.84 | 0.0 | 0.0 | 0.0 | 254.84 |
|
||||
| 4 | 30 | 01 May 2024 | | 0.0 | 252.77 | 2.05 | 0.0 | 0.0 | 254.82 | 0.0 | 0.0 | 0.0 | 254.82 |
|
||||
Then Loan Repayment schedule has the following data in Total row:
|
||||
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| 1000.0 | 19.34 | 0.0 | 0.0 | 1019.34 | 0.0 | 0.0 | 0.0 | 1019.34 |
|
||||
@@ -4499,23 +4499,23 @@ Feature: EMI calculation and repayment schedule checks for interest bearing loan
|
||||
| 01 January 2024 | Disbursement | 250.0 | 0.0 | 0.0 | 0.0 | 0.0 | 250.0 | false | false |
|
||||
| 07 January 2024 | Disbursement | 750.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false | false |
|
||||
When Admin sets the business date to "01 February 2024"
|
||||
And Customer makes "AUTOPAY" repayment on "01 February 2024" with 254.83 EUR transaction amount
|
||||
And Customer makes "AUTOPAY" repayment on "01 February 2024" with 254.84 EUR transaction amount
|
||||
When Admin sets the business date to "01 March 2024"
|
||||
And Customer makes "AUTOPAY" repayment on "01 March 2024" with 254.83 EUR transaction amount
|
||||
And Customer makes "AUTOPAY" repayment on "01 March 2024" with 254.84 EUR transaction amount
|
||||
When Admin sets the business date to "01 April 2024"
|
||||
And Customer makes "AUTOPAY" repayment on "01 April 2024" with 254.83 EUR transaction amount
|
||||
And Customer makes "AUTOPAY" repayment on "01 April 2024" with 254.84 EUR transaction amount
|
||||
When Admin sets the business date to "01 May 2024"
|
||||
And Customer makes "AUTOPAY" repayment on "01 May 2024" with 254.85 EUR transaction amount
|
||||
And Customer makes "AUTOPAY" repayment on "01 May 2024" with 254.82 EUR transaction amount
|
||||
When Admin sets the business date to "10 May 2024"
|
||||
When Customer makes "PAYOUT_REFUND" transaction with "AUTOPAY" payment type on "10 May 2024" with 500 EUR transaction amount and system-generated Idempotency key
|
||||
Then Loan Repayment schedule has 4 periods, with the following data for periods:
|
||||
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| | | 01 January 2024 | | 250.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||
| | | 07 January 2024 | | 750.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||
| 1 | 31 | 01 February 2024 | 01 February 2024 | 752.34 | 247.66 | 7.17 | 0.0 | 0.0 | 254.83 | 254.83 | 0.0 | 0.0 | 0.0 |
|
||||
| 2 | 29 | 01 March 2024 | 01 March 2024 | 503.41 | 248.93 | 5.9 | 0.0 | 0.0 | 254.83 | 254.83 | 0.0 | 0.0 | 0.0 |
|
||||
| 3 | 31 | 01 April 2024 | 01 April 2024 | 252.8 | 250.61 | 4.22 | 0.0 | 0.0 | 254.83 | 254.83 | 0.0 | 0.0 | 0.0 |
|
||||
| 4 | 30 | 01 May 2024 | 01 May 2024 | 0.0 | 252.8 | 2.05 | 0.0 | 0.0 | 254.85 | 254.85 | 0.0 | 0.0 | 0.0 |
|
||||
| 1 | 31 | 01 February 2024 | 01 February 2024 | 752.33 | 247.67 | 7.17 | 0.0 | 0.0 | 254.84 | 254.84 | 0.0 | 0.0 | 0.0 |
|
||||
| 2 | 29 | 01 March 2024 | 01 March 2024 | 503.39 | 248.94 | 5.9 | 0.0 | 0.0 | 254.84 | 254.84 | 0.0 | 0.0 | 0.0 |
|
||||
| 3 | 31 | 01 April 2024 | 01 April 2024 | 252.77 | 250.62 | 4.22 | 0.0 | 0.0 | 254.84 | 254.84 | 0.0 | 0.0 | 0.0 |
|
||||
| 4 | 30 | 01 May 2024 | 01 May 2024 | 0.0 | 252.77 | 2.05 | 0.0 | 0.0 | 254.82 | 254.82 | 0.0 | 0.0 | 0.0 |
|
||||
Then Loan Repayment schedule has the following data in Total row:
|
||||
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| 1000.0 | 19.34 | 0.0 | 0.0 | 1019.34 | 1019.34 | 0.0 | 0.0 | 0.0 |
|
||||
@@ -4523,10 +4523,10 @@ Feature: EMI calculation and repayment schedule checks for interest bearing loan
|
||||
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
|
||||
| 01 January 2024 | Disbursement | 250.0 | 0.0 | 0.0 | 0.0 | 0.0 | 250.0 | false | false |
|
||||
| 07 January 2024 | Disbursement | 750.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false | false |
|
||||
| 01 February 2024 | Repayment | 254.83 | 247.66 | 7.17 | 0.0 | 0.0 | 752.34 | false | false |
|
||||
| 01 March 2024 | Repayment | 254.83 | 248.93 | 5.9 | 0.0 | 0.0 | 503.41 | false | false |
|
||||
| 01 April 2024 | Repayment | 254.83 | 250.61 | 4.22 | 0.0 | 0.0 | 252.8 | false | false |
|
||||
| 01 May 2024 | Repayment | 254.85 | 252.8 | 2.05 | 0.0 | 0.0 | 0.0 | false | false |
|
||||
| 01 February 2024 | Repayment | 254.84 | 247.67 | 7.17 | 0.0 | 0.0 | 752.33 | false | false |
|
||||
| 01 March 2024 | Repayment | 254.84 | 248.94 | 5.9 | 0.0 | 0.0 | 503.39 | false | false |
|
||||
| 01 April 2024 | Repayment | 254.84 | 250.62 | 4.22 | 0.0 | 0.0 | 252.77 | false | false |
|
||||
| 01 May 2024 | Repayment | 254.82 | 252.77 | 2.05 | 0.0 | 0.0 | 0.0 | false | false |
|
||||
| 01 May 2024 | Accrual | 19.34 | 0.0 | 19.34 | 0.0 | 0.0 | 0.0 | false | false |
|
||||
| 10 May 2024 | Payout Refund | 500.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | false | false |
|
||||
| 10 May 2024 | Interest Refund | 14.01 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | false | false |
|
||||
@@ -4536,10 +4536,10 @@ Feature: EMI calculation and repayment schedule checks for interest bearing loan
|
||||
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| | | 01 January 2024 | | 250.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||
| | | 07 January 2024 | | 750.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||
| 1 | 31 | 01 February 2024 | 01 February 2024 | 752.34 | 247.66 | 7.17 | 0.0 | 0.0 | 254.83 | 254.83 | 0.0 | 0.0 | 0.0 |
|
||||
| 2 | 29 | 01 March 2024 | 01 March 2024 | 503.41 | 248.93 | 5.9 | 0.0 | 0.0 | 254.83 | 254.83 | 0.0 | 0.0 | 0.0 |
|
||||
| 3 | 31 | 01 April 2024 | 01 April 2024 | 252.8 | 250.61 | 4.22 | 0.0 | 0.0 | 254.83 | 254.83 | 0.0 | 0.0 | 0.0 |
|
||||
| 4 | 30 | 01 May 2024 | 01 May 2024 | 0.0 | 252.8 | 2.05 | 0.0 | 0.0 | 254.85 | 254.85 | 0.0 | 0.0 | 0.0 |
|
||||
| 1 | 31 | 01 February 2024 | 01 February 2024 | 752.33 | 247.67 | 7.17 | 0.0 | 0.0 | 254.84 | 254.84 | 0.0 | 0.0 | 0.0 |
|
||||
| 2 | 29 | 01 March 2024 | 01 March 2024 | 503.39 | 248.94 | 5.9 | 0.0 | 0.0 | 254.84 | 254.84 | 0.0 | 0.0 | 0.0 |
|
||||
| 3 | 31 | 01 April 2024 | 01 April 2024 | 252.77 | 250.62 | 4.22 | 0.0 | 0.0 | 254.84 | 254.84 | 0.0 | 0.0 | 0.0 |
|
||||
| 4 | 30 | 01 May 2024 | 01 May 2024 | 0.0 | 252.77 | 2.05 | 0.0 | 0.0 | 254.82 | 254.82 | 0.0 | 0.0 | 0.0 |
|
||||
Then Loan Repayment schedule has the following data in Total row:
|
||||
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| 1000.0 | 19.34 | 0.0 | 0.0 | 1019.34 | 1019.34 | 0.0 | 0.0 | 0.0 |
|
||||
@@ -4547,10 +4547,10 @@ Feature: EMI calculation and repayment schedule checks for interest bearing loan
|
||||
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
|
||||
| 01 January 2024 | Disbursement | 250.0 | 0.0 | 0.0 | 0.0 | 0.0 | 250.0 | false | false |
|
||||
| 07 January 2024 | Disbursement | 750.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false | false |
|
||||
| 01 February 2024 | Repayment | 254.83 | 247.66 | 7.17 | 0.0 | 0.0 | 752.34 | false | false |
|
||||
| 01 March 2024 | Repayment | 254.83 | 248.93 | 5.9 | 0.0 | 0.0 | 503.41 | false | false |
|
||||
| 01 April 2024 | Repayment | 254.83 | 250.61 | 4.22 | 0.0 | 0.0 | 252.8 | false | false |
|
||||
| 01 May 2024 | Repayment | 254.85 | 252.8 | 2.05 | 0.0 | 0.0 | 0.0 | false | false |
|
||||
| 01 February 2024 | Repayment | 254.84 | 247.67 | 7.17 | 0.0 | 0.0 | 752.33 | false | false |
|
||||
| 01 March 2024 | Repayment | 254.84 | 248.94 | 5.9 | 0.0 | 0.0 | 503.39 | false | false |
|
||||
| 01 April 2024 | Repayment | 254.84 | 250.62 | 4.22 | 0.0 | 0.0 | 252.77 | false | false |
|
||||
| 01 May 2024 | Repayment | 254.82 | 252.77 | 2.05 | 0.0 | 0.0 | 0.0 | false | false |
|
||||
| 01 May 2024 | Accrual | 19.34 | 0.0 | 19.34 | 0.0 | 0.0 | 0.0 | false | false |
|
||||
| 10 May 2024 | Payout Refund | 500.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | false | false |
|
||||
| 10 May 2024 | Interest Refund | 14.01 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | false | false |
|
||||
|
||||
+52
-3
@@ -26,9 +26,12 @@ import java.math.MathContext;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.TreeSet;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
@@ -62,7 +65,8 @@ public class ProgressiveLoanInterestScheduleModel {
|
||||
final LoanProductMinimumRepaymentScheduleRelatedDetail loanProductRelatedDetail, final Integer installmentAmountInMultiplesOf,
|
||||
final MathContext mc) {
|
||||
this.mc = mc;
|
||||
this.repaymentPeriods = copyRepaymentPeriods(repaymentPeriods);
|
||||
this.repaymentPeriods = copyRepaymentPeriods(repaymentPeriods,
|
||||
(previousPeriod, repaymentPeriod) -> new RepaymentPeriod(previousPeriod, repaymentPeriod, mc));
|
||||
this.interestRates = new TreeSet<>(interestRates);
|
||||
this.loanProductRelatedDetail = loanProductRelatedDetail;
|
||||
this.installmentAmountInMultiplesOf = installmentAmountInMultiplesOf;
|
||||
@@ -74,11 +78,20 @@ public class ProgressiveLoanInterestScheduleModel {
|
||||
installmentAmountInMultiplesOf, mc);
|
||||
}
|
||||
|
||||
private List<RepaymentPeriod> copyRepaymentPeriods(final List<RepaymentPeriod> repaymentPeriods) {
|
||||
public ProgressiveLoanInterestScheduleModel emptyCopy() {
|
||||
final List<RepaymentPeriod> repaymentPeriodCopies = copyRepaymentPeriods(repaymentPeriods,
|
||||
(previousPeriod, repaymentPeriod) -> new RepaymentPeriod(previousPeriod, repaymentPeriod.getFromDate(),
|
||||
repaymentPeriod.getDueDate(), repaymentPeriod.getEmi().zero(), mc));
|
||||
return new ProgressiveLoanInterestScheduleModel(repaymentPeriodCopies, interestRates, loanProductRelatedDetail,
|
||||
installmentAmountInMultiplesOf, mc);
|
||||
}
|
||||
|
||||
private List<RepaymentPeriod> copyRepaymentPeriods(final List<RepaymentPeriod> repaymentPeriods,
|
||||
final BiFunction<RepaymentPeriod, RepaymentPeriod, RepaymentPeriod> repaymentCopyFunction) {
|
||||
final List<RepaymentPeriod> repaymentCopies = new ArrayList<>(repaymentPeriods.size());
|
||||
RepaymentPeriod previousPeriod = null;
|
||||
for (RepaymentPeriod repaymentPeriod : repaymentPeriods) {
|
||||
RepaymentPeriod currentPeriod = new RepaymentPeriod(previousPeriod, repaymentPeriod, mc);
|
||||
RepaymentPeriod currentPeriod = repaymentCopyFunction.apply(previousPeriod, repaymentPeriod);
|
||||
previousPeriod = currentPeriod;
|
||||
repaymentCopies.add(currentPeriod);
|
||||
}
|
||||
@@ -229,4 +242,40 @@ public class ProgressiveLoanInterestScheduleModel {
|
||||
.filter(period -> isInPeriod(transactionDate, period.getFromDate(), period.getDueDate(), period.isFirstRepaymentPeriod()))//
|
||||
.findFirst();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return repaymentPeriods.stream() //
|
||||
.filter(rp -> !rp.getEmi().isZero()) //
|
||||
.findFirst() //
|
||||
.isEmpty(); //
|
||||
}
|
||||
|
||||
/**
|
||||
* This method gives you repayment pairs to copy attributes.
|
||||
*
|
||||
* @param periodFromDueDate
|
||||
* Copy from this due periods.
|
||||
* @param copyFromPeriods
|
||||
* Copy source
|
||||
* @param copyConsumer
|
||||
* Consumer to copy attributes. Params: (from, to)
|
||||
*/
|
||||
public void copyPeriodsFrom(final LocalDate periodFromDueDate, List<RepaymentPeriod> copyFromPeriods,
|
||||
BiConsumer<RepaymentPeriod, RepaymentPeriod> copyConsumer) {
|
||||
if (copyFromPeriods.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
final Iterator<RepaymentPeriod> actualIterator = repaymentPeriods.iterator();
|
||||
final Iterator<RepaymentPeriod> copyFromIterator = copyFromPeriods.iterator();
|
||||
while (actualIterator.hasNext()) {
|
||||
final RepaymentPeriod copyFromPeriod = copyFromIterator.next();
|
||||
RepaymentPeriod actualPeriod = actualIterator.next();
|
||||
while (actualIterator.hasNext() && !copyFromPeriod.getDueDate().isEqual(actualPeriod.getDueDate())) {
|
||||
actualPeriod = actualIterator.next();
|
||||
}
|
||||
if (!actualPeriod.getDueDate().isBefore(periodFromDueDate)) {
|
||||
copyConsumer.accept(copyFromPeriod, actualPeriod);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.loanproduct.calc;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class EmiChangeOperation {
|
||||
|
||||
public enum Action {
|
||||
DISBURSEMENT, INTEREST_RATE_CHANGE
|
||||
}
|
||||
|
||||
private final Action action;
|
||||
private final LocalDate submittedOnDate;
|
||||
|
||||
private final Money amount;
|
||||
private final BigDecimal interestRate;
|
||||
|
||||
public static EmiChangeOperation disburse(final LocalDate disbursementDueDate, final Money disbursedAmount) {
|
||||
return new EmiChangeOperation(EmiChangeOperation.Action.DISBURSEMENT, disbursementDueDate, disbursedAmount, null);
|
||||
}
|
||||
|
||||
public static EmiChangeOperation changeInterestRate(final LocalDate newInterestSubmittedOnDate, final BigDecimal newInterestRate) {
|
||||
return new EmiChangeOperation(EmiChangeOperation.Action.INTEREST_RATE_CHANGE, newInterestSubmittedOnDate, null, newInterestRate);
|
||||
}
|
||||
}
|
||||
+66
-29
@@ -102,9 +102,16 @@ public final class ProgressiveEMICalculator implements EMICalculator {
|
||||
@Override
|
||||
public void addDisbursement(final ProgressiveLoanInterestScheduleModel scheduleModel, final LocalDate disbursementDueDate,
|
||||
final Money disbursedAmount) {
|
||||
scheduleModel.changeOutstandingBalanceAndUpdateInterestPeriods(disbursementDueDate, disbursedAmount, scheduleModel.zero())
|
||||
addDisbursement(scheduleModel, EmiChangeOperation.disburse(disbursementDueDate, disbursedAmount));
|
||||
}
|
||||
|
||||
private void addDisbursement(final ProgressiveLoanInterestScheduleModel scheduleModel, final EmiChangeOperation operation) {
|
||||
scheduleModel
|
||||
.changeOutstandingBalanceAndUpdateInterestPeriods(operation.getSubmittedOnDate(), operation.getAmount(),
|
||||
scheduleModel.zero())
|
||||
.ifPresent((repaymentPeriod) -> calculateEMIValueAndRateFactors(
|
||||
getEffectiveRepaymentDueDate(scheduleModel, repaymentPeriod, disbursementDueDate), scheduleModel));
|
||||
getEffectiveRepaymentDueDate(scheduleModel, repaymentPeriod, operation.getSubmittedOnDate()), scheduleModel,
|
||||
operation));
|
||||
}
|
||||
|
||||
private LocalDate getEffectiveRepaymentDueDate(final ProgressiveLoanInterestScheduleModel scheduleModel,
|
||||
@@ -125,13 +132,18 @@ public final class ProgressiveEMICalculator implements EMICalculator {
|
||||
@Override
|
||||
public void changeInterestRate(final ProgressiveLoanInterestScheduleModel scheduleModel, final LocalDate newInterestSubmittedOnDate,
|
||||
final BigDecimal newInterestRate) {
|
||||
final LocalDate interestRateChangeEffectiveDate = newInterestSubmittedOnDate.minusDays(1);
|
||||
scheduleModel.addInterestRate(interestRateChangeEffectiveDate, newInterestRate);
|
||||
changeInterestRate(scheduleModel, EmiChangeOperation.changeInterestRate(newInterestSubmittedOnDate, newInterestRate));
|
||||
}
|
||||
|
||||
private void changeInterestRate(final ProgressiveLoanInterestScheduleModel scheduleModel, final EmiChangeOperation operation) {
|
||||
final LocalDate interestRateChangeEffectiveDate = operation.getSubmittedOnDate().minusDays(1);
|
||||
scheduleModel.addInterestRate(interestRateChangeEffectiveDate, operation.getInterestRate());
|
||||
scheduleModel
|
||||
.changeOutstandingBalanceAndUpdateInterestPeriods(interestRateChangeEffectiveDate, scheduleModel.zero(),
|
||||
scheduleModel.zero())
|
||||
.ifPresent(repaymentPeriod -> calculateEMIValueAndRateFactors(
|
||||
getEffectiveRepaymentDueDate(scheduleModel, repaymentPeriod, interestRateChangeEffectiveDate), scheduleModel));
|
||||
getEffectiveRepaymentDueDate(scheduleModel, repaymentPeriod, interestRateChangeEffectiveDate), scheduleModel,
|
||||
operation));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -283,15 +295,24 @@ public final class ProgressiveEMICalculator implements EMICalculator {
|
||||
/**
|
||||
* Calculate Equal Monthly Installment value and Rate Factor -1 values for calculate Interest
|
||||
*/
|
||||
void calculateEMIValueAndRateFactors(final LocalDate calculateFromRepaymentPeriodDueDate,
|
||||
final ProgressiveLoanInterestScheduleModel scheduleModel) {
|
||||
private void calculateEMIValueAndRateFactors(final LocalDate calculateFromRepaymentPeriodDueDate,
|
||||
final ProgressiveLoanInterestScheduleModel scheduleModel, final EmiChangeOperation operation) {
|
||||
final List<RepaymentPeriod> relatedRepaymentPeriods = scheduleModel.getRelatedRepaymentPeriods(calculateFromRepaymentPeriodDueDate);
|
||||
final boolean onlyOnActualModelShouldApply = scheduleModel.isEmpty()
|
||||
|| operation.getAction() == EmiChangeOperation.Action.INTEREST_RATE_CHANGE;
|
||||
|
||||
calculateRateFactorForPeriods(relatedRepaymentPeriods, scheduleModel);
|
||||
calculateOutstandingBalance(scheduleModel);
|
||||
calculateEMIOnPeriods(relatedRepaymentPeriods, scheduleModel);
|
||||
if (onlyOnActualModelShouldApply) {
|
||||
calculateEMIOnActualModel(relatedRepaymentPeriods, scheduleModel);
|
||||
} else {
|
||||
calculateEMIOnNewEmptyModelAndMerge(relatedRepaymentPeriods, scheduleModel, operation);
|
||||
}
|
||||
calculateOutstandingBalance(scheduleModel);
|
||||
calculateLastUnpaidRepaymentPeriodEMI(scheduleModel);
|
||||
checkAndAdjustEmiIfNeededOnRelatedRepaymentPeriods(scheduleModel, relatedRepaymentPeriods);
|
||||
if (onlyOnActualModelShouldApply) {
|
||||
checkAndAdjustEmiIfNeededOnRelatedRepaymentPeriods(scheduleModel, relatedRepaymentPeriods);
|
||||
}
|
||||
}
|
||||
|
||||
private void calculateLastUnpaidRepaymentPeriodEMI(ProgressiveLoanInterestScheduleModel scheduleModel) {
|
||||
@@ -378,19 +399,19 @@ public final class ProgressiveEMICalculator implements EMICalculator {
|
||||
*
|
||||
* @return Rate Interest Rate in fraction format
|
||||
*/
|
||||
BigDecimal calcNominalInterestRatePercentage(final BigDecimal interestRate, MathContext mc) {
|
||||
private BigDecimal calcNominalInterestRatePercentage(final BigDecimal interestRate, MathContext mc) {
|
||||
return MathUtil.nullToZero(interestRate).divide(DIVISOR_100, mc);
|
||||
}
|
||||
|
||||
/**
|
||||
* * Calculate rate factors from ONLY repayment periods
|
||||
*/
|
||||
void calculateRateFactorForPeriods(final List<RepaymentPeriod> repaymentPeriods,
|
||||
private void calculateRateFactorForPeriods(final List<RepaymentPeriod> repaymentPeriods,
|
||||
final ProgressiveLoanInterestScheduleModel scheduleModel) {
|
||||
repaymentPeriods.forEach(repaymentPeriod -> calculateRateFactorForRepaymentPeriod(repaymentPeriod, scheduleModel));
|
||||
}
|
||||
|
||||
void calculateRateFactorForRepaymentPeriod(final RepaymentPeriod repaymentPeriod,
|
||||
private void calculateRateFactorForRepaymentPeriod(final RepaymentPeriod repaymentPeriod,
|
||||
final ProgressiveLoanInterestScheduleModel scheduleModel) {
|
||||
repaymentPeriod.getInterestPeriods().forEach(interestPeriod -> {
|
||||
interestPeriod.setRateFactor(calculateRateFactorPerPeriod(scheduleModel, repaymentPeriod, interestPeriod.getFromDate(),
|
||||
@@ -403,8 +424,8 @@ public final class ProgressiveEMICalculator implements EMICalculator {
|
||||
/**
|
||||
* Calculate Rate Factor for an exact Period
|
||||
*/
|
||||
BigDecimal calculateRateFactorPerPeriod(final ProgressiveLoanInterestScheduleModel scheduleModel, final RepaymentPeriod repaymentPeriod,
|
||||
final LocalDate interestPeriodFromDate, final LocalDate interestPeriodDueDate) {
|
||||
private BigDecimal calculateRateFactorPerPeriod(final ProgressiveLoanInterestScheduleModel scheduleModel,
|
||||
final RepaymentPeriod repaymentPeriod, final LocalDate interestPeriodFromDate, final LocalDate interestPeriodDueDate) {
|
||||
final MathContext mc = scheduleModel.mc();
|
||||
final LoanProductMinimumRepaymentScheduleRelatedDetail loanProductRelatedDetail = scheduleModel.loanProductRelatedDetail();
|
||||
final BigDecimal interestRate = calcNominalInterestRatePercentage(scheduleModel.getInterestRate(interestPeriodFromDate),
|
||||
@@ -443,7 +464,8 @@ public final class ProgressiveEMICalculator implements EMICalculator {
|
||||
* @param interestPeriodDueDate
|
||||
* @return
|
||||
*/
|
||||
BigDecimal calculatePeriodFractions(final LocalDate interestPeriodFromDate, final LocalDate interestPeriodDueDate, MathContext mc) {
|
||||
private BigDecimal calculatePeriodFractions(final LocalDate interestPeriodFromDate, final LocalDate interestPeriodDueDate,
|
||||
MathContext mc) {
|
||||
BigDecimal cumulatedRateFactor = BigDecimal.ZERO;
|
||||
int actualYear = interestPeriodFromDate.getYear();
|
||||
int endYear = interestPeriodDueDate.getYear();
|
||||
@@ -473,7 +495,7 @@ public final class ProgressiveEMICalculator implements EMICalculator {
|
||||
* @param calculatedDaysInPeriod
|
||||
* @return
|
||||
*/
|
||||
BigDecimal calculateRateFactorPerPeriodBasedOnRepaymentFrequency(final BigDecimal interestRate,
|
||||
private BigDecimal calculateRateFactorPerPeriodBasedOnRepaymentFrequency(final BigDecimal interestRate,
|
||||
final PeriodFrequencyType repaymentFrequency, final BigDecimal repaymentEvery, final BigDecimal daysInMonth,
|
||||
final BigDecimal daysInYear, final BigDecimal actualDaysInPeriod, final BigDecimal calculatedDaysInPeriod,
|
||||
final MathContext mc) {
|
||||
@@ -488,7 +510,7 @@ public final class ProgressiveEMICalculator implements EMICalculator {
|
||||
};
|
||||
}
|
||||
|
||||
void calculateEMIOnPeriods(final List<RepaymentPeriod> repaymentPeriods, final ProgressiveLoanInterestScheduleModel scheduleModel) {
|
||||
private void calculateEMIOnActualModel(List<RepaymentPeriod> repaymentPeriods, ProgressiveLoanInterestScheduleModel scheduleModel) {
|
||||
if (repaymentPeriods.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
@@ -496,7 +518,7 @@ public final class ProgressiveEMICalculator implements EMICalculator {
|
||||
final BigDecimal rateFactorN = MathUtil.stripTrailingZeros(calculateRateFactorPlus1N(repaymentPeriods, mc));
|
||||
final BigDecimal fnResult = MathUtil.stripTrailingZeros(calculateFnResult(repaymentPeriods, mc));
|
||||
final RepaymentPeriod startPeriod = repaymentPeriods.get(0);
|
||||
// TODO: double check
|
||||
|
||||
final Money outstandingBalance = startPeriod.getInitialBalanceForEmiRecalculation();
|
||||
|
||||
final Money equalMonthlyInstallment = Money.of(outstandingBalance.getCurrencyData(),
|
||||
@@ -511,7 +533,22 @@ public final class ProgressiveEMICalculator implements EMICalculator {
|
||||
});
|
||||
}
|
||||
|
||||
Money applyInstallmentAmountInMultiplesOf(final ProgressiveLoanInterestScheduleModel scheduleModel,
|
||||
private void calculateEMIOnNewEmptyModelAndMerge(List<RepaymentPeriod> repaymentPeriods,
|
||||
ProgressiveLoanInterestScheduleModel scheduleModel, final EmiChangeOperation operation) {
|
||||
if (repaymentPeriods.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
final ProgressiveLoanInterestScheduleModel scheduleModelCopy = scheduleModel.emptyCopy();
|
||||
addDisbursement(scheduleModelCopy, operation);
|
||||
|
||||
final LocalDate firstDueDate = repaymentPeriods.get(0).getDueDate();
|
||||
scheduleModel.copyPeriodsFrom(firstDueDate, scheduleModelCopy.repaymentPeriods(), (newRepaymentPeriod, actualRepaymentPeriod) -> {
|
||||
actualRepaymentPeriod.setEmi(actualRepaymentPeriod.getEmi().plus(newRepaymentPeriod.getEmi()));
|
||||
actualRepaymentPeriod.setOriginalEmi(actualRepaymentPeriod.getOriginalEmi().plus(newRepaymentPeriod.getOriginalEmi()));
|
||||
});
|
||||
}
|
||||
|
||||
private Money applyInstallmentAmountInMultiplesOf(final ProgressiveLoanInterestScheduleModel scheduleModel,
|
||||
final Money equalMonthlyInstallment) {
|
||||
return scheduleModel.installmentAmountInMultiplesOf() != null
|
||||
? Money.roundToMultiplesOf(equalMonthlyInstallment, scheduleModel.installmentAmountInMultiplesOf())
|
||||
@@ -534,7 +571,7 @@ public final class ProgressiveEMICalculator implements EMICalculator {
|
||||
/**
|
||||
* Calculate Rate Factor Product from rate factors
|
||||
*/
|
||||
BigDecimal calculateRateFactorPlus1N(final List<RepaymentPeriod> periods, MathContext mc) {
|
||||
private BigDecimal calculateRateFactorPlus1N(final List<RepaymentPeriod> periods, MathContext mc) {
|
||||
return periods.stream().map(RepaymentPeriod::getRateFactorPlus1).reduce(BigDecimal.ONE,
|
||||
(BigDecimal acc, BigDecimal value) -> acc.multiply(value, mc));
|
||||
}
|
||||
@@ -542,7 +579,7 @@ public final class ProgressiveEMICalculator implements EMICalculator {
|
||||
/**
|
||||
* Summarize Fn values
|
||||
*/
|
||||
BigDecimal calculateFnResult(final List<RepaymentPeriod> periods, final MathContext mc) {
|
||||
private BigDecimal calculateFnResult(final List<RepaymentPeriod> periods, final MathContext mc) {
|
||||
return periods.stream()//
|
||||
.skip(1)//
|
||||
.map(RepaymentPeriod::getRateFactorPlus1)//
|
||||
@@ -552,8 +589,8 @@ public final class ProgressiveEMICalculator implements EMICalculator {
|
||||
/**
|
||||
* Calculate the EMI (Equal Monthly Installment) value
|
||||
*/
|
||||
BigDecimal calculateEMIValue(final BigDecimal rateFactorPlus1N, final BigDecimal outstandingBalanceForRest, final BigDecimal fnResult,
|
||||
MathContext mc) {
|
||||
private BigDecimal calculateEMIValue(final BigDecimal rateFactorPlus1N, final BigDecimal outstandingBalanceForRest,
|
||||
final BigDecimal fnResult, MathContext mc) {
|
||||
return rateFactorPlus1N.multiply(outstandingBalanceForRest, mc).divide(fnResult, mc);
|
||||
}
|
||||
|
||||
@@ -581,8 +618,8 @@ public final class ProgressiveEMICalculator implements EMICalculator {
|
||||
*
|
||||
* @return Rate Factor for period
|
||||
*/
|
||||
BigDecimal rateFactorByRepaymentEveryDay(final BigDecimal interestRate, final BigDecimal repaymentEvery, final BigDecimal daysInYear,
|
||||
final BigDecimal actualDaysInPeriod, final BigDecimal calculatedDaysInPeriod, MathContext mc) {
|
||||
private BigDecimal rateFactorByRepaymentEveryDay(final BigDecimal interestRate, final BigDecimal repaymentEvery,
|
||||
final BigDecimal daysInYear, final BigDecimal actualDaysInPeriod, final BigDecimal calculatedDaysInPeriod, MathContext mc) {
|
||||
return rateFactorByRepaymentPeriod(interestRate, BigDecimal.ONE, repaymentEvery, daysInYear, actualDaysInPeriod,
|
||||
calculatedDaysInPeriod, mc);
|
||||
}
|
||||
@@ -611,8 +648,8 @@ public final class ProgressiveEMICalculator implements EMICalculator {
|
||||
*
|
||||
* @return Rate Factor for period
|
||||
*/
|
||||
BigDecimal rateFactorByRepaymentEveryWeek(final BigDecimal interestRate, final BigDecimal repaymentEvery, final BigDecimal daysInYear,
|
||||
final BigDecimal actualDaysInPeriod, final BigDecimal calculatedDaysInPeriod, MathContext mc) {
|
||||
private BigDecimal rateFactorByRepaymentEveryWeek(final BigDecimal interestRate, final BigDecimal repaymentEvery,
|
||||
final BigDecimal daysInYear, final BigDecimal actualDaysInPeriod, final BigDecimal calculatedDaysInPeriod, MathContext mc) {
|
||||
return rateFactorByRepaymentPeriod(interestRate, ONE_WEEK_IN_DAYS, repaymentEvery, daysInYear, actualDaysInPeriod,
|
||||
calculatedDaysInPeriod, mc);
|
||||
}
|
||||
@@ -678,7 +715,7 @@ public final class ProgressiveEMICalculator implements EMICalculator {
|
||||
*
|
||||
* @return Rate Factor for period
|
||||
*/
|
||||
BigDecimal rateFactorByRepaymentPeriod(final BigDecimal interestRate, final BigDecimal repaymentPeriodMultiplierInDays,
|
||||
private BigDecimal rateFactorByRepaymentPeriod(final BigDecimal interestRate, final BigDecimal repaymentPeriodMultiplierInDays,
|
||||
final BigDecimal repaymentEvery, final BigDecimal daysInYear, final BigDecimal actualDaysInPeriod,
|
||||
final BigDecimal calculatedDaysInPeriod, final MathContext mc) {
|
||||
if (MathUtil.isZero(calculatedDaysInPeriod)) {
|
||||
@@ -697,7 +734,7 @@ public final class ProgressiveEMICalculator implements EMICalculator {
|
||||
* Calculate Rate Factor based on Partial Period
|
||||
*
|
||||
*/
|
||||
BigDecimal rateFactorByRepaymentPartialPeriod(final BigDecimal interestRate, final BigDecimal repaymentEvery,
|
||||
private BigDecimal rateFactorByRepaymentPartialPeriod(final BigDecimal interestRate, final BigDecimal repaymentEvery,
|
||||
final BigDecimal cumulatedPeriodRatio, final BigDecimal actualDaysInPeriod, final BigDecimal calculatedDaysInPeriod,
|
||||
final MathContext mc) {
|
||||
if (MathUtil.isZero(calculatedDaysInPeriod)) {
|
||||
|
||||
+19
-12
@@ -953,14 +953,16 @@ class ProgressiveEMICalculatorTest {
|
||||
disbursedAmount = toMoney(25.0);
|
||||
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 8), disbursedAmount);
|
||||
|
||||
checkPeriod(interestSchedule, 0, 0, 29.94, 0.001019591398, 0.00, 1.15, 28.79, 146.21);
|
||||
checkPeriod(interestSchedule, 0, 1, 29.94, 0.000764693548, 0.08, 1.15, 28.79, 146.21);
|
||||
checkPeriod(interestSchedule, 0, 2, 29.94, 0.006117548387, 1.07, 1.15, 28.79, 146.21);
|
||||
checkPeriod(interestSchedule, 1, 0, 29.94, 0.007901833333, 1.16, 28.78, 117.43);
|
||||
checkPeriod(interestSchedule, 2, 0, 29.94, 0.007901833333, 0.93, 29.01, 88.42);
|
||||
checkPeriod(interestSchedule, 3, 0, 29.94, 0.007901833333, 0.70, 29.24, 59.18);
|
||||
checkPeriod(interestSchedule, 4, 0, 29.94, 0.007901833333, 0.47, 29.47, 29.71);
|
||||
checkPeriod(interestSchedule, 5, 0, 29.94, 0.007901833333, 0.23, 29.71, 0.0);
|
||||
checkTotalInterestDue(interestSchedule, 4.65);
|
||||
|
||||
checkPeriod(interestSchedule, 0, 0, 29.93, 0.001019591398, 0.00, 1.15, 28.78, 146.22);
|
||||
checkPeriod(interestSchedule, 0, 1, 29.93, 0.000764693548, 0.08, 1.15, 28.78, 146.22);
|
||||
checkPeriod(interestSchedule, 0, 2, 29.93, 0.006117548387, 1.07, 1.15, 28.78, 146.22);
|
||||
checkPeriod(interestSchedule, 1, 0, 29.93, 0.007901833333, 1.16, 28.77, 117.45);
|
||||
checkPeriod(interestSchedule, 2, 0, 29.93, 0.007901833333, 0.93, 29.00, 88.45);
|
||||
checkPeriod(interestSchedule, 3, 0, 29.93, 0.007901833333, 0.70, 29.23, 59.22);
|
||||
checkPeriod(interestSchedule, 4, 0, 29.93, 0.007901833333, 0.47, 29.46, 29.76);
|
||||
checkPeriod(interestSchedule, 5, 0, 30.0, 0.007901833333, 0.24, 29.76, 0.0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1034,13 +1036,13 @@ class ProgressiveEMICalculatorTest {
|
||||
emiCalculator.payPrincipal(interestSchedule, LocalDate.of(2024, 6, 1), LocalDate.of(2024, 1, 1), toMoney(51.03));
|
||||
emiCalculator.payPrincipal(interestSchedule, LocalDate.of(2024, 7, 1), LocalDate.of(2024, 1, 1), toMoney(44.85));
|
||||
|
||||
Assertions.assertEquals(0.0, toDouble(interestSchedule.getTotalDueInterest()));
|
||||
checkTotalInterestDue(interestSchedule, 0.0);
|
||||
|
||||
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), toMoney(200.0));
|
||||
Assertions.assertEquals(4.20, toDouble(interestSchedule.getTotalDueInterest()));
|
||||
checkTotalInterestDue(interestSchedule, 4.11);
|
||||
|
||||
checkEmi(interestSchedule, 4, 84.03);
|
||||
checkEmi(interestSchedule, 5, 84.05);
|
||||
checkEmi(interestSchedule, 4, 85.05);
|
||||
checkEmi(interestSchedule, 5, 78.86);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1398,6 +1400,11 @@ class ProgressiveEMICalculatorTest {
|
||||
Assertions.assertEquals(emiValue, toDouble(interestScheduleModel.repaymentPeriods().get(repaymentIdx).getEmi()));
|
||||
}
|
||||
|
||||
private static void checkTotalInterestDue(final ProgressiveLoanInterestScheduleModel interestScheduleModel,
|
||||
final double totalInterestDue) {
|
||||
Assertions.assertEquals(totalInterestDue, toDouble(interestScheduleModel.getTotalDueInterest()));
|
||||
}
|
||||
|
||||
private static void checkPeriod(final ProgressiveLoanInterestScheduleModel interestScheduleModel, final int repaymentIdx,
|
||||
final int interestIdx, final double emiValue, final double rateFactor, final double interestDue, final double principalDue,
|
||||
final double remaingBalance) {
|
||||
|
||||
+3
-3
@@ -889,7 +889,7 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest {
|
||||
transaction(171.29, "Repayment", "01 May 2021"), //
|
||||
transaction(171.29, "Repayment", "01 June 2021"), //
|
||||
transaction(171.32, "Repayment", "01 July 2021"), //
|
||||
transaction(27.77, "Accrual", "01 July 2021") //
|
||||
transaction(27.76, "Accrual", "01 July 2021") //
|
||||
); //
|
||||
});
|
||||
runAt("11 July 2021", () -> {
|
||||
@@ -909,8 +909,8 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest {
|
||||
transaction(171.29, "Repayment", "01 June 2021"), //
|
||||
transaction(171.32, "Repayment", "01 July 2021"), //
|
||||
transaction(500.0, "Payout Refund", "11 July 2021"), //
|
||||
transaction(20.41, "Interest Refund", "11 July 2021"), //
|
||||
transaction(27.77, "Accrual", "01 July 2021") //
|
||||
transaction(20.40, "Interest Refund", "11 July 2021"), //
|
||||
transaction(27.76, "Accrual", "01 July 2021") //
|
||||
); //
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user