CostedLineItem.java

package com.tradecloud.domain.costing.clean;

import com.fasterxml.jackson.annotation.JsonManagedReference;
import com.tradecloud.common.base.HibernateUtils;
import com.tradecloud.domain.common.Currency;
import com.tradecloud.domain.costing.CostableType;
import com.tradecloud.domain.item.ItemType;
import com.tradecloud.domain.item.LineItem;
import com.tradecloud.domain.item.VolumeUnitOfMeasure;
import com.tradecloud.domain.item.WeightUnitOfMeasure;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.hibernate.annotations.ForeignKey;

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

@Entity
@Table(name = "costedlineitem")
@Access(AccessType.FIELD)
@XmlAccessorType(XmlAccessType.FIELD)
public class CostedLineItem extends CostedBase<CostedOrder, Costed> implements CostingItem {

    private static final long serialVersionUID = 1L;

    /**
     * The bidirectional link back to the parent {@link CostedOrder}.
     */
    @ManyToOne(optional = false)//, fetch = FetchType.LAZY)
    @ForeignKey(name = "fk_costedorder")
    @XmlIDREF
    @JsonManagedReference
    private CostedOrder costedOrder;
    /*
     * These three costs together add up to the total of all costs related to the supply costs
     */
    private BigDecimal supplyCost;

    /*
     * The two landed cost values
     */
    private BigDecimal unitLandedCost = BigDecimal.ZERO;
    private BigDecimal totalLandedCost = BigDecimal.ZERO;

    /*
     * Properties from line Item required during costing. Must be added with the costed line item is created
     */
    @XmlElement
    protected BigDecimal unitVolume;
    @XmlElement
    protected BigDecimal unitWeight;
    @ManyToOne
    @JoinColumn(name = "weightunitofmeasure")
    @ForeignKey(name = "fk_weightunitofmeasure")
    @XmlElement
    protected WeightUnitOfMeasure weightUnitOfMeasure;
    @ManyToOne
    @JoinColumn(name = "volumeunitofmeasure")
    @ForeignKey(name = "fk_volumeunitofmeasure")
    @XmlElement
    protected VolumeUnitOfMeasure volumeUnitOfMeasure;
    @XmlElement
    protected BigDecimal unitQuantity;
    @XmlElement
    protected BigDecimal unitPrice;
    @XmlElement
    protected BigDecimal dutyPercentage;
    @XmlElement
    protected BigDecimal adValoremPercentage;
    @XmlElement
    protected BigDecimal antiDumpingPercentage;
    @XmlElement
    protected BigDecimal counterVailingPercentage;
    @Enumerated(EnumType.STRING)
    @XmlAttribute(name = "ItemType")
    private ItemType itemtype;

    @ManyToOne
    @JoinColumn(name = "transactioncurrency_code")
    @ForeignKey(name = "fk_transactioncurrency")
    @XmlElement
    @NotNull
    protected Currency transactionCurrency;

    @ManyToOne
    @JoinColumn(name = "costingcurrency_code")
    @ForeignKey(name = "fk_costingcurrency")
    @XmlElement
    @NotNull
    protected Currency costingCurrency;

    @XmlElement(required = true)
    @NotNull(message = "Code is required")
    protected String code;

    @OneToOne(fetch = FetchType.LAZY)
    @XmlElement
    private LineItem lineItem;

    @XmlAttribute
    @Temporal(TemporalType.TIMESTAMP)
    private Date addedToOrderDate;

    // in transaction currency (aka foreign currency)
    private BigDecimal dutiableCost;

    @XmlElement(required = true)
    @NotNull(message = "Description is required")
    private String description;

    private String summaryReference;
    @XmlAttribute
    private boolean vatExemption;

    public BigDecimal getSupplyCost() {
        return supplyCost;
    }

    public void setSupplyCost(BigDecimal supplyCost) {
        this.supplyCost = supplyCost;
    }

    /**
     * Do not use for calculations, it is pre-rounded to 2 decimals. Get from totals distribution
     * @return
     */
    public BigDecimal getUnitLandedCost() {
        return unitLandedCost;
    }

    public void setUnitLandedCost(BigDecimal unitLandedCost) {
        this.unitLandedCost = unitLandedCost;
    }

    /**
     * Do not use for calculations, it is pre-rounded to 2 decimals. Get from totals distribution
     * @return
     */
    public BigDecimal getTotalLandedCost() {
        return totalLandedCost;
    }

    public void setTotalLandedCost(BigDecimal totalLandedCost) {
        this.totalLandedCost = totalLandedCost;
    }

    public BigDecimal getUnitVolume() {
        return unitVolume;
    }

    public void setUnitVolume(BigDecimal unitVolume) {
        this.unitVolume = unitVolume;
    }

    public BigDecimal getUnitWeight() {
        return unitWeight;
    }

    public void setUnitWeight(BigDecimal unitWeight) {
        this.unitWeight = unitWeight;
    }

    public VolumeUnitOfMeasure getVolumeUnitOfMeasure() {
        return volumeUnitOfMeasure;
    }

    @Override
    public BigDecimal getPrice() {
        return getUnitPrice();

    }

    public void setVolumeUnitOfMeasure(VolumeUnitOfMeasure volumeUnitOfMeasure) {
        this.volumeUnitOfMeasure = volumeUnitOfMeasure;
    }

    @Override
    public Costed getRootParent() {
        return getConsignment();
    }

    @Override
    public Costed toCosted() {
        return this;
    }

    @Override
    public BigDecimal getQuantity() {
        return getUnitQuantity();
    }

    public WeightUnitOfMeasure getWeightUnitOfMeasure() {
        return weightUnitOfMeasure;
    }

    public void setWeightUnitOfMeasure(WeightUnitOfMeasure weightUnitOfMeasure) {
        this.weightUnitOfMeasure = weightUnitOfMeasure;
    }

    public BigDecimal getUnitQuantity() {
        return unitQuantity;
    }

    public void setUnitQuantity(BigDecimal unitQuantity) {
        this.unitQuantity = unitQuantity;
    }

    public BigDecimal getUnitPrice() {
        return unitPrice;
    }

    @Override
    public ItemType getItemType() {
        if (lineItem != null)
            return lineItem.getItemType();
        return itemtype;
    }

    public void setItemtype(ItemType itemtype) {
        this.itemtype = itemtype;
    }

    public void setUnitPrice(BigDecimal unitPrice) {
        this.unitPrice = unitPrice;
    }

    public BigDecimal getDutyPercentage() {
        return dutyPercentage;
    }

    public void setDutyPercentage(BigDecimal dutyPercentage) {
        this.dutyPercentage = dutyPercentage;
    }

    public BigDecimal getAdValoremPercentage() {
        return adValoremPercentage;
    }

    public void setAdValoremPercentage(BigDecimal adValoremPercentage) {
        this.adValoremPercentage = adValoremPercentage;
    }

    public Currency getTransactionCurrency() {
        return transactionCurrency;
    }

    public void setTransactionCurrency(Currency transactionCurrency) {
        this.transactionCurrency = transactionCurrency;
    }

    public Currency getCostingCurrency() {
        return costingCurrency;
    }

    public void setCostingCurrency(Currency costingCurrency) {
        this.costingCurrency = costingCurrency;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public LineItem getLineItem() {
        return lineItem;
    }

    public void setLineItem(LineItem lineItem) {
        this.lineItem = lineItem;
    }

    public CostedOrder getCostedOrder() {
        return costedOrder;
    }

    public void setCostedOrder(CostedOrder costedOrder) {
        this.costedOrder = costedOrder;
    }

    @Override
    public void accept(CostingVisitor costingVisitor) {
        costingVisitor.visit(this);
    }

    @Override
    public void acceptVisitParentFirst(CostingVisitor costingVisitor) {
        costingVisitor.visit(this);
    }

    @Override
    public CostedConsignment getConsignment() {
        CostedConsignment consignment = null;
        if (costedOrder != null)
            consignment = costedOrder.getConsignment();
        return consignment;
    }

    public BigDecimal getAntiDumpingPercentage() {
        return antiDumpingPercentage;
    }

    public void setAntiDumpingPercentage(BigDecimal antiDumpingPercentage) {
        this.antiDumpingPercentage = antiDumpingPercentage;
    }

    public BigDecimal getCounterVailingPercentage() {
        return counterVailingPercentage;
    }

    @Override
    public String getOrganisation() {
        if (lineItem != null) {
            return lineItem.getOrganisationalUnit() != null ? lineItem.getOrganisationalUnit().getCode() : null;
        } else {
            return null;
        }
    }

    public void setCounterVailingPercentage(BigDecimal counterVailingPercentage) {
        this.counterVailingPercentage = counterVailingPercentage;
    }

    @Override
    public String toString() {

        StringBuffer displayCostingCurrency = new StringBuffer();
        if (costingCurrency != null) {
            displayCostingCurrency.append(" ");
            displayCostingCurrency.append(costingCurrency.getCode());
        }
        StringBuffer displayString =
                new StringBuffer("CostedLineItem [code=" + code + ", unitLandedCost " + unitLandedCost + displayCostingCurrency);

        if (unitQuantity != null) {
            displayString.append(", unitQuantity " + unitQuantity);
        }

        if (unitWeight != null) {
            displayString.append(", unitWeight " + unitWeight);
        }

        if (unitVolume != null) {
            displayString.append(", unitVolume " + unitVolume);
        }

        displayString.append(", totalLandedCost " + totalLandedCost + displayCostingCurrency);
        displayString.append("]");

        return displayString.toString();
    }

    @Override
    public CostableType getCostableType() {
        return CostableType.ORDER_LINE_ITEM;
    }

    @Override
    public int hashCode() {
        return new HashCodeBuilder()
                .append(code)
                .append(lineItem.getId())
                .append(description)
                .append(summaryReference)
                .append(costedOrder != null ? costedOrder.hashCode() : 0)
                .toHashCode();
    }

    @Override
    public CostedOrder getParent() {
        return costedOrder;
    }

    @Override
    public List<Costed> getCostedChildren() {
        return new ArrayList<>();
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }

        // Do not use class.equals. This can return false for proxy objects
        if (!HibernateUtils.proxyClassEquals(this, obj)) {
            return false;
        }

        CostedLineItem other = (CostedLineItem) obj;
        return new EqualsBuilder()
                .append(code, other.getCode())
                .append(lineItem, other.getLineItem())
                .append(description, other.getDescription())
                .append(costedOrder, other.getCostedOrder())
                .append(summaryReference, other.getSummaryReference())
                .isEquals();
    }

    @Override
    public String getKey() {
        return new StringBuilder(getClass().getCanonicalName()).append("-").append(hashCode()).toString();
    }

    @Deprecated //use getCostedTotals.getDutiableCost()
    public BigDecimal getDutiableCost() {
        return dutiableCost;
    }

    public void setDutiableCost(BigDecimal dutiableCost) {
        this.dutiableCost = dutiableCost;
    }

    @Override
    public String getReference() {
        return code;
    }

    /**
     * @return the addedToOrderDate
     */
    public Date getAddedToOrderDate() {
        return addedToOrderDate;
    }

    /**
     * @param addedToOrderDate the addedToOrderDate to set
     */
    public void setAddedToOrderDate(Date addedToOrderDate) {
        this.addedToOrderDate = addedToOrderDate;
    }

    @Override
    public boolean isItem() {
        return true;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    @Override
    public String getNumber() {
        return null;
    }

    public BigDecimal getTotalPrice() {
        if (getLineItem().getSellPriceExclusiveAmount() != null) {
            return getLineItem().getSellPriceExclusiveAmount().multiply(getUnitQuantity());

        }
        return null;
    }

    public BigDecimal getTotalPriceIncl() {
        if (getLineItem().getSellPriceInclusiveAmount() != null) {
            return getLineItem().getSellPriceInclusiveAmount().multiply(getUnitQuantity());

        }
        return null;
    }

    public String getSummaryReference() {
        return summaryReference;
    }

    public void setSummaryReference(String summaryReference) {
        this.summaryReference = summaryReference;
    }

    @Override
    public boolean isBondedSplitType() {
        return itemtype == ItemType.BONDED;
    }

    @Override
    public boolean isActualItem() {
        return false;
    }

    public boolean isVatExemption() {
        return vatExemption;
    }

    public void setVatExemption(boolean vatExemption) {
        this.vatExemption = vatExemption;
    }
}