CostedConsignment.java

package com.tradecloud.domain.costing.clean;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.tradecloud.common.base.HibernateUtils;
import com.tradecloud.domain.common.Incoterm;
import com.tradecloud.domain.container.ConsignmentContainer;
import com.tradecloud.domain.costing.Costable;
import com.tradecloud.domain.costing.CostableCostDefinition;
import com.tradecloud.domain.costing.CostableType;
import com.tradecloud.domain.document.invoice.ActualConsignment;
import com.tradecloud.domain.model.ordermanagement.Order;
import com.tradecloud.domain.model.organisationalunit.OrganisationalUnit;
import com.tradecloud.domain.model.shipment.ShippingMode;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.annotations.ForeignKey;
import org.hibernate.annotations.NaturalId;

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

@Entity
@Table(name = "costedconsignment")
@Access(AccessType.FIELD)
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "CostedConsignment")
public class CostedConsignment extends CostedBase<Costed, CostedOrder> implements Costable {

    private static final long serialVersionUID = 1L;

    @XmlElementWrapper(name = "CostedOrders")
    @XmlElement(name = "CostedOrder")
    @OrderBy("addedToConsignmentDate")
    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
    @Fetch(value = FetchMode.SELECT)
    @JsonIgnore
    private Set<CostedOrder> costedOrders = new LinkedHashSet<CostedOrder>();

    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
    @Fetch(value = FetchMode.SELECT)
    @XmlElementWrapper(name = "CostedContainers")
    @XmlElement(name = "CostedContainer")
    private Set<CostedContainer> costedContainers = new LinkedHashSet<CostedContainer>();

    @NotNull
    @ManyToOne(fetch = FetchType.LAZY)
    @XmlElement(name = "Incoterm")
    private Incoterm incoterm;

    @ManyToOne(fetch = FetchType.LAZY)
    @ForeignKey(name = "fk_organisationalunit")
    @XmlElement(name = "OrganisationalUnit")
    @JsonIgnore
    private OrganisationalUnit organisationalUnit;
    //not required for ExportConsignment, validation moved to service layer
    //@NotNull
    @XmlElement(name = "EstimatedArrivalDate")
    private Date estimatedArrivalDate;

    @NotNull(message = "Number should not be null")
    @XmlAttribute
    @NaturalId
    @XmlID
    private String number;

    @NotNull(message = "Reference should not be null")
    @XmlAttribute
    @XmlID
    private String reference;

    private String summaryReference;

    public CostedConsignment() {
    }

    public CostedConsignment(String number, String reference) {
        this.number = number;
        this.reference = reference;
    }

    public Set<CostedOrder> getCostedOrders() {
        return costedOrders;
    }

    public void setCostedOrders(Set<CostedOrder> costedOrders) {
        this.costedOrders = costedOrders;
    }

    public List<CostedOrder> getCostedOrdersList() {
        return new ArrayList<CostedOrder>(costedOrders);
    }

    public void addCostedOrder(CostedOrder costedOrder) {
        this.getCostedOrders().add(costedOrder);
        costedOrder.setCostedConsignment(this);
    }

    @Override
    public Incoterm getIncoterm() {
        return incoterm;
    }

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

    @Override
    public OrganisationalUnit getOrganisationalUnit() {
        return organisationalUnit;
    }

    public void setOrganisationalUnit(OrganisationalUnit organisationalUnit) {
        this.organisationalUnit = organisationalUnit;
    }

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

    @Override
    public ShippingMode getShippingMode() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public List<CostedLineItem> getLineItems() {
        List<CostedLineItem> lineItems = new ArrayList<CostedLineItem>();
        for (CostedOrder costedOrder : getCostedOrders()) {
            costedOrder.getCostedLineItems(lineItems);
        }
        return lineItems;
    }

    @Override
    public Date getArrivalDateAtPlaceOfDischarge() {
        return estimatedArrivalDate;
    }

    public void setEstimatedArrivalDate(Date estimatedArrivalDate) {
        this.estimatedArrivalDate = estimatedArrivalDate;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    public String getReference() {
        return reference;
    }

    public void setReference(String reference) {
        this.reference = reference;
    }

    @Deprecated
    //use the containers on the Consignment
    public Set<CostedContainer> getCostedContainers() {
        return costedContainers;
    }

    @Deprecated
    //use the containers on the Consignment
    public void setCostedContainers(Set<CostedContainer> costedContainers) {
        this.costedContainers = costedContainers;
    }

    public Date getEstimatedArrivalDate() {
        return estimatedArrivalDate;
    }

    @Override
    public void accept(CostingVisitor costingVisitor) {
        for (CostedOrder costedOrder : costedOrders) {
            costedOrder.accept(costingVisitor);
        }
        costingVisitor.visit(this);
    }

    @Override
    public void acceptVisitParentFirst(CostingVisitor costingVisitor) {
        costingVisitor.visit(this);
        for (CostedOrder costedOrder : costedOrders) {
            costedOrder.acceptVisitParentFirst(costingVisitor);
        }

    }

    @Override
    public Costed getParent() {
        return null;
    }

    @Override
    public List<CostedOrder> getCostedChildren() {
        List<CostedOrder> results = new ArrayList<CostedOrder>();
        for (CostedOrder costedOrder : getCostedOrdersList()) {
            results.add(costedOrder);
        }
        return results;
    }

    @Override
    public CostedConsignment getConsignment() {
        return this;
    }

    @Override
    public String toString() {
        return "CostedConsignment [number=" + number + ", reference=" + reference + "]";
    }

    @Override
    public int hashCode() {
        return new HashCodeBuilder().append(number).append(reference).append(summaryReference).toHashCode();
    }

    @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;
        }

        CostedConsignment other = (CostedConsignment) obj;
        return new EqualsBuilder()
                .append(number, other.getNumber())
                .append(reference, other.getReference())
                .append(summaryReference, other.getSummaryReference())
                .isEquals();
    }

    @Override
    public Set<? extends ConsignmentContainer> getContainers() {
        return costedContainers;
    }

    public List<CostedLineItem> getAllCostedLineItems() {
        List<CostedLineItem> costedLineItems = new ArrayList<CostedLineItem>();
        for (CostedOrder costedOrder : costedOrders) {
            costedLineItems.addAll(costedOrder.getCostedLineItems());
        }
        return costedLineItems;
    }

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

    public CostedOrder getCostedOrder(Order order) {
        for (CostedOrder costedOrder : costedOrders) {
            if (CostingStructureMatcher.match(order, costedOrder)) {
                return costedOrder;
            }
        }
        return null;
    }

    public BigDecimal getUnitQuantity() {
        BigDecimal sumAllOrders = BigDecimal.ZERO;
        for (CostedOrder costedOrder : costedOrders) {
            sumAllOrders = sumAllOrders.add(costedOrder.getUnitQuantity());
        }
        return sumAllOrders;
    }

    public BigDecimal getSumAllOrders() {
        BigDecimal sumAllOrders = BigDecimal.ZERO;
        for (CostedOrder costedOrder : costedOrders) {
            sumAllOrders = sumAllOrders.add(costedOrder.getSumUnitSellingPrice());
        }
        return sumAllOrders;
    }

    public BigDecimal getSumAllOrdersInclVAT() {
        BigDecimal sumAllOrders = BigDecimal.ZERO;
        for (CostedOrder costedOrder : costedOrders) {
            sumAllOrders = sumAllOrders.add(costedOrder.getSumUnitSellingPriceInclVAT());
        }
        return sumAllOrders;
    }

    public BigDecimal getAllOrderTotals() {
        BigDecimal sumAllOrders = BigDecimal.ZERO;
        for (CostedOrder costedOrder : costedOrders) {
            sumAllOrders = sumAllOrders.add(costedOrder.getAllItemTotals());
        }
        return sumAllOrders;
    }

    public boolean match(ActualConsignment actualConsignment) {
        return this.reference.equals(actualConsignment.getReference()) && this.number.equals(actualConsignment.getNumber());
    }

    @Override
    public CostableCostDefinition getCostableCostDefinition() {
        return null;
    }

    @Override
    public void setCostableCostDefinition(CostableCostDefinition costableCostDefinition) {

    }

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

    public String getSummaryReference() {
        return summaryReference;
    }

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

    @Override
    public ShippingMode getMultiModalShippingMode() {
        return null;
    }
}