BaseActual.java

package com.tradecloud.domain.document.invoice;

import com.tradecloud.common.base.PersistenceBase;
import com.tradecloud.domain.costing.clean.CostLineCosting;
import com.tradecloud.domain.costing.clean.Costed;
import com.tradecloud.domain.costing.clean.CostedTotals;
import com.tradecloud.domain.costing.clean.TotalsDistributionType;
import com.tradecloud.domain.costing.utils.CostingUtils;
import com.tradecloud.domain.export.ExportCosting;
import com.tradecloud.domain.item.ItemType;
import org.apache.commons.lang3.NotImplementedException;
import org.hibernate.annotations.ForeignKey;

import javax.persistence.*;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlTransient;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

/**
 * Base class for actuals. Holds common functionality required by all subclasses.
 *
 * @param <P>
 * @param <C>
 */
@MappedSuperclass
public abstract class BaseActual<P extends Costed, C extends Costed> extends PersistenceBase implements Actual<P, C> {

    private static final long serialVersionUID = 1L;

    /**
     * The Id of the entity that the BaseActual is based on.
     * e.g. for a ActualLineItem it's the id of the lineItem which it was created from
     */
    protected Long originalId;

    protected boolean distributableByVolume;

    protected boolean distributableByWeight;

    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
    @XmlElement
    @ForeignKey(name = "fk_costedTotals")
    private CostedTotals costedTotals = new CostedTotals();

    private String summaryNumber;

    protected BaseActual() {
    }

    protected BaseActual(Long originalId) {
        this.originalId = originalId;
    }

    /**
     * Various cost line costings to allow the costing to be broken down at each level.
     */
    @Embedded
    @XmlElement(name = "CostLineCosting")
    private CostLineCosting costLineCosting = new CostLineCosting();

    /*
     * Used to store the total weight, volume, and cost
     *  e.g. actualOrder.getTotalsDistribution.get(TotalsDistributionType.WEIGHT_KG)
     *  gives the total weight for that order
     */
    @XmlTransient
    @ElementCollection
    @ForeignKey(name = "fk_totalsDistribution")
    @MapKeyEnumerated(EnumType.STRING)
    private Map<TotalsDistributionType, BigDecimal> totalsDistribution = new HashMap<TotalsDistributionType, BigDecimal>();

    @XmlAttribute
    private BigDecimal sellPriceExclusiveAmount = BigDecimal.ZERO;

    @XmlAttribute
    private BigDecimal sellPriceInclusiveAmount = BigDecimal.ZERO;

    @XmlTransient
    @ElementCollection
    private Map<String, BigDecimal> costlineBondedAmount = new HashMap<String, BigDecimal>();

    public Map<TotalsDistributionType, BigDecimal> getTotalsDistribution() {
        return totalsDistribution;
    }

    public void setTotalsDistribution(Map<TotalsDistributionType, BigDecimal> totalsDistribution) {
        this.totalsDistribution = totalsDistribution;
    }

    /**
     * @return
     */
    @Override
    public CostLineCosting getCostLineCosting() {
        return costLineCosting;
    }

    public void setCostLineCosting(CostLineCosting costLineCosting) {
        this.costLineCosting = costLineCosting;
    }

    /**
     * Static helper method for getting a cached value. Used because CostsInvoice does not extend BaseActual
     *
     * @param costlineCosting
     * @param map
     * @param costLineCode
     * @return
     */
    public static CostingCell getCachedAmount(Costing costlineCosting, Map<String, CostingCell> map, String costLineCode) {
        if (!map.containsKey(costLineCode)) {
            // search costlines
            for (CostingCell costLineAmount : costlineCosting.getCostLineCostingCells()) {
                if (costLineAmount.getCode().equals(costLineCode)) {
                    map.put(costLineCode, costLineAmount);
                    break;
                }
            }
            // search calculated columns
            for (CostingCell costLineAmount : costlineCosting.getCalculatedCostingCells()) {
                if (costLineAmount.getCode().equals(costLineCode)) {
                    map.put(costLineCode, costLineAmount);
                    break;
                }
            }
        }
        return map.get(costLineCode);
    }

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

    public Long getOriginalId() {
        return originalId;
    }

    public void setOriginalId(Long originalId) {
        this.originalId = originalId;
    }

    /**
     * This field will be set to true if 1 of the line items linked to the structure has a volume value.
     */
    public boolean isDistributableByVolume() {
        return distributableByVolume;
    }

    public void setDistributableByVolume(boolean distributableByVolume) {
        this.distributableByVolume = distributableByVolume;
    }

    /**
     * This field will be set to true if 1 of the line items linked to the structure has a weight value.
     */
    public boolean isDistributableByWeight() {
        return distributableByWeight;
    }

    public void setDistributableByWeight(boolean distributableByWeight) {
        this.distributableByWeight = distributableByWeight;
    }

    @Override
    public CostedTotals getCostedTotals() {
        if (costedTotals == null) {
            costedTotals = new CostedTotals();
        }
        return costedTotals;
    }

    public void setCostedTotals(CostedTotals costedTotals) {
        this.costedTotals = costedTotals;
    }

    public boolean isActual() {
        return true;
    }

    @Override
    public boolean isItem() {
        return false;
    }

    @Override
    public boolean isOrder() {
        return false;
    }

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

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

    @Override
    public boolean isCostsInvoice() {
        return false;
    }

    @Override
    public ItemType getItemType() {
        return null;
    }

    @Override
    public Costed findRootParent() {
        return CostingUtils.findRootParent(this);
    }

    @Override
    public boolean match(Actual actual) {
        if (actual instanceof BaseActual) {
            return originalId != null && originalId.equals(((BaseActual) actual).getOriginalId());
        }
        return false;
    }

    @Override
    public String getReferenceWithShippingRef() {
        return null;
    }

    public BigDecimal getSellPriceExclusiveAmount() {
        return sellPriceExclusiveAmount;
    }

    public void setSellPriceExclusiveAmount(BigDecimal sellPriceExclusiveAmount) {
        this.sellPriceExclusiveAmount = sellPriceExclusiveAmount;
    }

    public BigDecimal getSellPriceInclusiveAmount() {
        return sellPriceInclusiveAmount;
    }

    public void setSellPriceInclusiveAmount(BigDecimal sellPriceInclusiveAmount) {
        this.sellPriceInclusiveAmount = sellPriceInclusiveAmount;
    }

    @Override
    public Map getCostlineBondedAmount() {
        return costlineBondedAmount;
    }

    public void setCostlineBondedAmount(Map<String, BigDecimal> costlineBondedAmount) {
        this.costlineBondedAmount = costlineBondedAmount;
    }

    public String getSummaryNumber() {
        return summaryNumber;
    }

    public void setSummaryNumber(String summaryNumber) {
        this.summaryNumber = summaryNumber;
    }

    public ExportCosting getExportCosting() {
        throw new NotImplementedException("please implement");
    }
}