ActualShipment.java

package com.tradecloud.domain.costing.clean;

import com.tradecloud.common.base.PersistenceBase;
import com.tradecloud.domain.common.Incoterm;
import com.tradecloud.domain.container.ShipmentContainer;
import com.tradecloud.domain.costing.Costable;
import com.tradecloud.domain.costing.CostableCostDefinition;
import com.tradecloud.domain.costing.CostableType;
import com.tradecloud.domain.costing.CostingContextType;
import com.tradecloud.domain.document.invoice.*;
import com.tradecloud.domain.model.organisationalunit.OrganisationalUnit;
import com.tradecloud.domain.model.shipment.ShippingMode;
import com.tradecloud.domain.shipment.Shipment;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.collections4.keyvalue.MultiKey;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.log4j.Logger;
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.*;

@Entity
@Table(name = "actualshipment")
@Access(AccessType.FIELD)
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "ActualShipment")
@Getter
@Setter
public class ActualShipment extends BaseActual<Costed, ActualConsignment> implements Costable {

    @Transient
    @XmlTransient
    private Logger log = Logger.getLogger(ActualShipment.class);

    @NotNull
    @XmlAttribute(required = true)
    @XmlID
    // XML id used for setting parent ActualConsignment in child ActualOrder
    private String number;

    @NotNull
    @XmlAttribute(required = true)
    @XmlID
    // XML id used for setting parent ActualConsignment in child ActualOrder
    private String reference;

    @XmlElementWrapper(name = "ActualConsignments")
    @XmlElement(name = "ActualConsignment")
    @ForeignKey(name = "fk_actualconsignment")
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "actualShipment", orphanRemoval = true, fetch = FetchType.LAZY)
    @OrderBy(value = "addedToShipmentDate")
    private Set<ActualConsignment> actualConsignments = new LinkedHashSet<ActualConsignment>();

    @NotNull
    @Basic(optional = false)
    @Column(name = "totalvalue")
    private BigDecimal totalInvoiceValue = new BigDecimal("0.00");

    @ManyToOne
    @XmlElement(name = "OrganisationalUnit")
    private OrganisationalUnit organisationalUnit;

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

    @Enumerated(value = EnumType.STRING)
    @XmlAttribute
    private ShippingMode multiModalShippingMode;

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

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

    @ManyToOne
    @XmlElement(name = "OrganisationalUnit")
    private static final long serialVersionUID = 1L;

    public ActualShipment() {
    }

    public ActualShipment(Shipment shipment) {
        super(shipment.getId());
        this.number = shipment.getNumber();
        this.reference = shipment.getReference();

        this.organisationalUnit = shipment.getOrganisationalUnit();
//        this.containers = cloneContainers(shipment);//use containers in shipment
        this.shippingMode = shipment.getShippingMode();
        this.multiModalShippingMode = shipment.getMultiModalShippingMode();
        this.arrivalDateAtPlaceOfDischarge = shipment.getArrivalDateAtPlaceOfDischarge();
        this.incoterm = shipment.getIncoterm();
    }

//    private Set<ShipmentContainer> cloneContainers(Shipment shipment){
//        Set<ShipmentContainer> toReturn = new HashSet<ShipmentContainer>();
//        for (ShipmentContainer container : shipment.getContainers()){
//            ShipmentContainer shipmentContainer = new ShipmentContainer(container);
//            shipmentContainer.setShipment(null);    //work around for bug tc-807
//            toReturn.add(shipmentContainer);
//        }
//        return toReturn;
//    }

    public ActualConsignment getConsignmentWithNumber(String number) {
        for (ActualConsignment actualConsignment : getActualConsignments()) {
            if (actualConsignment.getNumber().equals(number)) {
                return actualConsignment;
            }
        }
        return null;
    }

    public String getNumber() {
        return number;
    }

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

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

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

    public Set<ActualConsignment> getActualConsignments() {
        return actualConsignments;
    }

    public void setActualConsignments(Set<ActualConsignment> actualConsignments) {
        this.actualConsignments = actualConsignments;
    }

    public void addActualConsignment(ActualConsignment actualConsignment) {
        actualConsignments.add(actualConsignment);
        actualConsignment.setActualShipment(this);
    }

    public List<ActualConsignment> getActualConsignmentList() {
        return new ArrayList<ActualConsignment>(actualConsignments);
    }

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

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (!(obj instanceof ActualShipment)) {
            return false;
        }
        ActualShipment other = (ActualShipment) obj;
        return new EqualsBuilder().append(number, other.number).append(reference, other.reference).isEquals();
    }

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

    public BigDecimal getTotalInvoiceValue() {
        return totalInvoiceValue;
    }

    public void setTotalInvoiceValue(BigDecimal totalValue) {
        this.totalInvoiceValue = totalValue;
    }

    public Object getTraversalKey() {
        return new MultiKey(ActualShipment.class, number);
    }

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

    @Override
    public void setOrderQuantity(BigDecimal orderQuantity) {
        // TODO Auto-generated method stub
    }

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

    @Override
    public void setInvoiceQuantity(BigDecimal invoiceQuantity) {
        // TODO Auto-generated method stub
    }

    @Override
    public CostsInvoice getCostsInvoice() {
        return null;
    }

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

    @Override
    public void accept(CostingVisitor costingVisitor) {
        for (ActualConsignment actualConsignment : actualConsignments) {
            actualConsignment.accept(costingVisitor);
        }
        if (costingVisitor != null) {
            costingVisitor.visit(this);
        } else {
            log.error("Null CostingVisitor passed to ActualShipment: " + getId() + ", " + getReference());
        }
    }

    @Override
    public void acceptVisitParentFirst(CostingVisitor costingVisitor) {
        costingVisitor.visit(this);
        for (ActualConsignment actualConsignment : actualConsignments) {
            actualConsignment.acceptVisitParentFirst(costingVisitor);
        }
        costingVisitor.visit(this);
    }

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

    @Override
    public List<ActualConsignment> getCostedChildren() {
        return new ArrayList<ActualConsignment>(actualConsignments);
        /*
        List<ActualConsignment> results = new ArrayList<ActualConsignment>();
        for (ActualConsignment actualConsignment : getActualConsignmentList()) {
            results.add(actualConsignment);
        }
        return results;
        */
    }

    public List<ActualLineItem> getActualLineItems() {
        List<ActualLineItem> actualLineItems = new ArrayList<ActualLineItem>();
        for (ActualConsignment actualConsignment : getActualConsignments()) {
            for (ActualOrder actualOrder : actualConsignment.getActualOrders()) {
                actualLineItems.addAll(actualOrder.getActualLineItems());
            }
        }
        return actualLineItems;
    }

    public List<ActualOrder> getActualOrders() {
        List<ActualOrder> actualOrders = new ArrayList<ActualOrder>();
        for (ActualConsignment actualConsignment : getActualConsignments()) {
            actualOrders.addAll(actualConsignment.getActualOrderList());
        }
        return actualOrders;
    }

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

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

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

    @Override
    public Set<ShipmentContainer> getContainers() {
        throw new IllegalStateException("Use Containers in shipment");
    }

    @Override
    public ShippingMode getShippingMode() {
        return shippingMode;
    }

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

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

    @Override
    public List<? extends PersistenceBase> getLineItems() {
        return null;
    }

    public void setArrivalDateAtPlaceOfDischarge(Date arrivalDateAtPlaceOfDischarge) {
        this.arrivalDateAtPlaceOfDischarge = arrivalDateAtPlaceOfDischarge;
    }

//    public void setContainers(Set<ShipmentContainer> containers) {
//        this.containers = containers;
//    }

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

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

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

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

    @Override
    public void setCostableCostDefinition(CostableCostDefinition costableCostDefinition) {

    }

    public BigDecimal getSumAllConsignmentExVAT() {
        BigDecimal sum = BigDecimal.ZERO;
        for (ActualConsignment actualConsignment : actualConsignments) {
            sum = sum.add(actualConsignment.getSumAllOrders());
        }
        return sum;
    }

    public BigDecimal getSumAllConsignmentInVAT() {
        BigDecimal sum = BigDecimal.ZERO;
        for (ActualConsignment actualConsignment : actualConsignments) {
            sum = sum.add(actualConsignment.getSumAllOrdersInclVAT());
        }
        return sum;
    }

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

    @Override
    public CostingContextType getCostingContextType() {
        throw new RuntimeException("todo");
    }
}