@@ -3,6 +3,7 @@ package net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.ac
|
||||
import com.mongodb.WriteResult;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.accounts.AccountChangeInfo;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.accounts.AccountTransactionInfo;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.transactions.TransferState;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
@@ -69,5 +70,13 @@ public class AccountInfoUpdateService {
|
||||
AccountInfo.class);
|
||||
}
|
||||
|
||||
public void updateTransactionStatus(String accountId, String transactionId, TransferState status) {
|
||||
AccountInfo account = accountInfoRepository.findOne(accountId);
|
||||
if (account != null) {
|
||||
account.getTransactions().stream().filter(ati -> ati.getTransactionId().equals(transactionId)).forEach(ati -> ati.setStatus(status));
|
||||
accountInfoRepository.save(account);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,13 +3,14 @@ package net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.ac
|
||||
import io.eventuate.DispatchedEvent;
|
||||
import io.eventuate.EventHandlerMethod;
|
||||
import io.eventuate.EventSubscriber;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.accounts.AccountChangedEvent;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.accounts.AccountCreditedEvent;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.accounts.AccountDebitedEvent;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.accounts.AccountOpenedEvent;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.accounts.*;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.transactions.CreditRecordedEvent;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.transactions.DebitRecordedEvent;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.transactions.FailedDebitRecordedEvent;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.transactions.MoneyTransferCreatedEvent;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.accounts.AccountChangeInfo;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.accounts.AccountTransactionInfo;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.transactions.TransferState;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -64,14 +65,30 @@ public class AccountQueryWorkflow {
|
||||
|
||||
@EventHandlerMethod
|
||||
public void recordDebit(DispatchedEvent<AccountDebitedEvent> de) {
|
||||
String accountId = de.getEntityId();
|
||||
String transactionId = de.getEvent().getTransactionId();
|
||||
|
||||
accountInfoUpdateService.updateTransactionStatus(accountId, transactionId, TransferState.DEBITED);
|
||||
saveChange(de, -1);
|
||||
}
|
||||
|
||||
@EventHandlerMethod
|
||||
public void recordCredit(DispatchedEvent<AccountCreditedEvent> de) {
|
||||
String accountId = de.getEntityId();
|
||||
String transactionId = de.getEvent().getTransactionId();
|
||||
|
||||
accountInfoUpdateService.updateTransactionStatus(accountId, transactionId, TransferState.COMPLETED);
|
||||
saveChange(de, +1);
|
||||
}
|
||||
|
||||
@EventHandlerMethod
|
||||
public void recordFailed(DispatchedEvent<AccountDebitFailedDueToInsufficientFundsEvent> de) {
|
||||
String accountId = de.getEntityId();
|
||||
String transactionId = de.getEvent().getTransactionId();
|
||||
|
||||
accountInfoUpdateService.updateTransactionStatus(accountId, transactionId, TransferState.FAILED_DUE_TO_INSUFFICIENT_FUNDS);
|
||||
}
|
||||
|
||||
public <T extends AccountChangedEvent> void saveChange(DispatchedEvent<T> de, int delta) {
|
||||
String changeId = de.getEventId().asString();
|
||||
String transactionId = de.getEvent().getTransactionId();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.chrisrichardson.eventstore.javaexamples.banking.web.queryside.accounts;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.accounts.AccountInfo;
|
||||
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.accounts.AccountNotFoundException;
|
||||
@@ -11,10 +12,9 @@ import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@RestController
|
||||
public class AccountQueryController {
|
||||
@@ -51,9 +51,11 @@ public class AccountQueryController {
|
||||
@RequestMapping(value = "/accounts/{accountId}/history", method = RequestMethod.GET)
|
||||
public ResponseEntity<AccountHistoryResponse> getTransactionsHistory(@PathVariable String accountId) {
|
||||
AccountInfo accountInfo = accountInfoQueryService.findByAccountId(accountId);
|
||||
return ResponseEntity.ok().body(new AccountHistoryResponse(new AccountHistoryEntry(accountInfo.getDate()),
|
||||
accountInfo.getTransactions(),
|
||||
accountInfo.getChanges()));
|
||||
List<AccountHistoryEntry> historyEntries = new ArrayList<>();
|
||||
historyEntries.add(new AccountOpenInfo(accountInfo.getDate(), AccountHistoryEntry.EntryType.account));
|
||||
accountInfo.getTransactions().forEach(historyEntries::add);
|
||||
|
||||
return ResponseEntity.ok().body(new AccountHistoryResponse(historyEntries));
|
||||
}
|
||||
|
||||
@ResponseStatus(value= HttpStatus.NOT_FOUND, reason="account not found")
|
||||
|
||||
@@ -6,7 +6,7 @@ import net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.a
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.accounts.AccountService;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.transactions.MoneyTransfer;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.transactions.MoneyTransferService;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.transactions.TransferState;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.transactions.TransferState;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.transactions.TransferDetails;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -6,7 +6,7 @@ import net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.a
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.accounts.AccountService;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.transactions.MoneyTransfer;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.transactions.MoneyTransferService;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.transactions.TransferState;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.transactions.TransferState;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.transactions.TransferDetails;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -1,19 +1,31 @@
|
||||
package net.chrisrichardson.eventstore.javaexamples.banking.common.accounts;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Created by popikyardo on 9/1/16.
|
||||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS,
|
||||
include = JsonTypeInfo.As.PROPERTY,
|
||||
property = "entryType")
|
||||
@JsonSubTypes({
|
||||
@JsonSubTypes.Type(value = AccountTransactionInfo.class, name = "transaction"),
|
||||
@JsonSubTypes.Type(value = AccountOpenInfo.class, name = "account")
|
||||
})
|
||||
public class AccountHistoryEntry {
|
||||
|
||||
protected Date date;
|
||||
protected EntryType entryType;
|
||||
|
||||
public AccountHistoryEntry() {
|
||||
}
|
||||
|
||||
public AccountHistoryEntry(Date date) {
|
||||
public AccountHistoryEntry(Date date, EntryType entryType) {
|
||||
this.date = date;
|
||||
this.entryType = entryType;
|
||||
}
|
||||
|
||||
public Date getDate() {
|
||||
@@ -23,4 +35,16 @@ public class AccountHistoryEntry {
|
||||
public void setDate(Date date) {
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
public EntryType getEntryType() {
|
||||
return entryType;
|
||||
}
|
||||
|
||||
public void setEntryType(EntryType entryType) {
|
||||
this.entryType = entryType;
|
||||
}
|
||||
|
||||
public enum EntryType {
|
||||
transaction, account
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,40 +6,21 @@ import java.util.List;
|
||||
* Created by popikyardo on 9/1/16.
|
||||
*/
|
||||
public class AccountHistoryResponse {
|
||||
private AccountHistoryEntry accountOpened;
|
||||
private List<AccountTransactionInfo> transactionsHistory;
|
||||
private List<AccountChangeInfo> accountChangesHistory;
|
||||
private List<AccountHistoryEntry> transactionsHistory;
|
||||
|
||||
public AccountHistoryResponse() {
|
||||
}
|
||||
|
||||
public AccountHistoryResponse(AccountHistoryEntry accountOpened, List<AccountTransactionInfo> transactionsHistory, List<AccountChangeInfo> accountChangesHistory) {
|
||||
this.accountOpened = accountOpened;
|
||||
public AccountHistoryResponse(List<AccountHistoryEntry> transactionsHistory) {
|
||||
|
||||
this.transactionsHistory = transactionsHistory;
|
||||
this.accountChangesHistory = accountChangesHistory;
|
||||
}
|
||||
|
||||
public AccountHistoryEntry getAccountOpened() {
|
||||
return accountOpened;
|
||||
}
|
||||
|
||||
public void setAccountOpened(AccountHistoryEntry accountOpened) {
|
||||
this.accountOpened = accountOpened;
|
||||
}
|
||||
|
||||
public List<AccountTransactionInfo> getTransactionsHistory() {
|
||||
public List<AccountHistoryEntry> getTransactionsHistory() {
|
||||
return transactionsHistory;
|
||||
}
|
||||
|
||||
public void setTransactionsHistory(List<AccountTransactionInfo> transactionsHistory) {
|
||||
public void setTransactionsHistory(List<AccountHistoryEntry> transactionsHistory) {
|
||||
this.transactionsHistory = transactionsHistory;
|
||||
}
|
||||
|
||||
public List<AccountChangeInfo> getAccountChangesHistory() {
|
||||
return accountChangesHistory;
|
||||
}
|
||||
|
||||
public void setAccountChangesHistory(List<AccountChangeInfo> accountChangesHistory) {
|
||||
this.accountChangesHistory = accountChangesHistory;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package net.chrisrichardson.eventstore.javaexamples.banking.common.accounts;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Created by popikyardo on 9/1/16.
|
||||
*/
|
||||
public class AccountOpenInfo extends AccountHistoryEntry {
|
||||
|
||||
public AccountOpenInfo() {
|
||||
}
|
||||
|
||||
public AccountOpenInfo(Date date, EntryType entryType) {
|
||||
super(date, entryType);
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,20 @@
|
||||
package net.chrisrichardson.eventstore.javaexamples.banking.common.accounts;
|
||||
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.transactions.TransferState;
|
||||
import org.apache.commons.lang.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang.builder.HashCodeBuilder;
|
||||
import org.apache.commons.lang.builder.ToStringBuilder;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class AccountTransactionInfo {
|
||||
public class AccountTransactionInfo extends AccountHistoryEntry{
|
||||
|
||||
private String transactionId;
|
||||
private String fromAccountId;
|
||||
private String toAccountId;
|
||||
private long amount;
|
||||
private Date date;
|
||||
private String description;
|
||||
private TransferState status = TransferState.INITIAL;
|
||||
|
||||
public AccountTransactionInfo() {
|
||||
}
|
||||
@@ -35,6 +36,7 @@ public class AccountTransactionInfo {
|
||||
this.amount = amount;
|
||||
this.date = date;
|
||||
this.description = description;
|
||||
this.entryType = EntryType.transaction;
|
||||
}
|
||||
|
||||
public String getTransactionId() {
|
||||
@@ -69,14 +71,6 @@ public class AccountTransactionInfo {
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
public Date getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
public void setDate(Date date) {
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
@@ -85,6 +79,14 @@ public class AccountTransactionInfo {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public TransferState getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(TransferState status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return EqualsBuilder.reflectionEquals(this, o);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.transactions;
|
||||
package net.chrisrichardson.eventstore.javaexamples.banking.common.transactions;
|
||||
|
||||
public enum TransferState {
|
||||
NEW, INITIAL, DEBITED, COMPLETED, FAILED_DUE_TO_INSUFFICIENT_FUNDS
|
||||
@@ -69,11 +69,11 @@ public abstract class AbstractRestAPITest {
|
||||
new Verifier<AccountHistoryResponse>() {
|
||||
@Override
|
||||
public void verify(AccountHistoryResponse accountHistoryResponse) {
|
||||
Optional<AccountTransactionInfo> first = accountHistoryResponse.getTransactionsHistory().stream().filter(ti -> ti.getTransactionId().equals(moneyTransfer.getMoneyTransferId())).findFirst();
|
||||
Optional<AccountHistoryEntry> first = accountHistoryResponse.getTransactionsHistory().stream().filter( ahe -> ahe.getEntryType() == AccountHistoryEntry.EntryType.transaction && ((AccountTransactionInfo)ahe).getTransactionId().equals(moneyTransfer.getMoneyTransferId())).findFirst();
|
||||
|
||||
assertTrue(first.isPresent());
|
||||
|
||||
AccountTransactionInfo ti = first.get();
|
||||
AccountTransactionInfo ti = (AccountTransactionInfo)first.get();
|
||||
|
||||
assertEquals(fromAccountId, ti.getFromAccountId());
|
||||
assertEquals(toAccountId, ti.getToAccountId());
|
||||
@@ -111,7 +111,7 @@ public abstract class AbstractRestAPITest {
|
||||
new Producer<GetAccountsResponse>() {
|
||||
@Override
|
||||
public CompletableFuture<GetAccountsResponse> produce() {
|
||||
return CompletableFuture.completedFuture(getAuthenticatedRestTemplate().getForEntity(baseUrl("/accounts?customerId=" + customerId),
|
||||
return CompletableFuture.completedFuture(getAuthenticatedRestTemplate().getForEntity(baseUrl("/customer/"+customerId+"/accounts"),
|
||||
GetAccountsResponse.class));
|
||||
}
|
||||
},
|
||||
|
||||
@@ -4,6 +4,7 @@ import io.eventuate.Event;
|
||||
import io.eventuate.EventUtil;
|
||||
import io.eventuate.ReflectiveMutableCommandProcessingAggregate;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.transactions.*;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.transactions.TransferState;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user