ItemProductUtil.java

package com.tradecloud.domain.item;

import com.tradecloud.domain.base.utils.MathUtils;
import com.tradecloud.domain.base.utils.ObjectUtil;
import com.tradecloud.domain.document.invoice.ActualLineItem;
import com.tradecloud.domain.document.invoice.CostsInvoice;
import com.tradecloud.domain.duties.DutySchedule;
import com.tradecloud.domain.duties.ItacPermit;
import com.tradecloud.domain.duties.ItacPermitOptions;
import com.tradecloud.domain.duties.TypedDutySchedule;
import com.tradecloud.domain.place.FinalDestination;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;

import java.math.BigDecimal;
import java.math.MathContext;
import java.util.List;

public class ItemProductUtil {

    public static void calculateAndSetVolume(ItemInterface lineItem, BigDecimal packageVolume, BigDecimal unitVolume) {

        if (!MathUtils.isNonZero(unitVolume)) {
            unitVolume = calc(lineItem.getUnitHeight(), lineItem.getUnitLength(), lineItem.getUnitWidth());
        }
        if (unitVolume != null) {
            lineItem.setUnitVolume(unitVolume);
            if (MathUtils.isNonZero(unitVolume)) {
                if (MathUtils.isNonZero(lineItem.getUnitsPerPackage())) {
                    packageVolume = MathUtils.multiply(ObjectUtils.firstNonNull(unitVolume, BigDecimal.ZERO), lineItem.getUnitsPerPackage());
                    lineItem.setPackageVolume(packageVolume);
                }
            }
        }

        if (!MathUtils.isNonZero(packageVolume)) {
            packageVolume = calc(lineItem.getPackageHeight(), lineItem.getPackageLength(), lineItem.getPackageWidth());
        }
        if (packageVolume == null && lineItem.getUnitsPerPackage() != null && unitVolume != null) {
            packageVolume = unitVolume.multiply(lineItem.getUnitsPerPackage());
        }
        lineItem.setPackageVolume(ObjectUtils.firstNonNull(packageVolume, BigDecimal.ZERO));
        if (!MathUtils.isNonZero(unitVolume) && MathUtils.isNonZero(lineItem.getUnitsPerPackage())) {
            lineItem.setUnitVolume(
                    MathUtils.divideVA(ObjectUtils.firstNonNull(packageVolume, BigDecimal.ZERO), lineItem.getUnitsPerPackage()));
        }
    }

    public static void calculateAndSetWeight(ItemInterface lineItem, BigDecimal packageWeight, BigDecimal unitWeight) {
        if (MathUtils.isNonZero(unitWeight)) {
            lineItem.setUnitWeight(unitWeight);
            if (MathUtils.isNonZero(lineItem.getUnitsPerPackage())) {
                packageWeight = MathUtils.multiply(ObjectUtils.firstNonNull(unitWeight, BigDecimal.ZERO), lineItem.getUnitsPerPackage());
                lineItem.setPackageWeight(packageWeight);

            }
        } else {
            if (MathUtils.isNonZero(packageWeight)) {
                lineItem.setPackageWeight(packageWeight);
                if (!MathUtils.isNonZero(unitWeight) && MathUtils.isNonZero(lineItem.getUnitsPerPackage())) {
                    lineItem.setUnitWeight(MathUtils.divideVA(ObjectUtils.firstNonNull(packageWeight, BigDecimal.ZERO),
                            lineItem.getUnitsPerPackage()));
                }
            }
        }
    }

    private static BigDecimal calc(BigDecimal unitHeight, BigDecimal unitLength, BigDecimal unitWidth) {
        if (ObjectUtil.allNotNull(unitHeight, unitLength, unitWidth)) {
            if (!MathUtils.isZero(unitHeight) || !MathUtils.isZero(unitLength) ||
                    !MathUtils.isZero(unitWidth)) {

                return MathUtils.setScale(unitHeight
                        .multiply(unitLength)
                        .multiply(unitWidth.divide(new BigDecimal(1000000))), MathUtils.SCALE_VERY_ACCURATE);
            }
        }
        return null;
    }

    public static void defaultVolumeDimensionsWeightFromProduct(AbstractItem lineItem, AbstractItem defaultProduct) {
        if (defaultProduct != null) {
            lineItem.setUnitVolume(defaultProduct.getUnitVolume());
            lineItem.setUnitHeight(defaultProduct.getUnitHeight());
            lineItem.setUnitLength(defaultProduct.getUnitLength());
            lineItem.setUnitWidth(defaultProduct.getUnitWidth());
            lineItem.setPackageVolume(defaultProduct.getPackageVolume());
            lineItem.setPackageHeight(defaultProduct.getPackageHeight());
            lineItem.setPackageLength(defaultProduct.getPackageLength());
            lineItem.setPackageWidth(defaultProduct.getPackageWidth());
            lineItem.setUnitType(defaultProduct.getUnitType());
            lineItem.setPackageType(defaultProduct.getPackageType());
        }
    }

    public static void applyFieldChanges(String changedField, ItemInterface product) {
        switch (changedField) {
            case "unitsPerPackage":
                ItemProductUtil.calculateAndSetWeight(product, product.getPackageWeight(), product.getUnitWeight());
                ItemProductUtil.calculateAndSetVolume(product, product.getPackageVolume(), product.getUnitVolume());
                break;
            case "packageWeight":
                ItemProductUtil.calculateAndSetWeight(product, product.getPackageWeight(), null);
                break;
            case "unitWeight":
                ItemProductUtil.calculateAndSetWeight(product, null, product.getUnitWeight());
                if (MathUtils.isNonZero(product.getUnitWeight()) &&
                        product.getWeightUOM() != null &&
                        product.getSchedule1Part1A() != null &&
                        product.getSchedule1Part1A().equals(product.getSchedule1Part1A()) &&
                        product.getSchedule1Part1A().getSupplementaryQty1() != null &&
                        product.getSchedule1Part1A().getSupplementaryQty1().getUnit() != null &&
                        product.getWeightUOM().getCode().equals(product.getSchedule1Part1A().getSupplementaryQty1().getUnit().getSarsCode())) {
                    product.getSchedule1Part1A().getSupplementaryQty1().setValue(product.getUnitWeight());
                }
                break;
            case "unitDimensions":
                clearPackageDimensions(product);
                ItemProductUtil.calculateAndSetVolume(product, null, null);
                break;
            case "packageDimensions":
                clearUnitDimesions(product);
                ItemProductUtil.calculateAndSetVolume(product, null, null);
                break;
            case "unitVolume":
                clearDimensions(product);
                ItemProductUtil.calculateAndSetVolume(product, null, product.getUnitVolume());
                break;
            case "packageVolume":
                clearDimensions(product);
                ItemProductUtil.calculateAndSetVolume(product, product.getPackageVolume(), null);
                break;
        }
    }

    private static void clearDimensions(ItemInterface product) {
        clearPackageDimensions(product);
        clearUnitDimesions(product);
    }

    private static void clearUnitDimesions(ItemInterface product) {
        product.setUnitLength(null);
        product.setUnitWidth(null);
        product.setUnitHeight(null);
    }

    private static void clearPackageDimensions(ItemInterface product) {
        product.setPackageLength(null);
        product.setPackageWidth(null);
        product.setPackageHeight(null);
    }

    public static void setItemType(ItemInterface lineItem, FinalDestination finalDestination) {
        if (finalDestination != null && CollectionUtils.isNotEmpty(finalDestination.getStores())) {
            lineItem.setItemType(ItemType.valueOf(finalDestination.getStores().
                    get(0).getStoreType().name()));
        } else if (lineItem.getItemType() == null) {
            lineItem.setItemType(ItemType.GENERAL);
        }
    }

    public static boolean isDutyInformationValid(TypedDutySchedule schedule) {
        return schedule != null && schedule.getTariffHeading() != null
                && schedule.getTariffHeading().getTariff() != null
                && schedule.getTariffHeading().getTariff() != null && schedule.isValid();
    }

    public static boolean isDutyInformationValid(DutySchedule schedule) {
        return schedule != null && schedule.getTariffHeading() != null
                && schedule.getTariffHeading().getTariff() != null
                && schedule.getTariffHeading().getTariff() != null && schedule.isValid();
    }

    public static boolean isValidRebateSchedule3(ItemInterface lineItem) {
        return lineItem.getItemType() != null && lineItem.getItemType().equals(ItemType.INDUSTRIAL_REBATE) &&
                isDutyInformationValid(lineItem.getSchedule3Part1());
    }

    public static boolean isValidRebateSchedule4(ItemInterface lineItem) {
        return lineItem.getItemType() != null && lineItem.getItemType().equals(ItemType.GENERAL_REBATE) &&
                isDutyInformationValid(lineItem.getSchedule4Part1());
    }

    public static void validateRebatesSchedules(ItemInterface lineItem) {
        if (!isRebateTypeAndTariffied(lineItem)) {
            if (lineItem.getItemType() == ItemType.GENERAL_REBATE && !ItemProductUtil.isValidRebateSchedule4(lineItem)) {
                throw new IllegalStateException(String.format("Line item %s Schedule4Part1 is not valid", lineItem.getCode()));
            }
            if (lineItem.getItemType() == ItemType.INDUSTRIAL_REBATE && !ItemProductUtil.isValidRebateSchedule3(lineItem)) {
                throw new IllegalStateException(String.format("Line item %s Schedule3Part1 is not valid", lineItem.getCode()));
            }
        }
    }

    public static void validateRebatesSchedules(CostsInvoice costsInvoice) {
        List<ActualLineItem> actualLineItems = costsInvoice.getActualLineItems();
        for (ActualLineItem lineItem : actualLineItems) {
            if (!isRebateTypeAndTariffied(lineItem)) {
                if (lineItem.getItemType() == ItemType.GENERAL_REBATE && !ItemProductUtil.isValidRebateSchedule4(lineItem)) {
                    throw new IllegalStateException(String.format("Invoice %s, Line item %s Schedule4Part1 is not valid",
                            costsInvoice.getReference(), lineItem.getCode()));
                }
                if (lineItem.getItemType() == ItemType.INDUSTRIAL_REBATE && !ItemProductUtil.isValidRebateSchedule3(lineItem)) {
                    throw new IllegalStateException(String.format("Invoice %s, Line item %s Schedule3Part1 is not valid",
                            costsInvoice.getReference(), lineItem.getCode()));
                }
            }
        }
    }

    private static boolean isRebateTypeAndTariffied(ItemInterface lineItem) {
        return (lineItem.getItemType() == ItemType.GENERAL_REBATE || lineItem.getItemType() == ItemType.INDUSTRIAL_REBATE)
                && lineItem.inTariffiedState();
    }

    public static String itemCodeAppendedNumber(String code, Integer lineNumber) {
        if (code != null && lineNumber != null) {
            return new StringBuilder(code.trim()).append("#").append(lineNumber).toString();
        } else {
            return code;
        }
    }

    public static BigDecimal getRebatePercentage(ItemInterface lineItem) {
        BigDecimal percentage = BigDecimal.valueOf(100);
        final ItacPermit itacPermit = lineItem.getItacPermit();
        if ((lineItem.getSchedule3Part1() != null && itacPermit.getItacPermit() != null && itacPermit.isS3P1Rebate() &&
                itacPermit.getItacPermit().equals(ItacPermitOptions.NO)) ||
                (lineItem.getSchedule4Part1() != null && itacPermit.getItacPermit() != null && itacPermit.isS4P1Rebate() &&
                        itacPermit.getItacPermit().equals(ItacPermitOptions.NO))) {
            percentage = BigDecimal.ZERO;
        }

        BigDecimal rebatePercentage = BigDecimal.ONE.subtract(percentage.divide(BigDecimal.valueOf(100),
                MathContext.DECIMAL128));
        return rebatePercentage;
    }

}