import java.math.BigDecimal;
import java.util.UUID;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;

import java.time.Instant;
import javax.persistence.Convert;
import javax.persistence.Converter;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

 * Very basic modelling of an transaction concept to show the relation to account handled by JPA.
@Table(name = "BANK_TRANSACTION", uniqueConstraints = @UniqueConstraint(columnNames = {"FK_ACCOUNT_TID", "SID"}))
public class Transaction extends AbstractAuditable {

    private static final String[] EXCLUDED_FIELDS = new String[]{
        "tId", "account", "lastModifiedBy", "lastModifiedTime"

     * TID - the technical unique identifier for instance, i.e., primary key. This should NEVER EVER be exposed out side the service since it is
     * a key very internal to this service.
    @Column(name = "TID", length = 36, nullable = false, columnDefinition = "CHAR(36)")
    private String tId;

     * Semantic key of a transaction which is exposed as key to the outside world!
    @Column(name = "SID", length = 36, nullable = false, columnDefinition = "CHAR(36)")
    private String id;

     * The transaction is "owned" by account.
    @JoinColumn(name = "FK_ACCOUNT_TID", nullable = false)
    private Account account;

    @Column(name = "AMOUNT", nullable = false, columnDefinition = "DECIMAL(15,2)")
    private BigDecimal amount;

    @Column(name = "DESCRIPTION", length = 500, nullable = false)
    private String description;

    @Column(name = "TIMESTAMP")
    @Convert(converter = InstantConverter.class)
    private Instant timestamp;

    protected Transaction() {
        // Required by JPA

    public Transaction(Account account, String id, BigDecimal amount, String description, Instant timestamp) {
        this.account = account; = id;
        this.amount = amount;
        this.description = description;
        this.timestamp = timestamp;
        tId = UUID.randomUUID().toString();


    public Transaction(Account account, BigDecimal amount, String description) {
        // The semantic key might as well be generated as a hash value of the transaction values
        // for simplicity it is just a unique id here.
        this(account, UUID.randomUUID().toString(), amount, description,;

     * @param sid a controlled human readable and url capable identifier
    public Transaction(String sid, Account account, BigDecimal amount, String description) {
        this(account, amount, description); = sid;

    public String getId() {
        return id;

    public Account getAccount() {
        return account;

    public BigDecimal getAmount() {
        return amount;

    public String getDescription() {
        return description;

    public Instant getTimestamp() {
        return timestamp;

    protected String[] excludedFields() {
        return EXCLUDED_FIELDS;

    public String toString() {
        return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
                .append("account", account)
                .append("id", id)
                .append("amount", amount)
                .append("description", description)
                .append("timestamp", timestamp)