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


The following commit(s) were added to refs/heads/develop by this push:
     new 90c10a5ad FINERACT-1806: Reverse-replay logic for Charge-off 
transaction
90c10a5ad is described below

commit 90c10a5adee979cfa58b35690bc730665c9c50f3
Author: Adam Saghy <[email protected]>
AuthorDate: Thu Jun 22 12:31:15 2023 +0200

    FINERACT-1806: Reverse-replay logic for Charge-off transaction
---
 .../portfolio/loanaccount/domain/Loan.java         | 174 ++++++---------------
 ...tLoanRepaymentScheduleTransactionProcessor.java |  53 +++++--
 .../LoanPostChargeOffScenariosTest.java            |  40 ++---
 3 files changed, 107 insertions(+), 160 deletions(-)

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 7c3361e14..d69e1149f 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
@@ -59,9 +59,7 @@ import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
-import java.util.function.Consumer;
 import java.util.function.Predicate;
-import java.util.stream.Collectors;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.fineract.infrastructure.codes.domain.CodeValue;
 import 
org.apache.fineract.infrastructure.configuration.service.TemporaryConfigurationServiceContainer;
@@ -3368,7 +3366,8 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom {
         final List<LoanTransaction> repaymentsOrWaivers = new ArrayList<>();
         List<LoanTransaction> trans = getLoanTransactions();
         for (final LoanTransaction transaction : trans) {
-            if (transaction.isNotReversed() && !(transaction.isDisbursement() 
|| transaction.isNonMonetaryTransaction())) {
+            if (transaction.isNotReversed()
+                    && (transaction.isChargeOff() || 
!(transaction.isDisbursement() || transaction.isNonMonetaryTransaction()))) {
                 repaymentsOrWaivers.add(transaction);
             }
         }
@@ -4486,20 +4485,18 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom {
             final List<Long> existingTransactionIds, final List<Long> 
existingReversedTransactionIds, boolean isAccountTransfer) {
 
         final List<Map<String, Object>> accountingBridgeData = new 
ArrayList<>();
-
-        // get map before charge-off
         final List<Map<String, Object>> newLoanTransactionsBeforeChargeOff = 
new ArrayList<>();
-        final Map<String, Object> accountingBridgeDataBeforeChargeOff = 
getAccountingMapForChargeOffDateCriteria(currencyCode,
-                existingTransactionIds, existingReversedTransactionIds, 
isAccountTransfer, newLoanTransactionsBeforeChargeOff, true);
-
-        // get map after charge-off
         final List<Map<String, Object>> newLoanTransactionsAfterChargeOff = 
new ArrayList<>();
-        final Map<String, Object> accountingBridgeDataAfterChargeOff = 
getAccountingMapForChargeOffDateCriteria(currencyCode,
-                existingTransactionIds, existingReversedTransactionIds, 
isAccountTransfer, newLoanTransactionsAfterChargeOff, false);
+        // get map before charge-off
+        final Map<String, Object> accountingBridgeDataBeforeChargeOff = 
buildAccountingMapForChargeOffDateCriteria(currencyCode,
+                isAccountTransfer, true);
+        // get map after charge-off
+        final Map<String, Object> accountingBridgeDataAfterChargeOff = 
buildAccountingMapForChargeOffDateCriteria(currencyCode,
+                isAccountTransfer, false);
 
-        // get map onCharge off date
-        getAccountingMapDataOnChargeOffDate(currencyCode, 
existingTransactionIds, existingReversedTransactionIds,
-                newLoanTransactionsBeforeChargeOff, 
newLoanTransactionsAfterChargeOff);
+        // split the transactions according charge-off date
+        
classifyTransactionsBasedOnChargeOffDate(newLoanTransactionsBeforeChargeOff, 
newLoanTransactionsAfterChargeOff,
+                existingTransactionIds, existingReversedTransactionIds, 
currencyCode);
 
         accountingBridgeDataBeforeChargeOff.put("newLoanTransactions", 
newLoanTransactionsBeforeChargeOff);
         accountingBridgeData.add(accountingBridgeDataBeforeChargeOff);
@@ -4510,6 +4507,21 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom {
         return accountingBridgeData;
     }
 
+    private void classifyTransactionsBasedOnChargeOffDate(List<Map<String, 
Object>> newLoanTransactionsBeforeChargeOff,
+            List<Map<String, Object>> newLoanTransactionsAfterChargeOff, 
List<Long> existingTransactionIds,
+            List<Long> existingReversedTransactionIds, String currencyCode) {
+        // Before
+        filterTransactionsByChargeOffDate(newLoanTransactionsBeforeChargeOff, 
currencyCode, existingTransactionIds,
+                existingReversedTransactionIds, transaction -> 
transaction.getTransactionDate().isBefore(getChargedOffOnDate()));
+        // On
+        filterTransactionsByChargeOffDate(newLoanTransactionsBeforeChargeOff, 
newLoanTransactionsAfterChargeOff, currencyCode,
+                existingTransactionIds, existingReversedTransactionIds,
+                transaction -> 
transaction.getTransactionDate().isEqual(getChargedOffOnDate()));
+        // After
+        filterTransactionsByChargeOffDate(newLoanTransactionsAfterChargeOff, 
currencyCode, existingTransactionIds,
+                existingReversedTransactionIds, transaction -> 
transaction.getTransactionDate().isAfter(getChargedOffOnDate()));
+    }
+
     private Map<String, Object> getAccountingBridgeDataGenericAttributes(final 
String currencyCode, boolean isAccountTransfer) {
         final Map<String, Object> accountingBridgeDataGenericAttributes = new 
LinkedHashMap<>();
         accountingBridgeDataGenericAttributes.put("loanId", getId());
@@ -4525,8 +4537,7 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom {
         return accountingBridgeDataGenericAttributes;
     }
 
-    private Map<String, Object> getAccountingMapForChargeOffDateCriteria(final 
String currencyCode, final List<Long> existingTransactionIds,
-            final List<Long> existingReversedTransactionIds, boolean 
isAccountTransfer, List<Map<String, Object>> newLoanTransactions,
+    private Map<String, Object> 
buildAccountingMapForChargeOffDateCriteria(final String currencyCode, boolean 
isAccountTransfer,
             boolean isBeforeChargeOffDate) {
         final Map<String, Object> accountingBridgeDataChargeOff = new 
LinkedHashMap<>(
                 getAccountingBridgeDataGenericAttributes(currencyCode, 
isAccountTransfer));
@@ -4537,124 +4548,41 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom {
             accountingBridgeDataChargeOff.put("isChargeOff", isChargedOff());
             accountingBridgeDataChargeOff.put("isFraud", isFraud());
         }
-        Predicate<LoanTransaction> chargeOffDateCriteria = 
isBeforeChargeOffDate
-                ? transaction -> 
transaction.getTransactionDate().isBefore(getChargedOffOnDate())
-                : transaction -> 
transaction.getTransactionDate().isAfter(getChargedOffOnDate());
-        getTransactionsForAccountingBridgeData(currencyCode, 
existingTransactionIds, existingReversedTransactionIds, newLoanTransactions,
-                chargeOffDateCriteria);
         return accountingBridgeDataChargeOff;
     }
 
-    private void getAccountingMapDataOnChargeOffDate(String currencyCode, 
List<Long> existingTransactionIds,
-            List<Long> existingReversedTransactionIds, List<Map<String, 
Object>> newLoanTransactionsBeforeChargeOff,
-            List<Map<String, Object>> newLoanTransactionsAfterChargeOff) {
-        Predicate<LoanTransaction> isOnChargeOff = transaction -> 
transaction.getTransactionDate().isEqual(getChargedOffOnDate());
-        List<LoanTransaction> transactionsOnChargeOffDate = 
this.loanTransactions.stream().filter(isOnChargeOff)
-                .collect(Collectors.toList());
-        /**
-         *
-         * TODO: Modify logic to retrieve correct charge-off transaction once 
reverse replay of charge-off is
-         * implemented
-         */
-        LoanTransaction chargeOffTransaction = 
this.loanTransactions.stream().filter(LoanTransaction::isChargeOff).findFirst().get();
-        for (final LoanTransaction transaction : transactionsOnChargeOffDate) {
-            checkAndAddReversedTransactionOnChargeOffDate(currencyCode, 
transaction, existingTransactionIds, existingReversedTransactionIds,
-                    newLoanTransactionsBeforeChargeOff, 
newLoanTransactionsAfterChargeOff, chargeOffTransaction);
-            checkAndAddNewTransactionOnChargeOffDate(currencyCode, 
transaction, existingTransactionIds, newLoanTransactionsBeforeChargeOff,
-                    newLoanTransactionsAfterChargeOff, chargeOffTransaction);
-            checkAndAddChargeOffTransaction(currencyCode, transaction, 
existingTransactionIds, newLoanTransactionsAfterChargeOff);
-        }
-    }
-
-    private void checkAndAddReversedTransactionOnChargeOffDate(String 
currencyCode, LoanTransaction transaction,
-            List<Long> existingTransactionIds, List<Long> 
existingReversedTransactionIds,
-            List<Map<String, Object>> newLoanTransactionsBeforeChargeOff, 
List<Map<String, Object>> newLoanTransactionsAfterChargeOff,
-            LoanTransaction chargeOffTransaction) {
-        if (!transaction.isChargeOff()) {
-            if (transaction.isReversed() && 
existingTransactionIds.contains(transaction.getId())
-                    && 
!existingReversedTransactionIds.contains(transaction.getId())) {
-                
compareWithChargeOffIdAndAddTransactionForAccountingData(currencyCode, 
newLoanTransactionsBeforeChargeOff,
-                        newLoanTransactionsAfterChargeOff, transaction, 
chargeOffTransaction.getId());
-
-            }
-        }
-    }
+    private void filterTransactionsByChargeOffDate(List<Map<String, Object>> 
filteredTransactions, final String currencyCode,
+            final List<Long> existingTransactionIds, final List<Long> 
existingReversedTransactionIds,
+            Predicate<LoanTransaction> chargeOffDateCriteria) {
+        
filteredTransactions.addAll(this.loanTransactions.stream().filter(chargeOffDateCriteria).filter(transaction
 -> {
+            boolean isExistingTransaction = 
existingTransactionIds.contains(transaction.getId());
+            boolean isExistingReversedTransaction = 
existingReversedTransactionIds.contains(transaction.getId());
 
-    private void checkAndAddReverseReplayedTransactionOnChargeOffDate(String 
currencyCode, LoanTransaction transaction,
-            List<Map<String, Object>> newLoanTransactionsBeforeChargeOff, 
List<Map<String, Object>> newLoanTransactionsAfterChargeOff,
-            LoanTransaction chargeOffTransaction) {
-        Predicate<LoanTransactionRelation> isReplayed = transactionRelation -> 
LoanTransactionRelationTypeEnum.REPLAYED
-                .equals(transactionRelation.getRelationType());
-        List<LoanTransactionRelation> replayedTransactionRelations = 
transaction.getLoanTransactionRelations().stream().filter(isReplayed)
-                
.sorted(Comparator.comparing(LoanTransactionRelation::getToTransaction, 
Comparator.comparingLong(LoanTransaction::getId)))
-                .toList();
-        if (!replayedTransactionRelations.isEmpty()) {
-            // Transaction Id for first reversed transaction
-            Long transactionIdForReversedTransaction = 
replayedTransactionRelations.get(0).getToTransaction().getId();
-            if (transactionIdForReversedTransaction > 
chargeOffTransaction.getId()) {
-                
newLoanTransactionsAfterChargeOff.add(transaction.toMapData(currencyCode));
+            if (transaction.isReversed() && isExistingTransaction && 
!isExistingReversedTransaction) {
+                return true;
             } else {
-                
newLoanTransactionsBeforeChargeOff.add(transaction.toMapData(currencyCode));
+                return !isExistingTransaction;
             }
-        } else {
-            // new transaction
-            
compareWithChargeOffIdAndAddTransactionForAccountingData(currencyCode, 
newLoanTransactionsBeforeChargeOff,
-                    newLoanTransactionsAfterChargeOff, transaction, 
chargeOffTransaction.getId());
-        }
+        }).map(transaction -> transaction.toMapData(currencyCode)).toList());
     }
 
-    private void checkAndAddNewTransactionOnChargeOffDate(String currencyCode, 
LoanTransaction transaction,
-            List<Long> existingTransactionIds, List<Map<String, Object>> 
newLoanTransactionsBeforeChargeOff,
-            List<Map<String, Object>> newLoanTransactionsAfterChargeOff, 
LoanTransaction chargeOffTransaction) {
-        if (!transaction.isChargeOff()) {
-            if (!existingTransactionIds.contains(transaction.getId())) {
-                if (!transaction.getLoanTransactionRelations().isEmpty()) {
-                    
checkAndAddReverseReplayedTransactionOnChargeOffDate(currencyCode, transaction, 
newLoanTransactionsBeforeChargeOff,
-                            newLoanTransactionsAfterChargeOff, 
chargeOffTransaction);
-                } else {
-                    // new transaction
-                    
compareWithChargeOffIdAndAddTransactionForAccountingData(currencyCode, 
newLoanTransactionsBeforeChargeOff,
-                            newLoanTransactionsAfterChargeOff, transaction, 
chargeOffTransaction.getId());
-                }
-            }
-        }
-    }
+    private void filterTransactionsByChargeOffDate(List<Map<String, Object>> 
newLoanTransactionsBeforeChargeOff,
+            List<Map<String, Object>> newLoanTransactionsAfterChargeOff, 
String currencyCode, List<Long> existingTransactionIds,
+            List<Long> existingReversedTransactionIds, 
Predicate<LoanTransaction> chargeOffDateCriteria) {
 
-    private void checkAndAddChargeOffTransaction(String currencyCode, 
LoanTransaction transaction, List<Long> existingTransactionIds,
-            List<Map<String, Object>> newLoanTransactionsAfterChargeOff) {
-        if (transaction.isChargeOff()) {
-            /**
-             *
-             * TODO: Modify logic for reverse replay of charge-off
-             */
-            if (!existingTransactionIds.contains(transaction.getId())) {
-                
newLoanTransactionsAfterChargeOff.add(transaction.toMapData(currencyCode));
-            }
-        }
-    }
-
-    private void 
compareWithChargeOffIdAndAddTransactionForAccountingData(final String 
currencyCode,
-            List<Map<String, Object>> newLoanTransactionsBeforeChargeOff, 
List<Map<String, Object>> newLoanTransactionsAfterChargeOff,
-            LoanTransaction transaction, Long chargeOffTransactionId) {
-        if (transaction.getId() > chargeOffTransactionId) {
-            
newLoanTransactionsAfterChargeOff.add(transaction.toMapData(currencyCode));
-        } else {
-            
newLoanTransactionsBeforeChargeOff.add(transaction.toMapData(currencyCode));
-        }
-    }
+        LoanTransaction chargeOffTransaction = 
this.loanTransactions.stream().filter(LoanTransaction::isChargeOff)
+                .filter(LoanTransaction::isNotReversed).findFirst().get();
 
-    private void getTransactionsForAccountingBridgeData(final String 
currencyCode, final List<Long> existingTransactionIds,
-            final List<Long> existingReversedTransactionIds, final 
List<Map<String, Object>> newLoanTransactions,
-            Predicate<LoanTransaction> chargeOffDateCriteria) {
-        Consumer<LoanTransaction> addTransactionForAccounting = transaction -> 
{
-            if (transaction.isReversed() && 
existingTransactionIds.contains(transaction.getId())
-                    && 
!existingReversedTransactionIds.contains(transaction.getId())) {
-                newLoanTransactions.add(transaction.toMapData(currencyCode));
-            } else if (!existingTransactionIds.contains(transaction.getId())) {
-                newLoanTransactions.add(transaction.toMapData(currencyCode));
+        
this.loanTransactions.stream().filter(chargeOffDateCriteria).forEach(transaction
 -> {
+            boolean isExistingTransaction = 
existingTransactionIds.contains(transaction.getId());
+            boolean isExistingReversedTransaction = 
existingReversedTransactionIds.contains(transaction.getId());
+            List<Map<String, Object>> targetList = 
(transaction.getId().compareTo(chargeOffTransaction.getId()) < 0)
+                    ? newLoanTransactionsBeforeChargeOff
+                    : newLoanTransactionsAfterChargeOff;
+            if ((transaction.isReversed() && isExistingTransaction && 
!isExistingReversedTransaction) || !isExistingTransaction) {
+                targetList.add(transaction.toMapData(currencyCode));
             }
-        };
-        
this.loanTransactions.stream().filter(chargeOffDateCriteria).forEach(addTransactionForAccounting);
+        });
     }
 
     public Map<String, Object> deriveAccountingBridgeData(final String 
currencyCode, final List<Long> existingTransactionIds,
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/AbstractLoanRepaymentScheduleTransactionProcessor.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/AbstractLoanRepaymentScheduleTransactionProcessor.java
index 72750cb1a..5be6b1f75 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/AbstractLoanRepaymentScheduleTransactionProcessor.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/AbstractLoanRepaymentScheduleTransactionProcessor.java
@@ -189,7 +189,7 @@ public abstract class 
AbstractLoanRepaymentScheduleTransactionProcessor implemen
                         
loanTransaction.updateLoanTransactionToRepaymentScheduleMappings(
                                 
newLoanTransaction.getLoanTransactionToRepaymentScheduleMappings());
                     } else {
-                        createNewTransactionIfNecessary(loanTransaction, 
newLoanTransaction, currency, changedTransactionDetail);
+                        createNewTransaction(loanTransaction, 
newLoanTransaction, changedTransactionDetail);
                     }
                 }
 
@@ -204,6 +204,8 @@ public abstract class 
AbstractLoanRepaymentScheduleTransactionProcessor implemen
             } else if (loanTransaction.isChargeback()) {
                 recalculateCreditTransaction(changedTransactionDetail, 
loanTransaction, currency, installments, transactionsToBeProcessed);
                 
reprocessChargebackTransactionRelation(changedTransactionDetail, 
transactionsToBeProcessed);
+            } else if (loanTransaction.isChargeOff()) {
+                recalculateChargeOffTransaction(changedTransactionDetail, 
loanTransaction, currency, installments);
             }
         }
         reprocessInstallments(installments, currency);
@@ -211,6 +213,30 @@ public abstract class 
AbstractLoanRepaymentScheduleTransactionProcessor implemen
         return changedTransactionDetail;
     }
 
+    private void recalculateChargeOffTransaction(ChangedTransactionDetail 
changedTransactionDetail, LoanTransaction loanTransaction,
+            MonetaryCurrency currency, List<LoanRepaymentScheduleInstallment> 
installments) {
+        final LoanTransaction newLoanTransaction = 
LoanTransaction.copyTransactionProperties(loanTransaction);
+        newLoanTransaction.resetDerivedComponents();
+        // determine how much is outstanding total and breakdown for 
principal, interest and charges
+        Money principalPortion = Money.zero(currency);
+        Money interestPortion = Money.zero(currency);
+        Money feeChargesPortion = Money.zero(currency);
+        Money penaltychargesPortion = Money.zero(currency);
+        for (final LoanRepaymentScheduleInstallment currentInstallment : 
installments) {
+            if (currentInstallment.isNotFullyPaidOff()) {
+                principalPortion = 
principalPortion.plus(currentInstallment.getPrincipalOutstanding(currency));
+                interestPortion = 
interestPortion.plus(currentInstallment.getInterestOutstanding(currency));
+                feeChargesPortion = 
feeChargesPortion.plus(currentInstallment.getFeeChargesOutstanding(currency));
+                penaltychargesPortion = 
penaltychargesPortion.plus(currentInstallment.getPenaltyChargesCharged(currency));
+            }
+        }
+
+        newLoanTransaction.updateComponentsAndTotal(principalPortion, 
interestPortion, feeChargesPortion, penaltychargesPortion);
+        if (!LoanTransaction.transactionAmountsMatch(currency, 
loanTransaction, newLoanTransaction)) {
+            createNewTransaction(loanTransaction, newLoanTransaction, 
changedTransactionDetail);
+        }
+    }
+
     private void 
reprocessChargebackTransactionRelation(ChangedTransactionDetail 
changedTransactionDetail,
             List<LoanTransaction> transactionsToBeProcessed) {
 
@@ -260,7 +286,9 @@ public abstract class 
AbstractLoanRepaymentScheduleTransactionProcessor implemen
         List<LoanTransaction> mergedList = 
getMergedTransactionList(transactionsToBeProcessed, changedTransactionDetail);
         Money overpaidAmount = calculateOverpaidAmount(loanTransaction, 
mergedList, installments, currency);
         processCreditTransaction(newLoanTransaction, overpaidAmount, currency, 
installments);
-        createNewTransactionIfNecessary(loanTransaction, newLoanTransaction, 
currency, changedTransactionDetail);
+        if (!LoanTransaction.transactionAmountsMatch(currency, 
loanTransaction, newLoanTransaction)) {
+            createNewTransaction(loanTransaction, newLoanTransaction, 
changedTransactionDetail);
+        }
     }
 
     private List<LoanTransaction> 
getMergedTransactionList(List<LoanTransaction> transactionList,
@@ -270,17 +298,16 @@ public abstract class 
AbstractLoanRepaymentScheduleTransactionProcessor implemen
         return mergedList;
     }
 
-    private void createNewTransactionIfNecessary(LoanTransaction 
loanTransaction, LoanTransaction newLoanTransaction,
-            MonetaryCurrency currency, ChangedTransactionDetail 
changedTransactionDetail) {
-        if (!LoanTransaction.transactionAmountsMatch(currency, 
loanTransaction, newLoanTransaction)) {
-            loanTransaction.reverse();
-            loanTransaction.updateExternalId(null);
-            
newLoanTransaction.copyLoanTransactionRelations(loanTransaction.getLoanTransactionRelations());
-            // Adding Replayed relation from newly created transaction to 
reversed transaction
-            
newLoanTransaction.getLoanTransactionRelations().add(LoanTransactionRelation.linkToTransaction(newLoanTransaction,
-                    loanTransaction, 
LoanTransactionRelationTypeEnum.REPLAYED));
-            
changedTransactionDetail.getNewTransactionMappings().put(loanTransaction.getId(),
 newLoanTransaction);
-        }
+    private void createNewTransaction(LoanTransaction loanTransaction, 
LoanTransaction newLoanTransaction,
+            ChangedTransactionDetail changedTransactionDetail) {
+        loanTransaction.reverse();
+        loanTransaction.updateExternalId(null);
+        
newLoanTransaction.copyLoanTransactionRelations(loanTransaction.getLoanTransactionRelations());
+        // Adding Replayed relation from newly created transaction to reversed 
transaction
+        newLoanTransaction.getLoanTransactionRelations().add(
+                LoanTransactionRelation.linkToTransaction(newLoanTransaction, 
loanTransaction, LoanTransactionRelationTypeEnum.REPLAYED));
+        
changedTransactionDetail.getNewTransactionMappings().put(loanTransaction.getId(),
 newLoanTransaction);
+
     }
 
     private Money calculateOverpaidAmount(LoanTransaction loanTransaction, 
List<LoanTransaction> transactions,
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanPostChargeOffScenariosTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanPostChargeOffScenariosTest.java
index a759e3486..f850df079 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanPostChargeOffScenariosTest.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanPostChargeOffScenariosTest.java
@@ -58,15 +58,20 @@ import 
org.apache.fineract.integrationtests.common.funds.FundsHelper;
 import org.apache.fineract.integrationtests.common.funds.FundsResourceHandler;
 import 
org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder;
 import org.apache.fineract.integrationtests.common.loans.LoanProductHelper;
+import 
org.apache.fineract.integrationtests.common.loans.LoanTestLifecycleExtension;
 import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
 import 
org.apache.fineract.integrationtests.common.products.DelinquencyBucketsHelper;
 import org.apache.fineract.integrationtests.common.system.CodeHelper;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
 
+@ExtendWith(LoanTestLifecycleExtension.class)
 public class LoanPostChargeOffScenariosTest {
 
+    private static final DateTimeFormatter DATE_FORMATTER = new 
DateTimeFormatterBuilder().appendPattern("dd MMMM yyyy").toFormatter();
     private ResponseSpecification responseSpec;
     private RequestSpecification requestSpec;
     private ClientHelper clientHelper;
@@ -77,33 +82,23 @@ public class LoanPostChargeOffScenariosTest {
     // asset
     private Account loansReceivable;
     private Account interestFeeReceivable;
-    private Account otherReceivables;
-    private Account uncReceivable;
     private Account suspenseAccount;
     private Account fundReceivables;
-
     // liability
-    private Account aaSuspenseBalance;
     private Account suspenseClearingAccount;
     private Account overpaymentAccount;
-
     // income
-    private Account deferredInterestRevenue;
-    private Account retainedEarningsPriorYear;
     private Account interestIncome;
     private Account feeIncome;
     private Account feeChargeOff;
     private Account recoveries;
     private Account interestIncomeChargeOff;
-
     // expense
     private Account creditLossBadDebt;
     private Account creditLossBadDebtFraud;
     private Account writtenOff;
     private Account goodwillExpenseAccount;
 
-    private DateTimeFormatter dateFormatter = new 
DateTimeFormatterBuilder().appendPattern("dd MMMM yyyy").toFormatter();
-
     @BeforeEach
     public void setup() {
         Utils.initializeRESTAssured();
@@ -117,19 +112,14 @@ public class LoanPostChargeOffScenariosTest {
         // Asset
         this.loansReceivable = this.accountHelper.createAssetAccount();
         this.interestFeeReceivable = this.accountHelper.createAssetAccount();
-        this.otherReceivables = this.accountHelper.createAssetAccount();
-        this.uncReceivable = this.accountHelper.createAssetAccount();
         this.suspenseAccount = this.accountHelper.createAssetAccount();
         this.fundReceivables = this.accountHelper.createAssetAccount();
 
         // Liability
-        this.aaSuspenseBalance = this.accountHelper.createLiabilityAccount();
         this.suspenseClearingAccount = 
this.accountHelper.createLiabilityAccount();
         this.overpaymentAccount = this.accountHelper.createLiabilityAccount();
 
         // income
-        this.deferredInterestRevenue = 
this.accountHelper.createIncomeAccount();
-        this.retainedEarningsPriorYear = 
this.accountHelper.createIncomeAccount();
         this.interestIncome = this.accountHelper.createIncomeAccount();
         this.feeIncome = this.accountHelper.createIncomeAccount();
         this.feeChargeOff = this.accountHelper.createIncomeAccount();
@@ -158,7 +148,7 @@ public class LoanPostChargeOffScenariosTest {
                 
ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT,
 "10", false));
 
         LocalDate targetDate = LocalDate.of(2022, 9, 5);
-        final String feeCharge1AddedDate = dateFormatter.format(targetDate);
+        final String feeCharge1AddedDate = DATE_FORMATTER.format(targetDate);
         Integer feeLoanChargeId = 
loanTransactionHelper.addChargesForLoan(loanId,
                 
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(feeCharge),
 feeCharge1AddedDate, "10"));
 
@@ -328,7 +318,7 @@ public class LoanPostChargeOffScenariosTest {
                 
ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT,
 "10", false));
 
         LocalDate targetDate = LocalDate.of(2022, 9, 5);
-        final String feeCharge1AddedDate = dateFormatter.format(targetDate);
+        final String feeCharge1AddedDate = DATE_FORMATTER.format(targetDate);
         Integer feeLoanChargeId = 
loanTransactionHelper.addChargesForLoan(loanId,
                 
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(feeCharge),
 feeCharge1AddedDate, "10"));
 
@@ -452,7 +442,7 @@ public class LoanPostChargeOffScenariosTest {
                 
ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT,
 "10", false));
 
         LocalDate targetDate = LocalDate.of(2022, 9, 5);
-        final String feeCharge1AddedDate = dateFormatter.format(targetDate);
+        final String feeCharge1AddedDate = DATE_FORMATTER.format(targetDate);
         Integer feeLoanChargeId = 
loanTransactionHelper.addChargesForLoan(loanId,
                 
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(feeCharge),
 feeCharge1AddedDate, "10"));
 
@@ -586,7 +576,8 @@ public class LoanPostChargeOffScenariosTest {
     }
 
     @Test
-    public void transactionOnChargeOfDatePreChargeOffReverseReplayTest() {
+    @Disabled("Requires: FINERACT-1946")
+    public void transactionOnChargeOffDatePreChargeOffReverseReplayTest() {
         String loanExternalIdStr = UUID.randomUUID().toString();
         final Integer loanProductID = 
createLoanProductWithPeriodicAccrualAccounting();
         final Integer clientId = 
clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId().intValue();
@@ -597,7 +588,7 @@ public class LoanPostChargeOffScenariosTest {
                 
ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT,
 "10", false));
 
         LocalDate targetDate = LocalDate.of(2022, 9, 5);
-        final String feeCharge1AddedDate = dateFormatter.format(targetDate);
+        final String feeCharge1AddedDate = DATE_FORMATTER.format(targetDate);
         Integer feeLoanChargeId = 
loanTransactionHelper.addChargesForLoan(loanId,
                 
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(feeCharge),
 feeCharge1AddedDate, "10"));
 
@@ -730,7 +721,8 @@ public class LoanPostChargeOffScenariosTest {
     }
 
     @Test
-    public void transactionOnChargeOfDatePostChargeOffReverseReplayTest() {
+    @Disabled("Requires: FINERACT-1946")
+    public void transactionOnChargeOffDatePostChargeOffReverseReplayTest() {
         String loanExternalIdStr = UUID.randomUUID().toString();
         final Integer loanProductID = 
createLoanProductWithPeriodicAccrualAccounting();
         final Integer clientId = 
clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId().intValue();
@@ -741,7 +733,7 @@ public class LoanPostChargeOffScenariosTest {
                 
ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT,
 "10", false));
 
         LocalDate targetDate = LocalDate.of(2022, 9, 5);
-        final String feeCharge1AddedDate = dateFormatter.format(targetDate);
+        final String feeCharge1AddedDate = DATE_FORMATTER.format(targetDate);
         Integer feeLoanChargeId = 
loanTransactionHelper.addChargesForLoan(loanId,
                 
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(feeCharge),
 feeCharge1AddedDate, "10"));
 
@@ -885,7 +877,7 @@ public class LoanPostChargeOffScenariosTest {
                 
ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT,
 "10", false));
 
         LocalDate targetDate = LocalDate.of(2022, 9, 5);
-        final String feeCharge1AddedDate = dateFormatter.format(targetDate);
+        final String feeCharge1AddedDate = DATE_FORMATTER.format(targetDate);
         Integer feeLoanChargeId = 
loanTransactionHelper.addChargesForLoan(loanId,
                 
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(feeCharge),
 feeCharge1AddedDate, "10"));
 
@@ -992,7 +984,7 @@ public class LoanPostChargeOffScenariosTest {
                 
ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT,
 "10", false));
 
         LocalDate targetDate = LocalDate.of(2022, 9, 5);
-        final String feeCharge1AddedDate = dateFormatter.format(targetDate);
+        final String feeCharge1AddedDate = DATE_FORMATTER.format(targetDate);
         Integer feeLoanChargeId = 
loanTransactionHelper.addChargesForLoan(loanId,
                 
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(feeCharge),
 feeCharge1AddedDate, "10"));
 

Reply via email to