ActualConsignment.java

package com.tradecloud.domain.document.invoice;

import com.tradecloud.domain.costing.CostableType;
import com.tradecloud.domain.costing.clean.ActualShipment;
import com.tradecloud.domain.costing.clean.Costed;
import com.tradecloud.domain.costing.clean.CostingVisitor;
import com.tradecloud.domain.export.ExportCosting;
import com.tradecloud.domain.model.ordermanagement.Consignment;
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.Fetch;
import org.hibernate.annotations.FetchMode;
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 = "actualconsignment")
@Access(AccessType.FIELD)
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "ActualConsignment")
public class ActualConsignment extends BaseActual<Costed, ActualOrder> implements Comparable<ActualConsignment> {

    @Transient
    @XmlTransient
    private Logger log = Logger.getLogger(ActualConsignment.class);
    /**
     * The bidirectional link back to the parent {@link ActualShipment}.
     */
    @ManyToOne(fetch = FetchType.LAZY)
    @XmlIDREF
    @ForeignKey(name = "fk_actualshipment")
    private ActualShipment actualShipment;

    /**
     * The bidirectional link back to the parent {@link CostsInvoice}.
     * {@link CommercialInvoice}
     * {@link ServiceProviderInvoice}
     */
    @ManyToOne(fetch = FetchType.LAZY)
    @XmlIDREF
    private CostsInvoice costsInvoice;

    @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 = "ActualOrders")
    @XmlElement(name = "ActualOrder")
    @ForeignKey(name = "fk_actualconsignment")
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "actualConsignment", orphanRemoval = true, fetch = FetchType.LAZY)
    @OrderBy(value = "addedToConsignmentDate")
    @Fetch(value = FetchMode.SELECT)
    private Set<ActualOrder> actualOrders = new LinkedHashSet<ActualOrder>();

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

    @Temporal(TemporalType.TIMESTAMP)
    private Date addedToShipmentDate;

    private static final long serialVersionUID = 1L;

    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
    private ExportCosting exportCosting = new ExportCosting();

    public ActualConsignment() {
    }

    public ActualConsignment(String number, String reference, Long originalId, Date addedToShipmentDate) {
        super(originalId);
        this.number = number;
        this.reference = reference;
        this.addedToShipmentDate = addedToShipmentDate;
    }

    public ActualConsignment(Consignment consignment) {
        this(consignment.getNumber(), consignment.getReference(), consignment.getId(), consignment.getAddedToShipmentDate());
    }

    public ActualConsignment(ActualConsignment consignment) {
        this(consignment.getNumber(), consignment.getReference(), consignment.getOriginalId(), consignment.getAddedToShipmentDate());
    }

    public ActualOrder getOrderWithNumber(String number) {
        for (ActualOrder order : getActualOrders()) {
            if (order.getNumber().equals(number)) {
                return order;
            }
        }
        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;
    }

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

    public void setCostsInvoice(CostsInvoice costsInvoice) {
        this.costsInvoice = costsInvoice;
    }

    public Set<ActualOrder> getActualOrders() {
        return actualOrders;
    }

    public void setActualOrders(Set<ActualOrder> actualOrders) {
        this.actualOrders = actualOrders;
    }

    public void addActualOrder(ActualOrder actualOrder) {
        actualOrders.add(actualOrder);
        actualOrder.setActualConsignment(this);
    }

    public List<ActualOrder> getActualOrderList() {
        return new ArrayList<ActualOrder>(actualOrders);
    }

    public ActualShipment getActualShipment() {
        return actualShipment;
    }

    public void setActualShipment(ActualShipment actualShipment) {
        this.actualShipment = actualShipment;
    }

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

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

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

    @Override
    public BigDecimal getOrderQuantity() {
        // TODO. This should maybe be saved.
        BigDecimal orderQuantity = new BigDecimal("0");
        for (ActualOrder order : getActualOrders()) {
            orderQuantity = orderQuantity.add(order.getOrderQuantity());
        }
        return orderQuantity;
    }

    @Override
    public BigDecimal getInvoiceQuantity() {
        // TODO. This should maybe be saved.
        BigDecimal invoiceQuantity = new BigDecimal("0");
        for (ActualOrder order : getActualOrders()) {
            invoiceQuantity = invoiceQuantity.add(order.getInvoiceQuantity());
        }
        return invoiceQuantity;
    }

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

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

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

    @Override
    public void acceptVisitParentFirst(CostingVisitor costingVisitor) {
        costingVisitor.visit(this);
        for (ActualOrder actualOrder : actualOrders) {
            actualOrder.acceptVisitParentFirst(costingVisitor);
        }
    }

    @Override
    public BigDecimal getTotalInvoiceValue() {
        return totalInvoiceValue;
    }

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

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

    @Override
    public Costed getParent() {
        if (actualShipment != null) {
            return actualShipment;
        }
        return costsInvoice;
    }

    @Override
    public List<ActualOrder> getCostedChildren() {
        return new ArrayList<ActualOrder>(actualOrders);
        /*
        List<ActualOrder> results = new ArrayList<ActualOrder>();
        for (ActualOrder actualOrder : getActualOrderList()) {
            results.add(actualOrder);
        }
        return results;
        */
    }

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

    @Override
    public Object getTraversalKey() {
        return new MultiKey(ActualConsignment.class, number);
    }

    public Collection<? extends ActualLineItem> getActualItems() {
        List<ActualLineItem> actualLineItems = new ArrayList<ActualLineItem>();
        for (ActualOrder actualOrder : actualOrders) {
            actualLineItems.addAll(actualOrder.getActualLineItems());
        }
        return actualLineItems;
    }

    public Date getAddedToShipmentDate() {
        return addedToShipmentDate;
    }

    public void setAddedToShipmentDate(Date addedToShipmentDate) {
        this.addedToShipmentDate = addedToShipmentDate;
    }

    @Override
    public int compareTo(ActualConsignment o) {
        return addedToShipmentDate.compareTo(o.addedToShipmentDate);
    }

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

    public BigDecimal getSumAllOrders() {
        BigDecimal sumAllOrders = BigDecimal.ZERO;
        for (ActualOrder actualOrder : actualOrders) {
            sumAllOrders = sumAllOrders.add(actualOrder.getSumUnitSellingPrice());
        }
        return sumAllOrders;
    }

    public BigDecimal getSumAllOrdersInclVAT() {
        BigDecimal sumAllOrders = BigDecimal.ZERO;
        for (ActualOrder actualOrder : actualOrders) {
            sumAllOrders = sumAllOrders.add(actualOrder.getSumUnitSellingPriceInclVAT());
        }
        return sumAllOrders;
    }

    @Override
    public ExportCosting getExportCosting() {
        return exportCosting;
    }

    public void setExportCosting(ExportCosting exportCosting) {
        this.exportCosting = exportCosting;
    }
}