package com.prolog.rdc.tms.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.prolog.framework.common.message.RestMessage;
import com.prolog.framework.core.exception.PrologException;
import com.prolog.framework.core.restriction.Criteria;
import com.prolog.framework.core.restriction.Restriction;
import com.prolog.framework.core.restriction.Restrictions;
import com.prolog.product.core.framework.entity.UserEntity;
import com.prolog.rdc.tms.constant.BmsConstant;
import com.prolog.rdc.tms.constant.enums.LogTypeEnum;
import com.prolog.rdc.tms.dao.mapper.*;
import com.prolog.rdc.tms.model.dto.CheckConditionDTO;
import com.prolog.rdc.tms.model.dto.LoadingBillPriceDTO;
import com.prolog.rdc.tms.model.dto.ShipBillPriceDTO;
import com.prolog.rdc.tms.model.dto.SySParameterDTO;
import com.prolog.rdc.tms.model.dto.basicConfigure.StrategyBusinessMatchingDTO;
import com.prolog.rdc.tms.model.entity.*;
import com.prolog.rdc.tms.model.vo.basicConfigure.StrategyBusinessItemVO;
import com.prolog.rdc.tms.model.vo.basicConfigure.StrategyBusinessMatchingVO;
import com.prolog.rdc.tms.rmi.feign.MaindataFeign;
import com.prolog.rdc.tms.service.BillPayCostStrategyService;
import com.prolog.rdc.tms.service.strategy.ExecuteStrategyServiceImpl;
import com.prolog.rdc.tms.service.strategy.PayExecuteStrategyServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.plugin.PluginException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
@Slf4j
public class BillPayCostStrategyServiceImpl implements BillPayCostStrategyService {

    @Autowired
    private ExecuteStrategyServiceImpl strategyService;

    @Autowired
    private PayExecuteStrategyServiceImpl strategyPayService;
    @Autowired
    private LogisticsContractMapper logisticsContractMapper;
    @Autowired
    private FreightPriceMapper freightPriceMapper;
    @Autowired
    private BmsFreightPriceConditionMapper conditionMapper;
    @Autowired
    private ShipBillFeeTemporaryDetailMapper temporaryDetailMapper;

    @Autowired
    private BmsBillPayFeeHeaderMapper bmsBillPayFeeHeaderMapper;
    @Autowired
    private BmsBillPayFeeDetailMapper bmsBillPayFeeDetailMapper;

    @Autowired
    private MaindataFeign maindataTmsResource;

    @Autowired
    private BmsLogOperationMapper logOperationMapper;

    @Override
    public Integer loadingBillDriverCostStrategy(BmsLoadingBillHeaderModel loadingModel, String source,UserEntity user) {
        Integer rs = 200;
        log.info("派车单:" + JSON.toJSONString(loadingModel));

        // 先删除所有的费用
        this.deleteFeeDtl(loadingModel.getLoadingBillNo(), loadingModel.getId(), user, source);

        BmsBillPayFeeHeaderModel feeHeaderModel = new BmsBillPayFeeHeaderModel();
        feeHeaderModel.setBillNo(loadingModel.getLoadingBillNo());
        feeHeaderModel.setBillId(loadingModel.getId());
        feeHeaderModel.setBillType(20);
        feeHeaderModel.setSettlementDepartment(loadingModel.getSettlementDepartment());
        feeHeaderModel.setSettlementDepartmentId(loadingModel.getSettlementDepartmentId());
        feeHeaderModel.setSettlementDepartmentCode(loadingModel.getSettlementDepartmentCode());
        feeHeaderModel.setCheckStatus(0);
        feeHeaderModel.setSettlementStatus(0);
        feeHeaderModel.setPayFeeType(2);
        try {
            // 1.获取承运合同配置
            Criteria criteriaContract = Criteria.forClass(BmsLogisticsContractModel.class);
            Restriction r1 = Restrictions.eq(BmsLogisticsContractModel::getFirstPartyCode, loadingModel.getSettlementDepartmentCode());
            Restriction r2 = Restrictions.le(BmsLogisticsContractModel::getEffectiveDate, loadingModel.getStartDate());
            Restriction r3 = Restrictions.ge(BmsLogisticsContractModel::getExpiryDate, loadingModel.getStartDate());
            Restriction r4 = Restrictions.eq(BmsLogisticsContractModel::getEnterpriseId, user.getEnterpriseId());
            Restriction r5 = Restrictions.eq(BmsLogisticsContractModel::getStatus, 1);
            Restriction r7 = Restrictions.eq(BmsLogisticsContractModel::getContractMode, 3);
            criteriaContract.setRestriction(Restrictions.and(r1, r2, r3, r4, r5, r7));
            List<BmsLogisticsContractModel> contractModels = logisticsContractMapper.findByCriteria(criteriaContract);
            if (ObjectUtil.isEmpty(contractModels)) {
                log.info("派车单{}匹配不到承运合同,请先创建合同", JSON.toJSONString(loadingModel));
                throw new PrologException(StrUtil.format("派车单{}匹配不到承运合同,请先创建合同", loadingModel.getLoadingBillNo()));
            }
            log.info("匹配到的合同:" + JSON.toJSONString(contractModels));

            // 获取所有合同的价格表
            List<String> contractNoList = contractModels.stream().map(BmsLogisticsContractModel::getContractNo).collect(Collectors.toList());
            Criteria fCriteria = Criteria.forClass(BmsFreightPriceModel.class);
            Restriction r8 = Restrictions.in(BmsFreightPriceModel::getContractNo, contractNoList.stream().toArray(String[]::new));
            Restriction r9 = Restrictions.eq(BmsFreightPriceModel::getEnterpriseId, user.getEnterpriseId());
            Restriction r10 = Restrictions.eq(BmsFreightPriceModel::getStatus, 1);
            Restriction r11 = Restrictions.eq(BmsFreightPriceModel::getSettlementOrderType, 2);
            fCriteria.setRestriction(Restrictions.and(r8, r9, r10, r11));
            List<BmsFreightPriceModel> allPriceModelList = freightPriceMapper.findByCriteria(fCriteria);
            if (ObjectUtil.isEmpty(allPriceModelList)) {
                log.info(StrUtil.format("合同{}价格表不存在，请先创建价格表", contractNoList.stream().collect(Collectors.joining(","))));
                throw new PrologException(StrUtil.format("合同{}价格表不存在，请先创建价格表", contractNoList.stream().collect(Collectors.joining(","))));
            }
            log.info("获取所有合同的价格表:" + JSON.toJSONString(allPriceModelList));

            // 满足条件的价格表
            List<BmsFreightPriceModel> matchedCntPriceModelList = Lists.newArrayList();
            for (BmsFreightPriceModel priceModel : allPriceModelList) {
                // 3.查询匹配条件
                Criteria dCriteria = Criteria.forClass(BmsFreightPriceConditionModel.class);
                Restriction r12 = Restrictions.eq(BmsFreightPriceConditionModel::getPriceNo, priceModel.getPriceNo());
                Restriction r13 = Restrictions.eq(BmsFreightPriceConditionModel::getEnterpriseId, user.getEnterpriseId());
                dCriteria.setRestriction(Restrictions.and(r12, r13));
                List<BmsFreightPriceConditionModel> conditionList = conditionMapper.findByCriteria(dCriteria);
                if (ObjectUtil.isNotEmpty(conditionList)) {
                    // 不是空，需要判断条件是否满足
                    try {
                        CheckConditionDTO dto = this.checkLoadingPriceCondition(conditionList, loadingModel);
                        if (!dto.getFlag()) {
                            log.info("匹配价格表的满足条件校验失败:{}", dto.getMessage());
                            continue;
                        } else {
                            matchedCntPriceModelList.add(priceModel);
                        }
                    } catch (Exception e) {
                        log.info("匹配价格表的满足条件失败:{}" + ExceptionUtil.stacktraceToString(e));
                        throw new PrologException("匹配价格表的满足条件失败");
                    }
                } else {
                    matchedCntPriceModelList.add(priceModel);
                }
            }
            log.info("匹配到满足条件的价格表:" + JSON.toJSONString(matchedCntPriceModelList));

            if (ObjectUtil.isEmpty(matchedCntPriceModelList)) {
                throw new PrologException("派车单没有匹配到价格表");
            }
            Map<String, List<BmsFreightPriceModel>> contractListMap = matchedCntPriceModelList.stream().collect(Collectors.groupingBy(BmsFreightPriceModel::getContractNo));
            if (contractListMap.size() > 1) {
                throw new PrologException("派车单匹配到多个合同:" + contractListMap.keySet().stream().collect(Collectors.joining(",")));
            }
            Map<String, List<BmsFreightPriceModel>> priceListMap = matchedCntPriceModelList.stream().collect(Collectors.groupingBy(BmsFreightPriceModel::getExpenseName));
            if (priceListMap.size() != matchedCntPriceModelList.size()) {
                throw new PrologException("派车单匹配到重复的价格表");
            }
            String matchedPriceTblContractNo = matchedCntPriceModelList.get(0).getContractNo();
            List<BmsLogisticsContractModel> contractModel = contractModels.stream().filter(contract -> contract.getContractNo().equals(matchedPriceTblContractNo)).collect(Collectors.toList());
            if (ObjectUtil.isEmpty(contractModel)) {
                throw new PrologException("价格表对应的合同不在合同数据中");
            }

            List<LoadingBillPriceDTO> allList = Lists.newArrayList();
            for (BmsFreightPriceModel priceModel : matchedCntPriceModelList) {
                try {
                    Integer settlementModel = priceModel.getSettlementModel();
                    // 1.获取运费
                    List<LoadingBillPriceDTO> list = strategyPayService.executeStrategyLoading(contractModel.get(0), priceModel, settlementModel, loadingModel, source,user);
                    allList.addAll(list);
                } catch (Exception e) {
                    log.info("派车单:{},司机物流费用计算失败:{}",JSON.toJSONString(loadingModel),ExceptionUtil.stacktraceToString(e));
                    throw new PluginException("费用计算失败");
                }
            }
            for (LoadingBillPriceDTO priceDTO : allList) {
                feeHeaderModel.setCostContract(priceDTO.getCostContract());
                feeHeaderModel.setCostDate(DateUtil.date());
                feeHeaderModel.setSettlementCompanyId(priceDTO.getFirstPartyId());
                feeHeaderModel.setSettlementCompanyCode(priceDTO.getFirstPartyCode());
                feeHeaderModel.setSettlementCompany(priceDTO.getFirstPartyName());
                feeHeaderModel.setAbnormalStatus(0);
                feeHeaderModel.setCostStatus(1);

                BmsLogOperationModel feeVo = new BmsLogOperationModel();
                feeVo.setCreatetime(DateUtil.date());
                feeVo.setCreateperson(user.getNickname());
                feeVo.setEnterpriseId(user.getEnterpriseId());
                feeVo.setEnterpriseName(user.getEnterpriseName());
                feeVo.setOrderNo(loadingModel.getLoadingBillNo());
                feeVo.setLogMemo("派车单匹配价格表" + priceDTO.getCostPriceTable());
                feeVo.setLogType(LogTypeEnum.LOADING_BILL.getCode());
                logOperationMapper.save(feeVo);
            }
            // 支出总价 类型为支出的含税金额
            BigDecimal PayAmount = getShipbillTaxAmt(loadingModel.getId(), loadingModel.getLoadingBillNo(), null);
            feeHeaderModel.setPayAmount(PayAmount);
            // 类型为支出的来源是价格表生成 含税金额
            BigDecimal contractPayAmount = getShipbillTaxAmt(loadingModel.getId(), loadingModel.getLoadingBillNo(), 1);
            feeHeaderModel.setContractPayAmount(contractPayAmount);
        } catch (Exception e) {
            log.info("派车单司机物流价格计费失败:{}", ExceptionUtil.stacktraceToString(e));
            feeHeaderModel.setCostFailReason(e.getMessage());
            feeHeaderModel.setAbnormalStatus(1);
            feeHeaderModel.setCostStatus(2);
            rs = 255;
        }
        feeHeaderModel.setCreateperson(user.getNickname());
        feeHeaderModel.setCreatetime(DateUtil.date());
        feeHeaderModel.setUpdateperson(user.getNickname());
        feeHeaderModel.setUpdatetime(DateUtil.date());
        feeHeaderModel.setEnterpriseId(user.getEnterpriseId());
        feeHeaderModel.setEnterpriseName(user.getEnterpriseName());
        feeHeaderModel.setSettlementStatus(BmsConstant.SETTLEMENT_STATUS_0);

        bmsBillPayFeeHeaderMapper.save(feeHeaderModel);

        return rs;
    }
    
    @Override
    public Integer costShipBillTrailerStrategy(BmsShipBillHeaderModel costStrategy, List<BmsShipBillDetailModel> detailModels, String source,UserEntity user) {
        log.info("运单:" + JSON.toJSONString(costStrategy));
        log.info("运单明细:" + JSON.toJSONString(detailModels));
        Integer rs = 200;
        // 先删除所有的费用
        this.deleteFeeDtl(costStrategy.getShipbillNo(),costStrategy.getId(), user, source);

        BmsBillPayFeeHeaderModel feeHeaderModel = new BmsBillPayFeeHeaderModel();
        feeHeaderModel.setBillNo(costStrategy.getShipbillNo());
        feeHeaderModel.setBillId(costStrategy.getId());
        feeHeaderModel.setBillType(10);
//        feeHeaderModel.setSettlementDepartment(costStrategy.getSettlementDepartment());
//        feeHeaderModel.setSettlementDepartmentId(costStrategy.getSettlementDepartmentId());
//        feeHeaderModel.setSettlementDepartmentCode(costStrategy.getSettlementDepartmentCode());
        feeHeaderModel.setCheckStatus(0);
        feeHeaderModel.setSettlementStatus(BmsConstant.SETTLEMENT_STATUS_0);
        feeHeaderModel.setPayFeeType(1);
        try {
            String carrierCode = costStrategy.getCarriersCode();
            // 1.获取合同配置
            Criteria criteria = Criteria.forClass(BmsLogisticsContractModel.class);
//            Restriction r1 = Restrictions.eq(BmsLogisticsContractModel::getFirstPartyCode, costStrategy.getSettlementDepartmentCode());
            Restriction r2 = Restrictions.eq(BmsLogisticsContractModel::getSecondPartyCode, carrierCode);
            Restriction r3 = Restrictions.le("effectiveDate", costStrategy.getStartDate());
            Restriction r4 = Restrictions.ge("expiryDate", costStrategy.getStartDate());
            Restriction r5 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
            Restriction r16 = Restrictions.eq("status", 1);
            Restriction r17 = Restrictions.eq(BmsLogisticsContractModel::getContractMode, 1);

            criteria.setRestriction(Restrictions.and(r2, r3, r4, r5, r16, r17));
            List<BmsLogisticsContractModel> models = logisticsContractMapper.findByCriteria(criteria);
            if (ObjectUtil.isEmpty(models)) {
                throw new PluginException("物流合同不存在，请先创建合同");
            }
            log.info("匹配到的合同:" + JSON.toJSONString(models));

            List<ShipBillPriceDTO> allList = Lists.newArrayList();
            Integer pricePcdMatchType = 4;
            StrategyBusinessMatchingDTO businessMatchingDTO = shipbillMatchBusinessRule(costStrategy, detailModels,user);
            if (ObjectUtil.isNotEmpty(businessMatchingDTO) && businessMatchingDTO.getPricePcdMatchTypeSelect().intValue() == 1) {
                pricePcdMatchType = businessMatchingDTO.getPricePcdMatchType();
            } else {
                // 获取价格表省市区匹配方式的系统参数
                RestMessage<SySParameterDTO> parameterModel = maindataTmsResource.queryParameter();
                if (ObjectUtil.isEmpty(parameterModel) || !parameterModel.isSuccess()) {
                    throw new PluginException("获取系统参数异常");
                }
                pricePcdMatchType = parameterModel.getData().getPricePcdMatchType();
            }
            log.info("省市区匹配方式:" + pricePcdMatchType);
            // 获取所有合同的价格表
            List<String> contractNoList = models.stream().map(BmsLogisticsContractModel::getContractNo).collect(Collectors.toList());
            Criteria fCriteria = Criteria.forClass(BmsFreightPriceModel.class);
            Restriction r6 = Restrictions.in("contractNo", contractNoList.stream().toArray(String[]::new));
            Restriction r10 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
            Restriction r14 = Restrictions.eq("status", 1);
            fCriteria.setRestriction(Restrictions.and(r6, r10, r14));
            List<BmsFreightPriceModel> allPriceModelList = freightPriceMapper.findByCriteria(fCriteria);
            if (ObjectUtil.isEmpty(allPriceModelList)) {
                throw new PluginException(String.format("合同[%s]价格表不存在，请先创建价格表", contractNoList.stream().collect(Collectors.joining(","))));
            }
            log.info("获取所有合同的价格表:" + JSON.toJSONString(allPriceModelList));
            // 满足条件的价格表
            List<BmsFreightPriceModel> matchedCntPriceModelList = Lists.newArrayList();
            for (BmsFreightPriceModel priceModel : allPriceModelList) {
                // 3.查询匹配条件
                Criteria dCriteria = Criteria.forClass(BmsFreightPriceConditionModel.class);
                Restriction r8 = Restrictions.eq("priceNo", priceModel.getPriceNo());
                Restriction r9 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
                dCriteria.setRestriction(Restrictions.and(r8, r9));
                List<BmsFreightPriceConditionModel> conditionList = conditionMapper.findByCriteria(dCriteria);
                if (ObjectUtil.isNotEmpty(conditionList)) {
                    // 不是空，需要判断条件是否满足
                    try {
                        CheckConditionDTO dto = this.checkCondition(conditionList, costStrategy, detailModels);
                        if (!dto.getFlag()) {
                            log.info("匹配价格表的满足条件校验失败:{}", dto.getMessage());
                        } else {
                            matchedCntPriceModelList.add(priceModel);
                        }
                    } catch (Exception e) {
                        log.info("匹配价格表的满足条件失败:{}" + ExceptionUtil.stacktraceToString(e));
                        throw new PluginException("匹配价格表的满足条件失败");
                    }
                } else {
                    matchedCntPriceModelList.add(priceModel);
                }
            }
            log.info("匹配到满足条件的价格表:" + JSON.toJSONString(matchedCntPriceModelList));

            if (ObjectUtil.isEmpty(matchedCntPriceModelList)) {
                throw new PrologException("价格表匹配条件不满足");
            }
            // 用始发地，目的地匹配价格表
            List<BmsFreightPriceModel> matchedPcdPriceModelList = Lists.newArrayList();
            if (pricePcdMatchType.intValue() < BmsConstant.PRICE_PCD_MATCH_TYPE_IGNORE.intValue()) {
                switch (pricePcdMatchType.intValue()) {
                    case 1:
                        matchedPcdPriceModelList = pcdPreciseMatchPrice(costStrategy, matchedCntPriceModelList);
                        break;
                    case 2:
                        matchedPcdPriceModelList = pcdUpMatchPrice(costStrategy, matchedCntPriceModelList);
                        break;
                    case 3:
                        matchedPcdPriceModelList = pcdUpIgnoreMatchPrice(costStrategy, matchedCntPriceModelList);
                        break;
                }
            } else {
                matchedPcdPriceModelList = matchedCntPriceModelList;
            }
            if (ObjectUtil.isEmpty(matchedPcdPriceModelList)) {
                throw new PrologException("价格表的始发地和目的地,不满足");
            }
            Map<String, List<BmsFreightPriceModel>> contractListMap = matchedPcdPriceModelList.stream().collect(Collectors.groupingBy(BmsFreightPriceModel::getContractNo));
            if (contractListMap.size() > 1) {
                throw new PrologException("运单匹配到多个合同:" + contractListMap.keySet().stream().collect(Collectors.joining(",")));
            }
            Map<String, List<BmsFreightPriceModel>> priceListMap = matchedPcdPriceModelList.stream().collect(Collectors.groupingBy(BmsFreightPriceModel::getExpenseName));
            if (priceListMap.size() != matchedPcdPriceModelList.size()) {
                throw new PrologException("运单匹配到重复的价格表");
            }
            String matchedPriceTblContractNo = matchedPcdPriceModelList.get(0).getContractNo();
            List<BmsLogisticsContractModel> contractModel = models.stream().filter(contract -> contract.getContractNo().equals(matchedPriceTblContractNo)).collect(Collectors.toList());
            if (ObjectUtil.isEmpty(contractModel)) {
                throw new PluginException("价格表对应的合同不在合同数据中");
            }
            matchedPcdPriceModelList = matchedPcdPriceModelList.stream().sorted((price1, price2) -> "运费".equals(price1.getExpenseName()) ? -1 : "运费".equals(price2.getExpenseName()) ? 1 : 0).collect(Collectors.toList());
            for (BmsFreightPriceModel priceModel : matchedPcdPriceModelList) {
                try {
                    Integer settlementModel = priceModel.getSettlementModel();
                    // 阶梯计费且计费单据是运单包裹
                    if (settlementModel == 1 && priceModel.getSettlementOrderType() == 3) {
                        settlementModel = BmsConstant.LADDER_FOR_PACKAGE;
                    } else if (settlementModel == 8 && priceModel.getSettlementOrderType() == 3) {
                        settlementModel = BmsConstant.JD_LADDER_COST;
                    }
                    // 1.获取运费
                    List<ShipBillPriceDTO> list = strategyService.executeStrategy(contractModel.get(0), priceModel, settlementModel, costStrategy, source,user);
                    allList.addAll(list);
                } catch (Exception e) {
                    log.info("运单:{},托运物流费用计算失败:{}",JSON.toJSONString(costStrategy),ExceptionUtil.stacktraceToString(e));
                    throw new PrologException("计费失败，失败原因：" + e.getMessage());
                }
            }
            for (ShipBillPriceDTO priceDTO : allList) {
                feeHeaderModel.setCostContract(priceDTO.getCostContract());
                feeHeaderModel.setCostDate(DateUtil.date());
//                feeHeaderModel.setSettlementCompanyId(priceDTO.getFirstPartyId());
//                feeHeaderModel.setSettlementCompanyCode(priceDTO.getFirstPartyCode());
//                feeHeaderModel.setSettlementCompany(priceDTO.getFirstPartyName());
                feeHeaderModel.setAbnormalStatus(0);
                feeHeaderModel.setCostStatus(1);

                BmsLogOperationModel feeVo = new BmsLogOperationModel();
                feeVo.setCreatetime(DateUtil.date());
                feeVo.setCreateperson(user.getNickname());
                feeVo.setEnterpriseId(user.getEnterpriseId());
                feeVo.setEnterpriseName(user.getEnterpriseName());
                feeVo.setOrderNo(costStrategy.getShipbillNo());
                feeVo.setLogMemo("运单匹配价格表" + priceDTO.getCostPriceTable());
                feeVo.setLogType(LogTypeEnum.SHIP_BILL.getCode());
                logOperationMapper.save(feeVo);
            }
            // 支出总价 类型为支出的含税金额
            BigDecimal payAmount = getShipbillTaxAmt(costStrategy.getId(), costStrategy.getShipbillNo(), null);
            feeHeaderModel.setPayAmount(payAmount);
            // 类型为支出的来源是价格表生成 含税金额
            BigDecimal contractPayAmount = getShipbillTaxAmt(costStrategy.getId(), costStrategy.getShipbillNo(), 1);
            feeHeaderModel.setContractPayAmount(contractPayAmount);
        } catch (Exception e) {
            log.info("托运物流价格计费失败:{}",ExceptionUtil.stacktraceToString(e));
            feeHeaderModel.setCostFailReason(e.getMessage());
            feeHeaderModel.setAbnormalStatus(1);
            feeHeaderModel.setCostStatus(2);
            rs = 255;
        }
        feeHeaderModel.setCreateperson(user.getNickname());
        feeHeaderModel.setCreatetime(DateUtil.date());
        feeHeaderModel.setUpdateperson(user.getNickname());
        feeHeaderModel.setUpdatetime(DateUtil.date());
        feeHeaderModel.setEnterpriseId(user.getEnterpriseId());
        feeHeaderModel.setEnterpriseName(user.getEnterpriseName());

        bmsBillPayFeeHeaderMapper.save(feeHeaderModel);

        return rs;
    }

    private void deleteFeeDtl(String billNo, Long billId, UserEntity user, String source) {
        // 0：试验，1：非试验
        if (source.equals("0")) {
            Criteria tcriteria = Criteria.forClass(BmsShipBillFeeTemporaryDetailModel.class);
            Restriction r9 = Restrictions.eq("shipbillNo", billNo);
            Restriction r10 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
            tcriteria.setRestriction(Restrictions.and(r9, r10));
            List<BmsShipBillFeeTemporaryDetailModel> tmodels = temporaryDetailMapper.findByCriteria(tcriteria);
            if (ObjectUtil.isNotEmpty(tmodels)) {
                temporaryDetailMapper.deleteByCriteria(tcriteria);
            }
        } else {
            // 价格表
            Criteria criteriaPayFeeHeader = Criteria.forClass(BmsBillPayFeeHeaderModel.class);
            Restriction r13 = Restrictions.eq(BmsBillPayFeeHeaderModel::getBillId, billId);
            Restriction r14 = Restrictions.eq(BmsBillPayFeeHeaderModel::getBillNo, billNo);
            Restriction r15 = Restrictions.eq(BmsBillPayFeeHeaderModel::getEnterpriseId, user.getEnterpriseId());
            criteriaPayFeeHeader.setRestriction(Restrictions.and(r13, r14, r15));
            List<BmsBillPayFeeHeaderModel> feeHeaderModels = bmsBillPayFeeHeaderMapper.findByCriteria(criteriaPayFeeHeader);
            if (ObjectUtil.isNotEmpty(feeHeaderModels)) {
                bmsBillPayFeeHeaderMapper.deleteByCriteria(criteriaPayFeeHeader);
                log.info(StrUtil.format("费用主表:{}被删除", JSON.toJSONString(feeHeaderModels)));
            }

            // 判断是否存 运单合同 + 价格表 + 来源
            Criteria criteriaPayFeeDetail = Criteria.forClass(BmsBillPayFeeDetailModel.class);
            Restriction r3 = Restrictions.eq(BmsBillPayFeeDetailModel::getBillId, billId);
            Restriction r4 = Restrictions.eq(BmsBillPayFeeDetailModel::getBillNo, billNo);
            Restriction r5 = Restrictions.eq(BmsBillPayFeeDetailModel::getEnterpriseId, user.getEnterpriseId());
            criteriaPayFeeDetail.setRestriction(Restrictions.and(r3, r4, r5));
            List<BmsBillPayFeeDetailModel> dtlModels = bmsBillPayFeeDetailMapper.findByCriteria(criteriaPayFeeDetail);
            if (ObjectUtil.isNotEmpty(dtlModels)) {
                bmsBillPayFeeDetailMapper.deleteByCriteria(criteriaPayFeeDetail);
                log.info(StrUtil.format("费用明细:{}被删除", JSON.toJSONString(dtlModels)));
            }
        }
    }

    private CheckConditionDTO checkCondition(List<BmsFreightPriceConditionModel> conditionList, BmsShipBillHeaderModel costStrategy, List<BmsShipBillDetailModel> detailDTOS) throws Exception {
        log.info("价格表满足条件:" + JSON.toJSONString(conditionList));
        log.info("价格表满足条件匹配,运单:" + JSON.toJSONString(costStrategy));
        log.info("价格表满足条件匹配,运单明细:" + JSON.toJSONString(detailDTOS));
        Integer deliveryMethodType = costStrategy.getDeliveryMethodType();
        // 1客户 2仓库 3供应商
        Integer shipperType = costStrategy.getShipperType();
        Integer consigneeType = costStrategy.getConsigneeType();
        Integer orderType = costStrategy.getOrderType();
        Integer orderBusinessType = costStrategy.getOrderBusinessType();
        Integer transportType = costStrategy.getTransportType();
        Integer temperatureRequirement = costStrategy.getTemperatureRequirement();
        String cargoOwnerCode = costStrategy.getCargoOwnerCode();
        String shipperUnitCode = costStrategy.getShipperUnitCode();  // 发货放单位
        String consigneeUnitCode = costStrategy.getConsigneeUnitCode();  // 收货放单位
        String departmentCode = costStrategy.getSettlementDepartmentCode();
        String vehicleTypeCode = costStrategy.getVehicleTypeCode();
        CheckConditionDTO dto = new CheckConditionDTO();
        dto.setFlag(true);
        for (BmsFreightPriceConditionModel bmsFreightPriceConditionModel : conditionList) {
            log.info("价格表满足条件的明细条件:" + JSON.toJSONString(bmsFreightPriceConditionModel));
            // 条件 1：配送方式，2：发货方类型，3：收货放类型，4：订单类型，5：业务类型，6：运输模式，7：温度要求，8：货主，9：部门，10：商品,11:商品品类 12:车型
            Integer conditionType = bmsFreightPriceConditionModel.getConditionType();
            String conditionValue = bmsFreightPriceConditionModel.getConditionValue();
            String conditionValueName = bmsFreightPriceConditionModel.getConditionValueName();
            String unitCode = bmsFreightPriceConditionModel.getUnitCode();
            String unitName = bmsFreightPriceConditionModel.getUnitName();
            if (conditionType == 1 && !Objects.equals(deliveryMethodType.toString(), conditionValue)) {
                dto.setMessage("没有匹配到配送方式对应的类型");
                dto.setFlag(false);
                return dto;
            }
            if (conditionType == 2 && (!Objects.equals(shipperType.toString(), conditionValue) || !unitCode.contains(shipperUnitCode))) {
                dto.setMessage("没有匹配到发货方对应的类型");
                dto.setFlag(false);
                return dto;
            }
            if (conditionType == 3 && (!Objects.equals(consigneeType.toString(), conditionValue) || !unitCode.contains(consigneeUnitCode))) {
                dto.setMessage("没有匹配到收货方类型");
                dto.setFlag(false);
                return dto;
            }
            if (conditionType == 4 && !Objects.equals(orderType.toString(), conditionValue)) {
                dto.setMessage("没有匹配到订单类型");
                dto.setFlag(false);
                return dto;
            }
            if (conditionType == 5 && !Objects.equals(orderBusinessType.toString(), conditionValue)) {
                dto.setMessage("没有匹配到业务类型");
                dto.setFlag(false);
                return dto;
            }
            if (conditionType == 6 && !Objects.equals(transportType.toString(), conditionValue)) {
                dto.setMessage("没有匹配到运输类型");
                dto.setFlag(false);
                return dto;
            }
            if (conditionType == 7 && !Objects.equals(temperatureRequirement.toString(), conditionValue)) {
                dto.setMessage("没有匹配到温度类型");
                dto.setFlag(false);
                return dto;
            }
            // 货主
            if (conditionType == 8 && !unitCode.contains(cargoOwnerCode)) {
                dto.setMessage("没有匹配到货主");
                dto.setFlag(false);
                return dto;
            }
            // 部门
            if (conditionType == 9 && !unitCode.contains(departmentCode)) {
                dto.setMessage("没有匹配到部门");
                dto.setFlag(false);
                return dto;
            }
            if (conditionType == 10) {
                List<String> itemNames = detailDTOS.stream().map(BmsShipBillDetailModel::getItemName).collect(Collectors.toList());
                for (String itemName : itemNames) {
                    if (unitName.contains(itemName)) {
                        dto.setFlag(true);
                        dto.setMessage(null);
                        return dto;
                    } else {
                        dto.setMessage("没有匹配到商品信息");
                        dto.setFlag(false);
                    }
                }
                if (!dto.getFlag()) {
                    return dto;
                }
            }
            if (conditionType == 11) {
                List<String> itemCategoryCode = detailDTOS.stream().map(BmsShipBillDetailModel::getItemCategoryCode).collect(Collectors.toList());
                for (String categoryCode : itemCategoryCode) {
                    if (unitCode.contains(categoryCode)) {
                        dto.setFlag(true);
                        dto.setMessage(null);
                        return dto;
                    } else {
                        dto.setMessage("没有匹配到商品品类信息");
                        dto.setFlag(false);
                    }
                }
                if (!dto.getFlag()) {
                    return dto;
                }
            }
            if (conditionType == 12 && !unitCode.contains(vehicleTypeCode)) {
                dto.setMessage("没有匹配到车型");
                dto.setFlag(false);
                return dto;
            }
        }
        return dto;
    }

    /**
     * 运单匹配业务规则
     *
     * @param model
     * @return
     */
    public StrategyBusinessMatchingDTO shipbillMatchBusinessRule(BmsShipBillHeaderModel model, List<BmsShipBillDetailModel> detailModels,UserEntity user) {
        // 新增后自动提交判定
        StrategyBusinessMatchingVO matchBusinessVO = new StrategyBusinessMatchingVO();
        // 配送方式
        matchBusinessVO.setDeliveryMethodType(model.getDeliveryMethodType());
        // 发货方类型
        matchBusinessVO.setShipperType(model.getShipperType());
        // 发货方单位ID
        matchBusinessVO.setShipperUnitId(model.getShipperUnitId());
        // 收货方类型
        matchBusinessVO.setConsigneeType(model.getConsigneeType());
        // 收货方单位ID
        matchBusinessVO.setConsigneeUnitId(model.getConsigneeUnitId());
        // 订单类型
        matchBusinessVO.setOrderType(model.getOrderType());
        // 订单业务类型
        matchBusinessVO.setOrderBusinessType(model.getOrderBusinessType());
        // 运输模式
        matchBusinessVO.setTransportType(model.getTransportType());
        // 温度要求
        matchBusinessVO.setTemperatureRequirement(model.getTemperatureRequirement());
        // 货主ID
        matchBusinessVO.setCargoOwnerId(model.getCargoOwnerId());
        // 部门
        matchBusinessVO.setDepartmentId(model.getDepartmentId());
        matchBusinessVO.setTotalPcs(model.getTotalPcs());
        matchBusinessVO.setTotalWeight(model.getTotalWeight());
        matchBusinessVO.setUser(user);

        if (ObjectUtil.isNotEmpty(detailModels)) {
            List<StrategyBusinessItemVO> businessItemVOS = Lists.newArrayList();
            for (BmsShipBillDetailModel detailModel : detailModels) {
                StrategyBusinessItemVO businessItemVO = new StrategyBusinessItemVO();
                businessItemVO.setItemId(detailModel.getItemId());
                businessItemVO.setItemCategoryId(detailModel.getItemCategoryId());
                businessItemVO.setPcs(detailModel.getPcs());
                businessItemVO.setWeight(detailModel.getWeight());

                businessItemVOS.add(businessItemVO);
            }
            matchBusinessVO.setBusinessItemVOS(businessItemVOS);
        }
        log.info("运单匹配业务规则入参:" + JSON.toJSONString(matchBusinessVO));
        RestMessage<List<StrategyBusinessMatchingDTO>> matchRs = maindataTmsResource.matchingBusinessExecute(matchBusinessVO);
        if (!matchRs.isSuccess()) {
            throw new PrologException("运单【" + model.getShipbillNo() + "】调用maindata服务运单匹配业务规则失败");
        }
        List<StrategyBusinessMatchingDTO> strategyBusinessMatchingDTOS = matchRs.getData();
        log.info("运单匹配到的业务规则:" + JSON.toJSONString(strategyBusinessMatchingDTOS));
        if (ObjectUtil.isEmpty(strategyBusinessMatchingDTOS)) {
            return null;
        }
        if (strategyBusinessMatchingDTOS.size() > 1) {
            throw new PrologException("运单【" + model.getShipbillNo() + "】匹配到多个业务规则策略");
        }
        return strategyBusinessMatchingDTOS.get(0);
    }

    /**
     * 省市区精准匹配
     *
     * @param model
     * @return
     */
    public List<BmsFreightPriceModel> pcdPreciseMatchPrice(BmsShipBillHeaderModel model, List<BmsFreightPriceModel> matchedCntPriceModelList) {
        List<BmsFreightPriceModel> matchedPriceTbl = Lists.newArrayList();

        // 匹配始发地
        if (ObjectUtil.isNotEmpty(model.getShipperProvince()) &&
                ObjectUtil.isNotEmpty(model.getShipperCity()) &&
                ObjectUtil.isNotEmpty(model.getShipperDistrict())) {
            // 省市区匹配
            matchedPriceTbl = matchedCntPriceModelList.stream().filter(price -> model.getShipperProvince().equals(price.getShipperProvince())
                    && model.getShipperCity().equals(price.getShipperCity())
                    && model.getShipperDistrict().equals(price.getShipperDistrict())).collect(Collectors.toList());
        } else if (ObjectUtil.isNotEmpty(model.getShipperProvince()) &&
                ObjectUtil.isNotEmpty(model.getShipperCity())) {
            // 省市匹配
            matchedPriceTbl = matchedCntPriceModelList.stream().filter(price -> model.getShipperProvince().equals(price.getShipperProvince())
                    && model.getShipperCity().equals(price.getShipperCity())
                    && ObjectUtil.isEmpty(price.getShipperDistrict())).collect(Collectors.toList());
        } else if (ObjectUtil.isNotEmpty(model.getShipperProvince())) {
            matchedPriceTbl = matchedCntPriceModelList.stream().filter(price -> model.getShipperProvince().equals(price.getShipperProvince())
                    && ObjectUtil.isEmpty(price.getShipperCity())
                    && ObjectUtil.isEmpty(price.getShipperDistrict())).collect(Collectors.toList());
        } else {
            // 匹配省是空的价格表
            matchedPriceTbl = matchedCntPriceModelList.stream().filter(price -> ObjectUtil.isEmpty(price.getShipperProvince())).collect(Collectors.toList());
        }
        if (ObjectUtil.isEmpty(matchedPriceTbl)) {
            return null;
        }
        // 匹配目的地
        if (ObjectUtil.isNotEmpty(model.getConsigneeProvince()) &&
                ObjectUtil.isNotEmpty(model.getConsigneeCity()) &&
                ObjectUtil.isNotEmpty(model.getConsigneeDistrict())) {
            // 省市区匹配
            matchedPriceTbl = matchedPriceTbl.stream().filter(price -> model.getConsigneeProvince().equals(price.getConsigneeProvince())
                    && model.getConsigneeCity().equals(price.getConsigneeCity())
                    && model.getConsigneeDistrict().equals(price.getConsigneeDistrict())).collect(Collectors.toList());
        } else if (ObjectUtil.isNotEmpty(model.getConsigneeProvince()) &&
                ObjectUtil.isNotEmpty(model.getConsigneeCity())) {
            // 省市匹配
            matchedPriceTbl = matchedPriceTbl.stream().filter(price -> model.getConsigneeProvince().equals(price.getConsigneeProvince())
                    && model.getConsigneeCity().equals(price.getConsigneeCity())
                    && ObjectUtil.isEmpty(price.getConsigneeDistrict())).collect(Collectors.toList());
        } else if (ObjectUtil.isNotEmpty(model.getConsigneeProvince())) {
            matchedPriceTbl = matchedPriceTbl.stream().filter(price -> model.getConsigneeProvince().equals(price.getConsigneeProvince())
                    && ObjectUtil.isEmpty(price.getConsigneeCity())
                    && ObjectUtil.isEmpty(price.getConsigneeDistrict())).collect(Collectors.toList());
        } else {
            // 匹配省是空的价格表
            matchedPriceTbl = matchedPriceTbl.stream().filter(price -> ObjectUtil.isEmpty(price.getConsigneeProvince())).collect(Collectors.toList());
        }
        return matchedPriceTbl;
    }

    /**
     * 省市区向上匹配
     *
     * @param model
     * @return
     */
    public List<BmsFreightPriceModel> pcdUpMatchPrice(BmsShipBillHeaderModel model, List<BmsFreightPriceModel> matchedCntPriceModelList) {
        List<BmsFreightPriceModel> shipperMatchedPriceTbl = Lists.newArrayList();
        // 匹配始发地
        if (ObjectUtil.isNotEmpty(model.getShipperProvince()) &&
                ObjectUtil.isNotEmpty(model.getShipperCity()) &&
                ObjectUtil.isNotEmpty(model.getShipperDistrict())) {
            // 省市区匹配
            List<BmsFreightPriceModel> tmpMatchedPriceTbl = matchedCntPriceModelList.stream().filter(price -> model.getShipperProvince().equals(price.getShipperProvince())
                    && model.getShipperCity().equals(price.getShipperCity())
                    && model.getShipperDistrict().equals(price.getShipperDistrict())).collect(Collectors.toList());
            // 省市匹配
            if (ObjectUtil.isNotEmpty(tmpMatchedPriceTbl)) {
                shipperMatchedPriceTbl.addAll(tmpMatchedPriceTbl);
                tmpMatchedPriceTbl = matchedCntPriceModelList.stream().filter(price -> model.getShipperProvince().equals(price.getShipperProvince())
                        && model.getShipperCity().equals(price.getShipperCity())
                        && ObjectUtil.isEmpty(price.getShipperDistrict())).collect(Collectors.toList());
                if (ObjectUtil.isNotEmpty(tmpMatchedPriceTbl)) {
                    shipperMatchedPriceTbl.addAll(tmpMatchedPriceTbl);
                }
            } else {
                tmpMatchedPriceTbl = matchedCntPriceModelList.stream().filter(price -> model.getShipperProvince().equals(price.getShipperProvince())
                        && model.getShipperCity().equals(price.getShipperCity())
                        && ObjectUtil.isEmpty(price.getShipperDistrict())).collect(Collectors.toList());
                if (ObjectUtil.isNotEmpty(tmpMatchedPriceTbl)) {
                    shipperMatchedPriceTbl.addAll(tmpMatchedPriceTbl);
                }
            }
            // 省匹配
            if (ObjectUtil.isNotEmpty(shipperMatchedPriceTbl)) {
                tmpMatchedPriceTbl = matchedCntPriceModelList.stream().filter(price -> model.getShipperProvince().equals(price.getShipperProvince())
                        && ObjectUtil.isEmpty(price.getShipperCity())
                        && ObjectUtil.isEmpty(price.getShipperDistrict())).collect(Collectors.toList());
                if (ObjectUtil.isNotEmpty(tmpMatchedPriceTbl)) {
                    shipperMatchedPriceTbl.addAll(tmpMatchedPriceTbl);
                }
            } else {
                tmpMatchedPriceTbl = matchedCntPriceModelList.stream().filter(price -> model.getShipperProvince().equals(price.getShipperProvince())
                        && ObjectUtil.isEmpty(price.getShipperCity())
                        && ObjectUtil.isEmpty(price.getShipperDistrict())).collect(Collectors.toList());
                if (ObjectUtil.isNotEmpty(tmpMatchedPriceTbl)) {
                    shipperMatchedPriceTbl.addAll(tmpMatchedPriceTbl);
                }
            }
        } else if (ObjectUtil.isNotEmpty(model.getShipperProvince()) &&
                ObjectUtil.isNotEmpty(model.getShipperCity())) {
            // 省市匹配
            List<BmsFreightPriceModel> tmpMatchedPriceTbl = matchedCntPriceModelList.stream().filter(price -> model.getShipperProvince().equals(price.getShipperProvince())
                    && model.getShipperCity().equals(price.getShipperCity())
                    && ObjectUtil.isEmpty(price.getShipperDistrict())).collect(Collectors.toList());
            // 省匹配
            if (ObjectUtil.isNotEmpty(tmpMatchedPriceTbl)) {
                tmpMatchedPriceTbl = matchedCntPriceModelList.stream().filter(price -> model.getShipperProvince().equals(price.getShipperProvince())
                        && ObjectUtil.isEmpty(price.getShipperCity())
                        && ObjectUtil.isEmpty(price.getShipperDistrict())).collect(Collectors.toList());
                if (ObjectUtil.isNotEmpty(tmpMatchedPriceTbl)) {
                    shipperMatchedPriceTbl.addAll(tmpMatchedPriceTbl);
                }
            } else {
                tmpMatchedPriceTbl = matchedCntPriceModelList.stream().filter(price -> model.getShipperProvince().equals(price.getShipperProvince())
                        && ObjectUtil.isEmpty(price.getShipperCity())
                        && ObjectUtil.isEmpty(price.getShipperDistrict())).collect(Collectors.toList());
                if (ObjectUtil.isNotEmpty(tmpMatchedPriceTbl)) {
                    shipperMatchedPriceTbl.addAll(tmpMatchedPriceTbl);
                }
            }
        } else if (ObjectUtil.isNotEmpty(model.getShipperProvince())) {
            shipperMatchedPriceTbl = matchedCntPriceModelList.stream().filter(price -> model.getShipperProvince().equals(price.getShipperProvince())
                    && ObjectUtil.isEmpty(price.getShipperCity())
                    && ObjectUtil.isEmpty(price.getShipperDistrict())).collect(Collectors.toList());
        } else {
            // 匹配省是空的价格表
            shipperMatchedPriceTbl = matchedCntPriceModelList.stream().filter(price -> ObjectUtil.isEmpty(price.getShipperProvince())).collect(Collectors.toList());
        }
        if (ObjectUtil.isEmpty(shipperMatchedPriceTbl)) {
            return null;
        }
        // 匹配目的地
        List<BmsFreightPriceModel> consigneeMatchedPriceTbl = Lists.newArrayList();
        if (ObjectUtil.isNotEmpty(model.getConsigneeProvince()) &&
                ObjectUtil.isNotEmpty(model.getConsigneeCity()) &&
                ObjectUtil.isNotEmpty(model.getConsigneeDistrict())) {
            // 省市区匹配
            List<BmsFreightPriceModel> tmpMatchedPriceTbl = shipperMatchedPriceTbl.stream().filter(price -> model.getConsigneeProvince().equals(price.getConsigneeProvince())
                    && model.getConsigneeCity().equals(price.getConsigneeCity())
                    && model.getConsigneeDistrict().equals(price.getConsigneeDistrict())).collect(Collectors.toList());
            // 省市匹配
            if (ObjectUtil.isNotEmpty(tmpMatchedPriceTbl)) {
                consigneeMatchedPriceTbl.addAll(tmpMatchedPriceTbl);
                List<String> expenseName = consigneeMatchedPriceTbl.stream().map(BmsFreightPriceModel::getExpenseName).distinct().collect(Collectors.toList());
                tmpMatchedPriceTbl = shipperMatchedPriceTbl.stream().filter(price -> model.getConsigneeProvince().equals(price.getConsigneeProvince())
                        && model.getConsigneeCity().equals(price.getConsigneeCity())
                        && ObjectUtil.isEmpty(price.getConsigneeDistrict())
                        && !expenseName.contains(price.getExpenseName())).collect(Collectors.toList());
                if (ObjectUtil.isNotEmpty(tmpMatchedPriceTbl)) {
                    consigneeMatchedPriceTbl.addAll(tmpMatchedPriceTbl);
                }
            } else {
                tmpMatchedPriceTbl = shipperMatchedPriceTbl.stream().filter(price -> model.getConsigneeProvince().equals(price.getConsigneeProvince())
                        && model.getConsigneeCity().equals(price.getConsigneeCity())
                        && ObjectUtil.isEmpty(price.getConsigneeDistrict())).collect(Collectors.toList());
                if (ObjectUtil.isNotEmpty(tmpMatchedPriceTbl)) {
                    consigneeMatchedPriceTbl.addAll(tmpMatchedPriceTbl);
                }
            }
            // 省匹配
            if (ObjectUtil.isNotEmpty(consigneeMatchedPriceTbl)) {
                List<String> expenseName = consigneeMatchedPriceTbl.stream().map(BmsFreightPriceModel::getExpenseName).distinct().collect(Collectors.toList());
                tmpMatchedPriceTbl = shipperMatchedPriceTbl.stream().filter(price -> model.getConsigneeProvince().equals(price.getConsigneeProvince())
                        && ObjectUtil.isEmpty(price.getConsigneeCity())
                        && ObjectUtil.isEmpty(price.getConsigneeDistrict())
                        && !expenseName.contains(price.getExpenseName())).collect(Collectors.toList());
                if (ObjectUtil.isNotEmpty(tmpMatchedPriceTbl)) {
                    consigneeMatchedPriceTbl.addAll(tmpMatchedPriceTbl);
                }
            } else {
                tmpMatchedPriceTbl = shipperMatchedPriceTbl.stream().filter(price -> model.getConsigneeProvince().equals(price.getConsigneeProvince())
                        && ObjectUtil.isEmpty(price.getConsigneeCity())
                        && ObjectUtil.isEmpty(price.getConsigneeDistrict())).collect(Collectors.toList());
                if (ObjectUtil.isNotEmpty(tmpMatchedPriceTbl)) {
                    consigneeMatchedPriceTbl.addAll(tmpMatchedPriceTbl);
                }
            }
        } else if (ObjectUtil.isNotEmpty(model.getConsigneeProvince()) &&
                ObjectUtil.isNotEmpty(model.getConsigneeCity())) {
            // 省市匹配
            List<BmsFreightPriceModel> tmpMatchedPriceTbl = shipperMatchedPriceTbl.stream().filter(price -> model.getConsigneeProvince().equals(price.getConsigneeProvince())
                    && model.getConsigneeCity().equals(price.getConsigneeCity())
                    && ObjectUtil.isEmpty(price.getConsigneeDistrict())).collect(Collectors.toList());
            // 省匹配
            if (ObjectUtil.isNotEmpty(tmpMatchedPriceTbl)) {
                List<String> expenseName = tmpMatchedPriceTbl.stream().map(BmsFreightPriceModel::getExpenseName).distinct().collect(Collectors.toList());
                tmpMatchedPriceTbl = shipperMatchedPriceTbl.stream().filter(price -> model.getConsigneeProvince().equals(price.getConsigneeProvince())
                        && ObjectUtil.isEmpty(price.getConsigneeCity())
                        && ObjectUtil.isEmpty(price.getConsigneeDistrict())
                        && !expenseName.contains(price.getExpenseName())).collect(Collectors.toList());
                if (ObjectUtil.isNotEmpty(tmpMatchedPriceTbl)) {
                    consigneeMatchedPriceTbl.addAll(tmpMatchedPriceTbl);
                }
            } else {
                tmpMatchedPriceTbl = shipperMatchedPriceTbl.stream().filter(price -> model.getConsigneeProvince().equals(price.getConsigneeProvince())
                        && ObjectUtil.isEmpty(price.getConsigneeCity())
                        && ObjectUtil.isEmpty(price.getConsigneeDistrict())).collect(Collectors.toList());
                if (ObjectUtil.isNotEmpty(tmpMatchedPriceTbl)) {
                    consigneeMatchedPriceTbl.addAll(tmpMatchedPriceTbl);
                }
            }
        } else if (ObjectUtil.isNotEmpty(model.getConsigneeProvince())) {
            consigneeMatchedPriceTbl = shipperMatchedPriceTbl.stream().filter(price -> model.getConsigneeProvince().equals(price.getConsigneeProvince())
                    && ObjectUtil.isEmpty(price.getConsigneeCity())
                    && ObjectUtil.isEmpty(price.getConsigneeDistrict())).collect(Collectors.toList());
        } else {
            // 匹配省是空的价格表
            consigneeMatchedPriceTbl = shipperMatchedPriceTbl.stream().filter(price -> ObjectUtil.isEmpty(price.getConsigneeProvince())).collect(Collectors.toList());
        }
        if (ObjectUtil.isEmpty(consigneeMatchedPriceTbl)) {
            return null;
        }
        return consigneeMatchedPriceTbl;
    }

    public List<BmsFreightPriceModel> pcdUpIgnoreMatchPrice(BmsShipBillHeaderModel model, List<BmsFreightPriceModel> matchedCntPriceModelList) {
        List<BmsFreightPriceModel> pcdUpMatchPrice = pcdUpMatchPrice(model, matchedCntPriceModelList);
        if (ObjectUtil.isNotEmpty(pcdUpMatchPrice)) {
            return pcdUpMatchPrice;
        } else {
            return matchedCntPriceModelList;
        }
    }

    public BigDecimal getShipbillTaxAmt(Long billId, String billNo, Integer billingSource) {
        BigDecimal taxAmt = BigDecimal.ZERO;

        Criteria bmsFeeCriteria = Criteria.forClass(BmsBillPayFeeDetailModel.class);
        Restriction r1 = Restrictions.eq(BmsBillPayFeeDetailModel::getBillId, billId);
        Restriction r2 = Restrictions.eq(BmsBillPayFeeDetailModel::getBillNo, billNo);
        Restriction r3 = ObjectUtil.isEmpty(billingSource) ? null : Restrictions.eq(BmsBillPayFeeDetailModel::getBillingSource, billingSource);
        bmsFeeCriteria.setRestriction(Restrictions.and(r1, r2, r3));
        List<BmsBillPayFeeDetailModel> feeDetailModels = bmsBillPayFeeDetailMapper.findByCriteria(bmsFeeCriteria);
        if (ObjectUtil.isNotEmpty(feeDetailModels)) {
            taxAmt = feeDetailModels.stream().filter(dto -> ObjectUtil.isNotEmpty(dto.getTaxAmt())).map(BmsBillPayFeeDetailModel::getTaxAmt).reduce(BigDecimal.ZERO, BigDecimal::add);
        }
        return taxAmt;
    }

    private CheckConditionDTO checkLoadingPriceCondition(List<BmsFreightPriceConditionModel> conditionList, BmsLoadingBillHeaderModel costStrategy) throws Exception {
        log.info("价格表满足条件:" + JSON.toJSONString(conditionList));
        log.info("价格表满足条件匹配,派车单:" + JSON.toJSONString(costStrategy));
        String deliveryAreas = costStrategy.getDeliveryAreas();
        BigDecimal totalWeight = costStrategy.getTotalPayWeight();
        String deliveryLines = costStrategy.getDeliveryLines();
        String stationLines = costStrategy.getStationLines();
        String vehicleTypeCode = costStrategy.getVehicleTypeCode();
        String cargoOwnerCode = costStrategy.getCargoOwnerCode();
        BigDecimal totalPayMileage = costStrategy.getTotalPayMileage();

        CheckConditionDTO dto = new CheckConditionDTO();
        dto.setFlag(true);
        for (BmsFreightPriceConditionModel bmsFreightPriceConditionModel : conditionList) {
            log.info("价格表满足条件的明细条件:" + JSON.toJSONString(bmsFreightPriceConditionModel));
            // 条件 8：货主，12:车型, 21：支出重量，14：配送线路，15：站点线路，16：配送区域 19支出公里数
            Integer conditionType = bmsFreightPriceConditionModel.getConditionType();
            String conditionValue = bmsFreightPriceConditionModel.getConditionValue();
            String unitCode = bmsFreightPriceConditionModel.getUnitCode();
            // 货主
            if (conditionType == 8 && ObjectUtil.isEmpty(cargoOwnerCode)) {
                dto.setMessage("派车单的货主为空");
                dto.setFlag(false);
                return dto;
            } else if (conditionType == 8 && !unitCode.contains(cargoOwnerCode)) {
                dto.setMessage("没有匹配到货主");
                dto.setFlag(false);
                return dto;
            }

            if (conditionType == 12 && ObjectUtil.isEmpty(vehicleTypeCode)) {
                dto.setMessage("派车单的车型为空");
                dto.setFlag(false);
                return dto;
            } else if (conditionType == 12 && !unitCode.contains(vehicleTypeCode)) {
                dto.setMessage("没有匹配到车型");
                dto.setFlag(false);
                return dto;
            }

            if (conditionType == 14 && ObjectUtil.isEmpty(deliveryLines)) {
                dto.setMessage("派车单的配送线路为空");
                dto.setFlag(false);
                return dto;
            } else if (conditionType == 14 && ObjectUtil.isNotEmpty(deliveryLines)) {
                List<String> deliveryLineList = Arrays.stream(deliveryLines.split("-")).collect(Collectors.toList());
                for (String line : deliveryLineList) {
                    if (!conditionValue.contains(line)) {
                        dto.setMessage("没有匹配到配送线路");
                        dto.setFlag(false);
                        return dto;
                    }
                }
            }

            if (conditionType == 15 && ObjectUtil.isEmpty(stationLines)) {
                dto.setMessage("派车单的站点线路为空");
                dto.setFlag(false);
                return dto;
            } else if (conditionType == 15 && ObjectUtil.isNotEmpty(stationLines)) {
                List<String> stationLinesList = Arrays.stream(stationLines.split("-")).collect(Collectors.toList());
                for (String station : stationLinesList) {
                    if (!conditionValue.contains(station)) {
                        dto.setMessage("没有匹配到站点线路");
                        dto.setFlag(false);
                        return dto;
                    }
                }
            }

            if (conditionType == 16 && ObjectUtil.isEmpty(deliveryAreas)) {
                dto.setMessage("派车单的配送区域为空");
                dto.setFlag(false);
                return dto;
            } else if (conditionType == 16 && !conditionValue.contains(deliveryAreas)) {
                dto.setMessage("没有匹配到配送区域");
                dto.setFlag(false);
                return dto;
            }

            if (conditionType == 19 && ObjectUtil.isEmpty(totalPayMileage)) {
                dto.setMessage("派车单的公里数为空");
                dto.setFlag(false);
                return dto;
            } else if (conditionType == 19 && !(NumberUtil.isLessOrEqual(totalPayMileage, BigDecimal.valueOf(Integer.valueOf(unitCode)))
                    && NumberUtil.isGreaterOrEqual(totalPayMileage, BigDecimal.valueOf(Integer.valueOf(conditionValue))))) {
                dto.setMessage("没有匹配到支出公里数");
                dto.setFlag(false);
                return dto;
            }

            if (conditionType == 21 && ObjectUtil.isEmpty(totalWeight)) {
                dto.setMessage("派车单的重量为空");
                dto.setFlag(false);
                return dto;
            } else if (conditionType == 21 && !(NumberUtil.isLessOrEqual(totalWeight, BigDecimal.valueOf(Integer.valueOf(unitCode)))
                    && NumberUtil.isGreaterOrEqual(totalWeight, BigDecimal.valueOf(Integer.valueOf(conditionValue))))) {
                dto.setMessage("没有匹配到支出重量");
                dto.setFlag(false);
                return dto;
            }
        }
        return dto;
    }
}