From 46e1bd049211470e2e6493ef396e8462b4e07eeb Mon Sep 17 00:00:00 2001 From: "mark.vituska" Date: Mon, 14 Jul 2025 13:48:20 +0200 Subject: [PATCH] FINERACT-2181: Fix overdue balance updates in advanced payment schedule processing --- .../resources/features/EMICalculation.feature | 22 +++++++-------- ...edPaymentScheduleTransactionProcessor.java | 28 ++++++++++++++++--- 2 files changed, 35 insertions(+), 15 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 8ed1a8e9e..94f9652c2 100644 --- a/fineract-e2e-tests-runner/src/test/resources/features/EMICalculation.feature +++ b/fineract-e2e-tests-runner/src/test/resources/features/EMICalculation.feature @@ -2949,12 +2949,12 @@ Feature: EMI calculation and repayment schedule checks for interest bearing loan | 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 | | 67.05 | 16.52 | 0.49 | 0.0 | 0.0 | 17.01 | 10.0 | 0.0 | 10.0 | 7.01 | | 3 | 31 | 01 April 2024 | | 50.53 | 16.52 | 0.49 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | - | 4 | 30 | 01 May 2024 | | 33.91 | 16.62 | 0.39 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | - | 5 | 31 | 01 June 2024 | | 17.19 | 16.72 | 0.29 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | - | 6 | 30 | 01 July 2024 | | 0.0 | 17.19 | 0.2 | 0.0 | 0.0 | 17.39 | 0.0 | 0.0 | 0.0 | 17.39 | + | 4 | 30 | 01 May 2024 | | 33.81 | 16.72 | 0.29 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | + | 5 | 31 | 01 June 2024 | | 17.0 | 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 | 17.0 | 0.1 | 0.0 | 0.0 | 17.1 | 0.0 | 0.0 | 0.0 | 17.1 | 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.44 | 0.0 | 0.0 | 102.44 | 27.01 | 0.0 | 10.0 | 75.43 | + | 100.0 | 2.15 | 0.0 | 0.0 | 102.15 | 27.01 | 0.0 | 10.0 | 75.14 | 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 | @@ -2969,12 +2969,12 @@ Feature: EMI calculation and repayment schedule checks for interest bearing loan | 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 | | 67.05 | 16.52 | 0.49 | 0.0 | 0.0 | 17.01 | 10.0 | 0.0 | 10.0 | 7.01 | | 3 | 31 | 01 April 2024 | | 50.53 | 16.52 | 0.49 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | - | 4 | 30 | 01 May 2024 | | 33.95 | 16.58 | 0.43 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | - | 5 | 31 | 01 June 2024 | | 17.27 | 16.68 | 0.33 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | - | 6 | 30 | 01 July 2024 | | 0.0 | 17.27 | 0.24 | 0.0 | 0.0 | 17.51 | 0.0 | 0.0 | 0.0 | 17.51 | + | 4 | 30 | 01 May 2024 | | 33.81 | 16.72 | 0.29 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0 | 17.01 | + | 5 | 31 | 01 June 2024 | | 17.0 | 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 | 17.0 | 0.1 | 0.0 | 0.0 | 17.1 | 0.0 | 0.0 | 0.0 | 17.1 | 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.56 | 0.0 | 0.0 | 102.56 | 27.01 | 0.0 | 10.0 | 75.55 | + | 100.0 | 2.15 | 0.0 | 0.0 | 102.15 | 27.01 | 0.0 | 10.0 | 75.14 | 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 | @@ -7890,10 +7890,10 @@ Feature: EMI calculation and repayment schedule checks for interest bearing loan | 3 | 31 | 01 April 2025 | | 4661.9 | 1112.7 | 576.13 | 0.0 | 0.0 | 1688.83 | 0.0 | 0.0 | 0.0 | 1688.83 | | 4 | 30 | 01 May 2025 | | 3549.2 | 1112.7 | 576.13 | 0.0 | 0.0 | 1688.83 | 0.0 | 0.0 | 0.0 | 1688.83 | | 5 | 31 | 01 June 2025 | | 2436.5 | 1112.7 | 576.13 | 0.0 | 0.0 | 1688.83 | 0.0 | 0.0 | 0.0 | 1688.83 | - | 6 | 30 | 01 July 2025 | | 0.0 | 2436.5 | 896.66 | 0.0 | 0.0 | 3333.16 | 0.0 | 0.0 | 0.0 | 3333.16 | + | 6 | 30 | 01 July 2025 | | 0.0 | 2436.5 | 576.13 | 0.0 | 0.0 | 3012.63 | 0.0 | 0.0 | 0.0 | 3012.63 | And Loan Repayment schedule has the following data in Total row: | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding | - | 8000.0 | 3777.31 | 0.0 | 0.0 | 11777.31 | 0.05 | 0.0 | 0.04 | 11777.26 | + | 8000.0 | 3456.78 | 0.0 | 0.0 | 11456.78 | 0.05 | 0.0 | 0.04 | 11456.73 | @TestRailId:C3657 Scenario: Verify tranche interest bearing progressive loan that expects two tranches with repayment and undo last disbursement - UC1 @@ -9631,4 +9631,4 @@ Feature: EMI calculation and repayment schedule checks for interest bearing loan | Type | Account code | Account name | Debit | Credit | | ASSET | 112601 | Loans Receivable | | 906.25 | | ASSET | 112603 | Interest/Fee Receivable | | 16.87 | - | LIABILITY | 145023 | Suspense/Clearing account | 923.12 | | \ No newline at end of file + | LIABILITY | 145023 | Suspense/Clearing account | 923.12 | | 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 1802981c1..de0c98b5b 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 @@ -1570,10 +1570,8 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep } else { lastOverdueBalanceChange = currentDate; } - if (DateUtils.isBefore(ctx.getModel().lastOverdueBalanceChange(), toDate)) { - emiCalculator.addBalanceCorrection(ctx.getModel(), lastOverdueBalanceChange, aggregatedOverDuePrincipal.negated()); - ctx.getModel().lastOverdueBalanceChange(lastOverdueBalanceChange); - } + emiCalculator.addBalanceCorrection(ctx.getModel(), lastOverdueBalanceChange, aggregatedOverDuePrincipal.negated()); + ctx.getModel().lastOverdueBalanceChange(lastOverdueBalanceChange); } } @@ -1599,10 +1597,32 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep if (loanTransaction.isRepaymentLikeType() || loanTransaction.isInterestWaiver() || loanTransaction.isRecoveryRepayment()) { loanTransaction.resetDerivedComponents(); } + calculateUnrecognizedInterestForClosedPeriodByInterestRecalculationStrategy(loanTransaction, transactionCtx); + Money transactionAmountUnprocessed = loanTransaction.getAmount(transactionCtx.getCurrency()); processTransaction(loanTransaction, transactionCtx, transactionAmountUnprocessed); } + private void calculateUnrecognizedInterestForClosedPeriodByInterestRecalculationStrategy(LoanTransaction loanTransaction, + TransactionCtx transactionCtx) { + if (transactionCtx instanceof ProgressiveTransactionCtx progressiveTransactionCtx && progressiveTransactionCtx.isPrepayAttempt() + && loanTransaction.isRepaymentLikeType() && loanTransaction.getLoan().getLoanInterestRecalculationDetails() + .getPreCloseInterestCalculationStrategy().calculateTillRestFrequencyEnabled()) { + Optional oCurrentRepaymentPeriod = progressiveTransactionCtx.getModel().repaymentPeriods().stream() + .filter(rm -> DateUtils.isDateInRangeFromInclusiveToExclusive(rm.getFromDate(), rm.getDueDate(), + loanTransaction.getTransactionDate())) + .findFirst(); + if (oCurrentRepaymentPeriod.isPresent() && oCurrentRepaymentPeriod.get().isFullyPaid()) { + RepaymentPeriod currentRepaymentPeriod = oCurrentRepaymentPeriod.get(); + OutstandingDetails outstandingAmountsTillDate = emiCalculator + .getOutstandingAmountsTillDate(progressiveTransactionCtx.getModel(), currentRepaymentPeriod.getDueDate()); + if (outstandingAmountsTillDate.getOutstandingInterest().isGreaterThanZero()) { + currentRepaymentPeriod.setFutureUnrecognizedInterest(outstandingAmountsTillDate.getOutstandingInterest()); + } + } + } + } + private LoanTransactionToRepaymentScheduleMapping getTransactionMapping( List transactionMappings, LoanTransaction loanTransaction, LoanRepaymentScheduleInstallment currentInstallment, MonetaryCurrency currency) {