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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Lists;
import com.prolog.common.util.DateUtils;
import com.prolog.cs.platform.power.model.Organization;
import com.prolog.framework.common.message.RestMessage;
import com.prolog.framework.core.exception.BizException;
import com.prolog.framework.core.exception.ParameterException;
import com.prolog.framework.core.pojo.Page;
import com.prolog.framework.core.restriction.Criteria;
import com.prolog.framework.core.restriction.Order;
import com.prolog.framework.core.restriction.Restriction;
import com.prolog.framework.core.restriction.Restrictions;
import com.prolog.framework.dao.util.PageUtils;
import com.prolog.product.core.easyexcel.util.ExcelUtils;
import com.prolog.product.core.framework.entity.UserEntity;
import com.prolog.product.core.framework.util.PlgFxUsrUtils;
import com.prolog.product.core.tools.util.ToolKits;
import com.prolog.rdc.tms.constant.BmsConstant;
import com.prolog.rdc.tms.constant.enums.BusinessTypeEnum;
import com.prolog.rdc.tms.constant.enums.LogTypeEnum;
import com.prolog.rdc.tms.dao.mapper.BmsBillIncomeFeeHeaderMapper;
import com.prolog.rdc.tms.dao.mapper.BmsBillPayFeeDetailMapper;
import com.prolog.rdc.tms.dao.mapper.BmsBillPayFeeHeaderMapper;
import com.prolog.rdc.tms.dao.mapper.BmsShipBillAdjustMapper;
import com.prolog.rdc.tms.dao.mapper.BmsShipBillPackageMapper;
import com.prolog.rdc.tms.dao.mapper.LoadingBillHeadMapper;
import com.prolog.rdc.tms.dao.mapper.ShipBillDetailMapper;
import com.prolog.rdc.tms.dao.mapper.ShipBillHeadMapper;
import com.prolog.rdc.tms.model.dto.basicConfigure.StandardTemplateDetailsListDTO;
import com.prolog.rdc.tms.model.dto.basicData.BranchByNameDTO;
import com.prolog.rdc.tms.model.dto.basicData.CargoOwnerByEncodingNameDTO;
import com.prolog.rdc.tms.model.dto.basicData.ItemByEncodingNameDTO;
import com.prolog.rdc.tms.model.dto.fleetManagement.DriverCheckDTO;
import com.prolog.rdc.tms.model.dto.shipbill.BmsLogOperationDTO;
import com.prolog.rdc.tms.model.dto.shipbill.BmsShipBillAdjustDTO;
import com.prolog.rdc.tms.model.dto.shipbill.BmsShipBillDTO;
import com.prolog.rdc.tms.model.dto.shipbill.BmsShipBillDetailDTO;
import com.prolog.rdc.tms.model.dto.shipbill.BmsShipBillPackageDTO;
import com.prolog.rdc.tms.model.entity.BmsBillIncomeFeeDetailModel;
import com.prolog.rdc.tms.model.entity.BmsBillIncomeFeeHeaderModel;
import com.prolog.rdc.tms.model.entity.BmsBillPayFeeDetailModel;
import com.prolog.rdc.tms.model.entity.BmsBillPayFeeHeaderModel;
import com.prolog.rdc.tms.model.entity.BmsLoadingBillHeaderModel;
import com.prolog.rdc.tms.model.entity.BmsShipBillAdjustModel;
import com.prolog.rdc.tms.model.entity.BmsShipBillDetailModel;
import com.prolog.rdc.tms.model.entity.BmsShipBillHeaderModel;
import com.prolog.rdc.tms.model.entity.BmsShipBillPackageModel;
import com.prolog.rdc.tms.model.entity.SysRefdatadModel;
import com.prolog.rdc.tms.model.vo.BmsShipBillImportVO;
import com.prolog.rdc.tms.model.vo.basicConfigure.ImportLogAddVO;
import com.prolog.rdc.tms.model.vo.basicData.BranchByNameVO;
import com.prolog.rdc.tms.model.vo.basicData.CargoOwnerByEncodingNameVO;
import com.prolog.rdc.tms.model.vo.basicData.ItemByEncodingNameVO;
import com.prolog.rdc.tms.model.vo.fleetManagement.DriverCheckVO;
import com.prolog.rdc.tms.model.vo.shipbill.BmsShipBillItemVO;
import com.prolog.rdc.tms.model.vo.shipbill.BmsShipBillPackageVO;
import com.prolog.rdc.tms.model.vo.shipbill.BmsShipBillQueryVO;
import com.prolog.rdc.tms.model.vo.shipbill.BmsShipBillVO;
import com.prolog.rdc.tms.proxy.MainDataProxy;
import com.prolog.rdc.tms.rmi.feign.MaindataFeign;
import com.prolog.rdc.tms.rmi.feign.UserFeign;
import com.prolog.rdc.tms.service.BillIncomeCostStrategyService;
import com.prolog.rdc.tms.service.BillPayCostStrategyService;
import com.prolog.rdc.tms.service.BmsBillIncomeFeeService;
import com.prolog.rdc.tms.service.BmsBillLogService;
import com.prolog.rdc.tms.service.BmsBillPayFeeService;
import com.prolog.rdc.tms.service.BmsLoadingBillService;
import com.prolog.rdc.tms.service.BmsShipBillService;
import com.prolog.rdc.tms.util.ConvertorUtil;
import com.prolog.rdc.tms.util.FileUtils;
import com.prolog.rdc.tms.util.ImportUtils;
import com.prolog.rdc.tms.util.PublicMethods;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.stream.Collectors;

/**
 * @author hongbo.pan
 * @date 2023/4/13
 */
@Slf4j
@Service
public class BmsShipBillServiceImpl implements BmsShipBillService {

    @Autowired
    private ShipBillHeadMapper shipBillHeadMapper;

    @Autowired
    private ShipBillDetailMapper shipBillDetailMapper;

    @Autowired
    private BmsShipBillPackageMapper shipBillPackageMapper;

    @Autowired
    private BmsBillLogService logService;

    @Autowired
    private BmsShipBillAdjustMapper shipBillAdjustMapper;

    @Autowired
    private MainDataProxy mainDataProxy;

    @Autowired
    private ConvertorUtil convertorUtil;

    @Autowired
    private MaindataFeign maindataFeign;

    @Autowired
    private UserFeign userTmsResource;

    @Autowired
    private BmsBillIncomeFeeHeaderMapper incomeFeeHeaderMapper;

    @Autowired
    private BillIncomeCostStrategyService incomeCostStrategyService;

    @Autowired
    private BmsLoadingBillService loadingBillService;

    @Autowired
    private LoadingBillHeadMapper loadingBillHeadMapper;

    @Autowired
    private BmsBillPayFeeHeaderMapper payFeeHeaderMapper;

    @Autowired
    private BillPayCostStrategyService payCostStrategyService;

    @Autowired
    private BmsBillPayFeeService bmsBillPayFeeService;

    @Autowired
    private BmsBillIncomeFeeService bmsBillIncomeFeeService;

    @Autowired
    private BmsBillPayFeeDetailMapper payFeeDetailMapper;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveOrUpdate(BmsShipBillVO vo) {
        if (ObjectUtil.isNotNull(vo.getId())) {
            if (BusinessTypeEnum.INCOME.getCode().equals(vo.getBusinessTypeHidden())) {
                checkIncomeCheckStatus(vo.getShipbillNo());
            } else {
                checkPayCheckStatus(vo.getShipbillNo());
            }
            updateBmsShipBill(vo);
        } else {
            addBmsShipBill(vo);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveAndCal(BmsShipBillVO vo, String type) {
        if ("3".equals(type)) {
            copy(vo);
        } else {
            if (ObjectUtil.isNotNull(vo.getId())) {
                if (BusinessTypeEnum.INCOME.getCode().equals(vo.getBusinessTypeHidden())) {
                    checkIncomeCalculate(vo.getShipbillNo());
                } else {
                    checkPayCalculate(vo.getShipbillNo());
                }
                updateBmsShipBill(vo);
            } else {
                addBmsShipBill(vo);
            }
        }
        if (BusinessTypeEnum.INCOME.getCode().equals(vo.getBusinessTypeHidden())) {
            updateIncomeShipBillFee(vo.getShipbillNo());
        } else {
            updatePayShipBillFee(vo.getShipbillNo());
        }
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public void copy(BmsShipBillVO vo) {
        vo.setId(null);
        if (CollectionUtil.isNotEmpty(vo.getDetailList())) {
            vo.getDetailList().stream().peek(itemVO -> itemVO.setId(null)).collect(Collectors.toList());
        }
        if (CollectionUtil.isNotEmpty(vo.getPackageList())) {
            vo.getPackageList().stream().peek(packageVO -> packageVO.setId(null)).collect(Collectors.toList());
        }
        addBmsShipBill(vo);
    }

    @Override
    public Page<BmsShipBillDTO> findByCondition(BmsShipBillQueryVO vo) {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        Criteria criteria = Criteria.forClass(BmsShipBillHeaderModel.class);
        Restriction r1 = ToolKits.isEmpty(vo.getCargoOwnerName()) ? null : Restrictions.like(BmsShipBillHeaderModel::getCargoOwnerName, "%" + vo.getCargoOwnerName() + "%");
        Restriction r2 = ToolKits.isEmpty(vo.getOrderNo()) ? null : Restrictions.like(BmsShipBillHeaderModel::getOrderNo, "%" + vo.getOrderNo() + "%");
        Restriction r3 = ToolKits.isEmpty(vo.getShipbillNo()) ? null : Restrictions.like(BmsShipBillHeaderModel::getShipbillNo, "%" + vo.getShipbillNo() + "%");
        Restriction r4 = ToolKits.isEmpty(vo.getOrderBusinessType()) ? null : Restrictions.eq(BmsShipBillHeaderModel::getOrderBusinessType, vo.getOrderBusinessType());
        Restriction r5 = ToolKits.isEmpty(vo.getShipStartDate()) ? null : Restrictions.ge(BmsShipBillHeaderModel::getStartDate, vo.getShipStartDate());
        Restriction r6 = ToolKits.isEmpty(vo.getShipEndDate()) ? null : Restrictions.le(BmsShipBillHeaderModel::getStartDate, DateUtils.endOfToday(vo.getShipEndDate()));
        Restriction r7 = ToolKits.isEmpty(vo.getDeliveryStartDate()) ? null : Restrictions.ge(BmsShipBillHeaderModel::getDeliveryDate, vo.getDeliveryStartDate());
        Restriction r8 = ToolKits.isEmpty(vo.getDeliveryEndDate()) ? null : Restrictions.le(BmsShipBillHeaderModel::getDeliveryDate, DateUtils.endOfToday(vo.getDeliveryEndDate()));
        Restriction r9 = ToolKits.isEmpty(vo.getReceiptStartDate()) ? null : Restrictions.ge(BmsShipBillHeaderModel::getReceiptDate, vo.getReceiptStartDate());
        Restriction r10 = ToolKits.isEmpty(vo.getReceiptEndDate()) ? null : Restrictions.le(BmsShipBillHeaderModel::getReceiptDate, DateUtils.endOfToday(vo.getReceiptEndDate()));
        Restriction r11 = ToolKits.isEmpty(vo.getOriginalBackStartDate()) ? null : Restrictions.ge(BmsShipBillHeaderModel::getOriginalBackDate, vo.getOriginalBackStartDate());
        Restriction r12 = ToolKits.isEmpty(vo.getOriginalBackEndDate()) ? null : Restrictions.le(BmsShipBillHeaderModel::getOriginalBackDate, DateUtils.endOfToday(vo.getOriginalBackEndDate()));
        Restriction r13 = ToolKits.isEmpty(vo.getCompleteStartDate()) ? null : Restrictions.ge(BmsShipBillHeaderModel::getCompleteDate, vo.getCompleteStartDate());
        Restriction r14 = ToolKits.isEmpty(vo.getCompleteEndDate()) ? null : Restrictions.le(BmsShipBillHeaderModel::getCompleteDate, DateUtils.endOfToday(vo.getCompleteEndDate()));
        Restriction r15 = ToolKits.isEmpty(vo.getShipperProvinceCityDistrict()) ? null : Restrictions.like(BmsShipBillHeaderModel::getShipperProvinceCityDistrict, "%" + vo.getShipperProvinceCityDistrict() + "%");
        Restriction r16 = ToolKits.isEmpty(vo.getConsigneeProvinceCityDistrict()) ? null : Restrictions.like(BmsShipBillHeaderModel::getConsigneeProvinceCityDistrict, "%" + vo.getConsigneeProvinceCityDistrict() + "%");
        Restriction r17 = Restrictions.eq(BmsShipBillHeaderModel::getEnterpriseId, user.getEnterpriseId());
        Restriction r18 = ToolKits.isEmpty(vo.getOrderStartDate()) ? null : Restrictions.ge(BmsShipBillHeaderModel::getOrderDate, vo.getOrderStartDate());
        Restriction r19 = ToolKits.isEmpty(vo.getOrderEndDate()) ? null : Restrictions.le(BmsShipBillHeaderModel::getOrderDate, DateUtils.endOfToday(vo.getOrderEndDate()));
        Restriction r20 = ToolKits.isEmpty(vo.getCarrierName()) ? null : Restrictions.like(BmsShipBillHeaderModel::getCarrierName, "%" + vo.getCarrierName() + "%");
        Restriction r21 = ToolKits.isEmpty(vo.getDriverName()) ? null : Restrictions.like(BmsShipBillHeaderModel::getDriverName, "%" + vo.getDriverName() + "%");
        Restriction r22 = ToolKits.isEmpty(vo.getVehiclePlateNumber()) ? null : Restrictions.like(BmsShipBillHeaderModel::getVehicleName, "%" + vo.getVehiclePlateNumber() + "%");
        Restriction r23 = ToolKits.isEmpty(user.getDepts()) ? null : Restrictions.in(BmsShipBillHeaderModel::getSettlementDepartmentId, user.getDepts());
        criteria.setRestriction(Restrictions.and(r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, r20, r21, r22, r23));
        criteria.setOrder(Order.newInstance().desc("updatetime"));
        PageUtils.startPage(vo.getPageNum(), vo.getPageSize());
        List<BmsShipBillHeaderModel> modelList = shipBillHeadMapper.findByCriteria(criteria);
        List<BmsShipBillDTO> dtoList = Lists.newArrayList();
        if (CollectionUtil.isNotEmpty(modelList)) {
            List<SysRefdatadModel> dicData = getDic();
            dtoList = modelList.stream().map(model -> {
                BmsShipBillDTO dto = modelToBmsShipBillDTO(model, dicData);
                if (BusinessTypeEnum.INCOME.getCode().equals(vo.getBusinessTypeHidden())) {
                    dto = fillIncomeFee(dto, dicData);
                } else {
                    dto = fillPayFee(dto, dicData);
                }
                dto.setSettlementStatusName(ConvertorUtil.getName(dicData, BmsConstant.SETTLEMENT_STATUS, String.valueOf(dto.getSettlementStatus())));
                dto.setCheckStatusName(ConvertorUtil.getName(dicData, BmsConstant.CHECK_STATUS, String.valueOf(dto.getCheckStatus())));
                return dto;
            }).collect(Collectors.toList());
        }
        Page<BmsShipBillDTO> page = PageUtils.getPage(dtoList);
        if (modelList instanceof com.github.pagehelper.Page) {
            com.github.pagehelper.Page<BmsShipBillHeaderModel> p0 = (com.github.pagehelper.Page<BmsShipBillHeaderModel>) modelList;
            page.setPageCount(p0.getPages());
            page.setPageNum(p0.getPageNum());
            page.setPageSize(p0.getPageSize());
            page.setTotalCount(p0.getTotal());
            page.setStartRow(p0.getStartRow());
            page.setEndRow(p0.getEndRow());
        }
        return page;
    }

    @Override
    public List<BmsShipBillDTO> findByIdList(List<Long> idList) {
        List<SysRefdatadModel> dicData = getDic();
        return idList.stream().map(id -> {
            BmsShipBillHeaderModel model = shipBillHeadMapper.findById(id, BmsShipBillHeaderModel.class);
            return modelToBmsShipBillDTO(model, dicData);
        }).collect(Collectors.toList());
    }

    @Override
    public BmsShipBillDTO findById(Long id) {
        List<SysRefdatadModel> dicData = getDic();
        BmsShipBillHeaderModel model = shipBillHeadMapper.findById(id, BmsShipBillHeaderModel.class);
        return modelToBmsShipBillDTO(model, dicData);
    }

    @Override
    public BmsShipBillDTO detailById(Long id) {
        BmsShipBillHeaderModel headerModel = shipBillHeadMapper.findById(id, BmsShipBillHeaderModel.class);
        List<SysRefdatadModel> dicData = getDic();
        BmsShipBillDTO dto = modelToBmsShipBillDTO(headerModel, dicData);
        dto.setDetailList(getItem(id));
        dto.setPackageList(getPackage(id));
        return dto;
    }

    @Override
    public List<BmsShipBillDetailDTO> getItem(Long id) {
        BmsShipBillHeaderModel headerModel = shipBillHeadMapper.findById(id, BmsShipBillHeaderModel.class);
        List<BmsShipBillDetailDTO> dtoList = Lists.newArrayList();
        List<BmsShipBillDetailModel> modelList = getDetailModel(headerModel.getShipbillNo());
        if (CollectionUtil.isNotEmpty(modelList)) {
            List<SysRefdatadModel> dicData = convertorUtil.getDictionary(new String[] {
                    BmsConstant.CARGO_THERMOSPHERE
            });
            dtoList = modelList.stream().map(model -> {
                BmsShipBillDetailDTO dto = BeanUtil.copyProperties(model, BmsShipBillDetailDTO.class);
                dto.setCargoThermosphereName(ConvertorUtil.getName(dicData, BmsConstant.CARGO_THERMOSPHERE, String.valueOf(model.getCargoThermosphere())));
                return dto;
            }).collect(Collectors.toList());
        }
		return dtoList;
    }

    @Override
    public List<BmsShipBillPackageDTO> getPackage(Long id) {
        BmsShipBillHeaderModel headerModel = shipBillHeadMapper.findById(id, BmsShipBillHeaderModel.class);
        List<BmsShipBillPackageDTO> dtoList = Lists.newArrayList();
        List<BmsShipBillPackageModel> modelList = getPackageModel(headerModel.getShipbillNo());
        if (CollectionUtil.isNotEmpty(modelList)) {
            Criteria criteria = Criteria.forClass(BmsBillPayFeeDetailModel.class);
            Restriction r1 = Restrictions.eq(BmsBillPayFeeDetailModel::getBillId, headerModel.getId());
            Restriction r2 = Restrictions.eq(BmsBillPayFeeDetailModel::getBillNo, headerModel.getShipbillNo());
            Restriction r3 = Restrictions.eq(BmsBillPayFeeDetailModel::getEnterpriseId, headerModel.getEnterpriseId());
            Restriction r4 = Restrictions.isNotNull(BmsBillPayFeeDetailModel::getPackageId);
            Restriction r5 = Restrictions.eq(BmsBillPayFeeDetailModel::getExpenseName, "支出运费");
            criteria.setRestriction(Restrictions.and(r1, r2, r3, r4, r5));
            List<BmsBillPayFeeDetailModel> payFeeDetailList = payFeeDetailMapper.findByCriteria(criteria);
            Map<Long, List<BmsBillPayFeeDetailModel>> packageGroup =
                    payFeeDetailList.stream().collect(Collectors.groupingBy(BmsBillPayFeeDetailModel::getPackageId));
            dtoList = modelList.stream().map(dto -> {
                BmsShipBillPackageDTO packageDTO = BeanUtil.copyProperties(dto, BmsShipBillPackageDTO.class);
                packageDTO.setTransportFee(BigDecimal.ZERO);
                List<BmsBillPayFeeDetailModel> detailList = packageGroup.get(packageDTO.getId());
                if (CollUtil.isNotEmpty(detailList)) {
                    packageDTO.setTransportFee(detailList.stream().map(BmsBillPayFeeDetailModel::getTaxAmt).reduce(BigDecimal.ZERO, NumberUtil::add));
                }
                return packageDTO;
            }).collect(Collectors.toList());
        }
        return dtoList;
    }

    @Override
    public List<BmsShipBillAdjustDTO> getAdjust(Long id) {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        BmsShipBillHeaderModel headerModel = shipBillHeadMapper.findById(id, BmsShipBillHeaderModel.class);
        Criteria criteria = Criteria.forClass(BmsShipBillAdjustModel.class);
        Restriction r1 = Restrictions.eq(BmsShipBillAdjustModel::getShipbillNo, headerModel.getShipbillNo());
        Restriction r2 = Restrictions.eq(BmsShipBillAdjustModel::getEnterpriseId, user.getEnterpriseId());
        criteria.setRestriction(Restrictions.and(r1, r2));
        List<BmsShipBillAdjustDTO> dtoList = Lists.newArrayList();
        List<BmsShipBillAdjustModel> modelList = shipBillAdjustMapper.findByCriteria(criteria);
        if (CollectionUtil.isNotEmpty(modelList)) {
            dtoList = modelList.stream().map(dto -> BeanUtil.copyProperties(dto, BmsShipBillAdjustDTO.class)).collect(Collectors.toList());
        }
        return dtoList;
    }

    @Override
    public List<BmsLogOperationDTO> getLog(Long id) {
        BmsShipBillHeaderModel headerModel = shipBillHeadMapper.findById(id, BmsShipBillHeaderModel.class);
        return logService.getLog(LogTypeEnum.SHIP_BILL, headerModel.getShipbillNo());
    }

    @Override
    public void addShipBillAdjust(String code, String memo) {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        BmsShipBillAdjustModel adjustModel = new BmsShipBillAdjustModel();
        adjustModel.setShipbillNo(code);
        adjustModel.setAdjustMemo(memo);
        adjustModel.setAdjustDate(DateUtil.date());
        adjustModel.setAdjustName(user.getNickname());
        adjustModel.setCreateperson(user.getNickname());
        adjustModel.setCreatetime(DateUtil.date());
        adjustModel.setUpdateperson(user.getNickname());
        adjustModel.setUpdatetime(DateUtil.date());
        adjustModel.setEnterpriseId(user.getEnterpriseId());
        adjustModel.setEnterpriseName(user.getEnterpriseName());
        shipBillAdjustMapper.save(adjustModel);
    }

    @Override
    public void importShipbillData(MultipartFile file) {
        // 导入文件判断
        FileUtils.multipartFileJudge(file);
        // 获取导入批次号
        RestMessage<String> restMessage = maindataFeign.getCodeNumberByCode(BmsConstant.IMPORT_BATCHNO, "L");
        if (!restMessage.isSuccess()) {
            throw new ParameterException("获取导入批次号调用失败 :" + restMessage.getMessage());
        }
        String importBatchNumber = restMessage.getData();
        ToolKits.isParamNull(importBatchNumber, "导入批次号生成失败");
        // 导入日志对象
        ImportLogAddVO logAddVO = new ImportLogAddVO();
        logAddVO.setImportObjNo(BmsConstant.BMS_SHIP_BILL_IMPORT);
        logAddVO.setImportBatchNumber(importBatchNumber);
        // 导入统计
        int count = 0;
        try {
            // 导入执行
            count = this.importProcess(file);
            logAddVO.setStatus(BmsConstant.IMPORT_STATUS_YES);
            logAddVO.setSuccessNum(count);
            logAddVO.setFailNum(0);
            RestMessage<String> restMessage1 = maindataFeign.addImportLogExecute(logAddVO);
            if (!restMessage1.isSuccess()) {
                throw new ParameterException(restMessage1.getMessage());
            }
        } catch (Exception e) {
            e.printStackTrace();
            logAddVO.setStatus(BmsConstant.IMPORT_STATUS_NO);
            logAddVO.setSuccessNum(0);
            logAddVO.setFailNum(count);
            logAddVO.setFailReason(e.getMessage());
            RestMessage<String> restMessage1 = maindataFeign.addImportLogExecute(logAddVO);
            if (!restMessage1.isSuccess()) {
                throw new ParameterException(restMessage1.getMessage());
            }
            throw new ParameterException(e.getMessage());
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void calculate(List<Long> idList, BusinessTypeEnum businessTypeEnum) {
        List<BmsShipBillHeaderModel> modelList = shipBillHeadMapper.findByIds(BmsShipBillHeaderModel.class, idList.toArray(), null);
        modelList.forEach(headerModel -> {
            if (BmsConstant.SYNCHRONOUS_STATUS_FAILED.equals(headerModel.getSynchronousStatus())) {
                throw new BizException("运单"+headerModel.getShipbillNo()+"同步失败，不能核算！");
            }
            if (BusinessTypeEnum.INCOME.getCode().equals(businessTypeEnum.getCode())) {
                calIncome(headerModel);
            } else {
                calPay(headerModel);
            }
        });
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void submit(List<Long> idList, BusinessTypeEnum businessTypeEnum) {
        List<BmsShipBillHeaderModel> modelList = shipBillHeadMapper.findByIds(BmsShipBillHeaderModel.class, idList.toArray(), null);
        modelList.forEach(headerModel -> {
            if (BusinessTypeEnum.INCOME.getCode().equals(businessTypeEnum.getCode())) {
                submitIncome(headerModel);
            } else {
                submitPay(headerModel);
            }
        });
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void calculateAndSubmit(List<Long> idList, BusinessTypeEnum businessTypeEnum) {
        calculate(idList, businessTypeEnum);
        submit(idList, businessTypeEnum);
    }

    public int importProcess(MultipartFile file) {
        // 人员权限
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        ToolKits.isParamNull(user, "当前人员没有操作权限");
        // 当前时间
        Date date = new Date();
        int impCnt = 0;
        Properties properties = new Properties();
        // 待转换的对象
        Class<BmsShipBillImportVO> importVOClass = BmsShipBillImportVO.class;
        // 标准模板查询
        RestMessage<List<StandardTemplateDetailsListDTO>> restMessage = maindataFeign.listStandardTemplateDetailsExecute(BmsConstant.BMS_SHIP_BILL_IMPORT);
        if (!restMessage.isSuccess()) {
            throw new ParameterException("标准模板详情查询失败:" + restMessage.getMessage());
        }
        List<StandardTemplateDetailsListDTO> standardTemplateDetailsListDTOs = restMessage.getData();
        ToolKits.isParamNull(standardTemplateDetailsListDTOs, "运单标准模板未配置");
        for (StandardTemplateDetailsListDTO standardTemplateDetailsListDTO : standardTemplateDetailsListDTOs) {
            // 属性字段和注解属性字段值 键值对
            properties.setProperty(standardTemplateDetailsListDTO.getStdColNo(), standardTemplateDetailsListDTO.getCustColName());
        }
        // @ExcelProperty注解属性修改
        ImportUtils.setHeaderValue(properties, importVOClass);
        // EXCEL转对象
        List<BmsShipBillImportVO> bmsShipBillImportVOS = null;
        try {
            bmsShipBillImportVOS = ExcelUtils.read(file, importVOClass);
        } catch (Exception e) {
            e.printStackTrace();
            throw new ParameterException("EXCEL转对象失败:" + e.getMessage());
        }
        ToolKits.isParamNull(bmsShipBillImportVOS, "EXCEL文件内容为空,请重新导入");
        for (BmsShipBillImportVO bmsShipBillImportVO : bmsShipBillImportVOS) {
            ToolKits.isParamNull(bmsShipBillImportVO.getCargoOwnerCode(), "货主编码不为空");
            ToolKits.isParamNull(bmsShipBillImportVO.getCargoOwnerName(), "货主名称不为空");
            ToolKits.isParamNull(bmsShipBillImportVO.getOrderType(), "订单类型不为空");
            ToolKits.isParamNull(bmsShipBillImportVO.getOrderBusinessType(), "订单业务类型不为空");
            ToolKits.isParamNull(bmsShipBillImportVO.getDeliveryMethodType(), "配送方式不为空");
            ToolKits.isParamNull(bmsShipBillImportVO.getTransportType(), "运输模式不为空");
            ToolKits.isParamNull(bmsShipBillImportVO.getTemperatureRequirement(), "温度要求不为空");
            ToolKits.isParamNull(bmsShipBillImportVO.getShipperType(), "发货方类型不为空");
            ToolKits.isParamNull(bmsShipBillImportVO.getShipperUnitCode(), "发货方单位编码不为空");
            ToolKits.isParamNull(bmsShipBillImportVO.getShipperUnitName(), "发货方单位名称不为空");
            ToolKits.isParamNull(bmsShipBillImportVO.getShipperProvinceName(), "发货方省名称不为空");
            ToolKits.isParamNull(bmsShipBillImportVO.getShipperCityName(), "发货方市名称不为空");
            ToolKits.isParamNull(bmsShipBillImportVO.getShipperDistrictName(), "发货方区/县名称不为空");
            ToolKits.isParamNull(bmsShipBillImportVO.getShipperAddress(), "发货方详细地址不为空");
            ToolKits.isParamNull(bmsShipBillImportVO.getConsigneeType(), "收货方类型不为空");
            ToolKits.isParamNull(bmsShipBillImportVO.getConsigneeUnitCode(), "收货方单位编码不为空");
            ToolKits.isParamNull(bmsShipBillImportVO.getConsigneeUnitName(), "收货方单位名称不为空");
            ToolKits.isParamNull(bmsShipBillImportVO.getConsigneeProvinceName(), "收货方省名称不为空");
            ToolKits.isParamNull(bmsShipBillImportVO.getConsigneeCityName(), "收货方市名称不为空");
            ToolKits.isParamNull(bmsShipBillImportVO.getConsigneeDistrictName(), "收货方区/县名称不为空");
            ToolKits.isParamNull(bmsShipBillImportVO.getConsigneeAddress(), "收货方详细地址不为空");
            ToolKits.isParamNull(bmsShipBillImportVO.getTotalPcs(), "总件数不为空");
            ToolKits.isParamNull(bmsShipBillImportVO.getItemCode(), "商品编码不为空");
            ToolKits.isParamNull(bmsShipBillImportVO.getItemName(), "商品名称不为空");
            ToolKits.isParamNull(bmsShipBillImportVO.getPcs(), "商品件数不为空");
            ToolKits.isParamNull(bmsShipBillImportVO.getDepartmentName(), "所属部门名称不为空");

            List<Organization> data1;
            // 所属部门名称判定是否存在
            RestMessage<List<Organization>> departMents = userTmsResource.search(null, bmsShipBillImportVO.getDepartmentName(), null, String.valueOf(user.getEnterpriseId()));
            if (!departMents.isSuccess()) {
                throw new RuntimeException("部门【" + bmsShipBillImportVO.getDepartmentName() + "】不存在!");
            } else {
                data1 = departMents.getData();

                if (!user.getDepts().contains(data1.get(0).getId())) {
                    throw new RuntimeException("部门【" + bmsShipBillImportVO.getDepartmentName() + "】不存在，请先维护部门!");
                }
            }

            // 获取运单汇总ID
            String shipbillId = mainDataProxy.getCodeNumberByCode(BmsConstant.SHIP_BILL_HEAD_ID);
            // 运单对象
            BmsShipBillHeaderModel headerModel = new BmsShipBillHeaderModel();
            BeanUtils.copyProperties(bmsShipBillImportVO, headerModel);
            // 运单明细对象
            BmsShipBillDetailModel tmsShipbillDetailModel = new BmsShipBillDetailModel();
            BeanUtils.copyProperties(bmsShipBillImportVO, tmsShipbillDetailModel);
            // 订单类型数据字典
            PublicMethods.referenceDataProcessing(headerModel, maindataFeign, BmsConstant.ORDER_TYPE, "orderType", bmsShipBillImportVO.getOrderType());
            // 订单业务类型数据字典
            PublicMethods.referenceDataProcessing(headerModel, maindataFeign, BmsConstant.ORDER_BUSINESS_TYPE, "orderBusinessType", bmsShipBillImportVO.getOrderBusinessType());
            // 配送方式数据字典
            PublicMethods.referenceDataProcessing(headerModel, maindataFeign, BmsConstant.DELIVERY_METHOD_TYPE, "deliveryMethodType", bmsShipBillImportVO.getDeliveryMethodType());
            // 运输模式数据字典
            PublicMethods.referenceDataProcessing(headerModel, maindataFeign, BmsConstant.TRANSPORT_TYPE, "transportType", bmsShipBillImportVO.getTransportType());
            // 温度要求数据字典
            PublicMethods.referenceDataProcessing(headerModel, maindataFeign, BmsConstant.TEMPERATURE_REQUIREMENT, "temperatureRequirement", bmsShipBillImportVO.getTemperatureRequirement());
            // 发货方类型数据字典
            PublicMethods.referenceDataProcessing(headerModel, maindataFeign, BmsConstant.SHIPPER_TYPE, "shipperType", bmsShipBillImportVO.getShipperType());
            // 收货方类型数据字典
            PublicMethods.referenceDataProcessing(headerModel, maindataFeign, BmsConstant.CONSIGNEE_TYPE, "consigneeType", bmsShipBillImportVO.getConsigneeType());
            // 商品包装类型数据字典
            PublicMethods.referenceDataProcessing(tmsShipbillDetailModel, maindataFeign, BmsConstant.PACK_TYPE, "packType", bmsShipBillImportVO.getPackType());
            // 商品货物温层数据字典
            PublicMethods.referenceDataProcessing(tmsShipbillDetailModel, maindataFeign, BmsConstant.CARGO_THERMOSPHERE, "cargoThermosphere", bmsShipBillImportVO.getCargoThermosphere());
            // 货主校验
            CargoOwnerByEncodingNameVO cargoOwnerByEncodingNameVO = new CargoOwnerByEncodingNameVO();
            cargoOwnerByEncodingNameVO.setCargoOwnerCode(bmsShipBillImportVO.getCargoOwnerCode());
            cargoOwnerByEncodingNameVO.setCargoOwnerName(bmsShipBillImportVO.getCargoOwnerName());
            RestMessage<CargoOwnerByEncodingNameDTO> cargoOwnerRestMessage = maindataFeign.getCargoOwnerByEncodingNameExecute(cargoOwnerByEncodingNameVO);
            if (cargoOwnerRestMessage.isSuccess()) {
                headerModel.setCargoOwnerId(cargoOwnerRestMessage.getData().getCargoOwnerId());
            } else {
                throw new ParameterException(cargoOwnerRestMessage.getMessage());
            }
            // 判断商品资料
            ItemByEncodingNameDTO itemByEncodingNameDTO = null;
            ItemByEncodingNameVO itemByEncodingNameVO = new ItemByEncodingNameVO();
            itemByEncodingNameVO.setCargoOwnerId(headerModel.getCargoOwnerId());
            itemByEncodingNameVO.setCode(bmsShipBillImportVO.getItemCode());
            itemByEncodingNameVO.setName(bmsShipBillImportVO.getItemName());
            RestMessage<ItemByEncodingNameDTO> itemMessage = maindataFeign.getItemByEncodingNameExecute(itemByEncodingNameVO);
            if (itemMessage.isSuccess()) {
                itemByEncodingNameDTO = itemMessage.getData();
            } else {
                throw new ParameterException(itemMessage.getMessage());
            }
            // 判断仓资料
            BranchByNameDTO branchByNameDTO = null;
            if (ToolKits.isNotEmpty(bmsShipBillImportVO.getBranchName())) {
                BranchByNameVO branchByNameVO = new BranchByNameVO();
                branchByNameVO.setName(bmsShipBillImportVO.getBranchName());
                RestMessage<BranchByNameDTO> branchRestMessage = maindataFeign.getBranchByNameExecute(branchByNameVO);
                if (branchRestMessage.isSuccess()) {
                    branchByNameDTO = branchRestMessage.getData();
                } else {
                    throw new ParameterException(branchRestMessage.getMessage());
                }
            }
            // 汇总赋值
            headerModel.setShipbillNo(shipbillId);
            headerModel.setOrderId(bmsShipBillImportVO.getOrderNo());
            headerModel.setWmsOrderId(bmsShipBillImportVO.getWmsOrderNo());
            headerModel.setStatus(BmsConstant.SHIPBILL_STATUS_END);
            headerModel.setSource(BmsConstant.SOURCE_EXCEL);
            headerModel.setEnterpriseId(user.getEnterpriseId());
            headerModel.setEnterpriseName(user.getEnterpriseName());
            headerModel.setCreateperson(user.getNickname());
            headerModel.setCreatetime(date);
            headerModel.setUpdateperson(user.getNickname());
            headerModel.setUpdatetime(date);
            headerModel.setDepartmentId(data1.get(0).getId());
            headerModel.setDepartmentCode(data1.get(0).getCode());
            headerModel.setDepartmentName(data1.get(0).getName());
            shipBillHeadMapper.save(headerModel);
            // 运单明细赋值
            tmsShipbillDetailModel.setShipbillNo(headerModel.getShipbillNo());
            tmsShipbillDetailModel.setBranchId(branchByNameDTO == null ? null : branchByNameDTO.getId());
            tmsShipbillDetailModel.setBranchCode(branchByNameDTO == null ? null : branchByNameDTO.getCode());
            tmsShipbillDetailModel.setBranchName(branchByNameDTO == null ? null : branchByNameDTO.getName());
            tmsShipbillDetailModel.setCargoOwnerId(headerModel.getCargoOwnerId());
            tmsShipbillDetailModel.setCargoOwnerCode(headerModel.getCargoOwnerCode());
            tmsShipbillDetailModel.setCargoOwnerName(headerModel.getCargoOwnerName());
            tmsShipbillDetailModel.setSeqno(1);
            tmsShipbillDetailModel.setItemId(itemByEncodingNameDTO.getItemId());
            tmsShipbillDetailModel.setItemCategoryId(itemByEncodingNameDTO.getItemCategoryId());
            tmsShipbillDetailModel.setItemCategoryCode(itemByEncodingNameDTO.getItemCategoryCode());
            tmsShipbillDetailModel.setItemCategoryName(itemByEncodingNameDTO.getItemCategoryName());
            tmsShipbillDetailModel.setEnterpriseId(user.getEnterpriseId());
            tmsShipbillDetailModel.setEnterpriseName(user.getEnterpriseName());
            tmsShipbillDetailModel.setCreateperson(user.getNickname());
            tmsShipbillDetailModel.setCreatetime(date);
            tmsShipbillDetailModel.setUpdateperson(user.getNickname());
            tmsShipbillDetailModel.setUpdatetime(date);
            shipBillDetailMapper.save(tmsShipbillDetailModel);

            addShipBillAdjust(headerModel.getShipbillNo(), "新增件数" + headerModel.getTotalPcs().stripTrailingZeros().toPlainString());
            logService.addLog(LogTypeEnum.SHIP_BILL, headerModel.getShipbillNo(), "新增运单");
            impCnt++;
        }
        return impCnt;
    }

    /**
     * addBmsShipBill
     * @param vo
     */
    private void addBmsShipBill(BmsShipBillVO vo) {
        String shipBillNo = mainDataProxy.getCodeNumberByCode(BmsConstant.SHIP_BILL_HEAD_ID);
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        vo.setShipbillNo(shipBillNo);
        BmsShipBillHeaderModel bmsShipBillHeaderModel = BeanUtil.copyProperties(vo, BmsShipBillHeaderModel.class);
        if (bmsShipBillHeaderModel.getCarrierType().intValue() == 2 && ObjectUtil.isNotNull(bmsShipBillHeaderModel.getDriverId())) {
            // 获取司机的隶属机构
            DriverCheckVO driverCheckVO = new DriverCheckVO();
            driverCheckVO.setId(bmsShipBillHeaderModel.getDriverId());
            RestMessage<DriverCheckDTO> driverCheckDTORestMessage = maindataFeign.getDriverExecute(driverCheckVO);
            if (driverCheckDTORestMessage.isSuccess() && ObjectUtil.isNotNull(driverCheckDTORestMessage.getData())) {
                bmsShipBillHeaderModel.setCarrierId(driverCheckDTORestMessage.getData().getAffiliationId());
                bmsShipBillHeaderModel.setCarrierCode(driverCheckDTORestMessage.getData().getAffiliationCode());
                bmsShipBillHeaderModel.setCarrierName(driverCheckDTORestMessage.getData().getAffiliationName());
            }
        }
        bmsShipBillHeaderModel.setAffiliationId(bmsShipBillHeaderModel.getCarrierId());
        bmsShipBillHeaderModel.setAffiliationCode(bmsShipBillHeaderModel.getCarrierCode());
        bmsShipBillHeaderModel.setAffiliationName(bmsShipBillHeaderModel.getCarrierName());
        bmsShipBillHeaderModel.setShipbillNo(shipBillNo);
        bmsShipBillHeaderModel.setFeeCltType(BmsConstant.FEE_CLT_TYPE_NO_MATCH);
        bmsShipBillHeaderModel.setPayFeeCltType(BmsConstant.FEE_CLT_TYPE_NO_MATCH);
        bmsShipBillHeaderModel.setOrganizationId(user.getOrganizationId());
        bmsShipBillHeaderModel.setOrganizationCode(String.valueOf(user.getOrganizationId()));
        bmsShipBillHeaderModel.setOrganizationName(user.getOrgnaizationName());
        bmsShipBillHeaderModel.setSettlementCompany(vo.getDepartmentName());
        bmsShipBillHeaderModel.setSettlementCompanyId(vo.getDepartmentId());
        bmsShipBillHeaderModel.setSettlementCompanyCode(vo.getDepartmentCode());
        bmsShipBillHeaderModel.setSettlementDepartment(vo.getDepartmentName());
        bmsShipBillHeaderModel.setSettlementDepartmentId(vo.getDepartmentId());
        bmsShipBillHeaderModel.setSettlementDepartmentCode(vo.getDepartmentCode());
        bmsShipBillHeaderModel.setCreateperson(user.getNickname());
        bmsShipBillHeaderModel.setCreatetime(DateUtil.date());
        bmsShipBillHeaderModel.setUpdateperson(user.getNickname());
        bmsShipBillHeaderModel.setUpdatetime(DateUtil.date());
        bmsShipBillHeaderModel.setEnterpriseId(user.getEnterpriseId());
        bmsShipBillHeaderModel.setEnterpriseName(user.getEnterpriseName());
        bmsShipBillHeaderModel.setSource(BmsConstant.SOURCE_ADD);
        bmsShipBillHeaderModel.setStatus(BmsConstant.SHIPBILL_STATUS_END);
        bmsShipBillHeaderModel.setShipBillStatus(BmsConstant.SHIPBILL_STATUS_END);
        bmsShipBillHeaderModel.setAbnormalStatus(0);
        bmsShipBillHeaderModel.setShipperProvinceCityDistrict(vo.getShipperProvinceName() + vo.getShipperCityName() + vo.getShipperDistrictName());
        bmsShipBillHeaderModel.setConsigneeProvinceCityDistrict(vo.getConsigneeProvinceName() + vo.getConsigneeCityName() + vo.getConsigneeDistrictName());
        bmsShipBillHeaderModel.setCompletionDate(DateUtil.date());
        bmsShipBillHeaderModel.setTotalMileage(NumberUtil.null2Zero(bmsShipBillHeaderModel.getTotalMileage()));
        bmsShipBillHeaderModel.setTotalPayMileage(NumberUtil.null2Zero(bmsShipBillHeaderModel.getTotalPayMileage()));
        bmsShipBillHeaderModel.setTotalPcs(BigDecimal.ZERO);
        bmsShipBillHeaderModel.setTotalWeight(BigDecimal.ZERO);
        bmsShipBillHeaderModel.setTotalVolume(BigDecimal.ZERO);
        bmsShipBillHeaderModel.setPackageLclPiece(BigDecimal.ZERO);
        bmsShipBillHeaderModel.setPackageWholePiece(BigDecimal.ZERO);
        bmsShipBillHeaderModel.setPackageTotalWeight(BigDecimal.ZERO);
        bmsShipBillHeaderModel.setPackageTotalVolume(BigDecimal.ZERO);
        bmsShipBillHeaderModel.setTotalPayPcs(BigDecimal.ZERO);
        bmsShipBillHeaderModel.setTotalPayWeight(BigDecimal.ZERO);
        bmsShipBillHeaderModel.setTotalPayVolume(BigDecimal.ZERO);
        if (CollectionUtil.isNotEmpty(vo.getDetailList())) {
            addBmsShipBillDetail(bmsShipBillHeaderModel, vo.getDetailList());
            bmsShipBillHeaderModel.setTotalPcs(vo.getDetailList().stream().map(BmsShipBillItemVO::getPcs).reduce(BigDecimal.ZERO, NumberUtil::add));
            bmsShipBillHeaderModel.setTotalWeight(vo.getDetailList().stream().map(BmsShipBillItemVO::getWeight).reduce(BigDecimal.ZERO, NumberUtil::add));
            bmsShipBillHeaderModel.setTotalVolume(vo.getDetailList().stream().map(BmsShipBillItemVO::getVolume).reduce(BigDecimal.ZERO, NumberUtil::add));
            bmsShipBillHeaderModel.setTotalPayPcs(vo.getDetailList().stream().map(BmsShipBillItemVO::getPcs).reduce(BigDecimal.ZERO, NumberUtil::add));
            bmsShipBillHeaderModel.setTotalPayWeight(vo.getDetailList().stream().map(BmsShipBillItemVO::getWeight).reduce(BigDecimal.ZERO, NumberUtil::add));
            bmsShipBillHeaderModel.setTotalPayVolume(vo.getDetailList().stream().map(BmsShipBillItemVO::getVolume).reduce(BigDecimal.ZERO, NumberUtil::add));
        }
        sumPackage(vo, bmsShipBillHeaderModel);
        shipBillHeadMapper.save(bmsShipBillHeaderModel);
        Criteria criteria = Criteria.forClass(BmsShipBillHeaderModel.class);
        Restriction r1 = Restrictions.eq(BmsShipBillHeaderModel::getShipbillNo, bmsShipBillHeaderModel.getShipbillNo());
        Restriction r2 = Restrictions.eq(BmsShipBillHeaderModel::getEnterpriseId, user.getEnterpriseId());
        criteria.setRestriction(Restrictions.and(r1, r2));
        List<BmsShipBillHeaderModel> shipBillHeaderModelList = shipBillHeadMapper.findByCriteria(criteria);
        bmsShipBillHeaderModel.setId(shipBillHeaderModelList.get(0).getId());
        addShipBillAdjust(bmsShipBillHeaderModel.getShipbillNo(), "新增件数" + bmsShipBillHeaderModel.getTotalPcs().stripTrailingZeros().toPlainString());
        logService.addLog(LogTypeEnum.SHIP_BILL, bmsShipBillHeaderModel.getShipbillNo(), "新增运单");
        if (BusinessTypeEnum.INCOME.getCode().equals(vo.getBusinessTypeHidden())) {
            calIncomeShipBill(bmsShipBillHeaderModel);
        } else {
            calPayShipBill(bmsShipBillHeaderModel);
        }
    }

    /**
     * updateBmsShipBill
     * @param vo
     */
    private void updateBmsShipBill(BmsShipBillVO vo) {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        BmsShipBillHeaderModel bmsShipBillHeaderModel = shipBillHeadMapper.findById(vo.getId(), BmsShipBillHeaderModel.class);
        BigDecimal totalPcs = bmsShipBillHeaderModel.getTotalPcs();
        BigDecimal totalPayPcs = bmsShipBillHeaderModel.getTotalPayPcs();
        BeanUtil.copyProperties(vo, bmsShipBillHeaderModel);
        if (bmsShipBillHeaderModel.getCarrierType().intValue() == 2 && ObjectUtil.isNotNull(bmsShipBillHeaderModel.getDriverId())) {
            // 获取司机的隶属机构
            DriverCheckVO driverCheckVO = new DriverCheckVO();
            driverCheckVO.setId(bmsShipBillHeaderModel.getDriverId());
            RestMessage<DriverCheckDTO> driverCheckDTORestMessage = maindataFeign.getDriverExecute(driverCheckVO);
            if (driverCheckDTORestMessage.isSuccess() && ObjectUtil.isNotNull(driverCheckDTORestMessage.getData())) {
                bmsShipBillHeaderModel.setCarrierId(driverCheckDTORestMessage.getData().getAffiliationId());
                bmsShipBillHeaderModel.setCarrierCode(driverCheckDTORestMessage.getData().getAffiliationCode());
                bmsShipBillHeaderModel.setCarrierName(driverCheckDTORestMessage.getData().getAffiliationName());
            }
        }
        bmsShipBillHeaderModel.setAffiliationId(bmsShipBillHeaderModel.getCarrierId());
        bmsShipBillHeaderModel.setAffiliationCode(bmsShipBillHeaderModel.getCarrierCode());
        bmsShipBillHeaderModel.setAffiliationName(bmsShipBillHeaderModel.getCarrierName());
        bmsShipBillHeaderModel.setUpdateperson(user.getNickname());
        bmsShipBillHeaderModel.setUpdatetime(DateUtil.date());
        bmsShipBillHeaderModel.setShipperProvinceCityDistrict(vo.getShipperProvinceName() + vo.getShipperCityName() + vo.getShipperDistrictName());
        bmsShipBillHeaderModel.setConsigneeProvinceCityDistrict(vo.getConsigneeProvinceName() + vo.getConsigneeCityName() + vo.getConsigneeDistrictName());
        bmsShipBillHeaderModel.setSettlementCompany(vo.getDepartmentName());
        bmsShipBillHeaderModel.setSettlementCompanyId(vo.getDepartmentId());
        bmsShipBillHeaderModel.setSettlementCompanyCode(vo.getDepartmentCode());
        bmsShipBillHeaderModel.setSettlementDepartment(vo.getDepartmentName());
        bmsShipBillHeaderModel.setSettlementDepartmentId(vo.getDepartmentId());
        bmsShipBillHeaderModel.setSettlementDepartmentCode(vo.getDepartmentCode());
        //因为前端支出和收入的运单详情页公用一个，不改支出件重体的字段，这里需要特殊处理  详情页查询同理
        List<BmsShipBillDetailModel> detailModelList = getDetailModel(bmsShipBillHeaderModel.getShipbillNo());
        if (CollectionUtil.isNotEmpty(vo.getDetailList())) {
            List<Long> existIdList = Lists.newArrayList();
            vo.getDetailList().forEach(itemVO -> {
                // 新增行
                if (ObjectUtil.isNull(itemVO.getPayPcs())) {
                    addBmsShipBillDetail(bmsShipBillHeaderModel, Lists.newArrayList(itemVO));
                } else {
                    existIdList.add(itemVO.getId());
                    BmsShipBillDetailModel detailModel = shipBillDetailMapper.findById(itemVO.getId(), BmsShipBillDetailModel.class);
                    if (BusinessTypeEnum.INCOME.getCode().equals(vo.getBusinessTypeHidden())) {
                        detailModel.setPcs(itemVO.getPcs());
                        detailModel.setWeight(itemVO.getWeight());
                        detailModel.setVolume(itemVO.getVolume());
                    } else {
                        detailModel.setPayPcs(itemVO.getPcs());
                        detailModel.setPayWeight(itemVO.getWeight());
                        detailModel.setPayVolume(itemVO.getVolume());
                    }
                    detailModel.setPackType(itemVO.getPackType());
                    detailModel.setCargoThermosphere(itemVO.getCargoThermosphere());
                    detailModel.setUpdateperson(user.getNickname());
                    detailModel.setUpdatetime(DateUtil.date());
                    shipBillDetailMapper.update(detailModel);
                }
            });
            detailModelList = detailModelList.stream().filter(detailModel -> !existIdList.contains(detailModel.getId())).collect(Collectors.toList());
        }
        if (CollectionUtil.isNotEmpty(detailModelList)) {
            shipBillDetailMapper.deleteByIds(detailModelList.stream().map(BmsShipBillDetailModel::getId).collect(Collectors.toList()).toArray(), BmsShipBillDetailModel.class);
        }
        detailModelList = getDetailModel(bmsShipBillHeaderModel.getShipbillNo());
        if (CollectionUtil.isNotEmpty(detailModelList)) {
            bmsShipBillHeaderModel.setTotalPcs(detailModelList.stream().map(BmsShipBillDetailModel::getPcs).reduce(BigDecimal.ZERO, NumberUtil::add));
            bmsShipBillHeaderModel.setTotalWeight(detailModelList.stream().map(BmsShipBillDetailModel::getWeight).reduce(BigDecimal.ZERO, NumberUtil::add));
            bmsShipBillHeaderModel.setTotalVolume(detailModelList.stream().map(BmsShipBillDetailModel::getVolume).reduce(BigDecimal.ZERO, NumberUtil::add));
            bmsShipBillHeaderModel.setTotalPayPcs(detailModelList.stream().map(BmsShipBillDetailModel::getPayPcs).reduce(BigDecimal.ZERO, NumberUtil::add));
            bmsShipBillHeaderModel.setTotalPayWeight(detailModelList.stream().map(BmsShipBillDetailModel::getPayWeight).reduce(BigDecimal.ZERO, NumberUtil::add));
            bmsShipBillHeaderModel.setTotalPayVolume(detailModelList.stream().map(BmsShipBillDetailModel::getPayVolume).reduce(BigDecimal.ZERO, NumberUtil::add));
        }
        List<BmsShipBillPackageModel> packageModelList = getPackageModel(bmsShipBillHeaderModel.getShipbillNo());
        if (CollectionUtil.isNotEmpty(packageModelList)) {
            shipBillPackageMapper.deleteByIds(packageModelList.stream().map(BmsShipBillPackageModel::getId).collect(Collectors.toList()).toArray(), BmsShipBillPackageModel.class);
        }
        sumPackage(vo, bmsShipBillHeaderModel);
        shipBillHeadMapper.update(bmsShipBillHeaderModel);
        if (BusinessTypeEnum.INCOME.getCode().equals(vo.getBusinessTypeHidden())) {
            addShipBillAdjust(bmsShipBillHeaderModel.getShipbillNo(), "将收入数量从" + totalPcs.stripTrailingZeros().toPlainString() + "件调整到" + bmsShipBillHeaderModel.getTotalPcs().stripTrailingZeros().toPlainString());
        } else {
            addShipBillAdjust(bmsShipBillHeaderModel.getShipbillNo(), "将支出数量从" + totalPayPcs.stripTrailingZeros().toPlainString() + "件调整到" + bmsShipBillHeaderModel.getTotalPayPcs().stripTrailingZeros().toPlainString());
        }
        logService.addLog(LogTypeEnum.SHIP_BILL, bmsShipBillHeaderModel.getShipbillNo(), "运单修改");
//        if (BmsConstant.TMS_DOWN.equals(bmsShipBillHeaderModel.getSource())) {
//            Criteria criteria = Criteria.forClass(BmsShipBillHeaderModel.class);
//            Restriction r1 = Restrictions.eq(BmsShipBillHeaderModel::getLoadingId, bmsShipBillHeaderModel.getLoadingId());
//            Restriction r2 = Restrictions.eq(BmsShipBillHeaderModel::getEnterpriseId, bmsShipBillHeaderModel.getEnterpriseId());
//            criteria.setRestriction(Restrictions.and(r1, r2));
//            List<BmsShipBillHeaderModel> shipBillHeaderModelList = shipBillHeadMapper.findByCriteria(criteria);
//            if (CollectionUtil.isNotEmpty(shipBillHeaderModelList)) {
//                BmsLoadingBillHeaderModel headerModel = loadingBillHeadMapper.findById(bmsShipBillHeaderModel.getLoadingId(), BmsLoadingBillHeaderModel.class);
//                headerModel.setTotalPcs(shipBillHeaderModelList.stream().map(BmsShipBillHeaderModel::getTotalPcs).reduce(BigDecimal.ZERO, NumberUtil::add));
//                headerModel.setTotalWeight(shipBillHeaderModelList.stream().map(BmsShipBillHeaderModel::getTotalWeight).reduce(BigDecimal.ZERO, NumberUtil::add));
//                headerModel.setTotalVolume(shipBillHeaderModelList.stream().map(BmsShipBillHeaderModel::getTotalVolume).reduce(BigDecimal.ZERO, NumberUtil::add));
//                headerModel.setTotalLclPiece(shipBillHeaderModelList.stream().map(BmsShipBillHeaderModel::getPackageLclPiece).reduce(BigDecimal.ZERO, NumberUtil::add));
//                headerModel.setTotalWholePiece(shipBillHeaderModelList.stream().map(BmsShipBillHeaderModel::getPackageWholePiece).reduce(BigDecimal.ZERO, NumberUtil::add));
//                headerModel.setTotalPayPcs(shipBillHeaderModelList.stream().map(BmsShipBillHeaderModel::getTotalPayPcs).reduce(BigDecimal.ZERO, NumberUtil::add));
//                headerModel.setTotalPayWeight(shipBillHeaderModelList.stream().map(BmsShipBillHeaderModel::getTotalPayWeight).reduce(BigDecimal.ZERO, NumberUtil::add));
//                headerModel.setTotalPayVolume(shipBillHeaderModelList.stream().map(BmsShipBillHeaderModel::getTotalPayVolume).reduce(BigDecimal.ZERO, NumberUtil::add));
//                loadingBillHeadMapper.update(headerModel);
//            }
//        }
        calPayShipBill(bmsShipBillHeaderModel);
//        if (BusinessTypeEnum.INCOME.getCode().equals(vo.getBusinessTypeHidden())) {
//            if (BmsConstant.TMS_DOWN.equals(bmsShipBillHeaderModel.getSource())) {
//                loadingBillService.reIncomeCalculate(bmsShipBillHeaderModel.getLoadingId());
//            } else {
//                calIncomeShipBill(bmsShipBillHeaderModel);
//            }
//        } else {
//            if (BmsConstant.TMS_DOWN.equals(bmsShipBillHeaderModel.getSource())) {
//                loadingBillService.rePayCalculate(bmsShipBillHeaderModel.getId());
//            } else {
//                calPayShipBill(bmsShipBillHeaderModel);
//            }
//        }
    }

    /**
     * sumPackage
     * @param vo
     * @param bmsShipBillHeaderModel
     */
    private void sumPackage(BmsShipBillVO vo, BmsShipBillHeaderModel bmsShipBillHeaderModel) {
        if (CollectionUtil.isNotEmpty(vo.getPackageList())) {
            addBmsShipBillPackage(bmsShipBillHeaderModel, vo.getPackageList());
            bmsShipBillHeaderModel.setPackageLclPiece(vo.getPackageList().stream().map(BmsShipBillPackageVO::getLclPiece).reduce(BigDecimal.ZERO, NumberUtil::add));
            bmsShipBillHeaderModel.setPackageWholePiece(vo.getPackageList().stream().map(BmsShipBillPackageVO::getWholePiece).reduce(BigDecimal.ZERO, NumberUtil::add));
            bmsShipBillHeaderModel.setPackageTotalWeight(vo.getPackageList().stream().map(BmsShipBillPackageVO::getPackageTotalWeight).reduce(BigDecimal.ZERO, NumberUtil::add));
            bmsShipBillHeaderModel.setPackageTotalVolume(vo.getPackageList().stream().map(BmsShipBillPackageVO::getPackageTotalVolume).reduce(BigDecimal.ZERO, NumberUtil::add));
        }
    }

    /**
     * addBmsShipBillDetail
     * @param bmsShipBillHeaderModel
     * @param itemVOList
     */
    private List<BmsShipBillDetailModel> addBmsShipBillDetail(BmsShipBillHeaderModel bmsShipBillHeaderModel, List<BmsShipBillItemVO> itemVOList) {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        List<BmsShipBillDetailModel> detailModelList = itemVOList.stream().map(vo -> {
            BmsShipBillDetailModel detailModel = BeanUtil.copyProperties(vo, BmsShipBillDetailModel.class);
            detailModel.setId(null);
            detailModel.setPayPcs(vo.getPcs());
            detailModel.setPayWeight(vo.getWeight());
            detailModel.setPayVolume(vo.getVolume());
            detailModel.setShipbillNo(bmsShipBillHeaderModel.getShipbillNo());
            detailModel.setCargoOwnerId(bmsShipBillHeaderModel.getCargoOwnerId());
            detailModel.setCargoOwnerCode(bmsShipBillHeaderModel.getCargoOwnerCode());
            detailModel.setCargoOwnerName(bmsShipBillHeaderModel.getCargoOwnerName());
            detailModel.setCreateperson(user.getNickname());
            detailModel.setCreatetime(DateUtil.date());
            detailModel.setUpdateperson(user.getNickname());
            detailModel.setUpdatetime(DateUtil.date());
            detailModel.setEnterpriseId(user.getEnterpriseId());
            detailModel.setEnterpriseName(user.getEnterpriseName());
            return detailModel;
        }).collect(Collectors.toList());
        shipBillDetailMapper.saveBatch(detailModelList);
        return detailModelList;
    }

    /**
     * addBmsShipBillPackage
     * @param bmsShipBillHeaderModel
     * @param packageVOList
     */
    private void addBmsShipBillPackage(BmsShipBillHeaderModel bmsShipBillHeaderModel, List<BmsShipBillPackageVO> packageVOList) {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        shipBillPackageMapper.saveBatch(packageVOList.stream().map(vo -> {
            BmsShipBillPackageModel packageModel = BeanUtil.copyProperties(vo, BmsShipBillPackageModel.class);
            packageModel.setShipbillNo(bmsShipBillHeaderModel.getShipbillNo());
            packageModel.setCreateperson(user.getNickname());
            packageModel.setCreatetime(DateUtil.date());
            packageModel.setUpdateperson(user.getNickname());
            packageModel.setUpdatetime(DateUtil.date());
            packageModel.setEnterpriseId(user.getEnterpriseId());
            packageModel.setEnterpriseName(user.getEnterpriseName());
            return packageModel;
        }).collect(Collectors.toList()));
    }

    /**
     * modelToBmsShipBillDTO
     * @param model
     * @param dicData
     * @return
     */
    private BmsShipBillDTO modelToBmsShipBillDTO(BmsShipBillHeaderModel model, List<SysRefdatadModel> dicData) {
        BmsShipBillDTO shipBillDTO = BeanUtil.copyProperties(model, BmsShipBillDTO.class);
        shipBillDTO.setSettlementCompany(shipBillDTO.getSettlementDepartment());
        shipBillDTO.setSettlementCompanyId(shipBillDTO.getSettlementDepartmentId());
        shipBillDTO.setSettlementCompanyCode(shipBillDTO.getSettlementDepartmentCode());
        shipBillDTO.setOrderTypeName(ConvertorUtil.getName(dicData, BmsConstant.ORDER_TYPE, String.valueOf(model.getOrderType())));
        shipBillDTO.setOrderBusinessTypeName(ConvertorUtil.getName(dicData, BmsConstant.ORDER_BUSINESS_TYPE, String.valueOf(model.getOrderBusinessType())));
        shipBillDTO.setTemperatureRequirementName(ConvertorUtil.getName(dicData, BmsConstant.TEMPERATURE_REQUIREMENT, String.valueOf(model.getTemperatureRequirement())));
        shipBillDTO.setShipperTypeName(ConvertorUtil.getName(dicData, BmsConstant.SHIPPER_TYPE, String.valueOf(model.getShipperType())));
        shipBillDTO.setConsigneeTypeName(ConvertorUtil.getName(dicData, BmsConstant.CONSIGNEE_TYPE, String.valueOf(model.getConsigneeType())));
        shipBillDTO.setStatusName(ConvertorUtil.getName(dicData, BmsConstant.SHIPBILL_STATUS, String.valueOf(model.getStatus())));
        shipBillDTO.setSourceName(ConvertorUtil.getName(dicData, BmsConstant.SOURCE, String.valueOf(model.getSource())));
        shipBillDTO.setShipBillStatusName(ConvertorUtil.getName(dicData, BmsConstant.SHIPBILL_STATUS, String.valueOf(model.getShipBillStatus())));
        shipBillDTO.setSynchronousStatusName(ConvertorUtil.getName(dicData, BmsConstant.SYNCHRONOUS_STATUS, String.valueOf(model.getSynchronousStatus())));
        shipBillDTO.setAbnormalStatusName(ConvertorUtil.getName(dicData, BmsConstant.ABNORMAL_STATUS, String.valueOf(model.getAbnormalStatus())));
        shipBillDTO.setDeliveryMethodTypeName(ConvertorUtil.getName(dicData, BmsConstant.DELIVERY_METHOD_TYPE, String.valueOf(model.getDeliveryMethodType())));
        shipBillDTO.setTransportTypeName(ConvertorUtil.getName(dicData, BmsConstant.TRANSPORT_TYPE, String.valueOf(model.getTransportType())));
        shipBillDTO.setFeeCltTypeName(ConvertorUtil.getName(dicData, BmsConstant.FEE_CLT_TYPE, String.valueOf(model.getFeeCltType())));
        shipBillDTO.setPayFeeCltTypeName(ConvertorUtil.getName(dicData, BmsConstant.FEE_CLT_TYPE, String.valueOf(model.getPayFeeCltType())));
       if (ObjectUtil.isNotNull(model.getCarrierType())) {
            shipBillDTO.setCarrierTypeName(ConvertorUtil.getName(dicData, BmsConstant.LINE_CARRIER_TYPE, String.valueOf(model.getCarrierType())));
            if (model.getCarrierType().intValue() == 2) {
                shipBillDTO.setCarrierName(model.getDriverName());
            }
        }
        return shipBillDTO;
    }

    /**
     * fillIncomeFee
     * @param dto
     * @param dicData
     * @return
     */
    private BmsShipBillDTO fillIncomeFee(BmsShipBillDTO dto, List<SysRefdatadModel> dicData) {
        List<BmsBillIncomeFeeHeaderModel> incomeFeeHeaderModelList = getIncomeByShipBill(dto.getShipbillNo(), dto.getEnterpriseId());
        if (CollectionUtil.isNotEmpty(incomeFeeHeaderModelList)) {
            BmsBillIncomeFeeHeaderModel model = incomeFeeHeaderModelList.get(0);
            dto.setSettlementDate(model.getSettlementDate());
            dto.setSettlementStatus(model.getSettlementStatus());
            dto.setCostDate(model.getCostDate());
            dto.setCostContract(model.getCostContract());
            dto.setCostStatus(model.getCostStatus());
            dto.setCostFailReason(model.getCostFailReason());
            dto.setCostStatusName(ConvertorUtil.getName(dicData, BmsConstant.COST_STATUS, String.valueOf(dto.getCostStatus())));
            dto.setCheckStatus(model.getCheckStatus());
            dto.setIncomeAmount(NumberUtil.null2Zero(model.getIncomeAmount()));
            dto.setContractIncomeAmount(NumberUtil.null2Zero(model.getContractIncomeAmount()));

            List<BmsBillIncomeFeeDetailModel> detailModelList = bmsBillIncomeFeeService.findDetailModel(model);
            if (CollectionUtil.isNotEmpty(detailModelList)) {
                dto.setIncomeBillingPrice(detailModelList.stream().map(BmsBillIncomeFeeDetailModel::getBillingPrice).filter(StrUtil::isNotBlank).distinct().collect(Collectors.joining(",")));
            }
        } else {
            dto.setSettlementStatus(BmsConstant.SETTLEMENT_STATUS_0);
            dto.setCheckStatus(BmsConstant.CHECK_STATUS_0);
            dto.setIncomeAmount(BigDecimal.ZERO);
            dto.setContractIncomeAmount(BigDecimal.ZERO);
        }
        return dto;
    }

    /**
     * fillPayFee
     * @param dto
     * @param dicData
     * @return
     */
    private BmsShipBillDTO fillPayFee(BmsShipBillDTO dto, List<SysRefdatadModel> dicData) {
        List<BmsBillPayFeeHeaderModel> payFeeHeaderModelList = getPayByShipBill(dto.getShipbillNo(), dto.getEnterpriseId());
        if (CollectionUtil.isNotEmpty(payFeeHeaderModelList)) {
            BmsBillPayFeeHeaderModel model = payFeeHeaderModelList.get(0);
            dto.setSettlementDate(model.getSettlementDate());
            dto.setSettlementStatus(model.getSettlementStatus());
            dto.setCostDate(model.getCostDate());
            dto.setCostContract(model.getCostContract());
            dto.setCostStatus(model.getCostStatus());
            dto.setCostFailReason(model.getCostFailReason());
            dto.setCostStatusName(ConvertorUtil.getName(dicData, BmsConstant.COST_STATUS, String.valueOf(dto.getCostStatus())));
            dto.setCheckStatus(model.getCheckStatus());
            dto.setPayAmount(NumberUtil.null2Zero(model.getPayAmount()));
            dto.setContractPayAmount(NumberUtil.null2Zero(model.getContractPayAmount()));

            List<BmsBillPayFeeDetailModel> detailModelList = bmsBillPayFeeService.findDetailModel(model);
            if (CollectionUtil.isNotEmpty(detailModelList)) {
                dto.setPayBillingPrice(detailModelList.stream().map(BmsBillPayFeeDetailModel::getBillingPrice).filter(StrUtil::isNotBlank).distinct().collect(Collectors.joining(",")));
            }
        } else {
            dto.setSettlementStatus(BmsConstant.SETTLEMENT_STATUS_0);
            dto.setCheckStatus(BmsConstant.CHECK_STATUS_0);
            dto.setPayAmount(BigDecimal.ZERO);
            dto.setContractPayAmount(BigDecimal.ZERO);
        }
        return dto;
    }

    /**
     * getDic
     * @return
     */
    private List<SysRefdatadModel> getDic() {
        return convertorUtil.getDictionary(new String[] {
                BmsConstant.SHIPBILL_STATUS, // 运单状态
                BmsConstant.SHIPPER_TYPE, // 运输状态
                BmsConstant.ABNORMAL_STATUS, // 异常状态
                BmsConstant.ORDER_TYPE, // 订单类型
                BmsConstant.CONSIGNEE_TYPE, // 收货方类型
                BmsConstant.ORDER_BUSINESS_TYPE, // 订单业务类型
                BmsConstant.SETTLEMENT_STATUS, // 核算状态
                BmsConstant.SOURCE, // 来源
                BmsConstant.COST_STATUS, // 计费状态
                BmsConstant.SYNCHRONOUS_STATUS, // 同步状态
                BmsConstant.TEMPERATURE_REQUIREMENT,// 温度要求
                BmsConstant.LINE_CARRIER_TYPE,// 承运方类型
                BmsConstant.DELIVERY_METHOD_TYPE,// 配送方式
                BmsConstant.TRANSPORT_TYPE,// 运输模式
                // 费用计算类型
                BmsConstant.FEE_CLT_TYPE,
                BmsConstant.CHECK_STATUS
        });
    }

    /**
     * getIncomeByShipBill
     * @param shipBillNo
     * @param enterpriseId
     * @return
     */
    private List<BmsBillIncomeFeeHeaderModel> getIncomeByShipBill(String shipBillNo, Long enterpriseId) {
        Criteria criteria = Criteria.forClass(BmsBillIncomeFeeHeaderModel.class);
        Restriction r1 = Restrictions.eq(BmsBillIncomeFeeHeaderModel::getBillNo, shipBillNo);
        Restriction r2 = Restrictions.eq(BmsBillIncomeFeeHeaderModel::getBillType, 10);
        Restriction r3 = Restrictions.eq(BmsBillIncomeFeeHeaderModel::getEnterpriseId, enterpriseId);
        criteria.setRestriction(Restrictions.and(r1, r2, r3));
        return incomeFeeHeaderMapper.findByCriteria(criteria);
    }

    /**
     * getRelationIncomeByShipBill
     * @param shipBillNo
     * @param enterpriseId
     * @return
     */
    private List<BmsBillIncomeFeeHeaderModel> getRelationIncomeByShipBill(String shipBillNo, Long enterpriseId) {
        Criteria criteria = Criteria.forClass(BmsShipBillHeaderModel.class);
        Restriction r1 = Restrictions.eq(BmsShipBillHeaderModel::getShipbillNo, shipBillNo);
        Restriction r2 = Restrictions.eq(BmsShipBillHeaderModel::getEnterpriseId, enterpriseId);
        criteria.setRestriction(Restrictions.and(r1, r2));
        List<BmsShipBillHeaderModel> bmsShipBillHeaderModelList = shipBillHeadMapper.findByCriteria(criteria);
        if (CollectionUtil.isNotEmpty(bmsShipBillHeaderModelList)) {
            Long loadingId = bmsShipBillHeaderModelList.get(0).getLoadingId();
            if (ObjectUtil.isNull(loadingId)) {
                return getIncomeByShipBill(shipBillNo, enterpriseId);
            }
            r1 = Restrictions.eq(BmsShipBillHeaderModel::getLoadingId, loadingId);
            criteria.setRestriction(Restrictions.and(r1, r2));
            List<BmsShipBillHeaderModel> shipBillHeaderModelList = shipBillHeadMapper.findByCriteria(criteria);
            if (CollectionUtil.isNotEmpty(shipBillHeaderModelList)) {
                criteria = Criteria.forClass(BmsBillIncomeFeeHeaderModel.class);
                r1 = Restrictions.in(BmsBillIncomeFeeHeaderModel::getBillNo, shipBillHeaderModelList.stream().map(BmsShipBillHeaderModel::getShipbillNo).collect(Collectors.toList()));
                r2 = Restrictions.eq(BmsBillIncomeFeeHeaderModel::getBillType, 10);
                Restriction r3 = Restrictions.eq(BmsBillIncomeFeeHeaderModel::getEnterpriseId, enterpriseId);
                criteria.setRestriction(Restrictions.and(r1, r2, r3));
                return incomeFeeHeaderMapper.findByCriteria(criteria);
            }
        }
        return Lists.newArrayList();
    }

    /**
     * getPayByShipBill
     * @param shipBillNo
     * @param enterpriseId
     * @return
     */
    private List<BmsBillPayFeeHeaderModel> getPayByShipBill(String shipBillNo, Long enterpriseId) {
        Criteria criteria = Criteria.forClass(BmsBillPayFeeHeaderModel.class);
        Restriction r1 = Restrictions.eq(BmsBillPayFeeHeaderModel::getBillNo, shipBillNo);
        Restriction r2 = Restrictions.eq(BmsBillPayFeeHeaderModel::getBillType, 10);
        Restriction r3 = Restrictions.eq(BmsBillPayFeeHeaderModel::getEnterpriseId, enterpriseId);
        criteria.setRestriction(Restrictions.and(r1, r2, r3));
        return payFeeHeaderMapper.findByCriteria(criteria);
    }

    /**
     * getRelationPayByShipBill
     * @param shipBillNo
     * @param enterpriseId
     * @return
     */
    private List<BmsBillPayFeeHeaderModel> getRelationPayByShipBill(String shipBillNo, Long enterpriseId) {
        Criteria criteria = Criteria.forClass(BmsShipBillHeaderModel.class);
        Restriction r1 = Restrictions.eq(BmsShipBillHeaderModel::getShipbillNo, shipBillNo);
        Restriction r2 = Restrictions.eq(BmsShipBillHeaderModel::getEnterpriseId, enterpriseId);
        criteria.setRestriction(Restrictions.and(r1, r2));
        List<BmsShipBillHeaderModel> bmsShipBillHeaderModelList = shipBillHeadMapper.findByCriteria(criteria);
        if (CollectionUtil.isNotEmpty(bmsShipBillHeaderModelList)) {
            Long loadingId = bmsShipBillHeaderModelList.get(0).getLoadingId();
            if (ObjectUtil.isNull(loadingId)) {
                return getPayByShipBill(shipBillNo, enterpriseId);
            }
            r1 = Restrictions.eq(BmsShipBillHeaderModel::getLoadingId, loadingId);
            criteria.setRestriction(Restrictions.and(r1, r2));
            List<BmsShipBillHeaderModel> shipBillHeaderModelList = shipBillHeadMapper.findByCriteria(criteria);
            if (CollectionUtil.isNotEmpty(shipBillHeaderModelList)) {
                criteria = Criteria.forClass(BmsBillPayFeeHeaderModel.class);
                r1 = Restrictions.in(BmsBillPayFeeHeaderModel::getBillNo, shipBillHeaderModelList.stream().map(BmsShipBillHeaderModel::getShipbillNo).collect(Collectors.toList()));
                r2 = Restrictions.eq(BmsBillPayFeeHeaderModel::getBillType, 10);
                Restriction r3 = Restrictions.eq(BmsBillPayFeeHeaderModel::getEnterpriseId, enterpriseId);
                criteria.setRestriction(Restrictions.and(r1, r2, r3));
                return payFeeHeaderMapper.findByCriteria(criteria);
            }
        }
        return Lists.newArrayList();
    }

    /**
     * calIncomeShipBill
     * @param headerModel
     */
    private Integer calIncomeShipBill(BmsShipBillHeaderModel headerModel) {
        Integer feeCltType = BmsConstant.FEE_CLT_TYPE_NO_MATCH;
        List<BmsShipBillDetailModel> detailModelList = getDetailModel(headerModel.getShipbillNo());
        try {
            Integer result = incomeCostStrategyService.shipBillCostStrategy(headerModel, detailModelList, "1", PlgFxUsrUtils.getUserEntity());
            if (result == 200) {
                feeCltType = BmsConstant.FEE_CLT_TYPE_SHIP_BILL;
            }
        } catch (Exception e) {
            log.error("运单收入核算失败", e);
        }
        headerModel.setFeeCltType(feeCltType);
        shipBillHeadMapper.update(headerModel);
        return feeCltType;
    }

    /**
     * calPayShipBill
     * @param headerModel
     */
    private Integer calPayShipBill(BmsShipBillHeaderModel headerModel) {
        Integer feeCltType = BmsConstant.FEE_CLT_TYPE_NO_MATCH;
        List<BmsShipBillDetailModel> detailModelList = getDetailModel(headerModel.getShipbillNo());
        try {
            Integer result = payCostStrategyService.costShipBillTrailerStrategy(headerModel, detailModelList, "1", PlgFxUsrUtils.getUserEntity());
            if (result == 200) {
                feeCltType = BmsConstant.FEE_CLT_TYPE_SHIP_BILL;
            }
        } catch (Exception e) {
            log.error("运单支出核算失败", e);
        }
        headerModel.setPayFeeCltType(feeCltType);
        shipBillHeadMapper.update(headerModel);
        return feeCltType;
    }

    /**
     * updateIncomeShipBillFee
     * @param shipBillNo
     */
    private void updateIncomeShipBillFee(String shipBillNo) {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        Criteria criteria = Criteria.forClass(BmsShipBillHeaderModel.class);
        Restriction r1 = Restrictions.eq(BmsShipBillHeaderModel::getShipbillNo, shipBillNo);
        Restriction r2 = Restrictions.eq(BmsShipBillHeaderModel::getEnterpriseId, user.getEnterpriseId());
        criteria.setRestriction(Restrictions.and(r1, r2));
        List<BmsShipBillHeaderModel> modelList = shipBillHeadMapper.findByCriteria(criteria);
        if (CollectionUtil.isNotEmpty(modelList)) {
            List<BmsBillIncomeFeeHeaderModel> incomeModelList = getRelationIncomeByShipBill(shipBillNo, user.getEnterpriseId());
            if (CollectionUtil.isNotEmpty(incomeModelList)) {
                Integer settlementStatus = BmsConstant.SETTLEMENT_STATUS_1;
                if (incomeModelList.stream().anyMatch(incomeModel -> BmsConstant.COST_STATUS_FAILED.equals(incomeModel.getCostStatus()))) {
                    settlementStatus = BmsConstant.SETTLEMENT_STATUS_0;
                }
                Integer finalSettlementStatus = settlementStatus;
                incomeModelList.forEach(incomeModel -> {
                    incomeModel.setSettlementStatus(finalSettlementStatus);
                    incomeModel.setUpdateperson(user.getNickname());
                    incomeModel.setUpdatetime(DateUtil.date());
                    incomeFeeHeaderMapper.update(incomeModel);
                    logService.addLog(LogTypeEnum.SHIP_BILL, incomeModel.getBillNo(), "收入核算");
                });

                if (ObjectUtil.isNotNull(modelList.get(0).getLoadingId())) {
                    criteria = Criteria.forClass(BmsBillIncomeFeeHeaderModel.class);
                    r1 = Restrictions.eq(BmsBillIncomeFeeHeaderModel::getBillId, modelList.get(0).getLoadingId());
                    r2 = Restrictions.eq(BmsBillIncomeFeeHeaderModel::getBillType, 20);
                    Restriction r3 = Restrictions.eq(BmsBillIncomeFeeHeaderModel::getEnterpriseId, modelList.get(0).getEnterpriseId());
                    criteria.setRestriction(Restrictions.and(r1, r2, r3));
                    List<BmsBillIncomeFeeHeaderModel> bmsBillIncomeFeeHeaderModelList = incomeFeeHeaderMapper.findByCriteria(criteria);
                    if (CollectionUtil.isNotEmpty(bmsBillIncomeFeeHeaderModelList)) {
                        bmsBillIncomeFeeHeaderModelList.forEach(bmsBillIncomeFeeHeaderModel -> {
                            bmsBillIncomeFeeHeaderModel.setSettlementStatus(finalSettlementStatus);
                            bmsBillIncomeFeeHeaderModel.setUpdateperson(user.getNickname());
                            bmsBillIncomeFeeHeaderModel.setUpdatetime(DateUtil.date());
                            incomeFeeHeaderMapper.update(bmsBillIncomeFeeHeaderModel);
                        });
                    }
                }
            }
        }
    }

    /**
     * updatePayShipBillFee
     * @param shipBillNo
     */
    private void updatePayShipBillFee(String shipBillNo) {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        Criteria criteria = Criteria.forClass(BmsShipBillHeaderModel.class);
        Restriction r1 = Restrictions.eq(BmsShipBillHeaderModel::getShipbillNo, shipBillNo);
        Restriction r2 = Restrictions.eq(BmsShipBillHeaderModel::getEnterpriseId, user.getEnterpriseId());
        criteria.setRestriction(Restrictions.and(r1, r2));
        List<BmsShipBillHeaderModel> modelList = shipBillHeadMapper.findByCriteria(criteria);
        if (CollectionUtil.isNotEmpty(modelList)) {
            List<BmsBillPayFeeHeaderModel> payModelList = getRelationPayByShipBill(shipBillNo, user.getEnterpriseId());
            if (CollectionUtil.isNotEmpty(payModelList)) {
                Integer settlementStatus = BmsConstant.SETTLEMENT_STATUS_1;
                if (payModelList.stream().anyMatch(payModel -> BmsConstant.COST_STATUS_FAILED.equals(payModel.getCostStatus()))) {
                    settlementStatus = BmsConstant.SETTLEMENT_STATUS_0;
                }
                Integer finalSettlementStatus = settlementStatus;
                payModelList.forEach(payModel -> {
                    payModel.setSettlementStatus(finalSettlementStatus);
                    payModel.setUpdateperson(user.getNickname());
                    payModel.setUpdatetime(DateUtil.date());
                    payFeeHeaderMapper.update(payModel);
                    logService.addLog(LogTypeEnum.SHIP_BILL, payModel.getBillNo(), "支出核算");
                });

                if (ObjectUtil.isNotNull(modelList.get(0).getLoadingId())) {
                    criteria = Criteria.forClass(BmsBillPayFeeHeaderModel.class);
                    r1 = Restrictions.eq(BmsBillPayFeeHeaderModel::getBillId, modelList.get(0).getLoadingId());
                    r2 = Restrictions.eq(BmsBillPayFeeHeaderModel::getBillType, 20);
                    Restriction r3 = Restrictions.eq(BmsBillPayFeeHeaderModel::getEnterpriseId, modelList.get(0).getEnterpriseId());
                    criteria.setRestriction(Restrictions.and(r1, r2, r3));
                    List<BmsBillPayFeeHeaderModel> bmsBillPayFeeHeaderModelList = payFeeHeaderMapper.findByCriteria(criteria);
                    if (CollectionUtil.isNotEmpty(bmsBillPayFeeHeaderModelList)) {
                        bmsBillPayFeeHeaderModelList.forEach(bmsBillPayFeeHeaderModel -> {
                            bmsBillPayFeeHeaderModel.setSettlementStatus(finalSettlementStatus);
                            bmsBillPayFeeHeaderModel.setUpdateperson(user.getNickname());
                            bmsBillPayFeeHeaderModel.setUpdatetime(DateUtil.date());
                            payFeeHeaderMapper.update(bmsBillPayFeeHeaderModel);
                        });
                    }
                }
            }
        }
    }


    /**
     * checkIncomeCalculate
     * @param shipBillNo
     */
    private void checkIncomeCalculate(String shipBillNo) {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        List<BmsBillIncomeFeeHeaderModel> modelList = getRelationIncomeByShipBill(shipBillNo, user.getEnterpriseId());
        if (CollectionUtil.isNotEmpty(modelList)) {
            modelList.forEach(model -> {
                if (BmsConstant.SETTLEMENT_STATUS_1.equals(model.getSettlementStatus()) || BmsConstant.SETTLEMENT_STATUS_2.equals(model.getSettlementStatus())) {
                    if (shipBillNo.equals(model.getBillNo())) {
                        throw new BizException("运单" + shipBillNo + "正在收入核算中！");
                    } else {
                        throw new BizException("同派车单下运单" + model.getBillNo() + "正在收入核算中！");
                    }
                }
                if (!BmsConstant.CHECK_STATUS_0.equals(model.getCheckStatus())) {
                    if (shipBillNo.equals(model.getBillNo())) {
                        throw new BizException("运单"+shipBillNo+"已收入结算！");
                    } else {
                        throw new BizException("同派车单下运单" + model.getBillNo() + "已收入结算！");
                    }
                }
            });
        }
    }

    /**
     * checkPayCalculate
     * @param shipBillNo
     */
    private void checkPayCalculate(String shipBillNo) {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        List<BmsBillPayFeeHeaderModel> modelList = getPayByShipBill(shipBillNo, user.getEnterpriseId());
        if (CollectionUtil.isNotEmpty(modelList)) {
            modelList.forEach(model -> {
                if (BmsConstant.SETTLEMENT_STATUS_1.equals(model.getSettlementStatus()) || BmsConstant.SETTLEMENT_STATUS_2.equals(model.getSettlementStatus())) {
                    if (shipBillNo.equals(model.getBillNo())) {
                        throw new BizException("运单" + shipBillNo + "正在支出核算中！");
                    } else {
                        throw new BizException("同派车单下运单" + model.getBillNo() + "正在支出核算中！");
                    }
                }
                if (!BmsConstant.CHECK_STATUS_0.equals(model.getCheckStatus())) {
                    if (shipBillNo.equals(model.getBillNo())) {
                        throw new BizException("运单"+shipBillNo+"已支出结算！");
                    } else {
                        throw new BizException("同派车单下运单" + model.getBillNo() + "已支出结算！");
                    }
                }
            });
        }
    }

    /**
     * calIncome
     * @param headerModel
     */
    private void calIncome(BmsShipBillHeaderModel headerModel) {
        if (BmsConstant.FEE_CLT_TYPE_LOADING_BILL.equals(headerModel.getFeeCltType())) {
            throw new BizException("派车单计费不支持运单收入核算");
        }
        checkIncomeCalculate(headerModel.getShipbillNo());
        if (BmsConstant.TMS_DOWN.equals(headerModel.getSource())) {
            loadingBillService.reIncomeCalculate(headerModel.getLoadingId());
        } else {
            calIncomeShipBill(headerModel);
        }
        updateIncomeShipBillFee(headerModel.getShipbillNo());
    }

    /**
     * calPay
     * @param headerModel
     */
    private void calPay(BmsShipBillHeaderModel headerModel) {
        if (BmsConstant.FEE_CLT_TYPE_LOADING_BILL.equals(headerModel.getPayFeeCltType())) {
            throw new BizException("派车单计费不支持运单支出核算");
        }
        checkPayCalculate(headerModel.getShipbillNo());
        calPayShipBill(headerModel);
//        if (BmsConstant.TMS_DOWN.equals(headerModel.getSource())) {
//            loadingBillService.rePayCalculate(headerModel.getId());
//        } else {
//            calPayShipBill(headerModel);
//        }
        updatePayShipBillFee(headerModel.getShipbillNo());
    }

    /**
     * submitIncome
     * @param headerModel
     */
    private void submitIncome(BmsShipBillHeaderModel headerModel) {
        if (BmsConstant.FEE_CLT_TYPE_LOADING_BILL.equals(headerModel.getFeeCltType())) {
            throw new BizException("派车单计费不支持运单收入提交");
        }
        checkIncomeCheckStatus(headerModel.getShipbillNo());
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        List<BmsBillIncomeFeeHeaderModel> incomeFeeHeaderModelList = getIncomeByShipBill(headerModel.getShipbillNo(), user.getEnterpriseId());
        if (CollectionUtil.isNotEmpty(incomeFeeHeaderModelList)) {
            BmsBillIncomeFeeHeaderModel incomeFeeHeaderModel = incomeFeeHeaderModelList.get(0);
            if (BmsConstant.COST_STATUS_FAILED.equals(incomeFeeHeaderModel.getCostStatus())) {
                throw new BizException("计费失败，不能提交");
            }
            if (!BmsConstant.SETTLEMENT_STATUS_1.equals(incomeFeeHeaderModel.getSettlementStatus())) {
                throw new BizException("不为核算待提交，不能提交");
            }
            incomeFeeHeaderModel.setSettlementStatus(BmsConstant.SETTLEMENT_STATUS_3);
            incomeFeeHeaderModel.setSettlementDate(DateUtil.date());
            incomeFeeHeaderModel.setUpdateperson(user.getNickname());
            incomeFeeHeaderModel.setUpdatetime(DateUtil.date());
            incomeFeeHeaderMapper.update(incomeFeeHeaderModel);
            logService.addLog(LogTypeEnum.SHIP_BILL, headerModel.getShipbillNo(), "收入提交");

            if (ObjectUtil.isNotNull(headerModel.getLoadingId())) {
                Criteria criteria = Criteria.forClass(BmsBillIncomeFeeHeaderModel.class);
                Restriction r1 = Restrictions.eq(BmsBillIncomeFeeHeaderModel::getBillId, headerModel.getLoadingId());
                Restriction r2 = Restrictions.eq(BmsBillIncomeFeeHeaderModel::getBillType, 20);
                Restriction r3 = Restrictions.eq(BmsBillIncomeFeeHeaderModel::getEnterpriseId, headerModel.getEnterpriseId());
                criteria.setRestriction(Restrictions.and(r1, r2, r3));
                List<BmsBillIncomeFeeHeaderModel> bmsBillIncomeFeeHeaderModelList = incomeFeeHeaderMapper.findByCriteria(criteria);
                if (CollectionUtil.isNotEmpty(bmsBillIncomeFeeHeaderModelList)) {
                    bmsBillIncomeFeeHeaderModelList.forEach(bmsBillIncomeFeeHeaderModel -> {
                        bmsBillIncomeFeeHeaderModel.setSettlementStatus(BmsConstant.SETTLEMENT_STATUS_3);
                        bmsBillIncomeFeeHeaderModel.setUpdateperson(user.getNickname());
                        bmsBillIncomeFeeHeaderModel.setUpdatetime(DateUtil.date());
                        incomeFeeHeaderMapper.update(bmsBillIncomeFeeHeaderModel);
                    });
                }
            }
        }
    }

    /**
     * submitPay
     * @param headerModel
     */
    private void submitPay(BmsShipBillHeaderModel headerModel) {
        if (BmsConstant.FEE_CLT_TYPE_LOADING_BILL.equals(headerModel.getPayFeeCltType())) {
            throw new BizException("派车单计费不支持运单支出提交");
        }
        checkPayCheckStatus(headerModel.getShipbillNo());
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        List<BmsBillPayFeeHeaderModel> payFeeHeaderModelList = getPayByShipBill(headerModel.getShipbillNo(), headerModel.getEnterpriseId());
        if (CollectionUtil.isNotEmpty(payFeeHeaderModelList)) {
            BmsBillPayFeeHeaderModel payFeeHeaderModel = payFeeHeaderModelList.get(0);
            if (BmsConstant.COST_STATUS_FAILED.equals(payFeeHeaderModel.getCostStatus())) {
                throw new BizException("计费失败，不能提交");
            }
            if (!BmsConstant.SETTLEMENT_STATUS_1.equals(payFeeHeaderModel.getSettlementStatus())) {
                throw new BizException("不为核算待提交，不能提交");
            }
            payFeeHeaderModel.setSettlementStatus(BmsConstant.SETTLEMENT_STATUS_3);
            payFeeHeaderModel.setSettlementDate(DateUtil.date());
            payFeeHeaderModel.setUpdateperson(user.getNickname());
            payFeeHeaderModel.setUpdatetime(DateUtil.date());
            payFeeHeaderMapper.update(payFeeHeaderModel);
            logService.addLog(LogTypeEnum.SHIP_BILL, headerModel.getShipbillNo(), "支出提交");

            if (ObjectUtil.isNotNull(headerModel.getLoadingId())) {
                Criteria criteria = Criteria.forClass(BmsBillPayFeeHeaderModel.class);
                Restriction r1 = Restrictions.eq(BmsBillPayFeeHeaderModel::getBillId, headerModel.getLoadingId());
                Restriction r2 = Restrictions.eq(BmsBillPayFeeHeaderModel::getBillType, 20);
                Restriction r3 = Restrictions.eq(BmsBillPayFeeHeaderModel::getEnterpriseId, headerModel.getEnterpriseId());
                criteria.setRestriction(Restrictions.and(r1, r2, r3));
                List<BmsBillPayFeeHeaderModel> bmsBillPayFeeHeaderModelList = payFeeHeaderMapper.findByCriteria(criteria);
                if (CollectionUtil.isNotEmpty(bmsBillPayFeeHeaderModelList)) {
                    bmsBillPayFeeHeaderModelList.forEach(bmsBillPayFeeHeaderModel -> {
                        bmsBillPayFeeHeaderModel.setSettlementStatus(BmsConstant.SETTLEMENT_STATUS_3);
                        bmsBillPayFeeHeaderModel.setUpdateperson(user.getNickname());
                        bmsBillPayFeeHeaderModel.setUpdatetime(DateUtil.date());
                        payFeeHeaderMapper.update(bmsBillPayFeeHeaderModel);
                    });
                }
            }
        }
    }

    /**
     * checkIncomeCheckStatus
     * @param shipBillNo
     */
    private void checkIncomeCheckStatus(String shipBillNo) {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        List<BmsBillIncomeFeeHeaderModel> modelList = getIncomeByShipBill(shipBillNo, user.getEnterpriseId());
        if (CollectionUtil.isNotEmpty(modelList)) {
            BmsBillIncomeFeeHeaderModel model = modelList.get(0);
            if (!BmsConstant.CHECK_STATUS_0.equals(model.getCheckStatus())) {
                throw new BizException("运单"+shipBillNo+"已收入结算！");
            }
        }
    }

    /**
     * checkPayCheckStatus
     * @param shipBillNo
     */
    private void checkPayCheckStatus(String shipBillNo) {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        List<BmsBillPayFeeHeaderModel> modelList = getPayByShipBill(shipBillNo, user.getEnterpriseId());
        if (CollectionUtil.isNotEmpty(modelList)) {
            BmsBillPayFeeHeaderModel model = modelList.get(0);
            if (!BmsConstant.CHECK_STATUS_0.equals(model.getCheckStatus())) {
                throw new BizException("运单"+shipBillNo+"已支出结算！");
            }
        }
    }

    /**
     * getDetail
     * @param shipBillNo
     * @return
     */
    private List<BmsShipBillDetailModel> getDetailModel(String shipBillNo) {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        Criteria criteria = Criteria.forClass(BmsShipBillDetailModel.class);
        Restriction r1 = Restrictions.eq(BmsShipBillDetailModel::getShipbillNo, shipBillNo);
        Restriction r2 = Restrictions.eq(BmsShipBillDetailModel::getEnterpriseId, user.getEnterpriseId());
        criteria.setRestriction(Restrictions.and(r1, r2));
        return shipBillDetailMapper.findByCriteria(criteria);
    }

    /**
     * getPackage
     * @param shipBillNo
     * @return
     */
    private List<BmsShipBillPackageModel> getPackageModel(String shipBillNo) {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        Criteria criteria = Criteria.forClass(BmsShipBillPackageModel.class);
        Restriction r1 = Restrictions.eq(BmsShipBillPackageModel::getShipbillNo, shipBillNo);
        Restriction r2 = Restrictions.eq(BmsShipBillPackageModel::getEnterpriseId, user.getEnterpriseId());
        criteria.setRestriction(Restrictions.and(r1, r2));
        return shipBillPackageMapper.findByCriteria(criteria);
    }
}
