Confirm existance of elements before accessing them

This commit is contained in:
Wilfred Kigenyi
2025-03-14 12:59:35 +00:00
committed by Adam Saghy
parent 898a18c873
commit 2ac1445dba
2 changed files with 320 additions and 1 deletions
@@ -1593,13 +1593,18 @@ public class SavingsAccount extends AbstractAuditableWithUTCDateTimeCustom<Long>
public void validateAccountBalanceDoesNotViolateOverdraft(final List<SavingsAccountTransaction> savingsAccountTransaction,
final BigDecimal amountPaid) {
if (savingsAccountTransaction != null) {
if (savingsAccountTransaction != null && savingsAccountTransaction.size() > 0) {
SavingsAccountTransaction savingsAccountTransactionFirst = savingsAccountTransaction.get(0);
if (!this.allowOverdraft) {
if (savingsAccountTransactionFirst.getRunningBalance(this.currency).minus(amountPaid).isLessThanZero()) {
throw new InsufficientAccountBalanceException("transactionAmount", getAccountBalance(), null, amountPaid);
}
}
} else {
if (!this.allowOverdraft) {
throw new InsufficientAccountBalanceException("transactionAmount", BigDecimal.ZERO, null, amountPaid);
}
}
}
@@ -3184,6 +3184,320 @@ public class ClientSavingsIntegrationTest {
error.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
}
@Test
public void testSavingsAccountWithdrawalWithoutPriorTransactionsWithoutOverdraft() {
final DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("dd MMMM yyyy", Locale.US);
this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec);
final ResponseSpecification errorResponse = new ResponseSpecBuilder().expectStatusCode(403).build();
final SavingsAccountHelper validationErrorHelper = new SavingsAccountHelper(this.requestSpec, errorResponse);
/***
* Create a client to apply for savings account (overdraft account).
*/
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
// Assertions.assertNotNull(clientID);
final String minBalanceForInterestCalculation = null;
/***
* Create savings product with zero opening balance and overdraft disabled
*/
final String zeroOpeningBalance = "0.0";
final String minRequiredBalance = null;
final String enforceMinRequiredBalance = "false";
final boolean allowOverdraft = false;
final Integer savingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, zeroOpeningBalance,
minBalanceForInterestCalculation, minRequiredBalance, enforceMinRequiredBalance, allowOverdraft);
Assertions.assertNotNull(savingsProductID);
/***
* Apply for Savings account
*/
final Integer savingsId = this.savingsAccountHelper.applyForSavingsApplication(clientID, savingsProductID, ACCOUNT_TYPE_INDIVIDUAL);
Assertions.assertNotNull(savingsProductID);
HashMap modifications = this.savingsAccountHelper.updateSavingsAccount(clientID, savingsProductID, savingsId,
ACCOUNT_TYPE_INDIVIDUAL);
Assertions.assertTrue(modifications.containsKey("submittedOnDate"));
HashMap savingsStatusHashMap = SavingsStatusChecker.getStatusOfSavings(this.requestSpec, this.responseSpec, savingsId);
SavingsStatusChecker.verifySavingsIsPending(savingsStatusHashMap);
/***
* Approve the savings account
*/
savingsStatusHashMap = this.savingsAccountHelper.approveSavings(savingsId);
SavingsStatusChecker.verifySavingsIsApproved(savingsStatusHashMap);
LocalDate todaysDate = Utils.getLocalDateOfTenant();
todaysDate = todaysDate.minusMonths(1);
todaysDate = todaysDate.withDayOfMonth(1);
final String ACTIVATION_DATE = dateFormat.format(todaysDate);
final Integer lastDayOfMonth = todaysDate.lengthOfMonth();
todaysDate = todaysDate.withDayOfMonth(lastDayOfMonth);
final String TRANSACTION_DATE = dateFormat.format(todaysDate);
/***
* Activate the application and verify account status
*
* @param activationDate
* this value is every time first day of previous month
*/
savingsStatusHashMap = activateSavingsAccount(savingsId, ACTIVATION_DATE);
SavingsStatusChecker.verifySavingsIsActive(savingsStatusHashMap);
Float balance = Float.parseFloat(zeroOpeningBalance);
/***
* Attempt a withdrawal transaction, verify an exception will be thrown since there are no prior transactions to
* this transaction
*/
ArrayList<HashMap> savingsAccountErrorData = (ArrayList<HashMap>) validationErrorHelper.withdrawalFromSavingsAccount(savingsId,
WITHDRAW_AMOUNT, TRANSACTION_DATE, CommonConstants.RESPONSE_ERROR);
assertEquals("error.msg.savingsaccount.transaction.insufficient.account.balance",
savingsAccountErrorData.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
}
@Test
public void testWithdrawalWithPriorTransactionsWithOverdraft_AMT_GT_Balance() {
final DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("dd MMMM yyyy", Locale.US);
this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec);
final ResponseSpecification errorResponse = new ResponseSpecBuilder().expectStatusCode(400).build();
final SavingsAccountHelper validationErrorHelper = new SavingsAccountHelper(this.requestSpec, errorResponse);
/***
* Create a client to apply for savings account (overdraft account).
*/
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
// Assertions.assertNotNull(clientID);
final String minBalanceForInterestCalculation = null;
/***
* Create savings product with zero opening balance and overdraft enabled
*/
final String nonZeroOpeningBalance = "500.00";
final String minRequiredBalance = null;
final String enforceMinRequiredBalance = "false";
final boolean allowOverdraft = true;
final Integer savingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, nonZeroOpeningBalance,
minBalanceForInterestCalculation, minRequiredBalance, enforceMinRequiredBalance, allowOverdraft);
Assertions.assertNotNull(savingsProductID);
/***
* Apply for Savings account
*/
final Integer savingsId = this.savingsAccountHelper.applyForSavingsApplication(clientID, savingsProductID, ACCOUNT_TYPE_INDIVIDUAL);
Assertions.assertNotNull(savingsProductID);
HashMap modifications = this.savingsAccountHelper.updateSavingsAccount(clientID, savingsProductID, savingsId,
ACCOUNT_TYPE_INDIVIDUAL);
Assertions.assertTrue(modifications.containsKey("submittedOnDate"));
HashMap savingsStatusHashMap = SavingsStatusChecker.getStatusOfSavings(this.requestSpec, this.responseSpec, savingsId);
SavingsStatusChecker.verifySavingsIsPending(savingsStatusHashMap);
/***
* Approve the savings account
*/
savingsStatusHashMap = this.savingsAccountHelper.approveSavings(savingsId);
SavingsStatusChecker.verifySavingsIsApproved(savingsStatusHashMap);
LocalDate todaysDate = Utils.getLocalDateOfTenant();
todaysDate = todaysDate.minusMonths(1);
todaysDate = todaysDate.withDayOfMonth(1);
final String ACTIVATION_DATE = dateFormat.format(todaysDate);
final Integer lastDayOfMonth = todaysDate.lengthOfMonth();
todaysDate = todaysDate.withDayOfMonth(lastDayOfMonth);
/***
* Activate the application and verify account status
*
* @param activationDate
* this value is every time first day of previous month
*/
savingsStatusHashMap = activateSavingsAccount(savingsId, ACTIVATION_DATE);
SavingsStatusChecker.verifySavingsIsActive(savingsStatusHashMap);
Float balance = Float.parseFloat(nonZeroOpeningBalance);
/***
* Attempt a withdrawal transaction, verify an exception will be thrown since there are no prior transactions to
* this transaction
*/
/***
* Perform withdraw transaction, verify account balance(account balance will go to negative as no deposits are
* there prior to this transaction)
*/
Integer withdrawTransactionId = (Integer) this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsId, WITHDRAW_AMOUNT,
ACTIVATION_DATE, CommonConstants.RESPONSE_RESOURCE_ID);
HashMap withdrawTransaction = this.savingsAccountHelper.getSavingsTransaction(savingsId, withdrawTransactionId);
balance -= Float.parseFloat(WITHDRAW_AMOUNT);
assertEquals(Float.parseFloat(WITHDRAW_AMOUNT), withdrawTransaction.get("amount"), "Verifying Withdrawal Amount");
assertEquals(balance, withdrawTransaction.get("runningBalance"), "Verifying Balance after Withdrawal");
}
@Test
public void testWithdrawalWithPriorTransactionsWithOverdraft_AMT_LT_Balance() {
final DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("dd MMMM yyyy", Locale.US);
this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec);
final ResponseSpecification errorResponse = new ResponseSpecBuilder().expectStatusCode(400).build();
final SavingsAccountHelper validationErrorHelper = new SavingsAccountHelper(this.requestSpec, errorResponse);
/***
* Create a client to apply for savings account (overdraft account).
*/
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
// Assertions.assertNotNull(clientID);
final String minBalanceForInterestCalculation = null;
/***
* Create savings product with zero opening balance and overdraft enabled
*/
final String nonZeroOpeningBalance = "2000";
final String minRequiredBalance = null;
final String enforceMinRequiredBalance = "false";
final boolean allowOverdraft = false;
final Integer savingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, nonZeroOpeningBalance,
minBalanceForInterestCalculation, minRequiredBalance, enforceMinRequiredBalance, allowOverdraft);
Assertions.assertNotNull(savingsProductID);
/***
* Apply for Savings account
*/
final Integer savingsId = this.savingsAccountHelper.applyForSavingsApplication(clientID, savingsProductID, ACCOUNT_TYPE_INDIVIDUAL);
Assertions.assertNotNull(savingsProductID);
HashMap modifications = this.savingsAccountHelper.updateSavingsAccount(clientID, savingsProductID, savingsId,
ACCOUNT_TYPE_INDIVIDUAL);
Assertions.assertTrue(modifications.containsKey("submittedOnDate"));
HashMap savingsStatusHashMap = SavingsStatusChecker.getStatusOfSavings(this.requestSpec, this.responseSpec, savingsId);
SavingsStatusChecker.verifySavingsIsPending(savingsStatusHashMap);
/***
* Approve the savings account
*/
savingsStatusHashMap = this.savingsAccountHelper.approveSavings(savingsId);
SavingsStatusChecker.verifySavingsIsApproved(savingsStatusHashMap);
LocalDate todaysDate = Utils.getLocalDateOfTenant();
todaysDate = todaysDate.minusMonths(1);
todaysDate = todaysDate.withDayOfMonth(1);
final String ACTIVATION_DATE = dateFormat.format(todaysDate);
/***
* Activate the application and verify account status
*
* @param activationDate
* this value is every time first day of previous month
*/
savingsStatusHashMap = activateSavingsAccount(savingsId, ACTIVATION_DATE);
SavingsStatusChecker.verifySavingsIsActive(savingsStatusHashMap);
Float balance = Float.parseFloat(nonZeroOpeningBalance);
/***
* Attempt a withdrawal transaction, verify an exception will be thrown since there are no prior transactions to
* this transaction
*/
/***
* Perform withdraw transaction, verify account balance(account balance will go to negative as no deposits are
* there prior to this transaction)
*/
Integer withdrawTransactionId = (Integer) this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsId, WITHDRAW_AMOUNT,
ACTIVATION_DATE, CommonConstants.RESPONSE_RESOURCE_ID);
HashMap withdrawTransaction = this.savingsAccountHelper.getSavingsTransaction(savingsId, withdrawTransactionId);
balance -= Float.parseFloat(WITHDRAW_AMOUNT);
assertEquals(Float.parseFloat(WITHDRAW_AMOUNT), withdrawTransaction.get("amount"), "Verifying Withdrawal Amount");
assertEquals(balance, withdrawTransaction.get("runningBalance"), "Verifying Balance after Withdrawal");
}
@Test
public void testWithdrawalWithPriorTransactionsWithOverdraft_AMT_EQ_Balance() {
final DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("dd MMMM yyyy", Locale.US);
this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec);
final ResponseSpecification errorResponse = new ResponseSpecBuilder().expectStatusCode(400).build();
final SavingsAccountHelper validationErrorHelper = new SavingsAccountHelper(this.requestSpec, errorResponse);
/***
* Create a client to apply for savings account (overdraft account).
*/
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
// Assertions.assertNotNull(clientID);
final String minBalanceForInterestCalculation = null;
/***
* Create savings product with zero opening balance and overdraft enabled
*/
final String nonZeroOpeningBalance = "1000";
final String minRequiredBalance = null;
final String enforceMinRequiredBalance = "false";
final boolean allowOverdraft = false;
final Integer savingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, nonZeroOpeningBalance,
minBalanceForInterestCalculation, minRequiredBalance, enforceMinRequiredBalance, allowOverdraft);
Assertions.assertNotNull(savingsProductID);
/***
* Apply for Savings account
*/
final Integer savingsId = this.savingsAccountHelper.applyForSavingsApplication(clientID, savingsProductID, ACCOUNT_TYPE_INDIVIDUAL);
Assertions.assertNotNull(savingsProductID);
HashMap modifications = this.savingsAccountHelper.updateSavingsAccount(clientID, savingsProductID, savingsId,
ACCOUNT_TYPE_INDIVIDUAL);
Assertions.assertTrue(modifications.containsKey("submittedOnDate"));
HashMap savingsStatusHashMap = SavingsStatusChecker.getStatusOfSavings(this.requestSpec, this.responseSpec, savingsId);
SavingsStatusChecker.verifySavingsIsPending(savingsStatusHashMap);
/***
* Approve the savings account
*/
savingsStatusHashMap = this.savingsAccountHelper.approveSavings(savingsId);
SavingsStatusChecker.verifySavingsIsApproved(savingsStatusHashMap);
LocalDate todaysDate = Utils.getLocalDateOfTenant();
todaysDate = todaysDate.minusMonths(1);
todaysDate = todaysDate.withDayOfMonth(1);
final String ACTIVATION_DATE = dateFormat.format(todaysDate);
/***
* Activate the application and verify account status
*
* @param activationDate
* this value is every time first day of previous month
*/
savingsStatusHashMap = activateSavingsAccount(savingsId, ACTIVATION_DATE);
SavingsStatusChecker.verifySavingsIsActive(savingsStatusHashMap);
Float balance = Float.parseFloat(nonZeroOpeningBalance);
/***
* Attempt a withdrawal transaction, verify an exception will be thrown since there are no prior transactions to
* this transaction
*/
/***
* Perform withdraw transaction, verify account balance(account balance will go to negative as no deposits are
* there prior to this transaction)
*/
Integer withdrawTransactionId = (Integer) this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsId, WITHDRAW_AMOUNT,
ACTIVATION_DATE, CommonConstants.RESPONSE_RESOURCE_ID);
HashMap withdrawTransaction = this.savingsAccountHelper.getSavingsTransaction(savingsId, withdrawTransactionId);
balance -= Float.parseFloat(WITHDRAW_AMOUNT);
assertEquals(Float.parseFloat(WITHDRAW_AMOUNT), withdrawTransaction.get("amount"), "Verifying Withdrawal Amount");
assertEquals(balance, withdrawTransaction.get("runningBalance"), "Verifying Balance after Withdrawal");
}
private Integer createSavingsAccountDailyPostingOverdraft(final Integer clientID, final String startDate) {
final Integer savingsProductID = createSavingsProductDailyPostingOverdraft();
Assertions.assertNotNull(savingsProductID);