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 e4eb8afdf fineract-1652: Account Balance and Transaction running 
balance is wrong
     new d1c77a5e4 Merge pull request #2396 from logoutdhaval/fineract-1652
e4eb8afdf is described below

commit e4eb8afdf41422834ebee955d9164ad6dc5ecbdd
Author: Dhaval Maniyar <[email protected]>
AuthorDate: Thu Jun 30 21:43:21 2022 +0530

    fineract-1652: Account Balance and Transaction running balance is wrong
---
 .../savings/data/SavingsAccountSummaryData.java    | 37 +++++++++----
 .../savings/domain/FixedDepositAccount.java        | 37 +++++++------
 .../savings/domain/RecurringDepositAccount.java    | 28 ++++++----
 .../portfolio/savings/domain/SavingsAccount.java   | 62 ++++++++++++++--------
 .../savings/domain/SavingsAccountAssembler.java    | 17 ++++--
 .../domain/SavingsAccountDomainServiceJpa.java     | 19 ++++---
 .../savings/domain/SavingsAccountSummary.java      | 52 +++++++++++++-----
 .../savings/domain/SavingsAccountTransaction.java  |  7 ++-
 ...countWritePlatformServiceJpaRepositoryImpl.java | 34 +++++++-----
 .../SavingsAccountInterestPostingServiceImpl.java  |  3 +-
 ...countWritePlatformServiceJpaRepositoryImpl.java | 33 ++++++------
 .../service/SavingsSchedularInterestPoster.java    | 24 +++++----
 .../ClientSavingsIntegrationTest.java              | 56 +++++++++++++++++++
 13 files changed, 281 insertions(+), 128 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 e92edaefd..145f3e19f 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
@@ -78,7 +78,7 @@ public class SavingsAccountSummaryData implements 
Serializable {
         this.interestNotPosted = interestNotPosted;
         this.lastInterestCalculationDate = lastInterestCalculationDate;
         this.availableBalance = availableBalance;
-        this.interestPostedTillDate = interestPostedTillDate == null ? 
lastInterestCalculationDate : interestPostedTillDate;
+        this.interestPostedTillDate = interestPostedTillDate;
     }
 
     public void setPrevInterestPostedTillDate(LocalDate 
interestPostedTillDate) {
@@ -152,7 +152,7 @@ public class SavingsAccountSummaryData implements 
Serializable {
     public void updateSummaryWithPivotConfig(final CurrencyData currency, 
final SavingsAccountTransactionSummaryWrapper wrapper,
             final SavingsAccountTransaction transaction, final 
List<SavingsAccountTransactionData> savingsAccountTransactions) {
 
-        if (transaction != null) {
+        if (transaction != null && !transaction.isReversalTransaction()) {
             Money transactionAmount = Money.of(currency, 
transaction.getAmount());
             switch 
(SavingsAccountTransactionType.fromInt(transaction.getTypeOf())) {
                 case DEPOSIT:
@@ -219,15 +219,17 @@ public class SavingsAccountSummaryData implements 
Serializable {
             // boolean isUpdated = false;
             Money interestTotal = Money.of(currency, this.totalInterestPosted);
             Money withHoldTaxTotal = Money.of(currency, this.totalWithholdTax);
-
+            Money overdraftInterestTotal = Money.of(currency, 
this.totalOverdraftInterestDerived);
             final HashMap<String, Money> map = 
updateRunningBalanceAndPivotDate(true, savingsAccountTransactions, 
interestTotal,
-                    withHoldTaxTotal, currency);
+                    overdraftInterestTotal, withHoldTaxTotal, currency);
             interestTotal = map.get("interestTotal");
             withHoldTaxTotal = map.get("withHoldTax");
+            overdraftInterestTotal = map.get("overdraftInterestTotal");
             this.totalInterestPosted = 
interestTotal.getAmountDefaultedToNullIfZero();
             this.totalWithholdTax = 
withHoldTaxTotal.getAmountDefaultedToNullIfZero();
+            this.totalOverdraftInterestDerived = 
overdraftInterestTotal.getAmountDefaultedToNullIfZero();
             this.accountBalance = Money.of(currency, 
this.accountBalance).plus(this.totalInterestPosted).minus(this.totalWithholdTax)
-                    .getAmount();
+                    .minus(this.totalOverdraftInterestDerived).getAmount();
         }
     }
 
@@ -246,13 +248,23 @@ public class SavingsAccountSummaryData implements 
Serializable {
 
     @SuppressWarnings("unchecked")
     private HashMap<String, Money> updateRunningBalanceAndPivotDate(final 
boolean backdatedTxnsAllowedTill,
-            final List<SavingsAccountTransactionData> 
savingsAccountTransactions, Money interestTotal, Money withHoldTaxTotal,
-            CurrencyData currency) {
+            final List<SavingsAccountTransactionData> 
savingsAccountTransactions, Money interestTotal, Money overdraftInterestTotal,
+            Money withHoldTaxTotal, CurrencyData currency) {
         boolean isUpdated = false;
         HashMap<String, Money> map = new HashMap<>();
         for (int i = savingsAccountTransactions.size() - 1; i >= 0; i--) {
             final SavingsAccountTransactionData savingsAccountTransaction = 
savingsAccountTransactions.get(i);
-            if (savingsAccountTransaction.isInterestPostingAndNotReversed() && 
savingsAccountTransaction.isNotReversed() && !isUpdated) {
+            if (savingsAccountTransaction.isInterestPostingAndNotReversed() && 
!savingsAccountTransaction.isReversalTransaction()
+                    && !isUpdated) {
+                
setRunningBalanceOnPivotDate(savingsAccountTransaction.getRunningBalance(currency).getAmount());
+                
setInterestPostedTillDate(savingsAccountTransaction.getTransactionDate());
+                isUpdated = true;
+                if (!backdatedTxnsAllowedTill) {
+                    break;
+                }
+            }
+            if (savingsAccountTransaction.isOverdraftInterestAndNotReversed() 
&& !savingsAccountTransaction.isReversalTransaction()
+                    && !isUpdated) {
                 
setRunningBalanceOnPivotDate(savingsAccountTransaction.getRunningBalance(currency).getAmount());
                 
setInterestPostedTillDate(savingsAccountTransaction.getTransactionDate());
                 isUpdated = true;
@@ -261,10 +273,12 @@ public class SavingsAccountSummaryData implements 
Serializable {
                 }
             }
             if (backdatedTxnsAllowedTill) {
-                if 
(savingsAccountTransaction.isInterestPostingAndNotReversed() && 
savingsAccountTransaction.isNotReversed()) {
+                if 
(savingsAccountTransaction.isInterestPostingAndNotReversed()) {
                     interestTotal = 
interestTotal.plus(savingsAccountTransaction.getAmount());
                 }
-
+                if 
(savingsAccountTransaction.isOverdraftInterestAndNotReversed()) {
+                    overdraftInterestTotal = 
overdraftInterestTotal.plus(savingsAccountTransaction.getAmount());
+                }
                 if (savingsAccountTransaction.isWithHoldTaxAndNotReversed()) {
                     withHoldTaxTotal = 
withHoldTaxTotal.plus(savingsAccountTransaction.getAmount());
                 }
@@ -273,6 +287,7 @@ public class SavingsAccountSummaryData implements 
Serializable {
         if (backdatedTxnsAllowedTill) {
             map.put("interestTotal", interestTotal);
             map.put("withHoldTax", withHoldTaxTotal);
+            map.put("overdraftInterestTotal", overdraftInterestTotal);
         }
         return map;
     }
@@ -293,7 +308,7 @@ public class SavingsAccountSummaryData implements 
Serializable {
         this.totalWithholdTax = 
wrapper.calculateTotalWithholdTaxWithdrawal(currency, transactions);
 
         // boolean isUpdated = false;
-        updateRunningBalanceAndPivotDate(false, transactions, null, null, 
currency);
+        updateRunningBalanceAndPivotDate(false, transactions, null, null, 
null, currency);
 
         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)
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/FixedDepositAccount.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/FixedDepositAccount.java
index 9dff82f57..c03c8f957 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/FixedDepositAccount.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/FixedDepositAccount.java
@@ -191,19 +191,20 @@ public class FixedDepositAccount extends SavingsAccount {
     public void updateMaturityDateAndAmountBeforeAccountActivation(final 
MathContext mc, final boolean isPreMatureClosure,
             final boolean isSavingsInterestPostingAtCurrentPeriodEnd, final 
Integer financialYearBeginningMonth) {
         List<SavingsAccountTransaction> allTransactions = new ArrayList<>();
+        String refNo = null;
         final Money transactionAmountMoney = Money.of(getCurrency(), 
this.accountTermAndPreClosure.depositAmount());
         final SavingsAccountTransaction transaction = 
SavingsAccountTransaction.deposit(null, office(), null,
-                this.accountSubmittedOrActivationDate(), 
transactionAmountMoney, new Date(), null); // TODO:
-                                                                               
                     // verify
-                                                                               
                     // if
-                                                                               
                     // it
-                                                                               
                     // is
-                                                                               
                     // ok
-                                                                               
                     // to
-                                                                               
                     // pass
-                                                                               
                     // null
-                                                                               
                     // for
-                                                                               
                     // AppUser
+                this.accountSubmittedOrActivationDate(), 
transactionAmountMoney, new Date(), null, refNo); // TODO:
+        // verify
+        // if
+        // it
+        // is
+        // ok
+        // to
+        // pass
+        // null
+        // for
+        // AppUser
         transaction.updateRunningBalance(transactionAmountMoney);
         transaction.updateCumulativeBalanceAndDates(this.getCurrency(), 
interestCalculatedUpto());
         allTransactions.add(transaction);
@@ -528,8 +529,10 @@ public class FixedDepositAccount extends SavingsAccount {
         final boolean isInterestTransfer = false;
         final LocalDate postInterestOnDate = null;
         final boolean backdatedTxnsAllowedTill = false;
+        boolean postReversals = false;
         final List<PostingPeriod> postingPeriods = calculateInterestUsing(mc, 
interestPostingUpToDate, isInterestTransfer,
-                isSavingsInterestPostingAtCurrentPeriodEnd, 
financialYearBeginningMonth, postInterestOnDate, backdatedTxnsAllowedTill);
+                isSavingsInterestPostingAtCurrentPeriodEnd, 
financialYearBeginningMonth, postInterestOnDate, backdatedTxnsAllowedTill,
+                postReversals);
 
         Money interestPostedToDate = Money.zero(this.currency);
 
@@ -568,7 +571,7 @@ public class FixedDepositAccount extends SavingsAccount {
         if (recalucateDailyBalanceDetails) {
             // update existing transactions so derived balance fields are
             // correct.
-            recalculateDailyBalances(Money.zero(this.currency), 
interestPostingUpToDate, backdatedTxnsAllowedTill);
+            recalculateDailyBalances(Money.zero(this.currency), 
interestPostingUpToDate, backdatedTxnsAllowedTill, postReversals);
         }
 
         this.summary.updateSummary(this.currency, 
this.savingsAccountTransactionSummaryWrapper, this.transactions);
@@ -597,11 +600,11 @@ public class FixedDepositAccount extends SavingsAccount {
         }
 
         recalucateDailyBalance = 
applyWithholdTaxForDepositAccounts(accountCloseDate, recalucateDailyBalance, 
backdatedTxnsAllowedTill);
-
+        boolean postReversals = false;
         if (recalucateDailyBalance) {
             // update existing transactions so derived balance fields are
             // correct.
-            recalculateDailyBalances(Money.zero(this.currency), 
accountCloseDate, backdatedTxnsAllowedTill);
+            recalculateDailyBalances(Money.zero(this.currency), 
accountCloseDate, backdatedTxnsAllowedTill, postReversals);
         }
         this.summary.updateSummary(this.currency, 
this.savingsAccountTransactionSummaryWrapper, this.transactions);
         
this.accountTermAndPreClosure.updateMaturityDetails(this.getAccountBalance(), 
accountCloseDate);
@@ -651,10 +654,10 @@ public class FixedDepositAccount extends SavingsAccount {
     @Override
     public List<PostingPeriod> calculateInterestUsing(final MathContext mc, 
final LocalDate postingDate, boolean isInterestTransfer,
             final boolean isSavingsInterestPostingAtCurrentPeriodEnd, final 
Integer financialYearBeginningMonth,
-            final LocalDate postAsInterestOn, final boolean 
backdatedTxnsAllowedTill) {
+            final LocalDate postAsInterestOn, final boolean 
backdatedTxnsAllowedTill, final boolean postReversals) {
         final LocalDate interestPostingUpToDate = 
interestPostingUpToDate(postingDate);
         return super.calculateInterestUsing(mc, interestPostingUpToDate, 
isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd,
-                financialYearBeginningMonth, postAsInterestOn, 
backdatedTxnsAllowedTill);
+                financialYearBeginningMonth, postAsInterestOn, 
backdatedTxnsAllowedTill, postReversals);
     }
 
     private LocalDate interestPostingUpToDate(final LocalDate 
interestPostingDate) {
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 6d87fee26..cd28932d4 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
@@ -382,6 +382,7 @@ public class RecurringDepositAccount extends SavingsAccount 
{
                 latestTransactionDate = installment.getTransactionLocalDate();
             }
         }
+        String refNo = null;
         if (generateFutureTransactions) {
             for (RecurringDepositScheduleInstallment installment : 
depositScheduleInstallments()) {
                 if (installment.isPrincipalNotCompleted(getCurrency())) {
@@ -391,7 +392,7 @@ public class RecurringDepositAccount extends SavingsAccount 
{
                     }
                     final SavingsAccountTransaction transaction = 
SavingsAccountTransaction.deposit(null, office(), null, dueDate,
                             
installment.getDepositAmountOutstanding(getCurrency()),
-                            
Date.from(installment.dueDate().atStartOfDay(ZoneId.systemDefault()).toInstant()),
 null);
+                            
Date.from(installment.dueDate().atStartOfDay(ZoneId.systemDefault()).toInstant()),
 null, refNo);
                     allTransactions.add(transaction);
                 }
             }
@@ -542,14 +543,16 @@ public class RecurringDepositAccount extends 
SavingsAccount {
     protected void processAccountUponActivation(final DateTimeFormatter fmt, 
final AppUser user) {
         final Money minRequiredOpeningBalance = Money.of(this.currency, 
this.minRequiredOpeningBalance);
         final boolean backdatedTxnsAllowedTill = false;
+        String refNo = null;
         if (minRequiredOpeningBalance.isGreaterThanZero()) {
             final SavingsAccountTransactionDTO transactionDTO = new 
SavingsAccountTransactionDTO(fmt, getActivationLocalDate(),
                     minRequiredOpeningBalance.getAmount(), null, new Date(), 
user, accountType);
-            deposit(transactionDTO, backdatedTxnsAllowedTill);
+            deposit(transactionDTO, backdatedTxnsAllowedTill, refNo);
 
             // update existing transactions so derived balance fields are
             // correct.
-            recalculateDailyBalances(Money.zero(this.currency), 
DateUtils.getBusinessLocalDate(), backdatedTxnsAllowedTill);
+            boolean postReversals = false;
+            recalculateDailyBalances(Money.zero(this.currency), 
DateUtils.getBusinessLocalDate(), backdatedTxnsAllowedTill, postReversals);
         }
     }
 
@@ -644,8 +647,10 @@ public class RecurringDepositAccount extends 
SavingsAccount {
         boolean isInterestTransfer = false;
         LocalDate postInterestOnDate = null;
         final boolean backdatedTxnsAllowedTill = false;
+        boolean postReversals = false;
         final List<PostingPeriod> postingPeriods = calculateInterestUsing(mc, 
interestPostingUpToDate.minusDays(1), isInterestTransfer,
-                isSavingsInterestPostingAtCurrentPeriodEnd, 
financialYearBeginningMonth, postInterestOnDate, backdatedTxnsAllowedTill);
+                isSavingsInterestPostingAtCurrentPeriodEnd, 
financialYearBeginningMonth, postInterestOnDate, backdatedTxnsAllowedTill,
+                postReversals);
 
         Money interestPostedToDate = Money.zero(this.currency);
 
@@ -681,7 +686,7 @@ public class RecurringDepositAccount extends SavingsAccount 
{
         if (recalucateDailyBalanceDetails) {
             // update existing transactions so derived balance fields are
             // correct.
-            recalculateDailyBalances(Money.zero(this.currency), 
interestPostingUpToDate, backdatedTxnsAllowedTill);
+            recalculateDailyBalances(Money.zero(this.currency), 
interestPostingUpToDate, backdatedTxnsAllowedTill, postReversals);
         }
         this.summary.updateSummary(this.currency, 
this.savingsAccountTransactionSummaryWrapper, this.transactions);
     }
@@ -710,11 +715,11 @@ public class RecurringDepositAccount extends 
SavingsAccount {
         }
 
         applyWithholdTaxForDepositAccounts(accountCloseDate, 
recalucateDailyBalance, backdatedTxnsAllowedTill);
-
+        boolean postReversals = false;
         if (recalucateDailyBalance) {
             // update existing transactions so derived balance fields are
             // correct.
-            recalculateDailyBalances(Money.zero(this.currency), 
accountCloseDate, backdatedTxnsAllowedTill);
+            recalculateDailyBalances(Money.zero(this.currency), 
accountCloseDate, backdatedTxnsAllowedTill, postReversals);
         }
 
         this.summary.updateSummary(this.currency, 
this.savingsAccountTransactionSummaryWrapper, this.transactions);
@@ -764,10 +769,10 @@ public class RecurringDepositAccount extends 
SavingsAccount {
     @Override
     public List<PostingPeriod> calculateInterestUsing(final MathContext mc, 
final LocalDate postingDate, boolean isInterestTransfer,
             final boolean isSavingsInterestPostingAtCurrentPeriodEnd, final 
Integer financialYearBeginningMonth,
-            final LocalDate postAsInterestOn, final boolean 
backdatedTxnsAllowedTill) {
+            final LocalDate postAsInterestOn, final boolean 
backdatedTxnsAllowedTill, final boolean postReversals) {
         final LocalDate interestPostingUpToDate = 
interestPostingUpToDate(postingDate);
         return super.calculateInterestUsing(mc, interestPostingUpToDate, 
isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd,
-                financialYearBeginningMonth, postAsInterestOn, 
backdatedTxnsAllowedTill);
+                financialYearBeginningMonth, postAsInterestOn, 
backdatedTxnsAllowedTill, postReversals);
     }
 
     private LocalDate interestPostingUpToDate(final LocalDate 
interestPostingDate) {
@@ -839,7 +844,8 @@ public class RecurringDepositAccount extends SavingsAccount 
{
     }
 
     @Override
-    public SavingsAccountTransaction deposit(final 
SavingsAccountTransactionDTO transactionDTO, final boolean 
backdatedTxnsAllowedTill) {
+    public SavingsAccountTransaction deposit(final 
SavingsAccountTransactionDTO transactionDTO, final boolean 
backdatedTxnsAllowedTill,
+            final String refNo) {
 
         if (isAccountMatured()) {
             final String defaultUserMessage = "Transaction is not allowed. 
Account is matured.";
@@ -877,7 +883,7 @@ public class RecurringDepositAccount extends SavingsAccount 
{
             throw new PlatformApiDataValidationException(dataValidationErrors);
         }
 
-        final SavingsAccountTransaction transaction = 
super.deposit(transactionDTO, backdatedTxnsAllowedTill);
+        final SavingsAccountTransaction transaction = 
super.deposit(transactionDTO, backdatedTxnsAllowedTill, 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 625f998f3..864840876 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
@@ -514,7 +514,8 @@ public class SavingsAccount extends 
AbstractPersistableCustom {
             final boolean isSavingsInterestPostingAtCurrentPeriodEnd, final 
Integer financialYearBeginningMonth,
             final LocalDate postInterestOnDate, final boolean 
backdatedTxnsAllowedTill, final boolean postReversals) {
         final List<PostingPeriod> postingPeriods = calculateInterestUsing(mc, 
interestPostingUpToDate, isInterestTransfer,
-                isSavingsInterestPostingAtCurrentPeriodEnd, 
financialYearBeginningMonth, postInterestOnDate, backdatedTxnsAllowedTill);
+                isSavingsInterestPostingAtCurrentPeriodEnd, 
financialYearBeginningMonth, postInterestOnDate, backdatedTxnsAllowedTill,
+                postReversals);
 
         Money interestPostedToDate = Money.zero(this.currency);
 
@@ -628,7 +629,7 @@ public class SavingsAccount extends 
AbstractPersistableCustom {
 
             // update existing transactions so derived balance fields are
             // correct.
-            recalculateDailyBalances(openingAccountBalance, 
interestPostingUpToDate, backdatedTxnsAllowedTill);
+            recalculateDailyBalances(openingAccountBalance, 
interestPostingUpToDate, backdatedTxnsAllowedTill, postReversals);
         }
 
         if (!backdatedTxnsAllowedTill) {
@@ -654,7 +655,7 @@ public class SavingsAccount extends 
AbstractPersistableCustom {
         final List<SavingsAccountTransaction> withholdTransactions = new 
ArrayList<>();
         List<SavingsAccountTransaction> trans = 
getSavingsAccountTransactionsWithPivotConfig();
         for (final SavingsAccountTransaction transaction : trans) {
-            if (transaction.isWithHoldTaxAndNotReversed()) {
+            if (transaction.isWithHoldTaxAndNotReversed() && 
!transaction.isReversalTransaction()) {
                 withholdTransactions.add(transaction);
             }
         }
@@ -670,7 +671,7 @@ public class SavingsAccount extends 
AbstractPersistableCustom {
         List<SavingsAccountTransaction> trans = getTransactions();
         for (final SavingsAccountTransaction transaction : trans) {
             if ((transaction.isInterestPostingAndNotReversed() || 
transaction.isOverdraftInterestAndNotReversed())
-                    && transaction.occursOn(postingDate)) {
+                    && transaction.occursOn(postingDate) && 
!transaction.isReversalTransaction()) {
                 postingTransation = transaction;
                 break;
             }
@@ -683,7 +684,7 @@ public class SavingsAccount extends 
AbstractPersistableCustom {
         List<SavingsAccountTransaction> trans = 
getSavingsAccountTransactionsWithPivotConfig();
         for (final SavingsAccountTransaction transaction : trans) {
             if ((transaction.isInterestPostingAndNotReversed() || 
transaction.isOverdraftInterestAndNotReversed())
-                    && transaction.occursOn(postingDate)) {
+                    && transaction.occursOn(postingDate) && 
!transaction.isReversalTransaction()) {
                 postingTransation = transaction;
                 break;
             }
@@ -810,7 +811,7 @@ public class SavingsAccount extends 
AbstractPersistableCustom {
 
     public List<PostingPeriod> calculateInterestUsing(final MathContext mc, 
final LocalDate upToInterestCalculationDate,
             boolean isInterestTransfer, final boolean 
isSavingsInterestPostingAtCurrentPeriodEnd, final Integer 
financialYearBeginningMonth,
-            final LocalDate postInterestOnDate, final boolean 
backdatedTxnsAllowedTill) {
+            final LocalDate postInterestOnDate, final boolean 
backdatedTxnsAllowedTill, final boolean postReversals) {
 
         // no openingBalance concept supported yet but probably will to allow
         // for migrations.
@@ -825,7 +826,8 @@ public class SavingsAccount extends 
AbstractPersistableCustom {
 
         // update existing transactions so derived balance fields are
         // correct.
-        recalculateDailyBalances(openingAccountBalance, 
upToInterestCalculationDate, backdatedTxnsAllowedTill);
+
+        recalculateDailyBalances(openingAccountBalance, 
upToInterestCalculationDate, backdatedTxnsAllowedTill, postReversals);
 
         // 1. default to calculate interest based on entire history OR
         // 2. determine latest 'posting period' and find interest credited to
@@ -931,7 +933,7 @@ public class SavingsAccount extends 
AbstractPersistableCustom {
 
         for (final SavingsAccountTransaction transaction : 
listOfTransactionsSorted) {
             if (!(transaction.isInterestPostingAndNotReversed() || 
transaction.isOverdraftInterestAndNotReversed())
-                    && transaction.isNotReversed()) {
+                    && transaction.isNotReversed() && 
!transaction.isReversalTransaction()) {
                 orderedNonInterestPostingTransactions.add(transaction);
             }
         }
@@ -946,7 +948,7 @@ public class SavingsAccount extends 
AbstractPersistableCustom {
 
         for (final SavingsAccountTransaction transaction : 
listOfTransactionsSorted) {
             if (!(transaction.isInterestPostingAndNotReversed() || 
transaction.isOverdraftInterestAndNotReversed())
-                    && transaction.isNotReversed()) {
+                    && transaction.isNotReversed() && 
!transaction.isReversalTransaction()) {
                 orderedNonInterestPostingTransactions.add(transaction);
             }
         }
@@ -972,7 +974,7 @@ public class SavingsAccount extends 
AbstractPersistableCustom {
     }
 
     protected void recalculateDailyBalances(final Money openingAccountBalance, 
final LocalDate interestPostingUpToDate,
-            final boolean backdatedTxnsAllowedTill) {
+            final boolean backdatedTxnsAllowedTill, boolean postReversals) {
 
         Money runningBalance = openingAccountBalance.copy();
 
@@ -1026,15 +1028,25 @@ public class SavingsAccount extends 
AbstractPersistableCustom {
                                 
.add(SavingsAccountChargePaidBy.instance(accountTransaction, 
x.getSavingsAccountCharge(), x.getAmount())));
                         
accountTransaction.getSavingsAccountChargesPaid().addAll(newChargePaidBy);
                     }
+                    SavingsAccountTransaction reversal = null;
                     transaction.reverse();
+                    if (postReversals) {
+                        reversal = 
SavingsAccountTransaction.reversal(transaction);
+                    }
                     if (overdraftAmount.isGreaterThanZero()) {
                         
accountTransaction.updateOverdraftAmount(overdraftAmount.getAmount());
                     }
                     // accountTransaction.updateRunningBalance(runningBalance);
                     if (backdatedTxnsAllowedTill) {
                         addTransactionToExisting(accountTransaction);
+                        if (reversal != null) {
+                            addTransactionToExisting(reversal);
+                        }
                     } else {
                         addTransaction(accountTransaction);
+                        if (reversal != null) {
+                            addTransaction(reversal);
+                        }
                     }
                     isTransactionsModified = true;
                 }
@@ -1058,7 +1070,7 @@ public class SavingsAccount extends 
AbstractPersistableCustom {
         LocalDate endOfBalanceDate = interestPostingUpToDate;
         for (int i = accountTransactionsSorted.size() - 1; i >= 0; i--) {
             final SavingsAccountTransaction transaction = 
accountTransactionsSorted.get(i);
-            if (transaction.isNotReversed()
+            if (transaction.isNotReversed() && 
!transaction.isReversalTransaction()
                     && !(transaction.isInterestPostingAndNotReversed() || 
transaction.isOverdraftInterestAndNotReversed())) {
                 transaction.updateCumulativeBalanceAndDates(this.currency, 
endOfBalanceDate);
                 // this transactions transaction date is end of balance date 
for
@@ -1068,17 +1080,19 @@ public class SavingsAccount extends 
AbstractPersistableCustom {
         }
     }
 
-    public SavingsAccountTransaction deposit(final 
SavingsAccountTransactionDTO transactionDTO, final boolean 
backdatedTxnsAllowedTill) {
-        return deposit(transactionDTO, SavingsAccountTransactionType.DEPOSIT, 
backdatedTxnsAllowedTill);
+    public SavingsAccountTransaction deposit(final 
SavingsAccountTransactionDTO transactionDTO, final boolean 
backdatedTxnsAllowedTill,
+            final String refNo) {
+        return deposit(transactionDTO, SavingsAccountTransactionType.DEPOSIT, 
backdatedTxnsAllowedTill, refNo);
     }
 
     public SavingsAccountTransaction dividendPayout(final 
SavingsAccountTransactionDTO transactionDTO,
             final boolean backdatedTxnsAllowedTill) {
-        return deposit(transactionDTO, 
SavingsAccountTransactionType.DIVIDEND_PAYOUT, backdatedTxnsAllowedTill);
+        String refNo = null;
+        return deposit(transactionDTO, 
SavingsAccountTransactionType.DIVIDEND_PAYOUT, backdatedTxnsAllowedTill, refNo);
     }
 
     public SavingsAccountTransaction deposit(final 
SavingsAccountTransactionDTO transactionDTO,
-            final SavingsAccountTransactionType savingsAccountTransactionType, 
final boolean backdatedTxnsAllowedTill) {
+            final SavingsAccountTransactionType savingsAccountTransactionType, 
final boolean backdatedTxnsAllowedTill, final String refNo) {
         final String resourceTypeName = depositAccountType().resourceName();
         if (isNotActive()) {
             final String defaultUserMessage = "Transaction is not allowed. 
Account is not active.";
@@ -1122,7 +1136,7 @@ public class SavingsAccount extends 
AbstractPersistableCustom {
 
         final SavingsAccountTransaction transaction = 
SavingsAccountTransaction.deposit(this, office(), 
transactionDTO.getPaymentDetail(),
                 transactionDTO.getTransactionDate(), amount, 
transactionDTO.getCreatedDate(), transactionDTO.getAppUser(),
-                savingsAccountTransactionType);
+                savingsAccountTransactionType, refNo);
 
         if (backdatedTxnsAllowedTill) {
             addTransactionToExisting(transaction);
@@ -1251,6 +1265,10 @@ public class SavingsAccount extends 
AbstractPersistableCustom {
                 || 
this.sub_status.equals(SavingsAccountSubStatusEnum.DORMANT.getValue())) {
             this.sub_status = SavingsAccountSubStatusEnum.NONE.getValue();
         }
+        if (backdatedTxnsAllowedTill) {
+            this.summary.updateSummaryWithPivotConfig(this.currency, 
this.savingsAccountTransactionSummaryWrapper, transaction,
+                    this.savingsAccountTransactions);
+        }
         return transaction;
     }
 
@@ -1375,7 +1393,7 @@ public class SavingsAccount extends 
AbstractPersistableCustom {
         if (!backdatedTxnsAllowedTill) {
             for (final SavingsAccountTransaction transaction : 
retreiveListOfTransactions()) {
                 if ((transaction.isInterestPostingAndNotReversed() || 
transaction.isOverdraftInterestAndNotReversed())
-                        && transaction.isAfter(transactionDate)) {
+                        && transaction.isAfter(transactionDate) && 
!transaction.isReversalTransaction()) {
                     transactionBeforeLastInterestPosting = true;
                     break;
                 }
@@ -2760,15 +2778,15 @@ public class SavingsAccount extends 
AbstractPersistableCustom {
             final MathContext mc = MathContext.DECIMAL64;
             boolean isInterestTransfer = false;
             LocalDate postInterestAsOnDate = null;
+            boolean postReversals = false;
             if (this.isBeforeLastPostingPeriod(getActivationLocalDate(), 
backdatedTxnsAllowedTill)) {
                 final LocalDate today = DateUtils.getBusinessLocalDate();
-                boolean postReversals = false;
                 this.postInterest(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth,
                         postInterestAsOnDate, backdatedTxnsAllowedTill, 
postReversals);
             } else {
                 final LocalDate today = DateUtils.getBusinessLocalDate();
                 this.calculateInterestUsing(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd,
-                        financialYearBeginningMonth, postInterestAsOnDate, 
backdatedTxnsAllowedTill);
+                        financialYearBeginningMonth, postInterestAsOnDate, 
backdatedTxnsAllowedTill, postReversals);
             }
         }
     }
@@ -3513,7 +3531,8 @@ public class SavingsAccount extends 
AbstractPersistableCustom {
                         refNo.toString());
             }
         }
-        recalculateDailyBalances(Money.zero(this.currency), transactionDate, 
backdatedTxnsAllowedTill);
+        boolean postReversals = false;
+        recalculateDailyBalances(Money.zero(this.currency), transactionDate, 
backdatedTxnsAllowedTill, postReversals);
         this.summary.updateSummary(this.currency, 
this.savingsAccountTransactionSummaryWrapper, this.transactions);
     }
 
@@ -3532,7 +3551,8 @@ public class SavingsAccount extends 
AbstractPersistableCustom {
             SavingsAccountTransaction transaction = 
SavingsAccountTransaction.escheat(this, transactionDate, appUser, 
postInterestAsOnDate);
             this.transactions.add(transaction);
         }
-        recalculateDailyBalances(Money.zero(this.currency), transactionDate, 
false);
+        boolean postReversals = false;
+        recalculateDailyBalances(Money.zero(this.currency), transactionDate, 
false, postReversals);
         this.summary.updateSummary(this.currency, 
this.savingsAccountTransactionSummaryWrapper, this.transactions);
     }
 
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 de98a78e3..f5418f3a9 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
@@ -361,6 +361,11 @@ 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);
@@ -368,10 +373,11 @@ public class SavingsAccountAssembler {
         }
 
         // Update last running balance on account level
-        if (savingsAccountTransactions != null) {
-            
account.getSummary().setRunningBalanceOnPivotDate(savingsAccountTransactions.get(savingsAccountTransactions.size()
 - 1)
-                    .getRunningBalance(account.getCurrency()).getAmount());
-        }
+        // 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;
@@ -380,7 +386,8 @@ public class SavingsAccountAssembler {
     public SavingsAccountData assembleSavings(final SavingsAccountData 
account) {
 
         // Update last running balance on account level
-        if (account.getTransactions() != null && 
account.getTransactions().size() != 0) {
+        if (account.getTransactions() != null && 
account.getTransactions().size() != 0
+                && account.getSummary().getInterestPostedTillDate() != null) {
             
account.getSummary().setRunningBalanceOnPivotDate(account.getTransactions().get(account.getTransactions().size()
 - 1)
                     .getRunningBalance(account.getCurrency()).getAmount());
         }
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 29dbc4ce7..142605ee1 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
@@ -115,13 +115,14 @@ public class SavingsAccountDomainServiceJpa implements 
SavingsAccountDomainServi
         final MathContext mc = MathContext.DECIMAL64;
 
         final LocalDate today = DateUtils.getBusinessLocalDate();
+        boolean postReversals = false;
         if (account.isBeforeLastPostingPeriod(transactionDate, 
backdatedTxnsAllowedTill)) {
-            boolean postReversals = false;
             account.postInterest(mc, today, 
transactionBooleanValues.isInterestTransfer(), 
isSavingsInterestPostingAtCurrentPeriodEnd,
                     financialYearBeginningMonth, postInterestOnDate, 
backdatedTxnsAllowedTill, postReversals);
         } else {
             account.calculateInterestUsing(mc, today, 
transactionBooleanValues.isInterestTransfer(),
-                    isSavingsInterestPostingAtCurrentPeriodEnd, 
financialYearBeginningMonth, postInterestOnDate, backdatedTxnsAllowedTill);
+                    isSavingsInterestPostingAtCurrentPeriodEnd, 
financialYearBeginningMonth, postInterestOnDate, backdatedTxnsAllowedTill,
+                    postReversals);
         }
 
         List<DepositAccountOnHoldTransaction> depositAccountOnHoldTransactions 
= null;
@@ -191,18 +192,20 @@ public class SavingsAccountDomainServiceJpa implements 
SavingsAccountDomainServi
         Integer accountType = null;
         final SavingsAccountTransactionDTO transactionDTO = new 
SavingsAccountTransactionDTO(fmt, transactionDate, transactionAmount,
                 paymentDetail, new Date(), user, accountType);
-        final SavingsAccountTransaction deposit = 
account.deposit(transactionDTO, savingsAccountTransactionType, 
backdatedTxnsAllowedTill);
+        UUID refNo = UUID.randomUUID();
+        final SavingsAccountTransaction deposit = 
account.deposit(transactionDTO, savingsAccountTransactionType, 
backdatedTxnsAllowedTill,
+                refNo.toString());
         final LocalDate postInterestOnDate = null;
         final MathContext mc = MathContext.DECIMAL64;
 
         final LocalDate today = DateUtils.getBusinessLocalDate();
+        boolean postReversals = false;
         if (account.isBeforeLastPostingPeriod(transactionDate, 
backdatedTxnsAllowedTill)) {
-            boolean postReversals = false;
             account.postInterest(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth,
                     postInterestOnDate, backdatedTxnsAllowedTill, 
postReversals);
         } else {
             account.calculateInterestUsing(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd,
-                    financialYearBeginningMonth, postInterestOnDate, 
backdatedTxnsAllowedTill);
+                    financialYearBeginningMonth, postInterestOnDate, 
backdatedTxnsAllowedTill, postReversals);
         }
 
         saveTransactionToGenerateTransactionId(deposit);
@@ -316,20 +319,22 @@ public class SavingsAccountDomainServiceJpa implements 
SavingsAccountDomainServi
         final LocalDate today = DateUtils.getBusinessLocalDate();
         final MathContext mc = new MathContext(15, 
MoneyHelper.getRoundingMode());
         for (SavingsAccountTransaction savingsAccountTransaction : 
savingsAccountTransactions) {
+            boolean postReversals = true;
             if (savingsAccountTransaction.isPostInterestCalculationRequired()
                     && 
account.isBeforeLastPostingPeriod(savingsAccountTransaction.transactionLocalDate(),
 backdatedTxnsAllowedTill)) {
-                boolean postReversals = true;
+
                 account.postInterest(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth,
                         postInterestOnDate, backdatedTxnsAllowedTill, 
postReversals);
             } else {
                 account.calculateInterestUsing(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd,
-                        financialYearBeginningMonth, postInterestOnDate, 
backdatedTxnsAllowedTill);
+                        financialYearBeginningMonth, postInterestOnDate, 
backdatedTxnsAllowedTill, postReversals);
             }
 
             
account.validateAccountBalanceDoesNotBecomeNegativeMinimal(savingsAccountTransaction.getAmount(),
 false);
             account.activateAccountBasedOnBalance();
         }
         this.savingsAccountRepository.save(account);
+        
newTransactions.addAll(account.getSavingsAccountTransactionsWithPivotConfig());
         this.savingsAccountTransactionRepository.saveAll(newTransactions);
         postJournalEntries(account, existingTransactionIds, 
existingReversedTransactionIds, false, backdatedTxnsAllowedTill);
 
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 82d105de1..a234186b6 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
@@ -113,7 +113,7 @@ public final class SavingsAccountSummary {
         this.totalWithholdTax = 
wrapper.calculateTotalWithholdTaxWithdrawal(currency, transactions);
 
         // boolean isUpdated = false;
-        updateRunningBalanceAndPivotDate(false, transactions, null, null, 
currency);
+        updateRunningBalanceAndPivotDate(false, transactions, null, null, 
null, currency);
 
         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)
@@ -189,30 +189,53 @@ public final class SavingsAccountSummary {
             }
         } else {
             // boolean isUpdated = false;
-            Money interestTotal = Money.of(currency, this.totalInterestPosted);
-            Money withHoldTaxTotal = Money.of(currency, this.totalWithholdTax);
-
+            Money interestTotal = Money.zero(currency);
+            Money withHoldTaxTotal = Money.zero(currency);
+            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,
-                    withHoldTaxTotal, currency);
+                    overdraftInterestTotal, withHoldTaxTotal, currency);
             interestTotal = map.get("interestTotal");
             withHoldTaxTotal = map.get("withHoldTax");
+            overdraftInterestTotal = map.get("overdraftInterestTotal");
             this.totalInterestPosted = 
interestTotal.getAmountDefaultedToNullIfZero();
+            this.totalOverdraftInterestDerived = 
overdraftInterestTotal.getAmountDefaultedToNullIfZero();
             this.totalWithholdTax = 
withHoldTaxTotal.getAmountDefaultedToNullIfZero();
-            this.accountBalance = Money.of(currency, 
this.accountBalance).plus(this.totalInterestPosted).minus(this.totalWithholdTax)
-                    .getAmount();
+            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();
         }
     }
 
     @SuppressWarnings("unchecked")
     private HashMap<String, Money> updateRunningBalanceAndPivotDate(final 
boolean backdatedTxnsAllowedTill,
-            final List<SavingsAccountTransaction> savingsAccountTransactions, 
Money interestTotal, Money withHoldTaxTotal,
-            MonetaryCurrency currency) {
+            final List<SavingsAccountTransaction> savingsAccountTransactions, 
Money interestTotal, Money overdraftInterestTotal,
+            Money withHoldTaxTotal, MonetaryCurrency currency) {
         boolean isUpdated = false;
         HashMap<String, Money> map = new HashMap<>();
         for (int i = savingsAccountTransactions.size() - 1; i >= 0; i--) {
             final SavingsAccountTransaction savingsAccountTransaction = 
savingsAccountTransactions.get(i);
-            if (savingsAccountTransaction.isInterestPostingAndNotReversed() && 
savingsAccountTransaction.isNotReversed()
-                    && !savingsAccountTransaction.isReversalTransaction() && 
!isUpdated) {
+            if (savingsAccountTransaction.isInterestPostingAndNotReversed() && 
!savingsAccountTransaction.isReversalTransaction()
+                    && !isUpdated) {
+                
setRunningBalanceOnPivotDate(savingsAccountTransaction.getRunningBalance(currency).getAmount());
+                
setInterestPostedTillDate(savingsAccountTransaction.getLastTransactionDate());
+                isUpdated = true;
+                if (!backdatedTxnsAllowedTill) {
+                    break;
+                }
+            }
+            if (savingsAccountTransaction.isOverdraftInterestAndNotReversed() 
&& !savingsAccountTransaction.isReversalTransaction()
+                    && !isUpdated) {
                 
setRunningBalanceOnPivotDate(savingsAccountTransaction.getRunningBalance(currency).getAmount());
                 
setInterestPostedTillDate(savingsAccountTransaction.getLastTransactionDate());
                 isUpdated = true;
@@ -225,8 +248,10 @@ public final class SavingsAccountSummary {
                         && !savingsAccountTransaction.isReversalTransaction()) 
{
                     interestTotal = 
interestTotal.plus(savingsAccountTransaction.getAmount(currency));
                 }
-
-                if (savingsAccountTransaction.isWithHoldTaxAndNotReversed()) {
+                if 
(savingsAccountTransaction.isOverdraftInterestAndNotReversed() && 
!savingsAccountTransaction.isReversalTransaction()) {
+                    overdraftInterestTotal = 
overdraftInterestTotal.plus(savingsAccountTransaction.getAmount());
+                }
+                if (savingsAccountTransaction.isWithHoldTaxAndNotReversed() && 
!savingsAccountTransaction.isReversalTransaction()) {
                     withHoldTaxTotal = 
withHoldTaxTotal.plus(savingsAccountTransaction.getAmount(currency));
                 }
             }
@@ -234,6 +259,7 @@ public final class SavingsAccountSummary {
         if (backdatedTxnsAllowedTill) {
             map.put("interestTotal", interestTotal);
             map.put("withHoldTax", withHoldTaxTotal);
+            map.put("overdraftInterestTotal", overdraftInterestTotal);
         }
         return map;
     }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransaction.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransaction.java
index 3362d4ebe..861aa465a 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransaction.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransaction.java
@@ -153,22 +153,21 @@ public final class SavingsAccountTransaction extends 
AbstractPersistableCustom {
     }
 
     public static SavingsAccountTransaction deposit(final SavingsAccount 
savingsAccount, final Office office,
-            final PaymentDetail paymentDetail, final LocalDate date, final 
Money amount, Date createdDate, final AppUser appUser) {
+            final PaymentDetail paymentDetail, final LocalDate date, final 
Money amount, Date createdDate, final AppUser appUser,
+            final String refNo) {
         final boolean isReversed = false;
         final boolean isManualTransaction = false;
         final Boolean lienTransaction = false;
-        final String refNo = null;
         return new SavingsAccountTransaction(savingsAccount, office, 
paymentDetail, SavingsAccountTransactionType.DEPOSIT.getValue(), date,
                 createdDate, amount, isReversed, appUser, isManualTransaction, 
lienTransaction, refNo);
     }
 
     public static SavingsAccountTransaction deposit(final SavingsAccount 
savingsAccount, final Office office,
             final PaymentDetail paymentDetail, final LocalDate date, final 
Money amount, Date createdDate, final AppUser appUser,
-            final SavingsAccountTransactionType savingsAccountTransactionType) 
{
+            final SavingsAccountTransactionType savingsAccountTransactionType, 
final String refNo) {
         final boolean isReversed = false;
         final boolean isManualTransaction = false;
         final Boolean lienTransaction = false;
-        final String refNo = null;
         return new SavingsAccountTransaction(savingsAccount, office, 
paymentDetail, savingsAccountTransactionType.getValue(), date,
                 createdDate, amount, isReversed, appUser, isManualTransaction, 
lienTransaction, refNo);
     }
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 c7667bb1c..353070900 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
@@ -239,6 +239,7 @@ public class 
DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
                 }
                 final boolean isInterestTransfer = false;
                 final LocalDate postInterestOnDate = null;
+                final boolean postReversals = false;
                 if (activationChargeAmount.isGreaterThanZero()) {
                     payActivationCharge(account, user);
                 }
@@ -249,7 +250,7 @@ public class 
DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
                 } else {
                     final LocalDate today = DateUtils.getBusinessLocalDate();
                     account.calculateInterestUsing(mc, today, 
isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd,
-                            financialYearBeginningMonth, postInterestOnDate, 
false);
+                            financialYearBeginningMonth, postInterestOnDate, 
false, postReversals);
                 }
 
                 updateExistingTransactionsDetails(account, 
existingTransactionIds, existingReversedTransactionIds);
@@ -366,6 +367,7 @@ public class 
DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
             account.updateOverduePayments(overdueUptoDate);
             final boolean isInterestTransfer = false;
             final LocalDate postInterestOnDate = null;
+            boolean postReversals = false;
             if 
(account.isBeforeLastPostingPeriod(account.getActivationLocalDate(), false)) {
                 final LocalDate today = DateUtils.getBusinessLocalDate();
                 account.postInterest(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth,
@@ -373,7 +375,7 @@ public class 
DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
             } else {
                 final LocalDate today = DateUtils.getBusinessLocalDate();
                 account.calculateInterestUsing(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd,
-                        financialYearBeginningMonth, postInterestOnDate, 
false);
+                        financialYearBeginningMonth, postInterestOnDate, 
false, postReversals);
             }
             List<DepositAccountOnHoldTransaction> 
depositAccountOnHoldTransactions = null;
             if (account.getOnHoldFunds().compareTo(BigDecimal.ZERO) > 0) {
@@ -521,11 +523,12 @@ public class 
DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
         checkClientOrGroupActive(account);
 
         final LocalDate today = DateUtils.getBusinessLocalDate();
+        boolean postReversals = false;
         final MathContext mc = new MathContext(15, 
MoneyHelper.getRoundingMode());
         boolean isInterestTransfer = false;
         LocalDate postInterestOnDate = null;
         account.calculateInterestUsing(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd,
-                financialYearBeginningMonth, postInterestOnDate, false);
+                financialYearBeginningMonth, postInterestOnDate, false, 
postReversals);
 
         this.savingAccountRepositoryWrapper.save(account);
 
@@ -643,13 +646,14 @@ public class 
DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
         boolean isInterestTransfer = false;
         LocalDate postInterestOnDate = null;
         checkClientOrGroupActive(account);
+        boolean postReversals = false;
         if (savingsAccountTransaction.isPostInterestCalculationRequired()
                 && 
account.isBeforeLastPostingPeriod(savingsAccountTransaction.transactionLocalDate(),
 false)) {
             account.postInterest(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth,
                     postInterestOnDate, false);
         } else {
             account.calculateInterestUsing(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd,
-                    financialYearBeginningMonth, postInterestOnDate, false);
+                    financialYearBeginningMonth, postInterestOnDate, false, 
postReversals);
         }
         List<DepositAccountOnHoldTransaction> depositAccountOnHoldTransactions 
= null;
         if (account.getOnHoldFunds().compareTo(BigDecimal.ZERO) > 0) {
@@ -746,7 +750,7 @@ public class 
DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
         if (savingsAccountTransaction.isDeposit()) {
             final SavingsAccountTransactionDTO transactionDTO = new 
SavingsAccountTransactionDTO(fmt, transactionDate, transactionAmount,
                     paymentDetail, savingsAccountTransaction.createdDate(), 
user, accountType);
-            transaction = account.deposit(transactionDTO, false);
+            transaction = account.deposit(transactionDTO, false, 
refNo.toString());
         } else {
             final SavingsAccountTransactionDTO transactionDTO = new 
SavingsAccountTransactionDTO(fmt, transactionDate, transactionAmount,
                     paymentDetail, savingsAccountTransaction.createdDate(), 
user, accountType);
@@ -755,13 +759,14 @@ public class 
DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
         final Long newtransactionId = 
saveTransactionToGenerateTransactionId(transaction);
         boolean isInterestTransfer = false;
         final LocalDate postInterestOnDate = null;
+        boolean postReversals = false;
         if (account.isBeforeLastPostingPeriod(transactionDate, false)
                 || 
account.isBeforeLastPostingPeriod(savingsAccountTransaction.transactionLocalDate(),
 false)) {
             account.postInterest(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth,
                     postInterestOnDate, false);
         } else {
             account.calculateInterestUsing(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd,
-                    financialYearBeginningMonth, postInterestOnDate, false);
+                    financialYearBeginningMonth, postInterestOnDate, false, 
postReversals);
         }
         List<DepositAccountOnHoldTransaction> depositAccountOnHoldTransactions 
= null;
         if (account.getOnHoldFunds().compareTo(BigDecimal.ZERO) > 0) {
@@ -983,8 +988,9 @@ public class 
DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
         
savingsAccount.setStatus(SavingsAccountStatusType.TRANSFER_IN_PROGRESS.getValue());
         final MathContext mc = MathContext.DECIMAL64;
         boolean isInterestTransfer = false;
+        boolean postReversals = false;
         savingsAccount.calculateInterestUsing(mc, transferDate, 
isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd,
-                financialYearBeginningMonth, postInterestOnDate, false);
+                financialYearBeginningMonth, postInterestOnDate, false, 
postReversals);
 
         this.savingsAccountTransactionRepository.save(newTransferTransaction);
         this.savingAccountRepositoryWrapper.saveAndFlush(savingsAccount);
@@ -1014,11 +1020,12 @@ public class 
DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
                 savingsAccount.office(), transferDate, user);
         savingsAccount.addTransaction(withdrawtransferTransaction);
         savingsAccount.setStatus(SavingsAccountStatusType.ACTIVE.getValue());
+        boolean postReversals = false;
         final MathContext mc = MathContext.DECIMAL64;
         boolean isInterestTransfer = false;
         LocalDate postInterestOnDate = null;
         savingsAccount.calculateInterestUsing(mc, transferDate, 
isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd,
-                financialYearBeginningMonth, postInterestOnDate, false);
+                financialYearBeginningMonth, postInterestOnDate, false, 
postReversals);
 
         
this.savingsAccountTransactionRepository.save(withdrawtransferTransaction);
         this.savingAccountRepositoryWrapper.saveAndFlush(savingsAccount);
@@ -1059,10 +1066,11 @@ public class 
DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
             savingsAccount.reassignSavingsOfficer(fieldOfficer, transferDate);
         }
         boolean isInterestTransfer = false;
+        boolean postReversals = false;
         LocalDate postInterestOnDate = null;
         final MathContext mc = MathContext.DECIMAL64;
         savingsAccount.calculateInterestUsing(mc, transferDate, 
isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd,
-                financialYearBeginningMonth, postInterestOnDate, false);
+                financialYearBeginningMonth, postInterestOnDate, false, 
postReversals);
 
         
this.savingsAccountTransactionRepository.save(acceptTransferTransaction);
         this.savingAccountRepositoryWrapper.saveAndFlush(savingsAccount);
@@ -1215,15 +1223,15 @@ public class 
DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
         boolean isInterestTransfer = false;
         LocalDate postInterestOnDate = null;
         final MathContext mc = MathContext.DECIMAL64;
+        boolean postReversals = false;
         if 
(account.isBeforeLastPostingPeriod(savingsAccountCharge.getDueLocalDate(), 
false)) {
             final LocalDate today = DateUtils.getBusinessLocalDate();
-            boolean postReversals = false;
             account.postInterest(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth,
                     postInterestOnDate, false, postReversals);
         } else {
             final LocalDate today = DateUtils.getBusinessLocalDate();
             account.calculateInterestUsing(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd,
-                    financialYearBeginningMonth, postInterestOnDate, false);
+                    financialYearBeginningMonth, postInterestOnDate, false, 
postReversals);
         }
         List<DepositAccountOnHoldTransaction> depositAccountOnHoldTransactions 
= null;
         if (account.getOnHoldFunds().compareTo(BigDecimal.ZERO) > 0) {
@@ -1355,15 +1363,15 @@ public class 
DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
         boolean isInterestTransfer = false;
         LocalDate postInterestOnDate = null;
         final MathContext mc = MathContext.DECIMAL64;
+        boolean postReversals = false;
         if (account.isBeforeLastPostingPeriod(transactionDate, false)) {
             final LocalDate today = DateUtils.getBusinessLocalDate();
-            boolean postReversals = false;
             account.postInterest(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth,
                     postInterestOnDate, false, postReversals);
         } else {
             final LocalDate today = DateUtils.getBusinessLocalDate();
             account.calculateInterestUsing(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd,
-                    financialYearBeginningMonth, postInterestOnDate, false);
+                    financialYearBeginningMonth, postInterestOnDate, false, 
postReversals);
         }
         List<DepositAccountOnHoldTransaction> depositAccountOnHoldTransactions 
= null;
         if (account.getOnHoldFunds().compareTo(BigDecimal.ZERO) > 0) {
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountInterestPostingServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountInterestPostingServiceImpl.java
index 74a19d350..eed7393bb 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountInterestPostingServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountInterestPostingServiceImpl.java
@@ -422,11 +422,10 @@ public class SavingsAccountInterestPostingServiceImpl 
implements SavingsAccountI
         Money runningBalance = openingAccountBalance.copy();
 
         List<SavingsAccountTransactionData> accountTransactionsSorted = 
retreiveListOfTransactions(savingsAccountData);
-
         boolean isTransactionsModified = false;
 
         for (final SavingsAccountTransactionData transaction : 
accountTransactionsSorted) {
-            if (transaction.isReversed()) {
+            if (transaction.isReversed() || 
transaction.isReversalTransaction()) {
                 transaction.zeroBalanceFields();
             } else {
                 Money overdraftAmount = 
Money.zero(savingsAccountData.currency());
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 6f9d473fc..d22c85534 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
@@ -515,9 +515,9 @@ public class 
SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
         final MathContext mc = new MathContext(15, 
MoneyHelper.getRoundingMode());
         boolean isInterestTransfer = false;
         final LocalDate postInterestOnDate = null;
-
+        boolean postReversals = false;
         account.calculateInterestUsing(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd,
-                financialYearBeginningMonth, postInterestOnDate, 
backdatedTxnsAllowedTill);
+                financialYearBeginningMonth, postInterestOnDate, 
backdatedTxnsAllowedTill, postReversals);
 
         if (backdatedTxnsAllowedTill) {
             
this.savingsAccountTransactionRepository.saveAll(account.getSavingsAccountTransactionsWithPivotConfig());
@@ -787,15 +787,15 @@ public class 
SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
         }
         boolean isInterestTransfer = false;
         LocalDate postInterestOnDate = null;
+        boolean postReversals = false;
         checkClientOrGroupActive(account);
         if (savingsAccountTransaction.isPostInterestCalculationRequired()
                 && 
account.isBeforeLastPostingPeriod(savingsAccountTransaction.transactionLocalDate(),
 false)) {
-            boolean postReversals = false;
             account.postInterest(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth,
                     postInterestOnDate, false, postReversals);
         } else {
             account.calculateInterestUsing(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd,
-                    financialYearBeginningMonth, postInterestOnDate, false);
+                    financialYearBeginningMonth, postInterestOnDate, false, 
postReversals);
         }
         List<DepositAccountOnHoldTransaction> depositAccountOnHoldTransactions 
= null;
         if (account.getOnHoldFunds().compareTo(BigDecimal.ZERO) > 0) {
@@ -882,22 +882,22 @@ public class 
SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
         Integer accountType = null;
         final SavingsAccountTransactionDTO transactionDTO = new 
SavingsAccountTransactionDTO(fmt, transactionDate, transactionAmount,
                 paymentDetail, savingsAccountTransaction.createdDate(), user, 
accountType);
+        UUID refNo = UUID.randomUUID();
         if (savingsAccountTransaction.isDeposit()) {
-            transaction = account.deposit(transactionDTO, false);
+            transaction = account.deposit(transactionDTO, false, 
refNo.toString());
         } else {
-            UUID refNo = UUID.randomUUID();
             transaction = account.withdraw(transactionDTO, true, false, 
refNo.toString());
         }
         final Long newtransactionId = 
saveTransactionToGenerateTransactionId(transaction);
         final LocalDate postInterestOnDate = null;
+        boolean postReversals = false;
         if (account.isBeforeLastPostingPeriod(transactionDate, false)
                 || 
account.isBeforeLastPostingPeriod(savingsAccountTransaction.transactionLocalDate(),
 false)) {
-            boolean postReversals = false;
             account.postInterest(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth,
                     postInterestOnDate, false, postReversals);
         } else {
             account.calculateInterestUsing(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd,
-                    financialYearBeginningMonth, postInterestOnDate, false);
+                    financialYearBeginningMonth, postInterestOnDate, false, 
postReversals);
         }
         List<DepositAccountOnHoldTransaction> depositAccountOnHoldTransactions 
= null;
         if (account.getOnHoldFunds().compareTo(BigDecimal.ZERO) > 0) {
@@ -1079,8 +1079,9 @@ public class 
SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
         final MathContext mc = MathContext.DECIMAL64;
         boolean isInterestTransfer = false;
         LocalDate postInterestOnDate = null;
+        boolean postReversals = false;
         savingsAccount.calculateInterestUsing(mc, transferDate, 
isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd,
-                financialYearBeginningMonth, postInterestOnDate, false);
+                financialYearBeginningMonth, postInterestOnDate, false, 
postReversals);
 
         this.savingsAccountTransactionRepository.save(newTransferTransaction);
         this.savingAccountRepositoryWrapper.saveAndFlush(savingsAccount);
@@ -1110,8 +1111,9 @@ public class 
SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
         final MathContext mc = MathContext.DECIMAL64;
         boolean isInterestTransfer = false;
         LocalDate postInterestOnDate = null;
+        boolean postReversals = false;
         savingsAccount.calculateInterestUsing(mc, transferDate, 
isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd,
-                financialYearBeginningMonth, postInterestOnDate, false);
+                financialYearBeginningMonth, postInterestOnDate, false, 
postReversals);
 
         
this.savingsAccountTransactionRepository.save(withdrawtransferTransaction);
         this.savingAccountRepositoryWrapper.saveAndFlush(savingsAccount);
@@ -1152,8 +1154,9 @@ public class 
SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
         boolean isInterestTransfer = false;
         final MathContext mc = MathContext.DECIMAL64;
         LocalDate postInterestOnDate = null;
+        boolean postReversals = false;
         savingsAccount.calculateInterestUsing(mc, transferDate, 
isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd,
-                financialYearBeginningMonth, postInterestOnDate, false);
+                financialYearBeginningMonth, postInterestOnDate, false, 
postReversals);
 
         
this.savingsAccountTransactionRepository.save(acceptTransferTransaction);
         this.savingAccountRepositoryWrapper.saveAndFlush(savingsAccount);
@@ -1322,15 +1325,15 @@ public class 
SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
         boolean isInterestTransfer = false;
         LocalDate postInterestOnDate = null;
         final MathContext mc = MathContext.DECIMAL64;
+        boolean postReversals = false;
         if 
(account.isBeforeLastPostingPeriod(savingsAccountCharge.getDueLocalDate(), 
backdatedTxnsAllowedTill)) {
             final LocalDate today = DateUtils.getBusinessLocalDate();
-            boolean postReversals = false;
             account.postInterest(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth,
                     postInterestOnDate, backdatedTxnsAllowedTill, 
postReversals);
         } else {
             final LocalDate today = DateUtils.getBusinessLocalDate();
             account.calculateInterestUsing(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd,
-                    financialYearBeginningMonth, postInterestOnDate, 
backdatedTxnsAllowedTill);
+                    financialYearBeginningMonth, postInterestOnDate, 
backdatedTxnsAllowedTill, postReversals);
         }
 
         List<DepositAccountOnHoldTransaction> depositAccountOnHoldTransactions 
= null;
@@ -1475,15 +1478,15 @@ public class 
SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
         boolean isInterestTransfer = false;
         LocalDate postInterestOnDate = null;
         final MathContext mc = MathContext.DECIMAL64;
+        boolean postReversals = false;
         if (account.isBeforeLastPostingPeriod(transactionDate, 
backdatedTxnsAllowedTill)) {
             final LocalDate today = DateUtils.getBusinessLocalDate();
-            boolean postReversals = false;
             account.postInterest(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth,
                     postInterestOnDate, isInterestTransfer, postReversals);
         } else {
             final LocalDate today = DateUtils.getBusinessLocalDate();
             account.calculateInterestUsing(mc, today, isInterestTransfer, 
isSavingsInterestPostingAtCurrentPeriodEnd,
-                    financialYearBeginningMonth, postInterestOnDate, 
backdatedTxnsAllowedTill);
+                    financialYearBeginningMonth, postInterestOnDate, 
backdatedTxnsAllowedTill, postReversals);
         }
         List<DepositAccountOnHoldTransaction> depositAccountOnHoldTransactions 
= null;
         if (account.getOnHoldFunds().compareTo(BigDecimal.ZERO) > 0) {
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsSchedularInterestPoster.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsSchedularInterestPoster.java
index fda525233..57c6797d6 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsSchedularInterestPoster.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsSchedularInterestPoster.java
@@ -253,14 +253,20 @@ public class SavingsSchedularInterestPoster implements 
Callable<Void> {
         List<String> transRefNo = new ArrayList<>();
         for (SavingsAccountData savingsAccountData : savingsAccountDataList) {
             SavingsAccountSummaryData savingsAccountSummaryData = 
savingsAccountData.getSummary();
-            paramsForSavingsSummary
-                    .add(new Object[] { 
savingsAccountSummaryData.getTotalDeposits(), 
savingsAccountSummaryData.getTotalWithdrawals(),
-                            
savingsAccountSummaryData.getTotalInterestEarned(), 
savingsAccountSummaryData.getTotalInterestPosted(),
-                            
savingsAccountSummaryData.getTotalWithdrawalFees(), 
savingsAccountSummaryData.getTotalFeeCharge(),
-                            savingsAccountSummaryData.getTotalPenaltyCharge(), 
savingsAccountSummaryData.getTotalAnnualFees(),
-                            savingsAccountSummaryData.getAccountBalance(), 
savingsAccountSummaryData.getTotalOverdraftInterestDerived(),
-                            savingsAccountSummaryData.getTotalWithholdTax(), 
savingsAccountSummaryData.getLastInterestCalculationDate(),
-                            
savingsAccountSummaryData.getInterestPostedTillDate(), 
savingsAccountData.getId() });
+            paramsForSavingsSummary.add(new Object[] { 
savingsAccountSummaryData.getTotalDeposits(),
+                    savingsAccountSummaryData.getTotalWithdrawals(), 
savingsAccountSummaryData.getTotalInterestEarned(),
+                    savingsAccountSummaryData.getTotalInterestPosted(), 
savingsAccountSummaryData.getTotalWithdrawalFees(),
+                    savingsAccountSummaryData.getTotalFeeCharge(), 
savingsAccountSummaryData.getTotalPenaltyCharge(),
+                    savingsAccountSummaryData.getTotalAnnualFees(), 
savingsAccountSummaryData.getAccountBalance(),
+                    
savingsAccountSummaryData.getTotalOverdraftInterestDerived(), 
savingsAccountSummaryData.getTotalWithholdTax(),
+                    
Date.from(savingsAccountSummaryData.getLastInterestCalculationDate().atStartOfDay(DateUtils.getDateTimeZoneOfTenant())
+                            .toInstant()),
+                    savingsAccountSummaryData.getInterestPostedTillDate() != 
null
+                            ? 
Date.from(savingsAccountSummaryData.getInterestPostedTillDate()
+                                    
.atStartOfDay(DateUtils.getDateTimeZoneOfTenant()).toInstant())
+                            : 
Date.from(savingsAccountSummaryData.getLastInterestCalculationDate()
+                                    
.atStartOfDay(DateUtils.getDateTimeZoneOfTenant()).toInstant()),
+                    savingsAccountData.getId() });
             List<SavingsAccountTransactionData> 
savingsAccountTransactionDataList = 
savingsAccountData.getSavingsAccountTransactionData();
             for (SavingsAccountTransactionData savingsAccountTransactionData : 
savingsAccountTransactionDataList) {
                 if (savingsAccountTransactionData.getId() == null) {
@@ -287,7 +293,7 @@ public class SavingsSchedularInterestPoster implements 
Callable<Void> {
         if (transRefNo.size() > 0) {
             this.jdbcTemplate.batchUpdate(queryForSavingsUpdate, 
paramsForSavingsSummary);
             this.jdbcTemplate.batchUpdate(queryForTransactionInsertion, 
paramsForTransactionInsertion);
-
+            LOG.info("`Total No Of Interest Posting:` {}", transRefNo.size());
             List<SavingsAccountTransactionData> 
savingsAccountTransactionDataList = fetchTransactionsFromIds(transRefNo);
             if (savingsAccountDataList != null) {
                 LOG.info("Fetched Transactions from DB: {}", 
savingsAccountTransactionDataList.size());
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 7a85e0a88..f0512f740 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
@@ -52,6 +52,7 @@ import 
org.apache.fineract.integrationtests.common.savings.SavingsAccountHelper;
 import 
org.apache.fineract.integrationtests.common.savings.SavingsProductHelper;
 import 
org.apache.fineract.integrationtests.common.savings.SavingsStatusChecker;
 import org.apache.fineract.portfolio.charge.domain.ChargeTimeType;
+import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -2815,4 +2816,59 @@ public class ClientSavingsIntegrationTest {
         balance = Float.parseFloat("900.0");
         assertEquals(balance, summary.get("accountBalance"), "Verifying 
account balance is 900");
     }
+
+    @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");
+
+        final Integer clientID = ClientHelper.createClient(this.requestSpec, 
this.responseSpec);
+        ClientHelper.verifyClientCreatedOnServer(this.requestSpec, 
this.responseSpec, clientID);
+        final String minBalanceForInterestCalculation = null;
+        final String minRequiredBalance = "0";
+        final String enforceMinRequiredBalance = "false";
+        final boolean allowOverdraft = true;
+
+        final Integer savingsProductID = 
createSavingsProduct(this.requestSpec, this.responseSpec, "0", 
minBalanceForInterestCalculation,
+                minRequiredBalance, enforceMinRequiredBalance, allowOverdraft);
+        Assertions.assertNotNull(savingsProductID);
+
+        final Integer savingsId = 
this.savingsAccountHelper.applyForSavingsApplication(clientID, 
savingsProductID, ACCOUNT_TYPE_INDIVIDUAL);
+        Assertions.assertNotNull(savingsId);
+
+        HashMap savingsStatusHashMap = 
this.savingsAccountHelper.approveSavings(savingsId);
+        SavingsStatusChecker.verifySavingsIsApproved(savingsStatusHashMap);
+
+        savingsStatusHashMap = 
this.savingsAccountHelper.activateSavings(savingsId);
+        SavingsStatusChecker.verifySavingsIsActive(savingsStatusHashMap);
+
+        // withdrawal transaction 1
+        Integer withdrawalTransactionId = (Integer) 
this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsId, "500",
+                SavingsAccountHelper.TRANSACTION_DATE, 
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);
+        summary = this.savingsAccountHelper.getSavingsSummary(savingsId);
+        balance = Float.parseFloat("-1000.0");
+        assertEquals(balance, summary.get("accountBalance"), "Verifying 
account balance is -1000");
+
+        // Check for last transactions running balance
+        Object transactionObj = 
this.savingsAccountHelper.getSavingsDetails(savingsId, "transactions");
+        ArrayList<HashMap<String, Object>> transactions = 
(ArrayList<HashMap<String, Object>>) transactionObj;
+        HashMap<String, Object> requestedTransaction = 
transactions.get(transactions.size() - 2);
+        balance = Float.parseFloat("-1000.0");
+        assertEquals(balance.toString(), 
requestedTransaction.get("runningBalance").toString(), "Equality check for 
Balance");
+    }
+
+    @AfterEach
+    public void tearDown() {
+        
GlobalConfigurationHelper.resetAllDefaultGlobalConfigurations(this.requestSpec, 
this.responseSpec);
+        
GlobalConfigurationHelper.verifyAllDefaultGlobalConfigurations(this.requestSpec,
 this.responseSpec);
+    }
 }

Reply via email to