This is an automated email from the ASF dual-hosted git repository.

manojvm 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 d388a3aa3 fix for 1665 and 1666 (#2441)
d388a3aa3 is described below

commit d388a3aa35da925b5479509ce99c8f6263f6d19f
Author: logoutdhaval <[email protected]>
AuthorDate: Sun Jul 24 01:19:54 2022 +0530

    fix for 1665 and 1666 (#2441)
    
    Co-authored-by: Dhaval Maniyar <[email protected]>
---
 .../savings/data/SavingsAccountSummaryData.java    |   8 +-
 .../savings/domain/RecurringDepositAccount.java    |   8 +-
 .../portfolio/savings/domain/SavingsAccount.java   | 112 ++++++++++----
 .../savings/domain/SavingsAccountAssembler.java    |  22 ++-
 .../domain/SavingsAccountDomainServiceJpa.java     |  16 +-
 .../domain/SavingsAccountRepositoryWrapper.java    |   5 +
 .../savings/domain/SavingsAccountSummary.java      |  25 ++-
 .../SavingsAccountTransactionRepository.java       |   5 +
 ...countWritePlatformServiceJpaRepositoryImpl.java |   6 +-
 ...countWritePlatformServiceJpaRepositoryImpl.java |   6 +-
 .../ClientSavingsIntegrationTest.java              | 167 ++++++++++++++++++++-
 11 files changed, 293 insertions(+), 87 deletions(-)

diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountSummaryData.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountSummaryData.java
index 145f3e19f..2af8f1484 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountSummaryData.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountSummaryData.java
@@ -256,7 +256,6 @@ public class SavingsAccountSummaryData implements 
Serializable {
             final SavingsAccountTransactionData savingsAccountTransaction = 
savingsAccountTransactions.get(i);
             if (savingsAccountTransaction.isInterestPostingAndNotReversed() && 
!savingsAccountTransaction.isReversalTransaction()
                     && !isUpdated) {
-                
setRunningBalanceOnPivotDate(savingsAccountTransaction.getRunningBalance(currency).getAmount());
                 
setInterestPostedTillDate(savingsAccountTransaction.getTransactionDate());
                 isUpdated = true;
                 if (!backdatedTxnsAllowedTill) {
@@ -265,7 +264,6 @@ public class SavingsAccountSummaryData implements 
Serializable {
             }
             if (savingsAccountTransaction.isOverdraftInterestAndNotReversed() 
&& !savingsAccountTransaction.isReversalTransaction()
                     && !isUpdated) {
-                
setRunningBalanceOnPivotDate(savingsAccountTransaction.getRunningBalance(currency).getAmount());
                 
setInterestPostedTillDate(savingsAccountTransaction.getTransactionDate());
                 isUpdated = true;
                 if (!backdatedTxnsAllowedTill) {
@@ -273,13 +271,13 @@ public class SavingsAccountSummaryData implements 
Serializable {
                 }
             }
             if (backdatedTxnsAllowedTill) {
-                if 
(savingsAccountTransaction.isInterestPostingAndNotReversed()) {
+                if 
(savingsAccountTransaction.isInterestPostingAndNotReversed() && 
!savingsAccountTransaction.isReversalTransaction()) {
                     interestTotal = 
interestTotal.plus(savingsAccountTransaction.getAmount());
                 }
-                if 
(savingsAccountTransaction.isOverdraftInterestAndNotReversed()) {
+                if 
(savingsAccountTransaction.isOverdraftInterestAndNotReversed() && 
!savingsAccountTransaction.isReversalTransaction()) {
                     overdraftInterestTotal = 
overdraftInterestTotal.plus(savingsAccountTransaction.getAmount());
                 }
-                if (savingsAccountTransaction.isWithHoldTaxAndNotReversed()) {
+                if (savingsAccountTransaction.isWithHoldTaxAndNotReversed() && 
!savingsAccountTransaction.isReversalTransaction()) {
                     withHoldTaxTotal = 
withHoldTaxTotal.plus(savingsAccountTransaction.getAmount());
                 }
             }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/RecurringDepositAccount.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/RecurringDepositAccount.java
index 5a6027829..98e1a4823 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/RecurringDepositAccount.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/RecurringDepositAccount.java
@@ -541,10 +541,11 @@ public class RecurringDepositAccount extends 
SavingsAccount {
         final Money minRequiredOpeningBalance = Money.of(this.currency, 
this.minRequiredOpeningBalance);
         final boolean backdatedTxnsAllowedTill = false;
         String refNo = null;
+        final Long relaxingDaysConfigForPivotDate = 
this.configurationDomainService.retrieveRelaxingDaysConfigForPivotDate();
         if (minRequiredOpeningBalance.isGreaterThanZero()) {
             final SavingsAccountTransactionDTO transactionDTO = new 
SavingsAccountTransactionDTO(fmt, getActivationLocalDate(),
                     minRequiredOpeningBalance.getAmount(), null, 
DateUtils.getLocalDateTimeOfSystem(), user, accountType);
-            deposit(transactionDTO, backdatedTxnsAllowedTill, refNo);
+            deposit(transactionDTO, backdatedTxnsAllowedTill, 
relaxingDaysConfigForPivotDate, refNo);
 
             // update existing transactions so derived balance fields are
             // correct.
@@ -842,7 +843,7 @@ public class RecurringDepositAccount extends SavingsAccount 
{
 
     @Override
     public SavingsAccountTransaction deposit(final 
SavingsAccountTransactionDTO transactionDTO, final boolean 
backdatedTxnsAllowedTill,
-            final String refNo) {
+            final Long relaxingDaysConfigForPivotDate, final String refNo) {
 
         if (isAccountMatured()) {
             final String defaultUserMessage = "Transaction is not allowed. 
Account is matured.";
@@ -880,7 +881,8 @@ public class RecurringDepositAccount extends SavingsAccount 
{
             throw new PlatformApiDataValidationException(dataValidationErrors);
         }
 
-        final SavingsAccountTransaction transaction = 
super.deposit(transactionDTO, backdatedTxnsAllowedTill, refNo);
+        final SavingsAccountTransaction transaction = 
super.deposit(transactionDTO, backdatedTxnsAllowedTill,
+                relaxingDaysConfigForPivotDate, refNo);
 
         return transaction;
     }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccount.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccount.java
index 928531625..938666668 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccount.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccount.java
@@ -72,6 +72,7 @@ import javax.persistence.Transient;
 import javax.persistence.UniqueConstraint;
 import javax.persistence.Version;
 import org.apache.commons.lang3.StringUtils;
+import 
org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
 import org.apache.fineract.infrastructure.core.api.JsonCommand;
 import org.apache.fineract.infrastructure.core.data.ApiParameterError;
 import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
@@ -337,6 +338,8 @@ public class SavingsAccount extends 
AbstractPersistableCustom {
     @OneToMany(cascade = CascadeType.ALL, mappedBy = "account", orphanRemoval 
= true, fetch = FetchType.LAZY)
     protected List<InteropIdentifier> identifiers = new ArrayList<>();
 
+    public transient ConfigurationDomainService configurationDomainService;
+
     protected SavingsAccount() {
         //
     }
@@ -529,7 +532,12 @@ public class SavingsAccount extends 
AbstractPersistableCustom {
             if 
(!interestPostingTransactionDate.isAfter(interestPostingUpToDate)) {
                 interestPostedToDate = 
interestPostedToDate.plus(interestEarnedToBePostedForPeriod);
 
-                final SavingsAccountTransaction postingTransaction = 
findInterestPostingTransactionFor(interestPostingTransactionDate);
+                SavingsAccountTransaction postingTransaction = null;
+                if (backdatedTxnsAllowedTill) {
+                    postingTransaction = 
findInterestPostingSavingsTransactionWithPivotConfig(interestPostingTransactionDate);
+                } else {
+                    postingTransaction = 
findInterestPostingTransactionFor(interestPostingTransactionDate);
+                }
                 if (postingTransaction == null) {
                     SavingsAccountTransaction newPostingTransaction;
                     if 
(interestEarnedToBePostedForPeriod.isGreaterThanOrEqualTo(Money.zero(currency)))
 {
@@ -741,7 +749,7 @@ public class SavingsAccount extends 
AbstractPersistableCustom {
         SavingsAccountTransaction savingsTransaction = null;
         List<SavingsAccountTransaction> trans = getTransactions();
         for (final SavingsAccountTransaction transaction : trans) {
-            if (transaction.isNotReversed() && transaction.occursOn(date)) {
+            if (transaction.isNotReversed() && 
!transaction.isReversalTransaction() && transaction.occursOn(date)) {
                 savingsTransaction = transaction;
                 break;
             }
@@ -754,7 +762,7 @@ public class SavingsAccount extends 
AbstractPersistableCustom {
         SavingsAccountTransaction savingsTransaction = null;
         List<SavingsAccountTransaction> trans = 
getSavingsAccountTransactionsWithPivotConfig();
         for (final SavingsAccountTransaction transaction : trans) {
-            if (transaction.isNotReversed() && transaction.occursOn(date)) {
+            if (transaction.isNotReversed() && 
!transaction.isReversalTransaction() && transaction.occursOn(date)) {
                 savingsTransaction = transaction;
                 break;
             }
@@ -765,7 +773,7 @@ public class SavingsAccount extends 
AbstractPersistableCustom {
     public List<LocalDate> getManualPostingDates() {
         List<LocalDate> transactions = new ArrayList<>();
         for (SavingsAccountTransaction trans : this.transactions) {
-            if (trans.isInterestPosting() && trans.isNotReversed() && 
trans.isManualTransaction()) {
+            if (trans.isInterestPosting() && trans.isNotReversed() && 
!trans.isReversalTransaction() && trans.isManualTransaction()) {
                 transactions.add(trans.getTransactionLocalDate());
             }
         }
@@ -829,7 +837,12 @@ public class SavingsAccount extends 
AbstractPersistableCustom {
 
         final SavingsInterestCalculationDaysInYearType daysInYearType = 
SavingsInterestCalculationDaysInYearType
                 .fromInt(this.interestCalculationDaysInYearType);
-        List<LocalDate> postedAsOnDates = getManualPostingDates();
+        List<LocalDate> postedAsOnDates = null;
+        if (backdatedTxnsAllowedTill) {
+            postedAsOnDates = getManualPostingDatesWithPivotConfig();
+        } else {
+            postedAsOnDates = getManualPostingDates();
+        }
         if (postInterestOnDate != null) {
             postedAsOnDates.add(postInterestOnDate);
         }
@@ -840,26 +853,20 @@ public class SavingsAccount extends 
AbstractPersistableCustom {
         final List<PostingPeriod> allPostingPeriods = new ArrayList<>();
 
         Money periodStartingBalance;
-        if (this.startInterestCalculationDate != null) {
+        if (this.startInterestCalculationDate != null && 
!this.getStartInterestCalculationDate().equals(this.getActivationLocalDate())) {
             LocalDate startInterestCalculationDate = 
this.startInterestCalculationDate;
-            final SavingsAccountTransaction transaction = 
findLastTransaction(startInterestCalculationDate);
+            SavingsAccountTransaction transaction = null;
+            if (backdatedTxnsAllowedTill) {
+                transaction = 
findLastFilteredTransactionWithPivotConfig(startInterestCalculationDate);
+            } else {
+                transaction = 
findLastTransaction(startInterestCalculationDate);
+            }
 
             if (transaction == null) {
-                final String defaultUserMessage = "No transactions were found 
on the specified date "
-                        + getStartInterestCalculationDate().toString() + " for 
account number " + this.accountNumber.toString()
-                        + " and resource id " + getId();
-
-                final ApiParameterError error = 
ApiParameterError.parameterError(
-                        
"error.msg.savingsaccount.transaction.incorrect.start.interest.calculation.date",
 defaultUserMessage,
-                        "transactionDate", 
getStartInterestCalculationDate().toString());
-
-                final List<ApiParameterError> dataValidationErrors = new 
ArrayList<>();
-                dataValidationErrors.add(error);
-
-                throw new 
PlatformApiDataValidationException(dataValidationErrors);
+                periodStartingBalance = Money.zero(this.currency);
+            } else {
+                periodStartingBalance = Money.of(this.currency, 
this.summary.getRunningBalanceOnPivotDate());
             }
-
-            periodStartingBalance = 
transaction.getRunningBalance(this.currency);
         } else {
             periodStartingBalance = Money.zero(this.currency);
         }
@@ -878,11 +885,19 @@ public class SavingsAccount extends 
AbstractPersistableCustom {
                 isUserPosting = true;
             }
 
-            final PostingPeriod postingPeriod = 
PostingPeriod.createFrom(periodInterval, periodStartingBalance,
-                    retreiveOrderedNonInterestPostingTransactions(), 
this.currency, compoundingPeriodType, interestCalculationType,
-                    interestRateAsFraction, daysInYearType.getValue(), 
upToInterestCalculationDate, interestPostTransactions,
-                    isInterestTransfer, minBalanceForInterestCalculation, 
isSavingsInterestPostingAtCurrentPeriodEnd,
-                    overdraftInterestRateAsFraction, 
minOverdraftForInterestCalculation, isUserPosting, financialYearBeginningMonth);
+            PostingPeriod postingPeriod = null;
+            List<SavingsAccountTransaction> 
orderedNonInterestPostingTransactions = null;
+            if (backdatedTxnsAllowedTill) {
+                orderedNonInterestPostingTransactions = 
retreiveOrderedNonInterestPostingSavingsTransactionsWithPivotConfig();
+            } else {
+                orderedNonInterestPostingTransactions = 
retreiveOrderedNonInterestPostingTransactions();
+            }
+
+            postingPeriod = PostingPeriod.createFrom(periodInterval, 
periodStartingBalance, orderedNonInterestPostingTransactions,
+                    this.currency, compoundingPeriodType, 
interestCalculationType, interestRateAsFraction, daysInYearType.getValue(),
+                    upToInterestCalculationDate, interestPostTransactions, 
isInterestTransfer, minBalanceForInterestCalculation,
+                    isSavingsInterestPostingAtCurrentPeriodEnd, 
overdraftInterestRateAsFraction, minOverdraftForInterestCalculation,
+                    isUserPosting, financialYearBeginningMonth);
 
             periodStartingBalance = postingPeriod.closingBalance();
 
@@ -1023,7 +1038,7 @@ public class SavingsAccount extends 
AbstractPersistableCustom {
                     if (overdraftAmount.isGreaterThanZero()) {
                         
accountTransaction.updateOverdraftAmount(overdraftAmount.getAmount());
                     }
-                    // accountTransaction.updateRunningBalance(runningBalance);
+                    accountTransaction.updateRunningBalance(runningBalance);
                     if (backdatedTxnsAllowedTill) {
                         addTransactionToExisting(accountTransaction);
                         if (reversal != null) {
@@ -1068,18 +1083,21 @@ public class SavingsAccount extends 
AbstractPersistableCustom {
     }
 
     public SavingsAccountTransaction deposit(final 
SavingsAccountTransactionDTO transactionDTO, final boolean 
backdatedTxnsAllowedTill,
-            final String refNo) {
-        return deposit(transactionDTO, SavingsAccountTransactionType.DEPOSIT, 
backdatedTxnsAllowedTill, refNo);
+            final Long relaxingDaysConfigForPivotDate, final String refNo) {
+        return deposit(transactionDTO, SavingsAccountTransactionType.DEPOSIT, 
backdatedTxnsAllowedTill, relaxingDaysConfigForPivotDate,
+                refNo);
     }
 
     public SavingsAccountTransaction dividendPayout(final 
SavingsAccountTransactionDTO transactionDTO,
-            final boolean backdatedTxnsAllowedTill) {
+            final boolean backdatedTxnsAllowedTill, final Long 
relaxingDaysConfigForPivotDate) {
         String refNo = null;
-        return deposit(transactionDTO, 
SavingsAccountTransactionType.DIVIDEND_PAYOUT, backdatedTxnsAllowedTill, refNo);
+        return deposit(transactionDTO, 
SavingsAccountTransactionType.DIVIDEND_PAYOUT, backdatedTxnsAllowedTill,
+                relaxingDaysConfigForPivotDate, refNo);
     }
 
     public SavingsAccountTransaction deposit(final 
SavingsAccountTransactionDTO transactionDTO,
-            final SavingsAccountTransactionType savingsAccountTransactionType, 
final boolean backdatedTxnsAllowedTill, final String refNo) {
+            final SavingsAccountTransactionType savingsAccountTransactionType, 
final boolean backdatedTxnsAllowedTill,
+            final Long relaxingDaysConfigForPivotDate, final String refNo) {
         final String resourceTypeName = depositAccountType().resourceName();
         if (isNotActive()) {
             final String defaultUserMessage = "Transaction is not allowed. 
Account is not active.";
@@ -1117,6 +1135,9 @@ public class SavingsAccount extends 
AbstractPersistableCustom {
 
             throw new PlatformApiDataValidationException(dataValidationErrors);
         }
+        validatePivotDateTransaction(transactionDTO.getTransactionDate(), 
backdatedTxnsAllowedTill, relaxingDaysConfigForPivotDate,
+                resourceTypeName);
+
         
validateActivityNotBeforeClientOrGroupTransferDate(SavingsEvent.SAVINGS_DEPOSIT,
 transactionDTO.getTransactionDate());
 
         final Money amount = Money.of(this.currency, 
transactionDTO.getTransactionAmount());
@@ -1144,6 +1165,25 @@ public class SavingsAccount extends 
AbstractPersistableCustom {
         return transaction;
     }
 
+    public void validatePivotDateTransaction(LocalDate transactionDate, final 
boolean backdatedTxnsAllowedTill,
+            final Long relaxingDaysConfigForPivotDate, final String 
resourceTypeName) {
+        if (backdatedTxnsAllowedTill) {
+            if (this.getSummary().getLastInterestCalculationDate() != null && 
transactionDate
+                    
.isBefore(this.getSummary().getLastInterestCalculationDate().minusDays(relaxingDaysConfigForPivotDate)))
 {
+                final Object[] defaultUserArgs = 
Arrays.asList(transactionDate, getActivationLocalDate()).toArray();
+                final String defaultUserMessage = "Transaction date cannot be 
before transactions pivot date.";
+                final ApiParameterError error = 
ApiParameterError.parameterError(
+                        "error.msg." + resourceTypeName + 
".transaction.before.pivot.date", defaultUserMessage, "transactionDate",
+                        defaultUserArgs);
+
+                final List<ApiParameterError> dataValidationErrors = new 
ArrayList<>();
+                dataValidationErrors.add(error);
+
+                throw new 
PlatformApiDataValidationException(dataValidationErrors);
+            }
+        }
+    }
+
     public LocalDate getActivationLocalDate() {
         return this.activatedOnDate;
     }
@@ -1172,8 +1212,12 @@ public class SavingsAccount extends 
AbstractPersistableCustom {
         return startInterestCalculationLocalDate;
     }
 
+    public void setStartInterestCalculationDate(LocalDate 
startInterestCalculationDate) {
+        this.startInterestCalculationDate = startInterestCalculationDate;
+    }
+
     public SavingsAccountTransaction withdraw(final 
SavingsAccountTransactionDTO transactionDTO, final boolean applyWithdrawFee,
-            final boolean backdatedTxnsAllowedTill, String refNo) {
+            final boolean backdatedTxnsAllowedTill, final Long 
relaxingDaysConfigForPivotDate, String refNo) {
 
         if (!isTransactionsAllowed()) {
 
@@ -1224,6 +1268,8 @@ public class SavingsAccount extends 
AbstractPersistableCustom {
 
             throw new PlatformApiDataValidationException(dataValidationErrors);
         }
+        validatePivotDateTransaction(transactionDTO.getTransactionDate(), 
backdatedTxnsAllowedTill, relaxingDaysConfigForPivotDate,
+                "savingsaccount");
         
validateActivityNotBeforeClientOrGroupTransferDate(SavingsEvent.SAVINGS_WITHDRAWAL,
 transactionDTO.getTransactionDate());
 
         if (applyWithdrawFee) {
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountAssembler.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountAssembler.java
index d3e34cbbb..fa234fcaa 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountAssembler.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountAssembler.java
@@ -349,6 +349,16 @@ public class SavingsAccountAssembler {
                     LocalDate interestPostedTillDate = 
account.getSummary().getInterestPostedTillDate();
                     savingsAccountTransactions = 
this.savingsAccountRepository.findTransactionsAfterPivotDate(account,
                             
interestPostedTillDate.minusDays(relaxingDaysForPivotDate));
+
+                    savingsAccountTransactions.get(0).getSavingsAccount()
+                            
.setStartInterestCalculationDate(interestPostedTillDate.minusDays(relaxingDaysForPivotDate));
+                    List<SavingsAccountTransaction> pivotDateTransaction = 
this.savingsAccountRepository
+                            
.findTransactionRunningBalanceBeforePivotDate(account,
+                                    
interestPostedTillDate.minusDays(relaxingDaysForPivotDate + 1));
+                    if (pivotDateTransaction != null && 
!pivotDateTransaction.isEmpty()) {
+                        
account.getSummary().setRunningBalanceOnPivotDate(pivotDateTransaction.get(pivotDateTransaction.size()
 - 1)
+                                
.getRunningBalance(account.getCurrency()).getAmount());
+                    }
                 } else {
                     savingsAccountTransactions = 
this.savingsAccountRepository.findTransactionsAfterPivotDate(account,
                             account.getSummary().getInterestPostedTillDate());
@@ -358,24 +368,12 @@ public class SavingsAccountAssembler {
                     // Update transient variable
                     
account.setSavingsAccountTransactions(savingsAccountTransactions);
                 }
-                // Update last running balance on account level
-                if (savingsAccountTransactions != null && 
!savingsAccountTransactions.isEmpty()) {
-                    
account.getSummary().setRunningBalanceOnPivotDate(savingsAccountTransactions.get(savingsAccountTransactions.size()
 - 1)
-                            
.getRunningBalance(account.getCurrency()).getAmount());
-                }
             } else {
                 savingsAccountTransactions = 
this.savingsAccountRepository.findAllTransactions(account);
                 
account.setSavingsAccountTransactions(savingsAccountTransactions);
             }
         }
 
-        // Update last running balance on account level
-        // if (savingsAccountTransactions != null && 
!savingsAccountTransactions.isEmpty()) {
-        // 
account.getSummary().setRunningBalanceOnPivotDate(savingsAccountTransactions.get(savingsAccountTransactions.size()
-        // - 1)
-        // .getRunningBalance(account.getCurrency()).getAmount());
-        // }
-
         account.setHelpers(this.savingsAccountTransactionSummaryWrapper, 
this.savingsHelper);
         return account;
     }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountDomainServiceJpa.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountDomainServiceJpa.java
index 4806d5e91..555585145 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountDomainServiceJpa.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountDomainServiceJpa.java
@@ -91,6 +91,7 @@ public class SavingsAccountDomainServiceJpa implements 
SavingsAccountDomainServi
         account.validateForDebitBlock();
         final boolean isSavingsInterestPostingAtCurrentPeriodEnd = 
this.configurationDomainService
                 .isSavingsInterestPostingAtCurrentPeriodEnd();
+        final Long relaxingDaysConfigForPivotDate = 
this.configurationDomainService.retrieveRelaxingDaysConfigForPivotDate();
         final Integer financialYearBeginningMonth = 
this.configurationDomainService.retrieveFinancialYearBeginningMonth();
         if (transactionBooleanValues.isRegularTransaction() && 
!account.allowWithdrawal()) {
             throw new 
DepositAccountTransactionNotAllowedException(account.getId(), "withdraw", 
account.depositAccountType());
@@ -110,7 +111,7 @@ public class SavingsAccountDomainServiceJpa implements 
SavingsAccountDomainServi
                 paymentDetail, DateUtils.getLocalDateTimeOfSystem(), user, 
accountType);
         UUID refNo = UUID.randomUUID();
         final SavingsAccountTransaction withdrawal = 
account.withdraw(transactionDTO, transactionBooleanValues.isApplyWithdrawFee(),
-                backdatedTxnsAllowedTill, refNo.toString());
+                backdatedTxnsAllowedTill, relaxingDaysConfigForPivotDate, 
refNo.toString());
         final MathContext mc = MathContext.DECIMAL64;
 
         final LocalDate today = DateUtils.getBusinessLocalDate();
@@ -134,7 +135,10 @@ public class SavingsAccountDomainServiceJpa implements 
SavingsAccountDomainServi
                 depositAccountOnHoldTransactions, backdatedTxnsAllowedTill);
 
         saveTransactionToGenerateTransactionId(withdrawal);
-
+        if (backdatedTxnsAllowedTill) {
+            // Update transactions separately
+            
saveUpdatedTransactionsOfSavingsAccount(account.getSavingsAccountTransactionsWithPivotConfig());
+        }
         this.savingsAccountRepository.save(account);
 
         postJournalEntries(account, existingTransactionIds, 
existingReversedTransactionIds, transactionBooleanValues.isAccountTransfer(),
@@ -174,7 +178,7 @@ public class SavingsAccountDomainServiceJpa implements 
SavingsAccountDomainServi
         final boolean isSavingsInterestPostingAtCurrentPeriodEnd = 
this.configurationDomainService
                 .isSavingsInterestPostingAtCurrentPeriodEnd();
         final Integer financialYearBeginningMonth = 
this.configurationDomainService.retrieveFinancialYearBeginningMonth();
-
+        final Long relaxingDaysConfigForPivotDate = 
this.configurationDomainService.retrieveRelaxingDaysConfigForPivotDate();
         if (isRegularTransaction && !account.allowDeposit()) {
             throw new 
DepositAccountTransactionNotAllowedException(account.getId(), "deposit", 
account.depositAccountType());
         }
@@ -193,7 +197,7 @@ public class SavingsAccountDomainServiceJpa implements 
SavingsAccountDomainServi
                 paymentDetail, DateUtils.getLocalDateTimeOfSystem(), user, 
accountType);
         UUID refNo = UUID.randomUUID();
         final SavingsAccountTransaction deposit = 
account.deposit(transactionDTO, savingsAccountTransactionType, 
backdatedTxnsAllowedTill,
-                refNo.toString());
+                relaxingDaysConfigForPivotDate, refNo.toString());
         final LocalDate postInterestOnDate = null;
         final MathContext mc = MathContext.DECIMAL64;
 
@@ -292,6 +296,7 @@ public class SavingsAccountDomainServiceJpa implements 
SavingsAccountDomainServi
         final boolean isSavingsInterestPostingAtCurrentPeriodEnd = 
this.configurationDomainService
                 .isSavingsInterestPostingAtCurrentPeriodEnd();
         final Integer financialYearBeginningMonth = 
this.configurationDomainService.retrieveFinancialYearBeginningMonth();
+        final Long relaxingDaysConfigForPivotDate = 
this.configurationDomainService.retrieveRelaxingDaysConfigForPivotDate();
         final Set<Long> existingTransactionIds = new HashSet<>();
         final Set<Long> existingReversedTransactionIds = new HashSet<>();
 
@@ -327,7 +332,8 @@ public class SavingsAccountDomainServiceJpa implements 
SavingsAccountDomainServi
                 account.calculateInterestUsing(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd,
                         financialYearBeginningMonth, postInterestOnDate, 
backdatedTxnsAllowedTill, postReversals);
             }
-
+            
account.validatePivotDateTransaction(savingsAccountTransaction.getLastTransactionDate(),
 backdatedTxnsAllowedTill,
+                    relaxingDaysConfigForPivotDate, "savingsaccount");
             
account.validateAccountBalanceDoesNotBecomeNegativeMinimal(savingsAccountTransaction.getAmount(),
 false);
             account.activateAccountBasedOnBalance();
         }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountRepositoryWrapper.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountRepositoryWrapper.java
index 0746b5ea7..7b7c23869 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountRepositoryWrapper.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountRepositoryWrapper.java
@@ -134,6 +134,11 @@ public class SavingsAccountRepositoryWrapper {
         return 
this.savingsAccountTransactionRepository.findTransactionsAfterPivotDate(savingsAccount,
 transactionDate);
     }
 
+    public List<SavingsAccountTransaction> 
findTransactionRunningBalanceBeforePivotDate(
+            @Param("savingsAccount") SavingsAccount savingsAccount, 
@Param("date") LocalDate date) {
+        return 
this.savingsAccountTransactionRepository.findTransactionRunningBalanceBeforePivotDate(savingsAccount,
 date);
+    }
+
     @Transactional
     public List<SavingsAccountTransaction> 
findAllTransactions(@Param("savingsAccount") SavingsAccount savingsAccount) {
         return 
this.savingsAccountTransactionRepository.findBySavingsAccount(savingsAccount);
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountSummary.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountSummary.java
index a44dbcf03..90a49ced9 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountSummary.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountSummary.java
@@ -117,7 +117,10 @@ public final class SavingsAccountSummary {
     public void updateSummaryWithPivotConfig(final MonetaryCurrency currency, 
final SavingsAccountTransactionSummaryWrapper wrapper,
             final SavingsAccountTransaction transaction, final 
List<SavingsAccountTransaction> savingsAccountTransactions) {
 
-        if (transaction != null && !transaction.isReversalTransaction()) {
+        if (transaction != null) {
+            if (transaction.isReversalTransaction()) {
+                return;
+            }
             Money transactionAmount = Money.of(currency, 
transaction.getAmount());
             switch 
(SavingsAccountTransactionType.fromInt(transaction.getTypeOf())) {
                 case DEPOSIT:
@@ -188,12 +191,7 @@ public final class SavingsAccountSummary {
             Money overdraftInterestTotal = Money.zero(currency);
             this.totalDeposits = wrapper.calculateTotalDeposits(currency, 
savingsAccountTransactions);
             this.totalWithdrawals = 
wrapper.calculateTotalWithdrawals(currency, savingsAccountTransactions);
-            this.totalWithdrawalFees = 
wrapper.calculateTotalWithdrawalFees(currency, savingsAccountTransactions);
-            this.totalAnnualFees = wrapper.calculateTotalAnnualFees(currency, 
savingsAccountTransactions);
-            this.totalFeeCharge = wrapper.calculateTotalFeesCharge(currency, 
savingsAccountTransactions);
-            this.totalPenaltyCharge = 
wrapper.calculateTotalPenaltyCharge(currency, savingsAccountTransactions);
-            this.totalFeeChargesWaived = 
wrapper.calculateTotalFeesChargeWaived(currency, savingsAccountTransactions);
-            this.totalPenaltyChargesWaived = 
wrapper.calculateTotalPenaltyChargeWaived(currency, savingsAccountTransactions);
+
             final HashMap<String, Money> map = 
updateRunningBalanceAndPivotDate(true, savingsAccountTransactions, 
interestTotal,
                     overdraftInterestTotal, withHoldTaxTotal, currency);
             interestTotal = map.get("interestTotal");
@@ -202,12 +200,11 @@ public final class SavingsAccountSummary {
             this.totalInterestPosted = 
interestTotal.getAmountDefaultedToNullIfZero();
             this.totalOverdraftInterestDerived = 
overdraftInterestTotal.getAmountDefaultedToNullIfZero();
             this.totalWithholdTax = 
withHoldTaxTotal.getAmountDefaultedToNullIfZero();
-            this.accountBalance = Money.of(currency, 
this.totalDeposits).plus(this.totalInterestPosted).minus(this.totalWithdrawals)
-                    
.minus(this.totalWithdrawalFees).minus(this.totalAnnualFees).minus(this.totalFeeCharge).minus(this.totalPenaltyCharge)
-                    
.minus(this.totalOverdraftInterestDerived).minus(totalWithholdTax).getAmount();
-            // this.accountBalance = Money.of(currency,
-            // 
this.accountBalance).plus(this.totalInterestPosted).minus(this.totalWithholdTax)
-            // .getAmount();
+
+            this.accountBalance = getRunningBalanceOnPivotDate();
+            this.accountBalance = Money.of(currency, 
this.accountBalance).plus(Money.of(currency, this.totalDeposits))
+                    
.plus(this.totalInterestPosted).minus(this.totalWithdrawals).minus(this.totalWithholdTax)
+                    .minus(this.totalOverdraftInterestDerived).getAmount();
         }
     }
 
@@ -221,7 +218,6 @@ public final class SavingsAccountSummary {
             final SavingsAccountTransaction savingsAccountTransaction = 
savingsAccountTransactions.get(i);
             if (savingsAccountTransaction.isInterestPostingAndNotReversed() && 
!savingsAccountTransaction.isReversalTransaction()
                     && !isUpdated) {
-                
setRunningBalanceOnPivotDate(savingsAccountTransaction.getRunningBalance(currency).getAmount());
                 
setInterestPostedTillDate(savingsAccountTransaction.getLastTransactionDate());
                 isUpdated = true;
                 if (!backdatedTxnsAllowedTill) {
@@ -230,7 +226,6 @@ public final class SavingsAccountSummary {
             }
             if (savingsAccountTransaction.isOverdraftInterestAndNotReversed() 
&& !savingsAccountTransaction.isReversalTransaction()
                     && !isUpdated) {
-                
setRunningBalanceOnPivotDate(savingsAccountTransaction.getRunningBalance(currency).getAmount());
                 
setInterestPostedTillDate(savingsAccountTransaction.getLastTransactionDate());
                 isUpdated = true;
                 if (!backdatedTxnsAllowedTill) {
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransactionRepository.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransactionRepository.java
index c40bf9d89..6d2db4080 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransactionRepository.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransactionRepository.java
@@ -39,6 +39,11 @@ public interface SavingsAccountTransactionRepository
     List<SavingsAccountTransaction> 
findTransactionsAfterPivotDate(@Param("savingsAccount") SavingsAccount 
savingsAccount,
             @Param("transactionDate") LocalDate transactionDate);
 
+    @Lock(LockModeType.PESSIMISTIC_WRITE)
+    @Query("select st from SavingsAccountTransaction st where 
st.savingsAccount = :savingsAccount and st.dateOf = :date and 
st.reversalTransaction <> 1 and st.reversed <> 1 order by st.id")
+    List<SavingsAccountTransaction> 
findTransactionRunningBalanceBeforePivotDate(@Param("savingsAccount") 
SavingsAccount savingsAccount,
+            @Param("date") LocalDate date);
+
     @Lock(LockModeType.PESSIMISTIC_WRITE)
     List<SavingsAccountTransaction> 
findBySavingsAccount(@Param("savingsAccount") SavingsAccount savingsAccount);
 
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountWritePlatformServiceJpaRepositoryImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountWritePlatformServiceJpaRepositoryImpl.java
index aadea8e85..3aab8ef0a 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountWritePlatformServiceJpaRepositoryImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountWritePlatformServiceJpaRepositoryImpl.java
@@ -703,7 +703,7 @@ public class 
DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
         final boolean isSavingsInterestPostingAtCurrentPeriodEnd = 
this.configurationDomainService
                 .isSavingsInterestPostingAtCurrentPeriodEnd();
         final Integer financialYearBeginningMonth = 
this.configurationDomainService.retrieveFinancialYearBeginningMonth();
-
+        final Long relaxingDaysConfigForPivotDate = 
this.configurationDomainService.retrieveRelaxingDaysConfigForPivotDate();
         this.depositAccountTransactionDataValidator.validate(command, 
DepositAccountType.RECURRING_DEPOSIT);
 
         final SavingsAccountTransaction savingsAccountTransaction = 
this.savingsAccountTransactionRepository
@@ -750,11 +750,11 @@ public class 
DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
         if (savingsAccountTransaction.isDeposit()) {
             final SavingsAccountTransactionDTO transactionDTO = new 
SavingsAccountTransactionDTO(fmt, transactionDate, transactionAmount,
                     paymentDetail, savingsAccountTransaction.getCreatedDate(), 
user, accountType);
-            transaction = account.deposit(transactionDTO, false, 
refNo.toString());
+            transaction = account.deposit(transactionDTO, false, 
relaxingDaysConfigForPivotDate, refNo.toString());
         } else {
             final SavingsAccountTransactionDTO transactionDTO = new 
SavingsAccountTransactionDTO(fmt, transactionDate, transactionAmount,
                     paymentDetail, savingsAccountTransaction.getCreatedDate(), 
user, accountType);
-            transaction = account.withdraw(transactionDTO, true, false, 
refNo.toString());
+            transaction = account.withdraw(transactionDTO, true, false, 
relaxingDaysConfigForPivotDate, refNo.toString());
         }
         final Long newtransactionId = 
saveTransactionToGenerateTransactionId(transaction);
         boolean isInterestTransfer = false;
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java
index 35f567556..648a4bd0d 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java
@@ -822,7 +822,7 @@ public class 
SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
         final boolean isSavingsInterestPostingAtCurrentPeriodEnd = 
this.configurationDomainService
                 .isSavingsInterestPostingAtCurrentPeriodEnd();
         final Integer financialYearBeginningMonth = 
this.configurationDomainService.retrieveFinancialYearBeginningMonth();
-
+        final Long relaxingDaysConfigForPivotDate = 
this.configurationDomainService.retrieveRelaxingDaysConfigForPivotDate();
         final SavingsAccountTransaction savingsAccountTransaction = 
this.savingsAccountTransactionRepository
                 .findOneByIdAndSavingsAccountId(transactionId, savingsId);
         if (savingsAccountTransaction == null) {
@@ -882,9 +882,9 @@ public class 
SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
                 paymentDetail, savingsAccountTransaction.getCreatedDate(), 
user, accountType);
         UUID refNo = UUID.randomUUID();
         if (savingsAccountTransaction.isDeposit()) {
-            transaction = account.deposit(transactionDTO, false, 
refNo.toString());
+            transaction = account.deposit(transactionDTO, false, 
relaxingDaysConfigForPivotDate, refNo.toString());
         } else {
-            transaction = account.withdraw(transactionDTO, true, false, 
refNo.toString());
+            transaction = account.withdraw(transactionDTO, true, false, 
relaxingDaysConfigForPivotDate, refNo.toString());
         }
         final Long newtransactionId = 
saveTransactionToGenerateTransactionId(transaction);
         final LocalDate postInterestOnDate = null;
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientSavingsIntegrationTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientSavingsIntegrationTest.java
index f0512f740..d12abc8a3 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientSavingsIntegrationTest.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientSavingsIntegrationTest.java
@@ -76,6 +76,8 @@ public class ClientSavingsIntegrationTest {
     private ResponseSpecification responseSpec;
     private RequestSpecification requestSpec;
     private SavingsAccountHelper savingsAccountHelper;
+    private SavingsProductHelper savingsProductHelper;
+    private SchedulerJobHelper scheduleJobHelper;
 
     @BeforeEach
     public void setup() {
@@ -2820,9 +2822,7 @@ public class ClientSavingsIntegrationTest {
     @Test
     public void testAccountBalanceAndTransactionRunningBalanceWithConfigOn() {
         this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, 
this.responseSpec);
-        
GlobalConfigurationHelper.updateEnabledFlagForGlobalConfiguration(this.requestSpec,
 this.responseSpec, "38", false);
-        
GlobalConfigurationHelper.updateEnabledFlagForGlobalConfiguration(this.requestSpec,
 this.responseSpec, "39", true);
-        
GlobalConfigurationHelper.updateValueForGlobalConfiguration(requestSpec, 
responseSpec, "39", "5");
+        configurationForBackdatedTransaction();
 
         final Integer clientID = ClientHelper.createClient(this.requestSpec, 
this.responseSpec);
         ClientHelper.verifyClientCreatedOnServer(this.requestSpec, 
this.responseSpec, clientID);
@@ -2843,17 +2843,19 @@ public class ClientSavingsIntegrationTest {
 
         savingsStatusHashMap = 
this.savingsAccountHelper.activateSavings(savingsId);
         SavingsStatusChecker.verifySavingsIsActive(savingsStatusHashMap);
-
+        LocalDate transactionDate = 
LocalDate.now(Utils.getZoneIdOfTenant()).minusDays(5);
+        final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd 
MMMM yyyy");
+        String startDate = formatter.format(transactionDate);
         // withdrawal transaction 1
-        Integer withdrawalTransactionId = (Integer) 
this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsId, "500",
-                SavingsAccountHelper.TRANSACTION_DATE, 
CommonConstants.RESPONSE_RESOURCE_ID);
+        Integer withdrawalTransactionId = (Integer) 
this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsId, "500", 
startDate,
+                CommonConstants.RESPONSE_RESOURCE_ID);
         HashMap summary = 
this.savingsAccountHelper.getSavingsSummary(savingsId);
         Float balance = Float.parseFloat("-500.0");
         assertEquals(balance, summary.get("accountBalance"), "Verifying 
account balance is -500");
 
         // withdrawal transaction 2
-        withdrawalTransactionId = (Integer) 
this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsId, "500",
-                SavingsAccountHelper.TRANSACTION_DATE, 
CommonConstants.RESPONSE_RESOURCE_ID);
+        withdrawalTransactionId = (Integer) 
this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsId, "500", 
startDate,
+                CommonConstants.RESPONSE_RESOURCE_ID);
         summary = this.savingsAccountHelper.getSavingsSummary(savingsId);
         balance = Float.parseFloat("-1000.0");
         assertEquals(balance, summary.get("accountBalance"), "Verifying 
account balance is -1000");
@@ -2866,6 +2868,155 @@ public class ClientSavingsIntegrationTest {
         assertEquals(balance.toString(), 
requestedTransaction.get("runningBalance").toString(), "Equality check for 
Balance");
     }
 
+    @Test
+    public void testRunningBalanceAfterWithdrawalWithBackdateConfigurationOn() 
{
+        this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, 
this.responseSpec);
+        this.savingsProductHelper = new SavingsProductHelper();
+        this.scheduleJobHelper = new SchedulerJobHelper(requestSpec);
+        configurationForBackdatedTransaction();
+        LocalDate transactionDate = 
LocalDate.now(Utils.getZoneIdOfTenant()).minusDays(5);
+        final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd 
MMMM yyyy");
+        String startDate = formatter.format(transactionDate);
+        String secondTrx = formatter.format(transactionDate.plusDays(1));
+        final String jobName = "Post Interest For Savings";
+        final Integer clientID = ClientHelper.createClient(this.requestSpec, 
this.responseSpec, startDate);
+        Assertions.assertNotNull(clientID);
+
+        final Integer savingsId = 
createSavingsAccountDailyPostingOverdraft(clientID, startDate);
+        this.savingsAccountHelper.depositToSavingsAccount(savingsId, "100", 
startDate, CommonConstants.RESPONSE_RESOURCE_ID);
+        this.scheduleJobHelper.executeAndAwaitJob(jobName);
+        this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsId, 
"200", secondTrx, CommonConstants.RESPONSE_RESOURCE_ID);
+        HashMap<String, Object> summaryObj = 
this.savingsAccountHelper.getSavingsSummary(savingsId);
+
+        assertEquals("-100.0822", 
summaryObj.get("availableBalance").toString(), "Equality check for Balance");
+    }
+
+    @Test
+    public void testRunningBalanceAfterDepositWithBackdateConfigurationOn() {
+        this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, 
this.responseSpec);
+        this.savingsProductHelper = new SavingsProductHelper();
+        this.scheduleJobHelper = new SchedulerJobHelper(requestSpec);
+        configurationForBackdatedTransaction();
+        LocalDate transactionDate = 
LocalDate.now(Utils.getZoneIdOfTenant()).minusDays(5);
+        final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd 
MMMM yyyy");
+        String startDate = formatter.format(transactionDate);
+        String secondTrx = formatter.format(transactionDate.plusDays(1));
+        final String jobName = "Post Interest For Savings";
+        final Integer clientID = ClientHelper.createClient(this.requestSpec, 
this.responseSpec, startDate);
+        Assertions.assertNotNull(clientID);
+
+        final Integer savingsId = 
createSavingsAccountDailyPostingOverdraft(clientID, startDate);
+        this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsId, 
"100", startDate, CommonConstants.RESPONSE_RESOURCE_ID);
+        this.scheduleJobHelper.executeAndAwaitJob(jobName);
+        this.savingsAccountHelper.depositToSavingsAccount(savingsId, "200", 
secondTrx, CommonConstants.RESPONSE_RESOURCE_ID);
+        HashMap<String, Object> summaryObj = 
this.savingsAccountHelper.getSavingsSummary(savingsId);
+        assertEquals("100.0822", 
summaryObj.get("availableBalance").toString(), "Equality check for Balance");
+    }
+
+    @Test
+    public void 
testRunningBalanceAfterWithdrawalReversalWithBackdateConfigurationOn() {
+        this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, 
this.responseSpec);
+        this.savingsProductHelper = new SavingsProductHelper();
+        this.scheduleJobHelper = new SchedulerJobHelper(requestSpec);
+        configurationForBackdatedTransaction();
+        LocalDate transactionDate = 
LocalDate.now(Utils.getZoneIdOfTenant()).minusDays(5);
+        final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd 
MMMM yyyy");
+        String startDate = formatter.format(transactionDate);
+        String secondTrx = formatter.format(transactionDate.plusDays(1));
+        final String jobName = "Post Interest For Savings";
+        final Integer clientID = ClientHelper.createClient(this.requestSpec, 
this.responseSpec, startDate);
+        Assertions.assertNotNull(clientID);
+
+        final Integer savingsId = 
createSavingsAccountDailyPostingOverdraft(clientID, startDate);
+        this.savingsAccountHelper.depositToSavingsAccount(savingsId, "100", 
startDate, CommonConstants.RESPONSE_RESOURCE_ID);
+        this.scheduleJobHelper.executeAndAwaitJob(jobName);
+
+        Integer withdrawalToReverse = (Integer) 
this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsId, "200", 
secondTrx,
+                CommonConstants.RESPONSE_RESOURCE_ID);
+        this.savingsAccountHelper.reverseSavingsAccountTransaction(savingsId, 
withdrawalToReverse);
+        HashMap<String, Object> summaryObj = 
this.savingsAccountHelper.getSavingsSummary(savingsId);
+
+        assertEquals("100.137", summaryObj.get("availableBalance").toString(), 
"Equality check for Balance");
+    }
+
+    @Test
+    public void 
testRunningBalanceAfterDepositReversalWithBackdateConfigurationOn() {
+        this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, 
this.responseSpec);
+        this.savingsProductHelper = new SavingsProductHelper();
+        this.scheduleJobHelper = new SchedulerJobHelper(requestSpec);
+        configurationForBackdatedTransaction();
+        LocalDate transactionDate = 
LocalDate.now(Utils.getZoneIdOfTenant()).minusDays(5);
+        final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd 
MMMM yyyy");
+        String startDate = formatter.format(transactionDate);
+        String secondTrx = formatter.format(transactionDate.plusDays(1));
+        final String jobName = "Post Interest For Savings";
+        final Integer clientID = ClientHelper.createClient(this.requestSpec, 
this.responseSpec, startDate);
+        Assertions.assertNotNull(clientID);
+
+        final Integer savingsId = 
createSavingsAccountDailyPostingOverdraft(clientID, startDate);
+        this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsId, 
"100", startDate, CommonConstants.RESPONSE_RESOURCE_ID);
+        this.scheduleJobHelper.executeAndAwaitJob(jobName);
+        Integer depositToReverse = (Integer) 
this.savingsAccountHelper.depositToSavingsAccount(savingsId, "200", secondTrx,
+                CommonConstants.RESPONSE_RESOURCE_ID);
+        this.savingsAccountHelper.reverseSavingsAccountTransaction(savingsId, 
depositToReverse);
+
+        HashMap<String, Object> summaryObj = 
this.savingsAccountHelper.getSavingsSummary(savingsId);
+        assertEquals("-100.137", 
summaryObj.get("availableBalance").toString(), "Equality check for Balance");
+    }
+
+    @Test
+    public void testToPerformTransactionBeforePivotDate() {
+        this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, 
this.responseSpec);
+        this.savingsProductHelper = new SavingsProductHelper();
+        this.scheduleJobHelper = new SchedulerJobHelper(requestSpec);
+
+        configurationForBackdatedTransaction();
+
+        String transactionDate = "1 July 2022";
+
+        final Integer clientID = ClientHelper.createClient(this.requestSpec, 
this.responseSpec, transactionDate);
+        Assertions.assertNotNull(clientID);
+
+        final Integer savingsId = 
createSavingsAccountDailyPostingOverdraft(clientID, transactionDate);
+        this.savingsAccountHelper.depositToSavingsAccount(savingsId, "200", 
transactionDate, CommonConstants.RESPONSE_RESOURCE_ID);
+        final String jobName = "Post Interest For Savings";
+        this.scheduleJobHelper.executeAndAwaitJob(jobName);
+        final ResponseSpecification errorResponse = new 
ResponseSpecBuilder().expectStatusCode(403).build();
+        final SavingsAccountHelper validationErrorHelper = new 
SavingsAccountHelper(this.requestSpec, errorResponse);
+        List<HashMap> error = (List<HashMap>) 
validationErrorHelper.depositToSavingsAccount(savingsId, "3000", 
transactionDate,
+                CommonConstants.RESPONSE_ERROR);
+
+        assertEquals("error.msg.savings.transaction.is.not.allowed", 
error.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
+    }
+
+    private Integer createSavingsAccountDailyPostingOverdraft(final Integer 
clientID, final String startDate) {
+        final Integer savingsProductID = 
createSavingsProductDailyPostingOverdraft();
+        Assertions.assertNotNull(savingsProductID);
+        final Integer savingsId = 
this.savingsAccountHelper.applyForSavingsApplicationOnDate(clientID, 
savingsProductID,
+                ACCOUNT_TYPE_INDIVIDUAL, startDate);
+        Assertions.assertNotNull(savingsId);
+        HashMap savingsStatusHashMap = 
this.savingsAccountHelper.approveSavingsOnDate(savingsId, startDate);
+        SavingsStatusChecker.verifySavingsIsApproved(savingsStatusHashMap);
+        savingsStatusHashMap = 
this.savingsAccountHelper.activateSavingsAccount(savingsId, startDate);
+        SavingsStatusChecker.verifySavingsIsActive(savingsStatusHashMap);
+        return savingsId;
+    }
+
+    private Integer createSavingsProductDailyPostingOverdraft() {
+        final String overDraftLimit = "10000.0";
+        final String nominalAnnualInterestRateOverdraft = "10";
+        final String savingsProductJSON = 
this.savingsProductHelper.withInterestCompoundingPeriodTypeAsDaily()
+                
.withInterestPostingPeriodTypeAsDaily().withInterestCalculationPeriodTypeAsDailyBalance()
+                .withOverDraftRate(overDraftLimit, 
nominalAnnualInterestRateOverdraft).build();
+        return SavingsProductHelper.createSavingsProduct(savingsProductJSON, 
requestSpec, responseSpec);
+    }
+
+    public void configurationForBackdatedTransaction() {
+        
GlobalConfigurationHelper.updateEnabledFlagForGlobalConfiguration(this.requestSpec,
 this.responseSpec, "38", false);
+        
GlobalConfigurationHelper.updateEnabledFlagForGlobalConfiguration(this.requestSpec,
 this.responseSpec, "39", true);
+        
GlobalConfigurationHelper.updateValueForGlobalConfiguration(requestSpec, 
responseSpec, "39", "5");
+    }
+
     @AfterEach
     public void tearDown() {
         
GlobalConfigurationHelper.resetAllDefaultGlobalConfigurations(this.requestSpec, 
this.responseSpec);

Reply via email to