BaseCommercialInvoice.java

package com.tradecloud.domain.document.invoice;

import com.tradecloud.common.base.HibernateUtils;
import com.tradecloud.domain.costing.clean.Costed;
import com.tradecloud.domain.costing.clean.CostingVisitor;
import com.tradecloud.domain.document.DocumentType;
import com.tradecloud.domain.document.PaymentState;
import com.tradecloud.domain.exchangerate.RateOfExchanges;
import com.tradecloud.domain.export.ExportParty;
import com.tradecloud.domain.model.organisationalunit.OrganisationalUnit;
import com.tradecloud.domain.model.payment.ActualPaymentBasis;
import com.tradecloud.domain.model.payment.EstimatedPaymentBasis;
import com.tradecloud.domain.settlement.PlannedSettlement;
import com.tradecloud.domain.supplier.Creditor;
import com.tradecloud.domain.supplier.OrganisationalUnitSupplier;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;

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

/**
 * Created by ds on 2015/10/28.
 */
@MappedSuperclass
public abstract class BaseCommercialInvoice extends CostsInvoice implements RateOfExchanges {

    private transient BigDecimal spotRate;

    private transient BigDecimal forwardRate;

    public BaseCommercialInvoice() {
    }

    public BaseCommercialInvoice(OrganisationalUnit organisationalUnit, OrganisationalUnitSupplier supplier, BigDecimal quantity,
                                 UnitPricePerItem unitPricePerItem) {
        super();
        this.organisationalUnit = organisationalUnit;
        this.supplier = supplier;
        this.quantity = quantity;
        this.unitPricePerItem = unitPricePerItem;
    }

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

    //TODO: validate somewhere else@NotNull(message = "supplier is required")
    //@ScriptAssert(lang = "javascript", script = "_this.value1 != null || _this != value2)")
    @ManyToOne
    @XmlElement(name = "Supplier")
    private OrganisationalUnitSupplier supplier;

    @ManyToOne(fetch = FetchType.LAZY)
    private ExportParty exportParty;

    @NotNull(message = "quantity is required")
    @XmlAttribute
    private BigDecimal quantity;

    @Enumerated(EnumType.STRING)
    @XmlAttribute
    private UnitPricePerItem unitPricePerItem;

    public OrganisationalUnit getOrganisationalUnit() {
        return organisationalUnit;
    }

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

    @Override
    public OrganisationalUnitSupplier getSupplier() {
        return supplier;
    }

    public void setSupplier(OrganisationalUnitSupplier supplier) {
        this.supplier = supplier;
    }

    public BigDecimal getQuantity() {
        return quantity;
    }

    public void setQuantity(BigDecimal quantity) {
        this.quantity = quantity;
    }

    public UnitPricePerItem getUnitPricePerItem() {
        return unitPricePerItem;
    }

    public void setUnitPricePerItem(UnitPricePerItem unitPricePerItem) {
        this.unitPricePerItem = unitPricePerItem;
    }

    @Override
    public DocumentType getDocumentType() {
        return DocumentType.COMMERCIAL_INVOICE;
    }

    @Override
    public Creditor getCreditor() {
        return supplier;
    }

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

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

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

    @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;
        }
        BaseCommercialInvoice other = (BaseCommercialInvoice) obj;

        return new EqualsBuilder()
                .appendSuper(super.equals(obj))
                .append(supplier, other.getSupplier())
                .append(reference, other.getReference())
                .append(shipment, other.getShipment())
                .isEquals();
    }

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

    @Override
    public BigDecimal getOrderQuantity() {
        BigDecimal orderQuantity = new BigDecimal("0");
        for (ActualConsignment ac : getActualConsignments()) {
            orderQuantity = orderQuantity.add(ac.getOrderQuantity());
        }
        return orderQuantity;
    }

    @Override
    public BigDecimal getInvoiceQuantity() {
        BigDecimal invoiceQuantity = new BigDecimal("0");
        for (ActualConsignment ac : getActualConsignments()) {
            invoiceQuantity = invoiceQuantity.add(ac.getInvoiceQuantity());
        }
        return invoiceQuantity;
    }

    @Override
    public void setOrderQuantity(BigDecimal orderQuantity) {
        // Needed by JSF but they are not settable values
    }

    @Override
    public void setInvoiceQuantity(BigDecimal invoiceQuantity) {
    }

    @Override
    public abstract Object getTraversalKey();

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

    public ActualOrder findFirstActualOrder() {
        Set<ActualConsignment> actualConsignments = this.getActualConsignments();

        if (!actualConsignments.isEmpty()) {
            ActualConsignment actualConsignment = actualConsignments.iterator().next();
            List<ActualOrder> actualOrderList = actualConsignment.getActualOrderList();

            if (!actualOrderList.isEmpty()) {
                return actualOrderList.get(0);
            }
        }

        return null;
    }

    @Override
    public BigDecimal getSpotRate() {
        return spotRate;
    }

    @Override
    public void setSpotRate(BigDecimal spotRate) {
        this.spotRate = spotRate;
    }

    @Override
    public BigDecimal getForwardRate() {
        return forwardRate;
    }

    @Override
    public void setForwardRate(BigDecimal forwardRate) {
        this.forwardRate = forwardRate;
    }

    @Override
    public PaymentState getPaymentState() {
        return PaymentState.UNSETTLED;
    }

    @Override
    public ActualPaymentBasis getActualPaymentBasis() {
        return this.getSupplier().getActualPaymentBasis();
    }

    @Override
    public EstimatedPaymentBasis getEstimatedPaymentBasis() {
        return this.getSupplier().getEstimatedPaymentBasis();
    }

    @Override
    public EstimatedPaymentBasis getEstimatedPaymentBasis2() {
        return supplier.getSupplier().getEstimatedPaymentBasis2();
    }

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

    public abstract List<PlannedSettlement> getPlannedSettlementList();

    public ExportParty getExportParty() {
        return exportParty;
    }

    public void setExportParty(ExportParty exportParty) {
        this.exportParty = exportParty;
    }
}