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: And Loan Transactions tab has the following data:
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed | | 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 | Disbursement | 100.0 | 0.0 | 0.0 | 0.0 | 0.0 | 100.0 | false | false |
@TestRailId:C3882 @TestRailId:C3882
Scenario: Reschedule progressive loan to 0 percent interest then back to 10 percent Scenario: Reschedule progressive loan to 0 percent interest then back to 10 percent
When Admin sets the business date to "1 January 2024" 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 | | 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 | 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: When Admin creates and approves Loan reschedule with the following data:
| rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate | | rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate |
| 02 January 2024 | 01 January 2024 | | | | | 0 | | 02 January 2024 | 01 January 2024 | | | | | 0 |
Then Loan Repayment schedule has 6 periods, with the following data for periods: 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 | | 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 | | | | | | | 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 | | 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 | | 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: Then Loan Repayment schedule has the following data in Total row:
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding | | 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 | | 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: And Loan Transactions tab has the following data:
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed | | 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 | 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: When Admin creates and approves Loan reschedule with the following data:
| rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate | | rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate |
| 03 January 2024 | 01 January 2024 | | | | | 10 | | 03 January 2024 | 01 January 2024 | | | | | 10 |
Then Loan Repayment schedule has 6 periods, with the following data for periods: 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 | | 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 | | | | | | | 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 | | 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 | | 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: Then Loan Repayment schedule has the following data in Total row:
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding | | 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 | | 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: Then Loan Repayment schedule has the following data in Total row:
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding | | 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 | | 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: When Admin creates and approves Loan reschedule with the following data:
| rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate | | rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate |
| 02 February 2024 | 01 January 2024 | | | | | 10 | | 02 February 2024 | 01 January 2024 | | | | | 10 |
Then Loan Repayment schedule has 6 periods, with the following data for periods: 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 | | 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 | | | | | | | 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 | | 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 | | 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: Then Loan Repayment schedule has the following data in Total row:
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding | | 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 | | 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: Then Loan Transactions tab has the following data:
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed | | 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 | 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 | | 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 | | 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: When Admin creates and approves Loan reschedule with the following data:
| rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate | | rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate |
| 24 July 2025 | 24 July 2025 | | | | | 5 | | 24 July 2025 | 24 July 2025 | | | | | 5 |
Then Loan Repayment schedule has 6 periods, with the following data for periods: 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 | | 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 | | | | | | | 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 | | 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: Then Loan Repayment schedule has the following data in Total row:
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding | | 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: And Loan Transactions tab has the following data:
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed | | 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 | | 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" Then LoanRescheduledDueAdjustScheduleBusinessEvent is raised on "24 July 2025"
@TestRailId:C4225 @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" When Admin sets the business date to "05 September 2025"
And Admin creates a client with random data And Admin creates a client with random data
And Admin creates a fully customized loan with the following 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 | | 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 | | 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 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 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 "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 runs inline COB job for Loan
When Admin sets the business date to "10 November 2025" When Admin sets the business date to "10 November 2025"
When Admin runs inline COB job for Loan 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: When Admin creates and approves Loan reschedule with the following data:
| rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate | | rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate |
| 30 November 2025 | 10 November 2025 | 31 January 2026 | | | | | | 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) { private LocalDate applyLoanTermVariations(final LoanApplicationTerms loanApplicationTerms, final LocalDate scheduledDueDate) {
LocalDate modifiedScheduledDueDate = scheduledDueDate; LocalDate modifiedScheduledDueDate = scheduledDueDate;
if (LoanScheduleType.PROGRESSIVE.equals(loanApplicationTerms.getLoanScheduleType())) {
return modifiedScheduledDueDate;
}
// due date changes should be applied only for that dueDate // due date changes should be applied only for that dueDate
if (loanApplicationTerms.getLoanTermVariations() != null) { if (loanApplicationTerms.getLoanTermVariations() != null) {
if (loanApplicationTerms.getLoanTermVariations().hasDueDateVariation(scheduledDueDate)) { if (loanApplicationTerms.getLoanTermVariations().hasDueDateVariation(scheduledDueDate)) {
@@ -55,6 +55,7 @@ import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream; import java.util.stream.Stream;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
@@ -225,8 +226,7 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
.collect(Collectors.toCollection(ArrayList::new)); .collect(Collectors.toCollection(ArrayList::new));
final Integer installmentAmountInMultiplesOf = loan.getLoanProductRelatedDetail().getInstallmentAmountInMultiplesOf(); final Integer installmentAmountInMultiplesOf = loan.getLoanProductRelatedDetail().getInstallmentAmountInMultiplesOf();
ProgressiveLoanInterestScheduleModel scheduleModel = emiCalculator.generateInstallmentInterestScheduleModel(installments, ProgressiveLoanInterestScheduleModel scheduleModel = emiCalculator.generateInstallmentInterestScheduleModel(installments,
LoanConfigurationDetailsMapper.map(loan), loanTermVariations, installmentAmountInMultiplesOf, LoanConfigurationDetailsMapper.map(loan), installmentAmountInMultiplesOf, overpaymentHolder.getMoneyObject().getMc());
overpaymentHolder.getMoneyObject().getMc());
ProgressiveTransactionCtx ctx = new ProgressiveTransactionCtx(currency, installments, charges, overpaymentHolder, ProgressiveTransactionCtx ctx = new ProgressiveTransactionCtx(currency, installments, charges, overpaymentHolder,
changedTransactionDetail, scheduleModel); changedTransactionDetail, scheduleModel);
@@ -236,8 +236,8 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
List<LoanTransaction> overpaidTransactions = new ArrayList<>(); List<LoanTransaction> overpaidTransactions = new ArrayList<>();
for (final ChangeOperation changeOperation : changeOperations) { for (final ChangeOperation changeOperation : changeOperations) {
if (changeOperation.isLoanTermVariationsData()) { if (changeOperation.isLoanTermVariationsData()) {
final LoanTermVariationsData interestRateChange = changeOperation.getLoanTermVariationsData().get(); final LoanTermVariationsData termVariationsData = changeOperation.getLoanTermVariationsData().get();
processLoanTermVariation(installments, interestRateChange, scheduleModel); processLoanTermVariation(installments, termVariationsData, scheduleModel);
} else if (changeOperation.isTransaction()) { } else if (changeOperation.isTransaction()) {
LoanTransaction transaction = changeOperation.getLoanTransaction().get(); LoanTransaction transaction = changeOperation.getLoanTransaction().get();
if (loan.getStatus().isOverpaid() && transaction.isAccrualActivity()) { if (loan.getStatus().isOverpaid() && transaction.isAccrualActivity()) {
@@ -309,10 +309,92 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
case INTEREST_PAUSE -> handleInterestPause(installments, termVariationsData, scheduleModel); case INTEREST_PAUSE -> handleInterestPause(installments, termVariationsData, scheduleModel);
case INTEREST_RATE_FROM_INSTALLMENT -> handleChangeInterestRate(installments, termVariationsData, scheduleModel); case INTEREST_RATE_FROM_INSTALLMENT -> handleChangeInterestRate(installments, termVariationsData, scheduleModel);
case EXTEND_REPAYMENT_PERIOD -> handleExtraRepaymentPeriod(installments, termVariationsData, scheduleModel); case EXTEND_REPAYMENT_PERIOD -> handleExtraRepaymentPeriod(installments, termVariationsData, scheduleModel);
case DUE_DATE -> handleDueDateChangeOnRepaymentPeriod(installments, termVariationsData, scheduleModel);
default -> throw new IllegalStateException("Unhandled LoanTermVariationType."); 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, private void handleExtraRepaymentPeriod(final List<LoanRepaymentScheduleInstallment> installments,
final LoanTermVariationsData termVariationsData, final ProgressiveLoanInterestScheduleModel scheduleModel) { final LoanTermVariationsData termVariationsData, final ProgressiveLoanInterestScheduleModel scheduleModel) {
final LocalDate interestRateChangeSubmittedOnDate = termVariationsData.getTermVariationApplicableFrom(); final LocalDate interestRateChangeSubmittedOnDate = termVariationsData.getTermVariationApplicableFrom();
@@ -1266,7 +1348,7 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
.collect(Collectors.groupingBy(ltvd -> LoanTermVariationType.fromInt(ltvd.getTermType().getId().intValue()))); .collect(Collectors.groupingBy(ltvd -> LoanTermVariationType.fromInt(ltvd.getTermType().getId().intValue())));
Stream.of(LoanTermVariationType.INTEREST_RATE_FROM_INSTALLMENT, LoanTermVariationType.INTEREST_PAUSE, 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) { if (loanTermVariationsMap.get(key) != null) {
changeOperations.addAll(loanTermVariationsMap.get(key).stream().map(ChangeOperation::new).toList()); 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.organisation.monetary.domain.Money;
import org.apache.fineract.portfolio.loanaccount.data.DisbursementData; import org.apache.fineract.portfolio.loanaccount.data.DisbursementData;
import org.apache.fineract.portfolio.loanaccount.data.HolidayDetailDTO; 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.data.OutstandingAmountsDTO;
import org.apache.fineract.portfolio.loanaccount.domain.Loan; import org.apache.fineract.portfolio.loanaccount.domain.Loan;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge; import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
@@ -106,11 +105,8 @@ public class ProgressiveLoanScheduleGenerator implements LoanScheduleGenerator {
// generate list of proposed schedule due dates // generate list of proposed schedule due dates
final List<LoanScheduleModelRepaymentPeriod> expectedRepaymentPeriods = scheduledDateGenerator.generateRepaymentPeriods(mc, final List<LoanScheduleModelRepaymentPeriod> expectedRepaymentPeriods = scheduledDateGenerator.generateRepaymentPeriods(mc,
periodStartDate, loanApplicationTerms, holidayDetailDTO); periodStartDate, loanApplicationTerms, holidayDetailDTO);
List<LoanTermVariationsData> loanTermVariations = loanApplicationTerms.getLoanTermVariations() != null
? loanApplicationTerms.getLoanTermVariations().getExceptionData()
: null;
final ProgressiveLoanInterestScheduleModel interestScheduleModel = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestScheduleModel = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanApplicationTerms.toLoanConfigurationDetails(), loanTermVariations, expectedRepaymentPeriods, loanApplicationTerms.toLoanConfigurationDetails(),
loanApplicationTerms.getInstallmentAmountInMultiplesOf(), mc); loanApplicationTerms.getInstallmentAmountInMultiplesOf(), mc);
final List<LoanScheduleModelPeriod> periods = new ArrayList<>(expectedRepaymentPeriods.size()); final List<LoanScheduleModelPeriod> periods = new ArrayList<>(expectedRepaymentPeriods.size());
@@ -58,7 +58,7 @@ public class InterestScheduleModelServiceGsonContext {
public ProgressiveLoanInterestScheduleModel createProgressiveLoanInterestScheduleModelInstance(Type type) { public ProgressiveLoanInterestScheduleModel createProgressiveLoanInterestScheduleModelInstance(Type type) {
if (type == ProgressiveLoanInterestScheduleModel.class) { if (type == ProgressiveLoanInterestScheduleModel.class) {
setPrev(null); setPrev(null);
return new ProgressiveLoanInterestScheduleModel(new ArrayList<>(), getLoanProductRelatedDetail(), new ArrayList<>(), return new ProgressiveLoanInterestScheduleModel(new ArrayList<>(), getLoanProductRelatedDetail(),
installmentAmountInMultipliesOf, getMc()); installmentAmountInMultipliesOf, getMc());
} }
throw new IllegalArgumentException("Unsupported ProgressiveLoanInterestScheduleModel type: " + type); throw new IllegalArgumentException("Unsupported ProgressiveLoanInterestScheduleModel type: " + type);
@@ -26,7 +26,6 @@ import java.util.List;
import java.util.Optional; import java.util.Optional;
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency; import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
import org.apache.fineract.organisation.monetary.domain.Money; 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.LoanRepaymentScheduleInstallment;
import org.apache.fineract.portfolio.loanaccount.domain.reaging.LoanReAgeParameter; import org.apache.fineract.portfolio.loanaccount.domain.reaging.LoanReAgeParameter;
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanApplicationTerms; import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanApplicationTerms;
@@ -46,8 +45,7 @@ public interface EMICalculator {
*/ */
@NotNull @NotNull
ProgressiveLoanInterestScheduleModel generatePeriodInterestScheduleModel(@NotNull List<LoanScheduleModelRepaymentPeriod> periods, ProgressiveLoanInterestScheduleModel generatePeriodInterestScheduleModel(@NotNull List<LoanScheduleModelRepaymentPeriod> periods,
@NotNull ILoanConfigurationDetails loanProductRelatedDetail, List<LoanTermVariationsData> loanTermVariations, @NotNull ILoanConfigurationDetails loanProductRelatedDetail, Integer installmentAmountInMultiplesOf, MathContext mc);
Integer installmentAmountInMultiplesOf, MathContext mc);
/** /**
* This method creates an Interest model with repayment periods from the installments which retrieved from the * This method creates an Interest model with repayment periods from the installments which retrieved from the
@@ -56,7 +54,7 @@ public interface EMICalculator {
@NotNull @NotNull
ProgressiveLoanInterestScheduleModel generateInstallmentInterestScheduleModel( ProgressiveLoanInterestScheduleModel generateInstallmentInterestScheduleModel(
@NotNull List<LoanRepaymentScheduleInstallment> installments, @NotNull ILoanConfigurationDetails loanProductRelatedDetail, @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. * Find repayment period based on Due Date.
@@ -169,4 +167,7 @@ public interface EMICalculator {
EqualAmortizationValues calculateAdjustedEqualAmortizationValues(Money outstanding, Money total, EqualAmortizationValues calculateAdjustedEqualAmortizationValues(Money outstanding, Money total,
Money sumOfOtherEqualAmortizationValues, Integer numberOfInstallments, Integer installmentAmountInMultiplesOf, Money sumOfOtherEqualAmortizationValues, Integer numberOfInstallments, Integer installmentAmountInMultiplesOf,
MonetaryCurrency currency); 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.DaysInYearCustomStrategyType;
import org.apache.fineract.portfolio.common.domain.DaysInYearType; import org.apache.fineract.portfolio.common.domain.DaysInYearType;
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType; 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.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.LoanReAgeInterestHandlingType;
import org.apache.fineract.portfolio.loanaccount.domain.reaging.LoanReAgeParameter; import org.apache.fineract.portfolio.loanaccount.domain.reaging.LoanReAgeParameter;
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanApplicationTerms; import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanApplicationTerms;
@@ -77,28 +75,26 @@ public final class ProgressiveEMICalculator implements EMICalculator {
@Override @Override
@NotNull @NotNull
public ProgressiveLoanInterestScheduleModel generatePeriodInterestScheduleModel(@NotNull List<LoanScheduleModelRepaymentPeriod> periods, public ProgressiveLoanInterestScheduleModel generatePeriodInterestScheduleModel(@NotNull List<LoanScheduleModelRepaymentPeriod> periods,
@NotNull ILoanConfigurationDetails loanProductRelatedDetail, List<LoanTermVariationsData> loanTermVariations, @NotNull ILoanConfigurationDetails loanProductRelatedDetail, final Integer installmentAmountInMultiplesOf,
final Integer installmentAmountInMultiplesOf, final MathContext mc) { final MathContext mc) {
return generateInterestScheduleModel(periods, LoanScheduleModelRepaymentPeriod::periodFromDate, return generateInterestScheduleModel(periods, LoanScheduleModelRepaymentPeriod::periodFromDate,
LoanScheduleModelRepaymentPeriod::periodDueDate, loanProductRelatedDetail, loanTermVariations, LoanScheduleModelRepaymentPeriod::periodDueDate, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
installmentAmountInMultiplesOf, mc);
} }
@Override @Override
@NotNull @NotNull
public ProgressiveLoanInterestScheduleModel generateInstallmentInterestScheduleModel( public ProgressiveLoanInterestScheduleModel generateInstallmentInterestScheduleModel(
@NotNull List<LoanRepaymentScheduleInstallment> installments, @NotNull ILoanConfigurationDetails loanProductRelatedDetail, @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(); installments = installments.stream().filter(installment -> !installment.isDownPayment() && !installment.isAdditional()).toList();
return generateInterestScheduleModel(installments, LoanRepaymentScheduleInstallment::getFromDate, return generateInterestScheduleModel(installments, LoanRepaymentScheduleInstallment::getFromDate,
LoanRepaymentScheduleInstallment::getDueDate, loanProductRelatedDetail, loanTermVariations, installmentAmountInMultiplesOf, LoanRepaymentScheduleInstallment::getDueDate, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
mc);
} }
@NotNull @NotNull
private <T> ProgressiveLoanInterestScheduleModel generateInterestScheduleModel(@NotNull List<T> periods, Function<T, LocalDate> from, private <T> ProgressiveLoanInterestScheduleModel generateInterestScheduleModel(@NotNull List<T> periods, Function<T, LocalDate> from,
Function<T, LocalDate> to, @NotNull ILoanConfigurationDetails loanProductRelatedDetail, 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 Money zero = Money.zero(loanProductRelatedDetail.getCurrencyData(), mc);
final AtomicReference<RepaymentPeriod> prev = new AtomicReference<>(); final AtomicReference<RepaymentPeriod> prev = new AtomicReference<>();
List<RepaymentPeriod> repaymentPeriods = periods.stream().map(e -> { List<RepaymentPeriod> repaymentPeriods = periods.stream().map(e -> {
@@ -106,8 +102,7 @@ public final class ProgressiveEMICalculator implements EMICalculator {
prev.set(rp); prev.set(rp);
return rp; return rp;
}).toList(); }).toList();
return new ProgressiveLoanInterestScheduleModel(repaymentPeriods, loanProductRelatedDetail, loanTermVariations, return new ProgressiveLoanInterestScheduleModel(repaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
installmentAmountInMultiplesOf, mc);
} }
@Override @Override
@@ -566,8 +561,7 @@ public final class ProgressiveEMICalculator implements EMICalculator {
} }
calculateOutstandingBalance(scheduleModel); calculateOutstandingBalance(scheduleModel);
calculateLastUnpaidRepaymentPeriodEMI(scheduleModel, calculateFromRepaymentPeriodDueDate); calculateLastUnpaidRepaymentPeriodEMI(scheduleModel, calculateFromRepaymentPeriodDueDate);
if (onlyOnActualModelShouldApply && (scheduleModel.loanTermVariations() == null if (onlyOnActualModelShouldApply) {
|| scheduleModel.loanTermVariations().get(LoanTermVariationType.DUE_DATE) == null)) {
checkAndAdjustEmiIfNeededOnRelatedRepaymentPeriods(scheduleModel, relatedRepaymentPeriods); checkAndAdjustEmiIfNeededOnRelatedRepaymentPeriods(scheduleModel, relatedRepaymentPeriods);
} }
} }
@@ -638,6 +632,62 @@ public final class ProgressiveEMICalculator implements EMICalculator {
.reduce(scheduleModel.zero(), Money::add); .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, private List<RepaymentPeriod> findPossiblyOverdueRepaymentPeriods(final LocalDate targetDate,
final ProgressiveLoanInterestScheduleModel model) { final ProgressiveLoanInterestScheduleModel model) {
return model.repaymentPeriods().stream() // return model.repaymentPeriods().stream() //
@@ -767,7 +817,7 @@ public final class ProgressiveEMICalculator implements EMICalculator {
final List<LoanScheduleModelRepaymentPeriod> expectedRepaymentPeriods = scheduledDateGenerator.generateRepaymentPeriods(mc, final List<LoanScheduleModelRepaymentPeriod> expectedRepaymentPeriods = scheduledDateGenerator.generateRepaymentPeriods(mc,
periodStartDate, loanApplicationTerms, null); periodStartDate, loanApplicationTerms, null);
final ProgressiveLoanInterestScheduleModel temporaryReAgedScheduleModel = generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel temporaryReAgedScheduleModel = generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanApplicationTerms.toLoanConfigurationDetails(), null, expectedRepaymentPeriods, loanApplicationTerms.toLoanConfigurationDetails(),
loanApplicationTerms.getInstallmentAmountInMultiplesOf(), mc); loanApplicationTerms.getInstallmentAmountInMultiplesOf(), mc);
addDisbursement(temporaryReAgedScheduleModel, EmiChangeOperation.disburse(periodStartDate, loanApplicationTerms.getPrincipal())); 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.BiFunction;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.Setter; 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.DateUtils;
import org.apache.fineract.infrastructure.core.service.MathUtil; import org.apache.fineract.infrastructure.core.service.MathUtil;
import org.apache.fineract.organisation.monetary.domain.Money; 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; import org.apache.fineract.portfolio.loanproduct.domain.ILoanConfigurationDetails;
@Data @Data
@@ -62,7 +59,6 @@ public class ProgressiveLoanInterestScheduleModel {
private final TreeSet<InterestRate> interestRates; private final TreeSet<InterestRate> interestRates;
@JsonExclude @JsonExclude
private final ILoanConfigurationDetails loanProductRelatedDetail; private final ILoanConfigurationDetails loanProductRelatedDetail;
private final Map<LoanTermVariationType, List<LoanTermVariationsData>> loanTermVariations;
private final Integer installmentAmountInMultiplesOf; private final Integer installmentAmountInMultiplesOf;
@JsonExclude @JsonExclude
private final MathContext mc; private final MathContext mc;
@@ -74,12 +70,10 @@ public class ProgressiveLoanInterestScheduleModel {
private LocalDate lastOverdueBalanceChange; private LocalDate lastOverdueBalanceChange;
public ProgressiveLoanInterestScheduleModel(final List<RepaymentPeriod> repaymentPeriods, public ProgressiveLoanInterestScheduleModel(final List<RepaymentPeriod> repaymentPeriods,
final ILoanConfigurationDetails loanProductRelatedDetail, final List<LoanTermVariationsData> loanTermVariations, final ILoanConfigurationDetails loanProductRelatedDetail, final Integer installmentAmountInMultiplesOf, final MathContext mc) {
final Integer installmentAmountInMultiplesOf, final MathContext mc) {
this.repaymentPeriods = new ArrayList<>(repaymentPeriods); this.repaymentPeriods = new ArrayList<>(repaymentPeriods);
this.interestRates = new TreeSet<>(Collections.reverseOrder()); this.interestRates = new TreeSet<>(Collections.reverseOrder());
this.loanProductRelatedDetail = loanProductRelatedDetail; this.loanProductRelatedDetail = loanProductRelatedDetail;
this.loanTermVariations = buildLoanTermVariationMap(loanTermVariations);
this.installmentAmountInMultiplesOf = installmentAmountInMultiplesOf; this.installmentAmountInMultiplesOf = installmentAmountInMultiplesOf;
this.mc = mc; this.mc = mc;
this.zero = Money.zero(loanProductRelatedDetail.getCurrencyData(), 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, private ProgressiveLoanInterestScheduleModel(final List<RepaymentPeriod> repaymentPeriods, final TreeSet<InterestRate> interestRates,
final ILoanConfigurationDetails loanProductRelatedDetail, final ILoanConfigurationDetails loanProductRelatedDetail, final Integer installmentAmountInMultiplesOf, final MathContext mc,
final Map<LoanTermVariationType, List<LoanTermVariationsData>> loanTermVariations, final Integer installmentAmountInMultiplesOf, final boolean isCopiedForCalculation) {
final MathContext mc, final boolean isCopiedForCalculation) {
this.mc = mc; this.mc = mc;
this.repaymentPeriods = copyRepaymentPeriods(repaymentPeriods, this.repaymentPeriods = copyRepaymentPeriods(repaymentPeriods,
(previousPeriod, repaymentPeriod) -> RepaymentPeriod.copy(previousPeriod, repaymentPeriod, mc)); (previousPeriod, repaymentPeriod) -> RepaymentPeriod.copy(previousPeriod, repaymentPeriod, mc));
this.interestRates = new TreeSet<>(interestRates); this.interestRates = new TreeSet<>(interestRates);
this.loanProductRelatedDetail = loanProductRelatedDetail; this.loanProductRelatedDetail = loanProductRelatedDetail;
this.loanTermVariations = loanTermVariations;
this.installmentAmountInMultiplesOf = installmentAmountInMultiplesOf; this.installmentAmountInMultiplesOf = installmentAmountInMultiplesOf;
this.zero = Money.zero(loanProductRelatedDetail.getCurrencyData(), mc); this.zero = Money.zero(loanProductRelatedDetail.getCurrencyData(), mc);
modifiers = new HashMap<>(Map.of(EMI_RECALCULATION, true, COPY, isCopiedForCalculation, INTEREST_RECALCULATION_ENABLED, 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) { public ProgressiveLoanInterestScheduleModel deepCopy(MathContext mc) {
return new ProgressiveLoanInterestScheduleModel(repaymentPeriods, interestRates, loanProductRelatedDetail, loanTermVariations, return new ProgressiveLoanInterestScheduleModel(repaymentPeriods, interestRates, loanProductRelatedDetail,
installmentAmountInMultiplesOf, mc, false); installmentAmountInMultiplesOf, mc, false);
} }
public ProgressiveLoanInterestScheduleModel copyWithoutPaidAmounts() { public ProgressiveLoanInterestScheduleModel copyWithoutPaidAmounts() {
final List<RepaymentPeriod> repaymentPeriodCopies = copyRepaymentPeriods(repaymentPeriods, final List<RepaymentPeriod> repaymentPeriodCopies = copyRepaymentPeriods(repaymentPeriods,
(previousPeriod, repaymentPeriod) -> RepaymentPeriod.copyWithoutPaidAmounts(previousPeriod, repaymentPeriod, mc)); (previousPeriod, repaymentPeriod) -> RepaymentPeriod.copyWithoutPaidAmounts(previousPeriod, repaymentPeriod, mc));
return new ProgressiveLoanInterestScheduleModel(repaymentPeriodCopies, interestRates, loanProductRelatedDetail, loanTermVariations, return new ProgressiveLoanInterestScheduleModel(repaymentPeriodCopies, interestRates, loanProductRelatedDetail,
installmentAmountInMultiplesOf, mc, true); installmentAmountInMultiplesOf, mc, true);
} }
@@ -416,15 +408,6 @@ public class ProgressiveLoanInterestScheduleModel {
: date.isAfter(previousInterestPeriod.getDueDate()) ? previousInterestPeriod.getDueDate() : date; : 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() { public void disableEMIRecalculation() {
this.modifiers.put(EMI_RECALCULATION, false); this.modifiers.put(EMI_RECALCULATION, false);
} }
@@ -44,8 +44,9 @@ public class RepaymentPeriod {
@JsonExclude @JsonExclude
private final RepaymentPeriod previous; private final RepaymentPeriod previous;
@Setter
@Getter @Getter
private final LocalDate fromDate; private LocalDate fromDate;
@Setter @Setter
@Getter @Getter
private LocalDate dueDate; private LocalDate dueDate;
@@ -97,10 +98,10 @@ public class RepaymentPeriod {
private boolean noUnrecognisedInterest; private boolean noUnrecognisedInterest;
@Setter @Setter
@Getter @Getter
private boolean reAged = false; private boolean reAged;
@Setter @Setter
@Getter @Getter
private boolean reAgedEarlyRepaymentHolder = false; private boolean reAgedEarlyRepaymentHolder;
@Getter @Getter
@Setter @Setter
private Money reAgedInterest; 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.DaysInYearCustomStrategyType;
import org.apache.fineract.portfolio.common.domain.DaysInYearType; import org.apache.fineract.portfolio.common.domain.DaysInYearType;
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType; 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.LoanRepaymentScheduleInstallment;
import org.apache.fineract.portfolio.loanaccount.domain.LoanTermVariationType;
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction; import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType; 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.LoanReAgeInterestHandlingType;
import org.apache.fineract.portfolio.loanaccount.domain.reaging.LoanReAgeParameter; 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.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.loanschedule.domain.LoanScheduleModelRepaymentPeriod;
import org.apache.fineract.portfolio.loanaccount.service.ProgressiveLoanInterestScheduleModelParserServiceGsonImpl; import org.apache.fineract.portfolio.loanaccount.service.ProgressiveLoanInterestScheduleModelParserServiceGsonImpl;
import org.apache.fineract.portfolio.loanproduct.calc.data.EqualAmortizationValues; import org.apache.fineract.portfolio.loanproduct.calc.data.EqualAmortizationValues;
@@ -198,7 +197,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestScheduleModel = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestScheduleModel = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
Assertions.assertTrue(interestScheduleModel != null); Assertions.assertTrue(interestScheduleModel != null);
Assertions.assertTrue(interestScheduleModel.loanProductRelatedDetail() != null); Assertions.assertTrue(interestScheduleModel.loanProductRelatedDetail() != null);
@@ -237,7 +236,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -281,7 +280,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -317,7 +316,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -353,7 +352,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); 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)); threadLocalContextUtil.when(ThreadLocalContextUtil::getBusinessDate).thenReturn(LocalDate.of(2024, 2, 14));
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); 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)); threadLocalContextUtil.when(ThreadLocalContextUtil::getBusinessDate).thenReturn(LocalDate.of(2024, 2, 14));
final ProgressiveLoanInterestScheduleModel interestModel = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestModel = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestModel, LocalDate.of(2024, 1, 1), disbursedAmount); 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)); threadLocalContextUtil.when(ThreadLocalContextUtil::getBusinessDate).thenReturn(LocalDate.of(2024, 2, 14));
final ProgressiveLoanInterestScheduleModel interestModel = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestModel = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestModel, LocalDate.of(2024, 1, 1), disbursedAmount); 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)); threadLocalContextUtil.when(ThreadLocalContextUtil::getBusinessDate).thenReturn(LocalDate.of(2024, 2, 14));
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); 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)); threadLocalContextUtil.when(ThreadLocalContextUtil::getBusinessDate).thenReturn(LocalDate.of(2024, 2, 15));
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); 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)); threadLocalContextUtil.when(ThreadLocalContextUtil::getBusinessDate).thenReturn(LocalDate.of(2024, 2, 15));
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); 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)); threadLocalContextUtil.when(ThreadLocalContextUtil::getBusinessDate).thenReturn(LocalDate.of(2024, 2, 15));
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -870,7 +869,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
Money disbursedAmount = toMoney(100); Money disbursedAmount = toMoney(100);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -919,7 +918,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
Money disbursedAmount = toMoney(100.0); Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -968,7 +967,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
Money disbursedAmount = toMoney(100.0); Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 5), disbursedAmount); emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 5), disbursedAmount);
@@ -1014,7 +1013,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2023, 12, 12), disbursedAmount); emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2023, 12, 12), disbursedAmount);
@@ -1050,7 +1049,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( 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)); emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), toMoney(300.0));
Assertions.assertEquals(6.15, toDouble(interestSchedule.getTotalDueInterest())); Assertions.assertEquals(6.15, toDouble(interestSchedule.getTotalDueInterest()));
@@ -1098,7 +1097,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(1000.0); final Money disbursedAmount = toMoney(1000.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -1131,7 +1130,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -1164,7 +1163,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -1197,7 +1196,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -1239,7 +1238,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(1000.0); final Money disbursedAmount = toMoney(1000.0);
LocalDate disbursementDate = LocalDate.of(2024, 1, 1); LocalDate disbursementDate = LocalDate.of(2024, 1, 1);
@@ -1288,7 +1287,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestModel = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestModel = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(1000.0); final Money disbursedAmount = toMoney(1000.0);
emiCalculator.addDisbursement(interestModel, LocalDate.of(2024, 1, 1), disbursedAmount); emiCalculator.addDisbursement(interestModel, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -1350,7 +1349,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestModel = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestModel = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(1000.0); final Money disbursedAmount = toMoney(1000.0);
emiCalculator.addDisbursement(interestModel, LocalDate.of(2024, 1, 1), disbursedAmount); emiCalculator.addDisbursement(interestModel, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -1416,7 +1415,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestModel = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestModel = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount1st = toMoney(1000.0); final Money disbursedAmount1st = toMoney(1000.0);
final Money disbursedAmount2nd = toMoney(1000.0); final Money disbursedAmount2nd = toMoney(1000.0);
@@ -1489,7 +1488,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -1527,7 +1526,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); 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.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS);
Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1);
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
List<LoanTermVariationsData> loanTermVariations = new ArrayList<>();
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, loanTermVariations, installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); 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.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS);
Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1);
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
List<LoanTermVariationsData> loanTermVariations = new ArrayList<>();
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, loanTermVariations, installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); 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.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS);
Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1);
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
List<LoanTermVariationsData> loanTermVariations = new ArrayList<>();
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, loanTermVariations, installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); 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.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS);
Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1);
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
List<LoanTermVariationsData> loanTermVariations = new ArrayList<>();
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, loanTermVariations, installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); 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.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS);
Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1);
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
List<LoanTermVariationsData> loanTermVariations = new ArrayList<>();
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, loanTermVariations, installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); 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.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS);
Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1);
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
List<LoanTermVariationsData> loanTermVariations = new ArrayList<>();
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, loanTermVariations, installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); 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.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS);
Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1);
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
List<LoanTermVariationsData> loanTermVariations = new ArrayList<>();
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, loanTermVariations, installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); 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.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS);
Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1);
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
List<LoanTermVariationsData> loanTermVariations = new ArrayList<>();
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, loanTermVariations, installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); 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.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS);
Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1);
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
List<LoanTermVariationsData> loanTermVariations = new ArrayList<>();
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, loanTermVariations, installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -1906,12 +1896,12 @@ class ProgressiveEMICalculatorTest {
@Test @Test
public void test_reschedule_disbursedAmt100_dayInYears360_daysInMonth30_repayEvery1Month() { public void test_reschedule_disbursedAmt100_dayInYears360_daysInMonth30_repayEvery1Month() {
final List<LoanScheduleModelRepaymentPeriod> expectedRepaymentPeriods = List.of( final List<LoanScheduleModelRepaymentPeriod> expectedRepaymentPeriods = List.of(
repayment(1, LocalDate.of(2024, 1, 1), LocalDate.of(2024, 3, 1)), repayment(1, LocalDate.of(2024, 1, 1), LocalDate.of(2024, 2, 1)),
repayment(2, LocalDate.of(2024, 3, 1), LocalDate.of(2024, 4, 1)), repayment(2, LocalDate.of(2024, 2, 1), LocalDate.of(2024, 3, 1)),
repayment(3, LocalDate.of(2024, 4, 1), LocalDate.of(2024, 5, 1)), repayment(3, LocalDate.of(2024, 3, 1), LocalDate.of(2024, 4, 1)),
repayment(4, LocalDate.of(2024, 5, 1), LocalDate.of(2024, 6, 1)), repayment(4, LocalDate.of(2024, 4, 1), LocalDate.of(2024, 5, 1)),
repayment(5, LocalDate.of(2024, 6, 1), LocalDate.of(2024, 7, 1)), repayment(5, LocalDate.of(2024, 5, 1), LocalDate.of(2024, 6, 1)),
repayment(6, LocalDate.of(2024, 7, 1), LocalDate.of(2024, 8, 1))); repayment(6, LocalDate.of(2024, 6, 1), LocalDate.of(2024, 7, 1)));
final BigDecimal interestRate = BigDecimal.valueOf(7); final BigDecimal interestRate = BigDecimal.valueOf(7);
final Integer installmentAmountInMultiplesOf = null; final Integer installmentAmountInMultiplesOf = null;
@@ -1922,35 +1912,39 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS);
Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1);
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); 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( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, loanTermVariationsData, installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); 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, 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, 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, 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, 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, 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, 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 @Test
public void test_two_reschedules_disbursedAmt100_dayInYears360_daysInMonth30_repayEvery1Month() { public void test_two_reschedules_disbursedAmt100_dayInYears360_daysInMonth30_repayEvery1Month() {
final List<LoanScheduleModelRepaymentPeriod> expectedRepaymentPeriods = List.of( final List<LoanScheduleModelRepaymentPeriod> expectedRepaymentPeriods = List.of(
repayment(1, LocalDate.of(2024, 1, 1), LocalDate.of(2024, 3, 1)), repayment(1, LocalDate.of(2024, 1, 1), LocalDate.of(2024, 2, 1)),
repayment(2, LocalDate.of(2024, 3, 1), LocalDate.of(2024, 4, 1)), repayment(2, LocalDate.of(2024, 2, 1), LocalDate.of(2024, 3, 1)),
repayment(3, LocalDate.of(2024, 4, 1), LocalDate.of(2024, 6, 1)), repayment(3, LocalDate.of(2024, 3, 1), LocalDate.of(2024, 4, 1)),
repayment(4, LocalDate.of(2024, 6, 1), LocalDate.of(2024, 7, 1)), repayment(4, LocalDate.of(2024, 4, 1), LocalDate.of(2024, 5, 1)),
repayment(5, LocalDate.of(2024, 7, 1), LocalDate.of(2024, 8, 1)), repayment(5, LocalDate.of(2024, 5, 1), LocalDate.of(2024, 6, 1)),
repayment(6, LocalDate.of(2024, 8, 1), LocalDate.of(2024, 9, 1))); repayment(6, LocalDate.of(2024, 6, 1), LocalDate.of(2024, 7, 1)));
final BigDecimal interestRate = BigDecimal.valueOf(7); final BigDecimal interestRate = BigDecimal.valueOf(7);
final Integer installmentAmountInMultiplesOf = null; final Integer installmentAmountInMultiplesOf = null;
@@ -1961,38 +1955,40 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS);
Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1);
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); 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( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, loanTermVariationsData, installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); 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, 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, 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, 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, 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, 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, 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 @Test
public void test_reschedule_partial_period_disbursedAmt100_dayInYears360_daysInMonth30_repayEvery1Month() { public void test_reschedule_partial_period_disbursedAmt100_dayInYears360_daysInMonth30_repayEvery1Month() {
final List<LoanScheduleModelRepaymentPeriod> expectedRepaymentPeriods = List.of( final List<LoanScheduleModelRepaymentPeriod> expectedRepaymentPeriods = List.of(
repayment(1, LocalDate.of(2024, 1, 1), LocalDate.of(2024, 2, 1)), 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(2, LocalDate.of(2024, 2, 1), LocalDate.of(2024, 3, 1)),
repayment(3, LocalDate.of(2024, 4, 15), LocalDate.of(2024, 5, 15)), repayment(3, LocalDate.of(2024, 3, 1), LocalDate.of(2024, 4, 1)),
repayment(4, LocalDate.of(2024, 5, 15), LocalDate.of(2024, 6, 15)), repayment(4, LocalDate.of(2024, 4, 1), LocalDate.of(2024, 5, 1)),
repayment(5, LocalDate.of(2024, 6, 15), LocalDate.of(2024, 7, 15)), repayment(5, LocalDate.of(2024, 5, 1), LocalDate.of(2024, 6, 1)),
repayment(6, LocalDate.of(2024, 7, 15), LocalDate.of(2024, 8, 15))); repayment(6, LocalDate.of(2024, 6, 1), LocalDate.of(2024, 7, 1)));
final BigDecimal interestRate = BigDecimal.valueOf(7); final BigDecimal interestRate = BigDecimal.valueOf(7);
final Integer installmentAmountInMultiplesOf = null; final Integer installmentAmountInMultiplesOf = null;
@@ -2003,24 +1999,27 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS); Mockito.when(loanProductRelatedDetail.getRepaymentPeriodFrequencyType()).thenReturn(PeriodFrequencyType.MONTHS);
Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1);
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); 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( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, loanTermVariationsData, installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); 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, 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, 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, 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, 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, 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, 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 @Test
@@ -2045,7 +2044,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(5000.0); final Money disbursedAmount = toMoney(5000.0);
LocalDate disbursementDate = LocalDate.of(2023, 11, 13); LocalDate disbursementDate = LocalDate.of(2023, 11, 13);
@@ -2094,7 +2093,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(5000.0); final Money disbursedAmount = toMoney(5000.0);
LocalDate disbursementDate = LocalDate.of(2023, 11, 13); LocalDate disbursementDate = LocalDate.of(2023, 11, 13);
@@ -2139,7 +2138,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(5000.0); final Money disbursedAmount = toMoney(5000.0);
LocalDate disbursementDate = LocalDate.of(2023, 11, 13); LocalDate disbursementDate = LocalDate.of(2023, 11, 13);
@@ -2189,7 +2188,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(2450.0); final Money disbursedAmount = toMoney(2450.0);
LocalDate disbursementDate = LocalDate.of(2023, 10, 31); LocalDate disbursementDate = LocalDate.of(2023, 10, 31);
@@ -2226,7 +2225,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(10000.0); final Money disbursedAmount = toMoney(10000.0);
LocalDate disbursementDate = LocalDate.of(2023, 10, 30); LocalDate disbursementDate = LocalDate.of(2023, 10, 30);
@@ -2263,7 +2262,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(3333.0); final Money disbursedAmount = toMoney(3333.0);
LocalDate disbursementDate = LocalDate.of(2023, 10, 29); LocalDate disbursementDate = LocalDate.of(2023, 10, 29);
@@ -2300,7 +2299,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(245000.0); final Money disbursedAmount = toMoney(245000.0);
LocalDate disbursementDate = LocalDate.of(2023, 10, 31); LocalDate disbursementDate = LocalDate.of(2023, 10, 31);
@@ -2337,7 +2336,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(1500.0); final Money disbursedAmount = toMoney(1500.0);
LocalDate disbursementDate = LocalDate.of(2021, 10, 30); LocalDate disbursementDate = LocalDate.of(2021, 10, 30);
@@ -2374,7 +2373,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(5000); final Money disbursedAmount = toMoney(5000);
LocalDate disbursementDate = LocalDate.of(2022, 10, 29); LocalDate disbursementDate = LocalDate.of(2022, 10, 29);
@@ -2410,7 +2409,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator 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)); 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); checkPeriod(interestSchedule, 0, 857.71, 41.05, 816.66, 4183.34, false);
@@ -2443,7 +2442,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(true); Mockito.when(loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate()).thenReturn(true);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator 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)); 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); checkPeriod(interestSchedule, 0, 857.72, 41.05, 816.67, 4183.33, false);
@@ -2478,7 +2477,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -2535,7 +2534,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -2603,7 +2602,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -2662,7 +2661,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -2720,7 +2719,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -2772,7 +2771,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -2830,7 +2829,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -2887,7 +2886,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -2955,7 +2954,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(10000.0); final Money disbursedAmount = toMoney(10000.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2023, 12, 12), disbursedAmount); emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2023, 12, 12), disbursedAmount);
@@ -2993,7 +2992,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(15000.0); final Money disbursedAmount = toMoney(15000.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 7, 23), disbursedAmount); emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 7, 23), disbursedAmount);
@@ -3030,7 +3029,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(245000.0); final Money disbursedAmount = toMoney(245000.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2023, 10, 31), disbursedAmount); emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2023, 10, 31), disbursedAmount);
@@ -3070,7 +3069,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(2450); final Money disbursedAmount = toMoney(2450);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 10, 31), disbursedAmount); emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 10, 31), disbursedAmount);
@@ -3109,7 +3108,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(5000.0); final Money disbursedAmount = toMoney(5000.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2022, 10, 29), disbursedAmount); emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2022, 10, 29), disbursedAmount);
@@ -3145,7 +3144,7 @@ class ProgressiveEMICalculatorTest {
.thenReturn(DaysInYearCustomStrategyType.FEB_29_PERIOD_ONLY); .thenReturn(DaysInYearCustomStrategyType.FEB_29_PERIOD_ONLY);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -3181,7 +3180,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -3246,7 +3245,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestScheduleExpected = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestScheduleExpected = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
ProgressiveLoanInterestScheduleModel interestScheduleActual = copyJson(interestScheduleExpected); ProgressiveLoanInterestScheduleModel interestScheduleActual = copyJson(interestScheduleExpected);
@@ -3332,7 +3331,7 @@ class ProgressiveEMICalculatorTest {
final Integer installmentAmountInMultiplesOf = null; final Integer installmentAmountInMultiplesOf = null;
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(700.0)); emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(700.0));
checkPeriod(interestSchedule, 0, 181.94, 7.11, 174.83, 525.17, false); // checkPeriod(interestSchedule, 0, 181.94, 7.11, 174.83, 525.17, false); //
@@ -3371,7 +3370,7 @@ class ProgressiveEMICalculatorTest {
final Integer installmentAmountInMultiplesOf = null; final Integer installmentAmountInMultiplesOf = null;
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(750.0)); emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(750.0));
checkPeriod(interestSchedule, 0, 195.00, 7.50, 187.50, 562.50, false); // checkPeriod(interestSchedule, 0, 195.00, 7.50, 187.50, 562.50, false); //
@@ -3410,7 +3409,7 @@ class ProgressiveEMICalculatorTest {
final Integer installmentAmountInMultiplesOf = null; final Integer installmentAmountInMultiplesOf = null;
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(600.0)); emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(600.0));
checkPeriod(interestSchedule, 0, 151.38, 1.38, 150.00, 450.00, false); // checkPeriod(interestSchedule, 0, 151.38, 1.38, 150.00, 450.00, false); //
@@ -3449,7 +3448,7 @@ class ProgressiveEMICalculatorTest {
final Integer installmentAmountInMultiplesOf = null; final Integer installmentAmountInMultiplesOf = null;
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(400.0)); emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(400.0));
checkPeriod(interestSchedule, 0, 103.93, 3.93, 100.00, 300.00, false); // checkPeriod(interestSchedule, 0, 103.93, 3.93, 100.00, 300.00, false); //
@@ -3503,7 +3502,7 @@ class ProgressiveEMICalculatorTest {
final Integer installmentAmountInMultiplesOf = null; final Integer installmentAmountInMultiplesOf = null;
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(1000.0)); emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(1000.0));
@@ -3532,7 +3531,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1); Mockito.when(loanProductRelatedDetail.getRepayEvery()).thenReturn(1);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(1000.0)); emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(1000.0));
@@ -3563,7 +3562,7 @@ class ProgressiveEMICalculatorTest {
final Integer installmentAmountInMultiplesOf = null; final Integer installmentAmountInMultiplesOf = null;
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(1000.0)); emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(1000.0));
@@ -3595,7 +3594,7 @@ class ProgressiveEMICalculatorTest {
final Integer installmentAmountInMultiplesOf = null; final Integer installmentAmountInMultiplesOf = null;
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(1000.0)); emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(1000.0));
@@ -3628,7 +3627,7 @@ class ProgressiveEMICalculatorTest {
final Integer installmentAmountInMultiplesOf = null; final Integer installmentAmountInMultiplesOf = null;
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(1000.0)); emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(1000.0));
@@ -3659,7 +3658,7 @@ class ProgressiveEMICalculatorTest {
final Integer installmentAmountInMultiplesOf = null; final Integer installmentAmountInMultiplesOf = null;
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(1000.0)); emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(1000.0));
@@ -3696,7 +3695,7 @@ class ProgressiveEMICalculatorTest {
final Integer installmentAmountInMultiplesOf = null; final Integer installmentAmountInMultiplesOf = null;
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(1000.0)); emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(1000.0));
@@ -3737,7 +3736,7 @@ class ProgressiveEMICalculatorTest {
final Integer installmentAmountInMultiplesOf = null; final Integer installmentAmountInMultiplesOf = null;
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( 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(7500.0));
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(2500.0)); emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(2500.0));
@@ -3812,7 +3811,7 @@ class ProgressiveEMICalculatorTest {
final Integer installmentAmountInMultiplesOf = null; final Integer installmentAmountInMultiplesOf = null;
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(1000.0)); emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(1000.0));
@@ -3862,7 +3861,7 @@ class ProgressiveEMICalculatorTest {
final Integer installmentAmountInMultiplesOf = null; final Integer installmentAmountInMultiplesOf = null;
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(500.0)); emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(500.0));
checkPeriod(interestSchedule, 0, 170.01, 5.00, 165.01, 334.99, false); // checkPeriod(interestSchedule, 0, 170.01, 5.00, 165.01, 334.99, false); //
@@ -3899,7 +3898,7 @@ class ProgressiveEMICalculatorTest {
final Integer installmentAmountInMultiplesOf = null; final Integer installmentAmountInMultiplesOf = null;
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(500.0)); emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(500.0));
checkPeriod(interestSchedule, 0, 170.01, 5.00, 165.01, 334.99, false); // checkPeriod(interestSchedule, 0, 170.01, 5.00, 165.01, 334.99, false); //
@@ -3935,7 +3934,7 @@ class ProgressiveEMICalculatorTest {
final Integer installmentAmountInMultiplesOf = null; final Integer installmentAmountInMultiplesOf = null;
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(500.0)); emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(500.0));
checkPeriod(interestSchedule, 0, 170.01, 5.00, 165.01, 334.99, false); // checkPeriod(interestSchedule, 0, 170.01, 5.00, 165.01, 334.99, false); //
@@ -3993,7 +3992,7 @@ class ProgressiveEMICalculatorTest {
final Integer installmentAmountInMultiplesOf = null; final Integer installmentAmountInMultiplesOf = null;
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(500.0)); emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(500.0));
checkPeriod(interestSchedule, 0, 170.01, 5.00, 165.01, 334.99, false); // checkPeriod(interestSchedule, 0, 170.01, 5.00, 165.01, 334.99, false); //
@@ -4040,7 +4039,7 @@ class ProgressiveEMICalculatorTest {
final Integer installmentAmountInMultiplesOf = null; final Integer installmentAmountInMultiplesOf = null;
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(1000)); emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(1000));
@@ -4079,7 +4078,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.isAllowPartialPeriodInterestCalculation()).thenReturn(true); Mockito.when(loanProductRelatedDetail.isAllowPartialPeriodInterestCalculation()).thenReturn(true);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(1000)); emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(1000));
@@ -4116,7 +4115,7 @@ class ProgressiveEMICalculatorTest {
final Integer installmentAmountInMultiplesOf = null; final Integer installmentAmountInMultiplesOf = null;
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(1000)); emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(1000));
@@ -4177,7 +4176,7 @@ class ProgressiveEMICalculatorTest {
final Integer installmentAmountInMultiplesOf = null; final Integer installmentAmountInMultiplesOf = null;
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(1000)); emiCalculator.addDisbursement(interestSchedule, disbursementDate, toMoney(1000));
@@ -4262,7 +4261,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -4326,7 +4325,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -4415,7 +4414,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -4474,7 +4473,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -4534,7 +4533,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -4617,7 +4616,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -4700,7 +4699,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -4773,7 +4772,7 @@ class ProgressiveEMICalculatorTest {
Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency); Mockito.when(loanProductRelatedDetail.getCurrencyData()).thenReturn(currency);
final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel( final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generatePeriodInterestScheduleModel(
expectedRepaymentPeriods, loanProductRelatedDetail, List.of(), installmentAmountInMultiplesOf, mc); expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
final Money disbursedAmount = toMoney(100.0); final Money disbursedAmount = toMoney(100.0);
emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount); emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);