/*
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.fees.transaction;
import java.math.BigDecimal;
import java.util.Collection;
import nl.strohalm.cyclos.entities.Entity;
import nl.strohalm.cyclos.entities.Relationship;
import nl.strohalm.cyclos.entities.accounts.transactions.Transfer;
import nl.strohalm.cyclos.entities.accounts.transactions.TransferType;
import nl.strohalm.cyclos.entities.groups.MemberGroup;
import nl.strohalm.cyclos.entities.members.Member;
import nl.strohalm.cyclos.utils.Amount;
import nl.strohalm.cyclos.utils.StringValuedEnum;
/**
* A fee is applied on transfers
*
* @author luis
*/
public abstract class TransactionFee extends Entity {
public static enum ChargeType implements StringValuedEnum {
FIXED("F"), PERCENTAGE("P"), A_RATE("A"), D_RATE("D"), MIXED_A_D_RATES("M");
public static ChargeType from(final Amount.Type type) {
if (type == null) {
return null;
}
switch (type) {
case FIXED:
return FIXED;
case PERCENTAGE:
return PERCENTAGE;
}
return null;
}
private final String value;
private ChargeType(final String value) {
this.value = value;
}
@Override
public String getValue() {
return value;
}
public Amount.Type toAmountType() {
switch (this) {
case FIXED:
return Amount.Type.FIXED;
case PERCENTAGE:
case A_RATE:
case D_RATE:
case MIXED_A_D_RATES:
return Amount.Type.PERCENTAGE;
default:
return null;
}
}
}
public static enum Nature implements StringValuedEnum {
SIMPLE("S"), BROKER("B");
private final String value;
private Nature(final String value) {
this.value = value;
}
public Class<? extends TransactionFee> getFeeClass() {
if (this == SIMPLE) {
return SimpleTransactionFee.class;
} else {
return BrokerCommission.class;
}
}
@Override
public String getValue() {
return value;
}
}
public static enum Relationships implements Relationship {
GENERATED_TRANSFER_TYPE("generatedTransferType"), ORIGINAL_TRANSFER_TYPE("originalTransferType"), TRANSFERS("transfers"), FROM_GROUPS("fromGroups"), TO_GROUPS("toGroups"), FROM_FIXED_MEMBER("fromFixedMember");
private final String name;
private Relationships(final String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
}
public static enum Subject implements StringValuedEnum {
SYSTEM("sys"), SOURCE("src"), SOURCE_BROKER("sbr"), DESTINATION("dst"), DESTINATION_BROKER("dbr"), FIXED_MEMBER("mem");
private final String value;
private Subject(final String value) {
this.value = value;
}
@Override
public String getValue() {
return value;
}
}
private static final long serialVersionUID = -3840663900697716307L;
private String name;
private String description;
private Subject payer;
private boolean enabled;
private TransferType originalTransferType;
private TransferType generatedTransferType;
private ChargeType chargeType;
private BigDecimal value;
private BigDecimal maxFixedValue;
private BigDecimal maxPercentageValue;
private BigDecimal initialAmount;
private BigDecimal finalAmount;
private boolean deductAmount;
private Collection<Transfer> transfers;
private boolean fromAllGroups = true;
private Collection<MemberGroup> fromGroups;
private boolean toAllGroups = true;
private Collection<MemberGroup> toGroups;
private Member fromFixedMember;
public Amount getAmount() {
if (chargeType == null || value == null) {
return null;
}
return new Amount(value, chargeType.toAmountType());
}
public ChargeType getChargeType() {
return chargeType;
}
public String getDescription() {
return description;
}
public BigDecimal getFinalAmount() {
return finalAmount;
}
public Member getFromFixedMember() {
return fromFixedMember;
}
public Collection<MemberGroup> getFromGroups() {
return fromGroups;
}
public TransferType getGeneratedTransferType() {
return generatedTransferType;
}
public BigDecimal getInitialAmount() {
return initialAmount;
}
public BigDecimal getMaxFixedValue() {
return maxFixedValue;
}
public BigDecimal getMaxPercentageValue() {
return maxPercentageValue;
}
@Override
public String getName() {
return name;
}
public abstract Nature getNature();
public TransferType getOriginalTransferType() {
return originalTransferType;
}
public Subject getPayer() {
return payer;
}
public Collection<MemberGroup> getToGroups() {
return toGroups;
}
public Collection<Transfer> getTransfers() {
return transfers;
}
public BigDecimal getValue() {
return value;
}
public boolean isDeductAmount() {
return deductAmount;
}
public boolean isEnabled() {
return enabled;
}
public boolean isFromAllGroups() {
return fromAllGroups;
}
public boolean isFromMember() {
return !isFromSystem();
}
public boolean isFromSystem() {
return generatedTransferType.isFromSystem();
}
public boolean isToAllGroups() {
return toAllGroups;
}
public void setAmount(final Amount amount) {
if (amount == null) {
value = null;
chargeType = null;
} else {
value = amount.getValue();
chargeType = ChargeType.from(amount.getType());
}
}
/**
* for rates, the amount needs to be set without resetting the charge type. So call this one only in case of rates.
* @throws IllegalArgumentException in case the method is called outside of a A- or D-rated context, that is: when the chargeType is not related
* to A- or D-rate.
*/
public void setAmountForRates(final Amount amount) {
if (chargeType != ChargeType.A_RATE && chargeType != ChargeType.D_RATE && chargeType != ChargeType.MIXED_A_D_RATES) {
throw new IllegalArgumentException("TransactionFee.setAmountForRates can only be called in case of a charge type related to A-rate or D-rate.");
}
if (amount == null) {
value = null;
} else {
value = amount.getValue();
}
}
public void setChargeType(final ChargeType chargeType) {
this.chargeType = chargeType;
}
public void setDeductAmount(final boolean deductAmount) {
this.deductAmount = deductAmount;
}
public void setDescription(final String description) {
this.description = description;
}
public void setEnabled(final boolean enabled) {
this.enabled = enabled;
}
public void setFinalAmount(final BigDecimal finalAmount) {
this.finalAmount = finalAmount;
}
public void setFromAllGroups(final boolean fromAllGroups) {
this.fromAllGroups = fromAllGroups;
}
public void setFromFixedMember(final Member fromFixedMember) {
this.fromFixedMember = fromFixedMember;
}
public void setFromGroups(final Collection<MemberGroup> fromGroups) {
this.fromGroups = fromGroups;
}
public void setGeneratedTransferType(final TransferType generatedTransferType) {
this.generatedTransferType = generatedTransferType;
}
public void setInitialAmount(final BigDecimal initialAmount) {
this.initialAmount = initialAmount;
}
public void setMaxFixedValue(final BigDecimal maxFixedValue) {
this.maxFixedValue = maxFixedValue;
}
public void setMaxPercentageValue(final BigDecimal maxPercentageValue) {
this.maxPercentageValue = maxPercentageValue;
}
public void setName(final String name) {
this.name = name;
}
public void setOriginalTransferType(final TransferType originalTransferType) {
this.originalTransferType = originalTransferType;
}
public void setPayer(final Subject payer) {
this.payer = payer;
}
public void setToAllGroups(final boolean toAllGroups) {
this.toAllGroups = toAllGroups;
}
public void setToGroups(final Collection<MemberGroup> toGroups) {
this.toGroups = toGroups;
}
public void setTransfers(final Collection<Transfer> transfers) {
this.transfers = transfers;
}
public void setValue(final BigDecimal value) {
this.value = value;
}
@Override
public String toString() {
return getId() + " - " + name;
}
}