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 d82ffddeccf17c8042b3bf81156f140c7e697259 Author: adam.magyari <[email protected]> AuthorDate: Wed Jul 30 16:38:44 2025 +0200 FINERACT-2338: Allow backdated interest rate change on progressive loans --- .../test/resources/features/EMICalculation.feature | 58 -------- .../features/LoanInterestRateChange.feature | 155 +++++++++++++++++++++ ...gressiveLoanRescheduleRequestDataValidator.java | 22 +-- ...nRescheduleRequestWritePlatformServiceImpl.java | 10 ++ .../LoanRescheduleRequestTest.java | 17 +-- 5 files changed, 168 insertions(+), 94 deletions(-) diff --git a/fineract-e2e-tests-runner/src/test/resources/features/EMICalculation.feature b/fineract-e2e-tests-runner/src/test/resources/features/EMICalculation.feature index 61828b35ad..e50ec3ada9 100644 --- a/fineract-e2e-tests-runner/src/test/resources/features/EMICalculation.feature +++ b/fineract-e2e-tests-runner/src/test/resources/features/EMICalculation.feature @@ -1589,64 +1589,6 @@ Feature: EMI calculation and repayment schedule checks for interest bearing loan | 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 | - @TestRailId:C3217 - Scenario: Verify the Loan reschedule - Interest modification - UC3: Interest modification results an error when rescheduleFromDate equals business date - When Admin sets the business date to "01 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 | 01 January 2024 | 100 | 7 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 6 | MONTHS | 1 | MONTHS | 6 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION | - And Admin successfully approves the loan on "01 January 2024" with "100" amount and expected disbursement date on "01 January 2024" - When Admin successfully disburse the loan on "01 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.57 | 16.43 | 0.58 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | - | 2 | 29 | 01 March 2024 | | 67.05 | 16.52 | 0.49 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | - | 3 | 31 | 01 April 2024 | | 50.43 | 16.62 | 0.39 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | - | 4 | 30 | 01 May 2024 | | 33.71 | 16.72 | 0.29 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | - | 5 | 31 | 01 June 2024 | | 16.9 | 16.81 | 0.2 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | - | 6 | 30 | 01 July 2024 | | 0.0 | 16.9 | 0.1 | 0.0 | 0.0 | 17.0 | 0.0 | 0.0 | 0.0 | 17.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.05 | 0.0 | 0.0 | 102.05 | 0.0 | 0.0 | 0.0 | 102.05 | - Then Loan Transactions tab has the following data: - | Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed | - | 01 January 2024 | Disbursement | 100.0 | 0.0 | 0.0 | 0.0 | 0.0 | 100.0 | false | false | - When Admin sets the business date to "14 February 2024" - Then Loan reschedule with the following data results a 403 error and "LOAN_RESCHEDULE_DATE_NOT_IN_FUTURE" error message - | rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate | - | 14 February 2024 | 14 February 2024 | | 0 | 0 | 0 | 4 | - - @TestRailId:C3218 - Scenario: Verify the Loan reschedule - Interest modification - UC4: Interest modification results an error when rescheduleFromDate is earlier than business date - When Admin sets the business date to "01 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 | 01 January 2024 | 100 | 7 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 6 | MONTHS | 1 | MONTHS | 6 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION | - And Admin successfully approves the loan on "01 January 2024" with "100" amount and expected disbursement date on "01 January 2024" - When Admin successfully disburse the loan on "01 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.57 | 16.43 | 0.58 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | - | 2 | 29 | 01 March 2024 | | 67.05 | 16.52 | 0.49 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | - | 3 | 31 | 01 April 2024 | | 50.43 | 16.62 | 0.39 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | - | 4 | 30 | 01 May 2024 | | 33.71 | 16.72 | 0.29 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | - | 5 | 31 | 01 June 2024 | | 16.9 | 16.81 | 0.2 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | - | 6 | 30 | 01 July 2024 | | 0.0 | 16.9 | 0.1 | 0.0 | 0.0 | 17.0 | 0.0 | 0.0 | 0.0 | 17.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.05 | 0.0 | 0.0 | 102.05 | 0.0 | 0.0 | 0.0 | 102.05 | - Then Loan Transactions tab has the following data: - | Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed | - | 01 January 2024 | Disbursement | 100.0 | 0.0 | 0.0 | 0.0 | 0.0 | 100.0 | false | false | - When Admin sets the business date to "14 February 2024" - Then Loan reschedule with the following data results a 403 error and "LOAN_RESCHEDULE_DATE_NOT_IN_FUTURE" error message - | rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate | - | 13 February 2024 | 14 February 2024 | | 0 | 0 | 0 | 4 | - @TestRailId:C3219 Scenario: Verify Repayment schedule in case of 2nd disbursement (created on business date before 1st installment) is backdated to before 1st disbursement When Admin sets the business date to "01 January 2024" diff --git a/fineract-e2e-tests-runner/src/test/resources/features/LoanInterestRateChange.feature b/fineract-e2e-tests-runner/src/test/resources/features/LoanInterestRateChange.feature new file mode 100644 index 0000000000..d19807579d --- /dev/null +++ b/fineract-e2e-tests-runner/src/test/resources/features/LoanInterestRateChange.feature @@ -0,0 +1,155 @@ +@InterestRateChangeFeature +Feature: Loan interest rate change on repayment schedule + + Scenario: Verify Interest rate change - backdated, modification on installment due date - UC1 + When Admin sets the business date to "01 January 2024" + When Admin creates a client with random data + When Admin set "LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_PRECLOSE" loan product "DEFAULT" transaction type to "NEXT_INSTALLMENT" future installment allocation rule + 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_INTEREST_RECALCULATION_DAILY_TILL_PRECLOSE | 01 January 2024 | 100 | 7 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 6 | MONTHS | 1 | MONTHS | 6 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION | + And Admin successfully approves the loan on "01 January 2024" with "100" amount and expected disbursement date on "01 January 2024" + When Admin successfully disburse the loan on "01 January 2024" with "100" EUR transaction amount + When Admin runs inline COB job for Loan + 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.57 | 16.43 | 0.58 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | + | 2 | 29 | 01 March 2024 | | 67.05 | 16.52 | 0.49 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | + | 3 | 31 | 01 April 2024 | | 50.43 | 16.62 | 0.39 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | + | 4 | 30 | 01 May 2024 | | 33.71 | 16.72 | 0.29 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | + | 5 | 31 | 01 June 2024 | | 16.9 | 16.81 | 0.2 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | + | 6 | 30 | 01 July 2024 | | 0.0 | 16.9 | 0.1 | 0.0 | 0.0 | 17.0 | 0.0 | 0.0 | 0.0 | 17.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.05 | 0.0 | 0.0 | 102.05 | 0.0 | 0.0 | 0.0 | 102.05 | + Then Loan Transactions tab has the following data: + | Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed | + | 01 January 2024 | Disbursement | 100.0 | 0.0 | 0.0 | 0.0 | 0.0 | 100.0 | false | false | + When Admin sets the business date to "01 April 2024" + And Customer makes "AUTOPAY" repayment on "01 February 2024" with 17.01 EUR transaction amount + And Customer makes "AUTOPAY" repayment on "01 March 2024" with 17.01 EUR transaction amount + When Admin creates and approves Loan reschedule with the following data: + | rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate | + | 02 February 2024 | 02 February 2024 | | | | | 4 | + 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.57 | 16.43 | 0.58 | 0.0 | 0.0 | 17.01 | 17.01 | 0.0 | 0.0 | 0.0 | + | 2 | 29 | 01 March 2024 | 01 March 2024 | 66.97 | 16.6 | 0.28 | 0.0 | 0.0 | 16.88 | 16.88 | 0.0 | 0.0 | 0.0 | + | 3 | 31 | 01 April 2024 | | 50.31 | 16.66 | 0.22 | 0.0 | 0.0 | 16.88 | 0.13 | 0.13 | 0.0 | 16.75 | + | 4 | 30 | 01 May 2024 | | 33.6 | 16.71 | 0.17 | 0.0 | 0.0 | 16.88 | 0.0 | 0.0 | 0.0 | 16.88 | + | 5 | 31 | 01 June 2024 | | 16.83 | 16.77 | 0.11 | 0.0 | 0.0 | 16.88 | 0.0 | 0.0 | 0.0 | 16.88 | + | 6 | 30 | 01 July 2024 | | 0.0 | 16.83 | 0.06 | 0.0 | 0.0 | 16.89 | 0.0 | 0.0 | 0.0 | 16.89 | + 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.42 | 0.0 | 0.0 | 101.42 | 34.02 | 0.13 | 0.0 | 67.4 | + Then Loan Transactions tab has the following data: + | Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed | + | 01 January 2024 | Disbursement | 100.0 | 0.0 | 0.0 | 0.0 | 0.0 | 100.0 | false | false | + | 01 February 2024 | Repayment | 17.01 | 16.43 | 0.58 | 0.0 | 0.0 | 83.57 | false | false | + | 01 March 2024 | Repayment | 17.01 | 16.73 | 0.28 | 0.0 | 0.0 | 66.84 | false | true | + When Loan Pay-off is made on "01 April 2024" + Then Loan's all installments have obligations met + + Scenario: Verify Interest rate change - backdated, modification in middle of installment - UC2 + When Admin sets the business date to "01 January 2024" + When Admin creates a client with random data + When Admin set "LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_PRECLOSE" loan product "DEFAULT" transaction type to "NEXT_INSTALLMENT" future installment allocation rule + 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_INTEREST_RECALCULATION_DAILY_TILL_PRECLOSE | 01 January 2024 | 100 | 7 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 6 | MONTHS | 1 | MONTHS | 6 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION | + And Admin successfully approves the loan on "01 January 2024" with "100" amount and expected disbursement date on "01 January 2024" + When Admin successfully disburse the loan on "01 January 2024" with "100" EUR transaction amount + When Admin runs inline COB job for Loan + 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.57 | 16.43 | 0.58 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | + | 2 | 29 | 01 March 2024 | | 67.05 | 16.52 | 0.49 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | + | 3 | 31 | 01 April 2024 | | 50.43 | 16.62 | 0.39 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | + | 4 | 30 | 01 May 2024 | | 33.71 | 16.72 | 0.29 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | + | 5 | 31 | 01 June 2024 | | 16.9 | 16.81 | 0.2 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | + | 6 | 30 | 01 July 2024 | | 0.0 | 16.9 | 0.1 | 0.0 | 0.0 | 17.0 | 0.0 | 0.0 | 0.0 | 17.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.05 | 0.0 | 0.0 | 102.05 | 0.0 | 0.0 | 0.0 | 102.05 | + Then Loan Transactions tab has the following data: + | Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed | + | 01 January 2024 | Disbursement | 100.0 | 0.0 | 0.0 | 0.0 | 0.0 | 100.0 | false | false | + When Admin sets the business date to "01 April 2024" + And Customer makes "AUTOPAY" repayment on "01 February 2024" with 17.01 EUR transaction amount + And Customer makes "AUTOPAY" repayment on "01 March 2024" with 17.01 EUR transaction amount + When Admin creates and approves Loan reschedule with the following data: + | rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate | + | 16 February 2024 | 16 February 2024 | | | | | 4 | + 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.57 | 16.43 | 0.58 | 0.0 | 0.0 | 17.01 | 17.01 | 0.0 | 0.0 | 0.0 | + | 2 | 29 | 01 March 2024 | 01 March 2024 | 67.05 | 16.52 | 0.38 | 0.0 | 0.0 | 16.9 | 16.9 | 0.0 | 0.0 | 0.0 | + | 3 | 31 | 01 April 2024 | | 50.37 | 16.68 | 0.22 | 0.0 | 0.0 | 16.9 | 0.11 | 0.11 | 0.0 | 16.79 | + | 4 | 30 | 01 May 2024 | | 33.64 | 16.73 | 0.17 | 0.0 | 0.0 | 16.9 | 0.0 | 0.0 | 0.0 | 16.9 | + | 5 | 31 | 01 June 2024 | | 16.85 | 16.79 | 0.11 | 0.0 | 0.0 | 16.9 | 0.0 | 0.0 | 0.0 | 16.9 | + | 6 | 30 | 01 July 2024 | | 0.0 | 16.85 | 0.06 | 0.0 | 0.0 | 16.91 | 0.0 | 0.0 | 0.0 | 16.91 | + 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.52 | 0.0 | 0.0 | 101.52 | 34.02 | 0.11 | 0.0 | 67.5 | + Then Loan Transactions tab has the following data: + | Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed | + | 01 January 2024 | Disbursement | 100.0 | 0.0 | 0.0 | 0.0 | 0.0 | 100.0 | false | false | + | 01 February 2024 | Repayment | 17.01 | 16.43 | 0.58 | 0.0 | 0.0 | 83.57 | false | false | + | 01 March 2024 | Repayment | 17.01 | 16.63 | 0.38 | 0.0 | 0.0 | 66.94 | false | true | + When Loan Pay-off is made on "01 April 2024" + Then Loan's all installments have obligations met + + Scenario: Verify Interest rate change - backdated, modification in middle of installment, no reverse-replay - UC3 + When Admin sets the business date to "01 January 2024" + When Admin creates a client with random data + When Admin set "LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_PRECLOSE" loan product "DEFAULT" transaction type to "NEXT_INSTALLMENT" future installment allocation rule + 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_INTEREST_RECALCULATION_DAILY_TILL_PRECLOSE | 01 January 2024 | 100 | 7 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 6 | MONTHS | 1 | MONTHS | 6 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION | + And Admin successfully approves the loan on "01 January 2024" with "100" amount and expected disbursement date on "01 January 2024" + When Admin successfully disburse the loan on "01 January 2024" with "100" EUR transaction amount + When Admin runs inline COB job for Loan + 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.57 | 16.43 | 0.58 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | + | 2 | 29 | 01 March 2024 | | 67.05 | 16.52 | 0.49 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | + | 3 | 31 | 01 April 2024 | | 50.43 | 16.62 | 0.39 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | + | 4 | 30 | 01 May 2024 | | 33.71 | 16.72 | 0.29 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | + | 5 | 31 | 01 June 2024 | | 16.9 | 16.81 | 0.2 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | + | 6 | 30 | 01 July 2024 | | 0.0 | 16.9 | 0.1 | 0.0 | 0.0 | 17.0 | 0.0 | 0.0 | 0.0 | 17.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.05 | 0.0 | 0.0 | 102.05 | 0.0 | 0.0 | 0.0 | 102.05 | + Then Loan Transactions tab has the following data: + | Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed | + | 01 January 2024 | Disbursement | 100.0 | 0.0 | 0.0 | 0.0 | 0.0 | 100.0 | false | false | + When Admin sets the business date to "01 April 2024" + And Customer makes "AUTOPAY" repayment on "01 February 2024" with 17.01 EUR transaction amount + And Customer makes "AUTOPAY" repayment on "01 March 2024" with 17.01 EUR transaction amount + When Admin creates and approves Loan reschedule with the following data: + | rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate | + | 11 March 2024 | 11 March 2024 | | | | | 4 | + 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.57 | 16.43 | 0.58 | 0.0 | 0.0 | 17.01 | 17.01 | 0.0 | 0.0 | 0.0 | + | 2 | 29 | 01 March 2024 | 01 March 2024 | 67.05 | 16.52 | 0.49 | 0.0 | 0.0 | 17.01 | 17.01 | 0.0 | 0.0 | 0.0 | + | 3 | 31 | 01 April 2024 | | 50.41 | 16.64 | 0.27 | 0.0 | 0.0 | 16.91 | 0.0 | 0.0 | 0.0 | 16.91 | + | 4 | 30 | 01 May 2024 | | 33.67 | 16.74 | 0.17 | 0.0 | 0.0 | 16.91 | 0.0 | 0.0 | 0.0 | 16.91 | + | 5 | 31 | 01 June 2024 | | 16.87 | 16.8 | 0.11 | 0.0 | 0.0 | 16.91 | 0.0 | 0.0 | 0.0 | 16.91 | + | 6 | 30 | 01 July 2024 | | 0.0 | 16.87 | 0.06 | 0.0 | 0.0 | 16.93 | 0.0 | 0.0 | 0.0 | 16.93 | + 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.68 | 0.0 | 0.0 | 101.68 | 34.02 | 0.0 | 0.0 | 67.66 | + Then Loan Transactions tab has the following data: + | Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed | + | 01 January 2024 | Disbursement | 100.0 | 0.0 | 0.0 | 0.0 | 0.0 | 100.0 | false | false | + | 01 February 2024 | Repayment | 17.01 | 16.43 | 0.58 | 0.0 | 0.0 | 83.57 | false | false | + | 01 March 2024 | Repayment | 17.01 | 16.52 | 0.49 | 0.0 | 0.0 | 67.05 | false | false | + When Loan Pay-off is made on "01 April 2024" + Then Loan's all installments have obligations met diff --git a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/data/ProgressiveLoanRescheduleRequestDataValidator.java b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/data/ProgressiveLoanRescheduleRequestDataValidator.java index a110056f96..ad5037b645 100644 --- a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/data/ProgressiveLoanRescheduleRequestDataValidator.java +++ b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/data/ProgressiveLoanRescheduleRequestDataValidator.java @@ -45,7 +45,6 @@ import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder; import org.apache.fineract.infrastructure.core.exception.GeneralPlatformDomainRuleException; import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException; import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper; -import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.portfolio.loanaccount.domain.Loan; import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment; import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus; @@ -89,18 +88,8 @@ public class ProgressiveLoanRescheduleRequestDataValidator implements LoanResche "Only one operation is supported at a time during Loan Rescheduling"); } - final LocalDate businessDate = DateUtils.getBusinessLocalDate(); - if (rescheduleFromDate != null) { - if (hasInterestRateChange && !rescheduleFromDate.isAfter(businessDate)) { - throw new GeneralPlatformDomainRuleException( - "loan.reschedule.interest.rate.change.reschedule.from.date.should.be.in.future", - String.format("Loan Reschedule From date (%s) for Loan: %s should be in the future.", rescheduleFromDate, - loan.getId()), - loan.getId(), rescheduleFromDate); - } - if (hasInterestRateChange) { - validateInterestRateChangeRescheduleFromDate(loan, rescheduleFromDate); - } + if (rescheduleFromDate != null && hasInterestRateChange) { + validateInterestRateChangeRescheduleFromDate(loan, rescheduleFromDate); } LoanRepaymentScheduleInstallment installment; @@ -159,13 +148,6 @@ public class ProgressiveLoanRescheduleRequestDataValidator implements LoanResche if (loanRescheduleRequest.getInterestRateFromInstallmentTermVariationIfExists() != null) { installment = loan.getRelatedRepaymentScheduleInstallment(rescheduleFromDate); - if (!rescheduleFromDate.isAfter(DateUtils.getBusinessLocalDate())) { - throw new GeneralPlatformDomainRuleException( - "loan.reschedule.interest.rate.change.reschedule.from.date.should.be.in.future", - String.format("Loan Reschedule From date (%s) for Loan: %s should be in the future.", rescheduleFromDate, - loan.getId()), - loan.getId(), rescheduleFromDate); - } } else { installment = loan.fetchLoanRepaymentScheduleInstallmentByDueDate(rescheduleFromDate); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java index ebc1cf86c6..e8cf532238 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java @@ -43,6 +43,7 @@ import org.apache.fineract.infrastructure.core.exception.ErrorHandler; import org.apache.fineract.infrastructure.core.exception.GeneralPlatformDomainRuleException; import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException; import org.apache.fineract.infrastructure.core.service.DateUtils; +import org.apache.fineract.infrastructure.event.business.domain.loan.LoanBalanceChangedBusinessEvent; import org.apache.fineract.infrastructure.event.business.domain.loan.LoanRescheduledDueAdjustScheduleBusinessEvent; import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService; import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; @@ -402,9 +403,15 @@ public class LoanRescheduleRequestWritePlatformServiceImpl implements LoanResche if (rescheduleFromDate == null) { rescheduleFromDate = loanRescheduleRequest.getRescheduleFromDate(); } + + boolean hasInterestRateChange = false; for (LoanRescheduleRequestToTermVariationMapping mapping : loanRescheduleRequest .getLoanRescheduleRequestToTermVariationMappings()) { mapping.getLoanTermVariations().updateIsActive(true); + LoanTermVariationType termType = mapping.getLoanTermVariations().getTermType(); + if (termType.isInterestRateVariation() || termType.isInterestRateFromInstallment()) { + hasInterestRateChange = true; + } } BigDecimal annualNominalInterestRate = null; List<LoanTermVariationsData> loanTermVariations = new ArrayList<>(); @@ -457,6 +464,9 @@ public class LoanRescheduleRequestWritePlatformServiceImpl implements LoanResche postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds); loanAccrualTransactionBusinessEventService.raiseBusinessEventForAccrualTransactions(loan, existingTransactionIds); + if (hasInterestRateChange) { + businessEventNotifierService.notifyPostBusinessEvent(new LoanBalanceChangedBusinessEvent(loan)); + } return new CommandProcessingResultBuilder().withCommandId(jsonCommand.commandId()).withEntityId(loanRescheduleRequestId) .withLoanId(loanRescheduleRequest.getLoan().getId()).with(changes).withClientId(loan.getClientId()) diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleRequestTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleRequestTest.java index ac3b3c306c..93da039e9c 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleRequestTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleRequestTest.java @@ -286,14 +286,6 @@ public class LoanRescheduleRequestTest extends BaseLoanIntegrationTest { new PostLoansLoanIdRequest().actualDisbursementDate("15 February 2023").dateFormat(DATETIME_PATTERN) .transactionAmount(BigDecimal.valueOf(500.00)).locale("en")); - exception = assertThrows(CallFailedRuntimeException.class, - () -> loanRescheduleRequestHelper - .createLoanRescheduleRequest(new PostCreateRescheduleLoansRequest().loanId(loanResponse.get().getLoanId()) - .dateFormat(DATETIME_PATTERN).locale("en").submittedOnDate("15 February 2023") - .newInterestRate(BigDecimal.ONE).rescheduleReasonId(1L).rescheduleFromDate("15 February 2023"))); - assertEquals(403, exception.getResponse().code()); - assertTrue(exception.getMessage().contains("loan.reschedule.interest.rate.change.reschedule.from.date.should.be.in.future")); - rescheduleResponse.set(loanRescheduleRequestHelper.createLoanRescheduleRequest(new PostCreateRescheduleLoansRequest() .loanId(loanResponse.get().getLoanId()).dateFormat(DATETIME_PATTERN).locale("en").submittedOnDate("15 February 2023") .newInterestRate(BigDecimal.ONE).rescheduleReasonId(1L).rescheduleFromDate("16 February 2023"))); @@ -310,13 +302,6 @@ public class LoanRescheduleRequestTest extends BaseLoanIntegrationTest { // Do not allow create interest rate change if a previous interest rate change got already approved for that // date runAt("16 February 2023", () -> { - CallFailedRuntimeException exception = assertThrows(CallFailedRuntimeException.class, - () -> loanRescheduleRequestHelper.approveLoanRescheduleRequest(rescheduleResponse.get().getResourceId(), - new PostUpdateRescheduleLoansRequest().approvedOnDate("16 February 2024").locale("en") - .dateFormat(DATETIME_PATTERN))); - assertEquals(403, exception.getResponse().code()); - assertTrue(exception.getMessage().contains("loan.reschedule.interest.rate.change.reschedule.from.date.should.be.in.future")); - PostCreateRescheduleLoansResponse rescheduleLoansResponse = loanRescheduleRequestHelper .createLoanRescheduleRequest(new PostCreateRescheduleLoansRequest().loanId(loanResponse.get().getLoanId()) .dateFormat(DATETIME_PATTERN).locale("en").submittedOnDate("17 February 2023").newInterestRate(BigDecimal.ONE) @@ -325,7 +310,7 @@ public class LoanRescheduleRequestTest extends BaseLoanIntegrationTest { loanRescheduleRequestHelper.approveLoanRescheduleRequest(rescheduleLoansResponse.getResourceId(), new PostUpdateRescheduleLoansRequest().approvedOnDate("17 February 2024").locale("en").dateFormat(DATETIME_PATTERN)); - exception = assertThrows(CallFailedRuntimeException.class, + CallFailedRuntimeException exception = assertThrows(CallFailedRuntimeException.class, () -> loanRescheduleRequestHelper .createLoanRescheduleRequest(new PostCreateRescheduleLoansRequest().loanId(rescheduleLoansResponse.getLoanId()) .dateFormat(DATETIME_PATTERN).locale("en").submittedOnDate("17 February 2023")
