This is an automated email from the ASF dual-hosted git repository. adamsaghy pushed a commit to branch develop in repository https://gitbox.apache.org/repos/asf/fineract.git
commit 97b8bfa26f70e00e498e28cd6289ab1b6e751e1a Author: mariiaKraievska <[email protected]> AuthorDate: Mon Dec 15 14:08:45 2025 +0200 FINERACT-2354: Loan reschedule with extra terms after re-aging --- .../src/test/resources/features/Loan.feature | 2 +- .../test/resources/features/LoanReAging.feature | 24 +++++----- .../features/LoanReAgingEqualAmortization.feature | 56 ++++++++++------------ .../resources/features/LoanReAgingPreview.feature | 2 +- ...dvancedPaymentScheduleTransactionProcessor.java | 21 ++++---- .../portfolio/loanproduct/calc/EMICalculator.java | 3 +- .../loanproduct/calc/ProgressiveEMICalculator.java | 21 +++++--- .../data/ProgressiveLoanInterestScheduleModel.java | 5 +- .../calc/ProgressiveEMICalculatorTest.java | 16 +++---- 9 files changed, 76 insertions(+), 74 deletions(-) diff --git a/fineract-e2e-tests-runner/src/test/resources/features/Loan.feature b/fineract-e2e-tests-runner/src/test/resources/features/Loan.feature index 8bdd072cf7..5ba518723a 100644 --- a/fineract-e2e-tests-runner/src/test/resources/features/Loan.feature +++ b/fineract-e2e-tests-runner/src/test/resources/features/Loan.feature @@ -5853,7 +5853,7 @@ Feature: Loan | 2 | 15 | 16 February 2024 | | 600.0 | 150.0 | 0.0 | 0.0 | 0.0 | 150.0 | 0.0 | 0.0 | 0.0 | 150.0 | | 3 | 15 | 02 March 2024 | | 450.0 | 150.0 | 0.0 | 0.0 | 0.0 | 150.0 | 0.0 | 0.0 | 0.0 | 150.0 | | 4 | 10 | 12 March 2024 | | 300.0 | 150.0 | 0.0 | 0.0 | 0.0 | 150.0 | 0.0 | 0.0 | 0.0 | 150.0 | - | 5 | 15 | 01 April 2024 | | 150.0 | 150.0 | 0.0 | 0.0 | 0.0 | 150.0 | 0.0 | 0.0 | 0.0 | 150.0 | + | 5 | 20 | 01 April 2024 | | 150.0 | 150.0 | 0.0 | 0.0 | 0.0 | 150.0 | 0.0 | 0.0 | 0.0 | 150.0 | | 6 | 15 | 16 April 2024 | | 0.0 | 150.0 | 0.0 | 0.0 | 0.0 | 150.0 | 0.0 | 0.0 | 0.0 | 150.0 | Then Loan Repayment schedule has the following data in Total row: | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding | diff --git a/fineract-e2e-tests-runner/src/test/resources/features/LoanReAging.feature b/fineract-e2e-tests-runner/src/test/resources/features/LoanReAging.feature index 483c909bed..9fa332f0ee 100644 --- a/fineract-e2e-tests-runner/src/test/resources/features/LoanReAging.feature +++ b/fineract-e2e-tests-runner/src/test/resources/features/LoanReAging.feature @@ -1814,7 +1814,7 @@ Feature: LoanReAging | 1 | 0 | 01 January 2025 | 01 April 2025 | 500.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | | | | 16 January 2025 | | 100.0 | | | 0.0 | | 0.0 | 0.0 | | | | | 2 | 0 | 16 January 2025 | 01 April 2025 | 600.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | - | 3 | 31 | 01 February 2025 | 01 April 2025 | 600.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | + | 3 | 16 | 01 February 2025 | 01 April 2025 | 600.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | | 4 | 28 | 01 March 2025 | 01 April 2025 | 600.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | | 5 | 31 | 01 April 2025 | 01 April 2025 | 600.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | | 6 | 0 | 01 April 2025 | | 0.0 | 600.0 | 0.0 | 0.0 | 0.0 | 600.0 | 0.0 | 0.0 | 0.0 | 600.0 | @@ -8885,8 +8885,7 @@ Then Loan Repayment schedule has 4 periods, with the following data for periods: When Loan Pay-off is made on "16 April 2024" Then Loan is closed with zero outstanding balance and it's all installments have obligations met -# TODO check and unSkip when PS-2937 is done - @Skip @TestRailId:C4286 + @TestRailId:C4286 Scenario: Verify Re-aging with loan reschedule: UC1.1: Interest handling: DEFAULT, reschedule - extra terms When Admin sets the business date to "01 January 2024" And Admin creates a client with random data @@ -9002,8 +9001,7 @@ Then Loan Repayment schedule has 4 periods, with the following data for periods: When Admin creates and approves Loan reschedule with the following data: | rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate | | 01 July 2024 | 02 April 2024 | | | | 2 | | -# TODO check numbers - Then Loan Repayment schedule has 9 periods, with the following data for periods: + Then Loan Repayment schedule has 11 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.57 | 16.43 | 0.58 | 0.0 | 0.0 | 17.01 | 17.01 | 0.0 | 0.0 | 0.0 | @@ -9012,14 +9010,14 @@ Then Loan Repayment schedule has 4 periods, with the following data for periods: | 4 | 17 | 01 April 2024 | | 70.25 | 13.32 | 0.98 | 0.0 | 0.0 | 14.3 | 0.0 | 0.0 | 0.0 | 14.3 | | 5 | 30 | 01 May 2024 | | 56.36 | 13.89 | 0.41 | 0.0 | 0.0 | 14.3 | 0.0 | 0.0 | 0.0 | 14.3 | | 6 | 31 | 01 June 2024 | | 42.39 | 13.97 | 0.33 | 0.0 | 0.0 | 14.3 | 0.0 | 0.0 | 0.0 | 14.3 | - | 7 | 30 | 01 July 2024 | | 28.34 | 14.05 | 0.25 | 0.0 | 0.0 | 14.3 | 0.0 | 0.0 | 0.0 | 14.3 | - | 8 | 31 | 01 August 2024 | | 14.21 | 14.13 | 0.17 | 0.0 | 0.0 | 14.3 | 0.0 | 0.0 | 0.0 | 14.3 | - | 9 | 31 | 01 September 2024 | | 0.0 | 14.21 | 0.08 | 0.0 | 0.0 | 14.29 | 0.0 | 0.0 | 0.0 | 14.29 | - | 10 | 30 | 01 October 2024 | | 0.0 | 14.21 | 0.08 | 0.0 | 0.0 | 14.29 | 0.0 | 0.0 | 0.0 | 14.29 | - | 11 | 31 | 01 November 2024 | | 0.0 | 14.21 | 0.08 | 0.0 | 0.0 | 14.29 | 0.0 | 0.0 | 0.0 | 14.29 | + | 7 | 30 | 01 July 2024 | | 34.01 | 8.38 | 0.25 | 0.0 | 0.0 | 8.63 | 0.0 | 0.0 | 0.0 | 8.63 | + | 8 | 31 | 01 August 2024 | | 25.58 | 8.43 | 0.2 | 0.0 | 0.0 | 8.63 | 0.0 | 0.0 | 0.0 | 8.63 | + | 9 | 31 | 01 September 2024 | | 17.1 | 8.48 | 0.15 | 0.0 | 0.0 | 8.63 | 0.0 | 0.0 | 0.0 | 8.63 | + | 10 | 30 | 01 October 2024 | | 8.57 | 8.53 | 0.1 | 0.0 | 0.0 | 8.63 | 0.0 | 0.0 | 0.0 | 8.63 | + | 11 | 31 | 01 November 2024 | | 0.0 | 8.57 | 0.05 | 0.0 | 0.0 | 8.62 | 0.0 | 0.0 | 0.0 | 8.62 | And Loan Repayment schedule has the following data in Total row: - | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding | - | 100.0 | 2.8 | 0.0 | 0.0 | 102.8 | 17.01 | 0.0 | 0.0 | 85.79 | + | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding | + | 100.0 | 3.05 | 0.0 | 0.0 | 103.05 | 17.01 | 0.0 | 0.0 | 86.04 | 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 | @@ -9029,7 +9027,7 @@ Then Loan Repayment schedule has 4 periods, with the following data for periods: When Loan Pay-off is made on "02 April 2024" Then Loan is closed with zero outstanding balance and it's all installments have obligations met - # TODO check and unSkip when PS-2937 is done + # TODO check and unSkip when WAIVE_INTEREST strategy is implemented @Skip @TestRailId:C4287 Scenario: Verify Re-aging with loan reschedule: UC1.2: Interest handling: WAIVE_INTEREST, reschedule - extra terms When Admin sets the business date to "01 January 2024" diff --git a/fineract-e2e-tests-runner/src/test/resources/features/LoanReAgingEqualAmortization.feature b/fineract-e2e-tests-runner/src/test/resources/features/LoanReAgingEqualAmortization.feature index e933282d5a..a44efb3df6 100644 --- a/fineract-e2e-tests-runner/src/test/resources/features/LoanReAgingEqualAmortization.feature +++ b/fineract-e2e-tests-runner/src/test/resources/features/LoanReAgingEqualAmortization.feature @@ -8261,8 +8261,7 @@ Feature: LoanReAgingEqualAmortization When Loan Pay-off is made on "01 July 2024" Then Loan is closed with zero outstanding balance and it's all installments have obligations met - # TODO check and unSkip when PS-2937 is done - @Skip @TestRailId:C4288 + @TestRailId:C4288 Scenario: Verify Re-aging with loan reschedule: UC1.3: Interest handling: EQUAL_AMORTIZATION_PAYABLE_INTEREST, reschedule - extra terms When Admin sets the business date to "01 January 2024" And Admin creates a client with random data @@ -8353,7 +8352,6 @@ Feature: LoanReAgingEqualAmortization When Admin creates a Loan re-aging transaction with the following data: | frequencyNumber | frequencyType | startDate | numberOfInstallments | reAgeInterestHandling | | 1 | MONTHS | 01 April 2024 | 6 | EQUAL_AMORTIZATION_PAYABLE_INTEREST | - # TODO check numbers Then Loan Repayment schedule has 9 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 | | | | @@ -8379,24 +8377,23 @@ Feature: LoanReAgingEqualAmortization When Admin creates and approves Loan reschedule with the following data: | rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate | | 01 July 2024 | 02 April 2024 | | | | 2 | | -# TODO check numbers - Then Loan Repayment schedule has 9 periods, with the following data for periods: + Then Loan Repayment schedule has 11 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.57 | 16.43 | 0.58 | 0.0 | 0.0 | 17.01 | 17.01 | 0.0 | 0.0 | 0.0 | | 2 | 29 | 01 March 2024 | 15 March 2024 | 83.57 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | | 3 | 14 | 15 March 2024 | 15 March 2024 | 83.57 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | - | 4 | 17 | 01 April 2024 | | 70.25 | 13.32 | 0.98 | 0.0 | 0.0 | 14.3 | 0.0 | 0.0 | 0.0 | 14.3 | - | 5 | 30 | 01 May 2024 | | 56.36 | 13.89 | 0.41 | 0.0 | 0.0 | 14.3 | 0.0 | 0.0 | 0.0 | 14.3 | - | 6 | 31 | 01 June 2024 | | 42.39 | 13.97 | 0.33 | 0.0 | 0.0 | 14.3 | 0.0 | 0.0 | 0.0 | 14.3 | - | 7 | 30 | 01 July 2024 | | 28.34 | 14.05 | 0.25 | 0.0 | 0.0 | 14.3 | 0.0 | 0.0 | 0.0 | 14.3 | - | 8 | 31 | 01 August 2024 | | 14.21 | 14.13 | 0.17 | 0.0 | 0.0 | 14.3 | 0.0 | 0.0 | 0.0 | 14.3 | - | 9 | 31 | 01 September 2024 | | 0.0 | 14.21 | 0.08 | 0.0 | 0.0 | 14.29 | 0.0 | 0.0 | 0.0 | 14.29 | - | 10 | 30 | 01 October 2024 | | 0.0 | 14.21 | 0.08 | 0.0 | 0.0 | 14.29 | 0.0 | 0.0 | 0.0 | 14.29 | - | 11 | 31 | 01 November 2024 | | 0.0 | 14.21 | 0.08 | 0.0 | 0.0 | 14.29 | 0.0 | 0.0 | 0.0 | 14.29 | + | 4 | 17 | 01 April 2024 | | 69.64 | 13.93 | 0.12 | 0.0 | 0.0 | 14.05 | 0.0 | 0.0 | 0.0 | 14.05 | + | 5 | 30 | 01 May 2024 | | 55.71 | 13.93 | 0.12 | 0.0 | 0.0 | 14.05 | 0.0 | 0.0 | 0.0 | 14.05 | + | 6 | 31 | 01 June 2024 | | 41.78 | 13.93 | 0.12 | 0.0 | 0.0 | 14.05 | 0.0 | 0.0 | 0.0 | 14.05 | + | 7 | 30 | 01 July 2024 | | 33.47 | 8.31 | 0.12 | 0.0 | 0.0 | 8.43 | 0.0 | 0.0 | 0.0 | 8.43 | + | 8 | 31 | 01 August 2024 | | 25.16 | 8.31 | 0.12 | 0.0 | 0.0 | 8.43 | 0.0 | 0.0 | 0.0 | 8.43 | + | 9 | 31 | 01 September 2024 | | 16.84 | 8.32 | 0.11 | 0.0 | 0.0 | 8.43 | 0.0 | 0.0 | 0.0 | 8.43 | + | 10 | 30 | 01 October 2024 | | 8.41 | 8.43 | 0.0 | 0.0 | 0.0 | 8.43 | 0.0 | 0.0 | 0.0 | 8.43 | + | 11 | 31 | 01 November 2024 | | 0.0 | 8.41 | 0.0 | 0.0 | 0.0 | 8.41 | 0.0 | 0.0 | 0.0 | 8.41 | And Loan Repayment schedule has the following data in Total row: - | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding | - | 100.0 | 2.8 | 0.0 | 0.0 | 102.8 | 17.01 | 0.0 | 0.0 | 85.79 | + | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding | + | 100.0 | 1.29 | 0.0 | 0.0 | 101.29 | 17.01 | 0.0 | 0.0 | 84.28 | 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 | @@ -8406,8 +8403,7 @@ Feature: LoanReAgingEqualAmortization When Loan Pay-off is made on "02 April 2024" Then Loan is closed with zero outstanding balance and it's all installments have obligations met -# TODO check and unSkip when PS-2937 is done - @Skip @TestRailId:C4289 + @TestRailId:C4289 Scenario: Verify Re-aging with loan reschedule: UC1.4: Interest handling: EQUAL_AMORTIZATION_FULL_INTEREST, reschedule - extra terms When Admin sets the business date to "01 January 2024" And Admin creates a client with random data @@ -8498,7 +8494,6 @@ Feature: LoanReAgingEqualAmortization When Admin creates a Loan re-aging transaction with the following data: | frequencyNumber | frequencyType | startDate | numberOfInstallments | reAgeInterestHandling | | 1 | MONTHS | 01 April 2024 | 6 | EQUAL_AMORTIZATION_FULL_INTEREST | - # TODO check numbers Then Loan Repayment schedule has 9 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 | | | | @@ -8524,29 +8519,28 @@ Feature: LoanReAgingEqualAmortization When Admin creates and approves Loan reschedule with the following data: | rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate | | 01 July 2024 | 02 April 2024 | | | | 2 | | -# TODO check numbers - Then Loan Repayment schedule has 9 periods, with the following data for periods: + Then Loan Repayment schedule has 11 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.57 | 16.43 | 0.58 | 0.0 | 0.0 | 17.01 | 17.01 | 0.0 | 0.0 | 0.0 | | 2 | 29 | 01 March 2024 | 15 March 2024 | 83.57 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | | 3 | 14 | 15 March 2024 | 15 March 2024 | 83.57 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | - | 4 | 17 | 01 April 2024 | | 70.25 | 13.32 | 0.98 | 0.0 | 0.0 | 14.3 | 0.0 | 0.0 | 0.0 | 14.3 | - | 5 | 30 | 01 May 2024 | | 56.36 | 13.89 | 0.41 | 0.0 | 0.0 | 14.3 | 0.0 | 0.0 | 0.0 | 14.3 | - | 6 | 31 | 01 June 2024 | | 42.39 | 13.97 | 0.33 | 0.0 | 0.0 | 14.3 | 0.0 | 0.0 | 0.0 | 14.3 | - | 7 | 30 | 01 July 2024 | | 28.34 | 14.05 | 0.25 | 0.0 | 0.0 | 14.3 | 0.0 | 0.0 | 0.0 | 14.3 | - | 8 | 31 | 01 August 2024 | | 14.21 | 14.13 | 0.17 | 0.0 | 0.0 | 14.3 | 0.0 | 0.0 | 0.0 | 14.3 | - | 9 | 31 | 01 September 2024 | | 0.0 | 14.21 | 0.08 | 0.0 | 0.0 | 14.29 | 0.0 | 0.0 | 0.0 | 14.29 | - | 10 | 30 | 01 October 2024 | | 0.0 | 14.21 | 0.08 | 0.0 | 0.0 | 14.29 | 0.0 | 0.0 | 0.0 | 14.29 | - | 11 | 31 | 01 November 2024 | | 0.0 | 14.21 | 0.08 | 0.0 | 0.0 | 14.29 | 0.0 | 0.0 | 0.0 | 14.29 | + | 4 | 17 | 01 April 2024 | | 69.64 | 13.93 | 0.33 | 0.0 | 0.0 | 14.26 | 0.0 | 0.0 | 0.0 | 14.26 | + | 5 | 30 | 01 May 2024 | | 55.71 | 13.93 | 0.33 | 0.0 | 0.0 | 14.26 | 0.0 | 0.0 | 0.0 | 14.26 | + | 6 | 31 | 01 June 2024 | | 41.78 | 13.93 | 0.33 | 0.0 | 0.0 | 14.26 | 0.0 | 0.0 | 0.0 | 14.26 | + | 7 | 30 | 01 July 2024 | | 33.55 | 8.23 | 0.33 | 0.0 | 0.0 | 8.56 | 0.0 | 0.0 | 0.0 | 8.56 | + | 8 | 31 | 01 August 2024 | | 25.32 | 8.23 | 0.33 | 0.0 | 0.0 | 8.56 | 0.0 | 0.0 | 0.0 | 8.56 | + | 9 | 31 | 01 September 2024 | | 17.1 | 8.22 | 0.34 | 0.0 | 0.0 | 8.56 | 0.0 | 0.0 | 0.0 | 8.56 | + | 10 | 30 | 01 October 2024 | | 8.54 | 8.56 | 0.0 | 0.0 | 0.0 | 8.56 | 0.0 | 0.0 | 0.0 | 8.56 | + | 11 | 31 | 01 November 2024 | | 0.0 | 8.54 | 0.0 | 0.0 | 0.0 | 8.54 | 0.0 | 0.0 | 0.0 | 8.54 | And Loan Repayment schedule has the following data in Total row: - | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding | - | 100.0 | 2.8 | 0.0 | 0.0 | 102.8 | 17.01 | 0.0 | 0.0 | 85.79 | + | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding | + | 100.0 | 2.57 | 0.0 | 0.0 | 102.57 | 17.01 | 0.0 | 0.0 | 85.56 | 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.01 | 16.43 | 0.58 | 0.0 | 0.0 | 83.57 | false | false | - | 15 March 2024 | Re-age | 84.28 | 83.57 | 0.71 | 0.0 | 0.0 | 0.0 | false | false | + | 15 March 2024 | Re-age | 85.56 | 83.57 | 1.99 | 0.0 | 0.0 | 0.0 | false | false | # --- Close loan --- When Loan Pay-off is made on "02 April 2024" Then Loan is closed with zero outstanding balance and it's all installments have obligations met diff --git a/fineract-e2e-tests-runner/src/test/resources/features/LoanReAgingPreview.feature b/fineract-e2e-tests-runner/src/test/resources/features/LoanReAgingPreview.feature index 5cda8a56e3..0e7215425e 100644 --- a/fineract-e2e-tests-runner/src/test/resources/features/LoanReAgingPreview.feature +++ b/fineract-e2e-tests-runner/src/test/resources/features/LoanReAgingPreview.feature @@ -471,7 +471,7 @@ Feature: LoanReAgingPreview | 1 | 0 | 01 January 2025 | 01 April 2025 | 500.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | | | | 16 January 2025 | | 100.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | | | | | 2 | 0 | 16 January 2025 | 01 April 2025 | 600.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | - | 3 | 31 | 01 February 2025 | 01 April 2025 | 600.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | + | 3 | 16 | 01 February 2025 | 01 April 2025 | 600.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | | 4 | 28 | 01 March 2025 | 01 April 2025 | 600.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | | 5 | 31 | 01 April 2025 | 01 April 2025 | 600.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | | 6 | 0 | 01 April 2025 | | 0.0 | 600.0 | 0.0 | 0.0 | 0.0 | 600.0 | 0.0 | 0.0 | 0.0 | 600.0 | diff --git a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java index de8a16eecc..9dd24b79da 100644 --- a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java +++ b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java @@ -237,7 +237,7 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep for (final ChangeOperation changeOperation : changeOperations) { if (changeOperation.isLoanTermVariationsData()) { final LoanTermVariationsData termVariationsData = changeOperation.getLoanTermVariationsData().get(); - processLoanTermVariation(installments, termVariationsData, scheduleModel); + processLoanTermVariation(termVariationsData, ctx); } else if (changeOperation.isTransaction()) { LoanTransaction transaction = changeOperation.getLoanTransaction().get(); if (loan.getStatus().isOverpaid() && transaction.isAccrualActivity()) { @@ -303,12 +303,14 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep .map(TransactionChangeData::getNewTransaction).findFirst().orElse(transaction); } - private void processLoanTermVariation(final List<LoanRepaymentScheduleInstallment> installments, - final LoanTermVariationsData termVariationsData, final ProgressiveLoanInterestScheduleModel scheduleModel) { + private void processLoanTermVariation(final LoanTermVariationsData termVariationsData, final ProgressiveTransactionCtx ctx) { + final List<LoanRepaymentScheduleInstallment> installments = ctx.getInstallments(); + final ProgressiveLoanInterestScheduleModel scheduleModel = ctx.getModel(); switch (termVariationsData.getTermVariationType()) { case INTEREST_PAUSE -> handleInterestPause(installments, termVariationsData, scheduleModel); case INTEREST_RATE_FROM_INSTALLMENT -> handleChangeInterestRate(installments, termVariationsData, scheduleModel); - case EXTEND_REPAYMENT_PERIOD -> handleExtraRepaymentPeriod(installments, termVariationsData, scheduleModel); + case EXTEND_REPAYMENT_PERIOD -> + handleExtraRepaymentPeriod(installments, termVariationsData, scheduleModel, ctx.getAlreadyProcessedTransactions()); case DUE_DATE -> handleDueDateChangeOnRepaymentPeriod(installments, termVariationsData, scheduleModel); default -> throw new IllegalStateException("Unhandled LoanTermVariationType."); } @@ -396,10 +398,12 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep } private void handleExtraRepaymentPeriod(final List<LoanRepaymentScheduleInstallment> installments, - final LoanTermVariationsData termVariationsData, final ProgressiveLoanInterestScheduleModel scheduleModel) { + final LoanTermVariationsData termVariationsData, final ProgressiveLoanInterestScheduleModel scheduleModel, + final List<LoanTransaction> alreadyProcessedTransactions) { final LocalDate interestRateChangeSubmittedOnDate = termVariationsData.getTermVariationApplicableFrom(); final int repaymentPeriodsToAdd = termVariationsData.getDecimalValue().intValue(); - emiCalculator.addRepaymentPeriods(scheduleModel, interestRateChangeSubmittedOnDate, repaymentPeriodsToAdd); + emiCalculator.addRepaymentPeriods(scheduleModel, interestRateChangeSubmittedOnDate, repaymentPeriodsToAdd, + alreadyProcessedTransactions); final Loan loan = installments.getFirst().getLoan(); int nextInstallmentNumber = installments.stream().mapToInt(LoanRepaymentScheduleInstallment::getInstallmentNumber).max().orElse(0) @@ -419,6 +423,7 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep } } processInterestRateChangeOnInstallments(scheduleModel, interestRateChangeSubmittedOnDate, installments); + reprocessInstallments(installments); } private void handleChangeInterestRate(final List<LoanRepaymentScheduleInstallment> installments, @@ -3219,7 +3224,7 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep }).map(LoanTermVariations::toData).collect(Collectors.toCollection(ArrayList::new)); for (LoanTermVariationsData termVariationsData : loanTermVariationsToReprocess) { - processLoanTermVariation(installments, termVariationsData, ctx.getModel()); + processLoanTermVariation(termVariationsData, ctx); } } } @@ -3273,7 +3278,7 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep installments.stream().sorted(LoanRepaymentScheduleInstallment::compareToByFromDueDate).forEachOrdered(i -> { i.updateInstallmentNumber(counter.getAndIncrement()); final LocalDate prev = previousDueDate.get(); - if (prev != null && (i.isAdditional() || i.isReAged())) { + if (prev != null && !i.getFromDate().isEqual(prev) && !i.isDownPayment()) { i.updateFromDate(prev); } previousDueDate.set(i.getDueDate()); diff --git a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/EMICalculator.java b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/EMICalculator.java index 9fcc3e498a..ab49130141 100644 --- a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/EMICalculator.java +++ b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/EMICalculator.java @@ -27,6 +27,7 @@ import java.util.Optional; import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency; import org.apache.fineract.organisation.monetary.domain.Money; import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment; +import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction; 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.LoanScheduleModelRepaymentPeriod; @@ -81,7 +82,7 @@ public interface EMICalculator { BigDecimal newInterestRate); void addRepaymentPeriods(ProgressiveLoanInterestScheduleModel scheduleModel, LocalDate submittedOnDate, - int numberOfRepaymentPeriodsToAdd); + int numberOfRepaymentPeriodsToAdd, List<LoanTransaction> alreadyProcessedTransactions); /** * This method applies outstanding balance correction on the interest model. Negative amount decreases the diff --git a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/ProgressiveEMICalculator.java b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/ProgressiveEMICalculator.java index ecd33aab20..55faa01d8a 100644 --- a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/ProgressiveEMICalculator.java +++ b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/ProgressiveEMICalculator.java @@ -46,6 +46,7 @@ import org.apache.fineract.portfolio.common.domain.DaysInYearCustomStrategyType; import org.apache.fineract.portfolio.common.domain.DaysInYearType; import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType; import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment; +import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction; import org.apache.fineract.portfolio.loanaccount.domain.reaging.LoanReAgeInterestHandlingType; import org.apache.fineract.portfolio.loanaccount.domain.reaging.LoanReAgeParameter; import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanApplicationTerms; @@ -185,18 +186,24 @@ public final class ProgressiveEMICalculator implements EMICalculator { @Override public void addRepaymentPeriods(final ProgressiveLoanInterestScheduleModel scheduleModel, final LocalDate submittedOnDate, - final int numberOfRepaymentPeriodsToAdd) { + final int numberOfRepaymentPeriodsToAdd, final List<LoanTransaction> alreadyProcessedTransactions) { addRepaymentPeriods(scheduleModel, - EmiChangeOperation.addRepaymentPeriods(submittedOnDate, scheduleModel.zero(), numberOfRepaymentPeriodsToAdd)); + EmiChangeOperation.addRepaymentPeriods(submittedOnDate, scheduleModel.zero(), numberOfRepaymentPeriodsToAdd), + alreadyProcessedTransactions); } - public void addRepaymentPeriods(final ProgressiveLoanInterestScheduleModel scheduleModel, final EmiChangeOperation operation) { - LocalDate disbursementDate = scheduleModel.getStartDate(); - int repaymentPeriodCount = scheduleModel.repaymentPeriods().size(); + private void addRepaymentPeriods(final ProgressiveLoanInterestScheduleModel scheduleModel, final EmiChangeOperation operation, + final List<LoanTransaction> alreadyProcessedTransactions) { + final Optional<LoanReAgeParameter> reAgeTransactionParameter = alreadyProcessedTransactions.stream() + .filter(t -> t.isReAge() && !t.isReversed()).findFirst().map(LoanTransaction::getLoanReAgeParameter); + final LocalDate seedDate = reAgeTransactionParameter.map(LoanReAgeParameter::getStartDate).orElse(scheduleModel.getStartDate()); + final int repaymentPeriodCount = reAgeTransactionParameter.map(param -> param.getNumberOfInstallments() - 1) + .orElse(scheduleModel.repaymentPeriods().size()); + final LocalDate interestRateChangeEffectiveDate = operation.getSubmittedOnDate().minusDays(1); - List<LocalDateInterval> periods2 = generateAdditionalRepaymentPeriodDueDates(scheduleModel, operation.getPeriodsToAdd(), - repaymentPeriodCount, scheduleModel.resolveRepaymentPEriodLengthGeneratorFunction(disbursementDate)); + final List<LocalDateInterval> periods2 = generateAdditionalRepaymentPeriodDueDates(scheduleModel, operation.getPeriodsToAdd(), + repaymentPeriodCount, scheduleModel.resolveRepaymentPeriodLengthGeneratorFunction(seedDate)); updateModel(scheduleModel, periods2, LocalDateInterval::startDate, LocalDateInterval::endDate); scheduleModel diff --git a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/data/ProgressiveLoanInterestScheduleModel.java b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/data/ProgressiveLoanInterestScheduleModel.java index c5fd1f0c01..0af304fc0e 100644 --- a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/data/ProgressiveLoanInterestScheduleModel.java +++ b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/data/ProgressiveLoanInterestScheduleModel.java @@ -420,7 +420,7 @@ public class ProgressiveLoanInterestScheduleModel { return this.modifiers.get(COPY); } - public Function<Long, LocalDate> resolveRepaymentPEriodLengthGeneratorFunction(LocalDate instance) { + public Function<Long, LocalDate> resolveRepaymentPeriodLengthGeneratorFunction(final LocalDate instance) { return switch (loanProductRelatedDetail.getRepaymentPeriodFrequencyType()) { case MONTHS -> instance::plusMonths; case WEEKS -> instance::plusWeeks; @@ -429,7 +429,4 @@ public class ProgressiveLoanInterestScheduleModel { }; } - public boolean isInterestRecalculationIsAllowed() { - return modifiers.get(INTEREST_RECALCULATION_ENABLED); - } } diff --git a/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanproduct/calc/ProgressiveEMICalculatorTest.java b/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanproduct/calc/ProgressiveEMICalculatorTest.java index 819eb52b1f..c67c5a8bd0 100644 --- a/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanproduct/calc/ProgressiveEMICalculatorTest.java +++ b/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanproduct/calc/ProgressiveEMICalculatorTest.java @@ -4049,14 +4049,14 @@ class ProgressiveEMICalculatorTest { checkPeriod(interestSchedule, 2, 340.03, 3.37, 336.66, 0.00, false); // // add extra repayment period 1 - emiCalculator.addRepaymentPeriods(interestSchedule, LocalDate.of(2024, 7, 2), 1); + emiCalculator.addRepaymentPeriods(interestSchedule, LocalDate.of(2024, 7, 2), 1, List.of()); checkPeriod(interestSchedule, 0, 340.02, 10.00, 330.02, 669.98, false); // checkPeriod(interestSchedule, 1, 227.81, 6.70, 221.11, 448.87, false); // checkPeriod(interestSchedule, 2, 227.81, 4.49, 223.32, 225.55, false); // checkPeriod(interestSchedule, 3, 227.81, 2.26, 225.55, 0.00, false); // - emiCalculator.addRepaymentPeriods(interestSchedule, LocalDate.of(2024, 8, 2), 2); + emiCalculator.addRepaymentPeriods(interestSchedule, LocalDate.of(2024, 8, 2), 2, List.of()); checkPeriod(interestSchedule, 0, 340.02, 10.00, 330.02, 669.98, false); // checkPeriod(interestSchedule, 1, 227.81, 6.70, 221.11, 448.87, false); // @@ -4088,14 +4088,14 @@ class ProgressiveEMICalculatorTest { checkPeriod(interestSchedule, 2, 343.34, 10.00, 333.34, 0.00, false); // // add extra repayment period 1 - emiCalculator.addRepaymentPeriods(interestSchedule, LocalDate.of(2024, 7, 2), 1); + emiCalculator.addRepaymentPeriods(interestSchedule, LocalDate.of(2024, 7, 2), 1, List.of()); checkPeriod(interestSchedule, 0, 343.33, 10.00, 333.33, 666.67, false); // checkPeriod(interestSchedule, 1, 232.22, 10.00, 222.22, 444.45, false); // checkPeriod(interestSchedule, 2, 232.22, 10.00, 222.22, 222.23, false); // checkPeriod(interestSchedule, 3, 232.23, 10.00, 222.23, 0.00, false); // - emiCalculator.addRepaymentPeriods(interestSchedule, LocalDate.of(2024, 8, 2), 2); + emiCalculator.addRepaymentPeriods(interestSchedule, LocalDate.of(2024, 8, 2), 2, List.of()); checkPeriod(interestSchedule, 0, 343.33, 10.00, 333.33, 666.67, false); // checkPeriod(interestSchedule, 1, 232.22, 10.00, 222.22, 444.45, false); // @@ -4140,7 +4140,7 @@ class ProgressiveEMICalculatorTest { checkPeriod(interestSchedule, 3, 256.29, 0.00, 256.29, 0.00, true); // // add extra repayment period 1 - emiCalculator.addRepaymentPeriods(interestSchedule, LocalDate.of(2024, 6, 15), 1); + emiCalculator.addRepaymentPeriods(interestSchedule, LocalDate.of(2024, 6, 15), 1, List.of()); // verify 1st and 4th installments are not modified, additional principal paid are substract from last // period @@ -4150,7 +4150,7 @@ class ProgressiveEMICalculatorTest { checkPeriod(interestSchedule, 3, 256.29, 0.00, 256.29, 88.00, true); // checkPeriod(interestSchedule, 4, 89.76, 1.76, 88.00, 0.00, false); // - emiCalculator.addRepaymentPeriods(interestSchedule, LocalDate.of(2024, 6, 15), 2); + emiCalculator.addRepaymentPeriods(interestSchedule, LocalDate.of(2024, 6, 15), 2, List.of()); // verify 1st and 4th installments are not modified, additional principal paid are substract from last // periods @@ -4210,7 +4210,7 @@ class ProgressiveEMICalculatorTest { checkPeriod(interestSchedule, 3, 260.00, 10.00, 250.00, 0.00, true); // // add extra repayment period 1 - emiCalculator.addRepaymentPeriods(interestSchedule, LocalDate.of(2024, 6, 15), 1); + emiCalculator.addRepaymentPeriods(interestSchedule, LocalDate.of(2024, 6, 15), 1, List.of()); // verify 1st and 4th installments are not modified, additional principal paid are substract from last // period @@ -4221,7 +4221,7 @@ class ProgressiveEMICalculatorTest { checkPeriod(interestSchedule, 4, 110.00, 10.00, 100.00, 0.00, false); // // add extra repayment period 2 - emiCalculator.addRepaymentPeriods(interestSchedule, LocalDate.of(2024, 6, 15), 2); + emiCalculator.addRepaymentPeriods(interestSchedule, LocalDate.of(2024, 6, 15), 2, List.of()); // verify 1st and 4th installments are not modified, additional principal paid are substract from last // periods
