This is an automated email from the ASF dual-hosted git repository.
aleks pushed a commit to branch 1.8.0
in repository https://gitbox.apache.org/repos/asf/fineract.git
The following commit(s) were added to refs/heads/1.8.0 by this push:
new c3b462919 FINERACT-1646-backdated-transaction-available-balance-fix
c3b462919 is described below
commit c3b462919fed1206bd8a6d3255d3591f84970f2c
Author: Dhaval Maniyar <[email protected]>
AuthorDate: Sat Jul 30 22:08:59 2022 +0530
FINERACT-1646-backdated-transaction-available-balance-fix
---
.../portfolio/savings/data/SavingsAccountData.java | 10 +++++++++
.../savings/data/SavingsAccountSummaryData.java | 11 ++++++++--
.../savings/domain/SavingsAccountAssembler.java | 25 +++++++++++++++++-----
.../SavingsAccountInterestPostingServiceImpl.java | 8 +++++--
.../SavingsAccountReadPlatformServiceImpl.java | 2 +-
.../service/SavingsSchedularServiceImpl.java | 2 +-
.../ClientSavingsIntegrationTest.java | 12 ++++++-----
7 files changed, 54 insertions(+), 16 deletions(-)
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountData.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountData.java
index 8f66a23cf..befcbe8de 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountData.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountData.java
@@ -116,6 +116,8 @@ public final class SavingsAccountData implements
Serializable {
private final BigDecimal minOverdraftForInterestCalculation;
private transient List<SavingsAccountTransactionData>
savingsAccountTransactionData = new ArrayList<>();
+ private transient SavingsAccountTransactionData
lastSavingsAccountTransaction;
+
private List<DatatableData> datatables = null;
// import field
@@ -1104,4 +1106,12 @@ public final class SavingsAccountData implements
Serializable {
public Set<Long> getExistingReversedTransactionIds() {
return this.existingReversedTransactionIds;
}
+
+ public SavingsAccountTransactionData getLastSavingsAccountTransaction() {
+ return lastSavingsAccountTransaction;
+ }
+
+ public void setLastSavingsAccountTransaction(SavingsAccountTransactionData
lastSavingsAccountTransaction) {
+ this.lastSavingsAccountTransaction = lastSavingsAccountTransaction;
+ }
}
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 a7eea4d47..9335f8df6 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
@@ -223,16 +223,23 @@ public class SavingsAccountSummaryData implements
Serializable {
Money interestTotal = Money.of(currency, this.totalInterestPosted);
Money withHoldTaxTotal = Money.of(currency, this.totalWithholdTax);
Money overdraftInterestTotal = Money.of(currency,
this.totalOverdraftInterestDerived);
+ this.totalDeposits = wrapper.calculateTotalDeposits(currency,
savingsAccountTransactions);
+ this.totalWithdrawals =
wrapper.calculateTotalWithdrawals(currency, savingsAccountTransactions);
final HashMap<String, Money> map =
updateRunningBalanceAndPivotDate(true, savingsAccountTransactions,
interestTotal,
overdraftInterestTotal, withHoldTaxTotal, currency);
interestTotal = map.get("interestTotal");
withHoldTaxTotal = map.get("withHoldTax");
overdraftInterestTotal = map.get("overdraftInterestTotal");
+ BigDecimal deltaInterest =
interestTotal.minus(this.totalInterestPosted).getAmountDefaultedToNullIfZero();
+ BigDecimal deltaWithholdTax =
withHoldTaxTotal.minus(this.totalWithholdTax).getAmountDefaultedToNullIfZero();
+ BigDecimal deltaOverdraftInterestDerived =
overdraftInterestTotal.minus(this.totalOverdraftInterestDerived)
+ .getAmountDefaultedToNullIfZero();
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)
- .minus(this.totalOverdraftInterestDerived).getAmount();
+ this.accountBalance = getRunningBalanceOnPivotDate();
+ this.accountBalance = Money.of(currency,
this.accountBalance).plus(Money.of(currency,
this.totalDeposits)).plus(deltaInterest)
+
.minus(this.totalWithdrawals).minus(deltaWithholdTax).minus(deltaOverdraftInterestDerived).getAmount();
}
}
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 fa234fcaa..e45626574 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
@@ -48,6 +48,7 @@ import static
org.apache.fineract.portfolio.savings.SavingsApiConstants.withdraw
import com.google.gson.JsonElement;
import java.math.BigDecimal;
import java.time.LocalDate;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
@@ -74,6 +75,7 @@ import
org.apache.fineract.portfolio.savings.SavingsInterestCalculationType;
import org.apache.fineract.portfolio.savings.SavingsPeriodFrequencyType;
import org.apache.fineract.portfolio.savings.SavingsPostingInterestPeriodType;
import org.apache.fineract.portfolio.savings.data.SavingsAccountData;
+import
org.apache.fineract.portfolio.savings.data.SavingsAccountTransactionData;
import
org.apache.fineract.portfolio.savings.exception.SavingsProductNotFoundException;
import org.apache.fineract.useradministration.domain.AppUser;
import org.slf4j.Logger;
@@ -381,12 +383,25 @@ public class SavingsAccountAssembler {
public SavingsAccountData assembleSavings(final SavingsAccountData
account) {
// Update last running balance on account level
- 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());
+ final boolean backdatedTxnsAllowedTill =
this.configurationDomainService.retrievePivotDateConfig();
+ if (backdatedTxnsAllowedTill && account.getTransactions() != null &&
account.getSummary().getInterestPostedTillDate() != null) {
+ List<SavingsAccountTransactionData> removalList = new
ArrayList<>();
+
+ for (int i = 0; i < account.getTransactions().size(); i++) {
+ SavingsAccountTransactionData savingsAccountTransaction =
account.getTransactions().get(i);
+ removalList.add(savingsAccountTransaction);
+ if
((savingsAccountTransaction.isInterestPostingAndNotReversed()
+ ||
savingsAccountTransaction.isOverdraftInterestAndNotReversed())
+ && !savingsAccountTransaction.isReversalTransaction())
{
+
account.getSummary().setRunningBalanceOnPivotDate(savingsAccountTransaction.getRunningBalance());
+
account.setLastSavingsAccountTransaction(savingsAccountTransaction);
+ break;
+ }
+ }
+ account.getTransactions().removeAll(removalList);
+ } else {
+ account.getSummary().setRunningBalanceOnPivotDate(BigDecimal.ZERO);
}
-
account.setHelpers(this.savingsAccountTransactionSummaryWrapper,
this.savingsHelper);
return account;
}
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 dc2a87309..0ee01f2ba 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
@@ -364,8 +364,12 @@ public class SavingsAccountInterestPostingServiceImpl
implements SavingsAccountI
}
final List<SavingsAccountTransactionData> listOfTransactionsSorted =
new ArrayList<>();
listOfTransactionsSorted.addAll(savingsAccountData.getTransactions());
- final SavingsAccountTransactionDataComparator transactionComparator =
new SavingsAccountTransactionDataComparator();
- Collections.sort(listOfTransactionsSorted, transactionComparator);
+ if (!listOfTransactionsSorted.isEmpty()) {
+ final SavingsAccountTransactionDataComparator
transactionComparator = new SavingsAccountTransactionDataComparator();
+ Collections.sort(listOfTransactionsSorted, transactionComparator);
+ } else {
+
listOfTransactionsSorted.add(savingsAccountData.getLastSavingsAccountTransaction());
+ }
return listOfTransactionsSorted.get(0);
}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java
index b53a1bfed..31e8e3f0e 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java
@@ -272,7 +272,7 @@ public class SavingsAccountReadPlatformServiceImpl
implements SavingsAccountRead
+ "where (CASE WHEN sa.interest_posted_till_date is not
null THEN tr.transaction_date >= sa.interest_posted_till_date ELSE
tr.transaction_date >= sa.activatedon_date END) ";
}
- sql = sql + " and (sa.interest_posted_till_date is null or
sa.interest_posted_till_date < ? ) ";
+ sql = sql + " and (sa.interest_posted_till_date is null or
sa.interest_posted_till_date <= ? ) ";
sql = sql + " order by sa.id, tr.transaction_date, tr.created_date,
tr.id";
List<SavingsAccountData> savingsAccountDataList =
this.jdbcTemplate.query(sql, this.savingAccountMapperForInterestPosting, //
NOSONAR
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsSchedularServiceImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsSchedularServiceImpl.java
index 018fc5b98..5234e5932 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsSchedularServiceImpl.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsSchedularServiceImpl.java
@@ -76,7 +76,7 @@ public class SavingsSchedularServiceImpl implements
SavingsSchedularService {
Long maxSavingsIdInList = 0L;
// initialise the executor service with fetched configurations
final ExecutorService executorService =
Executors.newFixedThreadPool(threadPoolSize);
- final boolean backdatedTxnsAllowedTill = false;
+ final boolean backdatedTxnsAllowedTill =
this.configurationDomainService.retrievePivotDateConfig();
long start = System.currentTimeMillis();
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 a98a796a2..3e778bba3 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
@@ -2972,18 +2972,20 @@ public class ClientSavingsIntegrationTest {
configurationForBackdatedTransaction();
- String transactionDate = "1 July 2022";
+ LocalDate transactionDate =
LocalDate.now(Utils.getZoneIdOfTenant()).minusDays(10);
+ final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd
MMMM yyyy");
+ String startDate = formatter.format(transactionDate);
- final Integer clientID = ClientHelper.createClient(this.requestSpec,
this.responseSpec, transactionDate);
+ final Integer clientID = ClientHelper.createClient(this.requestSpec,
this.responseSpec, startDate);
Assertions.assertNotNull(clientID);
- final Integer savingsId =
createSavingsAccountDailyPostingOverdraft(clientID, transactionDate);
- this.savingsAccountHelper.depositToSavingsAccount(savingsId, "200",
transactionDate, CommonConstants.RESPONSE_RESOURCE_ID);
+ final Integer savingsId =
createSavingsAccountDailyPostingOverdraft(clientID, startDate);
+ this.savingsAccountHelper.depositToSavingsAccount(savingsId, "200",
startDate, 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,
+ List<HashMap> error = (List<HashMap>)
validationErrorHelper.depositToSavingsAccount(savingsId, "300", startDate,
CommonConstants.RESPONSE_ERROR);
assertEquals("error.msg.savings.transaction.is.not.allowed",
error.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));