FINERACT-1981: Fix reschedule installment for progressive loans

This commit is contained in:
Oleksii Novikov
2025-12-03 10:14:29 +01:00
committed by Adam Saghy
parent 9e32b3718d
commit c50ed19959
10 changed files with 595 additions and 219 deletions
@@ -917,7 +917,7 @@ Feature: LoanReschedule
And Loan Transactions tab has the following data:
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
| 01 January 2024 | Disbursement | 100.0 | 0.0 | 0.0 | 0.0 | 0.0 | 100.0 | false | false |
@TestRailId:C3882
Scenario: Reschedule progressive loan to 0 percent interest then back to 10 percent
When Admin sets the business date to "1 January 2024"
@@ -943,8 +943,8 @@ Feature: LoanReschedule
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
| 01 January 2024 | Disbursement | 100.0 | 0.0 | 0.0 | 0.0 | 0.0 | 100.0 | false | false |
When Admin creates and approves Loan reschedule with the following data:
| rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate |
| 02 January 2024 | 01 January 2024 | | | | | 0 |
| rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate |
| 02 January 2024 | 01 January 2024 | | | | | 0 |
Then Loan Repayment schedule has 6 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 | | 100.0 | | | 0.0 | | 0.0 | 0.0 | | | |
@@ -955,14 +955,14 @@ Feature: LoanReschedule
| 5 | 31 | 01 June 2024 | | 16.65 | 16.67 | 0.0 | 0.0 | 0.0 | 16.67 | 0.0 | 0.0 | 0.0 | 16.67 |
| 6 | 30 | 01 July 2024 | | 0.0 | 16.65 | 0.0 | 0.0 | 0.0 | 16.65 | 0.0 | 0.0 | 0.0 | 16.65 |
Then Loan Repayment schedule has the following data in Total row:
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| 100.0 | 0.0 | 0.0 | 0.0 | 100.0 | 0.0 | 0.0 | 0.0 | 100.0 |
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| 100.0 | 0.0 | 0.0 | 0.0 | 100.0 | 0.0 | 0.0 | 0.0 | 100.0 |
And Loan Transactions tab has the following data:
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
| 01 January 2024 | Disbursement | 100.0 | 0.0 | 0.0 | 0.0 | 0.0 | 100.0 | false | false |
When Admin creates and approves Loan reschedule with the following data:
| rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate |
| 03 January 2024 | 01 January 2024 | | | | | 10 |
| rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate |
| 03 January 2024 | 01 January 2024 | | | | | 10 |
Then Loan Repayment schedule has 6 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 | | 100.0 | | | 0.0 | | 0.0 | 0.0 | | | |
@@ -998,14 +998,14 @@ Feature: LoanReschedule
| 5 | 31 | 01 June 2024 | | 16.65 | 16.67 | 0.0 | 0.0 | 0.0 | 16.67 | 0.0 | 0.0 | 0.0 | 16.67 |
| 6 | 30 | 01 July 2024 | | 0.0 | 16.65 | 0.0 | 0.0 | 0.0 | 16.65 | 0.0 | 0.0 | 0.0 | 16.65 |
Then Loan Repayment schedule has the following data in Total row:
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| 100.0 | 0.0 | 0.0 | 0.0 | 100.0 | 0.0 | 0.0 | 0.0 | 100.0 |
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| 100.0 | 0.0 | 0.0 | 0.0 | 100.0 | 0.0 | 0.0 | 0.0 | 100.0 |
Then Loan Repayment schedule has the following data in Total row:
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| 100.0 | 0.0 | 0.0 | 0.0 | 100.0 | 0.0 | 0.0 | 0.0 | 100.0 |
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| 100.0 | 0.0 | 0.0 | 0.0 | 100.0 | 0.0 | 0.0 | 0.0 | 100.0 |
When Admin creates and approves Loan reschedule with the following data:
| rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate |
| 02 February 2024 | 01 January 2024 | | | | | 10 |
| rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate |
| 02 February 2024 | 01 January 2024 | | | | | 10 |
Then Loan Repayment schedule has 6 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 | | 100.0 | | | 0.0 | | 0.0 | 0.0 | | | |
@@ -1061,8 +1061,8 @@ Feature: LoanReschedule
| 5 | 31 | 01 June 2024 | | 16.99 | 16.88 | 0.28 | 0.0 | 0.0 | 17.16 | 0.0 | 0.0 | 0.0 | 17.16 |
| 6 | 30 | 01 July 2024 | | 0.0 | 16.99 | 0.14 | 0.0 | 0.0 | 17.13 | 0.0 | 0.0 | 0.0 | 17.13 |
Then Loan Repayment schedule has the following data in Total row:
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| 100.0 | 2.93 | 0.0 | 0.0 | 102.93 | 25.74 | 8.58 | 0.0 | 77.19 |
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| 100.0 | 2.93 | 0.0 | 0.0 | 102.93 | 25.74 | 8.58 | 0.0 | 77.19 |
Then Loan Transactions tab has the following data:
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
| 01 January 2024 | Disbursement | 100.0 | 0.0 | 0.0 | 0.0 | 0.0 | 100.0 | false | false |
@@ -1114,8 +1114,8 @@ Feature: LoanReschedule
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
| 24 July 2025 | Disbursement | 500.0 | 0.0 | 0.0 | 0.0 | 0.0 | 500.0 | false | false |
When Admin creates and approves Loan reschedule with the following data:
| rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate |
| 24 July 2025 | 24 July 2025 | | | | | 5 |
| rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate |
| 24 July 2025 | 24 July 2025 | | | | | 5 |
Then Loan Repayment schedule has 6 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 |
| | | 24 July 2025 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | |
@@ -1127,19 +1127,19 @@ Feature: LoanReschedule
| 6 | 31 | 24 January 2026 | | 0.0 | 84.21 | 0.35 | 0.0 | 0.0 | 84.56 | 0.0 | 0.0 | 0.0 | 84.56 |
Then Loan Repayment schedule has the following data in Total row:
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| 500.0 | 7.31 | 0.0 | 0.0 | 507.31 | 0.0 | 0.0 | 0.0 | 507.31 |
| 500.0 | 7.31 | 0.0 | 0.0 | 507.31 | 0.0 | 0.0 | 0.0 | 507.31 |
And Loan Transactions tab has the following data:
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
| 24 July 2025 | Disbursement | 500.0 | 0.0 | 0.0 | 0.0 | 0.0 | 500.0 | false | false |
Then LoanRescheduledDueAdjustScheduleBusinessEvent is raised on "24 July 2025"
@TestRailId:C4225
Scenario: Verify after reschedule of loan by changing due date, the last Accrual Activity transaction is reversed-replayed only once
Scenario: Verify after backdated repayment, the last Accrual Activity transaction is reversed-replayed only once
When Admin sets the business date to "05 September 2025"
And Admin creates a client with random data
And Admin creates a fully customized loan with the following data:
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
| LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL_ACCRUAL_ACTIVITY | 31 December 2024 | 1111 | 24.99 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 24 | MONTHS | 1 | MONTHS | 24 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
| LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL_ACCRUAL_ACTIVITY | 31 December 2024 | 1111 | 24.99 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 24 | MONTHS | 1 | MONTHS | 24 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
And Admin successfully approves the loan on "31 December 2024" with "1111" amount and expected disbursement date on "31 December 2024"
And Admin successfully disburse the loan on "31 December 2024" with "1111" EUR transaction amount
And Customer makes "AUTOPAY" repayment on "31 January 2025" with 59.26 EUR transaction amount
@@ -1169,8 +1169,267 @@ Feature: LoanReschedule
When Admin runs inline COB job for Loan
When Admin sets the business date to "10 November 2025"
When Admin runs inline COB job for Loan
And Customer makes "AUTOPAY" repayment on "29 June 2025" with 60 EUR transaction amount
Then In Loan Transactions the "1"th Transaction of "Accrual Activity" on "31 October 2025" has "1" relationship with type="REPLAYED"
Scenario: Verify progressive loan due date reschedule maintains EMI
When Admin sets the business date to "05 September 2025"
And Admin creates a client with random data
And Admin creates a fully customized loan with the following data:
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
| LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL_ACCRUAL_ACTIVITY | 31 December 2024 | 1111 | 24.99 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 24 | MONTHS | 1 | MONTHS | 24 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
And Admin successfully approves the loan on "31 December 2024" with "1111" amount and expected disbursement date on "31 December 2024"
And Admin successfully disburse the loan on "31 December 2024" with "1111" EUR transaction amount
And Customer makes "AUTOPAY" repayment on "31 January 2025" with 59.26 EUR transaction amount
And Customer makes "AUTOPAY" repayment on "28 February 2025" with 59.26 EUR transaction amount
And Customer makes "AUTOPAY" repayment on "31 March 2025" with 59.26 EUR transaction amount
And Customer makes "AUTOPAY" repayment on "30 April 2025" with 59.26 EUR transaction amount
And Customer makes "AUTOPAY" repayment on "30 May 2025" with 59.26 EUR transaction amount
And Customer makes "AUTOPAY" repayment on "29 June 2025" with 59.26 EUR transaction amount
And Customer makes "AUTOPAY" repayment on "31 July 2025" with 59.26 EUR transaction amount
And Customer makes "AUTOPAY" repayment on "31 August 2025" with 59.26 EUR transaction amount
When Admin sets the business date to "06 September 2025"
When Admin runs inline COB job for Loan
When Admin sets the business date to "11 September 2025"
When Customer undo "1"th "Repayment" transaction made on "31 August 2025"
When Admin sets the business date to "30 September 2025"
And Customer makes "AUTOPAY" repayment on "30 September 2025" with 59.26 EUR transaction amount
And Customer makes "AUTOPAY" repayment on "30 September 2025" with 59.26 EUR transaction amount
When Admin runs inline COB job for Loan
When Admin sets the business date to "10 October 2025"
When Customer undo "1"th "Repayment" transaction made on "30 September 2025"
When Customer undo "2"th "Repayment" transaction made on "30 September 2025"
When Admin sets the business date to "16 October 2025"
And Customer makes "AUTOPAY" repayment on "16 October 2025" with 60 EUR transaction amount
When Admin sets the business date to "31 October 2025"
And Customer makes "AUTOPAY" repayment on "31 October 2025" with 59.26 EUR transaction amount
And Customer makes "AUTOPAY" repayment on "31 October 2025" with 58.52 EUR transaction amount
When Admin runs inline COB job for Loan
When Admin sets the business date to "10 November 2025"
Then Loan Repayment schedule has 24 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 |
| | | 31 December 2024 | | 1111.0 | | | 0.0 | | 0.0 | 0.0 | | | |
| 1 | 31 | 31 January 2025 | 31 January 2025 | 1075.32 | 35.68 | 23.58 | 0.0 | 0.0 | 59.26 | 59.26 | 0.0 | 0.0 | 0.0 |
| 2 | 28 | 28 February 2025 | 28 February 2025 | 1036.67 | 38.65 | 20.61 | 0.0 | 0.0 | 59.26 | 59.26 | 0.0 | 0.0 | 0.0 |
| 3 | 31 | 31 March 2025 | 31 March 2025 | 999.41 | 37.26 | 22.0 | 0.0 | 0.0 | 59.26 | 59.26 | 0.0 | 0.0 | 0.0 |
| 4 | 30 | 30 April 2025 | 30 April 2025 | 960.68 | 38.73 | 20.53 | 0.0 | 0.0 | 59.26 | 59.26 | 0.0 | 0.0 | 0.0 |
| 5 | 31 | 31 May 2025 | 30 May 2025 | 921.81 | 38.87 | 20.39 | 0.0 | 0.0 | 59.26 | 59.26 | 59.26 | 0.0 | 0.0 |
| 6 | 30 | 30 June 2025 | 29 June 2025 | 881.48 | 40.33 | 18.93 | 0.0 | 0.0 | 59.26 | 59.26 | 59.26 | 0.0 | 0.0 |
| 7 | 31 | 31 July 2025 | 31 July 2025 | 840.93 | 40.55 | 18.71 | 0.0 | 0.0 | 59.26 | 59.26 | 0.0 | 0.0 | 0.0 |
| 8 | 31 | 31 August 2025 | 16 October 2025 | 799.52 | 41.41 | 17.85 | 0.0 | 0.0 | 59.26 | 59.26 | 0.0 | 59.26 | 0.0 |
| 9 | 30 | 30 September 2025 | 31 October 2025 | 756.68 | 42.84 | 16.42 | 0.0 | 0.0 | 59.26 | 59.26 | 0.0 | 59.26 | 0.0 |
| 10 | 31 | 31 October 2025 | 31 October 2025 | 713.48 | 43.2 | 16.06 | 0.0 | 0.0 | 59.26 | 59.26 | 0.0 | 0.0 | 0.0 |
| 11 | 30 | 30 November 2025 | | 668.87 | 44.61 | 14.65 | 0.0 | 0.0 | 59.26 | 0.0 | 0.0 | 0.0 | 59.26 |
| 12 | 31 | 31 December 2025 | | 623.81 | 45.06 | 14.2 | 0.0 | 0.0 | 59.26 | 0.0 | 0.0 | 0.0 | 59.26 |
| 13 | 31 | 31 January 2026 | | 577.79 | 46.02 | 13.24 | 0.0 | 0.0 | 59.26 | 0.0 | 0.0 | 0.0 | 59.26 |
| 14 | 28 | 28 February 2026 | | 529.61 | 48.18 | 11.08 | 0.0 | 0.0 | 59.26 | 0.0 | 0.0 | 0.0 | 59.26 |
| 15 | 31 | 31 March 2026 | | 481.59 | 48.02 | 11.24 | 0.0 | 0.0 | 59.26 | 0.0 | 0.0 | 0.0 | 59.26 |
| 16 | 30 | 30 April 2026 | | 432.22 | 49.37 | 9.89 | 0.0 | 0.0 | 59.26 | 0.0 | 0.0 | 0.0 | 59.26 |
| 17 | 31 | 31 May 2026 | | 382.13 | 50.09 | 9.17 | 0.0 | 0.0 | 59.26 | 0.0 | 0.0 | 0.0 | 59.26 |
| 18 | 30 | 30 June 2026 | | 330.72 | 51.41 | 7.85 | 0.0 | 0.0 | 59.26 | 0.0 | 0.0 | 0.0 | 59.26 |
| 19 | 31 | 31 July 2026 | | 278.48 | 52.24 | 7.02 | 0.0 | 0.0 | 59.26 | 0.0 | 0.0 | 0.0 | 59.26 |
| 20 | 31 | 31 August 2026 | | 225.13 | 53.35 | 5.91 | 0.0 | 0.0 | 59.26 | 0.0 | 0.0 | 0.0 | 59.26 |
| 21 | 30 | 30 September 2026 | | 170.49 | 54.64 | 4.62 | 0.0 | 0.0 | 59.26 | 0.0 | 0.0 | 0.0 | 59.26 |
| 22 | 31 | 31 October 2026 | | 114.85 | 55.64 | 3.62 | 0.0 | 0.0 | 59.26 | 0.0 | 0.0 | 0.0 | 59.26 |
| 23 | 30 | 30 November 2026 | | 57.95 | 56.9 | 2.36 | 0.0 | 0.0 | 59.26 | 0.0 | 0.0 | 0.0 | 59.26 |
| 24 | 31 | 31 December 2026 | | 0.0 | 57.95 | 1.23 | 0.0 | 0.0 | 59.18 | 0.0 | 0.0 | 0.0 | 59.18 |
When Admin creates and approves Loan reschedule with the following data:
| rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate |
| 30 November 2025 | 10 November 2025 | 31 January 2026 | | | | |
Then In Loan Transactions the "1"th Transaction of "Accrual Activity" on "31 October 2025" has "1" relationship with type="REPLAYED"
Then Loan Repayment schedule has 24 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 |
| | | 31 December 2024 | | 1111.0 | | | 0.0 | | 0.0 | 0.0 | | | |
| 1 | 31 | 31 January 2025 | 31 January 2025 | 1075.32 | 35.68 | 23.58 | 0.0 | 0.0 | 59.26 | 59.26 | 0.0 | 0.0 | 0.0 |
| 2 | 28 | 28 February 2025 | 28 February 2025 | 1036.67 | 38.65 | 20.61 | 0.0 | 0.0 | 59.26 | 59.26 | 0.0 | 0.0 | 0.0 |
| 3 | 31 | 31 March 2025 | 31 March 2025 | 999.41 | 37.26 | 22.0 | 0.0 | 0.0 | 59.26 | 59.26 | 0.0 | 0.0 | 0.0 |
| 4 | 30 | 30 April 2025 | 30 April 2025 | 960.68 | 38.73 | 20.53 | 0.0 | 0.0 | 59.26 | 59.26 | 0.0 | 0.0 | 0.0 |
| 5 | 31 | 31 May 2025 | 30 May 2025 | 921.81 | 38.87 | 20.39 | 0.0 | 0.0 | 59.26 | 59.26 | 59.26 | 0.0 | 0.0 |
| 6 | 30 | 30 June 2025 | 29 June 2025 | 881.48 | 40.33 | 18.93 | 0.0 | 0.0 | 59.26 | 59.26 | 59.26 | 0.0 | 0.0 |
| 7 | 31 | 31 July 2025 | 31 July 2025 | 840.93 | 40.55 | 18.71 | 0.0 | 0.0 | 59.26 | 59.26 | 0.0 | 0.0 | 0.0 |
| 8 | 31 | 31 August 2025 | 16 October 2025 | 799.52 | 41.41 | 17.85 | 0.0 | 0.0 | 59.26 | 59.26 | 0.0 | 59.26 | 0.0 |
| 9 | 30 | 30 September 2025 | 31 October 2025 | 756.68 | 42.84 | 16.42 | 0.0 | 0.0 | 59.26 | 59.26 | 0.0 | 59.26 | 0.0 |
| 10 | 31 | 31 October 2025 | 31 October 2025 | 713.48 | 43.2 | 16.06 | 0.0 | 0.0 | 59.26 | 59.26 | 0.0 | 0.0 | 0.0 |
| 11 | 92 | 31 January 2026 | | 699.16 | 14.32 | 44.94 | 0.0 | 0.0 | 59.26 | 0.0 | 0.0 | 0.0 | 59.26 |
| 12 | 28 | 28 February 2026 | | 653.3 | 45.86 | 13.4 | 0.0 | 0.0 | 59.26 | 0.0 | 0.0 | 0.0 | 59.26 |
| 13 | 31 | 31 March 2026 | | 607.91 | 45.39 | 13.87 | 0.0 | 0.0 | 59.26 | 0.0 | 0.0 | 0.0 | 59.26 |
| 14 | 30 | 30 April 2026 | | 561.14 | 46.77 | 12.49 | 0.0 | 0.0 | 59.26 | 0.0 | 0.0 | 0.0 | 59.26 |
| 15 | 31 | 31 May 2026 | | 513.79 | 47.35 | 11.91 | 0.0 | 0.0 | 59.26 | 0.0 | 0.0 | 0.0 | 59.26 |
| 16 | 30 | 30 June 2026 | | 465.08 | 48.71 | 10.55 | 0.0 | 0.0 | 59.26 | 0.0 | 0.0 | 0.0 | 59.26 |
| 17 | 31 | 31 July 2026 | | 415.69 | 49.39 | 9.87 | 0.0 | 0.0 | 59.26 | 0.0 | 0.0 | 0.0 | 59.26 |
| 18 | 31 | 31 August 2026 | | 365.25 | 50.44 | 8.82 | 0.0 | 0.0 | 59.26 | 0.0 | 0.0 | 0.0 | 59.26 |
| 19 | 30 | 30 September 2026 | | 313.49 | 51.76 | 7.5 | 0.0 | 0.0 | 59.26 | 0.0 | 0.0 | 0.0 | 59.26 |
| 20 | 31 | 31 October 2026 | | 260.88 | 52.61 | 6.65 | 0.0 | 0.0 | 59.26 | 0.0 | 0.0 | 0.0 | 59.26 |
| 21 | 30 | 30 November 2026 | | 206.98 | 53.9 | 5.36 | 0.0 | 0.0 | 59.26 | 0.0 | 0.0 | 0.0 | 59.26 |
| 22 | 31 | 31 December 2026 | | 152.11 | 54.87 | 4.39 | 0.0 | 0.0 | 59.26 | 0.0 | 0.0 | 0.0 | 59.26 |
| 23 | 31 | 31 January 2027 | | 96.08 | 56.03 | 3.23 | 0.0 | 0.0 | 59.26 | 0.0 | 0.0 | 0.0 | 59.26 |
| 24 | 28 | 28 February 2027 | | 0.0 | 96.08 | 1.84 | 0.0 | 0.0 | 97.92 | 0.0 | 0.0 | 0.0 | 97.92 |
Scenario: Verify basic loan rescheduling
When Admin sets the business date to "1 January 2024"
When Admin creates a client with random data
When Admin creates a fully customized loan with the following data:
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
| LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30 | 1 January 2024 | 100 | 9.4822 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 6 | MONTHS | 1 | MONTHS | 6 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
And Admin successfully approves the loan on "1 January 2024" with "100" amount and expected disbursement date on "1 January 2024"
When Admin successfully disburse the loan on "1 January 2024" with "100" EUR transaction amount
Then Loan Repayment schedule has 6 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 | | 100.0 | | | 0.0 | | 0.0 | 0.0 | | | |
| 1 | 31 | 01 February 2024 | | 83.66 | 16.34 | 0.79 | 0.0 | 0.0 | 17.13 | 0.0 | 0.0 | 0.0 | 17.13 |
| 2 | 29 | 01 March 2024 | | 67.19 | 16.47 | 0.66 | 0.0 | 0.0 | 17.13 | 0.0 | 0.0 | 0.0 | 17.13 |
| 3 | 31 | 01 April 2024 | | 50.59 | 16.6 | 0.53 | 0.0 | 0.0 | 17.13 | 0.0 | 0.0 | 0.0 | 17.13 |
| 4 | 30 | 01 May 2024 | | 33.86 | 16.73 | 0.4 | 0.0 | 0.0 | 17.13 | 0.0 | 0.0 | 0.0 | 17.13 |
| 5 | 31 | 01 June 2024 | | 17.0 | 16.86 | 0.27 | 0.0 | 0.0 | 17.13 | 0.0 | 0.0 | 0.0 | 17.13 |
| 6 | 30 | 01 July 2024 | | 0.0 | 17.0 | 0.13 | 0.0 | 0.0 | 17.13 | 0.0 | 0.0 | 0.0 | 17.13 |
Then Loan Repayment schedule has the following data in Total row:
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| 100.0 | 2.78 | 0.0 | 0.0 | 102.78 | 0.0 | 0.0 | 0.0 | 102.78 |
And Loan Transactions tab has the following data:
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
| 01 January 2024 | Disbursement | 100.0 | 0.0 | 0.0 | 0.0 | 0.0 | 100.0 | false | false |
When Admin sets the business date to "1 February 2024"
And Customer makes "AUTOPAY" repayment on "1 February 2024" with 17.13 EUR transaction amount
Then Loan Repayment schedule has 6 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 | | 100.0 | | | 0.0 | | 0.0 | 0.0 | | | |
| 1 | 31 | 01 February 2024 | 01 February 2024 | 83.66 | 16.34 | 0.79 | 0.0 | 0.0 | 17.13 | 17.13 | 0.0 | 0.0 | 0.0 |
| 2 | 29 | 01 March 2024 | | 67.19 | 16.47 | 0.66 | 0.0 | 0.0 | 17.13 | 0.0 | 0.0 | 0.0 | 17.13 |
| 3 | 31 | 01 April 2024 | | 50.59 | 16.6 | 0.53 | 0.0 | 0.0 | 17.13 | 0.0 | 0.0 | 0.0 | 17.13 |
| 4 | 30 | 01 May 2024 | | 33.86 | 16.73 | 0.4 | 0.0 | 0.0 | 17.13 | 0.0 | 0.0 | 0.0 | 17.13 |
| 5 | 31 | 01 June 2024 | | 17.0 | 16.86 | 0.27 | 0.0 | 0.0 | 17.13 | 0.0 | 0.0 | 0.0 | 17.13 |
| 6 | 30 | 01 July 2024 | | 0.0 | 17.0 | 0.13 | 0.0 | 0.0 | 17.13 | 0.0 | 0.0 | 0.0 | 17.13 |
Then Loan Repayment schedule has the following data in Total row:
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| 100.0 | 2.78 | 0.0 | 0.0 | 102.78 | 17.13 | 0.0 | 0.0 | 85.65 |
And Loan Transactions tab has the following data:
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
| 01 January 2024 | Disbursement | 100.0 | 0.0 | 0.0 | 0.0 | 0.0 | 100.0 | false | false |
| 01 February 2024 | Repayment | 17.13 | 16.34 | 0.79 | 0.0 | 0.0 | 83.66 | false | false |
When Admin sets the business date to "1 March 2024"
When Admin creates and approves Loan reschedule with the following data:
| rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate |
| 1 March 2024 | 1 March 2024 | 15 March 2024 | | | | |
Then Loan Repayment schedule has 6 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 | | 100.0 | | | 0.0 | | 0.0 | 0.0 | | | |
| 1 | 31 | 01 February 2024 | 01 February 2024 | 83.66 | 16.34 | 0.79 | 0.0 | 0.0 | 17.13 | 17.13 | 0.0 | 0.0 | 0.0 |
| 2 | 43 | 15 March 2024 | | 67.49 | 16.17 | 0.96 | 0.0 | 0.0 | 17.13 | 0.0 | 0.0 | 0.0 | 17.13 |
| 3 | 31 | 15 April 2024 | | 50.89 | 16.6 | 0.53 | 0.0 | 0.0 | 17.13 | 0.0 | 0.0 | 0.0 | 17.13 |
| 4 | 30 | 15 May 2024 | | 34.16 | 16.73 | 0.4 | 0.0 | 0.0 | 17.13 | 0.0 | 0.0 | 0.0 | 17.13 |
| 5 | 31 | 15 June 2024 | | 17.3 | 16.86 | 0.27 | 0.0 | 0.0 | 17.13 | 0.0 | 0.0 | 0.0 | 17.13 |
| 6 | 30 | 15 July 2024 | | 0.0 | 17.3 | 0.14 | 0.0 | 0.0 | 17.44 | 0.0 | 0.0 | 0.0 | 17.44 |
Scenario: Verify loan rescheduling with N+1 period
When Admin sets the business date to "1 January 2024"
When Admin creates a client with random data
When Admin creates a fully customized loan with the following data:
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
| LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30 | 1 January 2024 | 100 | 9.4822 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 6 | MONTHS | 1 | MONTHS | 6 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
And Admin successfully approves the loan on "1 January 2024" with "100" amount and expected disbursement date on "1 January 2024"
When Admin successfully disburse the loan on "1 January 2024" with "100" EUR transaction amount
Then Loan Repayment schedule has 6 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 | | 100.0 | | | 0.0 | | 0.0 | 0.0 | | | |
| 1 | 31 | 01 February 2024 | | 83.66 | 16.34 | 0.79 | 0.0 | 0.0 | 17.13 | 0.0 | 0.0 | 0.0 | 17.13 |
| 2 | 29 | 01 March 2024 | | 67.19 | 16.47 | 0.66 | 0.0 | 0.0 | 17.13 | 0.0 | 0.0 | 0.0 | 17.13 |
| 3 | 31 | 01 April 2024 | | 50.59 | 16.6 | 0.53 | 0.0 | 0.0 | 17.13 | 0.0 | 0.0 | 0.0 | 17.13 |
| 4 | 30 | 01 May 2024 | | 33.86 | 16.73 | 0.4 | 0.0 | 0.0 | 17.13 | 0.0 | 0.0 | 0.0 | 17.13 |
| 5 | 31 | 01 June 2024 | | 17.0 | 16.86 | 0.27 | 0.0 | 0.0 | 17.13 | 0.0 | 0.0 | 0.0 | 17.13 |
| 6 | 30 | 01 July 2024 | | 0.0 | 17.0 | 0.13 | 0.0 | 0.0 | 17.13 | 0.0 | 0.0 | 0.0 | 17.13 |
Then Loan Repayment schedule has the following data in Total row:
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| 100.0 | 2.78 | 0.0 | 0.0 | 102.78 | 0.0 | 0.0 | 0.0 | 102.78 |
And Loan Transactions tab has the following data:
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
| 01 January 2024 | Disbursement | 100.0 | 0.0 | 0.0 | 0.0 | 0.0 | 100.0 | false | false |
When Admin sets the business date to "1 February 2024"
And Customer makes "AUTOPAY" repayment on "1 February 2024" with 17.13 EUR transaction amount
When Admin sets the business date to "15 July 2024"
And Admin adds "LOAN_SNOOZE_FEE" due date charge with "15 July 2024" due date and 10 EUR transaction amount
Then Loan Repayment schedule has 7 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 | | 100.0 | | | 0.0 | | 0.0 | 0.0 | | | |
| 1 | 31 | 01 February 2024 | 01 February 2024 | 83.66 | 16.34 | 0.79 | 0.0 | 0.0 | 17.13 | 17.13 | 0.0 | 0.0 | 0.0 |
| 2 | 29 | 01 March 2024 | | 67.19 | 16.47 | 0.66 | 0.0 | 0.0 | 17.13 | 0.0 | 0.0 | 0.0 | 17.13 |
| 3 | 31 | 01 April 2024 | | 50.59 | 16.6 | 0.53 | 0.0 | 0.0 | 17.13 | 0.0 | 0.0 | 0.0 | 17.13 |
| 4 | 30 | 01 May 2024 | | 33.86 | 16.73 | 0.4 | 0.0 | 0.0 | 17.13 | 0.0 | 0.0 | 0.0 | 17.13 |
| 5 | 31 | 01 June 2024 | | 17.0 | 16.86 | 0.27 | 0.0 | 0.0 | 17.13 | 0.0 | 0.0 | 0.0 | 17.13 |
| 6 | 30 | 01 July 2024 | | 0.0 | 17.0 | 0.13 | 0.0 | 0.0 | 17.13 | 0.0 | 0.0 | 0.0 | 17.13 |
| 7 | 14 | 15 July 2024 | | 0.0 | 0.0 | 0.0 | 10.0 | 0.0 | 10.0 | 0.0 | 0.0 | 0.0 | 10.0 |
Then Loan Repayment schedule has the following data in Total row:
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| 100.0 | 2.78 | 10.0 | 0.0 | 112.78 | 17.13 | 0.0 | 0.0 | 95.65 |
And Loan Transactions tab has the following data:
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
| 01 January 2024 | Disbursement | 100.0 | 0.0 | 0.0 | 0.0 | 0.0 | 100.0 | false | false |
| 01 February 2024 | Repayment | 17.13 | 16.34 | 0.79 | 0.0 | 0.0 | 83.66 | false | false |
When Admin sets the business date to "1 March 2024"
When Admin creates and approves Loan reschedule with the following data:
| rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate |
| 1 March 2024 | 1 March 2024 | 30 March 2024 | | | | |
Then Loan Repayment schedule has 6 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 | | 100.0 | | | 0.0 | | 0.0 | 0.0 | | | |
| 1 | 31 | 01 February 2024 | 01 February 2024 | 83.66 | 16.34 | 0.79 | 0.0 | 0.0 | 17.13 | 17.13 | 0.0 | 0.0 | 0.0 |
| 2 | 58 | 30 March 2024 | | 67.81 | 15.85 | 1.28 | 0.0 | 0.0 | 17.13 | 0.0 | 0.0 | 0.0 | 17.13 |
| 3 | 31 | 30 April 2024 | | 51.22 | 16.59 | 0.54 | 0.0 | 0.0 | 17.13 | 0.0 | 0.0 | 0.0 | 17.13 |
| 4 | 30 | 30 May 2024 | | 34.49 | 16.73 | 0.4 | 0.0 | 0.0 | 17.13 | 0.0 | 0.0 | 0.0 | 17.13 |
| 5 | 31 | 30 June 2024 | | 17.63 | 16.86 | 0.27 | 0.0 | 0.0 | 17.13 | 0.0 | 0.0 | 0.0 | 17.13 |
| 6 | 30 | 30 July 2024 | | 0.0 | 17.63 | 0.14 | 10.0 | 0.0 | 27.77 | 0.0 | 0.0 | 0.0 | 27.77 |
Scenario: Verify loan rescheduling with automatic down payment
When Admin sets the business date to "1 January 2024"
When Admin creates a client with random data
When Admin creates a fully customized loan with the following data:
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
| LP2_ADV_PYMNT_INTEREST_RECALCULATION_DAILY_EMI_360_30_MULTIDISBURSE_AUTO_DOWNPAYMENT | 1 January 2024 | 100 | 9.4822 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 5 | MONTHS | 1 | MONTHS | 5 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
And Admin successfully approves the loan on "1 January 2024" with "100" amount and expected disbursement date on "1 January 2024"
When Admin successfully disburse the loan on "1 January 2024" with "100" EUR transaction amount
Then Loan Repayment schedule has 6 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 | | 100.0 | | | 0.0 | | 0.0 | 0.0 | | | |
| 1 | 0 | 01 January 2024 | 01 January 2024 | 75.0 | 25.0 | 0.0 | 0.0 | 0.0 | 25.0 | 25.0 | 0.0 | 0.0 | 0.0 |
| 2 | 31 | 01 February 2024 | | 60.23 | 14.77 | 0.59 | 0.0 | 0.0 | 15.36 | 0.0 | 0.0 | 0.0 | 15.36 |
| 3 | 29 | 01 March 2024 | | 45.35 | 14.88 | 0.48 | 0.0 | 0.0 | 15.36 | 0.0 | 0.0 | 0.0 | 15.36 |
| 4 | 31 | 01 April 2024 | | 30.35 | 15.0 | 0.36 | 0.0 | 0.0 | 15.36 | 0.0 | 0.0 | 0.0 | 15.36 |
| 5 | 30 | 01 May 2024 | | 15.23 | 15.12 | 0.24 | 0.0 | 0.0 | 15.36 | 0.0 | 0.0 | 0.0 | 15.36 |
| 6 | 31 | 01 June 2024 | | 0.0 | 15.23 | 0.12 | 0.0 | 0.0 | 15.35 | 0.0 | 0.0 | 0.0 | 15.35 |
Then Loan Repayment schedule has the following data in Total row:
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| 100.0 | 1.79 | 0.0 | 0.0 | 101.79 | 25.0 | 0.0 | 0.0 | 76.79 |
And Loan Transactions tab has the following data:
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
| 01 January 2024 | Disbursement | 100.0 | 0.0 | 0.0 | 0.0 | 0.0 | 100.0 | false | false |
| 01 January 2024 | Down Payment | 25.0 | 25.0 | 0.0 | 0.0 | 0.0 | 75.0 | false | false |
And Admin sets the business date to "1 February 2024"
And Customer makes "AUTOPAY" repayment on "1 February 2024" with 15.36 EUR transaction amount
Then Loan Repayment schedule has 6 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 | | 100.0 | | | 0.0 | | 0.0 | 0.0 | | | |
| 1 | 0 | 01 January 2024 | 01 January 2024 | 75.0 | 25.0 | 0.0 | 0.0 | 0.0 | 25.0 | 25.0 | 0.0 | 0.0 | 0.0 |
| 2 | 31 | 01 February 2024 | 01 February 2024 | 60.23 | 14.77 | 0.59 | 0.0 | 0.0 | 15.36 | 15.36 | 0.0 | 0.0 | 0.0 |
| 3 | 29 | 01 March 2024 | | 45.35 | 14.88 | 0.48 | 0.0 | 0.0 | 15.36 | 0.0 | 0.0 | 0.0 | 15.36 |
| 4 | 31 | 01 April 2024 | | 30.35 | 15.0 | 0.36 | 0.0 | 0.0 | 15.36 | 0.0 | 0.0 | 0.0 | 15.36 |
| 5 | 30 | 01 May 2024 | | 15.23 | 15.12 | 0.24 | 0.0 | 0.0 | 15.36 | 0.0 | 0.0 | 0.0 | 15.36 |
| 6 | 31 | 01 June 2024 | | 0.0 | 15.23 | 0.12 | 0.0 | 0.0 | 15.35 | 0.0 | 0.0 | 0.0 | 15.35 |
Then Loan Repayment schedule has the following data in Total row:
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| 100.0 | 1.79 | 0.0 | 0.0 | 101.79 | 40.36 | 0.0 | 0.0 | 61.43 |
And Loan Transactions tab has the following data:
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
| 01 January 2024 | Disbursement | 100.0 | 0.0 | 0.0 | 0.0 | 0.0 | 100.0 | false | false |
| 01 January 2024 | Down Payment | 25.0 | 25.0 | 0.0 | 0.0 | 0.0 | 75.0 | false | false |
| 01 February 2024 | Repayment | 15.36 | 14.77 | 0.59 | 0.0 | 0.0 | 60.23 | false | false |
When Admin sets the business date to "1 March 2024"
When Admin creates and approves Loan reschedule with the following data:
| rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate |
| 1 March 2024 | 1 March 2024 | 15 March 2024 | | | | |
Then Loan Repayment schedule has 6 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 | | 100.0 | | | 0.0 | | 0.0 | 0.0 | | | |
| 1 | 0 | 01 January 2024 | 01 January 2024 | 75.0 | 25.0 | 0.0 | 0.0 | 0.0 | 25.0 | 25.0 | 0.0 | 0.0 | 0.0 |
| 2 | 31 | 01 February 2024 | 01 February 2024 | 60.23 | 14.77 | 0.59 | 0.0 | 0.0 | 15.36 | 15.36 | 0.0 | 0.0 | 0.0 |
| 3 | 43 | 15 March 2024 | | 45.56 | 14.67 | 0.69 | 0.0 | 0.0 | 15.36 | 0.0 | 0.0 | 0.0 | 15.36 |
| 4 | 31 | 15 April 2024 | | 30.56 | 15.0 | 0.36 | 0.0 | 0.0 | 15.36 | 0.0 | 0.0 | 0.0 | 15.36 |
| 5 | 30 | 15 May 2024 | | 15.44 | 15.12 | 0.24 | 0.0 | 0.0 | 15.36 | 0.0 | 0.0 | 0.0 | 15.36 |
| 6 | 31 | 15 June 2024 | | 0.0 | 15.44 | 0.12 | 0.0 | 0.0 | 15.56 | 0.0 | 0.0 | 0.0 | 15.56 |
@@ -76,6 +76,11 @@ public class DefaultScheduledDateGenerator implements ScheduledDateGenerator {
private LocalDate applyLoanTermVariations(final LoanApplicationTerms loanApplicationTerms, final LocalDate scheduledDueDate) {
LocalDate modifiedScheduledDueDate = scheduledDueDate;
if (LoanScheduleType.PROGRESSIVE.equals(loanApplicationTerms.getLoanScheduleType())) {
return modifiedScheduledDueDate;
}
// due date changes should be applied only for that dueDate
if (loanApplicationTerms.getLoanTermVariations() != null) {
if (loanApplicationTerms.getLoanTermVariations().hasDueDateVariation(scheduledDueDate)) {
@@ -55,6 +55,7 @@ import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import lombok.AllArgsConstructor;
import lombok.Getter;
@@ -225,8 +226,7 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
.collect(Collectors.toCollection(ArrayList::new));
final Integer installmentAmountInMultiplesOf = loan.getLoanProductRelatedDetail().getInstallmentAmountInMultiplesOf();
ProgressiveLoanInterestScheduleModel scheduleModel = emiCalculator.generateInstallmentInterestScheduleModel(installments,
LoanConfigurationDetailsMapper.map(loan), loanTermVariations, installmentAmountInMultiplesOf,
overpaymentHolder.getMoneyObject().getMc());
LoanConfigurationDetailsMapper.map(loan), installmentAmountInMultiplesOf, overpaymentHolder.getMoneyObject().getMc());
ProgressiveTransactionCtx ctx = new ProgressiveTransactionCtx(currency, installments, charges, overpaymentHolder,
changedTransactionDetail, scheduleModel);
@@ -236,8 +236,8 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
List<LoanTransaction> overpaidTransactions = new ArrayList<>();
for (final ChangeOperation changeOperation : changeOperations) {
if (changeOperation.isLoanTermVariationsData()) {
final LoanTermVariationsData interestRateChange = changeOperation.getLoanTermVariationsData().get();
processLoanTermVariation(installments, interestRateChange, scheduleModel);
final LoanTermVariationsData termVariationsData = changeOperation.getLoanTermVariationsData().get();
processLoanTermVariation(installments, termVariationsData, scheduleModel);
} else if (changeOperation.isTransaction()) {
LoanTransaction transaction = changeOperation.getLoanTransaction().get();
if (loan.getStatus().isOverpaid() && transaction.isAccrualActivity()) {
@@ -309,10 +309,92 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
case INTEREST_PAUSE -> handleInterestPause(installments, termVariationsData, scheduleModel);
case INTEREST_RATE_FROM_INSTALLMENT -> handleChangeInterestRate(installments, termVariationsData, scheduleModel);
case EXTEND_REPAYMENT_PERIOD -> handleExtraRepaymentPeriod(installments, termVariationsData, scheduleModel);
case DUE_DATE -> handleDueDateChangeOnRepaymentPeriod(installments, termVariationsData, scheduleModel);
default -> throw new IllegalStateException("Unhandled LoanTermVariationType.");
}
}
private void handleDueDateChangeOnRepaymentPeriod(final List<LoanRepaymentScheduleInstallment> installments,
final LoanTermVariationsData termVariationsData, final ProgressiveLoanInterestScheduleModel scheduleModel) {
final LocalDate targetRepaymentPeriodDueDate = termVariationsData.getTermVariationApplicableFrom();
final LocalDate newDueDate = termVariationsData.getDateValue();
final Loan loan = installments.getFirst().getLoan();
final LoanApplicationTerms loanApplicationTerms = new LoanApplicationTerms.Builder() //
.currency(loan.getCurrency().toData()) //
.repaymentEvery(loan.getLoanProductRelatedDetail().getRepayEvery()) //
.repaymentPeriodFrequencyType(loan.getLoanProductRelatedDetail().getRepaymentPeriodFrequencyType()) //
.fixedLength(loan.getLoanProductRelatedDetail().getFixedLength()) //
.seedDate(newDueDate) //
.build();
emiCalculator.changeDueDate(scheduleModel, loanApplicationTerms, targetRepaymentPeriodDueDate, newDueDate);
IntStream.range(0, installments.size()).filter(i -> installments.get(i).getDueDate().equals(targetRepaymentPeriodDueDate))
.findFirst().ifPresent(targetInstallmentIndex -> {
long scheduleModelStartIndex = installments.subList(0, targetInstallmentIndex).stream()
.filter(inst -> !inst.isDownPayment() && !inst.isAdditional()).count();
for (int i = targetInstallmentIndex; i < installments.size(); i++) {
final LoanRepaymentScheduleInstallment installment = installments.get(i);
if (installment.isDownPayment() || installment.isAdditional()) {
continue;
}
if (scheduleModelStartIndex >= scheduleModel.repaymentPeriods().size()) {
break;
}
final RepaymentPeriod repaymentPeriod = scheduleModel.repaymentPeriods().get((int) scheduleModelStartIndex);
if (isNotObligationsMet(installment)) {
installment.updateFromDate(repaymentPeriod.getFromDate());
installment.updateDueDate(repaymentPeriod.getDueDate());
installment.updatePrincipal(repaymentPeriod.getDuePrincipal().getAmount());
installment.updateInterestCharged(repaymentPeriod.getDueInterest().getAmount());
}
scheduleModelStartIndex++;
}
});
mergeAdditionalInstallmentsBeforeMaturityDate(installments, scheduleModel, loan);
installments.sort(Comparator.comparing(LoanRepaymentScheduleInstallment::getDueDate));
int installmentNumber = 1;
for (LoanRepaymentScheduleInstallment installment : installments) {
installment.updateInstallmentNumber(installmentNumber++);
}
}
private void mergeAdditionalInstallmentsBeforeMaturityDate(final List<LoanRepaymentScheduleInstallment> installments,
final ProgressiveLoanInterestScheduleModel scheduleModel, final Loan loan) {
final LocalDate newMaturityDate = scheduleModel.repaymentPeriods().getLast().getDueDate();
final Optional<LoanRepaymentScheduleInstallment> lastRegularInstallmentOptional = installments.stream() //
.filter(i -> !i.isDownPayment() && !i.isAdditional() && !i.isReAged()) //
.reduce((first, second) -> second);
lastRegularInstallmentOptional.ifPresent(lastRegularInstallment -> {
final MonetaryCurrency currency = loan.getCurrency();
installments.stream() //
.filter(i -> i.isAdditional() && i.getDueDate() != null && i.getDueDate().isBefore(newMaturityDate))
.forEach(additionalInstallment -> {
final Money mergedFees = lastRegularInstallment.getFeeChargesCharged(currency)
.plus(additionalInstallment.getFeeChargesCharged(currency));
lastRegularInstallment.setFeeChargesCharged(mergedFees.getAmount());
final Money mergedPenalties = lastRegularInstallment.getPenaltyChargesCharged(currency)
.plus(additionalInstallment.getPenaltyChargesCharged(currency));
lastRegularInstallment.setPenaltyCharges(mergedPenalties.getAmount());
additionalInstallment.getInstallmentCharges().forEach(charge -> {
lastRegularInstallment.getInstallmentCharges().add(charge);
charge.setInstallment(lastRegularInstallment);
});
});
installments.removeIf(i -> i.isAdditional() && i.getDueDate() != null && i.getDueDate().isBefore(newMaturityDate));
});
}
private void handleExtraRepaymentPeriod(final List<LoanRepaymentScheduleInstallment> installments,
final LoanTermVariationsData termVariationsData, final ProgressiveLoanInterestScheduleModel scheduleModel) {
final LocalDate interestRateChangeSubmittedOnDate = termVariationsData.getTermVariationApplicableFrom();
@@ -1266,7 +1348,7 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
.collect(Collectors.groupingBy(ltvd -> LoanTermVariationType.fromInt(ltvd.getTermType().getId().intValue())));
Stream.of(LoanTermVariationType.INTEREST_RATE_FROM_INSTALLMENT, LoanTermVariationType.INTEREST_PAUSE,
LoanTermVariationType.EXTEND_REPAYMENT_PERIOD).forEach(key -> {
LoanTermVariationType.EXTEND_REPAYMENT_PERIOD, LoanTermVariationType.DUE_DATE).forEach(key -> {
if (loanTermVariationsMap.get(key) != null) {
changeOperations.addAll(loanTermVariationsMap.get(key).stream().map(ChangeOperation::new).toList());
}
@@ -37,7 +37,6 @@ import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
import org.apache.fineract.organisation.monetary.domain.Money;
import org.apache.fineract.portfolio.loanaccount.data.DisbursementData;
import org.apache.fineract.portfolio.loanaccount.data.HolidayDetailDTO;
import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData;
import org.apache.fineract.portfolio.loanaccount.data.OutstandingAmountsDTO;
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
@@ -106,11 +105,8 @@ public class ProgressiveLoanScheduleGenerator implements LoanScheduleGenerator {
// generate list of proposed schedule due dates
final List<LoanScheduleModelRepaymentPeriod> expectedRepaymentPeriods = scheduledDateGenerator.generateRepaymentPeriods(mc,
periodStartDate, loanApplicationTerms, holidayDetailDTO);
List<LoanTermVariationsData> loanTermVariations = loanApplicationTerms.getLoanTermVariations() != null
? loanApplicationTerms.getLoanTermVariations().getExceptionData()
: null;
final ProgressiveLoanInterestScheduleModel interestScheduleModel = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanApplicationTerms.toLoanConfigurationDetails(), loanTermVariations,
expectedRepaymentPeriods, loanApplicationTerms.toLoanConfigurationDetails(),
loanApplicationTerms.getInstallmentAmountInMultiplesOf(), mc);
final List<LoanScheduleModelPeriod> periods = new ArrayList<>(expectedRepaymentPeriods.size());
@@ -58,7 +58,7 @@ public class InterestScheduleModelServiceGsonContext {
public ProgressiveLoanInterestScheduleModel createProgressiveLoanInterestScheduleModelInstance(Type type) {
if (type == ProgressiveLoanInterestScheduleModel.class) {
setPrev(null);
return new ProgressiveLoanInterestScheduleModel(new ArrayList<>(), getLoanProductRelatedDetail(), new ArrayList<>(),
return new ProgressiveLoanInterestScheduleModel(new ArrayList<>(), getLoanProductRelatedDetail(),
installmentAmountInMultipliesOf, getMc());
}
throw new IllegalArgumentException("Unsupported ProgressiveLoanInterestScheduleModel type: " + type);
@@ -26,7 +26,6 @@ import java.util.List;
import java.util.Optional;
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
import org.apache.fineract.organisation.monetary.domain.Money;
import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData;
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
import org.apache.fineract.portfolio.loanaccount.domain.reaging.LoanReAgeParameter;
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanApplicationTerms;
@@ -46,8 +45,7 @@ public interface EMICalculator {
*/
@NotNull
ProgressiveLoanInterestScheduleModel generatePeriodInterestScheduleModel(@NotNull List<LoanScheduleModelRepaymentPeriod> periods,
@NotNull ILoanConfigurationDetails loanProductRelatedDetail, List<LoanTermVariationsData> loanTermVariations,
Integer installmentAmountInMultiplesOf, MathContext mc);
@NotNull ILoanConfigurationDetails loanProductRelatedDetail, Integer installmentAmountInMultiplesOf, MathContext mc);
/**
* This method creates an Interest model with repayment periods from the installments which retrieved from the
@@ -56,7 +54,7 @@ public interface EMICalculator {
@NotNull
ProgressiveLoanInterestScheduleModel generateInstallmentInterestScheduleModel(
@NotNull List<LoanRepaymentScheduleInstallment> installments, @NotNull ILoanConfigurationDetails loanProductRelatedDetail,
List<LoanTermVariationsData> loanTermVariations, Integer installmentAmountInMultiplesOf, MathContext mc);
Integer installmentAmountInMultiplesOf, MathContext mc);
/**
* Find repayment period based on Due Date.
@@ -169,4 +167,7 @@ public interface EMICalculator {
EqualAmortizationValues calculateAdjustedEqualAmortizationValues(Money outstanding, Money total,
Money sumOfOtherEqualAmortizationValues, Integer numberOfInstallments, Integer installmentAmountInMultiplesOf,
MonetaryCurrency currency);
void changeDueDate(ProgressiveLoanInterestScheduleModel scheduleModel, LoanApplicationTerms loanApplicationTerms,
LocalDate targetRepaymentPeriodDueDate, LocalDate newDueDate);
}
@@ -45,9 +45,7 @@ import org.apache.fineract.portfolio.common.domain.DaysInMonthType;
import org.apache.fineract.portfolio.common.domain.DaysInYearCustomStrategyType;
import org.apache.fineract.portfolio.common.domain.DaysInYearType;
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData;
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
import org.apache.fineract.portfolio.loanaccount.domain.LoanTermVariationType;
import org.apache.fineract.portfolio.loanaccount.domain.reaging.LoanReAgeInterestHandlingType;
import org.apache.fineract.portfolio.loanaccount.domain.reaging.LoanReAgeParameter;
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanApplicationTerms;
@@ -77,28 +75,26 @@ public final class ProgressiveEMICalculator implements EMICalculator {
@Override
@NotNull
public ProgressiveLoanInterestScheduleModel generatePeriodInterestScheduleModel(@NotNull List<LoanScheduleModelRepaymentPeriod> periods,
@NotNull ILoanConfigurationDetails loanProductRelatedDetail, List<LoanTermVariationsData> loanTermVariations,
final Integer installmentAmountInMultiplesOf, final MathContext mc) {
@NotNull ILoanConfigurationDetails loanProductRelatedDetail, final Integer installmentAmountInMultiplesOf,
final MathContext mc) {
return generateInterestScheduleModel(periods, LoanScheduleModelRepaymentPeriod::periodFromDate,
LoanScheduleModelRepaymentPeriod::periodDueDate, loanProductRelatedDetail, loanTermVariations,
installmentAmountInMultiplesOf, mc);
LoanScheduleModelRepaymentPeriod::periodDueDate, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
}
@Override
@NotNull
public ProgressiveLoanInterestScheduleModel generateInstallmentInterestScheduleModel(
@NotNull List<LoanRepaymentScheduleInstallment> installments, @NotNull ILoanConfigurationDetails loanProductRelatedDetail,
List<LoanTermVariationsData> loanTermVariations, final Integer installmentAmountInMultiplesOf, final MathContext mc) {
final Integer installmentAmountInMultiplesOf, final MathContext mc) {
installments = installments.stream().filter(installment -> !installment.isDownPayment() && !installment.isAdditional()).toList();
return generateInterestScheduleModel(installments, LoanRepaymentScheduleInstallment::getFromDate,
LoanRepaymentScheduleInstallment::getDueDate, loanProductRelatedDetail, loanTermVariations, installmentAmountInMultiplesOf,
mc);
LoanRepaymentScheduleInstallment::getDueDate, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
}
@NotNull
private <T> ProgressiveLoanInterestScheduleModel generateInterestScheduleModel(@NotNull List<T> periods, Function<T, LocalDate> from,
Function<T, LocalDate> to, @NotNull ILoanConfigurationDetails loanProductRelatedDetail,
List<LoanTermVariationsData> loanTermVariations, final Integer installmentAmountInMultiplesOf, final MathContext mc) {
final Integer installmentAmountInMultiplesOf, final MathContext mc) {
final Money zero = Money.zero(loanProductRelatedDetail.getCurrencyData(), mc);
final AtomicReference<RepaymentPeriod> prev = new AtomicReference<>();
List<RepaymentPeriod> repaymentPeriods = periods.stream().map(e -> {
@@ -106,8 +102,7 @@ public final class ProgressiveEMICalculator implements EMICalculator {
prev.set(rp);
return rp;
}).toList();
return new ProgressiveLoanInterestScheduleModel(repaymentPeriods, loanProductRelatedDetail, loanTermVariations,
installmentAmountInMultiplesOf, mc);
return new ProgressiveLoanInterestScheduleModel(repaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
}
@Override
@@ -566,8 +561,7 @@ public final class ProgressiveEMICalculator implements EMICalculator {
}
calculateOutstandingBalance(scheduleModel);
calculateLastUnpaidRepaymentPeriodEMI(scheduleModel, calculateFromRepaymentPeriodDueDate);
if (onlyOnActualModelShouldApply && (scheduleModel.loanTermVariations() == null
|| scheduleModel.loanTermVariations().get(LoanTermVariationType.DUE_DATE) == null)) {
if (onlyOnActualModelShouldApply) {
checkAndAdjustEmiIfNeededOnRelatedRepaymentPeriods(scheduleModel, relatedRepaymentPeriods);
}
}
@@ -638,6 +632,62 @@ public final class ProgressiveEMICalculator implements EMICalculator {
.reduce(scheduleModel.zero(), Money::add);
}
@Override
public void changeDueDate(final ProgressiveLoanInterestScheduleModel scheduleModel, final LoanApplicationTerms loanApplicationTerms,
final LocalDate targetRepaymentPeriodDueDate, LocalDate newDueDate) {
final RepaymentPeriod targetRepaymentPeriod = scheduleModel.findRepaymentPeriod(targetRepaymentPeriodDueDate).orElseThrow();
targetRepaymentPeriod.setDueDate(newDueDate);
if (!targetRepaymentPeriod.getInterestPeriods().isEmpty()) {
final InterestPeriod lastInterestPeriod = targetRepaymentPeriod.getInterestPeriods().getLast();
lastInterestPeriod.setDueDate(newDueDate);
}
final int targetRepaymentPeriodIndex = scheduleModel.repaymentPeriods().indexOf(targetRepaymentPeriod);
final int lastRepaymentPeriodIndex = scheduleModel.repaymentPeriods().size() - 1;
final LocalDate originalNewDueDate = newDueDate;
for (int i = targetRepaymentPeriodIndex + 1; i < scheduleModel.repaymentPeriods().size(); ++i) {
final RepaymentPeriod nextRepaymentPeriod = scheduleModel.repaymentPeriods().get(i);
nextRepaymentPeriod.setFromDate(newDueDate);
LocalDate nextRepaymentDate = scheduledDateGenerator.generateNextRepaymentDate(newDueDate, loanApplicationTerms, false);
if (i == lastRepaymentPeriodIndex && loanApplicationTerms.getFixedLength() != null) {
nextRepaymentDate = calculateDateForFixedLength(scheduleModel, loanApplicationTerms, targetRepaymentPeriodDueDate,
originalNewDueDate);
}
nextRepaymentPeriod.setDueDate(nextRepaymentDate);
if (!nextRepaymentPeriod.getInterestPeriods().isEmpty()) {
nextRepaymentPeriod.getInterestPeriods().getFirst().setFromDate(newDueDate);
final InterestPeriod lastInterestPeriod = nextRepaymentPeriod.getInterestPeriods().getLast();
lastInterestPeriod.setDueDate(nextRepaymentDate);
}
newDueDate = nextRepaymentDate;
}
final List<RepaymentPeriod> relatedRepaymentPeriods = scheduleModel.getRelatedRepaymentPeriods(targetRepaymentPeriodDueDate);
calculateRateFactorForPeriods(relatedRepaymentPeriods, scheduleModel);
calculateOutstandingBalance(scheduleModel);
calculateLastUnpaidRepaymentPeriodEMI(scheduleModel, targetRepaymentPeriodDueDate);
}
private LocalDate calculateDateForFixedLength(final ProgressiveLoanInterestScheduleModel scheduleModel,
final LoanApplicationTerms loanApplicationTerms, final LocalDate targetRepaymentPeriodDueDate, final LocalDate newDueDate) {
final long variationDays = DateUtils.getDifferenceInDays(targetRepaymentPeriodDueDate, newDueDate);
final LocalDate repaymentStartDate = scheduleModel.repaymentPeriods().getFirst().getFromDate();
return switch (loanApplicationTerms.getRepaymentPeriodFrequencyType()) {
case DAYS -> repaymentStartDate.plusDays(loanApplicationTerms.getFixedLength() + variationDays);
case WEEKS -> repaymentStartDate.plusWeeks(loanApplicationTerms.getFixedLength() + variationDays);
case MONTHS -> repaymentStartDate.plusMonths(loanApplicationTerms.getFixedLength() + variationDays);
case YEARS -> repaymentStartDate.plusYears(loanApplicationTerms.getFixedLength() + variationDays);
case INVALID, WHOLE_TERM -> throw new IllegalArgumentException(
"Unsupported period frequency type for fixed length: " + loanApplicationTerms.getRepaymentPeriodFrequencyType());
};
}
private List<RepaymentPeriod> findPossiblyOverdueRepaymentPeriods(final LocalDate targetDate,
final ProgressiveLoanInterestScheduleModel model) {
return model.repaymentPeriods().stream() //
@@ -767,7 +817,7 @@ public final class ProgressiveEMICalculator implements EMICalculator {
final List<LoanScheduleModelRepaymentPeriod> expectedRepaymentPeriods = scheduledDateGenerator.generateRepaymentPeriods(mc,
periodStartDate, loanApplicationTerms, null);
final ProgressiveLoanInterestScheduleModel temporaryReAgedScheduleModel = generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanApplicationTerms.toLoanConfigurationDetails(), null,
expectedRepaymentPeriods, loanApplicationTerms.toLoanConfigurationDetails(),
loanApplicationTerms.getInstallmentAmountInMultiplesOf(), mc);
addDisbursement(temporaryReAgedScheduleModel, EmiChangeOperation.disburse(periodStartDate, loanApplicationTerms.getPrincipal()));
@@ -40,7 +40,6 @@ import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Setter;
@@ -49,8 +48,6 @@ import org.apache.fineract.infrastructure.core.serialization.gson.JsonExclude;
import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.apache.fineract.infrastructure.core.service.MathUtil;
import org.apache.fineract.organisation.monetary.domain.Money;
import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData;
import org.apache.fineract.portfolio.loanaccount.domain.LoanTermVariationType;
import org.apache.fineract.portfolio.loanproduct.domain.ILoanConfigurationDetails;
@Data
@@ -62,7 +59,6 @@ public class ProgressiveLoanInterestScheduleModel {
private final TreeSet<InterestRate> interestRates;
@JsonExclude
private final ILoanConfigurationDetails loanProductRelatedDetail;
private final Map<LoanTermVariationType, List<LoanTermVariationsData>> loanTermVariations;
private final Integer installmentAmountInMultiplesOf;
@JsonExclude
private final MathContext mc;
@@ -74,12 +70,10 @@ public class ProgressiveLoanInterestScheduleModel {
private LocalDate lastOverdueBalanceChange;
public ProgressiveLoanInterestScheduleModel(final List<RepaymentPeriod> repaymentPeriods,
final ILoanConfigurationDetails loanProductRelatedDetail, final List<LoanTermVariationsData> loanTermVariations,
final Integer installmentAmountInMultiplesOf, final MathContext mc) {
final ILoanConfigurationDetails loanProductRelatedDetail, final Integer installmentAmountInMultiplesOf, final MathContext mc) {
this.repaymentPeriods = new ArrayList<>(repaymentPeriods);
this.interestRates = new TreeSet<>(Collections.reverseOrder());
this.loanProductRelatedDetail = loanProductRelatedDetail;
this.loanTermVariations = buildLoanTermVariationMap(loanTermVariations);
this.installmentAmountInMultiplesOf = installmentAmountInMultiplesOf;
this.mc = mc;
this.zero = Money.zero(loanProductRelatedDetail.getCurrencyData(), mc);
@@ -88,15 +82,13 @@ public class ProgressiveLoanInterestScheduleModel {
}
private ProgressiveLoanInterestScheduleModel(final List<RepaymentPeriod> repaymentPeriods, final TreeSet<InterestRate> interestRates,
final ILoanConfigurationDetails loanProductRelatedDetail,
final Map<LoanTermVariationType, List<LoanTermVariationsData>> loanTermVariations, final Integer installmentAmountInMultiplesOf,
final MathContext mc, final boolean isCopiedForCalculation) {
final ILoanConfigurationDetails loanProductRelatedDetail, final Integer installmentAmountInMultiplesOf, final MathContext mc,
final boolean isCopiedForCalculation) {
this.mc = mc;
this.repaymentPeriods = copyRepaymentPeriods(repaymentPeriods,
(previousPeriod, repaymentPeriod) -> RepaymentPeriod.copy(previousPeriod, repaymentPeriod, mc));
this.interestRates = new TreeSet<>(interestRates);
this.loanProductRelatedDetail = loanProductRelatedDetail;
this.loanTermVariations = loanTermVariations;
this.installmentAmountInMultiplesOf = installmentAmountInMultiplesOf;
this.zero = Money.zero(loanProductRelatedDetail.getCurrencyData(), mc);
modifiers = new HashMap<>(Map.of(EMI_RECALCULATION, true, COPY, isCopiedForCalculation, INTEREST_RECALCULATION_ENABLED,
@@ -104,14 +96,14 @@ public class ProgressiveLoanInterestScheduleModel {
}
public ProgressiveLoanInterestScheduleModel deepCopy(MathContext mc) {
return new ProgressiveLoanInterestScheduleModel(repaymentPeriods, interestRates, loanProductRelatedDetail, loanTermVariations,
return new ProgressiveLoanInterestScheduleModel(repaymentPeriods, interestRates, loanProductRelatedDetail,
installmentAmountInMultiplesOf, mc, false);
}
public ProgressiveLoanInterestScheduleModel copyWithoutPaidAmounts() {
final List<RepaymentPeriod> repaymentPeriodCopies = copyRepaymentPeriods(repaymentPeriods,
(previousPeriod, repaymentPeriod) -> RepaymentPeriod.copyWithoutPaidAmounts(previousPeriod, repaymentPeriod, mc));
return new ProgressiveLoanInterestScheduleModel(repaymentPeriodCopies, interestRates, loanProductRelatedDetail, loanTermVariations,
return new ProgressiveLoanInterestScheduleModel(repaymentPeriodCopies, interestRates, loanProductRelatedDetail,
installmentAmountInMultiplesOf, mc, true);
}
@@ -416,15 +408,6 @@ public class ProgressiveLoanInterestScheduleModel {
: date.isAfter(previousInterestPeriod.getDueDate()) ? previousInterestPeriod.getDueDate() : date;
}
private Map<LoanTermVariationType, List<LoanTermVariationsData>> buildLoanTermVariationMap(
final List<LoanTermVariationsData> loanTermVariationsData) {
if (loanTermVariationsData == null) {
return new HashMap<>();
}
return loanTermVariationsData.stream()
.collect(Collectors.groupingBy(ltvd -> LoanTermVariationType.fromInt(ltvd.getTermType().getId().intValue())));
}
public void disableEMIRecalculation() {
this.modifiers.put(EMI_RECALCULATION, false);
}
@@ -44,8 +44,9 @@ public class RepaymentPeriod {
@JsonExclude
private final RepaymentPeriod previous;
@Setter
@Getter
private final LocalDate fromDate;
private LocalDate fromDate;
@Setter
@Getter
private LocalDate dueDate;
@@ -97,10 +98,10 @@ public class RepaymentPeriod {
private boolean noUnrecognisedInterest;
@Setter
@Getter
private boolean reAged = false;
private boolean reAged;
@Setter
@Getter
private boolean reAgedEarlyRepaymentHolder = false;
private boolean reAgedEarlyRepaymentHolder;
@Getter
@Setter
private Money reAgedInterest;
@@ -37,14 +37,13 @@ import org.apache.fineract.portfolio.common.domain.DaysInMonthType;
import org.apache.fineract.portfolio.common.domain.DaysInYearCustomStrategyType;
import org.apache.fineract.portfolio.common.domain.DaysInYearType;
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData;
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
import org.apache.fineract.portfolio.loanaccount.domain.LoanTermVariationType;
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType;
import org.apache.fineract.portfolio.loanaccount.domain.reaging.LoanReAgeInterestHandlingType;
import org.apache.fineract.portfolio.loanaccount.domain.reaging.LoanReAgeParameter;
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.DefaultScheduledDateGenerator;
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanApplicationTerms;
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleModelRepaymentPeriod;
import org.apache.fineract.portfolio.loanaccount.service.ProgressiveLoanInterestScheduleModelParserServiceGsonImpl;
import org.apache.fineract.portfolio.loanproduct.calc.data.EqualAmortizationValues;
@@ -198,7 +197,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestScheduleModel = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
Assertions.assertTrue(interestScheduleModel != null);
Assertions.assertTrue(interestScheduleModel.loanProductRelatedDetail() != null);
@@ -237,7 +236,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -281,7 +280,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -317,7 +316,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -353,7 +352,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -401,7 +400,7 @@ class ProgressiveEMICalculatorTest {
threadLocalContextUtil.when(ThreadLocalContextUtil::getBusinessDate).thenReturn(LocalDate.of(2024, 2, 14));
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -443,7 +442,7 @@ class ProgressiveEMICalculatorTest {
threadLocalContextUtil.when(ThreadLocalContextUtil::getBusinessDate).thenReturn(LocalDate.of(2024, 2, 14));
final ProgressiveLoanInterestScheduleModel interestModel = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestModel, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -493,7 +492,7 @@ class ProgressiveEMICalculatorTest {
threadLocalContextUtil.when(ThreadLocalContextUtil::getBusinessDate).thenReturn(LocalDate.of(2024, 2, 14));
final ProgressiveLoanInterestScheduleModel interestModel = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestModel, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -540,7 +539,7 @@ class ProgressiveEMICalculatorTest {
threadLocalContextUtil.when(ThreadLocalContextUtil::getBusinessDate).thenReturn(LocalDate.of(2024, 2, 14));
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -586,7 +585,7 @@ class ProgressiveEMICalculatorTest {
threadLocalContextUtil.when(ThreadLocalContextUtil::getBusinessDate).thenReturn(LocalDate.of(2024, 2, 15));
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -701,7 +700,7 @@ class ProgressiveEMICalculatorTest {
threadLocalContextUtil.when(ThreadLocalContextUtil::getBusinessDate).thenReturn(LocalDate.of(2024, 2, 15));
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -783,7 +782,7 @@ class ProgressiveEMICalculatorTest {
threadLocalContextUtil.when(ThreadLocalContextUtil::getBusinessDate).thenReturn(LocalDate.of(2024, 2, 15));
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -870,7 +869,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
Money disbursedAmount = toMoney(100);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -919,7 +918,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -968,7 +967,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 5), disbursedAmount);
@@ -1014,7 +1013,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2023, 12, 12), disbursedAmount);
@@ -1050,7 +1049,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), toMoney(300.0));
Assertions.assertEquals(6.15, toDouble(interestSchedule.getTotalDueInterest()));
@@ -1098,7 +1097,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(1000.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -1131,7 +1130,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -1164,7 +1163,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -1197,7 +1196,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -1239,7 +1238,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(1000.0);
LocalDate disbursementDate = LocalDate.of(2024, 1, 1);
@@ -1288,7 +1287,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestModel = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(1000.0);
emiCalculator.addDisbursement(interestModel, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -1350,7 +1349,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestModel = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(1000.0);
emiCalculator.addDisbursement(interestModel, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -1416,7 +1415,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestModel = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount1st = toMoney(1000.0);
final Money disbursedAmount2nd = toMoney(1000.0);
@@ -1489,7 +1488,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -1527,7 +1526,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -1563,10 +1562,9 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS);
Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1);
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
List<LoanTermVariationsData> loanTermVariations = new ArrayList<>();
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, loanTermVariations, installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -1602,10 +1600,9 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS);
Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1);
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
List<LoanTermVariationsData> loanTermVariations = new ArrayList<>();
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, loanTermVariations, installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -1641,10 +1638,9 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS);
Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1);
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
List<LoanTermVariationsData> loanTermVariations = new ArrayList<>();
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, loanTermVariations, installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -1680,10 +1676,9 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS);
Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1);
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
List<LoanTermVariationsData> loanTermVariations = new ArrayList<>();
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, loanTermVariations, installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -1719,10 +1714,9 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS);
Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1);
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
List<LoanTermVariationsData> loanTermVariations = new ArrayList<>();
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, loanTermVariations, installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -1761,10 +1755,9 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS);
Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1);
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
List<LoanTermVariationsData> loanTermVariations = new ArrayList<>();
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, loanTermVariations, installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -1806,10 +1799,9 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS);
Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1);
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
List<LoanTermVariationsData> loanTermVariations = new ArrayList<>();
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, loanTermVariations, installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -1847,10 +1839,9 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS);
Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1);
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
List<LoanTermVariationsData> loanTermVariations = new ArrayList<>();
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, loanTermVariations, installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -1885,10 +1876,9 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS);
Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1);
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
List<LoanTermVariationsData> loanTermVariations = new ArrayList<>();
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, loanTermVariations, installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -1906,12 +1896,12 @@ class ProgressiveEMICalculatorTest {
@Test
public void test_reschedule_disbursedAmt100_dayInYears360_daysInMonth30_repayEvery1Month() {
final List<LoanScheduleModelRepaymentPeriod> expectedRepaymentPeriods = List.of(
repayment(1, LocalDate.of(2024, 1, 1), LocalDate.of(2024, 3, 1)),
repayment(2, LocalDate.of(2024, 3, 1), LocalDate.of(2024, 4, 1)),
repayment(3, LocalDate.of(2024, 4, 1), LocalDate.of(2024, 5, 1)),
repayment(4, LocalDate.of(2024, 5, 1), LocalDate.of(2024, 6, 1)),
repayment(5, LocalDate.of(2024, 6, 1), LocalDate.of(2024, 7, 1)),
repayment(6, LocalDate.of(2024, 7, 1), LocalDate.of(2024, 8, 1)));
repayment(1, LocalDate.of(2024, 1, 1), LocalDate.of(2024, 2, 1)),
repayment(2, LocalDate.of(2024, 2, 1), LocalDate.of(2024, 3, 1)),
repayment(3, LocalDate.of(2024, 3, 1), LocalDate.of(2024, 4, 1)),
repayment(4, LocalDate.of(2024, 4, 1), LocalDate.of(2024, 5, 1)),
repayment(5, LocalDate.of(2024, 5, 1), LocalDate.of(2024, 6, 1)),
repayment(6, LocalDate.of(2024, 6, 1), LocalDate.of(2024, 7, 1)));
final BigDecimal interestRate = BigDecimal.valueOf(7);
final Integer installmentAmountInMultiplesOf = null;
@@ -1922,35 +1912,39 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS);
Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1);
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
List<LoanTermVariationsData> loanTermVariationsData = List.of(//
new LoanTermVariationsData(1L, LoanTermVariationType.DUE_DATE.getValue(), //
LocalDate.of(2024, 2, 1), null, //
LocalDate.of(2024, 3, 1), false));
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, loanTermVariationsData, installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
final LoanApplicationTerms loanApplicationTerms = Mockito.mock(LoanApplicationTerms.class);
Mockito.when(loanApplicationTerms.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS);
Mockito.when(loanApplicationTerms.getRepaymentEvery()).thenReturn(1);
Mockito.when(loanApplicationTerms.getSeedDate()).thenReturn(LocalDate.of(2024, 1, 1));
Mockito.when(loanApplicationTerms.getCalculatedRepaymentsStartingFromLocalDate()).thenReturn(LocalDate.of(2024, 1, 1));
emiCalculator.changeDueDate(interestSchedule, loanApplicationTerms, LocalDate.of(2024, 2, 1), LocalDate.of(2024, 3, 1));
checkPeriod(interestSchedule, 0, 0, 17.01, 0.0, 0.0, 1.17, 15.84, 84.16);
checkPeriod(interestSchedule, 0, 1, 17.01, 0.005833333333, 1.1666666667, 1.17, 15.84, 84.16);
checkPeriod(interestSchedule, 1, 0, 17.01, 0.005833333333, 0.490933333306, 0.49, 16.52, 67.64);
checkPeriod(interestSchedule, 2, 0, 17.01, 0.005833333333, 0.394566666645, 0.39, 16.62, 51.02);
checkPeriod(interestSchedule, 3, 0, 17.01, 0.005833333333, 0.29761666665, 0.30, 16.71, 34.31);
checkPeriod(interestSchedule, 4, 0, 17.01, 0.005833333333, 0.200141666655, 0.20, 16.81, 17.50);
checkPeriod(interestSchedule, 5, 0, 17.60, 0.005833333333, 0.102083333328, 0.10, 17.50, 0.0);
checkPeriod(interestSchedule, 5, 0, 19.85, 0.005833333333, 2.34791666667, 2.35, 17.50, 0.0);
}
@Test
public void test_two_reschedules_disbursedAmt100_dayInYears360_daysInMonth30_repayEvery1Month() {
final List<LoanScheduleModelRepaymentPeriod> expectedRepaymentPeriods = List.of(
repayment(1, LocalDate.of(2024, 1, 1), LocalDate.of(2024, 3, 1)),
repayment(2, LocalDate.of(2024, 3, 1), LocalDate.of(2024, 4, 1)),
repayment(3, LocalDate.of(2024, 4, 1), LocalDate.of(2024, 6, 1)),
repayment(4, LocalDate.of(2024, 6, 1), LocalDate.of(2024, 7, 1)),
repayment(5, LocalDate.of(2024, 7, 1), LocalDate.of(2024, 8, 1)),
repayment(6, LocalDate.of(2024, 8, 1), LocalDate.of(2024, 9, 1)));
repayment(1, LocalDate.of(2024, 1, 1), LocalDate.of(2024, 2, 1)),
repayment(2, LocalDate.of(2024, 2, 1), LocalDate.of(2024, 3, 1)),
repayment(3, LocalDate.of(2024, 3, 1), LocalDate.of(2024, 4, 1)),
repayment(4, LocalDate.of(2024, 4, 1), LocalDate.of(2024, 5, 1)),
repayment(5, LocalDate.of(2024, 5, 1), LocalDate.of(2024, 6, 1)),
repayment(6, LocalDate.of(2024, 6, 1), LocalDate.of(2024, 7, 1)));
final BigDecimal interestRate = BigDecimal.valueOf(7);
final Integer installmentAmountInMultiplesOf = null;
@@ -1961,38 +1955,40 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS);
Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1);
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
List<LoanTermVariationsData> loanTermVariationsData = List.of(//
new LoanTermVariationsData(1L, LoanTermVariationType.DUE_DATE.getValue(), //
LocalDate.of(2024, 2, 1), null, //
LocalDate.of(2024, 3, 1), false), //
new LoanTermVariationsData(2L, LoanTermVariationType.DUE_DATE.getValue(), //
LocalDate.of(2024, 5, 1), null, //
LocalDate.of(2024, 6, 1), false));
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, loanTermVariationsData, installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
final LoanApplicationTerms loanApplicationTerms = Mockito.mock(LoanApplicationTerms.class);
Mockito.when(loanApplicationTerms.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS);
Mockito.when(loanApplicationTerms.getRepaymentEvery()).thenReturn(1);
Mockito.when(loanApplicationTerms.getSeedDate()).thenReturn(LocalDate.of(2024, 1, 1));
Mockito.when(loanApplicationTerms.getCalculatedRepaymentsStartingFromLocalDate()).thenReturn(LocalDate.of(2024, 1, 1));
emiCalculator.changeDueDate(interestSchedule, loanApplicationTerms, LocalDate.of(2024, 2, 1), LocalDate.of(2024, 3, 1));
emiCalculator.changeDueDate(interestSchedule, loanApplicationTerms, LocalDate.of(2024, 5, 1), LocalDate.of(2024, 6, 1));
checkPeriod(interestSchedule, 0, 0, 17.01, 0.0, 0.0, 1.17, 15.84, 84.16);
checkPeriod(interestSchedule, 0, 1, 17.01, 0.005833333333, 1.1666666667, 1.17, 15.84, 84.16);
checkPeriod(interestSchedule, 1, 0, 17.01, 0.005833333333, 0.490933333306, 0.49, 16.52, 67.64);
checkPeriod(interestSchedule, 2, 0, 17.01, 0.005833333333, 0.789133333354, 0.79, 16.22, 51.42);
checkPeriod(interestSchedule, 3, 0, 17.01, 0.005833333333, 0.299949999983, 0.30, 16.71, 34.71);
checkPeriod(interestSchedule, 4, 0, 17.01, 0.005833333333, 0.202474999988, 0.20, 16.81, 17.90);
checkPeriod(interestSchedule, 5, 0, 18.00, 0.005833333333, 0.104416666661, 0.10, 17.90, 0.0);
checkPeriod(interestSchedule, 5, 0, 20.41, 0.005833333333, 2.506, 2.51, 17.90, 0.0);
}
@Test
public void test_reschedule_partial_period_disbursedAmt100_dayInYears360_daysInMonth30_repayEvery1Month() {
final List<LoanScheduleModelRepaymentPeriod> expectedRepaymentPeriods = List.of(
repayment(1, LocalDate.of(2024, 1, 1), LocalDate.of(2024, 2, 1)),
repayment(2, LocalDate.of(2024, 2, 1), LocalDate.of(2024, 4, 15)),
repayment(3, LocalDate.of(2024, 4, 15), LocalDate.of(2024, 5, 15)),
repayment(4, LocalDate.of(2024, 5, 15), LocalDate.of(2024, 6, 15)),
repayment(5, LocalDate.of(2024, 6, 15), LocalDate.of(2024, 7, 15)),
repayment(6, LocalDate.of(2024, 7, 15), LocalDate.of(2024, 8, 15)));
repayment(2, LocalDate.of(2024, 2, 1), LocalDate.of(2024, 3, 1)),
repayment(3, LocalDate.of(2024, 3, 1), LocalDate.of(2024, 4, 1)),
repayment(4, LocalDate.of(2024, 4, 1), LocalDate.of(2024, 5, 1)),
repayment(5, LocalDate.of(2024, 5, 1), LocalDate.of(2024, 6, 1)),
repayment(6, LocalDate.of(2024, 6, 1), LocalDate.of(2024, 7, 1)));
final BigDecimal interestRate = BigDecimal.valueOf(7);
final Integer installmentAmountInMultiplesOf = null;
@@ -2003,24 +1999,27 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS);
Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1);
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
List<LoanTermVariationsData> loanTermVariationsData = List.of(//
new LoanTermVariationsData(1L, LoanTermVariationType.DUE_DATE.getValue(), //
LocalDate.of(2024, 3, 1), null, //
LocalDate.of(2024, 4, 15), false));
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, loanTermVariationsData, installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
LoanApplicationTerms loanApplicationTerms = Mockito.mock(LoanApplicationTerms.class);
Mockito.when(loanApplicationTerms.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS);
Mockito.when(loanApplicationTerms.getRepaymentEvery()).thenReturn(1);
Mockito.when(loanApplicationTerms.getSeedDate()).thenReturn(LocalDate.of(2024, 1, 1));
Mockito.when(loanApplicationTerms.getCalculatedRepaymentsStartingFromLocalDate()).thenReturn(LocalDate.of(2024, 1, 1));
emiCalculator.changeDueDate(interestSchedule, loanApplicationTerms, LocalDate.of(2024, 3, 1), LocalDate.of(2024, 4, 15));
checkPeriod(interestSchedule, 0, 0, 17.01, 0.0, 0.0, 0.58, 16.43, 83.57);
checkPeriod(interestSchedule, 0, 1, 17.01, 0.005833333333, 0.5833333333, 0.58, 16.43, 83.57);
checkPeriod(interestSchedule, 1, 0, 17.01, 0.005833333333, 1.20247944445, 1.20, 15.81, 67.76);
checkPeriod(interestSchedule, 2, 0, 17.01, 0.005833333333, 0.395266666644, 0.40, 16.61, 51.15);
checkPeriod(interestSchedule, 3, 0, 17.01, 0.005833333333, 0.298374999983, 0.3, 16.71, 34.44);
checkPeriod(interestSchedule, 4, 0, 17.01, 0.005833333333, 0.200899999989, 0.20, 16.81, 17.63);
checkPeriod(interestSchedule, 5, 0, 17.73, 0.005833333333, 0.102841666661, 0.10, 17.63, 0.0);
checkPeriod(interestSchedule, 5, 0, 21.59, 0.005833333333, 3.96283222223, 3.96, 17.63, 0.0);
}
@Test
@@ -2045,7 +2044,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(5000.0);
LocalDate disbursementDate = LocalDate.of(2023, 11, 13);
@@ -2094,7 +2093,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(5000.0);
LocalDate disbursementDate = LocalDate.of(2023, 11, 13);
@@ -2139,7 +2138,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(5000.0);
LocalDate disbursementDate = LocalDate.of(2023, 11, 13);
@@ -2189,7 +2188,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(2450.0);
LocalDate disbursementDate = LocalDate.of(2023, 10, 31);
@@ -2226,7 +2225,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(10000.0);
LocalDate disbursementDate = LocalDate.of(2023, 10, 30);
@@ -2263,7 +2262,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(3333.0);
LocalDate disbursementDate = LocalDate.of(2023, 10, 29);
@@ -2300,7 +2299,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(245000.0);
LocalDate disbursementDate = LocalDate.of(2023, 10, 31);
@@ -2337,7 +2336,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(1500.0);
LocalDate disbursementDate = LocalDate.of(2021, 10, 30);
@@ -2374,7 +2373,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(5000);
LocalDate disbursementDate = LocalDate.of(2022, 10, 29);
@@ -2410,7 +2409,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator
.generatePeriodInterestScheduleModel(expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), null, mc);
.generatePeriodInterestScheduleModel(expectedRepaymentPeriods, loanProductRelatedDetail, null, mc);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2023, 11, 13), Money.of(currency, BigDecimal.valueOf(5000), mc));
checkPeriod(interestSchedule, 0, 857.71, 41.05, 816.66, 4183.34, false);
@@ -2443,7 +2442,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(true);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator
.generatePeriodInterestScheduleModel(expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), null, mc);
.generatePeriodInterestScheduleModel(expectedRepaymentPeriods, loanProductRelatedDetail, null, mc);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2023, 11, 13), Money.of(currency, BigDecimal.valueOf(5000), mc));
checkPeriod(interestSchedule, 0, 857.72, 41.05, 816.67, 4183.33, false);
@@ -2478,7 +2477,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -2535,7 +2534,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -2603,7 +2602,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -2662,7 +2661,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -2720,7 +2719,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -2772,7 +2771,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -2830,7 +2829,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -2887,7 +2886,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -2955,7 +2954,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(10000.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2023, 12, 12), disbursedAmount);
@@ -2993,7 +2992,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(15000.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 7, 23), disbursedAmount);
@@ -3030,7 +3029,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(245000.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2023, 10, 31), disbursedAmount);
@@ -3070,7 +3069,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(2450);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 10, 31), disbursedAmount);
@@ -3109,7 +3108,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(5000.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2022, 10, 29), disbursedAmount);
@@ -3145,7 +3144,7 @@ class ProgressiveEMICalculatorTest {
.thenReturn(DaysInYearCustomStrategyType.FEB_29_PERIOD_ONLY);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -3181,7 +3180,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -3246,7 +3245,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestScheduleExpected = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
ProgressiveLoanInterestScheduleModel interestScheduleActual = copyJson(interestScheduleExpected);
@@ -3332,7 +3331,7 @@ class ProgressiveEMICalculatorTest {
final Integer installmentAmountInMultiplesOf = null;
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(700.0));
checkPeriod(interestSchedule, 0, 181.94, 7.11, 174.83, 525.17, false); //
@@ -3371,7 +3370,7 @@ class ProgressiveEMICalculatorTest {
final Integer installmentAmountInMultiplesOf = null;
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(750.0));
checkPeriod(interestSchedule, 0, 195.00, 7.50, 187.50, 562.50, false); //
@@ -3410,7 +3409,7 @@ class ProgressiveEMICalculatorTest {
final Integer installmentAmountInMultiplesOf = null;
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(600.0));
checkPeriod(interestSchedule, 0, 151.38, 1.38, 150.00, 450.00, false); //
@@ -3449,7 +3448,7 @@ class ProgressiveEMICalculatorTest {
final Integer installmentAmountInMultiplesOf = null;
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(400.0));
checkPeriod(interestSchedule, 0, 103.93, 3.93, 100.00, 300.00, false); //
@@ -3503,7 +3502,7 @@ class ProgressiveEMICalculatorTest {
final Integer installmentAmountInMultiplesOf = null;
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(1000.0));
@@ -3532,7 +3531,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(1000.0));
@@ -3563,7 +3562,7 @@ class ProgressiveEMICalculatorTest {
final Integer installmentAmountInMultiplesOf = null;
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(1000.0));
@@ -3595,7 +3594,7 @@ class ProgressiveEMICalculatorTest {
final Integer installmentAmountInMultiplesOf = null;
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(1000.0));
@@ -3628,7 +3627,7 @@ class ProgressiveEMICalculatorTest {
final Integer installmentAmountInMultiplesOf = null;
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(1000.0));
@@ -3659,7 +3658,7 @@ class ProgressiveEMICalculatorTest {
final Integer installmentAmountInMultiplesOf = null;
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(1000.0));
@@ -3696,7 +3695,7 @@ class ProgressiveEMICalculatorTest {
final Integer installmentAmountInMultiplesOf = null;
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(1000.0));
@@ -3737,7 +3736,7 @@ class ProgressiveEMICalculatorTest {
final Integer installmentAmountInMultiplesOf = null;
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(7500.0));
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(2500.0));
@@ -3812,7 +3811,7 @@ class ProgressiveEMICalculatorTest {
final Integer installmentAmountInMultiplesOf = null;
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(1000.0));
@@ -3862,7 +3861,7 @@ class ProgressiveEMICalculatorTest {
final Integer installmentAmountInMultiplesOf = null;
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(500.0));
checkPeriod(interestSchedule, 0, 170.01, 5.00, 165.01, 334.99, false); //
@@ -3899,7 +3898,7 @@ class ProgressiveEMICalculatorTest {
final Integer installmentAmountInMultiplesOf = null;
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(500.0));
checkPeriod(interestSchedule, 0, 170.01, 5.00, 165.01, 334.99, false); //
@@ -3935,7 +3934,7 @@ class ProgressiveEMICalculatorTest {
final Integer installmentAmountInMultiplesOf = null;
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(500.0));
checkPeriod(interestSchedule, 0, 170.01, 5.00, 165.01, 334.99, false); //
@@ -3993,7 +3992,7 @@ class ProgressiveEMICalculatorTest {
final Integer installmentAmountInMultiplesOf = null;
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(500.0));
checkPeriod(interestSchedule, 0, 170.01, 5.00, 165.01, 334.99, false); //
@@ -4040,7 +4039,7 @@ class ProgressiveEMICalculatorTest {
final Integer installmentAmountInMultiplesOf = null;
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(1000));
@@ -4079,7 +4078,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.isAllowPartialPeriodInterestCalculation()).thenReturn(true);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(1000));
@@ -4116,7 +4115,7 @@ class ProgressiveEMICalculatorTest {
final Integer installmentAmountInMultiplesOf = null;
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(1000));
@@ -4177,7 +4176,7 @@ class ProgressiveEMICalculatorTest {
final Integer installmentAmountInMultiplesOf = null;
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(1000));
@@ -4262,7 +4261,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -4326,7 +4325,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -4415,7 +4414,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -4474,7 +4473,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -4534,7 +4533,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -4617,7 +4616,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -4700,7 +4699,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -4773,7 +4772,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc);
expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);