/*
This file is part of Cyclos (www.cyclos.org).
A project of the Social Trade Organisation (www.socialtrade.org).
Cyclos is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
Cyclos is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Cyclos; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package nl.strohalm.cyclos.entities.accounts.transactions;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Collection;
import java.util.Map;
import nl.strohalm.cyclos.entities.Relationship;
import nl.strohalm.cyclos.entities.accounts.Account;
import nl.strohalm.cyclos.entities.accounts.AccountOwner;
import nl.strohalm.cyclos.entities.accounts.Rated;
import nl.strohalm.cyclos.entities.accounts.SystemAccountOwner;
import nl.strohalm.cyclos.entities.accounts.external.ExternalTransfer;
import nl.strohalm.cyclos.entities.accounts.fees.account.AccountFeeLog;
import nl.strohalm.cyclos.entities.accounts.fees.transaction.TransactionFee;
import nl.strohalm.cyclos.entities.accounts.loans.LoanPayment;
import nl.strohalm.cyclos.entities.members.Element;
import nl.strohalm.cyclos.entities.members.brokerings.BrokerCommissionContract;
import nl.strohalm.cyclos.entities.settings.LocalSettings;
import org.apache.commons.lang.ObjectUtils;
/**
* A unit transfer between two accounts. A transaction may be performed with several transfers (ex: additional fees)
* @author luis
*/
public class Transfer extends Payment implements Rated {
public static enum Relationships implements Relationship {
ACCOUNT_FEE_LOG("accountFeeLog"), CHILDREN("children"),
CHARGED_BACK_BY("chargedBackBy"), LOAN_PAYMENT("loanPayment"),
PARENT("parent"), CHARGEBACK_OF("chargebackOf"),
TRANSACTION_FEE("transactionFee"), RECEIVER("receiver"),
EXTERNAL_TRANSFER("externalTransfer"), AUTHORIZATIONS("authorizations"),
NEXT_AUTHORIZATION_LEVEL("nextAuthorizationLevel"), SCHEDULED_PAYMENT("scheduledPayment");
private final String name;
private Relationships(final String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
}
private static final long serialVersionUID = -4749387454425166686L;
private AccountFeeLog accountFeeLog;
private Collection<Transfer> children;
private Transfer chargedBackBy;
private String transactionNumber;
private String traceNumber;
private Long clientId;
private String traceData;
private LoanPayment loanPayment;
private Transfer parent;
private Transfer chargebackOf;
private TransactionFee transactionFee;
private Element receiver;
private ExternalTransfer externalTransfer;
private Collection<TransferAuthorization> authorizations;
private AuthorizationLevel nextAuthorizationLevel;
private ScheduledPayment scheduledPayment;
private BrokerCommissionContract brokerCommissionContract;
private Calendar expirationDate;
private Calendar emissionDate;
private BigDecimal iRate;
private transient Transfer root;
public AccountFeeLog getAccountFeeLog() {
return accountFeeLog;
}
/**
* Returns the amount as a positive number, even when it's negative (i.e. chargeback)
*/
public BigDecimal getActualAmount() {
final BigDecimal amount = getAmount();
return amount == null ? null : amount.abs();
}
/**
* Returns the process date if not null, date otherwise
*/
public Calendar getActualDate() {
return getProcessDate() == null ? getDate() : getProcessDate();
}
/**
* When the amount is negative (i.e. chargeback), returns the to account instead
*/
public Account getActualFrom() {
final BigDecimal amount = getAmount();
return amount == null || amount.compareTo(BigDecimal.ZERO) >= 0 ? getFrom() : getTo();
}
/**
* When the amount is negative (i.e. chargeback), returns the to account owner instead
*/
public AccountOwner getActualFromOwner() {
return getActualFrom().getOwner();
}
/**
* When the amount is negative (i.e. chargeback), returns the from account instead
*/
public Account getActualTo() {
final BigDecimal amount = getAmount();
return amount == null || amount.compareTo(BigDecimal.ZERO) >= 0 ? getTo() : getFrom();
}
/**
* When the amount is negative (i.e. chargeback), returns the from account owner instead
*/
public AccountOwner getActualToOwner() {
return getActualTo().getOwner();
}
public Collection<TransferAuthorization> getAuthorizations() {
return authorizations;
}
public BrokerCommissionContract getBrokerCommissionContract() {
return brokerCommissionContract;
}
public Transfer getChargebackOf() {
return chargebackOf;
}
public Transfer getChargedBackBy() {
return chargedBackBy;
}
public Collection<Transfer> getChildren() {
return children;
}
/**
* @return the (optional) client id that generates the transfer
*/
public Long getClientId() {
return clientId;
}
@Override
public Calendar getEmissionDate() {
return emissionDate;
}
@Override
public Calendar getExpirationDate() {
return expirationDate;
}
public ExternalTransfer getExternalTransfer() {
return externalTransfer;
}
@Override
public BigDecimal getiRate() {
return iRate;
}
public LoanPayment getLoanPayment() {
return loanPayment;
}
@Override
public Nature getNature() {
return Nature.TRANSFER;
}
public AuthorizationLevel getNextAuthorizationLevel() {
return nextAuthorizationLevel;
}
public Transfer getParent() {
return parent;
}
public Element getReceiver() {
return receiver;
}
public Transfer getRootTransfer() {
if (root == null) {
Transfer topMost = this;
while (topMost.getParent() != null) {
topMost = topMost.getParent();
}
root = topMost;
}
return root;
}
public ScheduledPayment getScheduledPayment() {
return scheduledPayment;
}
/**
* Optional.
* @returns the data set by the client making a payment.<br>
* As an example: it could be used to link a payment with its notifications (payment received).<br>
* It depends on the client side then there is no guarantee of uniqueness between different transfer.<br>
* Note: It has nothing to do with the (unique) pair <traceNumber, clientId> (used to query transactions by those values).
*/
public String getTraceData() {
return traceData;
}
/**
* @return the (optional) trace number generated by a client
*/
public String getTraceNumber() {
return traceNumber;
}
public TransactionFee getTransactionFee() {
return transactionFee;
}
public String getTransactionNumber() {
return transactionNumber;
}
/**
* When the amount is negative (i.e. chargeback), returns whether the to account is a system account
*/
public boolean isActuallyFromSystem() {
return getActualFromOwner() instanceof SystemAccountOwner;
}
/**
* When the amount is negative (i.e. chargeback), returns whether the from account is a system account
*/
public boolean isActuallyToSystem() {
return getActualToOwner() instanceof SystemAccountOwner;
}
public boolean isProcessedAtDifferentDate() {
return !ObjectUtils.equals(getDate(), getProcessDate());
}
public boolean isRoot() {
return parent == null;
}
public void setAccountFeeLog(final AccountFeeLog feeLog) {
accountFeeLog = feeLog;
}
public void setAuthorizations(final Collection<TransferAuthorization> authorizations) {
this.authorizations = authorizations;
}
public void setBrokerCommissionContract(final BrokerCommissionContract brokerCommissionContract) {
this.brokerCommissionContract = brokerCommissionContract;
}
public void setChargebackOf(final Transfer chargebackOf) {
this.chargebackOf = chargebackOf;
}
public void setChargedBackBy(final Transfer chargedBackBy) {
this.chargedBackBy = chargedBackBy;
}
public void setChildren(final Collection<Transfer> children) {
this.children = children;
}
public void setClientId(final Long clientId) {
this.clientId = clientId;
}
public void setEmissionDate(final Calendar emissionDate) {
this.emissionDate = emissionDate;
}
public void setExpirationDate(final Calendar expirationDate) {
this.expirationDate = expirationDate;
}
public void setExternalTransfer(final ExternalTransfer externalTransfer) {
this.externalTransfer = externalTransfer;
}
public void setiRate(final BigDecimal iRate) {
this.iRate = iRate;
}
public void setLoanPayment(final LoanPayment loanComponent) {
loanPayment = loanComponent;
}
public void setNextAuthorizationLevel(final AuthorizationLevel nextAuthorizationLevel) {
this.nextAuthorizationLevel = nextAuthorizationLevel;
}
public void setParent(final Transfer parent) {
this.parent = parent;
root = null;
}
public void setReceiver(final Element receiver) {
this.receiver = receiver;
}
public void setScheduledPayment(final ScheduledPayment scheduledPayment) {
this.scheduledPayment = scheduledPayment;
}
public void setTraceData(final String traceData) {
this.traceData = traceData;
}
public void setTraceNumber(final String traceNumber) {
this.traceNumber = traceNumber;
}
public void setTransactionFee(final TransactionFee fee) {
transactionFee = fee;
}
public void setTransactionNumber(final String transactionNumber) {
this.transactionNumber = transactionNumber;
}
@Override
protected void appendVariableValues(final Map<String, Object> variables, final LocalSettings localSettings) {
super.appendVariableValues(variables, localSettings);
variables.put("transaction_number", getTransactionNumber());
}
}