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

import cn.hutool.core.bean.BeanUtil;
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.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.prolog.common.util.ToolKits;
import com.prolog.framework.core.exception.BizException;
import com.prolog.framework.core.restriction.*;
import com.prolog.product.core.framework.entity.UserEntity;
import com.prolog.product.core.framework.util.PlgFxUsrUtils;
import com.prolog.rdc.tms.app.constant.DataDictionaryConstant;
import com.prolog.rdc.tms.app.constant.SeriaNnumberConstant;
import com.prolog.rdc.tms.app.constant.enums.*;
import com.prolog.rdc.tms.app.dao.mapper.*;
import com.prolog.rdc.tms.app.model.dto.business.*;
import com.prolog.rdc.tms.app.model.entity.*;
import com.prolog.rdc.tms.app.model.vo.business.*;
import com.prolog.rdc.tms.app.proxy.MainDataProxy;
import com.prolog.rdc.tms.app.service.business.*;
import com.prolog.rdc.tms.app.util.BusinessFlowUtil;
import com.prolog.rdc.tms.app.util.ConvertorUtil;
import com.prolog.rdc.tms.model.dto.basicData.ItemCheckDTO;
import com.prolog.rdc.tms.model.entity.SysRefdatadModel;
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 java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author hongbo.pan
 * @date 2022/12/7
 */
@Slf4j
@Service
public class LoadingScanServiceImpl implements LoadingScanService {

    @Autowired
    private TmsLoadingBillDetailMapper tmsLoadingBillDetailMapper;

    @Autowired
    private TmsLoadingBillHeaderMapper tmsLoadingBillHeaderMapper;

    @Autowired
    private TmsShipbillHeaderMapper tmsShipbillHeaderMapper;

    @Autowired
    private TmsShipbillDetailMapper tmsShipbillDetailMapper;

    @Autowired
    private TmsAppointmentDetailMapper tmsAppointmentDetailMapper;

    @Autowired
    private TmsAppointmentHeaderMapper tmsAppointmentHeaderMapper;

    @Autowired
    private MainDataProxy mainDataProxy;

    @Autowired
    private ShipbillOperateLogService shipbillOperateLogService;

    @Autowired
    private ShipbillNodeTrackingService shipbillNodeTrackingService;

    @Autowired
    private LoadingBillService loadingBillService;

    @Autowired
    private BusinessFlowUtil businessFlowUtil;

    @Autowired
    private ConvertorUtil convertorUtil;

    @Autowired
    private TmsShipbillDetailScanMapper tmsShipbillDetailScanMapper;

    @Autowired
    private TmsShipbillTransportLogMapper tmsShipbillTransportLogMapper;

    @Autowired
    private BookingService bookingService;

    /**
     * 获取月台扫描信息
     *
     * @param vo
     * @return
     */
    @Override
    public List<LoadingScanPlatformDTO> getPlatformScanInfo(LoadingScanQueryVO vo) {
        List<String> platformList = tmsLoadingBillDetailMapper.getPlatform(vo);
        List<LoadingScanPlatformDTO> list = Lists.newArrayList();
        if (ObjectUtil.isEmpty(platformList)) {
            return list;
        }
        List<String> platformList2 = Lists.newArrayList();
        platformList.stream().forEach(platform -> {
            Arrays.stream(platform.split(",")).forEach(p -> {
                platformList2.add(p);
            });
        });
        switch (vo.getScanLoadingMethod()) {
            case DataDictionaryConstant.SCANLOADING_METHED_LOADINGBILL_ITEM:
                list = getPlatformItemScanInfo(vo, platformList2);
                break;
            default:
                list = platformList2.stream().distinct().flatMap(platform -> Arrays.stream(platform.split(","))).map(s -> {
                    LoadingScanPlatformDTO dto = new LoadingScanPlatformDTO();
                    dto.setPlatformName(s);
                    vo.setPlatform(s);
                    dto.setLoadingScanShipBillDTO(getShipBillScanInfo(vo));
                    return dto;
                }).collect(Collectors.toList());
                break;
        }
        return list;
    }

    /**
     * 获取月台商品扫描信息
     *
     * @param vo
     * @return
     */
    public List<LoadingScanPlatformDTO> getPlatformItemScanInfo(LoadingScanQueryVO vo, List<String> platformList) {
        List<LoadingScanPlatformDTO> list = Lists.newArrayList();

        list = platformList.stream().distinct().map(s -> {
            LoadingScanPlatformDTO dto = new LoadingScanPlatformDTO();
            dto.setPlatformName(s);
            vo.setPlatform(s);
            dto.setLoadingScanShipBillDTO(getShipBillDetailScanInfo(vo));
            dto.setConfirmStatus(dto.getLoadingScanShipBillDTO().getConfirmStatus());
            return dto;
        }).collect(Collectors.toList());
        return list;
    }

    /**
     * 获取派车单扫描信息
     *
     * @param vo
     * @return
     */
    @Override
    public LoadingScanLoadingBillDTO getLoadingBillScanInfo(LoadingScanQueryVO vo) {
        vo.setScanStatus(DataDictionaryConstant.SCAN_STATUS_INIT);
        List<String> unScanLoadingBillIdList = tmsLoadingBillDetailMapper.getLoadingScanLoadingBill(vo);
        vo.setScanStatus(DataDictionaryConstant.SCAN_STATUS_LOADED);
        List<String> scannedLoadingBillIdList = tmsLoadingBillDetailMapper.getLoadingScanLoadingBill(vo);
        LoadingScanLoadingBillDTO dto = new LoadingScanLoadingBillDTO();
        List<String> allIdList = Lists.newArrayList();
        List<LoadingScanLoadingBillInfoDTO> allList = Lists.newArrayList();
        if (CollectionUtil.isNotEmpty(unScanLoadingBillIdList)) {
            dto.setUnScanLoadingBillIdList(unScanLoadingBillIdList);
            dto.setUnScan(unScanLoadingBillIdList.size());
            allIdList.addAll(unScanLoadingBillIdList);
            dto.setUnScanLoadingBillList(getLoadingScanLoadingBillInfoDTOList(unScanLoadingBillIdList));
            allList.addAll(dto.getUnScanLoadingBillList());
        } else {
            dto.setUnScan(0);
        }
        if (CollectionUtil.isNotEmpty(scannedLoadingBillIdList)) {
            dto.setScannedLoadingBillIdList(scannedLoadingBillIdList);
            dto.setScanned(scannedLoadingBillIdList.size());
            allIdList.addAll(scannedLoadingBillIdList);
            dto.setScannedLoadingBillList(getLoadingScanLoadingBillInfoDTOList(scannedLoadingBillIdList));
            allList.addAll(dto.getScannedLoadingBillList());
        } else {
            dto.setScanned(0);
        }
        dto.setTotalScanLoadingBillIdList(allIdList);
        dto.setTotalScan(allIdList.size());
        dto.setTotalScanLoadingBillList(allList);
        return dto;
    }

    /**
     * 获取运单扫描信息
     *
     * @param vo
     * @return
     */
    @Override
    public LoadingScanShipBillDTO getShipBillScanInfo(LoadingScanQueryVO vo) {
        LoadingScanShipBillDTO dto = new LoadingScanShipBillDTO();
        vo.setScanStatus(DataDictionaryConstant.SCAN_STATUS_INIT);
        List<String> unScanPlatformShipBillList = tmsLoadingBillDetailMapper.getLoadingScanShipBill(vo);
        vo.setScanStatus(DataDictionaryConstant.SCAN_STATUS_LOADED);
        List<String> scanPlatformShipBillList = tmsLoadingBillDetailMapper.getLoadingScanShipBill(vo);
        List<String> allIdList = Lists.newArrayList();
        List<LoadingScanShipBillInfoDTO> allList = Lists.newArrayList();
        if (CollectionUtil.isNotEmpty(unScanPlatformShipBillList)) {
            dto.setUnScanShipBillIdList(unScanPlatformShipBillList);
            dto.setUnScan(unScanPlatformShipBillList.size());
            allIdList.addAll(unScanPlatformShipBillList);
            dto.setUnScanShipBillList(getLoadingScanShipBillInfoDTOList(unScanPlatformShipBillList, vo));
            allList.addAll(dto.getUnScanShipBillList());
        } else {
            dto.setUnScan(0);
        }
        if (CollectionUtil.isNotEmpty(scanPlatformShipBillList)) {
            dto.setScannedShipBillIdList(scanPlatformShipBillList);
            dto.setScanned(scanPlatformShipBillList.size());
            allIdList.addAll(scanPlatformShipBillList);
            dto.setScannedShipBillList(getLoadingScanShipBillInfoDTOList(scanPlatformShipBillList, vo));
            allList.addAll(dto.getScannedShipBillList());
        } else {
            dto.setScanned(0);
        }
        dto.setTotalScanShipBillIdList(allIdList);
        dto.setTotalScan(allIdList.size());
        dto.setTotalScanShipBillList(allList);
        return dto;
    }

    /**
     * 扫描单号
     *
     * @param vo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public LoadingScanInfoDTO scanCode(LoadingScanCodeVO vo) {
        LoadingScanInfoDTO dto;
        String scanLoadingMethod = mainDataProxy.getSystemParamByCode(DataDictionaryConstant.SCANLOADING_METHED);
        if (DataDictionaryConstant.SCANLOADING_METHED_LOADINGBILL_SHIPBILL.equals(scanLoadingMethod)) {
            TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel = tmsLoadingBillHeaderMapper.findById(vo.getBillCode(), TmsLoadingBillHeaderModel.class);
            if (ObjectUtil.isNotNull(tmsLoadingBillHeaderModel)) {
                dto = scanLoadingBill(vo, tmsLoadingBillHeaderModel, scanLoadingMethod);
            } else {
                dto = scanShipBill(vo);
                updateLoadingTime(vo.getBillCode(), DateUtil.date(), null);
            }
        } else if (DataDictionaryConstant.SCANLOADING_METHED_SHIPBILL.equals(scanLoadingMethod)) {
            dto = scanShipBill(vo);
            updateLoadingTime(vo.getBillCode(), DateUtil.date(), null);
        } else if (DataDictionaryConstant.SCANLOADING_METHED_LOADINGBILL.equals(scanLoadingMethod)) {
            dto = scanLoadingBillOnly(vo);
            updateLoadingTime(vo.getBillCode(), DateUtil.date(), null);
        } else if (DataDictionaryConstant.SCANLOADING_METHED_LOADINGBILL_ITEM.equals(scanLoadingMethod)) {
            TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel = tmsLoadingBillHeaderMapper.findById(vo.getBillCode(), TmsLoadingBillHeaderModel.class);
            if (ObjectUtil.isNotNull(tmsLoadingBillHeaderModel)) {
                dto = scanLoadingBill(vo, tmsLoadingBillHeaderModel, scanLoadingMethod);
            } else {
                dto = scanShipBillDetail(vo);
                dto.getShipBillInfoDTOList().stream()
                   .map(LoadingScanShipBillInfoDTO::getShipbillId)
                   .collect(Collectors.toList())
                   .forEach(shipbillId -> {
                       updateLoadingTime(shipbillId, DateUtil.date(), null);
                   });
            }
        } else {
            throw new BizException("不支持的装车扫描类型");
        }
        return dto;
    }

    /**
     * 装车确认
     *
     * @param confirmVO
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public LoadingScanConfirmDTO scanConfirm(LoadingScanConfirmVO confirmVO) {
        ToolKits.isParamNull(confirmVO, "请求不为空");
        //ToolKits.isParamNull(confirmVO.getContainerWithVehicle(), "容器是否随车不为空");

        UserEntity user = PlgFxUsrUtils.getUserEntity();
        LoadingScanConfirmDTO dto = new LoadingScanConfirmDTO();
        dto.setType("3");
        LoadingScanQueryVO vo = BeanUtil.copyProperties(confirmVO, LoadingScanQueryVO.class);
        vo.setScanStatus(DataDictionaryConstant.SCAN_STATUS_LOADED);
        List<String> scannedLoadingBillIdList = tmsLoadingBillDetailMapper.getLoadingScanLoadingBill(vo);
        if (CollectionUtil.isEmpty(scannedLoadingBillIdList)) {
            return dto;
        }
        vo.setScanStatus(DataDictionaryConstant.SCAN_STATUS_INIT);
        vo.setLoadingBillIdList(scannedLoadingBillIdList);
        List<String> unScanShipBillIdList = tmsLoadingBillDetailMapper.getLoadingUnScanShipBill(vo);
        if (CollectionUtil.isNotEmpty(unScanShipBillIdList)) {
            dto.setType("1");
            dto.setUnScanShipBillIdList(unScanShipBillIdList);
            return dto;
        }
        List<TmsLoadingBillHeaderModel> tmsLoadingBillHeaderModelList = tmsLoadingBillHeaderMapper.findByIds(TmsLoadingBillHeaderModel.class, scannedLoadingBillIdList.toArray(),
                null);
        String relationThirdSystem = mainDataProxy.getSystemParamByCode(RelationThirdSystemEnum.ENUM_NAME);
        if (relationThirdSystem.contains(RelationThirdSystemEnum.TEMPERATURE.getCode()) || relationThirdSystem.contains(RelationThirdSystemEnum.CONTAINER.getCode())) {
            if (StrUtil.isBlank(confirmVO.getContainerId()) &&
                    tmsLoadingBillHeaderModelList.stream().anyMatch(tmsLoadingBillHeaderModel -> tmsLoadingBillHeaderModel.getColdShipbillNumber() > 0L &&
                            StrUtil.isBlank(tmsLoadingBillHeaderModel.getContainerId()))) {
                dto.setType("2");
                List<SysRefdatadModel> dicData = convertorUtil.getDictionary(new String[]{
                        DataDictionaryConstant.VEHICLE_TYPE_CATEGORY// 车辆类别
                });
                dto.setVehicleDeviceId(tmsLoadingBillHeaderModelList.stream().filter(tmsLoadingBillHeaderModel ->
                        StrUtil.isNotBlank(tmsLoadingBillHeaderModel.getVehicleDeviceId())).flatMap(tmsLoadingBillHeaderModel ->
                        Arrays.stream(tmsLoadingBillHeaderModel.getVehicleDeviceId().split(","))).distinct().collect(Collectors.joining(",")));
                dto.setVehicleDeviceCode(tmsLoadingBillHeaderModelList.stream().filter(tmsLoadingBillHeaderModel ->
                        StrUtil.isNotBlank(tmsLoadingBillHeaderModel.getVehicleDeviceCode())).flatMap(tmsLoadingBillHeaderModel ->
                        Arrays.stream(tmsLoadingBillHeaderModel.getVehicleDeviceCode().split(","))).distinct().collect(Collectors.joining(",")));
                dto.setVehicleDeviceName(tmsLoadingBillHeaderModelList.stream().filter(tmsLoadingBillHeaderModel ->
                        StrUtil.isNotBlank(tmsLoadingBillHeaderModel.getVehicleDeviceName())).flatMap(tmsLoadingBillHeaderModel ->
                        Arrays.stream(tmsLoadingBillHeaderModel.getVehicleDeviceName().split(","))).distinct().collect(Collectors.joining(",")));
                dto.setContainerId(tmsLoadingBillHeaderModelList.stream().filter(tmsLoadingBillHeaderModel ->
                        StrUtil.isNotBlank(tmsLoadingBillHeaderModel.getContainerId())).flatMap(tmsLoadingBillHeaderModel ->
                        Arrays.stream(tmsLoadingBillHeaderModel.getContainerId().split(","))).distinct().collect(Collectors.joining(",")));
                dto.setContainerCode(tmsLoadingBillHeaderModelList.stream().filter(tmsLoadingBillHeaderModel ->
                        StrUtil.isNotBlank(tmsLoadingBillHeaderModel.getContainerCode())).flatMap(tmsLoadingBillHeaderModel ->
                        Arrays.stream(tmsLoadingBillHeaderModel.getContainerCode().split(","))).distinct().collect(Collectors.joining(",")));
                dto.setContainerName(tmsLoadingBillHeaderModelList.stream().filter(tmsLoadingBillHeaderModel ->
                        StrUtil.isNotBlank(tmsLoadingBillHeaderModel.getContainerName())).flatMap(tmsLoadingBillHeaderModel ->
                        Arrays.stream(tmsLoadingBillHeaderModel.getContainerName().split(","))).distinct().collect(Collectors.joining(",")));
                dto.setVehicleTypeCategory(tmsLoadingBillHeaderModelList.stream().filter(tmsLoadingBillHeaderModel ->
                        StrUtil.isNotBlank(tmsLoadingBillHeaderModel.getVehicleTypeCategory())).map(TmsLoadingBillHeaderModel::getVehicleTypeCategory).distinct().collect(Collectors.joining(",")));
                dto.setVehicleTypeCategoryName(ConvertorUtil.getName(dicData, DataDictionaryConstant.VEHICLE_TYPE_CATEGORY, dto.getVehicleTypeCategory()));
                return dto;
            }
        }
        shipbillDetailConfirm(confirmVO);
        // 装车确认
        tmsLoadingBillHeaderModelList.forEach(tmsLoadingBillHeaderModel -> {
            tmsLoadingBillHeaderModel.setStatus(DataDictionaryConstant.LOADING_BILL_STATUS_ZC_CONFIRM);
            tmsLoadingBillHeaderModel.setContainerWithVehicle(confirmVO.getContainerWithVehicle());
            tmsLoadingBillHeaderModel.setUpdateperson(user.getNickname());
            tmsLoadingBillHeaderModel.setUpdatetime(new Date());
            if (StrUtil.isNotBlank(confirmVO.getVehicleTypeCategory())) {
                tmsLoadingBillHeaderModel.setVehicleTypeCategory(confirmVO.getVehicleTypeCategory());
            }
            if (StrUtil.isNotBlank(confirmVO.getVehicleDeviceId())) {
                tmsLoadingBillHeaderModel.setVehicleDeviceId(confirmVO.getVehicleDeviceId());
                tmsLoadingBillHeaderModel.setVehicleDeviceCode(confirmVO.getVehicleDeviceCode());
                tmsLoadingBillHeaderModel.setVehicleDeviceName(confirmVO.getVehicleDeviceName());
            }
            if (StrUtil.isNotBlank(confirmVO.getContainerId())) {
                tmsLoadingBillHeaderModel.setContainerId(confirmVO.getContainerId());
                tmsLoadingBillHeaderModel.setContainerCode(confirmVO.getContainerCode());
                tmsLoadingBillHeaderModel.setContainerName(confirmVO.getContainerName());
            }
            tmsLoadingBillHeaderModel.setLoadingEndDate(DateUtil.date());
            tmsLoadingBillHeaderMapper.update(tmsLoadingBillHeaderModel);

            updateLoadingTime(tmsLoadingBillHeaderModel.getLoadingBillId(), null, DateUtil.date());
        });
        Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
        Restriction restriction = Restrictions.in("loadingBillId", tmsLoadingBillHeaderModelList.stream()
                                                                                                .map(TmsLoadingBillHeaderModel::getLoadingBillId).collect(Collectors.toList()));
        criteria.setRestriction(restriction);
        List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModelList = tmsLoadingBillDetailMapper.findByCriteria(criteria);
        if (CollectionUtil.isNotEmpty(tmsLoadingBillDetailModelList)) {
            List<String> shipBillIdList = tmsLoadingBillDetailModelList.stream().map(TmsLoadingBillDetailModel::getShipbillId)
                                                                       .distinct().collect(Collectors.toList());
            List<TmsShipbillHeaderModel> tmsShipbillHeaderModelList = tmsShipbillHeaderMapper.findByIds(TmsShipbillHeaderModel.class,
                    shipBillIdList.toArray(), null);
            tmsShipbillHeaderModelList.forEach(tmsShipbillHeaderModel -> updateShipBillScanConfirm(tmsShipbillHeaderModel, confirmVO));
            dto.setScanShipBillIdList(shipBillIdList);
        }
        if (ObjectUtil.isNotEmpty(dto.getScanShipBillIdList())) {
            allScanConfirm(dto);
        }
        return dto;
    }

    /**
     * 运单剔除
     *
     * @param confirmVO
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void shipBillOut(LoadingScanConfirmVO confirmVO) {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        LoadingScanQueryVO vo = BeanUtil.copyProperties(confirmVO, LoadingScanQueryVO.class);
        vo.setScanStatus(DataDictionaryConstant.SCAN_STATUS_LOADED);
        List<String> scannedLoadingBillIdList = tmsLoadingBillDetailMapper.getLoadingScanLoadingBill(vo);
        if (CollectionUtil.isNotEmpty(scannedLoadingBillIdList)) {
            vo.setScanStatus(DataDictionaryConstant.SCAN_STATUS_INIT);
            vo.setLoadingBillIdList(scannedLoadingBillIdList);
            List<String> unScanShipBillIdList = tmsLoadingBillDetailMapper.getLoadingUnScanShipBill(vo);
            if (CollectionUtil.isNotEmpty(unScanShipBillIdList)) {
                List<TmsShipbillHeaderModel> tmsShipbillHeaderModelList = tmsShipbillHeaderMapper.findByIds(TmsShipbillHeaderModel.class, unScanShipBillIdList.toArray(), null);
                List<String> loadingBillIdList = Lists.newArrayList();
                tmsShipbillHeaderModelList.forEach(tmsShipbillHeaderModel -> {
                    Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
                    Restriction restriction = Restrictions.eq("shipbillId", tmsShipbillHeaderModel.getShipbillId());
                    criteria.setRestriction(restriction);
                    List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModelList = tmsLoadingBillDetailMapper.findByCriteria(criteria);
                    tmsLoadingBillDetailMapper.deleteByIds(tmsLoadingBillDetailModelList.stream().map(TmsLoadingBillDetailModel::getId).toArray(), TmsLoadingBillDetailModel.class);
                    tmsShipbillHeaderModel.setUpdatetime(new Date());
                    tmsShipbillHeaderModel.setUpdateperson(user.getNickname());
                    tmsShipbillHeaderModel.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_REVIEW);
                    tmsShipbillHeaderMapper.update(tmsShipbillHeaderModel);

                    // 运单节点回退
                    ShipbillNodeTrackingRollbackVO shipbillNodeTrackingRollbackVO = new ShipbillNodeTrackingRollbackVO();
                    shipbillNodeTrackingRollbackVO.setShipbillId(tmsShipbillHeaderModel.getShipbillId());
                    shipbillNodeTrackingRollbackVO.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_REVIEW);
                    shipbillNodeTrackingService.rollbackShipbillNodeTracking(shipbillNodeTrackingRollbackVO);

                    // 运单日志保存
                    ShipbillOperateLogSaveNewVO shipbillOperateLogSaveNewVO = new ShipbillOperateLogSaveNewVO();
                    shipbillOperateLogSaveNewVO.setShipbillId(tmsShipbillHeaderModel.getShipbillId());
                    shipbillOperateLogSaveNewVO.setShipbillNo(tmsShipbillHeaderModel.getShipbillId());
                    shipbillOperateLogSaveNewVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_ZC_CONFIRM);
                    shipbillOperateLogSaveNewVO.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_ZC_SCAN);
                    shipbillOperateLogSaveNewVO.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_REVIEW);
                    shipbillOperateLogSaveNewVO.setOperateDate(new Date());
                    shipbillOperateLogSaveNewVO.setEnterpriseId(user.getEnterpriseId());
                    shipbillOperateLogSaveNewVO.setEnterpriseName(user.getEnterpriseName());
                    shipbillOperateLogSaveNewVO.setUserId(user.getUserid());
                    shipbillOperateLogSaveNewVO.setUserName(user.getNickname());
                    shipbillOperateLogService.addShipbillOperateLogNewData(shipbillOperateLogSaveNewVO);
                    loadingBillIdList.addAll(tmsLoadingBillDetailModelList.stream().map(TmsLoadingBillDetailModel::getLoadingBillId).distinct().collect(Collectors.toList()));
                });
                bookingService.cancelAppointment(unScanShipBillIdList);
                loadingBillService.reCalLoadingBill(loadingBillIdList);
            }
        }
    }


    /**
     * 修改派车单装车扫描状态
     *
     * @param tmsLoadingBillHeaderModel
     */
    private void updateLoadingBillScan(TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel) {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        tmsLoadingBillHeaderModel.setScanStatus(DataDictionaryConstant.SCAN_STATUS_LOADED);
        tmsLoadingBillHeaderModel.setStatus(DataDictionaryConstant.LOADING_BILL_STATUS_SCAN);
        tmsLoadingBillHeaderModel.setUpdateperson(user.getNickname());
        tmsLoadingBillHeaderModel.setUpdatetime(new Date());
        tmsLoadingBillHeaderModel.setLoadingStartDate(DateUtil.date());
        tmsLoadingBillHeaderMapper.update(tmsLoadingBillHeaderModel);
    }

    /**
     * 修改运单装车扫描状态
     *
     * @param tmsShipbillHeaderModel
     */
    private void updateShipBillScan(TmsShipbillHeaderModel tmsShipbillHeaderModel) {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        tmsShipbillHeaderModel.setScanStatus(DataDictionaryConstant.SCAN_STATUS_LOADED);
        tmsShipbillHeaderModel.setUpdateperson(user.getNickname());
        tmsShipbillHeaderModel.setUpdatetime(new Date());
        tmsShipbillHeaderMapper.update(tmsShipbillHeaderModel);
        // 更新装车扫描状态 为已装车扫描
        Map<String, Object> mapUpdate = Maps.newHashMap();
        mapUpdate.put("scanStatus", DataDictionaryConstant.SCAN_STATUS_LOADED);
        mapUpdate.put("updateperson", user.getNickname());
        mapUpdate.put("updatetime", new Date());
        Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
        Restriction r1 = Restrictions.eq(TmsLoadingBillDetailModel::getEnterpriseId, user.getEnterpriseId());
        Restriction r2 = Restrictions.eq(TmsLoadingBillDetailModel::getShipbillId, tmsShipbillHeaderModel.getShipbillId());
        criteria.setRestriction(Restrictions.and(r1, r2));
        tmsLoadingBillDetailMapper.updateMapByCriteria(mapUpdate, criteria);
        shipBillLog(tmsShipbillHeaderModel, DataDictionaryConstant.SHIPBILL_STATUSNAME_ZC_SCAN, tmsShipbillHeaderModel.getStatus(), tmsShipbillHeaderModel.getStatus());
        //递归更新父级运单扫描状态
        String fatherShipBillId = tmsShipbillHeaderModel.getFatherShipbillId();
        while (StrUtil.isNotBlank(fatherShipBillId)) {
            TmsShipbillHeaderModel fatherShipBill =
                    tmsShipbillHeaderMapper.findById(fatherShipBillId, TmsShipbillHeaderModel.class);
            if (ObjectUtil.isNotNull(fatherShipBill)) {
                List<TmsShipbillHeaderModel> childShipBillList = getChildTmsShipBillHeaderModel(fatherShipBillId);
                if (childShipBillList.stream().allMatch(childShipBill -> DataDictionaryConstant.SCAN_STATUS_LOADED.equals(childShipBill.getScanStatus()))) {
                    fatherShipBill.setScanStatus(DataDictionaryConstant.SCAN_STATUS_LOADED);
                    fatherShipBill.setUpdateperson(user.getNickname());
                    fatherShipBill.setUpdatetime(new Date());
                    tmsShipbillHeaderMapper.update(fatherShipBill);
                    shipBillLog(fatherShipBill, DataDictionaryConstant.SHIPBILL_STATUSNAME_ZC_SCAN, fatherShipBill.getStatus(), fatherShipBill.getStatus());
                }
                fatherShipBillId = fatherShipBill.getFatherShipbillId();
            } else {
                fatherShipBillId = StrUtil.EMPTY;
            }
        }
    }

    /**
     * 修改运单明细装车扫描状态
     *
     * @param tmsShipbillHeaderModel
     */
    private void updateShipBillDetailScan(TmsShipbillHeaderModel tmsShipbillHeaderModel, LoadingScanCodeVO vo) {
        UserEntity user = PlgFxUsrUtils.getUserEntity();

        Criteria criteriaShipbillDetail = Criteria.forClass(TmsShipbillDetailModel.class);
        Restriction r11 = Restrictions.eq(TmsShipbillDetailModel::getEnterpriseId, user.getEnterpriseId());
        Restriction r12 = Restrictions.eq(TmsShipbillDetailModel::getShipbillId, tmsShipbillHeaderModel.getShipbillId());
        Restriction r13 = Restrictions.eq(TmsShipbillDetailModel::getItemCode, vo.getBillCode());
        Restriction r14 = Restrictions.eq(TmsShipbillDetailModel::getScanStatus, DataDictionaryConstant.SCAN_STATUS_INIT);
        criteriaShipbillDetail.setRestriction(Restrictions.and(r11, r12, r13, r14));
        List<TmsShipbillDetailModel> shipbillDetailModels = tmsShipbillDetailMapper.findByCriteria(criteriaShipbillDetail);
        for (TmsShipbillDetailModel detail : shipbillDetailModels) {
            TmsShipbillDetailScanModel detailScanModel = new TmsShipbillDetailScanModel();
            String id = mainDataProxy.getCodeNumberByCode(SeriaNnumberConstant.TMS_SHIPBILL_DETAIL_SCAN_ID);
            detailScanModel.setId(id);
            detailScanModel.setLoadingBillNo(vo.getLoadingBillNo());
            detailScanModel.setShipbillId(tmsShipbillHeaderModel.getShipbillId());
            detailScanModel.setShipbillNo(tmsShipbillHeaderModel.getShipbillNo());
            detailScanModel.setShipbillDetailId(detail.getId());
            detailScanModel.setItemId(detail.getItemId());
            detailScanModel.setItemCode(detail.getItemCode());
            detailScanModel.setItemName(detail.getItemName());
            detailScanModel.setConfirmStatus(10);
            detailScanModel.setScanStatus(20);
            detailScanModel.setPcs(detail.getPcs());
            detailScanModel.setScannedPcs(BigDecimal.ZERO);
            detailScanModel.setStagingLocation(vo.getPlatformName());
            detailScanModel.setCreateperson(user.getNickname());
            detailScanModel.setCreatetime(DateUtil.date());
            tmsShipbillDetailScanMapper.save(detailScanModel);

            detail.setScanStatus(DataDictionaryConstant.SCAN_STATUS_LOADED);
            detail.setUpdateperson(user.getNickname());
            detail.setUpdatetime(new Date());
            tmsShipbillDetailMapper.update(detail);

            shipBillLog(tmsShipbillHeaderModel, "商品" + detail.getItemCode() + DataDictionaryConstant.SHIPBILL_STATUSNAME_ZC_SCAN, tmsShipbillHeaderModel.getStatus(),
                    tmsShipbillHeaderModel.getStatus());
        }
    }

    /**
     * 修改运单装车确认状态
     *
     * @param tmsShipbillHeaderModel
     */
    private void updateShipBillScanConfirm(TmsShipbillHeaderModel tmsShipbillHeaderModel, LoadingScanConfirmVO confirmVO) {
        int status = businessFlowUtil.judgmentNextFlowSts(tmsShipbillHeaderModel.getFlowConfig(), DataDictionaryConstant.FLOW_CONFIG_SCANNING);
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        tmsShipbillHeaderModel.setStatus(status);
        tmsShipbillHeaderModel.setUpdateperson(user.getNickname());
        tmsShipbillHeaderModel.setUpdatetime(new Date());
        if (StrUtil.isNotBlank(confirmVO.getVehicleTypeCategory())) {
            tmsShipbillHeaderModel.setVehicleTypeCategory(confirmVO.getVehicleTypeCategory());
        }
        if (StrUtil.isNotBlank(confirmVO.getContainerId())) {
            tmsShipbillHeaderModel.setContainerId(confirmVO.getContainerId());
            tmsShipbillHeaderModel.setContainerCode(confirmVO.getContainerCode());
            tmsShipbillHeaderModel.setContainerName(confirmVO.getContainerName());
        }
        if (StrUtil.isNotBlank(confirmVO.getVehicleDeviceId())) {
            tmsShipbillHeaderModel.setVehicleDeviceId(confirmVO.getVehicleDeviceId());
            tmsShipbillHeaderModel.setVehicleDeviceCode(confirmVO.getVehicleDeviceCode());
            tmsShipbillHeaderModel.setVehicleDeviceName(confirmVO.getVehicleDeviceName());
        }
        tmsShipbillHeaderMapper.update(tmsShipbillHeaderModel);

        // 更新装车扫描状态 为已装车扫描
        Map<String, Object> mapUpdate = Maps.newHashMap();
        mapUpdate.put("status", status);
        mapUpdate.put("updateperson", user.getNickname());
        mapUpdate.put("updatetime", new Date());
        if (StrUtil.isNotBlank(confirmVO.getContainerId())) {
            mapUpdate.put("containerId", confirmVO.getContainerId());
            mapUpdate.put("containerCode", confirmVO.getContainerCode());
            mapUpdate.put("containerName", confirmVO.getContainerName());
        }
        if (StrUtil.isNotBlank(confirmVO.getVehicleDeviceId())) {
            mapUpdate.put("vehicleDeviceId", confirmVO.getVehicleDeviceId());
            mapUpdate.put("vehicleDeviceCode", confirmVO.getVehicleDeviceCode());
            mapUpdate.put("vehicleDeviceName", confirmVO.getVehicleDeviceName());
        }
        if (StrUtil.isNotBlank(confirmVO.getVehicleTypeCategory())) {
            mapUpdate.put("vehicleTypeCategory", confirmVO.getVehicleTypeCategory());
        }
        Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
        Restriction r1 = Restrictions.eq(TmsLoadingBillDetailModel::getEnterpriseId, user.getEnterpriseId());
        Restriction r2 = Restrictions.eq(TmsLoadingBillDetailModel::getShipbillId, tmsShipbillHeaderModel.getShipbillId());
        criteria.setRestriction(Restrictions.and(r1, r2));
        tmsLoadingBillDetailMapper.updateMapByCriteria(mapUpdate, criteria);
        shipBillLog(tmsShipbillHeaderModel, DataDictionaryConstant.SHIPBILL_STATUSNAME_ZC_CONFIRM, tmsShipbillHeaderModel.getStatus(), status);
        //递归更新父级运单扫描状态
        String fatherShipBillId = tmsShipbillHeaderModel.getFatherShipbillId();
        while (StrUtil.isNotBlank(fatherShipBillId)) {
            TmsShipbillHeaderModel fatherShipBill =
                    tmsShipbillHeaderMapper.findById(fatherShipBillId, TmsShipbillHeaderModel.class);
            if (ObjectUtil.isNotNull(fatherShipBill)) {
                List<TmsShipbillHeaderModel> childShipBillList = getChildTmsShipBillHeaderModel(fatherShipBillId);
                if (childShipBillList.stream().allMatch(childShipBill -> status == childShipBill.getStatus().intValue())) {
                    fatherShipBill.setStatus(status);
                    fatherShipBill.setUpdateperson(user.getNickname());
                    fatherShipBill.setUpdatetime(new Date());
                    if (StrUtil.isNotBlank(confirmVO.getVehicleTypeCategory())) {
                        fatherShipBill.setVehicleTypeCategory(confirmVO.getVehicleTypeCategory());
                    }
                    if (StrUtil.isNotBlank(confirmVO.getContainerId())) {
                        fatherShipBill.setContainerId(confirmVO.getContainerId());
                        fatherShipBill.setContainerCode(confirmVO.getContainerCode());
                        fatherShipBill.setContainerName(confirmVO.getContainerName());
                    }
                    if (StrUtil.isNotBlank(confirmVO.getVehicleDeviceId())) {
                        fatherShipBill.setVehicleDeviceId(confirmVO.getVehicleDeviceId());
                        fatherShipBill.setVehicleDeviceCode(confirmVO.getVehicleDeviceCode());
                        fatherShipBill.setVehicleDeviceName(confirmVO.getVehicleDeviceName());
                    }
                    tmsShipbillHeaderMapper.update(fatherShipBill);
                    shipBillLog(fatherShipBill, DataDictionaryConstant.SHIPBILL_STATUSNAME_ZC_CONFIRM, fatherShipBill.getStatus(), status);
                }
                fatherShipBillId = fatherShipBill.getFatherShipbillId();
            } else {
                fatherShipBillId = StrUtil.EMPTY;
            }
        }
    }

    /**
     * 通过父级运单找子单
     *
     * @param shipBillId
     * @return
     */
    private List<TmsShipbillHeaderModel> getChildTmsShipBillHeaderModel(String shipBillId) {
        Criteria criteria = Criteria.forClass(TmsShipbillHeaderModel.class);
        Restriction restriction = new RestrictionBuilder()
                .eq("fatherShipbillId", shipBillId)
                .build();
        criteria.setRestriction(restriction);
        return tmsShipbillHeaderMapper.findByCriteria(criteria);
    }

    /**
     * getLoadingScanLoadingBillInfoDTO
     *
     * @param loadingBillIdList
     * @return
     */
    private List<LoadingScanLoadingBillInfoDTO> getLoadingScanLoadingBillInfoDTOList(List<String> loadingBillIdList) {
        List<TmsLoadingBillHeaderModel> tmsLoadingBillHeaderModelList = tmsLoadingBillHeaderMapper.findByIds(TmsLoadingBillHeaderModel.class, loadingBillIdList.toArray(), null);
        return tmsLoadingBillHeaderModelList.stream().map(tmsLoadingBillHeaderModel ->
                BeanUtil.copyProperties(tmsLoadingBillHeaderModel, LoadingScanLoadingBillInfoDTO.class)).collect(Collectors.toList());
    }

    /**
     * getLoadingScanShipBillInfoDTOList
     *
     * @param shipBillIdList
     * @return
     */
    private List<LoadingScanShipBillInfoDTO> getLoadingScanShipBillInfoDTOList(List<String> shipBillIdList, LoadingScanQueryVO vo) {
        List<TmsShipbillHeaderModel> tmsShipbillHeaderModelList = tmsShipbillHeaderMapper.findByIds(TmsShipbillHeaderModel.class, shipBillIdList.toArray(), null);
        return tmsShipbillHeaderModelList.stream().map(tmsShipbillHeaderModel -> getLoadingScanShipBillInfoDTO(tmsShipbillHeaderModel, vo)).collect(Collectors.toList());
    }

    /**
     * getLoadingScanShipBillInfoDTO
     *
     * @param tmsShipbillHeaderModel
     * @return
     */
    private LoadingScanShipBillInfoDTO getLoadingScanShipBillInfoDTO(TmsShipbillHeaderModel tmsShipbillHeaderModel, LoadingScanQueryVO vo) {
        LoadingScanShipBillInfoDTO dto1 = BeanUtil.copyProperties(tmsShipbillHeaderModel, LoadingScanShipBillInfoDTO.class);
        String loadingBillId = loadingBillService.getLoadingBillIdByShipBillId(tmsShipbillHeaderModel.getShipbillId());
        dto1.setLoadingBillId(loadingBillId);
        dto1.setLoadingBillNo(loadingBillId);
        if (!DataDictionaryConstant.SHIPPER_TYPE_CK.equals(dto1.getShipperType())) {
            dto1.setShipperName(dto1.getShipperUnitName() + DataDictionaryConstant.Line_SYMBOL + dto1.getShipperName());
        }
        if (!DataDictionaryConstant.CONSIGNEE_TYPE_CK.equals(dto1.getConsigneeType())) {
            dto1.setConsigneeName(dto1.getConsigneeUnitName() + DataDictionaryConstant.Line_SYMBOL + dto1.getConsigneeName());
        }
        Criteria criteria = Criteria.forClass(TmsShipbillDetailModel.class);
        Restriction r1 = Restrictions.eq(TmsShipbillDetailModel::getShipbillId, tmsShipbillHeaderModel.getShipbillId());
        Restriction r2 = ToolKits.isEmpty(vo.getScanStatus()) ? null : Restrictions.eq(TmsShipbillDetailModel::getScanStatus, vo.getScanStatus());
        Restriction r4 = ToolKits.isEmpty(vo.getItemCode()) ? null : Restrictions.eq(TmsShipbillDetailModel::getItemCode, vo.getItemCode());
        Restriction r3 = null;
        if (ObjectUtil.isNotEmpty(vo.getPlatform()) && !"虚拟月台".equals(vo.getPlatform())) {
            r3 = Restrictions.eq(TmsShipbillDetailModel::getStagingLocation, vo.getPlatform());
        }
        criteria.setRestriction(Restrictions.and(r1, r2, r3, r4));
        List<TmsShipbillDetailModel> tmsShipbillDetailModelList = tmsShipbillDetailMapper.findByCriteria(criteria);

        if (CollectionUtil.isNotEmpty(tmsShipbillDetailModelList)) {
            List<LoadingScanShipBillDetailInfoDTO> detailInfoDTOList = Lists.newArrayList();
            tmsShipbillDetailModelList.stream().forEach(d -> {
                LoadingScanShipBillDetailInfoDTO dto = BeanUtil.copyProperties(d, LoadingScanShipBillDetailInfoDTO.class);
                dto.setScannedPcs(getShipbillDetailScannedPcs(dto.getId()));
                detailInfoDTOList.add(dto);
            });
            dto1.setDetailInfoDTOList(detailInfoDTOList);
        }
        return dto1;
    }

    /**
     * 记录运单日志
     *
     * @param tmsShipbillHeaderModel
     */
    private void shipBillLog(TmsShipbillHeaderModel tmsShipbillHeaderModel, String event, Integer oldStatus, Integer newStatus) {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        ShipbillNodeTrackingSaveNewVO shipbillNodeTrackingSaveNewVO = new ShipbillNodeTrackingSaveNewVO();
        ShipbillOperateLogSaveNewVO shipbillOperateLogSaveNewVO = new ShipbillOperateLogSaveNewVO();
        shipbillNodeTrackingSaveNewVO.setNodeEvent(event);
        shipbillNodeTrackingSaveNewVO.setStatus(newStatus);
        shipbillNodeTrackingSaveNewVO.setShipbillId(tmsShipbillHeaderModel.getShipbillId());
        shipbillNodeTrackingSaveNewVO.setShipbillNo(tmsShipbillHeaderModel.getShipbillNo());
        shipbillNodeTrackingSaveNewVO.setNodeDate(new Date());
        shipbillNodeTrackingSaveNewVO.setUserId(user.getUserid());
        shipbillNodeTrackingSaveNewVO.setUserName(user.getNickname());
        shipbillNodeTrackingSaveNewVO.setEnterpriseId(user.getEnterpriseId());
        shipbillNodeTrackingSaveNewVO.setEnterpriseName(user.getEnterpriseName());
        shipbillNodeTrackingService.addShipbillNodeTrackingNewData(shipbillNodeTrackingSaveNewVO);

        shipbillOperateLogSaveNewVO.setOperateEvent(event);
        shipbillOperateLogSaveNewVO.setOldStatus(oldStatus);
        shipbillOperateLogSaveNewVO.setNewStatus(newStatus);
        shipbillOperateLogSaveNewVO.setShipbillId(tmsShipbillHeaderModel.getShipbillId());
        shipbillOperateLogSaveNewVO.setShipbillNo(tmsShipbillHeaderModel.getShipbillNo());
        shipbillOperateLogSaveNewVO.setUserId(user.getUserid());
        shipbillOperateLogSaveNewVO.setUserName(user.getNickname());
        shipbillOperateLogSaveNewVO.setEnterpriseId(user.getEnterpriseId());
        shipbillOperateLogSaveNewVO.setEnterpriseName(user.getEnterpriseName());
        shipbillOperateLogSaveNewVO.setOperateDate(new Date());
        shipbillOperateLogService.addShipbillOperateLogNewData(shipbillOperateLogSaveNewVO);
    }

    /**
     * 装车扫描运单
     *
     * @param vo
     * @return
     */
    private LoadingScanInfoDTO scanShipBill(LoadingScanCodeVO vo) {
        LoadingScanInfoDTO dto = new LoadingScanInfoDTO();
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        TmsShipbillHeaderModel tmsShipbillHeaderModel = tmsShipbillHeaderMapper.findById(vo.getBillCode(), TmsShipbillHeaderModel.class);
        if (ObjectUtil.isEmpty(tmsShipbillHeaderModel)) {
            throw new BizException("派车单/运单【" + vo.getBillCode() + "】扫描失败！");
        }
        if (DataDictionaryConstant.SCAN_STATUS_LOADED.equals(tmsShipbillHeaderModel.getScanStatus())) {
            throw new BizException("运单【" + vo.getBillCode() + "】已扫描！");
        }
        if (!tmsShipbillHeaderModel.getFlowConfig().contains(DataDictionaryConstant.FLOW_CONFIG_SCANNING)) {
            throw new BizException("运单【" + vo.getBillCode() + "】没有匹配到装车扫描的业务流程");
        }
        Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
        Restriction r1 = Restrictions.eq(TmsLoadingBillDetailModel::getEnterpriseId, user.getEnterpriseId());
        Restriction r2 = Restrictions.eq(TmsLoadingBillDetailModel::getShipbillId, tmsShipbillHeaderModel.getShipbillId());
        criteria.setRestriction(Restrictions.and(r1, r2));
        criteria.setOrder(Order.newInstance().desc(new String[]{"createtime"}));
        List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModelList = tmsLoadingBillDetailMapper.findByCriteria(criteria);
        if (CollectionUtil.isEmpty(tmsLoadingBillDetailModelList)) {
            throw new BizException("运单【" + vo.getBillCode() + "】对应派车单明细不存在！");
        }
        TmsLoadingBillHeaderModel loadingBillHeaderModel = tmsLoadingBillHeaderMapper.findById(
                tmsLoadingBillDetailModelList.get(0).getLoadingBillId(), TmsLoadingBillHeaderModel.class);
        if (ObjectUtil.isEmpty(loadingBillHeaderModel)) {
            throw new BizException("运单【" + vo.getBillCode() + "】对应派车单不存在！");
        }
        if (!vo.getDriverId().equals(loadingBillHeaderModel.getDriverId()) || !vo.getVehiclePlateNumber().equals(loadingBillHeaderModel.getVehiclePlateNumber())) {
            throw new BizException("运单【" + vo.getBillCode() + "】不属于您的提货范围！");
        }
        if (!DataDictionaryConstant.SCAN_STATUS_LOADED.equals(loadingBillHeaderModel.getScanStatus())) {
            updateLoadingBillScan(loadingBillHeaderModel);
        }
        updateShipBillScan(tmsShipbillHeaderModel);
        dto.setCodeType(LoadingScanOrderTypeEnum.SHIP_NO.getCode());
        dto.setMessage("运单【" + vo.getBillCode() + "】扫描成功！");
        dto.setLoadingBillInfoDTO(BeanUtil.copyProperties(loadingBillHeaderModel, LoadingScanLoadingBillInfoDTO.class));
        LoadingScanQueryVO queryVO = new LoadingScanQueryVO();
        dto.setShipBillInfoDTOList(Lists.newArrayList(getLoadingScanShipBillInfoDTO(tmsShipbillHeaderModel, queryVO)));
        return dto;
    }

    /**
     * 装车扫描运单明细
     *
     * @param vo
     * @return
     */
    private LoadingScanInfoDTO scanShipBillDetail(LoadingScanCodeVO vo) {
        if (ObjectUtil.isEmpty(vo.getPlatformName())) {
            throw new BizException("请指定商品所在的月台！");
        }
        if (ObjectUtil.isEmpty(vo.getLoadingBillNo())) {
            throw new BizException("请先扫描派车单！");
        }
        LoadingScanInfoDTO dto = new LoadingScanInfoDTO();
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        LoadingScanQueryVO queryVO = new LoadingScanQueryVO();
        queryVO.setDriverId(vo.getDriverId());
        queryVO.setVehiclePlateNumber(vo.getVehiclePlateNumber());
        queryVO.setPlatform(vo.getPlatformName());
        List<String> loadingBillIds = Lists.newArrayList();
        loadingBillIds.add(vo.getLoadingBillNo());
        queryVO.setLoadingBillIdList(loadingBillIds);
        List<String> shipBillList = tmsLoadingBillDetailMapper.getLoadingScanShipBill(queryVO);
        if (ObjectUtil.isEmpty(shipBillList)) {
            throw new BizException("派车单,商品,月台不一致！");
        }
        Criteria criteriaShipbillDetail = Criteria.forClass(TmsShipbillDetailModel.class);
        Restriction r11 = Restrictions.eq(TmsShipbillDetailModel::getEnterpriseId, user.getEnterpriseId());
        Restriction r12 = Restrictions.in(TmsShipbillDetailModel::getShipbillId, shipBillList);
        Restriction r13 = Restrictions.eq(TmsShipbillDetailModel::getItemCode, vo.getBillCode());
        Restriction r14 = null;
        if (!"虚拟月台".equals(vo.getPlatformName())) {
            r14 = Restrictions.eq(TmsShipbillDetailModel::getStagingLocation, vo.getPlatformName());
        }
        criteriaShipbillDetail.setRestriction(Restrictions.and(r11, r12, r13, r14));
        List<TmsShipbillDetailModel> shipbillDetailModels = tmsShipbillDetailMapper.findByCriteria(criteriaShipbillDetail);

        if (ObjectUtil.isEmpty(shipbillDetailModels)) {
            throw new BizException("商品不在派车单中！");
        }
        Criteria criteriaShipbillDetailScan = Criteria.forClass(TmsShipbillDetailScanModel.class);
        Restriction r1 = Restrictions.in(TmsShipbillDetailScanModel::getShipbillId, shipBillList);
        Restriction r2 = Restrictions.eq(TmsShipbillDetailScanModel::getItemCode, vo.getBillCode());
        criteriaShipbillDetailScan.setRestriction(Restrictions.and(r1, r2));
        List<TmsShipbillDetailScanModel> shipbillDetailScanModels = tmsShipbillDetailScanMapper.findByCriteria(criteriaShipbillDetailScan);
        if (ObjectUtil.isNotEmpty(shipbillDetailScanModels)) {
            if (shipbillDetailScanModels.stream().allMatch(d -> d.getPcs().compareTo(d.getScannedPcs()) <= 0)) {
                throw new BizException("商品已全部扫描！");
            }
        }

        List<LoadingScanShipBillInfoDTO> shipBillInfoDTOList = Lists.newArrayList();
        shipbillDetailModels.stream().map(TmsShipbillDetailModel::getShipbillId).distinct().collect(Collectors.toList())
                            .stream().forEach(billId -> {
            TmsShipbillHeaderModel tmsShipbillHeaderModel = tmsShipbillHeaderMapper.findById(billId, TmsShipbillHeaderModel.class);

            if (!tmsShipbillHeaderModel.getFlowConfig().contains(DataDictionaryConstant.FLOW_CONFIG_SCANNING)) {
                throw new BizException("商品没有匹配到装车扫描的业务流程");
            }
            Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
            Restriction r21 = Restrictions.eq(TmsLoadingBillDetailModel::getEnterpriseId, user.getEnterpriseId());
            Restriction r22 = Restrictions.eq(TmsLoadingBillDetailModel::getShipbillId, tmsShipbillHeaderModel.getShipbillId());
            criteria.setRestriction(Restrictions.and(r21, r22));
            criteria.setOrder(Order.newInstance().desc(new String[]{"createtime"}));
            List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModelList = tmsLoadingBillDetailMapper.findByCriteria(criteria);
            if (CollectionUtil.isEmpty(tmsLoadingBillDetailModelList)) {
                throw new BizException("商品【" + vo.getBillCode() + "】对应派车单明细不存在！");
            }
            TmsLoadingBillDetailModel loadingBillDetailModel = tmsLoadingBillDetailModelList.get(0);
            TmsLoadingBillHeaderModel loadingBillHeaderModel = tmsLoadingBillHeaderMapper.findById(
                    loadingBillDetailModel.getLoadingBillId(), TmsLoadingBillHeaderModel.class);
            if (ObjectUtil.isEmpty(loadingBillHeaderModel)) {
                throw new BizException("商品【" + vo.getBillCode() + "】对应派车单不存在！");
            }
            if (!vo.getDriverId().equals(loadingBillHeaderModel.getDriverId()) || !vo.getVehiclePlateNumber().equals(loadingBillHeaderModel.getVehiclePlateNumber())) {
                throw new BizException("商品【" + vo.getBillCode() + "】不属于您的提货范围！");
            }
            if (!DataDictionaryConstant.SCAN_STATUS_LOADED.equals(loadingBillHeaderModel.getScanStatus())) {
                throw new BizException("请先扫描派车单！");
            }
            if (!DataDictionaryConstant.SCAN_STATUS_LOADED.equals(loadingBillDetailModel.getScanStatus())) {
                loadingBillDetailModel.setScanStatus(DataDictionaryConstant.SCAN_STATUS_LOADED);
                loadingBillDetailModel.setUpdatetime(DateUtil.date());
                loadingBillDetailModel.setUpdateperson(user.getNickname());
                tmsLoadingBillDetailMapper.update(loadingBillDetailModel);
            }

            updateShipBillDetailScan(tmsShipbillHeaderModel, vo);
            LoadingScanQueryVO scanQueryVO = new LoadingScanQueryVO();
            scanQueryVO.setScanStatus(20);
            scanQueryVO.setItemCode(vo.getBillCode());
            shipBillInfoDTOList.add(getLoadingScanShipBillInfoDTO(tmsShipbillHeaderModel, scanQueryVO));
        });

        dto.setCodeType(LoadingScanOrderTypeEnum.ITEM_NO.getCode());
        dto.setMessage("商品【" + vo.getBillCode() + "】扫描成功！");
        dto.setShipBillInfoDTOList(shipBillInfoDTOList);
        return dto;
    }

    /**
     * 装车扫描派车单
     *
     * @param vo
     * @return
     */
    private LoadingScanInfoDTO scanLoadingBill(LoadingScanCodeVO vo, TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel, String scanLoadingMethod) {
        LoadingScanInfoDTO dto = new LoadingScanInfoDTO();
        checkLoadingBill(vo, tmsLoadingBillHeaderModel, scanLoadingMethod);
        updateLoadingBillScan(tmsLoadingBillHeaderModel);
        dto.setCodeType(LoadingScanOrderTypeEnum.LOADING_NO.getCode());
        dto.setMessage("派车单【" + vo.getBillCode() + "】扫描成功！");
        dto.setLoadingBillInfoDTO(BeanUtil.copyProperties(tmsLoadingBillHeaderModel, LoadingScanLoadingBillInfoDTO.class));
        return dto;
    }

    /**
     * 只扫描派车单
     *
     * @param vo
     * @return
     */
    private LoadingScanInfoDTO scanLoadingBillOnly(LoadingScanCodeVO vo) {
        LoadingScanInfoDTO dto = new LoadingScanInfoDTO();
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel = tmsLoadingBillHeaderMapper.findById(vo.getBillCode(), TmsLoadingBillHeaderModel.class);
        if (ObjectUtil.isEmpty(tmsLoadingBillHeaderModel)) {
            throw new BizException("派车单【" + vo.getBillCode() + "】不存在！");
        }
        checkLoadingBill(vo, tmsLoadingBillHeaderModel, null);
        Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
        Restriction r1 = Restrictions.eq(TmsLoadingBillDetailModel::getEnterpriseId, user.getEnterpriseId());
        Restriction r2 = Restrictions.eq(TmsLoadingBillDetailModel::getLoadingBillId, tmsLoadingBillHeaderModel.getLoadingBillId());
        criteria.setRestriction(Restrictions.and(r1, r2));
        List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModelList = tmsLoadingBillDetailMapper.findByCriteria(criteria);
        List<TmsShipbillHeaderModel> tmsShipbillHeaderModelList = tmsLoadingBillDetailModelList.stream().map(tmsLoadingBillDetailModel ->
                tmsShipbillHeaderMapper.findById(tmsLoadingBillDetailModel.getShipbillId(), TmsShipbillHeaderModel.class)).collect(Collectors.toList());
        updateLoadingBillScan(tmsLoadingBillHeaderModel);
        tmsShipbillHeaderModelList.forEach(tmsShipbillHeaderModel -> updateShipBillScan(tmsShipbillHeaderModel));
        LoadingScanQueryVO queryVO = new LoadingScanQueryVO();
        dto.setCodeType(LoadingScanOrderTypeEnum.LOADING_NO.getCode());
        dto.setMessage("派车单【" + vo.getBillCode() + "】扫描成功！");
        dto.setLoadingBillInfoDTO(BeanUtil.copyProperties(tmsLoadingBillHeaderModel, LoadingScanLoadingBillInfoDTO.class));
        dto.setShipBillInfoDTOList(tmsShipbillHeaderModelList.stream().map(tmsShipbillHeaderModel ->
                getLoadingScanShipBillInfoDTO(tmsShipbillHeaderModel, queryVO)).collect(Collectors.toList()));
        return dto;
    }

    /**
     * checkLoadingBill
     *
     * @param vo
     * @param tmsLoadingBillHeaderModel
     */
    private void checkLoadingBill(LoadingScanCodeVO vo, TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel, String scanLoadingMethod) {
        if (!vo.getDriverId().equals(tmsLoadingBillHeaderModel.getDriverId()) || !vo.getVehiclePlateNumber().equals(tmsLoadingBillHeaderModel.getVehiclePlateNumber())) {
            throw new BizException("派车单【" + vo.getBillCode() + "】不属于您的提货范围！");
        }
        if (DataDictionaryConstant.SCANLOADING_METHED_LOADINGBILL_ITEM.equals(scanLoadingMethod)) {
            LoadingScanQueryVO queryVO = new LoadingScanQueryVO();
            queryVO.setDriverId(vo.getDriverId());
            queryVO.setVehiclePlateNumber(vo.getVehiclePlateNumber());
            queryVO.setPlatform(vo.getPlatformName());
            List<String> loadingBillIds = Lists.newArrayList();
            loadingBillIds.add(vo.getBillCode());
            queryVO.setLoadingBillIdList(loadingBillIds);
            List<String> shipBillList = tmsLoadingBillDetailMapper.getLoadingScanShipBill(queryVO);
            if (ObjectUtil.isEmpty(shipBillList)) {
                throw new BizException("派车单【" + vo.getBillCode() + "】和月台不一致！");
            }
        } else {
            if (DataDictionaryConstant.SCAN_STATUS_LOADED.equals(tmsLoadingBillHeaderModel.getScanStatus())) {
                throw new BizException("派车单【" + vo.getBillCode() + "】已扫描！");
            }
        }
    }

    /**
     * 获取运单明细扫描信息
     *
     * @param vo
     * @return
     */
    public LoadingScanShipBillDTO getShipBillDetailScanInfo(LoadingScanQueryVO vo) {
        LoadingScanShipBillDTO dto = new LoadingScanShipBillDTO();
        dto.setConfirmStatus(DataDictionaryConstant.SCAN_STATUS_INIT);
        dto.setScanned(0);
        dto.setUnScan(0);
        dto.setTotalScan(0);
        List<String> allShipBillList = tmsLoadingBillDetailMapper.getLoadingScanShipBill(vo);
        List<String> allIdList = Lists.newArrayList();
        List<LoadingScanShipBillInfoDTO> allList = Lists.newArrayList();
        if (ObjectUtil.isEmpty(allShipBillList)) {
            return dto;
        }
        Criteria criteriaShipbillDetail = Criteria.forClass(TmsShipbillDetailModel.class);
        Restriction r1 = Restrictions.in(TmsShipbillDetailModel::getShipbillId, allShipBillList);
        Restriction r2 = Restrictions.eq(TmsShipbillDetailModel::getScanStatus, DataDictionaryConstant.SCAN_STATUS_INIT);
        Restriction r3 = null;
        if (ObjectUtil.isNotEmpty(vo.getPlatform()) && !"虚拟月台".equals(vo.getPlatform())) {
            r3 = Restrictions.eq(TmsShipbillDetailModel::getStagingLocation, vo.getPlatform());
        }
        criteriaShipbillDetail.setRestriction(Restrictions.and(r1, r2, r3));
        List<TmsShipbillDetailModel> noScanTmsShipbillDetailModels = tmsShipbillDetailMapper.findByCriteria(criteriaShipbillDetail);

        Criteria criteriaShipbillDetailScan = Criteria.forClass(TmsShipbillDetailScanModel.class);
        r1 = Restrictions.in(TmsShipbillDetailScanModel::getShipbillId, allShipBillList);
        r2 = Restrictions.eq(TmsShipbillDetailScanModel::getScanStatus, DataDictionaryConstant.SCAN_STATUS_LOADED);
        r3 = ObjectUtil.isEmpty(vo.getPlatform()) ? null : Restrictions.eq(TmsShipbillDetailModel::getStagingLocation, vo.getPlatform());
        criteriaShipbillDetailScan.setRestriction(Restrictions.and(r1, r2, r3));
        List<TmsShipbillDetailScanModel> scannedTmsShipbillDetailModels = tmsShipbillDetailScanMapper.findByCriteria(criteriaShipbillDetailScan);
        if (ObjectUtil.isNotEmpty(scannedTmsShipbillDetailModels)) {
            vo.setScanStatus(20);
            dto.setScannedShipBillList(getLoadingScanShipBillInfoDTOList(scannedTmsShipbillDetailModels.stream().map(TmsShipbillDetailScanModel::getShipbillId).distinct().collect(Collectors.toList()), vo));
            dto.setScanned(dto.getScannedShipBillList().stream().mapToInt(list -> list.getDetailInfoDTOList().size()).sum());
            allList.addAll(dto.getScannedShipBillList());

            if (ObjectUtil.isNotEmpty(vo.getPlatform()) && scannedTmsShipbillDetailModels.stream().anyMatch(d -> d.getStagingLocation().equals(vo.getPlatform()) && DataDictionaryConstant.SCAN_STATUS_LOADED.equals(d.getConfirmStatus()))) {
                dto.setConfirmStatus(DataDictionaryConstant.SCAN_STATUS_LOADED);
            }
        }

        if (ObjectUtil.isNotEmpty(noScanTmsShipbillDetailModels)) {
            vo.setScanStatus(10);
            dto.setUnScanShipBillList(getLoadingScanShipBillInfoDTOList(noScanTmsShipbillDetailModels.stream().map(TmsShipbillDetailModel::getShipbillId).distinct().collect(Collectors.toList()), vo));
            dto.setUnScan(dto.getUnScanShipBillList().stream().mapToInt(list -> list.getDetailInfoDTOList().size()).sum());
            allList.addAll(dto.getUnScanShipBillList());
        }
        vo.setScanStatus(null);

        dto.setTotalScanShipBillIdList(allIdList);
        dto.setTotalScan(dto.getUnScan().intValue() + dto.getScanned().intValue());
        dto.setTotalScanShipBillList(allList);
        return dto;
    }

    /**
     * 保存商品的扫描件数
     *
     * @param vo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveItemScanPcs(LoadingScanShipbillDetailVO vo) {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        if (ToolKits.isEmpty(vo.getScannedPcs()) || NumberUtil.equals(BigDecimal.ZERO, vo.getScannedPcs())) {
            throw new BizException("商品【" + vo.getItemCode() + "】扫描件数为空");
        }
        BigDecimal scannedPcs = vo.getScannedPcs();
        BigDecimal detailPcs = BigDecimal.ZERO;

        Criteria criteriaShipbillDetailScan = Criteria.forClass(TmsShipbillDetailScanModel.class);
        Restriction r1 = Restrictions.in(TmsShipbillDetailScanModel::getShipbillDetailId, vo.getIds().split(","));
        Restriction r2 = Restrictions.eq(TmsShipbillDetailScanModel::getScanStatus, DataDictionaryConstant.SCAN_STATUS_LOADED);
        Restriction r3 = Restrictions.eq(TmsShipbillDetailScanModel::getItemCode, vo.getItemCode());
        criteriaShipbillDetailScan.setRestriction(Restrictions.and(r1, r2, r3));
        criteriaShipbillDetailScan.setOrder(Order.newInstance().asc(new String[]{"shipbillId"}));
        List<TmsShipbillDetailScanModel> scannedTmsShipbillDetailModels = tmsShipbillDetailScanMapper.findByCriteria(criteriaShipbillDetailScan);

        if (ObjectUtil.isEmpty(scannedTmsShipbillDetailModels)) {
            throw new BizException("商品【" + vo.getItemCode() + "】对应的运单明细不存在！");
        }
        for (TmsShipbillDetailScanModel detailModel : scannedTmsShipbillDetailModels) {
            if (scannedPcs.compareTo(BigDecimal.ZERO) == 0) {
                detailPcs = BigDecimal.ZERO;
            } else if (scannedPcs.compareTo(detailModel.getPcs()) > 0) {
                detailPcs = detailModel.getPcs();
                scannedPcs = scannedPcs.subtract(detailPcs);
            } else if (scannedPcs.compareTo(detailModel.getPcs()) <= 0) {
                detailPcs = scannedPcs;
                scannedPcs = BigDecimal.ZERO;
            }
            detailModel.setScannedPcs(detailPcs);
            detailModel.setUpdateperson(user.getNickname());
            detailModel.setUpdatetime(DateUtil.date());
            tmsShipbillDetailScanMapper.update(detailModel);
        }
        ;
    }

    public BigDecimal getShipbillDetailScannedPcs(String id) {
        BigDecimal scannedPcs = BigDecimal.ZERO;

        Criteria criteriaShipbillDetailScan = Criteria.forClass(TmsShipbillDetailScanModel.class);
        Restriction r1 = Restrictions.eq(TmsShipbillDetailScanModel::getShipbillDetailId, id);
        Restriction r2 = Restrictions.eq(TmsShipbillDetailScanModel::getScanStatus, DataDictionaryConstant.SCAN_STATUS_LOADED);
        criteriaShipbillDetailScan.setRestriction(Restrictions.and(r1, r2));
        List<TmsShipbillDetailScanModel> scannedTmsShipbillDetailModels = tmsShipbillDetailScanMapper.findByCriteria(criteriaShipbillDetailScan);
        if (ObjectUtil.isNotEmpty(scannedTmsShipbillDetailModels)) {
            scannedPcs = scannedPcs.add(scannedTmsShipbillDetailModels.get(0).getScannedPcs());
        }
        return scannedPcs;
    }

    /**
     * 部分装车确认
     *
     * @param confirmVO
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public LoadingScanConfirmDTO partScanConfirm(LoadingScanConfirmVO confirmVO) {
        ToolKits.isParamNull(confirmVO, "请求不为空");

        return shipbillDetailConfirm(confirmVO);
    }

    public LoadingScanConfirmDTO shipbillDetailConfirm(LoadingScanConfirmVO confirmVO) {
        String scanLoadingMethod = mainDataProxy.getSystemParamByCode(DataDictionaryConstant.SCANLOADING_METHED);
        if (!DataDictionaryConstant.SCANLOADING_METHED_LOADINGBILL_ITEM.equals(scanLoadingMethod)) {
            return null;
        }
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        LoadingScanConfirmDTO dto = new LoadingScanConfirmDTO();
        dto.setType("3");
        LoadingScanQueryVO vo = BeanUtil.copyProperties(confirmVO, LoadingScanQueryVO.class);
        vo.setScanStatus(DataDictionaryConstant.SCAN_STATUS_LOADED);
        List<String> scannedLoadingBillIdList = tmsLoadingBillDetailMapper.getLoadingScanLoadingBill(vo);
        if (CollectionUtil.isEmpty(scannedLoadingBillIdList)) {
            return dto;
        }
        Criteria criteria = Criteria.forClass(TmsShipbillDetailScanModel.class);
        Restriction r1 = Restrictions.in(TmsShipbillDetailScanModel::getLoadingBillNo, scannedLoadingBillIdList);
        Restriction r2 = ObjectUtil.isEmpty(confirmVO.getPlatformName()) ? null : Restrictions.in(TmsShipbillDetailScanModel::getStagingLocation,
                confirmVO.getPlatformName().split(","));
        Restriction r3 = Restrictions.eq(TmsShipbillDetailScanModel::getScanStatus, 20);
        criteria.setRestriction(Restrictions.and(r1, r2, r3));
        List<TmsShipbillDetailScanModel> detailScanModels = tmsShipbillDetailScanMapper.findByCriteria(criteria);
        if (CollectionUtil.isNotEmpty(detailScanModels)) {
            detailScanModels.stream().filter(d -> !DataDictionaryConstant.SCAN_STATUS_LOADED.equals(d.getConfirmStatus())).forEach(detail -> {
                detail.setConfirmStatus(20);
                detail.setCreatetime(DateUtil.date());
                detail.setCreateperson(user.getNickname());
                tmsShipbillDetailScanMapper.update(detail);
            });
        } else {
            throw new BizException("请先扫描商品！");
        }
        return dto;
    }

    private void updateLoadingTime(String billCode, Date loadingStartDate, Date loadingEndDate) {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        Criteria criteriaLoadingBillDetail = Criteria.forClass(TmsLoadingBillDetailModel.class);
        Restriction r1 = Restrictions.eq(TmsLoadingBillDetailModel::getEnterpriseId, user.getEnterpriseId());
        Restriction r2 = Restrictions.eq(TmsLoadingBillDetailModel::getLoadingBillId, billCode);
        Restriction r3 = Restrictions.eq(TmsLoadingBillDetailModel::getShipbillNo, billCode);
        Restriction r4 = Restrictions.or(r2, r3);
        criteriaLoadingBillDetail.setRestriction(Restrictions.and(r1, r4));
        List<TmsLoadingBillDetailModel> loadingBillDetailModelList = tmsLoadingBillDetailMapper.findByCriteria(criteriaLoadingBillDetail);

        if (ToolKits.isEmpty(loadingBillDetailModelList)) {
            return;
        }
        for (String shipbillId : loadingBillDetailModelList.stream().map(TmsLoadingBillDetailModel::getShipbillId).collect(Collectors.toList())) {
            Criteria criteriaShipbillTransLog = Criteria.forClass(TmsShipbillTransLogModel.class);
            r1 = Restrictions.eq(TmsShipbillTransLogModel::getEnterpriseId, user.getEnterpriseId());
            r2 = Restrictions.eq(TmsShipbillTransLogModel::getShipbillId, shipbillId);
            List<TmsShipbillTransLogModel> transLogModels = tmsShipbillTransportLogMapper.findByCriteria(criteriaShipbillTransLog);
            if (ToolKits.isEmpty(transLogModels)) {
                continue;
            }
            TmsShipbillTransLogModel transLogModel = transLogModels.get(0);
            if (ToolKits.isEmpty(transLogModel.getLoadAndUnloadStartTime()) && ToolKits.isNotEmpty(loadingStartDate)) {
                transLogModel.setLoadAndUnloadStartTime(loadingStartDate);
            } else if (ToolKits.isNotEmpty(loadingEndDate)) {
                transLogModel.setLoadAndUnloadEndTime(loadingEndDate);
            }
            transLogModel.setUpdateperson(user.getNickname());
            transLogModel.setUpdatetime(DateUtil.date());
            tmsShipbillTransportLogMapper.update(transLogModel);
        }
    }

    /**
     * 完全装车确认
     *
     * @param confirmDTO
     * @return
     */
    public LoadingScanConfirmDTO allScanConfirm(LoadingScanConfirmDTO confirmDTO) {
        Criteria criteria = Criteria.forClass(TmsShipbillDetailScanModel.class);
        Restriction r1 = ObjectUtil.isEmpty(confirmDTO.getScanShipBillIdList()) ? null : Restrictions.in(TmsShipbillDetailScanModel::getShipbillId,
                confirmDTO.getScanShipBillIdList());
        Restriction r2 = Restrictions.eq(TmsShipbillDetailScanModel::getScanStatus, 20);
        criteria.setRestriction(Restrictions.and(r1, r2));
        List<TmsShipbillDetailScanModel> detailScanModels = tmsShipbillDetailScanMapper.findByCriteria(criteria);
        if (ObjectUtil.isEmpty(detailScanModels)) {
            return null;
        }
        List<TmsShipbillDetailModel> splitShipbillDetails = Lists.newArrayList();
        detailScanModels.stream().forEach(d -> {
            if (d.getPcs().compareTo(d.getScannedPcs()) > 0) {
                TmsShipbillDetailModel detailModel = tmsShipbillDetailMapper.findById(d.getShipbillDetailId(), TmsShipbillDetailModel.class);
                if (ObjectUtil.isNotEmpty(detailModel)) {
                    BigDecimal scannedPcs = d.getScannedPcs();
                    detailModel.setPcs(d.getPcs().subtract(d.getScannedPcs()));
                    detailModel.setExtNum5(scannedPcs);
                    splitShipbillDetails.add(detailModel);
                }
            }
        });

        Criteria criteriaShipbillDetail = Criteria.forClass(TmsShipbillDetailModel.class);
        r1 = Restrictions.in(TmsShipbillDetailModel::getShipbillId, confirmDTO.getScanShipBillIdList());
        r2 = Restrictions.notIn(TmsShipbillDetailModel::getId, detailScanModels.stream().map(TmsShipbillDetailScanModel::getShipbillDetailId).collect(Collectors.toList()));
        criteriaShipbillDetail.setRestriction(Restrictions.and(r1, r2));
        List<TmsShipbillDetailModel> noScanTmsShipbillDetailModels = tmsShipbillDetailMapper.findByCriteria(criteriaShipbillDetail);
        if (ObjectUtil.isNotEmpty(noScanTmsShipbillDetailModels)) {
            splitShipbillDetails.addAll(noScanTmsShipbillDetailModels);
        }

        if (ObjectUtil.isNotEmpty(splitShipbillDetails)) {
            List<String> updateShipBillIds = splitShipbillDetails.stream()
                                                                 .map(TmsShipbillDetailModel::getShipbillId)
                                                                 .distinct()
                                                                 .collect(Collectors.toList());
            createNewShipbill(splitShipbillDetails);
            updateShipBillPcsWeightVolume(updateShipBillIds);
        }
        return confirmDTO;
    }

    public void createNewShipbill(List<TmsShipbillDetailModel> addShibillDetail) {
        Map<Object, List<TmsShipbillDetailModel>> addShipbillMap = Maps.newHashMap();
        Map<Long, ItemCheckDTO> itemMap = Maps.newHashMap();
        addShipbillMap = addShibillDetail.stream().collect(Collectors.groupingBy(o -> o.getShipbillId()));
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        for (Object obj : addShipbillMap.keySet()) {
            List<TmsShipbillDetailModel> addDetailModels = addShipbillMap.get(obj);
            if (ToolKits.isEmpty(addDetailModels)) {
                continue;
            }
            String newShipbillId = mainDataProxy.getCodeNumberByCode(SeriaNnumberConstant.TMS_SHIPBILL_HEADER_ID);
            // 保存每个子单中的明细信息
            int idx = 1;
            // 商品总件数
            BigDecimal newGoodsTotalPcs = new BigDecimal(0);
            // 商品总体积
            BigDecimal newGoodsTotalVolume = new BigDecimal(0);
            // 商品总重量
            BigDecimal newGoodsTotalWeight = new BigDecimal(0);
            for (TmsShipbillDetailModel newShibillDetail : addDetailModels) {
                TmsShipbillDetailModel subTmsShipbillDetailModel = new TmsShipbillDetailModel();
                // 运单明细ID
                String subShipbillDetailId = mainDataProxy.getCodeNumberByCode(SeriaNnumberConstant.TMS_SHIPBILL_DETAIL_ID);

                BeanUtils.copyProperties(newShibillDetail, subTmsShipbillDetailModel);
                // 取商品资料
                ItemCheckDTO rsItemInfo = itemMap.get(Long.valueOf(subTmsShipbillDetailModel.getItemId()));
                if (ToolKits.isEmpty(rsItemInfo)) {
                    rsItemInfo = mainDataProxy.getItemById(newShibillDetail.getItemId());
                    itemMap.put(subTmsShipbillDetailModel.getItemId(), rsItemInfo);
                }

                // ID
                subTmsShipbillDetailModel.setId(subShipbillDetailId);
                subTmsShipbillDetailModel.setSeqno(idx);
                idx++;
                subTmsShipbillDetailModel.setOriginalSeqno(newShibillDetail.getOriginalSeqno());
                // 运单ID
                subTmsShipbillDetailModel.setShipbillId(newShipbillId);
                // 运单编号
                subTmsShipbillDetailModel.setShipbillNo(newShipbillId);

                subTmsShipbillDetailModel.setEnterpriseId(user.getEnterpriseId());
                subTmsShipbillDetailModel.setEnterpriseName(user.getEnterpriseName());

                subTmsShipbillDetailModel.setPcs(newShibillDetail.getPcs());
                subTmsShipbillDetailModel.setCreateperson(user.getNickname());
                subTmsShipbillDetailModel.setCreatetime(DateUtil.date());
                subTmsShipbillDetailModel.setWeight(subTmsShipbillDetailModel.getPcs().multiply(rsItemInfo.getWeight()));
                subTmsShipbillDetailModel.setVolume(subTmsShipbillDetailModel.getPcs().multiply(rsItemInfo.getVolume()));
                subTmsShipbillDetailModel.setOrigPcs(subTmsShipbillDetailModel.getPcs());
                subTmsShipbillDetailModel.setClosingPcs(BigDecimal.valueOf(0));
                subTmsShipbillDetailModel.setDeliveryPcs(BigDecimal.valueOf(0));
                subTmsShipbillDetailModel.setScanStatus(DataDictionaryConstant.SCAN_STATUS_INIT);
                subTmsShipbillDetailModel.setUnitVolume(rsItemInfo.getVolume());
                subTmsShipbillDetailModel.setUnitWeight(rsItemInfo.getWeight());
                subTmsShipbillDetailModel.setPlanStatus(null);
                tmsShipbillDetailMapper.save(subTmsShipbillDetailModel);

                if (ToolKits.isNotEmpty(subTmsShipbillDetailModel.getPcs())) {
                    newGoodsTotalPcs = newGoodsTotalPcs.add(subTmsShipbillDetailModel.getPcs());
                }
                if (ToolKits.isNotEmpty(subTmsShipbillDetailModel.getVolume())) {
                    newGoodsTotalVolume = newGoodsTotalVolume.add(subTmsShipbillDetailModel.getVolume());
                }
                if (ToolKits.isNotEmpty(subTmsShipbillDetailModel.getWeight())) {
                    newGoodsTotalWeight = newGoodsTotalWeight.add(subTmsShipbillDetailModel.getWeight());
                }
                if (DataDictionaryConstant.SCAN_STATUS_INIT.equals(newShibillDetail.getScanStatus())) {
                    tmsShipbillDetailMapper.deleteById(newShibillDetail.getId(), TmsShipbillDetailModel.class);
                } else {
                    newShibillDetail.setPcs(newShibillDetail.getExtNum5());
                    newShibillDetail.setOrigPcs(newShibillDetail.getOrigPcs().subtract(newShibillDetail.getExtNum5()));
                    newShibillDetail.setWeight(newShibillDetail.getPcs().multiply(rsItemInfo.getWeight()));
                    newShibillDetail.setVolume(newShibillDetail.getPcs().multiply(rsItemInfo.getVolume()));
                    newShibillDetail.setUpdateperson(user.getNickname());
                    newShibillDetail.setUpdatetime(DateUtil.date());
                    newShibillDetail.setExtNum5(null);
                    tmsShipbillDetailMapper.update(newShibillDetail);
                }
            }
            // 作成运单
            TmsShipbillHeaderModel newHeaderModel = new TmsShipbillHeaderModel();
            TmsShipbillHeaderModel oldHeaderModel = tmsShipbillHeaderMapper.findById(addDetailModels.get(0).getShipbillId(), TmsShipbillHeaderModel.class);
            BeanUtils.copyProperties(oldHeaderModel, newHeaderModel);
            newHeaderModel.setShipbillId(newShipbillId);
            newHeaderModel.setShipbillNo(newShipbillId);
            // 总件数
            newHeaderModel.setTotalPcs(newGoodsTotalPcs);
            // 总体积
            newHeaderModel.setTotalVolume(newGoodsTotalVolume);
            // 总重量
            newHeaderModel.setTotalWeight(newGoodsTotalWeight);
            // 实际总件数
            newHeaderModel.setActualTotalPcs(newGoodsTotalPcs);
            // 实际总体积
            newHeaderModel.setActualTotalVolume(newGoodsTotalVolume);
            // 实际总重量
            newHeaderModel.setActualTotalWeight(newGoodsTotalWeight);
            newHeaderModel.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_REVIEW);
            newHeaderModel.setSplitOrderStatus(DataDictionaryConstant.SPLIT_ORDER_STATUS_UN);
            newHeaderModel.setSplitOrderType(DataDictionaryConstant.SPLIT_ORDER_TYPE_UN);
            newHeaderModel.setCarrierSplitOrderStatus(DataDictionaryConstant.CARRIER_SPLIT_ORDER_STATUS_UN);
            newHeaderModel.setCarrierSplitOrderType(DataDictionaryConstant.CARRIER_SPLIT_ORDER_TYPE_UN);
            newHeaderModel.setCreateperson(user.getNickname());
            newHeaderModel.setCreatetime(DateUtil.date());
            newHeaderModel.setShipbillType(ShipBillTypeEnum.NORMAL.getCode());
            newHeaderModel.setSignInStatus(SignInStatusEnum.NOT_SIGN.getCode());
            newHeaderModel.setDriverReceiveStatus(DriverReceiveStatusEnum.N.getCode());

            if (ToolKits.isNotEmpty(oldHeaderModel.getFatherShipbillId())) {
                newHeaderModel.setFatherShipbillId(oldHeaderModel.getOriginalShipbillId());
                newHeaderModel.setFatherShipbillNo(oldHeaderModel.getOriginalShipbillNo());
                newHeaderModel.setOriginalShipbillId(oldHeaderModel.getOriginalShipbillId());
                newHeaderModel.setOriginalShipbillNo(oldHeaderModel.getOriginalShipbillNo());
            }
            newHeaderModel.setIntelligentLock(IntelligentLockEnum.UN_LOCK.getCode());
            tmsShipbillHeaderMapper.save(newHeaderModel);

            // 初期化订单运输记录表
            saveTransportLog(newHeaderModel.getShipbillId(), DateUtil.date(), newHeaderModel.getEstimatedPickupStartTime());

            // 子运单日志保存
            ShipbillOperateLogSaveNewVO subShipbillOperateLogSaveVO = new ShipbillOperateLogSaveNewVO();
            subShipbillOperateLogSaveVO.setShipbillId(newHeaderModel.getShipbillId());
            subShipbillOperateLogSaveVO.setShipbillNo(newHeaderModel.getShipbillNo());
            subShipbillOperateLogSaveVO.setOperateDate(DateUtil.date());
            subShipbillOperateLogSaveVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_NODE_SCAN_NEW);
            subShipbillOperateLogSaveVO.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_YTJ);
            subShipbillOperateLogSaveVO.setNewStatus(newHeaderModel.getStatus());

            subShipbillOperateLogSaveVO.setUserId(user.getUserid());
            subShipbillOperateLogSaveVO.setUserName(user.getNickname());
            subShipbillOperateLogSaveVO.setEnterpriseId(user.getEnterpriseId());
            subShipbillOperateLogSaveVO.setEnterpriseName(user.getEnterpriseName());
            shipbillOperateLogService.addShipbillOperateLogNewData(subShipbillOperateLogSaveVO);

            // 运单节点保存
            ShipbillNodeTrackingSaveNewVO shipbillNodeTrackingSaveVO = new ShipbillNodeTrackingSaveNewVO();
            shipbillNodeTrackingSaveVO.setShipbillId(newHeaderModel.getShipbillId());
            shipbillNodeTrackingSaveVO.setShipbillNo(newHeaderModel.getShipbillId());
            shipbillNodeTrackingSaveVO.setNodeDate(DateUtil.date());
            shipbillNodeTrackingSaveVO.setStatus(newHeaderModel.getStatus());
            shipbillNodeTrackingSaveVO.setNodeEvent(DataDictionaryConstant.SHIPBILL_NODE_SCAN_NEW);

            shipbillNodeTrackingSaveVO.setUserId(user.getUserid());
            shipbillNodeTrackingSaveVO.setUserName(user.getNickname());
            shipbillNodeTrackingSaveVO.setEnterpriseId(user.getEnterpriseId());
            shipbillNodeTrackingSaveVO.setEnterpriseName(user.getEnterpriseName());
            shipbillNodeTrackingService.addShipbillNodeTrackingNewData(shipbillNodeTrackingSaveVO);

            if (ToolKits.isNotEmpty(oldHeaderModel.getTotalPcs()) && BigDecimal.ZERO.compareTo(oldHeaderModel.getTotalPcs()) < 0) {
                oldHeaderModel.setTotalPcs(oldHeaderModel.getTotalPcs().subtract(newHeaderModel.getTotalPcs()));
            }
            if (ToolKits.isNotEmpty(oldHeaderModel.getTotalWeight()) && BigDecimal.ZERO.compareTo(oldHeaderModel.getTotalWeight()) < 0) {
                oldHeaderModel.setTotalWeight(oldHeaderModel.getTotalWeight().subtract(newHeaderModel.getTotalWeight()));
            }
            if (ToolKits.isNotEmpty(oldHeaderModel.getTotalVolume()) && BigDecimal.ZERO.compareTo(oldHeaderModel.getTotalVolume()) < 0) {
                oldHeaderModel.setTotalVolume(oldHeaderModel.getTotalVolume().subtract(newHeaderModel.getTotalVolume()));
            }
            oldHeaderModel.setActualTotalPcs(oldHeaderModel.getTotalPcs());
            oldHeaderModel.setActualTotalWeight(oldHeaderModel.getTotalWeight());
            oldHeaderModel.setActualTotalVolume(oldHeaderModel.getTotalVolume());
            oldHeaderModel.setUpdateperson(user.getNickname());
            oldHeaderModel.setUpdatetime(DateUtil.date());
            tmsShipbillHeaderMapper.update(oldHeaderModel);

            Restriction r1 = Restrictions.eq("shipbillId", oldHeaderModel.getShipbillId());
            Restriction r2 = Restrictions.eq("enterpriseId", user.getEnterpriseId());

            Criteria criteriaLoadingDetail = Criteria.forClass(TmsLoadingBillDetailModel.class);
            criteriaLoadingDetail.setRestriction(Restrictions.and(r1, r2));
            criteriaLoadingDetail.setOrder(Order.newInstance().desc(new String[]{"createtime"}));
            List<TmsLoadingBillDetailModel> loadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteriaLoadingDetail);
            if (ToolKits.isEmpty(loadingBillDetailModels)) {
                continue;
            }
            TmsLoadingBillDetailModel loadingBillDetailModel = loadingBillDetailModels.get(0);
            loadingBillDetailModel.setActualTotalPcs(oldHeaderModel.getTotalPcs());
            loadingBillDetailModel.setActualTotalWeight(oldHeaderModel.getTotalWeight());
            loadingBillDetailModel.setActualTotalVolume(oldHeaderModel.getTotalVolume());
            loadingBillDetailModel.setUpdateperson(user.getNickname());
            loadingBillDetailModel.setUpdatetime(DateUtil.date());
            tmsLoadingBillDetailMapper.update(loadingBillDetailModel);

            TmsLoadingBillHeaderModel loadingBillHeaderModel = tmsLoadingBillHeaderMapper.findById(loadingBillDetailModel.getLoadingBillId(), TmsLoadingBillHeaderModel.class);
            if (ToolKits.isEmpty(loadingBillHeaderModel)) {
                continue;
            }
            if (ToolKits.isNotEmpty(loadingBillHeaderModel.getTotalPcs()) && BigDecimal.ZERO.compareTo(loadingBillHeaderModel.getTotalPcs()) < 0) {
                loadingBillHeaderModel.setTotalPcs(loadingBillHeaderModel.getTotalPcs().subtract(newHeaderModel.getTotalPcs()));
            }
            if (ToolKits.isNotEmpty(loadingBillHeaderModel.getTotalWeight()) && BigDecimal.ZERO.compareTo(loadingBillHeaderModel.getTotalWeight()) < 0) {
                loadingBillHeaderModel.setTotalWeight(loadingBillHeaderModel.getTotalWeight().subtract(newHeaderModel.getTotalWeight()));
            }
            if (ToolKits.isNotEmpty(loadingBillHeaderModel.getTotalVolume()) && BigDecimal.ZERO.compareTo(loadingBillHeaderModel.getTotalVolume()) < 0) {
                loadingBillHeaderModel.setTotalVolume(loadingBillHeaderModel.getTotalVolume().subtract(newHeaderModel.getTotalVolume()));
            }
            loadingBillHeaderModel.setActualTotalPcs(loadingBillHeaderModel.getTotalPcs());
            loadingBillHeaderModel.setActualTotalWeight(loadingBillHeaderModel.getTotalWeight());
            loadingBillHeaderModel.setActualTotalVolume(loadingBillHeaderModel.getTotalVolume());
            loadingBillHeaderModel.setUpdateperson(user.getNickname());
            loadingBillHeaderModel.setUpdatetime(DateUtil.date());
            tmsLoadingBillHeaderMapper.update(loadingBillHeaderModel);
        }
    }

    public void saveTransportLog(String shipbillId, Date date, Date pickUpStartDt) {
        TmsShipbillTransLogModel logModel = new TmsShipbillTransLogModel();
        String id = mainDataProxy.getCodeNumberByCode(SeriaNnumberConstant.TMS_SHIPBILL_TRANSPORT_LOG_ID);
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        logModel.setId(id);
        logModel.setShipbillId(shipbillId);
        logModel.setShipbillNo(shipbillId);

        logModel.setOrderDt(date);
        logModel.setCommitDt(date);
        logModel.setReviewDt(date);
        logModel.setEstimatedPickupStartTime(pickUpStartDt);
        logModel.setEnterpriseId(user.getEnterpriseId());
        logModel.setEnterpriseName(user.getEnterpriseName());
        logModel.setCreateperson(user.getNickname());
        logModel.setCreatetime(date);
        logModel.setUpdateperson(user.getNickname());
        logModel.setUpdatetime(date);

        tmsShipbillTransportLogMapper.save(logModel);
    }

    private void updateShipBillPcsWeightVolume(List<String> updateShipBillIds) {
        if (ToolKits.isEmpty(updateShipBillIds)) {
            return;
        }
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        Set<String> loadingIdSet = Sets.newHashSet();
        Set<String> appointmentIdSet = Sets.newHashSet();
        Criteria criteriaAppointmentDetail = Criteria.forClass(TmsAppointmentDetailModel.class);
        Criteria criteriaLoadingBillDetail = Criteria.forClass(TmsLoadingBillDetailModel.class);
        for (String shipbillId:updateShipBillIds) {
            Criteria criteriaShipbillDetail = Criteria.forClass(TmsShipbillDetailModel.class);
            Restriction r1 = Restrictions.eq(TmsShipbillDetailModel::getShipbillId, shipbillId);
            Restriction r2 = Restrictions.eq(TmsShipbillDetailModel::getEnterpriseId, user.getEnterpriseId());
            criteriaShipbillDetail.setRestriction(Restrictions.and(r1,r2));
            List<TmsShipbillDetailModel> shipbillDetailModels = tmsShipbillDetailMapper.findByCriteria(criteriaShipbillDetail);
            if (ToolKits.isEmpty(shipbillDetailModels)) {
                continue;
            }
            BigDecimal totalPcs = shipbillDetailModels.stream().map(TmsShipbillDetailModel::getPcs).reduce(BigDecimal.ZERO,NumberUtil::add);
            BigDecimal totalWeight = shipbillDetailModels.stream().map(TmsShipbillDetailModel::getWeight).reduce(BigDecimal.ZERO,NumberUtil::add);
            BigDecimal totalVolume = shipbillDetailModels.stream().map(TmsShipbillDetailModel::getVolume).reduce(BigDecimal.ZERO,NumberUtil::add);

            TmsShipbillHeaderModel shipbillHeaderModel = tmsShipbillHeaderMapper.findById(shipbillId,TmsShipbillHeaderModel.class);
            if (ToolKits.isEmpty(shipbillHeaderModel)) {
                continue;
            }
            shipbillHeaderModel.setTotalPcs(totalPcs);
            shipbillHeaderModel.setTotalWeight(totalWeight);
            shipbillHeaderModel.setTotalVolume(totalVolume);
            shipbillHeaderModel.setActualTotalPcs(totalPcs);
            shipbillHeaderModel.setActualTotalWeight(totalWeight);
            shipbillHeaderModel.setActualTotalVolume(totalVolume);
            shipbillHeaderModel.setUpdateperson(user.getNickname());
            shipbillHeaderModel.setUpdatetime(DateUtil.date());
            tmsShipbillHeaderMapper.update(shipbillHeaderModel);

            // 修改调度单的件重体
            Restriction r3 = Restrictions.eq(TmsLoadingBillDetailModel::getShipbillId, shipbillId);
            Restriction r4 = Restrictions.eq(TmsLoadingBillDetailModel::getEnterpriseId, user.getEnterpriseId());
            criteriaLoadingBillDetail.setRestriction(Restrictions.and(r3, r4));
            criteriaLoadingBillDetail.setOrder(Order.newInstance().desc(new String[] { "createtime" }));
            List<TmsLoadingBillDetailModel> loadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteriaLoadingBillDetail);
            if (ToolKits.isEmpty(loadingBillDetailModels)) {
                continue;
            }
            // 修改第一条明细
            for (TmsLoadingBillDetailModel loadingBillDetail : loadingBillDetailModels) {
                loadingBillDetail.setTotalPcs(totalPcs);
                loadingBillDetail.setTotalVolume(totalVolume);
                loadingBillDetail.setTotalWeight(totalWeight);
                loadingBillDetail.setActualTotalPcs(totalPcs);
                loadingBillDetail.setActualTotalVolume(totalVolume);
                loadingBillDetail.setActualTotalWeight(totalWeight);
                loadingBillDetail.setUpdateperson(user.getNickname());
                loadingBillDetail.setUpdatetime(DateUtil.date());
                tmsLoadingBillDetailMapper.update(loadingBillDetail);

                loadingIdSet.add(loadingBillDetail.getLoadingBillId());
                break;
            }
            // 修改预约单的件重体
            Restriction r5 = Restrictions.eq(TmsAppointmentDetailModel::getShipbillId, shipbillId);
            Restriction r6 = Restrictions.eq(TmsAppointmentDetailModel::getEnterpriseId, user.getEnterpriseId());
            criteriaAppointmentDetail.setRestriction(Restrictions.and(r5, r6));
            List<TmsAppointmentDetailModel> appointmentDetailModels = tmsAppointmentDetailMapper.findByCriteria(criteriaAppointmentDetail);
            if (ToolKits.isEmpty(appointmentDetailModels)) {
                continue;
            }
            for (TmsAppointmentDetailModel appointmentDetailModel : appointmentDetailModels) {
                appointmentDetailModel.setTotalPcs(totalPcs);
                appointmentDetailModel.setTotalVolume(totalVolume);
                appointmentDetailModel.setTotalWeight(totalWeight);
                appointmentDetailModel.setActualTotalPcs(totalPcs);
                appointmentDetailModel.setActualTotalVolume(totalVolume);
                appointmentDetailModel.setActualTotalWeight(totalWeight);
                appointmentDetailModel.setUpdateperson(user.getNickname());
                appointmentDetailModel.setUpdatetime(DateUtil.date());
                tmsAppointmentDetailMapper.update(appointmentDetailModel);
                appointmentIdSet.add(appointmentDetailModel.getAppointmentId());
            }
        }
        for (String appointmentId : appointmentIdSet) {
            Restriction r5 = Restrictions.eq(TmsAppointmentDetailModel::getAppointmentId, appointmentId);
            Restriction r6 = Restrictions.eq(TmsAppointmentDetailModel::getEnterpriseId, user.getEnterpriseId());
            criteriaAppointmentDetail.setRestriction(Restrictions.and(r5, r6));
            List<TmsAppointmentDetailModel> appointmentDetailModelList = tmsAppointmentDetailMapper.findByCriteria(criteriaAppointmentDetail);
            if (ToolKits.isNotEmpty(appointmentDetailModelList)) {
                BigDecimal hTotalPcs = appointmentDetailModelList.stream().map(TmsAppointmentDetailModel::getTotalPcs).reduce(BigDecimal.ZERO, NumberUtil::add);
                BigDecimal hTotalWeigth = appointmentDetailModelList.stream().map(TmsAppointmentDetailModel::getTotalWeight).reduce(BigDecimal.ZERO, NumberUtil::add);
                BigDecimal hTotalVolume = appointmentDetailModelList.stream().map(TmsAppointmentDetailModel::getTotalVolume).reduce(BigDecimal.ZERO, NumberUtil::add);

                TmsAppointmentHeaderModel appointmentHeaderModel = tmsAppointmentHeaderMapper.findById(appointmentId, TmsAppointmentHeaderModel.class);
                if (ToolKits.isNotEmpty(appointmentHeaderModel)) {
                    appointmentHeaderModel.setTotalPcs(hTotalPcs);
                    appointmentHeaderModel.setTotalVolume(hTotalVolume);
                    appointmentHeaderModel.setTotalWeight(hTotalWeigth);
                    appointmentHeaderModel.setUpdateperson(user.getNickname());
                    appointmentHeaderModel.setUpdatetime(DateUtil.date());
                    tmsAppointmentHeaderMapper.update(appointmentHeaderModel);
                }
            }
        }

        for (String loadingId : loadingIdSet) {
            Restriction r5 = Restrictions.eq(TmsLoadingBillDetailModel::getLoadingBillId, loadingId);
            Restriction r6 = Restrictions.eq(TmsLoadingBillDetailModel::getEnterpriseId, user.getEnterpriseId());
            criteriaLoadingBillDetail.setRestriction(Restrictions.and(r5, r6));
            List<TmsLoadingBillDetailModel> loadingBillDetailModelList = tmsLoadingBillDetailMapper.findByCriteria(criteriaLoadingBillDetail);
            if (ToolKits.isNotEmpty(loadingBillDetailModelList)) {
                BigDecimal hTotalPcs = loadingBillDetailModelList.stream().map(TmsLoadingBillDetailModel::getTotalPcs).reduce(BigDecimal.ZERO, NumberUtil::add);
                BigDecimal hTotalWeigth = loadingBillDetailModelList.stream().map(TmsLoadingBillDetailModel::getTotalWeight).reduce(BigDecimal.ZERO, NumberUtil::add);
                BigDecimal hTotalVolume = loadingBillDetailModelList.stream().map(TmsLoadingBillDetailModel::getTotalVolume).reduce(BigDecimal.ZERO, NumberUtil::add);

                TmsLoadingBillHeaderModel loadingBillHeaderModel = tmsLoadingBillHeaderMapper.findById(loadingId, TmsLoadingBillHeaderModel.class);
                if (ToolKits.isNotEmpty(loadingBillHeaderModel)) {
                    loadingBillHeaderModel.setTotalPcs(hTotalPcs);
                    loadingBillHeaderModel.setTotalVolume(hTotalVolume);
                    loadingBillHeaderModel.setTotalWeight(hTotalWeigth);
                    loadingBillHeaderModel.setActualTotalPcs(loadingBillHeaderModel.getTotalPcs());
                    loadingBillHeaderModel.setActualTotalVolume(loadingBillHeaderModel.getTotalVolume());
                    loadingBillHeaderModel.setActualTotalWeight(loadingBillHeaderModel.getTotalWeight());
                    loadingBillHeaderModel.setUpdateperson(user.getNickname());
                    loadingBillHeaderModel.setUpdatetime(DateUtil.date());
                    tmsLoadingBillHeaderMapper.update(loadingBillHeaderModel);
                }
            }
        }
    }
}
