InvoiceLineItem.java

package com.tradecloud.domain.item;

import com.tradecloud.domain.common.Currency;
import com.tradecloud.domain.common.Incoterm;
import com.tradecloud.domain.document.invoice.CommercialInvoice;
import com.tradecloud.domain.model.ordermanagement.Order;
import com.tradecloud.domain.settlement.GoodsReceivedAllocation;
import com.tradecloud.domain.shipment.Shipment;

import javax.persistence.*;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import java.math.BigDecimal;
import java.util.*;

@Entity
@Table(name = "invoicelineitem")
@Access(AccessType.FIELD)
@XmlAccessorType(XmlAccessType.FIELD)
public class InvoiceLineItem extends AbstractIncotermBasedDocumentLineItem {

    private static final long serialVersionUID = 1L;

    /**
     * Parent.
     */
    @ManyToOne
    private CommercialInvoice invoice;

    private BigDecimal unitWeight;
    private BigDecimal unitVolume;
    @ManyToOne
    private WeightUnitOfMeasure weightUOM;
    @ManyToOne
    private VolumeUnitOfMeasure volumeUOM;
    private String tariffHeading;
    private BigDecimal estimatePrice;
    private BigDecimal invoicePrice;
    private BigDecimal orderQuantity;
    private BigDecimal sourceQuantity;
    private BigDecimal packedQuantity;

    @ManyToOne
    private PackingSlipLineItem packingSlipLineItem;

    @OneToMany
    private Set<GoodsReceivedAllocation> goodsReceivedAllocations = new HashSet<GoodsReceivedAllocation>();
    @OneToMany
    private Set<CreditNoteLineItem> creditNoteLineItems = new HashSet<CreditNoteLineItem>();

    private String orderRef;
    private String packingSlipRef;
    private String rplNumber;
    private String deliveryNoteRef;
    private String deliveryNoteItemRef;
    private String orderItemReference;

    @ManyToOne
    private Shipment shipment;
    private String articleNumber;
    private String customerReference;
    @ManyToOne
    private UnitType unitType;

    public BigDecimal getUnitWeight() {
        return unitWeight;
    }

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

    public BigDecimal getUnitVolume() {
        return unitVolume;
    }

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

    public BigDecimal getEstimatePrice() {
        return estimatePrice;
    }

    public void setEstimatePrice(BigDecimal estimatePrice) {
        this.estimatePrice = estimatePrice;
    }

    public BigDecimal getInvoicePrice() {
        return invoicePrice;
    }

    public void setInvoicePrice(BigDecimal invoicePrice) {
        this.invoicePrice = invoicePrice;
    }

    public BigDecimal getOrderQuantity() {
        return orderQuantity;
    }

    public void setOrderQuantity(BigDecimal orderQuantity) {
        this.orderQuantity = orderQuantity;
    }

    public BigDecimal getSourceQuantity() {
        return sourceQuantity;
    }

    public void setSourceQuantity(BigDecimal sourceQuantity) {
        this.sourceQuantity = sourceQuantity;
    }

    public BigDecimal getPackedQuantity() {
        return packedQuantity;
    }

    public void setPackedQuantity(BigDecimal packedQuantity) {
        this.packedQuantity = packedQuantity;
    }

    public String getOrderItemReference() {
        return orderItemReference;
    }

    public void setOrderItemReference(String orderItemReference) {
        this.orderItemReference = orderItemReference;
    }

    public String getDeliveryNoteItemRef() {
        return deliveryNoteItemRef;
    }

    public void setDeliveryNoteItemRef(String deliveryNoteItemRef) {
        this.deliveryNoteItemRef = deliveryNoteItemRef;
    }

    public String getDeliveryNoteRef() {
        return deliveryNoteRef;
    }

    public void setDeliveryNoteRef(String deliveryNoteRef) {
        this.deliveryNoteRef = deliveryNoteRef;
    }

    /**
     * Simple constructor of InvoiceLineItem instances.
     */
    public InvoiceLineItem() {
    }

    public String getTariffHeading() {
        return tariffHeading;
    }

    public void setTariffHeading(String tariffHeading) {
        this.tariffHeading = tariffHeading;
    }

    public CommercialInvoice getInvoice() {
        return invoice;
    }

    public void setInvoice(CommercialInvoice invoice) {
        this.invoice = invoice;
    }

    public PackingSlipLineItem getPackingSlipLineItem() {
        return packingSlipLineItem;
    }

    public void setPackingSlipLineItem(PackingSlipLineItem packingSlipLineItem) {
        this.packingSlipLineItem = packingSlipLineItem;
    }

    public void setUnitQuantity(BigDecimal unitQuantity) {
        super.setUnitQuantity(unitQuantity);
    }

    public Set getGoodsReceivedAllocations() {
        return goodsReceivedAllocations;
    }

    public void addGoodsReceivedAllocation(GoodsReceivedAllocation allocation) {
        // allocation.setInvoiceLineItem(this);
        getGoodsReceivedAllocations().add(allocation);
    }

    public Set getCreditNoteLineItems() {
        return creditNoteLineItems;
    }

    public void addCreditNoteLineItem(CreditNoteLineItem creditNoteLineItem) {
        // creditNoteLineItem.setInvoiceLineItem(this);
        getCreditNoteLineItems().add(creditNoteLineItem);
    }

    private LineItem getEffectiveOrderLineItem() {
        // Apparently unnecessary to look deeper - will always be filled in if
        // packing slip is chosen and
        // packing slip is directly or indirectly linked to an order
        return getOrderLineItem();
        // LineItem orderLineItem = getOrderLineItem();
        // if ( orderLineItem != null ) {
        // return orderLineItem;
        // }
        // else {
        // PackingSlipLineItem packingSlipLineItem = getPackingSlipLineItem();
        // return packingSlipLineItem != null ?
        // packingSlipLineItem.getOrderLineItem() : null;
        // }
    }

    public Currency getCurrency(boolean atCostNotSale) {
        CommercialInvoice invoice = getInvoice();
        return invoice.getCurrency();
    }

    private BigDecimal getUnitCostPrice() {
        return getInvoicePrice();
    }

    private BigDecimal getUnitSalePrice() {
        return getInvoicePrice();
    }

    /**
     * Try to retrieve a cost currency from this export invoice item's
     * associated order item or catalogue item Precondition:
     * getInvoice().isExport() == true.
     *
     * @return
     */
    private Currency deriveExportCostCurrency() {
        LineItem orderLineItem = getEffectiveOrderLineItem();
        if (orderLineItem != null) {
            return null;// orderLineItem.getCurrency();
        } else {
            Product item = getProduct();
            if (item != null) {
                Currency currency = item.getCurrency();
                if (currency != null) {
                    return currency;
                }
            }
            // Fall back on invoice item's sale currency
            return invoice.getCurrency();
        }
    }

    /**
     * Try to retrieve a unit cost BigDecimal from this export invoice item's
     * associated order item or catalogue item Precondition:
     * getInvoice().isExport() == true.
     *
     * @return
     */
    private BigDecimal deriveExportUnitCostPrice() {
        LineItem orderLineItem = getEffectiveOrderLineItem();
        // if (orderLineItem != null)
        // {
        // return orderLineItem.getUnitCostPrice();
        // }
        // else
        // {
        // Product item = getProduct();
        // if (item != null)
        // {
        // BigDecimal unitPrice = item.getUnitPrice();
        // Currency currency = item
        // .getPurchaseCurrencyCode());
        // if (currency != null)
        // {
        // return new Price(unitPrice, currency, item.getUnitType());
        // }
        // }
        // Fall back on invoice item's unit sale price
        return getUnitSalePrice();
        // }
    }

    public boolean isUnitCostPriceSpecified() {
        return true;
    } // getInvoice().isImport(); }

    public boolean isUnitSalePriceSpecified() {
        // return getInvoice().isExport();
        // TODO don't have isExport on invoice anymore.
        return false;
    }

    public boolean isUnitCostPriceOverridden(Incoterm incoterm) {
        return false;
    } // getInvoice().isImport(); }

    public boolean isUnitSalePriceOverridden(Incoterm incoterm) {
        return false;
    } // getInvoice().isExport(); }

    // public BigDecimal getAmountAtPriceIncoterm(boolean atCostNotSale)
    // {
    // return atCostNotSale ? getCostAmountAtPriceIncoterm()
    // : getSaleAmountAtPriceIncoterm();
    // }
    //
    // private BigDecimal getCostAmountAtPriceIncoterm()
    // {
    // BigDecimal price = getUnitCostPrice();
    // return BigDecimal != null ? new BigDecimal(price.BigDecimalValue()
    // * getUnitQuantity(), price.getCurrency()) : null;
    // }
    //
    // private BigDecimal getSaleAmountAtPriceIncoterm()
    // {
    // BigDecimal price = getUnitSalePrice();
    // return BigDecimal != null ? new BigDecimal(price.BigDecimalValue()
    // * getUnitQuantity(), price.getCurrency()) : null;
    // }
    //
    // public BigDecimal getNettUnitQuantity()
    // {
    // BigDecimal creditedQuantity = 0.0;
    // for (Iterator iter = getCreditNoteLineItems().iterator(); iter
    // .hasNext();)
    // {
    // CreditNoteLineItem creditNoteLineItem = (CreditNoteLineItem) iter
    // .next();
    // creditedQuantity += creditNoteLineItem.getUnitQuantity();
    // }
    // return new Quantity(getUnitQuantity() - creditedQuantity, null);
    // }
    //
    // public BigDecimal getNettAmountAtPriceIncoterm(boolean atCostNotSale)
    // {
    // BigDecimal invoicedAmount = getAmountAtPriceIncoterm(atCostNotSale);
    // if (invoicedAmount == null)
    // return null;
    // BigDecimal nettAmount = invoicedAmount;
    //
    // if (isPrimaryType(atCostNotSale))
    // {
    // for (Iterator iter = getCreditNoteLineItems().iterator(); iter
    // .hasNext();)
    // {
    // CreditNoteLineItem creditNoteLineItem = (CreditNoteLineItem) iter
    // .next();
    // BigDecimal creditedAmount = creditNoteLineItem
    // .getAmountAtPriceIncoterm(atCostNotSale);
    // if (creditedAmount == null || creditedAmount.isZero())
    // continue;
    // nettAmount = nettAmount.subtract(creditedAmount);
    // }
    // }
    // return nettAmount;
    // }
    //
    // public BigDecimal getNettUnitPrice(boolean atCostNotSale)
    // {
    // BigDecimal amt = getNettAmountAtPriceIncoterm(atCostNotSale);
    // return amt != null ? amt.divideBy(getNettUnitQuantity()) : null;
    // }
    //
    // public Route getRoute()
    // {
    // if (this.getOrderLineItem() == null)
    // return null;
    // else
    // {
    // Route orderRoute = this.getOrderLineItem().getOrder().getRoute();
    // Route shipmentRoute = new Route(orderRoute.getOriginID(),
    // orderRoute.getForwardingDepotID(), this.getInvoice()
    // .getShipment().getPlaceOfLoadingID(), this
    // .getInvoice().getShipment().getPlaceOfDischargeID(),
    // orderRoute.getDepotID(),
    // orderRoute.getNamedPlaceID());
    // return shipmentRoute;
    // }
    // }
    //
    // public IncotermBasedDocument getDocument()
    // {
    // return getInvoice();
    // }

    public Long getOrderID() {
        LineItem orderLineItem = getOrderLineItem();
        if (orderLineItem != null) {
            Order order = orderLineItem.getOrder();
            return order != null ? order.getId() : null;
        }
        return null;
    }

    public Map getNettAmountsByIncoterm(boolean atCostNotSale) {
        Map invoicedAmountsByIncoterm = getAmountsByIncoterm(atCostNotSale);
        Map nettAmountsByIncoterm = invoicedAmountsByIncoterm;

        if (isPrimaryType(atCostNotSale)) {
            Set creditNoteLineItems = getCreditNoteLineItems();

            // for (Iterator iter = creditNoteLineItems.iterator();
            // iter.hasNext();) {
            // CreditNoteLineItem creditNoteLineItem = (CreditNoteLineItem)
            // iter.next();
            // Map creditedAmountsByIncoterm =
            // creditNoteLineItem.getAmountsByIncoterm(atCostNotSale);
            //
            // for (Iterator iterator =
            // creditedAmountsByIncoterm.keySet().iterator();
            // iterator.hasNext();) {
            // Incoterm creditedIncoterm = (Incoterm) iterator.next();
            // BigDecimal creditedAmount = (BigDecimal)
            // creditedAmountsByIncoterm.get(creditedIncoterm);
            // if (creditedAmount == null || creditedAmount.isZero())
            // continue;
            //
            // BigDecimal nettAmount = (BigDecimal)
            // nettAmountsByIncoterm.get(creditedIncoterm);
            // if (nettAmount == null) { // should never reach this code -
            // // credit notes incoterms
            // // are invoice's incoterms
            // List incoterms = new
            // ArrayList(invoicedAmountsByIncoterm.keySet());
            // Incoterm closestIncoterm =
            // Incoterm.findClosestIncoterm(creditedIncoterm, incoterms, true,
            // true, true);
            // nettAmount = (BigDecimal)
            // nettAmountsByIncoterm.get(closestIncoterm);
            // new
            // Exception("Should never get here").fillInStackTrace().printStackTrace();
            // }
            // nettAmount = nettAmount.subtract(creditedAmount);
            // nettAmountsByIncoterm.put(creditedIncoterm, nettAmount);
            // }
            // }
        }
        return nettAmountsByIncoterm;
    }

    /**
     * Returns true if this invoice line item's "primary type" matches the given
     * atCostNotSale flag. An import invoice line item will only return true if
     * the given flag is true. An export invoice line item will only return true
     * if the given flag is false.
     *
     * @param atCostNotSale
     * @return
     */
    private boolean isPrimaryType(boolean atCostNotSale) {
        boolean export = true;// !getInvoice().isImport();
        return atCostNotSale ^ export; // return (atCostNotSale && !export) ||
        // (!atCostNotSale && export);
    }

    /**
     * @return
     */
    public Map getNettPricesByIncoterm(boolean atCostNotSale) {
        Map nettAmountsByIncoterm = getNettAmountsByIncoterm(atCostNotSale);
        Map nettPricesByIncoterm = new HashMap(nettAmountsByIncoterm.size());
        BigDecimal nettQuantity = getNettUnitQuantity();
        for (Iterator iter = nettAmountsByIncoterm.keySet().iterator(); iter.hasNext(); ) {
            Incoterm incoterm = (Incoterm) iter.next();
            BigDecimal nettAmount = (BigDecimal) nettAmountsByIncoterm.get(incoterm);
            BigDecimal nettPrice = nettAmount.divide(nettQuantity);
            nettPricesByIncoterm.put(incoterm, nettPrice);
        }
        return nettPricesByIncoterm;
    }

    private BigDecimal getNettUnitQuantity() {
        // TODO Auto-generated method stub
        return null;
    }

    /**
     * @see com.rmbgs.ts.domain.doc.IncotermBasedLineItem#getUnitPrice(boolean)
     */
    public BigDecimal getUnitPrice(boolean atCostNotSale) {
        return atCostNotSale ? getUnitCostPrice() : getUnitSalePrice();
    }

    /**
     * @see com.rmbgs.ts.domain.doc.IncotermBasedLineItem#getUnitQuantity(boolean)
     */
    public BigDecimal getUnitQuantity(boolean atCostNotSale) {
        return getUnitQuantity();
    }

    public String getOrderRef() {
        return orderRef;
    }

    public void setOrderRef(String orderRef) {
        this.orderRef = orderRef;
    }

    public String getPackingSlipRef() {
        return packingSlipRef;
    }

    public void setPackingSlipRef(String packingSlipRef) {
        this.packingSlipRef = packingSlipRef;
    }

    public String getRplNumber() {
        return rplNumber;
    }

    public void setRplNumber(String rplNumber) {
        this.rplNumber = rplNumber;
    }

    public Shipment getShipment() {
        return shipment;
    }

    public void setShipment(Shipment shipment) {
        this.shipment = shipment;
    }

    public String getArticleNumber() {
        return articleNumber;
    }

    public void setArticleNumber(String articleNumber) {
        this.articleNumber = articleNumber;
    }

    public String getCustomerReference() {
        return customerReference;
    }

    public void setCustomerReference(String customerReference) {
        this.customerReference = customerReference;
    }

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

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

    public WeightUnitOfMeasure getWeightUOM() {
        return weightUOM;
    }

    public void setWeightUOM(WeightUnitOfMeasure weightUOM) {
        this.weightUOM = weightUOM;
    }

    public VolumeUnitOfMeasure getVolumeUOM() {
        return volumeUOM;
    }

    public void setVolumeUOM(VolumeUnitOfMeasure volumeUOM) {
        this.volumeUOM = volumeUOM;
    }

    public UnitType getUnitType() {
        return unitType;
    }

    public void setUnitType(UnitType unitType) {
        this.unitType = unitType;
    }

    public void setGoodsReceivedAllocations(Set<GoodsReceivedAllocation> goodsReceivedAllocations) {
        this.goodsReceivedAllocations = goodsReceivedAllocations;
    }

    public void setCreditNoteLineItems(Set<CreditNoteLineItem> creditNoteLineItems) {
        this.creditNoteLineItems = creditNoteLineItems;
    }

}