FINERACT-1330: Pay Charge & withdrawals is violating Overdraft conditions on current and past Transactions

This commit is contained in:
rrpawar96
2022-08-23 11:00:10 +02:00
committed by Arnold Gálovics
parent ed80540a95
commit d75835170a
5 changed files with 99 additions and 6 deletions
@@ -1521,6 +1521,7 @@ public class SavingsAccount extends AbstractPersistableCustom {
final List<DepositAccountOnHoldTransaction> depositAccountOnHoldTransactions, final boolean backdatedTxnsAllowedTill) {
List<SavingsAccountTransaction> transactionsSortedByDate = null;
BigDecimal transactionAmount = null;
if (backdatedTxnsAllowedTill) {
transactionsSortedByDate = retrieveSortedTransactions();
} else {
@@ -1535,6 +1536,9 @@ public class SavingsAccount extends AbstractPersistableCustom {
Money minRequiredBalance = minRequiredBalanceDerived(getCurrency());
LocalDate lastSavingsDate = null;
for (final SavingsAccountTransaction transaction : transactionsSortedByDate) {
transactionAmount = transaction.getAmount();
if (transaction.isNotReversed() && transaction.isCredit()) {
runningBalance = runningBalance.plus(transaction.getAmount(this.currency));
} else if (transaction.isNotReversed() && transaction.isDebit()) {
@@ -1573,14 +1577,11 @@ public class SavingsAccount extends AbstractPersistableCustom {
throw new PlatformApiDataValidationException(dataValidationErrors);
}
}
}
lastSavingsDate = transaction.transactionLocalDate();
}
BigDecimal withdrawalFee = null;
BigDecimal transactionAmount = null;
if (isOverdraft()) {
if (runningBalance.minus(minRequiredBalance).isLessThanZero()) {
throw new InsufficientAccountBalanceException("transactionAmount", getAccountBalance(), withdrawalFee, transactionAmount);
@@ -1588,6 +1589,18 @@ public class SavingsAccount extends AbstractPersistableCustom {
}
}
public void validateAccountBalanceDoesNotViolateOverdraft(final List<SavingsAccountTransaction> savingsAccountTransaction,
final BigDecimal amountPaid) {
if (savingsAccountTransaction != null) {
SavingsAccountTransaction savingsAccountTransactionFirst = savingsAccountTransaction.get(0);
if (!this.allowOverdraft) {
if (savingsAccountTransactionFirst.getRunningBalance(this.currency).minus(amountPaid).isLessThanZero()) {
throw new InsufficientAccountBalanceException("transactionAmount", getAccountBalance(), null, amountPaid);
}
}
}
}
protected boolean isAccountLocked(final LocalDate transactionDate) {
boolean isLocked = false;
final boolean accountHasLockedInSetting = this.lockedInUntilDate != null;
@@ -21,6 +21,7 @@ package org.apache.fineract.portfolio.savings.domain;
import java.time.LocalDate;
import java.util.List;
import javax.persistence.LockModeType;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Lock;
@@ -47,6 +48,9 @@ public interface SavingsAccountTransactionRepository
@Lock(LockModeType.PESSIMISTIC_WRITE)
List<SavingsAccountTransaction> findBySavingsAccount(@Param("savingsAccount") SavingsAccount savingsAccount);
@Query("select sat from SavingsAccountTransaction sat where sat.refNo = :refNo")
List<SavingsAccountTransaction> findAllTransactionByRefNo(@Param("refNo") String refNo);
List<SavingsAccountTransaction> findByRefNo(@Param("refNo") String refNo);
@Query("select sat from SavingsAccountTransaction sat where sat.savingsAccount.id = :savingsId and sat.dateOf <= :transactionDate and sat.reversed=false")
List<SavingsAccountTransaction> findBySavingsAccountIdAndLessThanDateOfAndReversedIsFalse(@Param("savingsId") Long savingsId,
@Param("transactionDate") LocalDate transactionDate, Pageable pageable);
}
@@ -130,6 +130,9 @@ import org.apache.fineract.useradministration.domain.AppUserRepositoryWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
@@ -718,7 +721,7 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
List<SavingsAccountTransaction> savingsAccountTransactions = null;
if (isBulk) {
String transactionRefNo = savingsAccountTransaction.getRefNo();
savingsAccountTransactions = this.savingsAccountTransactionRepository.findAllTransactionByRefNo(transactionRefNo);
savingsAccountTransactions = this.savingsAccountTransactionRepository.findByRefNo(transactionRefNo);
reversal = this.savingsAccountDomainService.handleReversal(account, savingsAccountTransactions, backdatedTxnsAllowedTill);
} else {
reversal = this.savingsAccountDomainService.handleReversal(account, Collections.singletonList(savingsAccountTransaction),
@@ -1471,6 +1474,13 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
this.savingAccountAssembler.assignSavingAccountHelpers(account);
final Set<Long> existingTransactionIds = new HashSet<>();
final Set<Long> existingReversedTransactionIds = new HashSet<>();
Pageable sortedByDateAndIdDesc = PageRequest.of(0, 1, Sort.by("dateOf", "id").descending());
List<SavingsAccountTransaction> savingsAccountTransaction = this.savingsAccountTransactionRepository
.findBySavingsAccountIdAndLessThanDateOfAndReversedIsFalse(account.getId(), transactionDate, sortedByDateAndIdDesc);
account.validateAccountBalanceDoesNotViolateOverdraft(savingsAccountTransaction, amountPaid);
updateExistingTransactionsDetails(account, existingTransactionIds, existingReversedTransactionIds);
SavingsAccountTransaction chargeTransaction = account.payCharge(savingsAccountCharge, amountPaid, transactionDate, formatter, user,
backdatedTxnsAllowedTill, null);
@@ -1488,6 +1498,7 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
financialYearBeginningMonth, postInterestOnDate, backdatedTxnsAllowedTill, postReversals);
}
List<DepositAccountOnHoldTransaction> depositAccountOnHoldTransactions = null;
if (account.getOnHoldFunds().compareTo(BigDecimal.ZERO) > 0) {
depositAccountOnHoldTransactions = this.depositAccountOnHoldTransactionRepository
.findBySavingsAccountAndReversedFalseOrderByCreatedDateAsc(account);