CostFormula.java

package com.tradecloud.domain.costing;

import com.tradecloud.common.base.PersistenceBase;
import com.tradecloud.domain.common.Currency;
import com.tradecloud.domain.common.Incoterm;
import com.tradecloud.domain.model.organisationalunit.OrganisationalUnit;
import com.tradecloud.domain.model.shipment.ShippingMode;
import com.tradecloud.domain.party.ServiceProvider;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.hibernate.annotations.ForeignKey;

import javax.persistence.*;
import javax.validation.constraints.NotNull;
import javax.xml.bind.annotation.*;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Entity for Formula Factory cost line algorithms.
 */
@Entity
@Table(name = "costformula")
@Access(AccessType.FIELD)
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "CostFormula")
public class CostFormula extends PersistenceBase implements Serializable {

    private static final long serialVersionUID = 1L;

    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(name = "costformula_organisationalunits", joinColumns = {
            @JoinColumn(name = "costformula_id", unique = false)},
            inverseJoinColumns = {
                    @JoinColumn(name = "organisationalunit_id", unique = false)})
    @ForeignKey(name = "fk_organisationalunit")
    @XmlElement(name = "OrganisationalUnit")
    private List<OrganisationalUnit> organisationalUnits = new ArrayList<>();

    @XmlElement
    @Enumerated(value = EnumType.STRING)
    private ShippingMode shippingMode;

    @ManyToOne
    @JoinColumn(name = "incoterm_code")
    @ForeignKey(name = "fk_incoterm")
    @XmlElement(name = "Incoterm")
    private Incoterm incoterm;

    @NotNull
    @ManyToOne
    @JoinColumn(name = "costlinetemplate_code")
    @ForeignKey(name = "fk_costlinetemplate")
    @XmlElement(name = "CostLineTemplate", required = true)
    private CostLineTemplate costLineTemplate;

    @Temporal(TemporalType.TIMESTAMP)
    private Date effectiveDate;

    @NotNull
    @Enumerated(value = EnumType.STRING)
    @Column
    @XmlAttribute
    private CostApplicationMethod costApplicationMethod;

    @Enumerated(value = EnumType.STRING)
    @Column
    @XmlAttribute
    private CostApplicationBasis costApplicationBasis;

    @Basic
    private BigDecimal rate;

    @ManyToOne
    @JoinColumn(name = "currency_code")
    @ForeignKey(name = "fk_currency")
    @XmlElement(name = "Currency")
    private Currency currency;

    @Enumerated(value = EnumType.STRING)
    @Column
    @XmlAttribute
    private CostCalculationLevel costCalculationLevel;

    @Deprecated
    @NotNull
    @Basic
    private boolean useMinValue;

    @Basic
    private BigDecimal minValue;

    @Deprecated
    @ManyToOne
    @JoinColumn(name = "min_currency_code")
    @ForeignKey(name = "fk_min_currency")
    @XmlElement(name = "minCurrency")
    private Currency minCurrencyCode;

    @Deprecated
    @NotNull
    @Basic
    private boolean useMaxValue;

    @Basic
    private BigDecimal maxValue;

    @Deprecated
    @ManyToOne
    @JoinColumn(name = "max_currency_code")
    @ForeignKey(name = "fk_max_currency")
    @XmlElement(name = "maxCurrency")
    private Currency maxCurrencyCode;

    @NotNull
    @Basic
    private boolean useSlidingScales;

    @Transient
    private boolean currencyEditable;

    @XmlAttribute
    @Enumerated(EnumType.STRING)
    @NotNull
    private CostingContextType costingContextType = CostingContextType.IMPORT;

    @XmlAttribute
    @Enumerated(EnumType.STRING)
    private FormulaContainerType containerType;

    @XmlElement(name = "FreightForwarder")
    @ManyToOne(fetch = FetchType.LAZY)
    private ServiceProvider freightForwarder;

    @XmlElement(name = "FreightForwarder")
    @Enumerated(EnumType.STRING)
    private CostRateSourceType rateSource;

    public CostFormula() {
        shippingMode = ShippingMode.SEA;
        rate = BigDecimal.ZERO;
        // null signifies the ALL option here
        organisationalUnits.add(null);
        costApplicationMethod = CostApplicationMethod.CONTAINER_PORT_RATE;
        costApplicationBasis = CostApplicationBasis.SUPPLY_COST;
        costCalculationLevel = CostCalculationLevel.CONSIGNMENT_SHIPMENT;
        useSlidingScales = false;
        useMinValue = false;
        useMaxValue = false;
        costingContextType = CostingContextType.IMPORT;
    }

    public CostFormula(CostFormula costFormulaToCopy) {
        shippingMode = costFormulaToCopy.getShippingMode();
        incoterm = costFormulaToCopy.getIncoterm();
        costLineTemplate = costFormulaToCopy.getCostLineTemplate();
        effectiveDate = costFormulaToCopy.getEffectiveDate();
        costApplicationMethod = costFormulaToCopy.getCostApplicationMethod();
        costApplicationBasis = costFormulaToCopy.getCostApplicationBasis();
        rate = costFormulaToCopy.getRate();
        currency = costFormulaToCopy.getCurrency();
        costCalculationLevel = costFormulaToCopy.getCostCalculationLevel();
        useSlidingScales = costFormulaToCopy.isUseSlidingScales();
        useMinValue = costFormulaToCopy.isUseMinValue();
        minValue = costFormulaToCopy.getMinValue();
        minCurrencyCode = costFormulaToCopy.getMinCurrencyCode();
        useMaxValue = costFormulaToCopy.isUseMaxValue();
        maxValue = costFormulaToCopy.getMaxValue();
        maxCurrencyCode = costFormulaToCopy.getMaxCurrencyCode();
        costingContextType = costFormulaToCopy.getCostingContextType();
        containerType = costFormulaToCopy.getContainerType();
        rateSource = costFormulaToCopy.getRateSource();
    }

    public List<OrganisationalUnit> getOrganisationalUnits() {
        return organisationalUnits;
    }

    public void setOrganisationalUnits(List<OrganisationalUnit> organisationalUnits) {
        this.organisationalUnits = organisationalUnits;
    }

    // Shortcut methods for the case where there is only one. This makes the UI much easier for now.
    public OrganisationalUnit getOrganisationalUnit() {
        return getOrganisationalUnits().isEmpty() ? null : getOrganisationalUnits().get(0);
    }

    // Shortcut methods for the case where there is only one. This makes the UI much easier for now.
    public void setOrganisationalUnit(OrganisationalUnit organisationalUnit) {
        getOrganisationalUnits().clear();
        getOrganisationalUnits().add(organisationalUnit);
    }

    public void addOrganisationalUnit(OrganisationalUnit organisationalUnit) {
        this.organisationalUnits.add(organisationalUnit);
    }

    public void removeOrganisationalUnit(OrganisationalUnit organisationalUnit) {
        this.organisationalUnits.remove(organisationalUnit);
    }

    public ShippingMode getShippingMode() {
        return shippingMode;
    }

    public void setShippingMode(ShippingMode shippingMode) {
        this.shippingMode = shippingMode;
    }

    public Incoterm getIncoterm() {
        return incoterm;
    }

    public void setIncoterm(Incoterm incoterm) {
        this.incoterm = incoterm;
    }

    public CostLineTemplate getCostLineTemplate() {
        return costLineTemplate;
    }

    public void setCostLineTemplate(CostLineTemplate costLineTemplate) {
        this.costLineTemplate = costLineTemplate;
    }

    public Date getEffectiveDate() {
        return effectiveDate;
    }

    public void setEffectiveDate(Date effectiveDate) {
        this.effectiveDate = effectiveDate;
    }

    public CostApplicationMethod getCostApplicationMethod() {
        return costApplicationMethod;
    }

    public void setCostApplicationMethod(CostApplicationMethod costApplicationMethod) {
        this.costApplicationMethod = costApplicationMethod;
    }

    public CostApplicationBasis getCostApplicationBasis() {
        return costApplicationBasis;
    }

    public void setCostApplicationBasis(CostApplicationBasis costApplicationBasis) {
        this.costApplicationBasis = costApplicationBasis;
    }

    public BigDecimal getRate() {
        return rate;
    }

    public void setRate(BigDecimal rate) {
        this.rate = rate;
    }

    public Currency getCurrency() {
        return currency;
    }

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

    public CostCalculationLevel getCostCalculationLevel() {
        return costCalculationLevel;
    }

    public void setCostCalculationLevel(CostCalculationLevel costCalculationLevel) {
        this.costCalculationLevel = costCalculationLevel;
    }

    public boolean isUseSlidingScales() {
        return useSlidingScales;
    }

    public void setUseSlidingScales(boolean useSlidingScales) {
        this.useSlidingScales = useSlidingScales;
    }

    public boolean isCurrencyEditable() {
        if (CostApplicationMethod.PERCENTAGE.equals(costApplicationMethod)) {
            //  If the cost application method is set to "percentage" then the % is auto-selected next to the rate which the user cannot change.
            setCurrency(null);
            currencyEditable = false;
        } else {
            currencyEditable = true;
        }
        return currencyEditable;
    }

    public void setCurrencyEditable(boolean currencyEditable) {
        this.currencyEditable = currencyEditable;
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this).append("shippingMode", shippingMode).append("incoterm", incoterm)
                .append("costLineTemplate", costLineTemplate)
                .append("effectiveDate", effectiveDate).append(costApplicationMethod).append(costApplicationBasis).append(rate).append(currency)
                .append(costCalculationLevel).append(useSlidingScales).append(useMinValue).append(minValue)
                .append(minCurrencyCode).append(useMaxValue).append(maxValue).append(maxCurrencyCode).toString();
    }

    @Override
    public int hashCode() {
        return new HashCodeBuilder().append(shippingMode).append(incoterm).append(costLineTemplate)
                .append(effectiveDate).append(costApplicationMethod)
                .append(costApplicationBasis).append(rate).append(currency).append(costCalculationLevel)
                .append(useSlidingScales).append(useMinValue).append(minValue).append(minCurrencyCode).append(useMaxValue).append(maxValue)
                .append(maxCurrencyCode).toHashCode();
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (!(obj instanceof CostFormula)) {
            return false;
        }
        CostFormula other = (CostFormula) obj;
        return new EqualsBuilder().append(shippingMode, other.shippingMode).append(incoterm, other.incoterm)
                .append(costLineTemplate, other.costLineTemplate)
                .append(effectiveDate, other.effectiveDate).append(costApplicationMethod, other.costApplicationMethod)
                .append(costApplicationBasis, other.costApplicationBasis).append(rate, other.rate).append(currency, other.currency)
                .append(costCalculationLevel, other.costCalculationLevel)
                .append(useSlidingScales, other.useSlidingScales).append(useMinValue, other.useMinValue).append(minValue, other.minValue)
                .append(minCurrencyCode, other.minCurrencyCode).append(useMaxValue, other.useMaxValue).append(maxValue, other.maxValue)
                .append(maxCurrencyCode, other.maxCurrencyCode).isEquals();
    }

    @Deprecated
    public boolean isUseMinValue() {
        return useMinValue;
    }

    @Deprecated
    public void setUseMinValue(boolean useMinValue) {
        this.useMinValue = useMinValue;
    }

    public BigDecimal getMinValue() {
        return minValue;
    }

    public void setMinValue(BigDecimal minValue) {
        this.minValue = minValue;
    }

    @Deprecated
    public Currency getMinCurrencyCode() {
        return minCurrencyCode;
    }

    @Deprecated
    public void setMinCurrencyCode(Currency minCurrencyCode) {
        this.minCurrencyCode = minCurrencyCode;
    }

    @Deprecated
    public boolean isUseMaxValue() {
        return useMaxValue;
    }

    @Deprecated
    public void setUseMaxValue(boolean useMaxValue) {
        this.useMaxValue = useMaxValue;
    }

    public BigDecimal getMaxValue() {
        return maxValue;
    }

    public void setMaxValue(BigDecimal maxValue) {
        this.maxValue = maxValue;
    }

    @Deprecated
    public Currency getMaxCurrencyCode() {
        return maxCurrencyCode;
    }

    @Deprecated
    public void setMaxCurrencyCode(Currency maxCurrencyCode) {
        this.maxCurrencyCode = maxCurrencyCode;
    }

    public CostingContextType getCostingContextType() {
        return costingContextType;
    }

    public void setCostingContextType(CostingContextType costingContextType) {
        this.costingContextType = costingContextType;
    }

    public ServiceProvider getFreightForwarder() {
        return freightForwarder;
    }

    public void setFreightForwarder(ServiceProvider freightForwarder) {
        this.freightForwarder = freightForwarder;
    }

    public FormulaContainerType getContainerType() {
        return containerType;
    }

    public void setContainerType(FormulaContainerType containerType) {
        this.containerType = containerType;
    }

    public CostRateSourceType getRateSource() {
        return rateSource;
    }

    public void setRateSource(CostRateSourceType rateSource) {
        this.rateSource = rateSource;
    }
}