FINERACT-2457: Share transaction chronological validation incorrectly blocks new transactions based on rejected/reversed transactions

This commit is contained in:
Wilfred Kigenyi
2026-02-19 11:15:28 +00:00
committed by Adam Saghy
parent fcc3da2515
commit c9a41794e8
2 changed files with 439 additions and 30 deletions
@@ -29,6 +29,7 @@ import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -706,16 +707,8 @@ public class ShareAccountDataSerializer {
}
}
boolean isTransactionBeforeExistingTransactions = false;
Set<ShareAccountTransaction> transactions = account.getShareAccountTransactions();
for (ShareAccountTransaction transaction : transactions) {
if (!transaction.isChargeTransaction()) {
LocalDate transactionDate = transaction.getPurchasedDate();
if (DateUtils.isBefore(requestedDate, transactionDate)) {
isTransactionBeforeExistingTransactions = true;
break;
}
}
}
isTransactionBeforeExistingTransactions = isTransactionBeforeExistingTransactions(requestedDate,
isTransactionBeforeExistingTransactions, account);
if (isTransactionBeforeExistingTransactions) {
baseDataValidator.reset().parameter(ShareAccountApiConstants.requesteddate_paramname).value(requestedDate)
.failWithCodeNoParameterAddedToErrorCode("purchase.transaction.date.cannot.be.before.existing.transactions");
@@ -732,6 +725,23 @@ public class ShareAccountDataSerializer {
return actualChanges;
}
private boolean isTransactionBeforeExistingTransactions(LocalDate requestedDate, boolean isTransactionBeforeExistingTransactions,
ShareAccount shareAccount) {
Collection<ShareAccountTransaction> activeTransactions = shareAccount.getShareAccountTransactions().stream()
.filter(tr -> tr.isActive() && !tr.isChargeTransaction() && !tr.isPurchaseRejectedTransaction()).toList();
for (ShareAccountTransaction transaction : activeTransactions) {
if (!transaction.isChargeTransaction() && transaction.isActive() && !transaction.isPurchaseRejectedTransaction()) {
LocalDate transactionDate = transaction.getPurchasedDate();
if (DateUtils.isBefore(requestedDate, transactionDate)) {
isTransactionBeforeExistingTransactions = true;
break;
}
}
}
return isTransactionBeforeExistingTransactions;
}
private void handleAdditionalSharesChargeTransactions(final ShareAccount account, final ShareAccountTransaction purchaseTransaction) {
Set<ShareAccountCharge> charges = account.getCharges();
BigDecimal totalChargeAmount = BigDecimal.ZERO;
@@ -863,16 +873,8 @@ public class ShareAccountDataSerializer {
baseDataValidator.reset().parameter(ShareAccountApiConstants.requestedshares_paramname).value(sharesRequested).notNull()
.longGreaterThanZero();
boolean isTransactionBeforeExistingTransactions = false;
Set<ShareAccountTransaction> transactions = account.getShareAccountTransactions();
for (ShareAccountTransaction transaction : transactions) {
if (!transaction.isChargeTransaction() && transaction.isActive()) {
LocalDate transactionDate = transaction.getPurchasedDate();
if (DateUtils.isBefore(requestedDate, transactionDate)) {
isTransactionBeforeExistingTransactions = true;
break;
}
}
}
isTransactionBeforeExistingTransactions = isTransactionBeforeExistingTransactions(requestedDate,
isTransactionBeforeExistingTransactions, account);
if (isTransactionBeforeExistingTransactions) {
baseDataValidator.reset().parameter(ShareAccountApiConstants.requesteddate_paramname).value(requestedDate)
.failWithCodeNoParameterAddedToErrorCode("redeem.transaction.date.cannot.be.before.existing.transactions");
@@ -1018,16 +1020,8 @@ public class ShareAccountDataSerializer {
throw new PlatformApiDataValidationException(dataValidationErrors);
}
boolean isTransactionBeforeExistingTransactions = false;
Set<ShareAccountTransaction> transactions = account.getShareAccountTransactions();
for (ShareAccountTransaction transaction : transactions) {
if (!transaction.isChargeTransaction()) {
LocalDate transactionDate = transaction.getPurchasedDate();
if (DateUtils.isBefore(closedDate, transactionDate)) {
isTransactionBeforeExistingTransactions = true;
break;
}
}
}
isTransactionBeforeExistingTransactions = isTransactionBeforeExistingTransactions(closedDate,
isTransactionBeforeExistingTransactions, account);
if (isTransactionBeforeExistingTransactions) {
baseDataValidator.reset().parameter(ShareAccountApiConstants.closeddate_paramname).value(closedDate)
.failWithCodeNoParameterAddedToErrorCode("share.account.cannot.be.closed.before.existing.transactions");
@@ -983,6 +983,285 @@ public class ShareAccountIntegrationTests {
Assertions.assertEquals("0", String.valueOf(summaryMap.get("totalPendingForApprovalShares")));
}
// Refactored Test 1
@Test
@SuppressWarnings("unchecked")
public void testChronologicalAdditionalSharesAfterRejectedTransaction() {
shareProductHelper = new ShareProductHelper();
final Integer productId = createShareProduct();
Assertions.assertNotNull(productId);
final Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(clientId);
Integer savingsAccountId = SavingsAccountHelper.openSavingsAccount(requestSpec, responseSpec, clientId, "1000");
Assertions.assertNotNull(savingsAccountId);
// Setup and activate share account with initial shares on 01 March 2016
final Integer shareAccountId = setupAndActivateShareAccount(clientId, productId, savingsAccountId, "01 March 2016");
// Apply additional shares on 15 April 2016
applyAdditionalShares(shareAccountId, "15 April 2016", "20");
// Retrieve transactions and find the additional shares request
Map<String, Object> shareAccountData = ShareAccountTransactionHelper.retrieveShareAccount(shareAccountId, requestSpec,
responseSpec);
List<Map<String, Object>> transactions = (List<Map<String, Object>>) shareAccountData.get("purchasedShares");
Assertions.assertNotNull(transactions);
// Find and reject the additional shares request (15 April 2016)
String additionalSharesRequestId = findTransactionId(transactions, "purchasedSharesType.purchased", "15 April 2016");
Assertions.assertNotNull(additionalSharesRequestId, "Additional shares request for 15 April 2016 should exist");
// Reject the additional shares request
rejectAdditionalSharesRequest(shareAccountId, additionalSharesRequestId);
// Verify transaction is rejected
shareAccountData = ShareAccountTransactionHelper.retrieveShareAccount(shareAccountId, requestSpec, responseSpec);
transactions = (List<Map<String, Object>>) shareAccountData.get("purchasedShares");
verifyTransactionStatus(transactions, "purchasedSharesType.purchased", "15 April 2016", "purchasedSharesStatusType.rejected");
// Now try to apply additional shares with a date BEFORE the rejected transaction (10 April 2016)
// This should succeed because rejected transactions should be ignored in chronological validation
applyAdditionalShares(shareAccountId, "10 April 2016", "15");
// Verify the new transaction was successfully added
shareAccountData = ShareAccountTransactionHelper.retrieveShareAccount(shareAccountId, requestSpec, responseSpec);
transactions = (List<Map<String, Object>>) shareAccountData.get("purchasedShares");
verifyTransactionWithShares(transactions, "purchasedSharesType.purchased", "10 April 2016", "15",
"purchasedSharesStatusType.applied");
}
@Test
@SuppressWarnings("unchecked")
public void testChronologicalAccountClosureBeforeRejectedTransaction() {
// FINERACT-2457: Account closure validation should ignore rejected/reversed transactions
shareProductHelper = new ShareProductHelper();
final Integer productId = createShareProduct();
Assertions.assertNotNull(productId);
final Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(clientId);
Integer savingsAccountId = SavingsAccountHelper.openSavingsAccount(requestSpec, responseSpec, clientId, "1000");
Assertions.assertNotNull(savingsAccountId);
// Setup and activate share account with initial shares on 01 March 2016
final Integer shareAccountId = setupAndActivateShareAccount(clientId, productId, savingsAccountId, "01 March 2016");
// Apply additional shares on 20 May 2016
applyAdditionalShares(shareAccountId, "20 May 2016", "30");
// Retrieve transactions and find the additional shares request
Map<String, Object> shareAccountData = ShareAccountTransactionHelper.retrieveShareAccount(shareAccountId, requestSpec,
responseSpec);
List<Map<String, Object>> transactions = (List<Map<String, Object>>) shareAccountData.get("purchasedShares");
Assertions.assertNotNull(transactions);
// Find and reject the additional shares request (20 May 2016)
String additionalSharesRequestId = findTransactionId(transactions, "purchasedSharesType.purchased", "20 May 2016");
Assertions.assertNotNull(additionalSharesRequestId, "Additional shares request for 20 May 2016 should exist");
// Reject the additional shares request
rejectAdditionalSharesRequest(shareAccountId, additionalSharesRequestId);
// Verify transaction is rejected
shareAccountData = ShareAccountTransactionHelper.retrieveShareAccount(shareAccountId, requestSpec, responseSpec);
transactions = (List<Map<String, Object>>) shareAccountData.get("purchasedShares");
verifyTransactionStatus(transactions, "purchasedSharesType.purchased", "20 May 2016", "purchasedSharesStatusType.rejected");
// Now try to close the account with a date BEFORE the rejected transaction (15 May 2016)
// This should succeed because rejected transactions should be ignored in chronological validation
Map<String, Object> closeAccountMap = new HashMap<>();
closeAccountMap.put("note", "Share Account Close Note");
closeAccountMap.put("dateFormat", "dd MMMM yyyy");
closeAccountMap.put("closedDate", "15 May 2016");
closeAccountMap.put("locale", "en");
String closeJson = new Gson().toJson(closeAccountMap);
ShareAccountTransactionHelper.postCommand("close", shareAccountId, closeJson, requestSpec, responseSpec);
// Verify the account was successfully closed
shareAccountData = ShareAccountTransactionHelper.retrieveShareAccount(shareAccountId, requestSpec, responseSpec);
Map<String, Object> statusMap = (Map<String, Object>) shareAccountData.get("status");
Assertions.assertEquals("shareAccountStatusType.closed", String.valueOf(statusMap.get("code")));
Map<String, Object> timelineMap = (Map<String, Object>) shareAccountData.get("timeline");
List<Integer> closedDateList = (List<Integer>) timelineMap.get("closedDate");
LocalDate closedDate = LocalDate.of(closedDateList.get(0), closedDateList.get(1), closedDateList.get(2));
Assertions.assertEquals("15 May 2016", closedDate.format(Utils.dateFormatter));
}
// Additional Test 1: Verify original validation still works (Negative Test)
@Test
@SuppressWarnings("unchecked")
public void testChronologicalAdditionalSharesBeforeActiveTransactionShouldFail() {
// FINERACT-2457: Verify that the fix didn't break the original chronological validation
// Transactions BEFORE active/approved transactions should still be REJECTED
shareProductHelper = new ShareProductHelper();
final Integer productId = createShareProduct();
Assertions.assertNotNull(productId);
final Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(clientId);
Integer savingsAccountId = SavingsAccountHelper.openSavingsAccount(requestSpec, responseSpec, clientId, "1000");
Assertions.assertNotNull(savingsAccountId);
// Setup and activate share account with initial shares on 01 March 2016
final Integer shareAccountId = setupAndActivateShareAccount(clientId, productId, savingsAccountId, "01 March 2016");
// Apply additional shares on 15 April 2016 (this remains active/approved)
applyAdditionalShares(shareAccountId, "15 April 2016", "20");
// Verify the transaction exists and is in applied/active state
Map<String, Object> shareAccountData = ShareAccountTransactionHelper.retrieveShareAccount(shareAccountId, requestSpec,
responseSpec);
List<Map<String, Object>> transactions = (List<Map<String, Object>>) shareAccountData.get("purchasedShares");
Assertions.assertNotNull(transactions);
String transactionId = findTransactionId(transactions, "purchasedSharesType.purchased", "15 April 2016");
Assertions.assertNotNull(transactionId, "Transaction for 15 April 2016 should exist");
// Try to apply additional shares BEFORE the active transaction (10 April 2016)
// This should FAIL because the April 15 transaction is ACTIVE/APPROVED
Map<String, Object> additionalSharesRequestMap = new HashMap<>();
additionalSharesRequestMap.put("requestedDate", "10 April 2016");
additionalSharesRequestMap.put("dateFormat", "dd MMMM yyyy");
additionalSharesRequestMap.put("locale", "en");
additionalSharesRequestMap.put("requestedShares", "15");
String additionalSharesRequestJson = new Gson().toJson(additionalSharesRequestMap);
ResponseSpecification errorResponse = new ResponseSpecBuilder().expectStatusCode(400).build();
try {
ShareAccountTransactionHelper.postCommand("applyadditionalshares", shareAccountId, additionalSharesRequestJson, requestSpec,
errorResponse);
} catch (Exception e) {
Assertions.assertTrue(
e.getMessage().contains("chronological") || e.getMessage().contains("date") || e.getMessage().contains("before"),
"Error message should indicate chronological validation failure");
}
}
// Additional Test 3: Test edge case - transaction on same date as rejected transaction
@Test
@SuppressWarnings("unchecked")
public void testChronologicalAdditionalSharesOnSameDateAsRejectedTransaction() {
// FINERACT-2457: Test behavior when applying shares on the SAME date as a rejected transaction
shareProductHelper = new ShareProductHelper();
final Integer productId = createShareProduct();
Assertions.assertNotNull(productId);
final Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(clientId);
Integer savingsAccountId = SavingsAccountHelper.openSavingsAccount(requestSpec, responseSpec, clientId, "1000");
Assertions.assertNotNull(savingsAccountId);
// Setup and activate share account with initial shares on 01 March 2016
final Integer shareAccountId = setupAndActivateShareAccount(clientId, productId, savingsAccountId, "01 March 2016");
// Apply and reject shares on 15 April 2016
applyAdditionalShares(shareAccountId, "15 April 2016", "20");
Map<String, Object> shareAccountData = ShareAccountTransactionHelper.retrieveShareAccount(shareAccountId, requestSpec,
responseSpec);
List<Map<String, Object>> transactions = (List<Map<String, Object>>) shareAccountData.get("purchasedShares");
String txId = findTransactionId(transactions, "purchasedSharesType.purchased", "15 April 2016");
Assertions.assertNotNull(txId);
rejectAdditionalSharesRequest(shareAccountId, txId);
// Verify transaction is rejected
shareAccountData = ShareAccountTransactionHelper.retrieveShareAccount(shareAccountId, requestSpec, responseSpec);
transactions = (List<Map<String, Object>>) shareAccountData.get("purchasedShares");
verifyTransactionStatus(transactions, "purchasedSharesType.purchased", "15 April 2016", "purchasedSharesStatusType.rejected");
// Try to apply shares on the SAME date as the rejected transaction
// This should succeed since rejected transactions are ignored
applyAdditionalShares(shareAccountId, "15 April 2016", "15");
// Verify the new transaction was successfully added
shareAccountData = ShareAccountTransactionHelper.retrieveShareAccount(shareAccountId, requestSpec, responseSpec);
transactions = (List<Map<String, Object>>) shareAccountData.get("purchasedShares");
// Count how many transactions exist for 15 April 2016
DateFormat simple = new SimpleDateFormat("dd MMMM yyyy");
int countForDate = 0;
int appliedCountForDate = 0;
for (Map<String, Object> transaction : transactions) {
Map<String, Object> transactionTypeMap = (Map<String, Object>) transaction.get("type");
List<Integer> dateList = (List<Integer>) transaction.get("purchasedDate");
String transactionType = (String) transactionTypeMap.get("code");
String transactionDate = formatTransactionDate(dateList, simple);
if (transactionType.equals("purchasedSharesType.purchased") && transactionDate.equals("15 April 2016")) {
countForDate++;
Map<String, Object> transactionStatusMap = (Map<String, Object>) transaction.get("status");
String status = String.valueOf(transactionStatusMap.get("code"));
if (status.equals("purchasedSharesStatusType.applied")) {
appliedCountForDate++;
Assertions.assertEquals("15", String.valueOf(transaction.get("numberOfShares")));
}
}
}
// Should have 2 transactions for this date: 1 rejected, 1 applied
Assertions.assertEquals(2, countForDate, "Should have 2 transactions for 15 April 2016");
Assertions.assertEquals(1, appliedCountForDate, "Should have 1 applied transaction for 15 April 2016");
}
// Additional Test 4: Test account closure before active transaction should still fail
@Test
@SuppressWarnings("unchecked")
public void testChronologicalAccountClosureBeforeActiveTransactionShouldFail() {
// FINERACT-2457: Verify that closing account before active transactions is still blocked
shareProductHelper = new ShareProductHelper();
final Integer productId = createShareProduct();
Assertions.assertNotNull(productId);
final Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec);
Assertions.assertNotNull(clientId);
Integer savingsAccountId = SavingsAccountHelper.openSavingsAccount(requestSpec, responseSpec, clientId, "1000");
Assertions.assertNotNull(savingsAccountId);
// Setup and activate share account with initial shares on 01 March 2016
final Integer shareAccountId = setupAndActivateShareAccount(clientId, productId, savingsAccountId, "01 March 2016");
// Apply additional shares on 20 May 2016 (and keep it active/approved)
applyAdditionalShares(shareAccountId, "20 May 2016", "30");
// Verify the transaction exists and is active
Map<String, Object> shareAccountData = ShareAccountTransactionHelper.retrieveShareAccount(shareAccountId, requestSpec,
responseSpec);
List<Map<String, Object>> transactions = (List<Map<String, Object>>) shareAccountData.get("purchasedShares");
String transactionId = findTransactionId(transactions, "purchasedSharesType.purchased", "20 May 2016");
Assertions.assertNotNull(transactionId, "Transaction for 20 May 2016 should exist");
// Try to close account on 15 May 2016 (before the active transaction)
// This should FAIL
Map<String, Object> closeAccountMap = new HashMap<>();
closeAccountMap.put("note", "Share Account Close Note");
closeAccountMap.put("dateFormat", "dd MMMM yyyy");
closeAccountMap.put("closedDate", "15 May 2016");
closeAccountMap.put("locale", "en");
String closeJson = new Gson().toJson(closeAccountMap);
ResponseSpecification errorResponse = new ResponseSpecBuilder().expectStatusCode(400).build();
try {
ShareAccountTransactionHelper.postCommand("close", shareAccountId, closeJson, requestSpec, errorResponse);
// If we get here, the validation worked correctly (request was rejected)
// This is the expected behavior
} catch (Exception e) {
// Depending on the framework, the error might be thrown as an exception
// We expect this to fail, so this is acceptable
Assertions
.assertTrue(
e.getMessage().contains("chronological") || e.getMessage().contains("date") || e.getMessage().contains("before")
|| e.getMessage().contains("transaction"),
"Error message should indicate chronological validation failure");
}
// Verify account is still active (not closed)
shareAccountData = ShareAccountTransactionHelper.retrieveShareAccount(shareAccountId, requestSpec, responseSpec);
Map<String, Object> statusMap = (Map<String, Object>) shareAccountData.get("status");
Assertions.assertEquals("shareAccountStatusType.active", String.valueOf(statusMap.get("code")),
"Account should still be active since closure was rejected");
}
private Integer createShareProduct() {
String shareProductJson = shareProductHelper.build();
return ShareProductTransactionHelper.createShareProduct(shareProductJson, requestSpec, responseSpec);
@@ -1009,4 +1288,140 @@ public class ShareAccountIntegrationTests {
map.put("amount", amount);
return map;
}
private void updateShareAccountWithInitialData(Integer shareAccountId, Integer requestedShares, String applicationDate) {
Map<String, Object> shareAccountDataForUpdate = new HashMap<>();
shareAccountDataForUpdate.put("requestedShares", requestedShares);
shareAccountDataForUpdate.put("applicationDate", applicationDate);
shareAccountDataForUpdate.put("dateFormat", "dd MMMM yyyy");
shareAccountDataForUpdate.put("locale", "en_GB");
String updateShareAccountJsonString = new Gson().toJson(shareAccountDataForUpdate);
ShareAccountTransactionHelper.updateShareAccount(shareAccountId, updateShareAccountJsonString, requestSpec, responseSpec);
}
private void approveShareAccount(Integer shareAccountId, String approvalDate) {
Map<String, Object> approveMap = new HashMap<>();
approveMap.put("note", "Share Account Approval Note");
approveMap.put("dateFormat", "dd MMMM yyyy");
approveMap.put("approvedDate", approvalDate);
approveMap.put("locale", "en");
String approve = new Gson().toJson(approveMap);
ShareAccountTransactionHelper.postCommand("approve", shareAccountId, approve, requestSpec, responseSpec);
}
private void activateShareAccount(Integer shareAccountId, String activationDate) {
Map<String, Object> activateMap = new HashMap<>();
activateMap.put("dateFormat", "dd MMMM yyyy");
activateMap.put("activatedDate", activationDate);
activateMap.put("locale", "en");
String activateJson = new Gson().toJson(activateMap);
ShareAccountTransactionHelper.postCommand("activate", shareAccountId, activateJson, requestSpec, responseSpec);
}
private void applyAdditionalShares(Integer shareAccountId, String requestedDate, String requestedShares) {
Map<String, Object> additionalSharesRequestMap = new HashMap<>();
additionalSharesRequestMap.put("requestedDate", requestedDate);
additionalSharesRequestMap.put("dateFormat", "dd MMMM yyyy");
additionalSharesRequestMap.put("locale", "en");
additionalSharesRequestMap.put("requestedShares", requestedShares);
String additionalSharesRequestJson = new Gson().toJson(additionalSharesRequestMap);
ShareAccountTransactionHelper.postCommand("applyadditionalshares", shareAccountId, additionalSharesRequestJson, requestSpec,
responseSpec);
}
private String formatTransactionDate(List<Integer> dateList, DateFormat formatter) {
Calendar cal = Calendar.getInstance();
cal.set(dateList.get(0), dateList.get(1) - 1, dateList.get(2));
Date date = cal.getTime();
return formatter.format(date);
}
private String findTransactionId(List<Map<String, Object>> transactions, String transactionTypeCode, String expectedDate) {
DateFormat simple = new SimpleDateFormat("dd MMMM yyyy");
for (Map<String, Object> transaction : transactions) {
Map<String, Object> transactionTypeMap = (Map<String, Object>) transaction.get("type");
List<Integer> dateList = (List<Integer>) transaction.get("purchasedDate");
String transactionType = (String) transactionTypeMap.get("code");
String transactionDate = formatTransactionDate(dateList, simple);
if (transactionType.equals(transactionTypeCode) && transactionDate.equals(expectedDate)) {
return String.valueOf(transaction.get("id"));
}
}
return null;
}
private void rejectAdditionalSharesRequest(Integer shareAccountId, String transactionId) {
Map<String, List<Map<String, Object>>> rejectMap = new HashMap<>();
List<Map<String, Object>> list = new ArrayList<>();
Map<String, Object> idsMap = new HashMap<>();
idsMap.put("id", transactionId);
list.add(idsMap);
rejectMap.put("requestedShares", list);
String rejectJson = new Gson().toJson(rejectMap);
ShareAccountTransactionHelper.postCommand("rejectadditionalshares", shareAccountId, rejectJson, requestSpec, responseSpec);
}
private void verifyTransactionStatus(List<Map<String, Object>> transactions, String transactionTypeCode, String expectedDate,
String expectedStatus) {
DateFormat simple = new SimpleDateFormat("dd MMMM yyyy");
boolean transactionFound = false;
for (Map<String, Object> transaction : transactions) {
Map<String, Object> transactionTypeMap = (Map<String, Object>) transaction.get("type");
List<Integer> dateList = (List<Integer>) transaction.get("purchasedDate");
String transactionType = (String) transactionTypeMap.get("code");
String transactionDate = formatTransactionDate(dateList, simple);
if (transactionType.equals(transactionTypeCode) && transactionDate.equals(expectedDate)) {
Map<String, Object> transactionStatusMap = (Map<String, Object>) transaction.get("status");
Assertions.assertEquals(expectedStatus, String.valueOf(transactionStatusMap.get("code")));
transactionFound = true;
break;
}
}
Assertions.assertTrue(transactionFound,
String.format("Transaction with type %s for %s should exist", transactionTypeCode, expectedDate));
}
private void verifyTransactionWithShares(List<Map<String, Object>> transactions, String transactionTypeCode, String expectedDate,
String expectedShares, String expectedStatus) {
DateFormat simple = new SimpleDateFormat("dd MMMM yyyy");
boolean transactionFound = false;
for (Map<String, Object> transaction : transactions) {
Map<String, Object> transactionTypeMap = (Map<String, Object>) transaction.get("type");
List<Integer> dateList = (List<Integer>) transaction.get("purchasedDate");
String transactionType = (String) transactionTypeMap.get("code");
String transactionDate = formatTransactionDate(dateList, simple);
if (transactionType.equals(transactionTypeCode) && transactionDate.equals(expectedDate)) {
Assertions.assertEquals(expectedShares, String.valueOf(transaction.get("numberOfShares")));
Map<String, Object> transactionStatusMap = (Map<String, Object>) transaction.get("status");
Assertions.assertEquals(expectedStatus, String.valueOf(transactionStatusMap.get("code")));
transactionFound = true;
break;
}
}
Assertions.assertTrue(transactionFound, String.format("Transaction for %s should be successfully created", expectedDate));
}
private Integer setupAndActivateShareAccount(Integer clientId, Integer productId, Integer savingsAccountId, String initialDate) {
final Integer shareAccountId = createShareAccount(clientId, productId, savingsAccountId);
Assertions.assertNotNull(shareAccountId);
updateShareAccountWithInitialData(shareAccountId, 25, initialDate);
approveShareAccount(shareAccountId, initialDate);
activateShareAccount(shareAccountId, initialDate);
// Verify account is active
Map<String, Object> shareAccountData = ShareAccountTransactionHelper.retrieveShareAccount(shareAccountId, requestSpec,
responseSpec);
Map<String, Object> statusMap = (Map<String, Object>) shareAccountData.get("status");
Assertions.assertEquals("shareAccountStatusType.active", String.valueOf(statusMap.get("code")));
return shareAccountId;
}
}