Package com.wesabe.api.accounts.entities

Source Code of com.wesabe.api.accounts.entities.Account

package com.wesabe.api.accounts.entities;

import java.math.BigDecimal;
import java.util.Currency;
import java.util.Locale;
import java.util.Set;

import javax.persistence.*;

import org.hibernate.annotations.BatchSize;
import org.hibernate.annotations.NotFound;
import org.hibernate.annotations.NotFoundAction;
import org.hibernate.validator.InvalidStateException;
import org.hibernate.validator.InvalidValue;
import org.hibernate.validator.NotEmpty;
import org.joda.time.DateTime;

import com.google.common.base.Objects;
import com.google.common.base.Predicate;
import com.google.common.collect.Sets;
import com.wesabe.api.util.guid.GUID;
import com.wesabe.api.util.money.CurrencyCodeParser;
import com.wesabe.api.util.money.Money;
import com.wesabe.api.util.money.UnknownCurrencyCodeException;

@Entity
@Table(name="accounts")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="type", discriminatorType=DiscriminatorType.STRING)
@DiscriminatorValue("Account")
@NamedQueries({
  @NamedQuery(
    name="com.wesabe.api.accounts.Account.findByAccountKeyAndRelativeId",
    query="SELECT a FROM Account a" +
        " WHERE a.accountKey = :accountKey AND a.relativeId = :accountId"
  ),
  @NamedQuery(
    name="com.wesabe.api.accounts.Account.findAllByAccountKey",
    query="SELECT a FROM Account a" +
        " WHERE a.accountKey = :accountKey AND a.status IN (:statuses)" +
        " ORDER BY a.relativeId ASC"
  )
})
public class Account {
  private static final CurrencyCodeParser CURRENCY_CODE_PARSER = new CurrencyCodeParser();

  @Id
  @GeneratedValue(strategy=GenerationType.AUTO)
  private Integer id;

  @Column(nullable=false) @NotEmpty
  private String name;

  @Column(name="currency")
  private String currencyCode = Currency.getInstance(Locale.getDefault()).getCurrencyCode();

  @Column(name="account_key", nullable=false, unique=false, length=64)
  private String accountKey;

  @Column(nullable=false)
  private int status = AccountStatus.ACTIVE.getValue();

  @Column(nullable=false, unique=true, length=64)
  private String guid = GUID.generateRandom(64).toString();

  @Column(name="id_for_user")
  private Integer relativeId;

  @Column(name="position")
  private Integer position = 0;

  @Transient
  private BigDecimal balance;

  @Column(nullable=false, name="account_type_id")
  private int accountTypeId = AccountType.UNKNOWN.getValue();

  @OneToMany(mappedBy="account")
  @BatchSize(size=10)
  private Set<AccountBalance> accountBalances = Sets.newHashSet();

  @OneToMany(mappedBy="account")
  @BatchSize(size=200)
  private Set<Txaction> txactions = Sets.newHashSet();

  @ManyToOne(fetch=FetchType.LAZY)
  @JoinColumn(name="financial_inst_id", nullable=true)
  @NotFound(action=NotFoundAction.IGNORE)
  private FinancialInst financialInst;
 
  public Account() {
  }

  public Account(String name, Currency currency) {
    this.name = name;
    this.currencyCode = currency.getCurrencyCode();
  }

  public void setName(String name) {
    this.name = name;
  }

  public String getName() {
    return name;
  }

  public Integer getId() {
    return id;
  }

  public void setAccountKey(String accountKey) {
    this.accountKey = accountKey;
  }

  public String getAccountKey() {
    return accountKey;
  }

  public void setStatus(AccountStatus status) {
    this.status = status.getValue();
  }

  public AccountStatus getStatus() {
    return AccountStatus.byValue(status);
  }

  public Currency getCurrency() throws UnknownCurrencyCodeException {
    return CURRENCY_CODE_PARSER.parse(currencyCode);
  }

  public void setCurrency(Currency currency) {
    this.currencyCode = currency.getCurrencyCode();
  }

  public GUID getGuid() {
    return new GUID(guid);
  }

  public void setRelativeId(int relativeId) {
    this.relativeId = Integer.valueOf(relativeId);
  }

  public Integer getRelativeId() {
    return relativeId;
  }
 
  public FinancialInst getFinancialInst() {
    return financialInst;
  }

  @Override
  public boolean equals(Object obj) {
    if (obj instanceof Account) {
      Account that = (Account) obj;

      return Objects.equal(getAccountKey(), that.getAccountKey())
        && Objects.equal(getCurrency(), that.getCurrency())
        && Objects.equal(getGuid(), that.getGuid())
        && Objects.equal(getId(), getId())
        && Objects.equal(getName(), that.getName())
        && Objects.equal(getRelativeId(), that.getRelativeId())
        && Objects.equal(getStatus(), that.getStatus());
    }
    return false;
  }

  @Override
  public int hashCode() {
    return Objects.hashCode(
      accountKey, currencyCode, guid, id, name,
      relativeId, Integer.valueOf(status)
    );
  }

  public Money getBalance() {
    if (!canHaveBalance()) {
      return null;
    }

    if (hasCachedBalance()) {
      return new Money(balance, getCurrency());
    }

    return calculateBalance();
  }

  public void setBalance(BigDecimal balance) {
    accountBalances.add(new AccountBalance(this, balance, new DateTime()));
    calculateBalance();
  }
 
  public void setBalance(Money balance) {
    if (!balance.getCurrency().equals(getCurrency())) {
      throw new InvalidStateException(new InvalidValue[] {
          new InvalidValue("currency for new balance ("+balance.getCurrency()+") does not match account currency ("+getCurrency()+")", getClass(), "balance", balance, this)
      });
    }
   
    setBalance(balance.getValue());
  }

  private boolean hasCachedBalance() {
    return balance != null;
  }

  public boolean hasBalance() {
    return canHaveBalance() && (getBalance() != null);
  }

  private boolean canHaveBalance() {
    return getAccountType().hasBalance();
  }
 
  public void enableBalance() {
    if (getAccountType().hasBalance()) {
      // nothing to do
      return;
    }
   
    setAccountType(AccountType.MANUAL);
    // give us some sort of balance if we don't have one
    if (!hasBalance()) {
      setBalance(new BigDecimal("0.0"));
    }
  }

  public void disableBalance() {
    if (!getAccountType().hasBalance()) {
      // nothing to do
      return;
    }
   
    if (getAccountType().hasUploads()) {
      throw new InvalidStateException(new InvalidValue[] {
          new InvalidValue("cannot disable balances on accounts with uploads", getClass(), "accountTypeId", AccountType.CASH, this)
      });
    }
   
    setAccountType(AccountType.CASH);
  }
 
  private Money calculateBalance() {
    final AccountBalance accountBalance = getMostRecentAccountBalance();
    if (accountBalance == null) {
      // FIXME coda@wesabe.com -- Apr 28, 2009: We *really* don't expect getBalance() to return null.
      return null;
    }

    Money balance = accountBalance.getBalance();
    for (Txaction txaction : getTransactionsSince(accountBalance.getDate())) {
      balance = balance.add(txaction.getAmount());
    }

    this.balance = balance.getValue();
    return balance;
  }

  public DateTime getBalanceDate() {
    final AccountBalance accountBalance = getMostRecentAccountBalance();
    if (accountBalance == null) {
      return null;
    }

    return accountBalance.getDate();
  }

  public Set<Txaction> getTxactions() {
    return txactions;
  }

  private Set<Txaction> getTransactionsSince(final DateTime date) {
    return Sets.filter(getTxactions(), new Predicate<Txaction>() {
      @Override
      public boolean apply(final Txaction txaction) {
        return !txaction.isDeleted() &&
             !txaction.isDisabled() &&
             txaction.getDatePosted().isAfter(date);
      }
    });
  }

  private AccountBalance getMostRecentAccountBalance() {
    AccountBalance mostRecentAccountBalance = null;

    for (AccountBalance accountBalance : getAccountBalances()) {
      if ((mostRecentAccountBalance == null) ||
          ((accountBalance.getDate() != null) &&
           (mostRecentAccountBalance.getDate() != null) &&
           mostRecentAccountBalance.getDate().isBefore(accountBalance.getDate()))) {
        mostRecentAccountBalance = accountBalance;
      }
    }

    return mostRecentAccountBalance;
  }

  public Set<AccountBalance> getAccountBalances() {
    return accountBalances;
  }

  public boolean isActive() {
    return getStatus().equals(AccountStatus.ACTIVE);
  }

  public boolean isArchived() {
    return getStatus().equals(AccountStatus.ARCHIVED);
  }

  public AccountType getAccountType() {
    return AccountType.byValue(accountTypeId);
  }

  public void setAccountType(AccountType accountType) {
    this.accountTypeId = accountType.getValue();
  }
 
  public Integer getPosition() {
    return position;
  }

  public static Account ofType(AccountType accountType) {
    Account account = new Account();
    account.setAccountType(accountType);
    return account;
  }

  // REVIEW: 2009-05-13 <andre@wesabe.com> -- This should probably check for the max
  // of [last balance date, last ssu job date, last transaction date] or Today if those
  // are in the future.
  public DateTime getLastActivityDate() {
    AccountBalance mostRecentAccountBalance = getMostRecentAccountBalance();

    if (mostRecentAccountBalance == null) {
      return null;
    }

    return mostRecentAccountBalance.getCreatedAt();
  }
}
TOP

Related Classes of com.wesabe.api.accounts.entities.Account

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.