FINERACT-1646-backdated-transaction-available-balance-fix
This commit is contained in:
committed by
Aleksandar Vidakovic
parent
c9be0a2816
commit
c21ea4e1d3
+10
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+9
-2
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+20
-5
@@ -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;
|
||||
}
|
||||
|
||||
+1
-1
@@ -76,7 +76,7 @@ public class PostInterestForSavingTasklet implements Tasklet {
|
||||
final int pageSize = batchSize * threadPoolSize;
|
||||
Long maxSavingsIdInList = 0L;
|
||||
final ExecutorService executorService = Executors.newFixedThreadPool(threadPoolSize);
|
||||
final boolean backdatedTxnsAllowedTill = false;
|
||||
final boolean backdatedTxnsAllowedTill = this.configurationDomainService.retrievePivotDateConfig();
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
|
||||
+6
-2
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+7
-5
@@ -2973,18 +2973,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));
|
||||
|
||||
Reference in New Issue
Block a user