You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by ad...@apache.org on 2026/01/15 08:48:15 UTC

(fineract) 01/02: FINERACT-2354: Re-aging:- Accrual and Accrual Activity handling - Default Handling

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 fcf1fb61261bb3c54a751e16af3ce081e0300c77
Author: mariiaKraievska <ri...@gmail.com>
AuthorDate: Thu Dec 18 12:54:52 2025 +0200

    FINERACT-2354: Re-aging:- Accrual and Accrual Activity handling - Default Handling
---
 .../test/resources/features/LoanReAging.feature    | 24 +++---
 .../test/resources/features/LoanRepayment.feature  |  1 +
 .../portfolio/loanaccount/domain/Loan.java         |  4 +
 .../domain/ProgressiveLoanScheduleGenerator.java   |  9 ++-
 .../LoanAccrualActivityProcessingServiceImpl.java  | 88 ++++++++++++++++------
 .../service/LoanAccrualsProcessingServiceImpl.java |  8 +-
 6 files changed, 96 insertions(+), 38 deletions(-)

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 08811d80f2..1b429ea50f 100644
--- a/fineract-e2e-tests-runner/src/test/resources/features/LoanReAging.feature
+++ b/fineract-e2e-tests-runner/src/test/resources/features/LoanReAging.feature
@@ -4175,7 +4175,7 @@ Then Loan Repayment schedule has 4 periods, with the following data for periods:
       | 01 February 2024 | Chargeback       | 17.01  | 16.43     | 0.58     | 0.0  | 0.0       | 100.0        | false    | false    |
       | 15 March 2024    | Re-age           | 101.42 | 100.0     | 1.42     | 0.0  | 0.0       | 0.0          | false    | false    |
       | 15 March 2024    | Repayment        | 101.42 | 100.0     | 1.42     | 0.0  | 0.0       | 0.0          | false    | false    |
-      | 15 March 2024    | Accrual          | 0.58   | 0.0       | 0.58     | 0.0  | 0.0       | 0.0          | false    | false    |
+      | 15 March 2024    | Accrual          | 2.0    | 0.0       | 2.0      | 0.0  | 0.0       | 0.0          | false    | false    |
 
   @TestRailId:C4135 @AdvancedPaymentAllocation
   Scenario: Verify allowing Re-aging on interest bearing loan - Interest calculation: Default Behavior - Charge-back before re-aging and installment is partially paid - UC3.1
@@ -4274,7 +4274,7 @@ Then Loan Repayment schedule has 4 periods, with the following data for periods:
       | 01 March 2024    | Repayment        | 10.0   | 10.0      | 0.0      | 0.0  | 0.0       | 90.0         | false    | false    |
       | 15 March 2024    | Re-age           | 91.4   | 90.0      | 1.4      | 0.0  | 0.0       | 0.0          | false    | false    |
       | 15 March 2024    | Repayment        | 91.4   | 90.0      | 1.4      | 0.0  | 0.0       | 0.0          | false    | false    |
-      | 15 March 2024    | Accrual          | 0.58   | 0.0       | 0.58     | 0.0  | 0.0       | 0.0          | false    | false    |
+      | 15 March 2024    | Accrual          | 1.98   | 0.0       | 1.98     | 0.0  | 0.0       | 0.0          | false    | false    |
 
   @TestRailId:C4356 @AdvancedPaymentAllocation
   Scenario: Verify Re-aging on interest bearing loan - Interest calculation: Default Behavior - with NEXT_INSTALLMENT allocation rule, backdated re-aging on 1st installment after repay and chargeback on 1st due - UC3.2
@@ -4603,7 +4603,7 @@ Then Loan Repayment schedule has 4 periods, with the following data for periods:
       | 01 February 2024 | Accrual Activity | 0.58   | 0.0       | 0.58     | 0.0  | 0.0       | 0.0          | false    | false    |
       | 15 March 2024    | Re-age           | 76.22  | 75.58     | 0.64     | 0.0  | 0.0       | 0.0          | false    | false    |
       | 15 March 2024    | Repayment        | 76.22  | 75.58     | 0.64     | 0.0  | 0.0       | 0.0          | false    | false    |
-      | 15 March 2024    | Accrual          | 0.58   | 0.0       | 0.58     | 0.0  | 0.0       | 0.0          | false    | false    |
+      | 15 March 2024    | Accrual          | 1.22   | 0.0       | 1.22     | 0.0  | 0.0       | 0.0          | false    | false    |
       | 15 March 2024    | Accrual Activity | 0.64   | 0.0       | 0.64     | 0.0  | 0.0       | 0.0          | false    | false    |
     When Admin set "LP2_ADV_CUSTOM_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL" loan product "DEFAULT" transaction type to "NEXT_INSTALLMENT" future installment allocation rule
 
@@ -4827,7 +4827,7 @@ Then Loan Repayment schedule has 4 periods, with the following data for periods:
       | 01 March 2024    | Accrual Activity | 0.47   | 0.0       | 0.47     | 0.0  | 0.0       | 0.0          | false    | false    |
       | 15 March 2024    | Re-age           | 59.21  | 59.05     | 0.16     | 0.0  | 0.0       | 0.0          | false    | false    |
       | 15 March 2024    | Repayment        | 59.21  | 59.05     | 0.16     | 0.0  | 0.0       | 0.0          | false    | false    |
-      | 15 March 2024    | Accrual          | 1.05   | 0.0       | 1.05     | 0.0  | 0.0       | 0.0          | false    | false    |
+      | 15 March 2024    | Accrual          | 1.21   | 0.0       | 1.21     | 0.0  | 0.0       | 0.0          | false    | false    |
       | 15 March 2024    | Accrual Activity | 0.16   | 0.0       | 0.16     | 0.0  | 0.0       | 0.0          | false    | false    |
     When Admin set "LP2_ADV_CUSTOM_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL" loan product "DEFAULT" transaction type to "NEXT_INSTALLMENT" future installment allocation rule
 
@@ -4927,7 +4927,7 @@ Then Loan Repayment schedule has 4 periods, with the following data for periods:
       | 01 March 2024    | Accrual Activity | 0.49   | 0.0       | 0.49     | 0.0  | 0.0       | 0.0          | false    | false    |
       | 01 April 2024    | Accrual Activity | 0.39   | 0.0       | 0.39     | 0.0  | 0.0       | 0.0          | false    | false    |
       | 01 May 2024      | Repayment        | 67.83  | 67.05     | 0.78     | 0.0  | 0.0       | 0.0          | false    | false    |
-      | 01 May 2024      | Accrual          | 1.07   | 0.0       | 1.07     | 0.0  | 0.0       | 0.0          | false    | false    |
+      | 01 May 2024      | Accrual          | 1.85   | 0.0       | 1.85     | 0.0  | 0.0       | 0.0          | false    | false    |
       | 01 May 2024      | Accrual Activity | 0.39   | 0.0       | 0.39     | 0.0  | 0.0       | 0.0          | false    | false    |
 
   @TestRailId:C4233
@@ -5020,7 +5020,7 @@ Then Loan Repayment schedule has 4 periods, with the following data for periods:
       | 01 March 2024    | Re-age           | 76.02  | 75.58     | 0.44     | 0.0  | 0.0       | 0.0          | false    | false    |
       | 01 March 2024    | Accrual Activity | 0.44   | 0.0       | 0.44     | 0.0  | 0.0       | 0.0          | false    | false    |
       | 15 March 2024    | Repayment        | 76.22  | 75.58     | 0.64     | 0.0  | 0.0       | 0.0          | false    | false    |
-      | 15 March 2024    | Accrual          | 0.58   | 0.0       | 0.58     | 0.0  | 0.0       | 0.0          | false    | false    |
+      | 15 March 2024    | Accrual          | 1.22   | 0.0       | 1.22     | 0.0  | 0.0       | 0.0          | false    | false    |
       | 15 March 2024    | Accrual Activity | 0.2    | 0.0       | 0.2      | 0.0  | 0.0       | 0.0          | false    | false    |
 
   @TestRailId:C4085 @AdvancedPaymentAllocation
@@ -6498,7 +6498,7 @@ Then Loan Repayment schedule has 4 periods, with the following data for periods:
       | 01 February 2024 | Re-age           | 83.57  | 83.57     | 0.0      | 0.0  | 0.0       | 0.0          | false    | false    |
       | 01 March 2024    | Repayment        | 17.01  | 17.01     | 0.0      | 0.0  | 0.0       | 66.56        | false    | true     |
       | 01 June 2024     | Repayment        | 68.22  | 66.56     | 1.66     | 0.0  | 0.0       | 0.0          | false    | false    |
-      | 01 June 2024     | Accrual          | 0.58   | 0.0       | 0.58     | 0.0  | 0.0       | 0.0          | false    | false    |
+      | 01 June 2024     | Accrual          | 2.24   | 0.0       | 2.24     | 0.0  | 0.0       | 0.0          | false    | false    |
 
   @TestRailId:С4268 @AdvancedPaymentAllocation
   Scenario: Verify allowing Re-aging on interest bearing loan - Interest calculation: Default Behavior - with LAST_INSTALLMENT allocation rule and partial repayment, due date and frequency changed - UC5.1
@@ -6591,7 +6591,7 @@ Then Loan Repayment schedule has 4 periods, with the following data for periods:
       | 01 February 2024 | Accrual Activity | 0.58   | 0.0       | 0.58     | 0.0  | 0.0       | 0.0          | false    | false    |
       | 15 March 2024    | Re-age           | 76.22  | 75.58     | 0.64     | 0.0  | 0.0       | 0.0          | false    | false    |
       | 15 March 2024    | Repayment        | 76.22  | 75.58     | 0.64     | 0.0  | 0.0       | 0.0          | false    | false    |
-      | 15 March 2024    | Accrual          | 0.58   | 0.0       | 0.58     | 0.0  | 0.0       | 0.0          | false    | false    |
+      | 15 March 2024    | Accrual          | 1.22   | 0.0       | 1.22     | 0.0  | 0.0       | 0.0          | false    | false    |
       | 15 March 2024    | Accrual Activity | 0.64   | 0.0       | 0.64     | 0.0  | 0.0       | 0.0          | false    | false    |
     When Admin set "LP2_ADV_CUSTOM_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL" loan product "DEFAULT" transaction type to "NEXT_INSTALLMENT" future installment allocation rule
 
@@ -6697,7 +6697,7 @@ Then Loan Repayment schedule has 4 periods, with the following data for periods:
       | 13 April 2024    | Accrual Activity | 0.18   | 0.0       | 0.18     | 0.0  | 0.0       | 0.0          | false    | false    |
       | 27 April 2024    | Accrual Activity | 0.18   | 0.0       | 0.18     | 0.0  | 0.0       | 0.0          | false    | false    |
       | 01 May 2024      | Repayment        | 67.83  | 67.05     | 0.78     | 0.0  | 0.0       | 0.0          | false    | false    |
-      | 01 May 2024      | Accrual          | 1.07   | 0.0       | 1.07     | 0.0  | 0.0       | 0.0          | false    | false    |
+      | 01 May 2024      | Accrual          | 1.85   | 0.0       | 1.85     | 0.0  | 0.0       | 0.0          | false    | false    |
       | 01 May 2024      | Accrual Activity | 0.05   | 0.0       | 0.05     | 0.0  | 0.0       | 0.0          | false    | false    |
 
   @TestRailId:С4270 @AdvancedPaymentAllocation
@@ -6790,7 +6790,7 @@ Then Loan Repayment schedule has 4 periods, with the following data for periods:
       | 01 March 2024    | Re-age           | 76.02  | 75.58     | 0.44     | 0.0  | 0.0       | 0.0          | false    | false    |
       | 01 March 2024    | Accrual Activity | 0.44   | 0.0       | 0.44     | 0.0  | 0.0       | 0.0          | false    | false    |
       | 15 March 2024    | Repayment        | 76.22  | 75.58     | 0.64     | 0.0  | 0.0       | 0.0          | false    | false    |
-      | 15 March 2024    | Accrual          | 0.58   | 0.0       | 0.58     | 0.0  | 0.0       | 0.0          | false    | false    |
+      | 15 March 2024    | Accrual          | 1.22   | 0.0       | 1.22     | 0.0  | 0.0       | 0.0          | false    | false    |
       | 15 March 2024    | Accrual Activity | 0.2    | 0.0       | 0.2      | 0.0  | 0.0       | 0.0          | false    | false    |
 
   @TestRailId:С4271 @AdvancedPaymentAllocation
@@ -6895,7 +6895,7 @@ Then Loan Repayment schedule has 4 periods, with the following data for periods:
       | 16 April 2024    | Accrual Activity | 0.18   | 0.0       | 0.18     | 0.0  | 0.0       | 0.0          | false    | false    |
       | 30 April 2024    | Accrual Activity | 0.18   | 0.0       | 0.18     | 0.0  | 0.0       | 0.0          | false    | false    |
       | 01 May 2024      | Repayment        | 67.82  | 67.05     | 0.77     | 0.0  | 0.0       | 0.0          | false    | false    |
-      | 01 May 2024      | Accrual          | 1.07   | 0.0       | 1.07     | 0.0  | 0.0       | 0.0          | false    | false    |
+      | 01 May 2024      | Accrual          | 1.84   | 0.0       | 1.84     | 0.0  | 0.0       | 0.0          | false    | false    |
       | 01 May 2024      | Accrual Activity | 0.01   | 0.0       | 0.01     | 0.0  | 0.0       | 0.0          | false    | false    |
 
   @TestRailId:C4249 @AdvancedPaymentAllocation
@@ -8520,7 +8520,7 @@ Then Loan Repayment schedule has 4 periods, with the following data for periods:
       | 16 April 2024    | Payout Refund         | 40.0   | 14.52     | 0.48     | 0.0  | 25.0      | 69.05        | false    | false    |
       | 16 April 2024    | Interest Refund       | 0.52   | 0.39      | 0.13     | 0.0  | 0.0       | 68.66        | false    | false    |
       | 17 April 2024    | Repayment             | 80.0   | 68.66     | 0.0      | 0.0  | 0.0       | 0.0          | false    | false    |
-      | 17 April 2024    | Accrual               | 25.58  | 0.0       | 0.58     | 0.0  | 25.0      | 0.0          | false    | false    |
+      | 17 April 2024    | Accrual               | 26.19  | 0.0       | 1.19     | 0.0  | 25.0      | 0.0          | false    | false    |
       | 17 April 2024    | Accrual Activity      | 25.13  | 0.0       | 0.13     | 0.0  | 25.0      | 0.0          | false    | false    |
       | 18 April 2024    | Credit Balance Refund | 11.34  | 0.0       | 0.0      | 0.0  | 0.0       | 0.0          | false    | false    |
 #   --- Close loan ---
diff --git a/fineract-e2e-tests-runner/src/test/resources/features/LoanRepayment.feature b/fineract-e2e-tests-runner/src/test/resources/features/LoanRepayment.feature
index 80db7c67bc..2026b67ac1 100644
--- a/fineract-e2e-tests-runner/src/test/resources/features/LoanRepayment.feature
+++ b/fineract-e2e-tests-runner/src/test/resources/features/LoanRepayment.feature
@@ -5685,6 +5685,7 @@ Feature: LoanRepayment
       | 16 August 2025   | Accrual          | 5.28   | 0.0       | 5.28     | 0.0  | 0.0       | 0.0          | false    | false    |
       | 16 August 2025   | Accrual Activity | 1.76   | 0.0       | 1.76     | 0.0  | 0.0       | 0.0          | false    | false    |
       | 21 August 2025   | Accrual          | 2.8    | 0.0       | 0.0      | 0.0  | 2.8       | 0.0          | false    | false    |
+      | 21 August 2025   | Accrual Activity | 2.8    | 0.0       | 0.0      | 0.0  | 2.8       | 0.0          | false    | true     |
       | 22 August 2025   | Repayment        | 195.07 | 186.99    | 5.28     | 0.0  | 2.8       | 0.0          | true     | false    |
     Then Loan status will be "ACTIVE"
     Then Loan has 195.07 outstanding amount
diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
index fa1984c86b..787d9db877 100644
--- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
+++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
@@ -1764,6 +1764,10 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
         return getLoanTransaction(e -> e.isNotReversed() && e.isContractTermination());
     }
 
+    public LoanTransaction findReAgeTransaction() {
+        return getLoanTransaction(LoanTransaction::isReAge);
+    }
+
     public void handleMaturityDateActivate() {
         if (this.expectedMaturityDate != null && !this.expectedMaturityDate.equals(this.actualMaturityDate)) {
             this.actualMaturityDate = this.expectedMaturityDate;
diff --git a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/ProgressiveLoanScheduleGenerator.java b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/ProgressiveLoanScheduleGenerator.java
index e67ff4c236..ffb2816ecd 100644
--- a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/ProgressiveLoanScheduleGenerator.java
+++ b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/ProgressiveLoanScheduleGenerator.java
@@ -41,6 +41,9 @@ import org.apache.fineract.portfolio.loanaccount.data.OutstandingAmountsDTO;
 import org.apache.fineract.portfolio.loanaccount.domain.Loan;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
 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.domain.transactionprocessor.LoanRepaymentScheduleTransactionProcessor;
 import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.AdvancedPaymentScheduleTransactionProcessor;
 import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleDTO;
@@ -243,10 +246,14 @@ public class ProgressiveLoanScheduleGenerator implements LoanScheduleGenerator {
         Loan loan = installment.getLoan();
         LoanRepaymentScheduleTransactionProcessor transactionProcessor = loanTransactionProcessingService
                 .getTransactionProcessor(loan.getTransactionProcessingStrategyCode());
+        final LoanTransaction reAgeTransaction = loan.findReAgeTransaction();
+        final LoanReAgeParameter loanReAgeParameter = reAgeTransaction != null ? reAgeTransaction.getLoanReAgeParameter() : null;
+
         if (!(transactionProcessor instanceof AdvancedPaymentScheduleTransactionProcessor processor)) {
             throw new IllegalStateException("Expected an AdvancedPaymentScheduleTransactionProcessor");
         }
-        if (installment.isAdditional() || installment.isDownPayment() || installment.isReAged()) {
+        if (installment.isAdditional() || installment.isDownPayment() || (installment.isReAged() && loanReAgeParameter != null
+                && !LoanReAgeInterestHandlingType.DEFAULT.equals(loanReAgeParameter.getInterestHandlingType()))) {
             return Money.zero(loan.getCurrency());
         }
         Optional<ProgressiveLoanInterestScheduleModel> savedModel = interestScheduleModelRepositoryWrapper.getSavedModel(loan, targetDate);
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualActivityProcessingServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualActivityProcessingServiceImpl.java
index ff5b44200c..474648b4f8 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualActivityProcessingServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualActivityProcessingServiceImpl.java
@@ -20,8 +20,10 @@ package org.apache.fineract.portfolio.loanaccount.service;
 
 import java.math.BigDecimal;
 import java.time.LocalDate;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
@@ -44,7 +46,6 @@ import org.apache.fineract.portfolio.loanaccount.domain.ChangedTransactionDetail
 import org.apache.fineract.portfolio.loanaccount.domain.Loan;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanAccountService;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
-import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleProcessingWrapper;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRelation;
@@ -108,18 +109,60 @@ public class LoanAccrualActivityProcessingServiceImpl implements LoanAccrualActi
     }
 
     @Override
-    public void recalculateAccrualActivityTransaction(Loan loan, ChangedTransactionDetail changedTransactionDetail) {
-        List<LoanTransaction> accrualActivities = loan.getLoanTransactions().stream()
+    public void recalculateAccrualActivityTransaction(final Loan loan, final ChangedTransactionDetail changedTransactionDetail) {
+        if (!loan.getLoanProductRelatedDetail().isEnableAccrualActivityPosting()) {
+            return;
+        }
+
+        final List<LoanTransaction> accrualActivities = loan.getLoanTransactions().stream()
                 .filter(lt -> lt.isNotReversed() && lt.isAccrualActivity()).toList();
-        accrualActivities.forEach(accrualActivity -> {
-            final LoanTransaction newLoanTransaction = LoanTransaction.copyTransactionProperties(accrualActivity);
 
-            calculateAccrualActivity(newLoanTransaction, loan.getCurrency(), loan.getRepaymentScheduleInstallments());
+        if (!accrualActivities.isEmpty()) {
+            final Map<LoanRepaymentScheduleInstallment, LoanTransaction> installmentsToAccrualActivities = new HashMap<>();
+
+            accrualActivities.forEach(accrualActivity -> {
+                final LoanTransaction newLoanTransaction = LoanTransaction.copyTransactionProperties(accrualActivity);
+                final List<LoanRepaymentScheduleInstallment> installments = loan.getRepaymentScheduleInstallments().stream()
+                        .filter(i -> !i.isDownPayment()).toList();
+                final LocalDate transactionDate = newLoanTransaction.getTransactionDate();
+
+                List<LoanRepaymentScheduleInstallment> targetInstallments = new ArrayList<>(installments.stream().filter(i -> i.getDueDate()
+                        .isEqual(transactionDate)
+                        || (DateUtils.isEqual(i.getObligationsMetOnDate(), transactionDate) && i.getDueDate().isAfter(transactionDate)))
+                        .toList());
+
+                AtomicBoolean transactionShouldBeReplayed = new AtomicBoolean(false);
+                if (targetInstallments.isEmpty()) {
+                    final Set<LocalDate> existingAccrualDates = accrualActivities.stream().map(LoanTransaction::getDateOf)
+                            .collect(Collectors.toSet());
+
+                    final Optional<LocalDate> nearestDueDate = installments.stream().map(LoanRepaymentScheduleInstallment::getDueDate)
+                            .filter(dueDate -> !existingAccrualDates.contains(dueDate)).min(Comparator.naturalOrder());
+
+                    if (nearestDueDate.isPresent()) {
+                        targetInstallments = installments.stream().filter(i -> i.getDueDate().equals(nearestDueDate.get()))
+                                .collect(Collectors.toList());
+                        transactionShouldBeReplayed.set(true);
+                    }
+                }
 
-            if (!LoanTransaction.transactionAmountsMatch(loan.getCurrency(), accrualActivity, newLoanTransaction)) {
-                createNewTransaction(accrualActivity, newLoanTransaction, changedTransactionDetail);
-            }
-        });
+                calculateAccrualActivity(newLoanTransaction, loan.getCurrency(), targetInstallments, transactionShouldBeReplayed);
+                targetInstallments.forEach(installment -> installmentsToAccrualActivities.put(installment, newLoanTransaction));
+
+                if (!LoanTransaction.transactionAmountsMatch(loan.getCurrency(), accrualActivity, newLoanTransaction)
+                        || transactionShouldBeReplayed.get()) {
+                    createNewTransaction(accrualActivity, newLoanTransaction, changedTransactionDetail);
+                }
+
+            });
+
+            final List<LoanRepaymentScheduleInstallment> installmentsToCreateNewAccrualActivities = loan.getRepaymentScheduleInstallments(
+                    i -> !i.isDownPayment() && DateUtils.isAfter(DateUtils.getBusinessLocalDate(), i.getDueDate())
+                            && !(installmentsToAccrualActivities.containsKey(i) && installmentsToAccrualActivities.get(i).isNotReversed()));
+
+            installmentsToCreateNewAccrualActivities
+                    .forEach(installment -> makeAccrualActivityTransaction(loan, installment, installment.getDueDate()));
+        }
     }
 
     protected void createNewTransaction(LoanTransaction loanTransaction, LoanTransaction newLoanTransaction,
@@ -169,7 +212,7 @@ public class LoanAccrualActivityProcessingServiceImpl implements LoanAccrualActi
         for (LoanRepaymentScheduleInstallment installment : loan.getRepaymentScheduleInstallments()) {
             if (!installment.isDownPayment() && !installment.isAdditional() && DateUtils.isBefore(installment.getDueDate(), closureDate)) {
                 List<LoanTransaction> installmentAccruals = accrualActivities.stream()
-                        .filter(t -> t.getDateOf().isEqual(installment.getDueDate())).toList();
+                        .filter(t -> t.getDateOf().isEqual(installment.getDueDate()) && t.isNotReversed()).toList();
 
                 if (installmentAccruals.isEmpty()) {
                     // No AAT for this installment; create one
@@ -242,27 +285,18 @@ public class LoanAccrualActivityProcessingServiceImpl implements LoanAccrualActi
     }
 
     private void calculateAccrualActivity(LoanTransaction loanTransaction, MonetaryCurrency currency,
-            List<LoanRepaymentScheduleInstallment> installments) {
-
-        final int firstNormalInstallmentNumber = LoanRepaymentScheduleProcessingWrapper.fetchFirstNormalInstallmentNumber(installments);
-
-        final List<LoanRepaymentScheduleInstallment> targetInstallments = installments.stream()
-                .filter(installment -> LoanRepaymentScheduleProcessingWrapper.isInPeriod(loanTransaction.getTransactionDate(), installment,
-                        installment.getInstallmentNumber().equals(firstNormalInstallmentNumber))
-                        || (DateUtils.isEqual(installment.getObligationsMetOnDate(), loanTransaction.getTransactionDate())
-                                && installment.getDueDate().isAfter(loanTransaction.getTransactionDate())))
-                .toList();
-
+            List<LoanRepaymentScheduleInstallment> targetInstallments, AtomicBoolean transactionShouldBeReplayed) {
         if (targetInstallments.isEmpty()) {
             return;
         }
-
         AtomicBoolean isReset = new AtomicBoolean(false);
         targetInstallments.forEach(currentInstallment -> {
-            if (currentInstallment.isNotFullyPaidOff() && (currentInstallment.getDueDate().isAfter(loanTransaction.getTransactionDate())
+            if (currentInstallment.isNotFullyPaidOff() && ((currentInstallment.getDueDate().isAfter(loanTransaction.getTransactionDate())
+                    && !currentInstallment.getDueDate().isBefore(DateUtils.getBusinessLocalDate()))
                     || (currentInstallment.getDueDate().isEqual(loanTransaction.getTransactionDate())
                             && loanTransaction.getTransactionDate().equals(DateUtils.getBusinessLocalDate())))) {
                 loanTransaction.reverse();
+                transactionShouldBeReplayed.set(false);
             } else {
                 if (!isReset.get()) {
                     loanTransaction.resetDerivedComponents();
@@ -278,12 +312,18 @@ public class LoanAccrualActivityProcessingServiceImpl implements LoanAccrualActi
                 if ((loan.isClosedObligationsMet() || loanBalanceService.isOverPaid(loan)) && currentInstallment.isObligationsMet()
                         && currentInstallment.isTransactionDateWithinPeriod(currentInstallment.getObligationsMetOnDate())) {
                     loanTransaction.updateTransactionDate(currentInstallment.getObligationsMetOnDate());
+                    transactionShouldBeReplayed.set(false);
+                } else {
+                    if (transactionShouldBeReplayed.get()) {
+                        loanTransaction.updateTransactionDate(currentInstallment.getDueDate());
+                    }
                 }
             }
         });
         if (MathUtil.isZero(MathUtil.nullToZero(MathUtil.add(loanTransaction.getInterestPortion(), loanTransaction.getFeeChargesPortion(),
                 loanTransaction.getPenaltyChargesPortion())))) {
             loanTransaction.reverse();
+            transactionShouldBeReplayed.set(false);
         }
     }
 
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualsProcessingServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualsProcessingServiceImpl.java
index 0ba26ade41..f84ac18a45 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualsProcessingServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualsProcessingServiceImpl.java
@@ -80,6 +80,8 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionComparato
 import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionToRepaymentScheduleMapping;
 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.LoanReAgeParameter;
 import org.apache.fineract.portfolio.loanaccount.exception.LoanNotFoundException;
 import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleGenerator;
 import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleGeneratorFactory;
@@ -468,7 +470,11 @@ public class LoanAccrualsProcessingServiceImpl implements LoanAccrualsProcessing
     private void addInterestAccrual(@NonNull final Loan loan, @NonNull final LocalDate tillDate,
             final LoanScheduleGenerator scheduleGenerator, @NonNull final LoanRepaymentScheduleInstallment installment,
             @NonNull final AccrualPeriodsData accrualPeriods) {
-        if (installment.isAdditional() || installment.isReAged()) {
+        final LoanTransaction reAgeTransaction = loan.findReAgeTransaction();
+        final LoanReAgeParameter loanReAgeParameter = reAgeTransaction != null ? reAgeTransaction.getLoanReAgeParameter() : null;
+
+        if (installment.isAdditional() || (installment.isReAged() && loanReAgeParameter != null
+                && !LoanReAgeInterestHandlingType.DEFAULT.equals(loanReAgeParameter.getInterestHandlingType()))) {
             return;
         }
         final AccrualPeriodData period = accrualPeriods.getPeriodByInstallmentNumber(installment.getInstallmentNumber());