CostApplicationBasis.java

package com.tradecloud.domain.costing;

import com.tradecloud.domain.model.RateOfExchangeType;

import javax.xml.bind.annotation.XmlEnum;
import java.util.ArrayList;
import java.util.List;

/**
 * The cost application basis refers to the cost basis applicable for the calculation, i.e. if an administrator has selected percentage as the 'cost
 * application method', then 'cost application basis' allows the administrator to select the "what", it's a percentage of what.
 */
@XmlEnum
public enum CostApplicationBasis {

    AGENT_COST("Agent Cost Application Basis", "Agent Cost Application Basis", true, 0),

    SUPPLY_COST("Supply Cost (qty * price)", "Supply Cost (qty * price)", true, 0),
    SUPPLY_COST_FWD_RATE("Supply Cost (qty * price) * SI Fwd ROE", "Supply Cost (qty * price) * SI Fwd ROE", true, 0),
    SUPPLY_COST_FWD_RATE_PLUS_BANK_CHARGES("Supply Cost (qty * price) * SI Fwd ROE plus Bank Charges",
            "Supply Cost (qty * price) * SI Fwd ROE plus Bank Charges", true, 0),
    TOTAL_SUPPLY_COST_FWD_RATE_PLUS_BANK_CHARGES("Total Supply Cost * SI Fwd ROE plus Bank Charges",
            "Total Supply Cost * SI Fwd ROE plus Bank Charges", true, 0),
    SUPPLY_COST_SPOT_RATE("Supply Cost (qty * price) * SI Spot ROE", "Supply Cost (qty * price) * SI Spot ROE", true, 0),

    SUPPLY_COST_INC_DISCOUNT("Supply Cost including Discount", "Supply Cost including Discount", true, 0),
    SUPPLY_COST_INC_DISCOUNT_SPT_RATE("Supply Cost including Discount * Spt ROE", "Supply Cost including Discount * Spt ROE", false, 0),
    SUPPLY_COST_INC_DISCOUNT_FWD_RATE("Supply Cost including Discount * Fwd ROE", "Supply Cost including Discount * Fwd ROE", false, 0),

    SUPPLIER_INVOICE("Supplier Invoice", "Supplier Invoice", true, 0), // in foreign currency
    SUPPLIER_INVOICE_SPT_RATE("Supplier Invoice * Spt ROE", "Supplier Invoice * Spt ROE", false, 0),
    SUPPLIER_INVOICE_FWD_RATE("Supplier Invoice * Fwd ROE", "Supplier Invoice * Fwd ROE", false, 0),
    //These must always use xgnite ratefeed
    SUPPLIER_INVOICE_RATE_FEED_SPT_RATE("Supplier Invoice * Rate Feed Spt ROE", "Supplier Invoice * Rate Feed Spt ROE", true, 0),
    SUPPLIER_INVOICE_RATE_FEED_FWD_RATE("Supplier Invoice * Rate Feed Fwd ROE", "Supplier Invoice * Rate Feed Fwd ROE", true, 0),

    TOTAL_COST_EXVAT("Total Cost (excl VAT)", "Total Cost (excl VAT)", true, 2),
    TOTAL_COST_EXVAT_EXCLUDED_COST_LINES("Total Cost (excl VAT + Excluded Costlines)", "Total Cost (excl VAT + Excluded Costlines)", true, 2),
    TOTAL_COST_INCVAT("Total Cost (incl VAT)", "Total Cost (incl VAT)", true, 2),
    TOTAL_COST_EXINTPROV("Total Cost (excl Internal provisions and VAT)", "Total Cost (excl Internal provisions and VAT)", true, 2),
    TOTAL_COST_INCVAT_BONDED_EXINTPROV("Total Cost (incl Bonded duties and VAT, excl Int Prov) ",
            "Total Cost (incl Bonded duties and VAT, excl Int Prov) ", true, 2),
    TOTAL_CUSTOMS_COST_GROUP("Total Customs Cost group ",
            "Total Customs Cost group ", true, 1),

    // Sample & Spares don't have supply cost as they are free. If we do add them to SUPPLY_COST, SUPPLY_COST_FWD_RATE and SUPPLY_COST_SPOT_RATE
    // they will impact alc costing for cost lines that are dependent on supply cost. We there for handle supply cost for samples and spares
    // separately.
    SUPPLY_COST_SAMPLES_AND_SPARES("Sample & Spare: Supply Cost", "Sample & Spare: Supply Cost", false, 0),
    SUPPLY_COST_FWD_RATE_SAMPLES_AND_SPARES("Sample & Spare: Supply Cost * SI Fwd ROE", "Sample & Spare: Supply Cost * SI Fwd ROE", false, 0),
    SUPPLY_COST_SPOT_RATE_SAMPLES_AND_SPARES("Sample & Spare: Supply Cost * SI Spot ROE", "Sample & Spare: Supply Cost * SI Spot ROE", false, 0),
    //The algorithm must include all indirect (responsibility = Importer) cost lines enabled for the cost groups: Freight, Forwarding and Clearing.
    // Plus the calculated agency Fee under Clearing
    //Will get executed after all non total costlines.
    DISBURSEMENT_EXCL_CUSTOMS_INC_AGENCY("Disbursement excl. customs, incl. agency", "Disbursement excl. customs, incl. agency", true, 1),
    DISBURSEMENT_INCL_CUSTOMS("Disbursement incl. customs", "Disbursement incl. customs", true, 1),
    DISBURSEMENT_INCL_CUSTOMS_AND_INTEREST("Disbursement including VAT, Duties and interest", "Disbursement including VAT, Duties and interest", true
            , 1),
    DISBURSEMENT_ALL_EXC_VAT(" Disbursements All Ex VAT", " Disbursements All Ex VAT", true
            , 1),
    CARTAGE_COST("Cartage Cost", "Cartage Cost", true, 1),
    RAILAGE_COST("Railage Cost", "Railage Cost", true, 1),
    DUTIABLE_COST("Dutiable Cost", "Dutiable Cost", true, 1),
    FOREIGN_DISBURSEMENT("Foreign Disbursement", ".Foreign Disbursement", true, 1),
    FREIGHT_FREIGHT("Freight: Freight Cost", "Freight: Freight Cost", true, 1),
    PAYMENT_BASIS_1("Payment Basis 1", "Payment Basis 1", true, 1),
    PAYMENT_BASIS_2("Payment Basis 2", "Payment Basis 2", true, 1);


    private final transient String name;
    private final transient boolean selectable;
    private final transient String description;
    //For total costline we need to sort them using this field, it is possible to have 2 totals costlines that depends on each other,
    //e.g DISBURSEMENT_EXCL_CUSTOMS_INC_AGENCY falls under total Cos App Basis but need to executed before TOTAL_COST_EXVAT.
    private final transient Integer evaluationPriority;

    CostApplicationBasis(String name, String description, boolean selectable, Integer evaluationPriority) {
        this.name = name;
        this.description = description;
        this.selectable = selectable;
        this.evaluationPriority = evaluationPriority;
    }

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return name;
    }

    public boolean isSelectable() {
        return selectable;
    }

    public String getDescription() {
        return description;
    }

    public boolean isBasedOnTotalCost() {
        return TOTAL_COST_EXVAT.equals(this) ||
                TOTAL_COST_EXVAT_EXCLUDED_COST_LINES.equals(this) ||
                TOTAL_COST_INCVAT.equals(this) ||
                TOTAL_COST_EXINTPROV.equals(this) ||
                DISBURSEMENT_EXCL_CUSTOMS_INC_AGENCY.equals(this) ||
                DISBURSEMENT_INCL_CUSTOMS.equals(this) ||
                DISBURSEMENT_INCL_CUSTOMS_AND_INTEREST.equals(this) ||
                DISBURSEMENT_ALL_EXC_VAT.equals(this) ||
                CARTAGE_COST.equals(this) ||
                RAILAGE_COST.equals(this) ||
                DUTIABLE_COST.equals(this) ||
                FOREIGN_DISBURSEMENT.equals(this) ||
                TOTAL_CUSTOMS_COST_GROUP.equals(this) ||
                TOTAL_COST_INCVAT_BONDED_EXINTPROV.equals(this);
    }

    public boolean isBasedOnLocalCost() {
        return isBasedOnTotalCost() ||
                SUPPLIER_INVOICE_SPT_RATE.equals(this) ||
                SUPPLIER_INVOICE_RATE_FEED_SPT_RATE.equals(this) ||
                SUPPLIER_INVOICE_FWD_RATE.equals(this) ||
                SUPPLIER_INVOICE_RATE_FEED_FWD_RATE.equals(this) ||
                SUPPLY_COST_INC_DISCOUNT_SPT_RATE.equals(this) ||
                SUPPLY_COST_INC_DISCOUNT_FWD_RATE.equals(this) ||
                SUPPLY_COST_SPOT_RATE.equals(this) ||
                SUPPLY_COST_FWD_RATE.equals(this) ||
                SUPPLY_COST_SPOT_RATE_SAMPLES_AND_SPARES.equals(this) ||
                SUPPLY_COST_FWD_RATE_SAMPLES_AND_SPARES.equals(this) ||
                SUPPLY_COST_FWD_RATE_PLUS_BANK_CHARGES.equals(this) ||
                TOTAL_SUPPLY_COST_FWD_RATE_PLUS_BANK_CHARGES.equals(this) ||
                FREIGHT_FREIGHT.equals(this);
    }

    public static List<CostApplicationBasis> onlyVisible() {
        List<CostApplicationBasis> onlyVisible = new ArrayList<>();
        for (CostApplicationBasis costApplicationBasis : values()) {
            if (costApplicationBasis.isSelectable()) {
                onlyVisible.add(costApplicationBasis);
            }
        }
        return onlyVisible;
    }

    public CostApplicationBasis getLocalCostEquivalent(RateOfExchangeType rateOfExchangeType) {
        if (SUPPLY_COST.equals(this)) {
            return RateOfExchangeType.FORWARD.equals(rateOfExchangeType) ? SUPPLY_COST_FWD_RATE : SUPPLY_COST_SPOT_RATE;
        } else if (SUPPLY_COST_INC_DISCOUNT.equals(this)) {
            return RateOfExchangeType.FORWARD.equals(rateOfExchangeType) ? SUPPLY_COST_INC_DISCOUNT_FWD_RATE : SUPPLY_COST_INC_DISCOUNT_SPT_RATE;
        } else if (SUPPLIER_INVOICE.equals(this)) {
            return RateOfExchangeType.FORWARD.equals(rateOfExchangeType) ? SUPPLIER_INVOICE_FWD_RATE : SUPPLIER_INVOICE_SPT_RATE;
        } else if (SUPPLY_COST_SAMPLES_AND_SPARES.equals(this)) {
            return RateOfExchangeType.FORWARD.equals(rateOfExchangeType) ? SUPPLY_COST_FWD_RATE_SAMPLES_AND_SPARES :
                    SUPPLY_COST_SPOT_RATE_SAMPLES_AND_SPARES;
        }
        return null;
    }

    public Integer getEvaluationPriority() {
        return evaluationPriority;
    }
}