TariffDataImportHelper.java

package com.tradecloud.dto.duties;

import com.tradecloud.domain.base.utils.DateUtils;
import com.tradecloud.domain.configuration.TradeAgreements;
import com.tradecloud.domain.document.invoice.ActualLineItem;
import com.tradecloud.domain.duties.*;
import com.tradecloud.domain.item.ItemInterface;
import com.tradecloud.domain.item.ItemType;
import com.tradecloud.domain.item.LineItem;
import com.tradecloud.domain.place.Country;
import com.tradecloud.tariffing.domain.*;
import org.apache.commons.collections.CollectionUtils;
import org.apache.log4j.Logger;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

public class TariffDataImportHelper {

    private final static Logger log = Logger.getLogger(TariffDataImportHelper.class);

    /**
     * Set the tariff codes and other fields from the result of a tariff search.
     *
     * @param abstractItem
     * @param searchResult
     * @param duty
     * @param applyAdditionalTariffs
     */
    public static void setTariffCodes(ItemInterface abstractItem, TariffSearchResult searchResult, Map.Entry<String, Duty> duty,
                                      boolean applyAdditionalTariffs, boolean applyRebateTariffs) {
        // Can be null if the user didn't select a radio button
        if (searchResult != null && duty != null) {
            if (applyAdditionalTariffs) {

                String type = getType(searchResult.getBaseTariff());

                if (type != null) {
                    if (type.equals("S1P2A")) {
                        Schedule1Part2AHelper.setTariffCode(abstractItem.getSchedule1Part2A(), searchResult.getBaseTariff());
                        Schedule1Part2AHelper.populateSchedule1Part2A(abstractItem.getSchedule1Part2A(), searchResult.getBaseTariff());
                    } else if (type.equals("S1P2B")) {
                        TariffGeneralHelper.setBaseTariffCode(abstractItem.getSchedule1Part2B(), searchResult.getBaseTariff());
                        Schedule1Part2BHelper.populateSchedule1Part2B(abstractItem.getSchedule1Part2B(), searchResult.getBaseTariff());
                    } else if (type.equals("S2P1")) {
                        TariffGeneralHelper.setBaseTariffCode(abstractItem.getSchedule2Part1(), searchResult.getBaseTariff());
                        Schedule2Part1Helper.populateSchedule2Part1(abstractItem.getSchedule2Part1(), searchResult.getBaseTariff());
                    } else if (type.equals("S2P2")) {
                        TariffGeneralHelper.setBaseTariffCode(abstractItem.getSchedule2Part2(), searchResult.getBaseTariff());
                    } else if (type.equals("S1P3E")) {
                        TariffGeneralHelper.setBaseTariffCode(abstractItem.getSchedule1Part3E(), searchResult.getBaseTariff());
                        Schedule1Part3EHelper.populateSchedule1Part3E(abstractItem.getSchedule1Part3E(), searchResult.getBaseTariff());
                        applyAdditionalDutyRules(abstractItem);
                        TariffGeneralHelper.setTariffValid(abstractItem.getSchedule1Part3E());
                    } else if (type.equals("S1P7")) {
                        TariffGeneralHelper.setBaseTariffCode(abstractItem.getSchedule1Part7(), searchResult.getBaseTariff());
                        Schedule1Part7Helper.populateSchedule1Part7(abstractItem.getSchedule1Part7(), searchResult.getBaseTariff());
                    } else {
                        log.error("Unknown tariff code. Code=" + searchResult.getBaseTariff().getCode());
                    }
                }
            }

            if (searchResult.getAntiDumping() != null) {
                TariffGeneralHelper.setBaseTariffCode(abstractItem.getSchedule2Part1(), searchResult.getAntiDumping());
                Schedule2Part1Helper.populateSchedule2Part1(abstractItem.getSchedule2Part1(), searchResult.getAntiDumping());
            }

            if (applyRebateTariffs) {
                for (BaseTariff tariff : searchResult.getRebateTariffs()) {
                    applyRebate(abstractItem, tariff);
                }
            }

            Schedule1Part1AHelper.setTariffCode(abstractItem.getSchedule1Part1A(), searchResult.getTariff(), duty.getKey(), duty.getValue());
            applyOtherDutyRules(abstractItem);
            applySupplementaryQuantity1(abstractItem, searchResult.getTariff());

            //validate new
            validateNew(abstractItem, searchResult);
        }
    }

    private static void applyRebate(ItemInterface abstractItem, BaseTariff baseTariff) {
        String type = getType(baseTariff);
        if (type != null) {
            if (type.equals("S3")) {
                TariffGeneralHelper.setBaseTariffCode(abstractItem.getSchedule3Part1(), baseTariff);
                Schedule3Part1Helper.populateSchedule3Part1(abstractItem.getSchedule3Part1(), baseTariff);
                if (!abstractItem.isLineItem()) {
                    abstractItem.getItacPermit().setRebateSchedule(ItemType.INDUSTRIAL_REBATE);
                }
            } else if (type.equals("S4")) {
                TariffGeneralHelper.setBaseTariffCode(abstractItem.getSchedule4Part1(), baseTariff);
                Schedule4Part1Helper.populateSchedule4Part1(abstractItem.getSchedule4Part1(), baseTariff);
                if (!abstractItem.isLineItem()) {
                    abstractItem.getItacPermit().setRebateSchedule(ItemType.GENERAL_REBATE);
                }
            }
        }
    }

    public static void validateNew(ItemInterface abstractItem, TariffSearchResult searchResult) {
        if (abstractItem.getSchedule1Part1A().isValid()) {
            //deleted
            if (searchResult.getTariff().getEndDate() != null &&
                DateUtils.inThePast(searchResult.getTariff().getEndDate())) {
                abstractItem.getSchedule1Part1A().setValid(false);
                abstractItem.setSarsTariffUpdateReason("Tariff deleted");
            }

            //current additional but update no additional
            if (anyAdditionalsPopulated(abstractItem) && !anyAdditionalsPopulated(searchResult)) {
                abstractItem.getSchedule1Part1A().setValid(false);
                abstractItem.setSarsTariffUpdateReason("abstractItem has additional but SARS update does not");
            }

            //current abstractItem with additional but not in list of update additional list
            if (anyAdditionalsPopulated(abstractItem) && anyAdditionalsPopulated(searchResult)) {
                for (AdditionalTariff additionalTariff : searchResult.getTariff().getAdditionalTariffs().values()) {
                    if (additionalTariff.getType().equals("S1P2A") && abstractItem.getSchedule1Part2A() != null &&
                        !abstractItem.getSchedule1Part2A().isValid()) {
                        abstractItem.getSchedule1Part1A().setValid(false);
                        abstractItem.setSarsTariffUpdateReason("abstractItem needs S1P2A");
                    }

                    if (additionalTariff.getType().equals("S1P2B") && abstractItem.getSchedule1Part2B() != null &&
                        !abstractItem.getSchedule1Part2B().isValid()) {
                        abstractItem.getSchedule1Part1A().setValid(false);
                        abstractItem.setSarsTariffUpdateReason("abstractItem needs S1P2B");
                    }
                }

                if (CollectionUtils.isNotEmpty(searchResult.getTariff().getAntiDumpingTariffs().values()) &&
                    abstractItem.getSchedule2Part1() != null &&
                    !abstractItem.getSchedule2Part1().isValid()) {

                    //country names from tariffbook
                    List<String> countries = searchResult.getTariff().getAntiDumpingTariffs().values()
                            .stream().map(ad -> ad.getCountry().toLowerCase()).collect(Collectors.toList());

                    Optional<String> allCountries = countries.stream()
                            .filter(ad -> ad.equalsIgnoreCase("ALL COUNTRIES")).findAny();

                    //get exteranal references

                    Country countryOfOrigin = abstractItem.getCountryOfOrigin();
                    List<String> externalReferences = countryOfOrigin.getExternalReferenceList()
                            .stream().map(er -> er.getReferenceValue().toLowerCase()).collect(Collectors.toList());
                    //add country name
                    externalReferences.add(countryOfOrigin.getName().toLowerCase());

                    Set<String> setOne = new HashSet<>(countries);
                    List<String> found = externalReferences.stream().filter(e -> setOne.contains(e)).collect(Collectors.toList());

                    if (allCountries.isPresent() || !found.isEmpty()) {
                        abstractItem.getSchedule1Part1A().setValid(false);
                        abstractItem.setSarsTariffUpdateReason("abstractItem needs S2P1");
                    }
                }

                if (CollectionUtils.isNotEmpty(searchResult.getTariff().getEnvironmentalTariffs().values()) &&
                    abstractItem.getSchedule1Part3E() != null &&
                    !abstractItem.getSchedule1Part3E().isValid()) {
                    abstractItem.getSchedule1Part1A().setValid(false);
                    abstractItem.setSarsTariffUpdateReason("abstractItem needs S1P3E");
                }

                if (CollectionUtils.isNotEmpty(searchResult.getTariff().getSugarTariffs().values()) &&
                    abstractItem.getSchedule1Part7() != null &&
                    !abstractItem.getSchedule1Part7().isValid()) {
                    abstractItem.getSchedule1Part1A().setValid(false);
                    abstractItem.setSarsTariffUpdateReason("abstractItem needs S1P7");
                }
            }

            //updated passed all other scenarios
            /*if (abstractItem.getSchedule1Part1A().isValid()) {
                tariffTransformer.updateTariffValueUsingTradeAgreement(abstractItem, true, integrationProperties,
                        searchResult.getTariff().getCode());
                abstractItemCatalogueService.update(abstractItem, true);
                abstractItemsUpdated.add(abstractItem);
            }*/

            //tricky one: list of additional contains more than the available list at time of tariffing
            {
            }
        }
    }

    private static boolean anyAdditionalsPopulated(TariffSearchResult searchResult) {
        return CollectionUtils.isNotEmpty(searchResult.getTariff().getAdditionalTariffs().values()) ||
               CollectionUtils.isNotEmpty(searchResult.getTariff().getAntiDumpingTariffs().values()) ||
               CollectionUtils.isNotEmpty(searchResult.getTariff().getEnvironmentalTariffs().values()) ||
               CollectionUtils.isNotEmpty(searchResult.getTariff().getSugarTariffs().values());
    }

    private static boolean anyAdditionalsPopulated(ItemInterface abstractItem) {
        return abstractItem.getSchedule1Part2A().isValid() ||
               abstractItem.getSchedule1Part2B().isValid() ||
               abstractItem.getSchedule2Part1().isValid() ||
               abstractItem.getSchedule1Part3E().isValid() ||
               abstractItem.getSchedule2Part2().isValid() ||
               abstractItem.getSchedule1Part7().isValid();
    }

    private static void applySupplementaryQuantity1(ItemInterface abstractItem, Tariff tariff) {
        if (tariff.getDutyUnit().toLowerCase().contains("kg")) {
            BigDecimal suppQtyValue = BigDecimal.ZERO;
            if (abstractItem.getSchedule1Part1A().getSupplementaryQty1().getValue() != null) {
                suppQtyValue = abstractItem.getSchedule1Part1A().getSupplementaryQty1().getValue();
            } else if (abstractItem.getUnitWeight() != null) {
                suppQtyValue = abstractItem.getUnitWeight();
            }

            abstractItem.getSchedule1Part1A().setSupplementaryQty1(new SupplementaryQuantity(suppQtyValue,
                    DutyUnit.getBySarsTariffServerCode(tariff.getDutyUnit())));
        } else if (tariff.getDutyUnit().toLowerCase().contains("u") || tariff.getDutyUnit().toLowerCase().contains("each") ||
                   tariff.getDutyUnit().toLowerCase().contains("2u")) {
            BigDecimal suppQtyValue = BigDecimal.ONE;
            if (abstractItem.getSchedule1Part1A().getSupplementaryQty1().getValue() != null) {
                suppQtyValue = abstractItem.getSchedule1Part1A().getSupplementaryQty1().getValue();
            } else if ((abstractItem instanceof LineItem || abstractItem instanceof ActualLineItem) && abstractItem.getUnitQuantity() != null) {
                suppQtyValue = BigDecimal.ONE;
            }

            abstractItem.getSchedule1Part1A().setSupplementaryQty1(new SupplementaryQuantity(suppQtyValue,
                    DutyUnit.getBySarsTariffServerCode(tariff.getDutyUnit())));
        } else {
            if ((abstractItem instanceof LineItem || abstractItem instanceof ActualLineItem) && abstractItem.getUnitQuantity() != null &&
                abstractItem.getSchedule1Part1A().getSupplementaryQty1().getValue() == null) {
                abstractItem.getSchedule1Part1A().setSupplementaryQty1(new SupplementaryQuantity(BigDecimal.ONE,
                        DutyUnit.getBySarsTariffServerCode(tariff.getDutyUnit())));
            }
        }
    }

    private static void applyOtherDutyRules(ItemInterface abstractItem) {
        //TRM-4249
        if (abstractItem.getSchedule1Part1A() != null
            && abstractItem.getSchedule1Part1A().getDutyRate() != null
            && abstractItem.getSchedule1Part1A().getDutyRate().getOtherDuty1() != null
            && abstractItem.getSchedule1Part1A().getDutyRate().getOtherDuty1().getUnit() != null
            && abstractItem.getSchedule1Part1A().getDutyRate().getOtherDuty1().getUnit().equals(DutyUnit.PAIRS)
            && abstractItem.getSchedule1Part1A().getCalculationMethod().equals(DutyCalculationMethod.OR)) {
            BigDecimal quantity = BigDecimal.ONE;
            if (abstractItem instanceof LineItem) {
                LineItem lineItem = (LineItem) abstractItem;
                quantity = lineItem.getUnitQuantity();
            }
            abstractItem.getSchedule1Part1A().getDutyRate().getOtherDuty1().setAdditionalValue(quantity);
        }
        //LIB-36
        if (abstractItem instanceof LineItem && abstractItem.getSchedule1Part1A() != null
            && abstractItem.getSchedule1Part1A().getDutyRate() != null
            && abstractItem.getSchedule1Part1A().getDutyRate().getOtherDuty1() != null
            && abstractItem.getSchedule1Part1A().getDutyRate().getOtherDuty1().getUnit() != null
            && abstractItem.getSchedule1Part1A().getDutyRate().getOtherDuty1().getUnit().equals(DutyUnit.MASS_KG)
            && abstractItem.getSchedule1Part1A().getCalculationMethod().equals(DutyCalculationMethod.WITH_MAX_OF)) {
            LineItem lineItem = (LineItem) abstractItem;
            lineItem.getSchedule1Part1A().getDutyRate().getOtherDuty1().setAdditionalValue(lineItem.getUnitWeight());
        }
    }

    public static void applyAdditionalDutyRules(ItemInterface abstractItem) {
        //ATT-162
        if (abstractItem.getSchedule1Part3E() != null
            && abstractItem.getSchedule1Part3E().getDutyRate() != null
            && abstractItem.getSchedule1Part3E().getDutyRate().getOtherDuty1() != null
            && abstractItem.getSchedule1Part3E().getDutyRate().getOtherDuty1().getUnit() != null
            && abstractItem.getSchedule1Part3E().getDutyRate().getOtherDuty1().getUnit().equals(DutyUnit.MASS_KG)
            && abstractItem.getSchedule1Part3E().getCalculationMethod().equals(DutyCalculationMethod.SINGLE)) {

            if (abstractItem.getWeightUOM() != null) {
                BigDecimal weightKG = abstractItem.getWeightUOM().convert(abstractItem.getUnitWeight());
                abstractItem.getSchedule1Part3E().getDutyRate().getOtherDuty1().setAdditionalValue(weightKG);
            } else {
                abstractItem.getSchedule1Part3E().getDutyRate().getOtherDuty1().setAdditionalValue(BigDecimal.ZERO);
            }
        }
    }

    private static String getType(BaseTariff baseTariff) {
        if (baseTariff instanceof AdditionalTariff) {
            AdditionalTariff additionalTariff = (AdditionalTariff) baseTariff;
            return additionalTariff.getType();
        } else if (baseTariff instanceof AntiDumping) {
            AntiDumping antiDumping = (AntiDumping) baseTariff;
            return antiDumping.getType();
        } else if (baseTariff instanceof Environmental) {
            Environmental environmental = (Environmental) baseTariff;
            return environmental.getType();
        } else if (baseTariff instanceof SugarTax) {
            SugarTax sugarTax = (SugarTax) baseTariff;
            return sugarTax.getType();
        } else if (baseTariff instanceof Rebate) {
            Rebate rebate = (Rebate) baseTariff;
            return rebate.getType();
        }
        return null;
    }

    public static void clearTariffCode(Schedule1Part1A dutySchedule) {
        clearBaseTariffCode(dutySchedule);
        dutySchedule.getDutyRate().setPercentage(null);
        dutySchedule.setCalculationMethod(null);
        dutySchedule.setTradeAgreement(null);
        dutySchedule.setTradeAgreementOverridden(false);
        dutySchedule.setDutyDescription(null);
        dutySchedule.setSupplementaryQty1(null);
        dutySchedule.setSupplementaryQty2(null);
        dutySchedule.setSupplementaryQty3(null);
        clearOtherDuties(dutySchedule);
    }

    private static void clearTariffCode(Schedule1Part2A dutySchedule) {
        clearBaseTariffCode(dutySchedule);
        dutySchedule.getDutyRate().setValue(null);
        clearOtherDuties(dutySchedule);
    }

    private static void clearTariffCode(Schedule1Part2B dutySchedule) {
        clearBaseTariffCode(dutySchedule);
        clearOtherDuties(dutySchedule);
    }

    private static void clearTariffCode(Schedule2Part1 dutySchedule) {
        clearBaseTariffCode(dutySchedule);
        clearOtherDuties(dutySchedule);
        dutySchedule.setCalculationMethod(null);
    }

    private static void clearTariffCode(Schedule2Part2 dutySchedule) {
        clearBaseTariffCode(dutySchedule);
        clearOtherDuties(dutySchedule);
    }

    private static void clearTariffCode(Schedule1Part3E dutySchedule) {
        clearBaseTariffCode(dutySchedule);
        clearOtherDuties(dutySchedule);
    }

    private static void clearBaseTariffCode(DutySchedule dutySchedule) {
        dutySchedule.setValid(false);
        dutySchedule.setValidationDisabled(true);

        TariffHeading tariffHeading = dutySchedule.getTariffHeading();
        tariffHeading.setPart1(null);
        tariffHeading.setPart2(null);
        tariffHeading.setPart3(null);
        tariffHeading.setPart4(null);
        tariffHeading.setPart5(null);
    }

    public static void clearTariffCodes(ItemInterface abstractItem) {
        clearTariffCode(abstractItem.getSchedule1Part1A());
        clearTariffCode(abstractItem.getSchedule1Part2A());
        clearTariffCode(abstractItem.getSchedule1Part2B());
        clearTariffCode(abstractItem.getSchedule2Part1());
        clearTariffCodesS2P1(abstractItem);
        clearTariffCode(abstractItem.getSchedule2Part2());
        clearTariffCode(abstractItem.getSchedule1Part3E());
        clearTariffCode(abstractItem.getSchedule3Part1());
        clearTariffCode(abstractItem.getSchedule4Part1());
    }

    public static void clearTariffCodesS2P1(ItemInterface abstractItem) {
        if (abstractItem.getSchedule2Part1() != null) {
            abstractItem.getSchedule2Part1().setOriginatingPlace(null);
            abstractItem.getSchedule2Part1().getDutyRate().setPercentage(null);
            abstractItem.getSchedule2Part1().getDutyRate().setValue(null);
        }
    }

    public static void clearTariffCodesS1P1(ItemInterface abstractItem) {
        clearBaseTariffCode(abstractItem.getSchedule1Part1A());
        abstractItem.getSchedule1Part1A().getDutyRate().setPercentage(null);
        abstractItem.getSchedule1Part1A().setCalculationMethod(null);
        abstractItem.getSchedule1Part1A().setTradeAgreement(null);
        abstractItem.getSchedule1Part1A().setDutyDescription(null);
        clearOtherDuties(abstractItem.getSchedule1Part1A());
    }

    private static void clearTariffCode(Schedule3Part1 dutySchedule) {
        clearBaseTariffCode(dutySchedule);
        dutySchedule.getDutyRate().setPercentage(null);
        dutySchedule.setCalculationMethod(null);
        clearOtherDuties(dutySchedule);
    }

    private static void clearTariffCode(Schedule4Part1 dutySchedule) {
        clearBaseTariffCode(dutySchedule);
        dutySchedule.getDutyRate().setPercentage(null);
        dutySchedule.setCalculationMethod(null);
        clearOtherDuties(dutySchedule);
    }

    private static void clearOtherDuties(DutySchedule dutySchedule) {
        dutySchedule.getDutyRate().setOtherDuty1(null);
        dutySchedule.getDutyRate().setOtherDuty2(null);
        dutySchedule.getDutyRate().setOtherDuty3(null);
    }

    // Not sure these are in the right place. There is so much tariff code around
    public static TradeAgreement getCountryTradeAgreement(List<TradeAgreements> tradeAgreements, Country
            countryOfOrigin) {
        if (null != tradeAgreements) {
            List<TradeAgreement> tradeAgreementList = new ArrayList<>();
            for (TradeAgreements tradeAgreements2 : tradeAgreements) {
                if (!tradeAgreementList.contains(tradeAgreements2.getTradeAgreement())) {
                    tradeAgreementList.add(tradeAgreements2.getTradeAgreement());
                    if (tradeAgreements2.getCountries().contains(countryOfOrigin)) {
                        return tradeAgreements2.getTradeAgreement();
                    }
                }
            }
        }
        return null;
    }

    // Not sure these are in the right place. There is so much tariff code around
    public static Map.Entry<String, Duty> getDutyFromAgreements(TradeAgreement tradeAgreement, TariffSearchResult
            tariffSearchResult) {
        if (tradeAgreement != null && tariffSearchResult != null && tariffSearchResult.getTariff() != null) {
            switch (tradeAgreement) {
                case AFCFTA:
                    return new AbstractMap.SimpleEntry("AFCFTA", tariffSearchResult.getTariff().getAfCFTADuty());
                case EFTA:
                    return new AbstractMap.SimpleEntry("EFTA", tariffSearchResult.getTariff().getEftaDuty());
                case EU:
                    return new AbstractMap.SimpleEntry("EU", tariffSearchResult.getTariff().getEuDuty());
                case SADC:
                    return new AbstractMap.SimpleEntry("SADC", tariffSearchResult.getTariff().getSadcDuty());
                case MERCOSUR:
                    return new AbstractMap.SimpleEntry("MERCOSUR", tariffSearchResult.getTariff().getMercosurDuty());
                default:
                    return new AbstractMap.SimpleEntry("General", tariffSearchResult.getTariff().getGeneralDuty());
            }

        } else {
            if (tariffSearchResult != null && tariffSearchResult.getTariff() != null) {
                return new AbstractMap.SimpleEntry("General", tariffSearchResult.getTariff().getGeneralDuty());
            }
        }

        return null;
    }

    public static boolean hasAdditional(Tariff tariff) {
        if (tariff != null) {
            return !tariff.getAdditionalTariffs().isEmpty() || !tariff.getAntiDumping().isEmpty() || !tariff.getEnvironmentalTariffs().isEmpty();
        }
        return false;
    }

    public static boolean hasRebates(Tariff tariff) {
        if (tariff != null) {
            return !tariff.getRebateTariffs().isEmpty();
        }
        return false;
    }

    public static void setRebateTariffCodes(ItemInterface abstractItem, Rebate baseTariff) {
        applyRebate(abstractItem, baseTariff);
    }

}