From fbe7ae9e517934cc68f56b0c422718b91d06e952 Mon Sep 17 00:00:00 2001 From: Oleksii Novikov Date: Wed, 19 Feb 2025 11:18:03 +0200 Subject: [PATCH] FINERACT-2148: Accrual handling in case of backdated Charged-off transaction --- .../resources/features/LoanChargeOff.feature | 91 +++++++++++++++++++ ...WritePlatformServiceJpaRepositoryImpl.java | 10 ++ 2 files changed, 101 insertions(+) diff --git a/fineract-e2e-tests-runner/src/test/resources/features/LoanChargeOff.feature b/fineract-e2e-tests-runner/src/test/resources/features/LoanChargeOff.feature index 9e0a9296cb9..c1aedf9a8b6 100644 --- a/fineract-e2e-tests-runner/src/test/resources/features/LoanChargeOff.feature +++ b/fineract-e2e-tests-runner/src/test/resources/features/LoanChargeOff.feature @@ -6273,3 +6273,94 @@ Feature: Charge-off | 15 February 2024 | Waive loan charges | 10.0 | 0.0 | 0.0 | 0.0 | 0.0 | 83.59 | false | false | | 15 February 2024 | Charge-off | 88.81 | 83.59 | 0.22 | 5.0 | 0.0 | 0.0 | false | true | + Scenario: Backdate charge-off reverse accruals with isInterestRecognitionOnDisbursementDate = true + When Admin sets the business date to "1 January 2024" + 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_RECOGNITION_DISBURSEMENT_DAILY_EMI_360_30_ACCRUAL_ACTIVITY | 01 January 2024 | 1000 | 26 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 4 | MONTHS | 1 | MONTHS | 4 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION | + Then Loan Repayment schedule has 4 periods, with the following data for periods: + | Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding | + | | | 01 January 2024 | | 1000.0 | | | 0.0 | | 0.0 | | | | 0.0 | + | 1 | 31 | 01 February 2024 | | 757.98 | 242.02 | 21.67 | 0.0 | 0.0 | 263.69 | 0.0 | 0.0 | 0.0 | 263.69 | + | 2 | 29 | 01 March 2024 | | 510.71 | 247.27 | 16.42 | 0.0 | 0.0 | 263.69 | 0.0 | 0.0 | 0.0 | 263.69 | + | 3 | 31 | 01 April 2024 | | 258.09 | 252.62 | 11.07 | 0.0 | 0.0 | 263.69 | 0.0 | 0.0 | 0.0 | 263.69 | + | 4 | 30 | 01 May 2024 | | 0.0 | 258.09 | 5.59 | 0.0 | 0.0 | 263.68 | 0.0 | 0.0 | 0.0 | 263.68 | + Then Loan Repayment schedule has the following data in Total row: + | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding | + | 1000 | 54.75 | 0 | 0 | 1054.75 | 0 | 0 | 0 | 1054.75 | + And Admin successfully approves the loan on "1 January 2024" with "1000" amount and expected disbursement date on "1 January 2024" + And Admin successfully disburse the loan on "1 January 2024" with "1000" EUR transaction amount + And Admin runs inline COB job for Loan + When Admin sets the business date to "15 January 2024" + And Customer makes "AUTOPAY" repayment on "15 January 2024" with 263.69 EUR transaction amount + When Admin sets the business date to "20 January 2024" + Then Admin runs inline COB job for Loan + And Admin does charge-off the loan on "17 January 2024" + 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 | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false | false | + | 01 January 2024 | Accrual | 0.7 | 0.0 | 0.7 | 0.0 | 0.0 | 0.0 | false | false | + | 02 January 2024 | Accrual | 0.7 | 0.0 | 0.7 | 0.0 | 0.0 | 0.0 | false | false | + | 03 January 2024 | Accrual | 0.7 | 0.0 | 0.7 | 0.0 | 0.0 | 0.0 | false | false | + | 04 January 2024 | Accrual | 0.7 | 0.0 | 0.7 | 0.0 | 0.0 | 0.0 | false | false | + | 05 January 2024 | Accrual | 0.69 | 0.0 | 0.69 | 0.0 | 0.0 | 0.0 | false | false | + | 06 January 2024 | Accrual | 0.7 | 0.0 | 0.7 | 0.0 | 0.0 | 0.0 | false | false | + | 07 January 2024 | Accrual | 0.7 | 0.0 | 0.7 | 0.0 | 0.0 | 0.0 | false | false | + | 08 January 2024 | Accrual | 0.7 | 0.0 | 0.7 | 0.0 | 0.0 | 0.0 | false | false | + | 09 January 2024 | Accrual | 0.7 | 0.0 | 0.7 | 0.0 | 0.0 | 0.0 | false | false | + | 10 January 2024 | Accrual | 0.7 | 0.0 | 0.7 | 0.0 | 0.0 | 0.0 | false | false | + | 11 January 2024 | Accrual | 0.7 | 0.0 | 0.7 | 0.0 | 0.0 | 0.0 | false | false | + | 12 January 2024 | Accrual | 0.7 | 0.0 | 0.7 | 0.0 | 0.0 | 0.0 | false | false | + | 13 January 2024 | Accrual | 0.7 | 0.0 | 0.7 | 0.0 | 0.0 | 0.0 | false | false | + | 14 January 2024 | Accrual | 0.69 | 0.0 | 0.69 | 0.0 | 0.0 | 0.0 | false | false | + | 15 January 2024 | Repayment | 263.69 | 253.91 | 9.78 | 0.0 | 0.0 | 746.09 | false | false | + | 15 January 2024 | Accrual | 0.52 | 0.0 | 0.52 | 0.0 | 0.0 | 0.0 | false | false | + | 16 January 2024 | Accrual | 0.52 | 0.0 | 0.52 | 0.0 | 0.0 | 0.0 | false | false | + | 17 January 2024 | Charge-off | 787.63 | 746.09 | 41.54 | 0.0 | 0.0 | 0.0 | false | false | + + Scenario: Backdate charge-off reverse accruals with isInterestRecognitionOnDisbursementDate = false + When Admin sets the business date to "1 January 2024" + 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_360_30_INTEREST_RECALCULATION_DAILY_TILL_PRECLOSE | 01 January 2024 | 1000 | 26 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 4 | MONTHS | 1 | MONTHS | 4 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION | + Then Loan Repayment schedule has 4 periods, with the following data for periods: + | Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding | + | | | 01 January 2024 | | 1000.0 | | | 0.0 | | 0.0 | | | | 0.0 | + | 1 | 31 | 01 February 2024 | | 757.98 | 242.02 | 21.67 | 0.0 | 0.0 | 263.69 | 0.0 | 0.0 | 0.0 | 263.69 | + | 2 | 29 | 01 March 2024 | | 510.71 | 247.27 | 16.42 | 0.0 | 0.0 | 263.69 | 0.0 | 0.0 | 0.0 | 263.69 | + | 3 | 31 | 01 April 2024 | | 258.09 | 252.62 | 11.07 | 0.0 | 0.0 | 263.69 | 0.0 | 0.0 | 0.0 | 263.69 | + | 4 | 30 | 01 May 2024 | | 0.0 | 258.09 | 5.59 | 0.0 | 0.0 | 263.68 | 0.0 | 0.0 | 0.0 | 263.68 | + Then Loan Repayment schedule has the following data in Total row: + | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding | + | 1000 | 54.75 | 0 | 0 | 1054.75 | 0 | 0 | 0 | 1054.75 | + And Admin successfully approves the loan on "1 January 2024" with "1000" amount and expected disbursement date on "1 January 2024" + And Admin successfully disburse the loan on "1 January 2024" with "1000" EUR transaction amount + And Admin runs inline COB job for Loan + When Admin sets the business date to "15 January 2024" + And Customer makes "AUTOPAY" repayment on "15 January 2024" with 263.69 EUR transaction amount + When Admin sets the business date to "20 January 2024" + Then Admin runs inline COB job for Loan + And Admin does charge-off the loan on "17 January 2024" + 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 | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false | false | + | 02 January 2024 | Accrual | 0.7 | 0.0 | 0.7 | 0.0 | 0.0 | 0.0 | false | false | + | 03 January 2024 | Accrual | 0.7 | 0.0 | 0.7 | 0.0 | 0.0 | 0.0 | false | false | + | 04 January 2024 | Accrual | 0.7 | 0.0 | 0.7 | 0.0 | 0.0 | 0.0 | false | false | + | 05 January 2024 | Accrual | 0.7 | 0.0 | 0.7 | 0.0 | 0.0 | 0.0 | false | false | + | 06 January 2024 | Accrual | 0.69 | 0.0 | 0.69 | 0.0 | 0.0 | 0.0 | false | false | + | 07 January 2024 | Accrual | 0.7 | 0.0 | 0.7 | 0.0 | 0.0 | 0.0 | false | false | + | 08 January 2024 | Accrual | 0.7 | 0.0 | 0.7 | 0.0 | 0.0 | 0.0 | false | false | + | 09 January 2024 | Accrual | 0.7 | 0.0 | 0.7 | 0.0 | 0.0 | 0.0 | false | false | + | 10 January 2024 | Accrual | 0.7 | 0.0 | 0.7 | 0.0 | 0.0 | 0.0 | false | false | + | 11 January 2024 | Accrual | 0.7 | 0.0 | 0.7 | 0.0 | 0.0 | 0.0 | false | false | + | 12 January 2024 | Accrual | 0.7 | 0.0 | 0.7 | 0.0 | 0.0 | 0.0 | false | false | + | 13 January 2024 | Accrual | 0.7 | 0.0 | 0.7 | 0.0 | 0.0 | 0.0 | false | false | + | 14 January 2024 | Accrual | 0.7 | 0.0 | 0.7 | 0.0 | 0.0 | 0.0 | false | false | + | 15 January 2024 | Repayment | 263.69 | 253.91 | 9.78 | 0.0 | 0.0 | 746.09 | false | false | + | 15 January 2024 | Accrual | 0.69 | 0.0 | 0.69 | 0.0 | 0.0 | 0.0 | false | false | + | 16 January 2024 | Accrual | 0.52 | 0.0 | 0.52 | 0.0 | 0.0 | 0.0 | false | false | + | 17 January 2024 | Accrual | 0.52 | 0.0 | 0.52 | 0.0 | 0.0 | 0.0 | false | false | + | 17 January 2024 | Charge-off | 787.63 | 746.09 | 41.54 | 0.0 | 0.0 | 0.0 | false | false | diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java index cf3a0f9eb68..6b2f6e77291 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java @@ -3119,6 +3119,16 @@ public CommandProcessingResult chargeOff(JsonCommand command) { this.noteRepository.save(note); } + loan.getLoanTransactions().stream().filter(LoanTransaction::isAccrual) + .filter(transaction -> loan.getLoanProductRelatedDetail().isInterestRecognitionOnDisbursementDate() + ? !DateUtils.isBefore(transaction.getTransactionDate(), transactionDate) + : DateUtils.isAfter(transaction.getTransactionDate(), transactionDate)) + .forEach(transaction -> { + transaction.reverse(); + final LoanAdjustTransactionBusinessEvent.Data data = new LoanAdjustTransactionBusinessEvent.Data(transaction); + businessEventNotifierService.notifyPostBusinessEvent(new LoanAdjustTransactionBusinessEvent(data)); + }); + postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds); businessEventNotifierService.notifyPostBusinessEvent(new LoanChargeOffPostBusinessEvent(chargeOffTransaction)); return new CommandProcessingResultBuilder() //