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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
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.prolog.common.util.DateUtils;
import com.prolog.common.util.ToolKits;
import com.prolog.framework.common.message.RestMessage;
import com.prolog.framework.core.exception.BizException;
import com.prolog.framework.core.exception.PrologException;
import com.prolog.framework.core.restriction.Criteria;
import com.prolog.framework.core.restriction.Order;
import com.prolog.framework.core.restriction.Restriction;
import com.prolog.framework.core.restriction.Restrictions;
import com.prolog.framework.utils.ObjectUtils;
import com.prolog.product.core.framework.entity.UserEntity;
import com.prolog.product.core.framework.util.PlgFxUsrUtils;
import com.prolog.rdc.tms.app.constant.BussinessConstant;
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.*;
import com.prolog.rdc.tms.app.model.entity.*;
import com.prolog.rdc.tms.app.model.vo.*;
import com.prolog.rdc.tms.app.model.vo.business.AddShipbillEventFeedbackVO;
import com.prolog.rdc.tms.app.model.vo.business.ShipbillNodeTrackingSaveNewVO;
import com.prolog.rdc.tms.app.model.vo.business.ShipbillOperateLogSaveNewVO;
import com.prolog.rdc.tms.app.proxy.MainDataProxy;
import com.prolog.rdc.tms.app.service.PendingPickUpService;
import com.prolog.rdc.tms.app.service.business.*;
import com.prolog.rdc.tms.app.util.*;
import com.prolog.rdc.tms.model.constant.RedisConstant;
import com.prolog.rdc.tms.model.dto.DeviceByOneDTO;
import com.prolog.rdc.tms.model.dto.basicData.ItemCheckDTO;
import com.prolog.rdc.tms.model.dto.basicData.TmsBaseBranchApTimeDTO;
import com.prolog.rdc.tms.model.dto.basicData.TmsBaseBranchDTO;
import com.prolog.rdc.tms.model.dto.basicData.TmsBaseCarportDTO;
import com.prolog.rdc.tms.model.dto.message.SendMessageDTO;
import com.prolog.rdc.tms.model.enums.MessageOrderTypeEnum;
import com.prolog.rdc.tms.model.enums.MessageTypeEnum;
import com.prolog.rdc.tms.model.vo.basicConfigure.ApprovalOpenVO;
import com.prolog.rdc.tms.model.vo.basicData.ItemCheckVO;
import com.prolog.rdc.tms.model.vo.fleetManagement.VehicleGpsSaveVO;
import com.prolog.rdc.tms.rmi.feign.MaindataFeign;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 *
 *
 * 司机APP-待提货实现层
 *
 * @className :PendingAppointmentServiceImpl
 * @author :qian.yh
 * @creationTime :2022/07/04
 * @description :
 *
 * @modifier :
 * @modifyTime :
 * @reviseRemarks:
 *
 * @version :1.0.0
 *
 */
@Slf4j
@Service
public class PendingPickUpServiceImpl implements PendingPickUpService {
	@Resource
	private TmsShipbillHeaderMapper tmsShipbillHeaderMapper;

	@Resource
	private TmsLoadingBillDetailMapper tmsLoadingBillDetailMapper;

	@Resource
	private TmsShipbillTransportLogMapper tmsShipbillTransportLogMapper;

	@Resource
	private TmsAppointmentHeaderMapper tmsAppointmentHeaderMapper;

	@Resource
	private TmsShipbillNodeTrackingMapper tmsShipbillNodeTrackingMapper;

	@Resource
	private TmsShipbillOperateLogMapper tmsShipbillOperateLogMapper;

	@Resource
	private TmsAppointmentDetailMapper tmsAppointmentDetailMapper;

	@Resource
	private TmsLoadingBillHeaderMapper tmsLoadingBillHeaderMapper;

	@Autowired
	private ShipbillOperateLogService shipbillOperateLogService;

	@Autowired
	private ShipbillNodeTrackingService shipbillNodeTrackingService;

	@Autowired
	private TmsShipbillDetailMapper tmsShipbillDetailMapper;

	@Resource
	private MaindataFeign maindataFeign;

	@Autowired
	private LoadingBillService loadingBillService;

	@Autowired
	private MainDataProxy mainDataProxy;

	@Autowired
	private AutoSignJudge autoSignJudge;

	@Autowired
	private TmsShipbillHeaderTempMapper tmsShipbillHeaderTempMapper;

	@Autowired
	private TmsShipbillDetailTempMapper tmsShipbillDetailTempMapper;

	@Autowired
	private ShipbillEventFeedbackService shipbillEventFeedbackService;

	@Autowired
	private PendingReceiptService pendingReceiptService;

	@Autowired
	private RedisTemplate redisTemplate;

	@Autowired
	private TmsShipbillContainerTempMapper shipbillContainerTempMapper;

	@Autowired
	private BusinessFlowUtil businessFlowUtil;

	/**
	 * 提货任务数汇总查询
	 */
	@Override
	public List<PendingPickUpQueryDTO> pendingPickUpQuery(PendingPickUpQueryVO pendingPickUpQueryVO) throws Exception {
		ToolKits.isParamNull(pendingPickUpQueryVO, "司机待预约汇总查询请求参数不为空");
		ToolKits.isParamNull(pendingPickUpQueryVO.getDriverId(), "司机ID不为空");
		ToolKits.isParamNull(pendingPickUpQueryVO.getVehiclePlateNumber(), "车牌号不为空");
		ToolKits.isParamNull(pendingPickUpQueryVO.getEnterpriseId(), "企业ID不能为空");
		List<PendingPickUpQueryDTO> dtos = Lists.newArrayList();
		dtos = tmsShipbillHeaderMapper.pendingPickUpQuery(pendingPickUpQueryVO);
		if (ObjectUtils.isEmpty(dtos)) {
			return dtos;
		}

		// STD-DEVELOP20220823 lhb 自动签到 20220901 start
		// 判断是否 自动提货签到
		if (ToolKits.isNotEmpty(pendingPickUpQueryVO.getDriverLongitude()) && ToolKits.isNotEmpty(pendingPickUpQueryVO.getDriverLatitude())) {
			List<String> shipbills = Lists.newArrayList();
			for (PendingPickUpQueryDTO pickUpQueryDTO : dtos) {
				if (pickUpQueryDTO.getShipperPickUpRail().doubleValue() > 0 && pickUpQueryDTO.getStatus().intValue() == DataDictionaryConstant.SHIPBILL_STATUS_QY.intValue() && ToolKits.isNotEmpty(pickUpQueryDTO.getShipfromLongitude()) && ToolKits.isNotEmpty(pickUpQueryDTO.getShipfromLatitude()) && pickUpQueryDTO.getShipperPickUpSign().intValue() > 0 && pickUpQueryDTO.getShipperAutoPickUpSign().intValue() > 0) {
					// 司机和仓库之间的距离
					double pos = DistanceUtil.getDistance(pendingPickUpQueryVO.getDriverLongitude().doubleValue(), pendingPickUpQueryVO.getDriverLatitude().doubleValue(), Double.valueOf(pickUpQueryDTO.getShipfromLongitude()).doubleValue(), Double.valueOf(pickUpQueryDTO.getShipfromLatitude()).doubleValue());
					if (Double.compare(pos, pickUpQueryDTO.getShipperPickUpRail().doubleValue()) <= 0) {
						shipbills.add(pickUpQueryDTO.getShipbillIds());
					}
				}
			}
			List<String> autoCheckInShipbills = Lists.newArrayList();
			if (ToolKits.isNotEmpty(shipbills)) {
				shipbills.stream().forEach(id -> {
					// 是否在自动签到时间范围内
					if (autoSignJudge.autoSignJudge(id,"1")) {
						autoCheckInShipbills.add(id);
					}
				});
			}
			if (ToolKits.isNotEmpty(autoCheckInShipbills)) {
				PendingPickUpSignInVO signInVO = new PendingPickUpSignInVO();
				signInVO.setShipbillIds(autoCheckInShipbills.stream().collect(Collectors.joining(",")));
				// 调用提货签到
				pendingPickUpSignIn(signInVO);

				// 重新查询
				dtos = tmsShipbillHeaderMapper.pendingPickUpQuery(pendingPickUpQueryVO);
				if (ObjectUtils.isEmpty(dtos)) {
					return dtos;
				}
			}
		}

		dtos.forEach(dto -> {
			if (StrUtil.isBlank(dto.getDriverReceiveStatus())) {
				dto.setDriverReceiveStatus(DriverReceiveStatusEnum.N.getCode());
			} else {
				if (Arrays.stream(dto.getDriverReceiveStatus().split(",")).allMatch(s -> DriverReceiveStatusEnum.A.getCode().equals(s))) {
					dto.setDriverReceiveStatus(DriverReceiveStatusEnum.A.getCode());
				} else {
					dto.setDriverReceiveStatus(DriverReceiveStatusEnum.N.getCode());
				}
			}
			List<TmsShipbillHeaderModel> tmsShipbillHeaderModelList =
					tmsShipbillHeaderMapper.findByIds(TmsShipbillHeaderModel.class, dto.getShipbillIds().split(","), null);
			if (CollectionUtil.isNotEmpty(tmsShipbillHeaderModelList)) {
				List<TmsShipbillHeaderModel> filterContainer = tmsShipbillHeaderModelList.stream().filter(tmsShipbillHeaderModel -> StrUtil.isNotBlank(tmsShipbillHeaderModel.getContainerId())).collect(Collectors.toList());
				dto.setContainerId(filterContainer.stream().flatMap(tmsShipbillHeaderModel -> Arrays.stream(tmsShipbillHeaderModel.getContainerId().split(","))).distinct().collect(Collectors.joining(",")));
				dto.setContainerCode(filterContainer.stream().flatMap(tmsShipbillHeaderModel -> Arrays.stream(tmsShipbillHeaderModel.getContainerCode().split(","))).distinct().collect(Collectors.joining(",")));
				dto.setContainerName(filterContainer.stream().flatMap(tmsShipbillHeaderModel -> Arrays.stream(tmsShipbillHeaderModel.getContainerName().split(","))).distinct().collect(Collectors.joining(",")));
				List<TmsShipbillHeaderModel> filterVehicleDevice = tmsShipbillHeaderModelList.stream().filter(tmsShipbillHeaderModel -> StrUtil.isNotBlank(tmsShipbillHeaderModel.getVehicleDeviceId())).collect(Collectors.toList());
				dto.setVehicleDeviceId(filterVehicleDevice.stream().flatMap(tmsShipbillHeaderModel -> Arrays.stream(tmsShipbillHeaderModel.getVehicleDeviceId().split(","))).distinct().collect(Collectors.joining(",")));
				dto.setVehicleDeviceCode(filterVehicleDevice.stream().flatMap(tmsShipbillHeaderModel -> Arrays.stream(tmsShipbillHeaderModel.getVehicleDeviceCode().split(","))).distinct().collect(Collectors.joining(",")));
				dto.setVehicleDeviceName(filterVehicleDevice.stream().flatMap(tmsShipbillHeaderModel -> Arrays.stream(tmsShipbillHeaderModel.getVehicleDeviceName().split(","))).distinct().collect(Collectors.joining(",")));
			}
		});
		// STD-DEVELOP20220823 lhb 自动签到 20220901 end
		return dtos;
	}

	/**
	 * 提货任务明细查询
	 */
	@Override
	public List<PendingPickUpDetailQueryDTO> pendingPickUpDetailQuery(PendingPickUpDetailQueryVO pendingPickUpDetailQueryVO) throws Exception {
		ToolKits.isParamNull(pendingPickUpDetailQueryVO, "司机待预约明细查询请求参数不为空");
		ToolKits.isParamNull(pendingPickUpDetailQueryVO.getShipbillIds(), "选择的运单ID不为空");
		ToolKits.isParamNull(pendingPickUpDetailQueryVO.getDriverId(), "司机ID不为空");
		ToolKits.isParamNull(pendingPickUpDetailQueryVO.getVehiclePlateNumber(), "车牌号不为空");
		ToolKits.isParamNull(pendingPickUpDetailQueryVO.getEnterpriseId(), "企业ID不能为空");
		ToolKits.isParamNull(pendingPickUpDetailQueryVO.getShipfrom(), "发货地ID不能为空");
		// ToolKits.isParamNull(pendingPickUpDetailQueryVO.getShipfromDate(),
		// "预计发货时间不能为空");

		String[] shipbillIds = pendingPickUpDetailQueryVO.getShipbillIds().split(",");
		List<TmsShipbillHeaderModel> shipbillHeaderModels = tmsShipbillHeaderMapper.findByIds(TmsShipbillHeaderModel.class, shipbillIds, null);
		if (ObjectUtils.isEmpty(shipbillHeaderModels)) {
			throw new RuntimeException("未找到对应的运单明细！");
		}

		List<PendingPickUpDetailQueryDTO> returndtos = new ArrayList<PendingPickUpDetailQueryDTO>();
		for (TmsShipbillHeaderModel headerModel : shipbillHeaderModels) {
			PendingPickUpDetailQueryDTO dto = new PendingPickUpDetailQueryDTO();

			dto.setShipbillId(headerModel.getShipbillId());
			dto.setEnterpriseId(pendingPickUpDetailQueryVO.getEnterpriseId());
			dto.setDriverId(pendingPickUpDetailQueryVO.getDriverId());
			dto.setShipbillNo(headerModel.getShipbillNo());
			dto.setOrderDate(headerModel.getOrderDate());
			dto.setShipfromId(String.valueOf(headerModel.getShipperId()));
			dto.setShipfromCode(headerModel.getShipperCode());
			dto.setShipfromName(headerModel.getShipperName());
			dto.setShipfromAddress(headerModel.getShipperAddress());
			dto.setShipfromDate(headerModel.getEstimatedPickupStartTime());
			dto.setLoadingBillId(loadingBillService.getLoadingBillIdByShipBillId(headerModel.getShipbillId()));

			dto.setShipToCode(String.valueOf(headerModel.getConsigneeId()));
			dto.setShipToName(headerModel.getConsigneeName());
			dto.setShipToAddress(headerModel.getConsigneeAddress());
			dto.setShipToConsignee(headerModel.getConsigneeContact());
			dto.setShipToConsigneeMobel(headerModel.getConsigneePhoneNumber());
			dto.setShipToConsigneeTel(headerModel.getConsigneeLandlineNumber());

			ShipbillDetailQueryVO vo = new ShipbillDetailQueryVO();
			vo.setEnterpriseId(dto.getEnterpriseId());
			vo.setShipbillId(dto.getShipbillId());
			List<ShipbillItemDetailQueryDTO> itemDetails = tmsShipbillHeaderMapper.shipbillItemDetailQuery(vo);
			dto.setItemDetail(itemDetails);
			dto.setPackageDetailDTOList(pendingReceiptService.getPackageDetailDTO(dto.getShipbillId()));

			returndtos.add(dto);
		}
		return returndtos;
	}

	/**
	 * 提货签到
	 */
	@Override
	public void pendingPickUpSignIn(PendingPickUpSignInVO pendingPickUpSignInVO) throws Exception {
		ToolKits.isParamNull(pendingPickUpSignInVO, "请求参数不为空");
		ToolKits.isParamNull(pendingPickUpSignInVO.getShipbillIds(), "运单不为空");

		UserEntity user = PlgFxUsrUtils.getUserEntity();
		ToolKits.isParamNull(user, "当前人员没有操作权限");

		Date date = DateUtil.date();

		Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
		Restriction r1 = Restrictions.in(TmsLoadingBillDetailModel::getShipbillId, pendingPickUpSignInVO.getShipbillIds().split(","));
		Restriction r2 = Restrictions.eq(TmsLoadingBillDetailModel::getStatus, DataDictionaryConstant.SHIPBILL_STATUS_QY);
		Restriction r3 = Restrictions.eq(TmsLoadingBillDetailModel::getEnterpriseId, user.getEnterpriseId());
		criteria.setRestriction(Restrictions.and(r1, r2, r3));
		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteria);
		Assert.isTrue(tmsLoadingBillDetailModels.size() != 0, "待签到运单不存在");
		for (TmsLoadingBillDetailModel tmsLoadingBillDetailModel : tmsLoadingBillDetailModels) {
			// 原状态
			Integer oldStatus = tmsLoadingBillDetailModel.getStatus();

			tmsLoadingBillDetailModel.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_THQD);
			tmsLoadingBillDetailModel.setUpdateperson(user.getNickname());
			tmsLoadingBillDetailModel.setUpdatetime(date);
			tmsLoadingBillDetailMapper.update(tmsLoadingBillDetailModel);

			ShipbillOperateLogSaveNewVO shipbillOperateLogSaveNewVO = new ShipbillOperateLogSaveNewVO();
			shipbillOperateLogSaveNewVO.setShipbillId(tmsLoadingBillDetailModel.getShipbillId());
			shipbillOperateLogSaveNewVO.setShipbillNo(tmsLoadingBillDetailModel.getShipbillId());
			shipbillOperateLogSaveNewVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_QYQD);
			shipbillOperateLogSaveNewVO.setOldStatus(oldStatus);
			shipbillOperateLogSaveNewVO.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_QY);
			shipbillOperateLogSaveNewVO.setOperateDate(DateUtil.date());
			shipbillOperateLogSaveNewVO.setEnterpriseId(user.getEnterpriseId());
			shipbillOperateLogSaveNewVO.setEnterpriseName(user.getEnterpriseName());
			shipbillOperateLogSaveNewVO.setUserId(user.getUserid());
			shipbillOperateLogSaveNewVO.setUserName(user.getNickname());
			shipbillOperateLogService.addShipbillOperateLogNewData(shipbillOperateLogSaveNewVO);

			Map<String, Object> mapUpdate = Maps.newHashMap();
			mapUpdate.put("departureSignTime", date);
			mapUpdate.put("updateperson", user.getNickname());
			mapUpdate.put("updatetime", date);

			// 更新运输记录表
			Criteria criteriaTransportLog = Criteria.forClass(TmsShipbillTransLogModel.class);
			Restriction r4 = Restrictions.eq(TmsShipbillTransLogModel::getEnterpriseId, tmsLoadingBillDetailModel.getEnterpriseId());
			Restriction r5 = Restrictions.eq(TmsShipbillTransLogModel::getShipbillId, tmsLoadingBillDetailModel.getShipbillId());
			criteriaTransportLog.setRestriction(Restrictions.and(r4, r5));
			tmsShipbillTransportLogMapper.updateMapByCriteria(mapUpdate, criteriaTransportLog);
		}
	}

	/**
	 * 提货取号
	 */
	@Override
	public PendingPickUpTakeNumberDTO pendingPickUpTakeNumber(PendingPickUpTakeNumberVO pendingPickUpTakeNumberVO) throws Exception {
		ToolKits.isParamNull(pendingPickUpTakeNumberVO, "请求参数不为空");
		ToolKits.isParamNull(pendingPickUpTakeNumberVO.getBranchId(), "仓库不为空");
		ToolKits.isParamNull(pendingPickUpTakeNumberVO.getAppointmentId(), "请选择预约单");

		UserEntity user = PlgFxUsrUtils.getUserEntity();
		ToolKits.isParamNull(user, "当前人员没有操作权限");

		// 查询仓库信息
		RestMessage<TmsBaseBranchDTO> msg = maindataFeign.getOneBranch(pendingPickUpTakeNumberVO.getBranchId());
		if (!msg.isSuccess()) {
			throw new PrologException("仓库查询接口调用失败：" + msg.getMessage());
		}
		ToolKits.isParamNull(msg.getData(), "仓库ID【" + pendingPickUpTakeNumberVO.getBranchId() + "】不存在");
		// 仓库叫号处理方式
		Integer callMethod = msg.getData().getCallHandleType();
		ToolKits.isParamNull(msg.getData().getApTimeDTOList(), "仓库ID【" + pendingPickUpTakeNumberVO.getBranchId() + "】未维护可预约时间段");

		// 判断仓库是否存在提货等待的车位
		RestMessage<List<TmsBaseCarportDTO>> restMessage = maindataFeign.queryCarportList(pendingPickUpTakeNumberVO.getBranchId());
		if (!restMessage.isSuccess()) {
			throw new PrologException("仓库车位查询接口调用失败：" + restMessage.getMessage());
		}
		List<TmsBaseCarportDTO> filterList = Optional.ofNullable(restMessage.getData()).orElse(new ArrayList<>()).stream().filter(dto -> ObjectUtil.equal(dto.getType(), DataDictionaryConstant.CARPORT_TYPE_THDDQ)).collect(Collectors.toList());
		// 提货等待区车位数
		int count1 = filterList.size();

		// 当前时间
		Date date = DateUtil.date();

		TmsAppointmentHeaderModel tmsAppointmentHeader = tmsAppointmentHeaderMapper.findById(pendingPickUpTakeNumberVO.getAppointmentId(), TmsAppointmentHeaderModel.class);
		Assert.isTrue(ToolKits.isNotEmpty(tmsAppointmentHeader), "预约单查询失败");
		Assert.isTrue(ToolKits.isEmpty(tmsAppointmentHeader.getQueueNumber()), "当前预约单已取号,无需重复取号");
		Assert.isTrue(ToolKits.isNotEmpty(tmsAppointmentHeader.getAppointmentTime()) && tmsAppointmentHeader.getAppointmentTime().indexOf("-") != -1, "预约单【" + tmsAppointmentHeader.getAppointmentNo() + "】预约时间段不能为空或预约时间段数据格式不合法");

		if (count1 == 0) {
			// 不存在提货等待的车位
			tmsAppointmentHeader.setStatus(DataDictionaryConstant.APPOINTMENT_STATUS_YQH);
		} else {
			// 存在 类型为【提货等待区】的仓库车位
			// 查询预约单中,当前仓库下预约单状态为【等待中】的预约单记录条数
			Criteria criteria = Criteria.forClass(TmsAppointmentHeaderModel.class);
			Restriction r1 = Restrictions.eq(TmsAppointmentHeaderModel::getEnterpriseId, user.getEnterpriseId());
			Restriction r2 = Restrictions.eq(TmsAppointmentHeaderModel::getBranchId, pendingPickUpTakeNumberVO.getBranchId());
			Restriction r3 = Restrictions.eq(TmsAppointmentHeaderModel::getStatus, DataDictionaryConstant.APPOINTMENT_STATUS_DDZ);
			criteria.setRestriction(Restrictions.and(r1, r2, r3));
			List<TmsAppointmentHeaderModel> list = tmsAppointmentHeaderMapper.findByCriteria(criteria);
			// 等待区已使用车位数
			int count2 = ToolKits.isEmpty(list) ? 0 : list.size();
			if (count1 - count2 > 0) {
				// 当前仓库下还存在可用的空闲车位,更新当前预约单状态为【等待中】
				tmsAppointmentHeader.setStatus(DataDictionaryConstant.APPOINTMENT_STATUS_DDZ);
			} else {
				// 当前仓库下没有可用的空闲车位,更新当前预约单状态为【已取号】
				tmsAppointmentHeader.setStatus(DataDictionaryConstant.APPOINTMENT_STATUS_YQH);
			}
		}

		// 预约号
		StringBuffer number = new StringBuffer();

		// 获取开始时间段
		String startTime = tmsAppointmentHeader.getAppointmentTime().split("-")[0];
		// 获取开始时间段中的小时部分
		String startHour = startTime.split(":")[0];

		// 获取结束时间段
		String endTime = tmsAppointmentHeader.getAppointmentTime().split("-")[1];
		// 获取结束时间段中的小时部分
		String endhour = endTime.split(":")[0];

		// 预约日期时间
		Date reserveDateTime = DateUtil.parseDateTime(DateUtil.formatDate(tmsAppointmentHeader.getAppointmentDate()) + " " + endTime + ":" + "00");

		// 判断当前时间是否在 当前预约单的预约时间内
		if (date.before(reserveDateTime)) {
			Criteria criteria = Criteria.forClass(TmsAppointmentHeaderModel.class);
			Restriction r1 = Restrictions.eq(TmsAppointmentHeaderModel::getEnterpriseId, user.getEnterpriseId());
			Restriction r2 = Restrictions.eq(TmsAppointmentHeaderModel::getBranchId, pendingPickUpTakeNumberVO.getBranchId());
			Restriction r3 = Restrictions.eq(TmsAppointmentHeaderModel::getAppointmentTime, tmsAppointmentHeader.getAppointmentTime());
			Restriction r4 = Restrictions.eq(TmsAppointmentHeaderModel::getAppointmentType, DataDictionaryConstant.APPOINTMENT_TYPE_TH);
			Restriction r5 = Restrictions.gt(TmsAppointmentHeaderModel::getStatus, DataDictionaryConstant.APPOINTMENT_STATUS_YSH);
			Restriction r6 = Restrictions.between(TmsAppointmentHeaderModel::getQueueNumberTime, DateUtil.beginOfDay(date), DateUtil.endOfDay(date));

			// 判断当前预约单是否包含紧急加急运单
			if (tmsAppointmentHeader.getUrgentQuantity() > 0) {
				number = new StringBuffer("急");

				Restriction r7 = Restrictions.gt(TmsAppointmentHeaderModel::getUrgentQuantity, 0);
				criteria.setRestriction(Restrictions.and(r1, r2, r3, r4, r5, r6, r7));
				List<TmsAppointmentHeaderModel> orderList = tmsAppointmentHeaderMapper.findByCriteria(criteria);

				// 获取最大排队号+1作为当前预约单的排队号，最大排队号为空从001开始
				if (ToolKits.isNotEmpty(orderList) && orderList.size() > 0) {
					// 取出所有排队号
					List<String> queueNumberList = orderList.stream().map(TmsAppointmentHeaderModel::getQueueNumber).collect(Collectors.toList());
					// 排队号转换类型
					List<BigDecimal> queueNumbers = queueNumberList.stream().map(s -> new BigDecimal(s.replace("急", ""))).collect(Collectors.toList());
					// 获取最大排队号
					BigDecimal queueNumberMax = queueNumbers.stream().reduce(queueNumbers.get(0), BigDecimal::max);
					// 自增加1生成当前预约单的取号号码
					number.append(queueNumberMax.add(new BigDecimal("1")));
				} else {
					// 生成今天预约单排队号(年月日+预约时间段开始小时数+预约时间段结束小时数+三位自增数)
					number.append(DateUtil.format(date, DatePattern.PURE_DATE_FORMAT)).append(startHour).append(endhour).append("001");
				}

				// 生成叫号顺序
				this.getCallNumber(user, tmsAppointmentHeader, callMethod, true, date);
			} else {
				Restriction r7 = Restrictions.eq(TmsAppointmentHeaderModel::getUrgentQuantity, 0);
				criteria.setRestriction(Restrictions.and(r1, r2, r3, r4, r5, r6, r7));
				List<TmsAppointmentHeaderModel> orderList = tmsAppointmentHeaderMapper.findByCriteria(criteria);

				// 获取最大排队号+1作为当前预约单的排队号，最大排队号为空从001开始
				if (ToolKits.isNotEmpty(orderList) && orderList.size() > 0) {
					// 取出所有排队号
					List<String> queueNumberList = orderList.stream().map(TmsAppointmentHeaderModel::getQueueNumber).collect(Collectors.toList());
					// 排队号转换类型
					List<BigDecimal> queueNumbers = queueNumberList.stream().map(s -> new BigDecimal(s)).collect(Collectors.toList());
					// 获取最大排队号
					BigDecimal queueNumberMax = queueNumbers.stream().reduce(queueNumbers.get(0), BigDecimal::max);
					// 自增加1生成当前预约单的取号号码
					number.append(queueNumberMax.add(new BigDecimal("1")));
				} else {
					// 生成今天预约单排队号(年月日+预约时间段开始小时数+预约时间段结束小时数+三位自增数)
					number.append(DateUtil.format(date, DatePattern.PURE_DATE_FORMAT)).append(startHour).append(endhour).append("001");
				}

				// 生成叫号顺序
				this.getCallNumber(user, tmsAppointmentHeader, callMethod, false, date);
			}
		} else {
			// 当前仓最后可预约时间
			int maxTime = 0;
			// 仓可预约时间段处理
			List<TmsBaseBranchApTimeDTO> tmsBaseBranchApTimeDTOs = msg.getData().getApTimeDTOList();
			for (TmsBaseBranchApTimeDTO tmsBaseBranchApTimeDTO : tmsBaseBranchApTimeDTOs) {
				int endHour = Integer.parseInt(tmsBaseBranchApTimeDTO.getEndTime().split(":")[0]);
				if (endHour > maxTime) {
					maxTime = endHour;
				}
			}
			// 获取开始时间段中的小时部分
			startHour = String.format("%0" + 2 + "d", maxTime);
			// 获取结束时间段中的小时部分
			endhour = String.format("%0" + 2 + "d", maxTime + 1);

			Criteria criteria = Criteria.forClass(TmsAppointmentHeaderModel.class);
			Restriction r1 = Restrictions.eq(TmsAppointmentHeaderModel::getEnterpriseId, user.getEnterpriseId());
			Restriction r2 = Restrictions.eq(TmsAppointmentHeaderModel::getBranchId, pendingPickUpTakeNumberVO.getBranchId());
			Restriction r3 = Restrictions.between(TmsAppointmentHeaderModel::getQueueNumberTime, DateUtil.beginOfDay(date), DateUtil.endOfDay(date));
			Restriction r4 = Restrictions.eq(TmsAppointmentHeaderModel::getAppointmentType, DataDictionaryConstant.APPOINTMENT_TYPE_TH);
			Restriction r5 = Restrictions.like(TmsAppointmentHeaderModel::getQueueNumber, "%" + startHour + endhour + "%");
			// 判断当前预约单是否包含紧急加急运单
			if (tmsAppointmentHeader.getUrgentQuantity() > 0) {
				// 生成今天预约单排队号(年月日+当前仓库设置的最晚时间段后的一个小时时间段+三位自增数)
				number = new StringBuffer("急");

				Restriction r6 = Restrictions.gt(TmsAppointmentHeaderModel::getUrgentQuantity, 0);
				criteria.setRestriction(Restrictions.and(r1, r2, r3, r4, r5, r6));
				List<TmsAppointmentHeaderModel> orderList = tmsAppointmentHeaderMapper.findByCriteria(criteria);

				// 获取最大排队号+1作为当前预约单的排队号，最大排队号为空从001开始
				if (ToolKits.isNotEmpty(orderList) && orderList.size() > 0) {
					// 取出所有排队号
					List<String> queueNumberList = orderList.stream().map(TmsAppointmentHeaderModel::getQueueNumber).collect(Collectors.toList());
					// 排队号转换类型
					List<BigDecimal> queueNumbers = queueNumberList.stream().map(s -> new BigDecimal(s.replace("急", ""))).collect(Collectors.toList());
					// 获取最大排队号
					BigDecimal queueNumberMax = queueNumbers.stream().reduce(queueNumbers.get(0), BigDecimal::max);
					// 自增加1生成当前预约单的取号号码
					number.append(queueNumberMax.add(new BigDecimal("1")));
				} else {
					// 生成今天预约单排队号(年月日+当前仓库设置的最晚时间段后的一个小时时间段+三位自增数)
					number.append(DateUtil.format(date, DatePattern.PURE_DATE_FORMAT)).append(startHour).append(endhour).append("001");
				}

				// 生成叫号顺序
				this.getCallNumber(user, tmsAppointmentHeader, callMethod, true, date);

			} else {
				Restriction r6 = Restrictions.eq(TmsAppointmentHeaderModel::getUrgentQuantity, 0);
				criteria.setRestriction(Restrictions.and(r1, r2, r3, r4, r5, r6));
				List<TmsAppointmentHeaderModel> orderList = tmsAppointmentHeaderMapper.findByCriteria(criteria);
				if (ToolKits.isNotEmpty(orderList) && orderList.size() > 0) {
					// 取出所有排队号
					List<String> queueNumberList = orderList.stream().map(TmsAppointmentHeaderModel::getQueueNumber).collect(Collectors.toList());
					// 排队号转换类型
					List<BigDecimal> queueNumbers = queueNumberList.stream().map(s -> new BigDecimal(s)).collect(Collectors.toList());
					// 获取最大排队号
					BigDecimal queueNumberMax = queueNumbers.stream().reduce(queueNumbers.get(0), BigDecimal::max);
					// 自增加1生成当前预约单的取号号码
					number.append(queueNumberMax.add(new BigDecimal("1")));
				} else {
					// 生成今天预约单排队号(年月日+当前仓库设置的最晚时间段后的一个小时时间段+三位自增数)
					number.append(DateUtil.format(date, DatePattern.PURE_DATE_FORMAT)).append(startHour).append(endhour).append("001");
				}

				// 生成叫号顺序
				this.getCallNumber(user, tmsAppointmentHeader, callMethod, false, date);
			}
		}

		Assert.isTrue(ToolKits.isNotEmpty(number), "排队号生成失败");

		tmsAppointmentHeader.setUpdateperson(user.getNickname());
		tmsAppointmentHeader.setUpdatetime(DateUtil.date());
		tmsAppointmentHeader.setQueueNumber(number.toString());
		tmsAppointmentHeader.setQueueNumber(number.toString());
		tmsAppointmentHeader.setQueueNumberTime(date);
		tmsAppointmentHeader.setCallNumberTime(date);
		tmsAppointmentHeaderMapper.update(tmsAppointmentHeader);

		PendingPickUpTakeNumberDTO pendingPickUpTakeNumberDTO = new PendingPickUpTakeNumberDTO();
		SimpleDateFormat dataformat = new SimpleDateFormat("yyyy-MM-dd");
		pendingPickUpTakeNumberDTO.setAppointmentDate(dataformat.format(tmsAppointmentHeader.getAppointmentDate()));
		pendingPickUpTakeNumberDTO.setAppointmentId(tmsAppointmentHeader.getAppointmentId());
		pendingPickUpTakeNumberDTO.setAppointmentTime(tmsAppointmentHeader.getAppointmentTime());
		pendingPickUpTakeNumberDTO.setAppointNumber(tmsAppointmentHeader.getReserveNumber());
		pendingPickUpTakeNumberDTO.setDriverName(tmsAppointmentHeader.getDriverName());
		pendingPickUpTakeNumberDTO.setDriverTel(tmsAppointmentHeader.getDriverPhoneNumber());
		pendingPickUpTakeNumberDTO.setQueueNumber(tmsAppointmentHeader.getQueueNumber());
		pendingPickUpTakeNumberDTO.setShipBillNums(tmsAppointmentHeader.getShipbillQuantity());
		pendingPickUpTakeNumberDTO.setShipBillPackages(tmsAppointmentHeader.getTotalPcs().intValue());
		pendingPickUpTakeNumberDTO.setShipfromDate(dataformat.format(tmsAppointmentHeader.getAppointmentDate()) + " " + tmsAppointmentHeader.getAppointmentTime());
		pendingPickUpTakeNumberDTO.setShipfromAddress(tmsAppointmentHeader.getBranchAddress());
		pendingPickUpTakeNumberDTO.setVehiclePlateNumber(tmsAppointmentHeader.getVehiclePlateNumber());
		pendingPickUpTakeNumberDTO.setShipfromName(tmsAppointmentHeader.getBranchName());
		pendingPickUpTakeNumberDTO.setShipfromId(tmsAppointmentHeader.getBranchId().toString());
		MessageUtil.addMessage(new SendMessageDTO(MessageOrderTypeEnum.APPOINTMENT_NO.getCode(), MessageTypeEnum.TAKE_NUMBER.getCode(), Lists.newArrayList(tmsAppointmentHeader.getAppointmentId())));
		return pendingPickUpTakeNumberDTO;
	}

	/**
	 * 获取叫号顺序
	 *
	 * @param user                 用户对象
	 * @param tmsAppointmentHeader 预约单对象
	 * @param callMethod           取号方式
	 * @param urgent               是否急单
	 */
	public void getCallNumber(UserEntity user, TmsAppointmentHeaderModel tmsAppointmentHeader, Integer callMethod, boolean urgent, Date date) {
		// 查询预约单
		Criteria criteria = Criteria.forClass(TmsAppointmentHeaderModel.class);
		Restriction r1 = Restrictions.eq(TmsAppointmentHeaderModel::getEnterpriseId, user.getEnterpriseId());
		Restriction r2 = Restrictions.eq(TmsAppointmentHeaderModel::getBranchId, tmsAppointmentHeader.getBranchId());
		Restriction r3 = Restrictions.between(TmsAppointmentHeaderModel::getQueueNumberTime, DateUtil.beginOfDay(date), DateUtil.endOfDay(date));
		Restriction r4 = Restrictions.in(TmsAppointmentHeaderModel::getStatus, new Integer[] { DataDictionaryConstant.APPOINTMENT_STATUS_YQH, DataDictionaryConstant.APPOINTMENT_STATUS_DDZ });
		Restriction r5 = Restrictions.eq(TmsAppointmentHeaderModel::getAppointmentType, DataDictionaryConstant.APPOINTMENT_TYPE_TH);
		criteria.setRestriction(Restrictions.and(r1, r2, r3, r4, r5));
		List<TmsAppointmentHeaderModel> tmsAppointmentHeaderModels = tmsAppointmentHeaderMapper.findByCriteria(criteria);

		// 按排队号叫号
		if (ObjectUtil.equal(callMethod, DataDictionaryConstant.CALL_HANDLE_TYPE_NUMBER)) {
			if (urgent) {
				// 紧急预约单处理
				if (ToolKits.isNotEmpty(tmsAppointmentHeaderModels)) {
					// 筛选紧急的预约单
					List<TmsAppointmentHeaderModel> urgentAppointmenList = tmsAppointmentHeaderModels.stream().filter(s -> s.getUrgentQuantity().intValue() > 0).collect(Collectors.toList());
					if (ToolKits.isNotEmpty(urgentAppointmenList)) {
						// 取出所有排队号
						List<String> callNumberList = urgentAppointmenList.stream().map(TmsAppointmentHeaderModel::getCallNumber).collect(Collectors.toList());
						// 排队号转换类型
						List<BigDecimal> callNumbers = callNumberList.stream().map(s -> new BigDecimal(s)).collect(Collectors.toList());
						// 获取最大排队号
						BigDecimal callNumber = callNumbers.stream().reduce(callNumbers.get(0), BigDecimal::max);
						// 排队号加1
						tmsAppointmentHeader.setCallNumber(String.valueOf(callNumber.add(new BigDecimal("1"))));
					} else {
						// 排队号初始值
						tmsAppointmentHeader.setCallNumber(String.valueOf(BussinessConstant.CALL_NUMBER));
					}

					// 筛选非紧急的预约单
					List<TmsAppointmentHeaderModel> notUrgentAppointmenList = tmsAppointmentHeaderModels.stream().filter(s -> s.getUrgentQuantity().intValue() == 0).collect(Collectors.toList());
					for (TmsAppointmentHeaderModel notUrgentAppointmen : notUrgentAppointmenList) {
						// 叫号顺序顺延1
						notUrgentAppointmen.setCallNumber(((new BigDecimal(notUrgentAppointmen.getCallNumber())).add(new BigDecimal("1"))).toString());
						tmsAppointmentHeaderMapper.update(notUrgentAppointmen);
					}
				} else {
					// 排队号初始值
					tmsAppointmentHeader.setCallNumber(String.valueOf(BussinessConstant.CALL_NUMBER));
				}
			} else {
				// 非紧急预约单处理
				if (ToolKits.isNotEmpty(tmsAppointmentHeaderModels)) {
					// 取出所有排队号
					List<String> callNumberList = tmsAppointmentHeaderModels.stream().map(TmsAppointmentHeaderModel::getCallNumber).collect(Collectors.toList());
					// 排队号转换类型
					List<BigDecimal> callNumbers = callNumberList.stream().map(s -> new BigDecimal(s)).collect(Collectors.toList());
					// 获取最大排队号
					BigDecimal callNumber = callNumbers.stream().reduce(callNumbers.get(0), BigDecimal::max);
					// 排队号加1
					tmsAppointmentHeader.setCallNumber(String.valueOf(callNumber.add(new BigDecimal("1"))));
				} else {
					// 排队号初始值
					tmsAppointmentHeader.setCallNumber(String.valueOf(BussinessConstant.CALL_NUMBER));
				}
			}
		} else if (ObjectUtil.equal(callMethod, DataDictionaryConstant.CALL_HANDLE_TYPE_WAITINGAREA)) {
			// 紧急预约单处理
			if (urgent) {
				// 判断当前预约单是否等待中
				if (ObjectUtil.equal(tmsAppointmentHeader.getStatus(), DataDictionaryConstant.APPOINTMENT_STATUS_DDZ)) {
					if (ToolKits.isNotEmpty(tmsAppointmentHeaderModels)) {
						// TODO
						// 筛选紧急且为等待中的预约单
						List<TmsAppointmentHeaderModel> urgentAndDdzAppointmenList = tmsAppointmentHeaderModels.stream().filter(s -> s.getUrgentQuantity().intValue() > 0 && s.getStatus().intValue() == DataDictionaryConstant.APPOINTMENT_STATUS_DDZ.intValue()).collect(Collectors.toList());
						if (ToolKits.isNotEmpty(urgentAndDdzAppointmenList)) {
							// 取出所有排队号
							List<String> callNumberList = urgentAndDdzAppointmenList.stream().map(TmsAppointmentHeaderModel::getCallNumber).collect(Collectors.toList());
							// 排队号转换类型
							List<BigDecimal> callNumbers = callNumberList.stream().map(s -> new BigDecimal(s)).collect(Collectors.toList());
							// 获取最大排队号
							BigDecimal callNumber = callNumbers.stream().reduce(callNumbers.get(0), BigDecimal::max);
							// 排队号加1
							tmsAppointmentHeader.setCallNumber(String.valueOf(callNumber.add(new BigDecimal("1"))));

							// 其余的预约单叫号顺序顺延一位
							List<TmsAppointmentHeaderModel> otherAppointmenList = tmsAppointmentHeaderModels.stream().filter(s -> new BigDecimal(s.getCallNumber()).compareTo(callNumber) > 0).collect(Collectors.toList());
							for (TmsAppointmentHeaderModel otherAppointmen : otherAppointmenList) {
								// 叫号顺序顺延1
								otherAppointmen.setCallNumber(((new BigDecimal(otherAppointmen.getCallNumber())).add(new BigDecimal("1"))).toString());
								tmsAppointmentHeaderMapper.update(otherAppointmen);
							}
						} else {
							// 排队号初始值
							tmsAppointmentHeader.setCallNumber(String.valueOf(BussinessConstant.CALL_NUMBER));

							// 其余的预约单叫号顺序顺延一位
							for (TmsAppointmentHeaderModel tmsAppointmentHeaderModel : tmsAppointmentHeaderModels) {
								// 叫号顺序顺延1
								tmsAppointmentHeaderModel.setCallNumber(((new BigDecimal(tmsAppointmentHeaderModel.getCallNumber())).add(new BigDecimal("1"))).toString());
								tmsAppointmentHeaderMapper.update(tmsAppointmentHeaderModel);
							}
						}
					} else {
						// 排队号初始值
						tmsAppointmentHeader.setCallNumber(String.valueOf(BussinessConstant.CALL_NUMBER));
					}
				} else {
					// 当前预约单非等待中状态处理
					if (ToolKits.isNotEmpty(tmsAppointmentHeaderModels)) {
						// 判断是否有等待中的预约单
						List<TmsAppointmentHeaderModel> ddzAppointmenList = tmsAppointmentHeaderModels.stream().filter(s -> s.getStatus().intValue() == DataDictionaryConstant.APPOINTMENT_STATUS_DDZ.intValue()).collect(Collectors.toList());
						if (ToolKits.isNotEmpty(ddzAppointmenList)) {
							// 取出所有叫号顺序
							List<String> callNumberList = ddzAppointmenList.stream().map(TmsAppointmentHeaderModel::getCallNumber).collect(Collectors.toList());
							// 叫号顺序转换类型
							List<BigDecimal> callNumbers = callNumberList.stream().map(s -> new BigDecimal(s)).collect(Collectors.toList());
							// 获取等待区最大叫号顺序
							BigDecimal callNumber = callNumbers.stream().reduce(callNumbers.get(0), BigDecimal::max);

							// 判断等待区最后一位是否紧急预约单(即最大叫号顺序对应的预约单)
							TmsAppointmentHeaderModel endDdqAppointment = ddzAppointmenList.stream().filter(s -> s.getCallNumber().equals(callNumber.toString())).findAny().orElse(null);
							// 最后一位是紧急预约单
							if (endDdqAppointment.getUrgentQuantity().intValue() > 0) {
								// 非等待区叫号重新排序
								List<TmsAppointmentHeaderModel> fddzAppointmenList = tmsAppointmentHeaderModels.stream().filter(s -> s.getStatus().intValue() != DataDictionaryConstant.APPOINTMENT_STATUS_DDZ.intValue()).collect(Collectors.toList());
								// 非等待区是否存在预约单
								if (ToolKits.isNotEmpty(fddzAppointmenList)) {
									// 非等待区是否有紧急预约单
									List<TmsAppointmentHeaderModel> urgentAppointmenList = fddzAppointmenList.stream().filter(s -> s.getUrgentQuantity().intValue() > 0).collect(Collectors.toList());
									// 非等待区存在紧急预约单
									if (ToolKits.isNotEmpty(urgentAppointmenList)) {
										// 取出所有排队号
										List<String> callNumberList1 = urgentAppointmenList.stream().map(TmsAppointmentHeaderModel::getCallNumber).collect(Collectors.toList());
										// 排队号转换类型
										List<BigDecimal> callNumbers1 = callNumberList1.stream().map(s -> new BigDecimal(s)).collect(Collectors.toList());
										// 获取最大排队号
										BigDecimal callNumber1 = callNumbers1.stream().reduce(callNumbers1.get(0), BigDecimal::max);
										// 排队号加1
										tmsAppointmentHeader.setCallNumber(String.valueOf(callNumber1.add(new BigDecimal("1"))));

										// 其他预约单叫号顺序顺延1
										List<TmsAppointmentHeaderModel> otherAppointmenList = fddzAppointmenList.stream().filter(s -> new BigDecimal(s.getCallNumber()).compareTo(callNumber1) > 0).collect(Collectors.toList());
										for (TmsAppointmentHeaderModel otherAppointmen : otherAppointmenList) {
											// 叫号顺序顺延1
											otherAppointmen.setCallNumber(((new BigDecimal(otherAppointmen.getCallNumber())).add(new BigDecimal("1"))).toString());
											tmsAppointmentHeaderMapper.update(otherAppointmen);
										}
									} else {
										// 非等待区没有紧急预约单
										tmsAppointmentHeader.setCallNumber(String.valueOf(callNumber.add(new BigDecimal("1"))));

										// 非等待区预约单叫号顺序顺延1
										for (TmsAppointmentHeaderModel tmsAppointmentHeaderModel : fddzAppointmenList) {
											tmsAppointmentHeaderModel.setCallNumber(((new BigDecimal(tmsAppointmentHeaderModel.getCallNumber())).add(new BigDecimal("1"))).toString());
											tmsAppointmentHeaderMapper.update(tmsAppointmentHeaderModel);
										}
									}
								} else {
									// 非等待区没有紧急预约单
									tmsAppointmentHeader.setCallNumber(String.valueOf(callNumber.add(new BigDecimal("1"))));
								}
							} else {
								// 最后一位非紧急预约单
								// 等待区中是否存在紧急预约单
								List<TmsAppointmentHeaderModel> urgentAppointmenList = ddzAppointmenList.stream().filter(s -> s.getUrgentQuantity().intValue() > 0).collect(Collectors.toList());
								// 等待区中存在紧急预约单
								if (ToolKits.isNotEmpty(urgentAppointmenList)) {
									// 取出所有排队号
									List<String> callNumberList1 = urgentAppointmenList.stream().map(TmsAppointmentHeaderModel::getCallNumber).collect(Collectors.toList());
									// 排队号转换类型
									List<BigDecimal> callNumbers1 = callNumberList1.stream().map(s -> new BigDecimal(s)).collect(Collectors.toList());
									// 获取最大排队号
									BigDecimal callNumber1 = callNumbers1.stream().reduce(callNumbers1.get(0), BigDecimal::max);
									// 排队号加1
									tmsAppointmentHeader.setCallNumber(String.valueOf(callNumber1.add(new BigDecimal("1"))));
									tmsAppointmentHeader.setStatus(DataDictionaryConstant.APPOINTMENT_STATUS_DDZ);

									// 其他预约单叫号顺序顺延1
									List<TmsAppointmentHeaderModel> otherAppointmenList = tmsAppointmentHeaderModels.stream().filter(s -> new BigDecimal(s.getCallNumber()).compareTo(callNumber1) > 0).collect(Collectors.toList());
									for (TmsAppointmentHeaderModel otherAppointmen : otherAppointmenList) {
										if (otherAppointmen.getCallNumber().equals(callNumber.toString())) {
											otherAppointmen.setStatus(DataDictionaryConstant.APPOINTMENT_STATUS_YQH);
										}

										// 叫号顺序顺延1
										otherAppointmen.setCallNumber(((new BigDecimal(otherAppointmen.getCallNumber())).add(new BigDecimal("1"))).toString());
										tmsAppointmentHeaderMapper.update(otherAppointmen);
									}
								} else {
									tmsAppointmentHeader.setCallNumber(String.valueOf(BussinessConstant.CALL_NUMBER));
									tmsAppointmentHeader.setStatus(DataDictionaryConstant.APPOINTMENT_STATUS_DDZ);

									// 其他预约单顺延1位
									for (TmsAppointmentHeaderModel tmsAppointmentHeaderModel : tmsAppointmentHeaderModels) {
										if (tmsAppointmentHeaderModel.getCallNumber().equals(callNumber.toString())) {
											tmsAppointmentHeaderModel.setStatus(DataDictionaryConstant.APPOINTMENT_STATUS_YQH);
										}
										tmsAppointmentHeaderModel.setCallNumber(((new BigDecimal(tmsAppointmentHeaderModel.getCallNumber())).add(new BigDecimal("1"))).toString());
										tmsAppointmentHeaderMapper.update(tmsAppointmentHeaderModel);
									}
								}
							}
						} else {
							// 判断是否存在紧急的预约单
							List<TmsAppointmentHeaderModel> urgentAppointmenList = tmsAppointmentHeaderModels.stream().filter(s -> s.getUrgentQuantity().intValue() > 0).collect(Collectors.toList());
							if (ToolKits.isNotEmpty(urgentAppointmenList)) {
								// 取出所有排队号
								List<String> callNumberList = urgentAppointmenList.stream().map(TmsAppointmentHeaderModel::getCallNumber).collect(Collectors.toList());
								// 排队号转换类型
								List<BigDecimal> callNumbers = callNumberList.stream().map(s -> new BigDecimal(s)).collect(Collectors.toList());
								// 获取最大排队号
								BigDecimal callNumber = callNumbers.stream().reduce(callNumbers.get(0), BigDecimal::max);
								// 排队号加1
								tmsAppointmentHeader.setCallNumber(String.valueOf(callNumber.add(new BigDecimal("1"))));

								// 其他预约单叫号顺序顺延1
								List<TmsAppointmentHeaderModel> otherAppointmenList = tmsAppointmentHeaderModels.stream().filter(s -> new BigDecimal(s.getCallNumber()).compareTo(callNumber) > 0).collect(Collectors.toList());
								for (TmsAppointmentHeaderModel otherAppointmen : otherAppointmenList) {
									// 叫号顺序顺延1
									otherAppointmen.setCallNumber(((new BigDecimal(otherAppointmen.getCallNumber())).add(new BigDecimal("1"))).toString());
									tmsAppointmentHeaderMapper.update(otherAppointmen);
								}
							} else {
								// 排队号初始值
								tmsAppointmentHeader.setCallNumber(String.valueOf(BussinessConstant.CALL_NUMBER));
								// 其他预约单叫号顺序顺延1
								for (TmsAppointmentHeaderModel tmsAppointmentHeaderModel : tmsAppointmentHeaderModels) {
									tmsAppointmentHeaderModel.setCallNumber(((new BigDecimal(tmsAppointmentHeaderModel.getCallNumber())).add(new BigDecimal("1"))).toString());
									tmsAppointmentHeaderMapper.update(tmsAppointmentHeaderModel);
								}
							}
						}
					} else {
						// 排队号初始值
						tmsAppointmentHeader.setCallNumber(String.valueOf(BussinessConstant.CALL_NUMBER));
					}
				}
			} else {
				// 非紧急预约单处理
				if (ToolKits.isNotEmpty(tmsAppointmentHeaderModels)) {
					// 取出所有排队号
					List<String> callNumberList = tmsAppointmentHeaderModels.stream().map(TmsAppointmentHeaderModel::getCallNumber).collect(Collectors.toList());
					// 排队号转换类型
					List<BigDecimal> callNumbers = callNumberList.stream().map(s -> new BigDecimal(s)).collect(Collectors.toList());
					// 获取最大排队号
					BigDecimal callNumber = callNumbers.stream().reduce(callNumbers.get(0), BigDecimal::max);
					// 排队号加1
					tmsAppointmentHeader.setCallNumber(String.valueOf(callNumber.add(new BigDecimal("1"))));
				} else {
					// 排队号初始值
					tmsAppointmentHeader.setCallNumber(String.valueOf(BussinessConstant.CALL_NUMBER));
				}
			}
		} else {
			throw new PrologException("叫号方式【" + callMethod + "】错误");
		}
	}

	/**
	 * 启运登记
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public List<PendingPickUpDetailQueryDTO> pendingPickUpStartShipment(PendingPickUpStartShipmentVO pendingPickUpStartShipmentVO) throws Exception {
		ToolKits.isParamNull(pendingPickUpStartShipmentVO, "司机待预约明细查询请求参数不为空");
		ToolKits.isParamNull(pendingPickUpStartShipmentVO.getDriverId(), "司机ID不为空");
		ToolKits.isParamNull(pendingPickUpStartShipmentVO.getVehiclePlateNumber(), "车牌号不为空");
		ToolKits.isParamNull(pendingPickUpStartShipmentVO.getEnterpriseId(), "企业ID不能为空");
		ToolKits.isParamNull(pendingPickUpStartShipmentVO.getShipfrom(), "发货地ID不能为空");

		UserEntity user = PlgFxUsrUtils.getUserEntity();
		ToolKits.isParamNull(user, "当前人员没有操作权限");

		Date date = DateUtils.nowDate();

		// 货物图片
		String departurePhoto = pendingPickUpStartShipmentVO.getStartShipmentUrl();
		// 当前时间
//		StringBuffer nodeEvent = new StringBuffer();
//		nodeEvent.append("启运登记 备注:");
		String driverOpenReceiveReject = mainDataProxy.getSystemParamByCode(DataDictionaryConstant.DRIVER_OPEN_RECEIVE_REJECT);
		String relationThirdSystem = mainDataProxy.getSystemParamByCode(RelationThirdSystemEnum.ENUM_NAME);
		// STD-BUG20220823 lhb 23991 订单没有勾选上传货物图片也有校验图片拦截 20220823 start
		String[] shipbillIds = pendingPickUpStartShipmentVO.getShipbillIds().split(",");
		List<TmsShipbillHeaderModel> headerModelList = tmsShipbillHeaderMapper.findByIds(TmsShipbillHeaderModel.class, shipbillIds, null);

		headerModelList.forEach(tmsShipbillHeaderModel -> {
			if (DataDictionaryConstant.DRIVER_OPEN_RECEIVE_REJECT_OPEN.equals(driverOpenReceiveReject) &&
					DriverReceiveStatusEnum.N.getCode().equals(tmsShipbillHeaderModel.getDriverReceiveStatus())) {
				throw new PrologException("运单" + tmsShipbillHeaderModel.getShipbillId() + "未接单，不能启运登记");
			}
			if (!DataDictionaryConstant.TEMPERATURE_REQUIREMENT_CW.equals(tmsShipbillHeaderModel.getTemperatureRequirement())) {
//				if (Boolean.TRUE.equals(pendingPickUpStartShipmentVO.getShowDepartureTemperature()) && ObjectUtil.isNull(pendingPickUpStartShipmentVO.getDepartureTemperature())) {
//					throw new BizException("启运温度不能为空");
//				}
				if (!DataDictionaryConstant.VEHICLE_TYPE_CATEGORY_LC.equals(tmsShipbillHeaderModel.getVehicleTypeCategory())) {
					if (relationThirdSystem.contains(RelationThirdSystemEnum.GPS.getCode())) {
						if (StrUtil.isBlank(pendingPickUpStartShipmentVO.getVehicleDeviceId())) {
							throw new BizException("运单" + tmsShipbillHeaderModel.getShipbillId() + "未绑定设备，请先输入设备号");
						}
					}
					if(relationThirdSystem.contains(RelationThirdSystemEnum.TEMPERATURE.getCode()) || relationThirdSystem.contains(RelationThirdSystemEnum.CONTAINER.getCode())){
						if (StrUtil.isBlank(pendingPickUpStartShipmentVO.getContainerId())) {
							throw new BizException("运单" + tmsShipbillHeaderModel.getShipbillId() + "未绑定保温箱，请先选择容器号");
						}
					}
				}
			}
		});

		String pickUpCheckDtlSystem = mainDataProxy.getSystemParamByCode(DataDictionaryConstant.PICK_UP_CHECK_DETAIL_SWITCH);
		if (DataDictionaryConstant.WHETHER_YES.toString().equals(pickUpCheckDtlSystem)
				&& ToolKits.isEmpty(pendingPickUpStartShipmentVO.getCheckDetails())) {
			throw new BizException("启运登记检查清单不为空");
		}

		List<TmsShipbillHeaderModel> picList = headerModelList.stream().filter(m -> ToolKits.isNotEmpty(m.getShipperPickUpPicture()) && m.getShipperPickUpPicture().equals(DataDictionaryConstant.WHETHER_YES)).collect(Collectors.toList());
		if (ToolKits.isNotEmpty(picList) && ToolKits.isEmpty(pendingPickUpStartShipmentVO.getStartShipmentUrl())) {
			throw new PrologException("货物图片不能为空");
		}

		// 查询代提货数据
		PendingPickUpDetailQueryVO pendingPickUpDetailQueryVO = new PendingPickUpDetailQueryVO();
		BeanUtils.copyProperties(pendingPickUpStartShipmentVO, pendingPickUpDetailQueryVO);
		pendingPickUpDetailQueryVO.setShipbillIdList(shipbillIds);
		List<PendingPickUpDetailQueryDTO> dtos = tmsShipbillHeaderMapper.pendingPickUpDetailQuery(pendingPickUpDetailQueryVO);
		if (ObjectUtils.isEmpty(dtos)) {
			throw new BizException("未找到对应的运单明细！");
		}
		for (PendingPickUpDetailQueryDTO dto : dtos) {
			if (ToolKits.isNotEmpty(dto.getShipperPickUpSign()) && dto.getShipperPickUpSign().equals(DataDictionaryConstant.WHETHER_YES)) {
				if (!dto.getStatus().equals(DataDictionaryConstant.SHIPBILL_STATUS_THQD)) {
					throw new BizException("运单【" + dto.getShipbillId() + "】不能启运登记");
				}
			} else if (!dto.getStatus().equals(DataDictionaryConstant.SHIPBILL_STATUS_QY)) {
				throw new BizException("运单【" + dto.getShipbillId() + "】不能启运登记");
			}
		}

		// 经纬度都有值时 才写入数据到GPS表
		if (ToolKits.isNotEmpty(pendingPickUpStartShipmentVO.getLongitude()) && ToolKits.isNotEmpty(pendingPickUpStartShipmentVO.getLatitude())) {
			for (TmsShipbillHeaderModel tmsShipbillHeader : headerModelList) {
				// 写入司机GPS数据
				VehicleGpsSaveVO savevo = new VehicleGpsSaveVO();
				savevo.setStartShipTime(date);
				savevo.setLongitude(pendingPickUpStartShipmentVO.getLongitude());
				savevo.setLatitude(pendingPickUpStartShipmentVO.getLatitude());
				savevo.setShipbillId(tmsShipbillHeader.getShipbillId());
				savevo.setShipbillNo(tmsShipbillHeader.getShipbillNo());
				savevo.setTemperature(pendingPickUpStartShipmentVO.getDepartureTemperature());
				savevo.setFlag("1");
				maindataFeign.saveVehicleGps(savevo);
			}
		}

		String eventFeedbackMode = mainDataProxy.getSystemParamByCode(EventFeedbackModeEnum.ENUM_NAME);
		if (eventFeedbackMode.contains(EventFeedbackModeEnum.OPEN_SHIP_EVENT.getCode())) {
			AddShipbillEventFeedbackVO vo = new AddShipbillEventFeedbackVO();
			vo.setType(EventTypeEnum.SHIP.getCode());
			vo.setShipbillId(pendingPickUpStartShipmentVO.getShipbillIds());
			vo.setMileage(pendingPickUpStartShipmentVO.getMileage());
			vo.setAddress(pendingPickUpStartShipmentVO.getAddress());
			vo.setLongitude(pendingPickUpStartShipmentVO.getLongitude());
			vo.setLatitude(pendingPickUpStartShipmentVO.getLatitude());
			vo.setEventType(pendingPickUpStartShipmentVO.getEventType());
			vo.setEventContent(pendingPickUpStartShipmentVO.getEventContent());
			vo.setEventPic(pendingPickUpStartShipmentVO.getEventPic());
			TmsShipbillEventFeedback model = shipbillEventFeedbackService.add(vo);
			Boolean eventFeedbackFlow = Boolean.FALSE;
			for (TmsShipbillHeaderModel headerModel : headerModelList) {
				if (approvalOpen(headerModel, DataDictionaryConstant.APPROVAL_FLOW_TYPE_EVENT_FEEDBACK, model.getId())) {
					eventFeedbackFlow = Boolean.TRUE;
					break;
				}
			}
			if (!eventFeedbackFlow) {
				shipbillEventFeedbackService.eventFeedback(model.getId());
			}
		}

		if (Boolean.TRUE.equals(pendingPickUpStartShipmentVO.getShowContainerTemperature())) {
			if (CollectionUtil.isEmpty(pendingPickUpStartShipmentVO.getTemperatureVOList())) {
				throw new BizException("容器温度集合不存在");
			}
			pendingPickUpStartShipmentVO.getTemperatureVOList().forEach(vo -> {
				if (ObjectUtil.isNull(vo.getTemperature())) {
					throw new BizException("容器" + vo.getName() + "温度为空");
				}
			});
			headerModelList.forEach(model -> {
				Criteria criteria = Criteria.forClass(TmsShipbillContainerTemp.class);
				Restriction r1 = Restrictions.eq(TmsShipbillContainerTemp::getEnterpriseId, user.getEnterpriseId());
				Restriction r2 = Restrictions.eq(TmsShipbillContainerTemp::getShipbillId, model.getShipbillId());
				criteria.setRestriction(Restrictions.and(r1, r2));
				shipbillContainerTempMapper.deleteByCriteria(criteria);
				pendingPickUpStartShipmentVO.getTemperatureVOList().forEach(vo -> {
					TmsShipbillContainerTemp temp = new TmsShipbillContainerTemp();
					temp.setId(mainDataProxy.getCodeNumberByCode(SeriaNnumberConstant.TMS_SHIPBILL_CONTAINER_TEMP_ID));
					temp.setShipbillId(model.getShipbillId());
					temp.setContainerId(vo.getId());
					temp.setContainerCode(vo.getCode());
					temp.setContainerName(vo.getName());
					temp.setDepartureTemp(vo.getTemperature());
					temp.setDepartureTempTime(DateUtil.date());
					temp.setCreatetime(DateUtil.date());
					temp.setCreateperson(user.getNickname());
					temp.setUpdatetime(DateUtil.date());
					temp.setUpdateperson(user.getNickname());
					temp.setEnterpriseId(user.getEnterpriseId());
					temp.setEnterpriseName(user.getEnterpriseName());
					shipbillContainerTempMapper.save(temp);
				});
			});
		}


		List<StartShipmentDetailVO> detailVOList = pendingPickUpStartShipmentVO.getDetailVOList();
		Map<String, StartShipmentDetailVO> detailVOMap = detailVOList.stream().collect(
				Collectors.toMap(t1 -> t1.getId(), t2 -> t2, (t1, t2) -> t2));

		String pickupHandleType = mainDataProxy.getSystemParamByCode(PickUpHandleTypeEnum.ENUM_NAME);
		if (PickUpHandleTypeEnum.SHOW.getCode().equals(pickupHandleType) && CollectionUtil.isNotEmpty(pendingPickUpStartShipmentVO.getDetailVOList())) {
			if (detailVOList.stream().anyMatch(detailVO -> NumberUtil.isGreater(detailVO.getQty(), detailVO.getPickUpPcs()))) {
				headerModelList.forEach(headerModel -> {
					TmsShipbillHeaderTempModel tempModel = BeanUtil.copyProperties(headerModel, TmsShipbillHeaderTempModel.class);
					tempModel.setVehicleDeviceId(pendingPickUpStartShipmentVO.getVehicleDeviceId());
					tempModel.setVehicleDeviceCode(pendingPickUpStartShipmentVO.getVehicleDeviceCode());
					tempModel.setVehicleDeviceName(pendingPickUpStartShipmentVO.getVehicleDeviceName());
					tempModel.setContainerId(pendingPickUpStartShipmentVO.getContainerId());
					tempModel.setContainerCode(pendingPickUpStartShipmentVO.getContainerCode());
					tempModel.setContainerName(pendingPickUpStartShipmentVO.getContainerName());
					tempModel.setDepartureTemperature(pendingPickUpStartShipmentVO.getDepartureTemperature());
					tempModel.setDepartureTime(date);
					tempModel.setMemo(departurePhoto);
					tmsShipbillHeaderTempMapper.save(tempModel);
					headerModel.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_QYSH);
					headerModel.setUpdateperson(user.getNickname());
					headerModel.setUpdatetime(date);
					tmsShipbillHeaderMapper.update(headerModel);

					Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
					Restriction r1 = Restrictions.eq("shipbillId", headerModel.getShipbillId());
					Restriction r2 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
					criteria.setRestriction(Restrictions.and(r1, r2));
					criteria.setOrder(Order.newInstance().desc(TmsLoadingBillDetailModel::getCreatetime));
					List<TmsLoadingBillDetailModel> loadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteria);
					ToolKits.isParamNull(loadingBillDetailModels, "未找到对应的调度单明细");
					TmsLoadingBillDetailModel loadingBillDetailModel = loadingBillDetailModels.get(0);
					loadingBillDetailModel.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_QYSH);
					loadingBillDetailModel.setUpdateperson(user.getNickname());
					loadingBillDetailModel.setUpdatetime(date);
					tmsLoadingBillDetailMapper.update(loadingBillDetailModel);


					// 声明节点实体
					ShipbillNodeTrackingSaveNewVO shipbillNodeTrackingSaveNewVO = new ShipbillNodeTrackingSaveNewVO();
					// 声明日志实体
					ShipbillOperateLogSaveNewVO shipbillOperateLogSaveNewVO = new ShipbillOperateLogSaveNewVO();
					// 节点保存
					shipbillNodeTrackingSaveNewVO.setNodeEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_QYSH);
					shipbillNodeTrackingSaveNewVO.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_QYSH);
					shipbillNodeTrackingSaveNewVO.setShipbillId(headerModel.getShipbillId());
					shipbillNodeTrackingSaveNewVO.setShipbillNo(headerModel.getShipbillNo());
					shipbillNodeTrackingSaveNewVO.setNodeDate(date);
					shipbillNodeTrackingSaveNewVO.setUserId(user.getUserid());
					shipbillNodeTrackingSaveNewVO.setUserName(user.getNickname());
					shipbillNodeTrackingSaveNewVO.setEnterpriseId(user.getEnterpriseId());
					shipbillNodeTrackingSaveNewVO.setEnterpriseName(user.getEnterpriseName());
					shipbillNodeTrackingService.addShipbillNodeTrackingNewData(shipbillNodeTrackingSaveNewVO);

					shipbillOperateLogSaveNewVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_QYSH);
					shipbillOperateLogSaveNewVO.setOldStatus(headerModel.getStatus());
					shipbillOperateLogSaveNewVO.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_QYSH);
					shipbillOperateLogSaveNewVO.setShipbillId(headerModel.getShipbillId());
					shipbillOperateLogSaveNewVO.setShipbillNo(headerModel.getShipbillNo());
					shipbillOperateLogSaveNewVO.setUserId(user.getUserid());
					shipbillOperateLogSaveNewVO.setUserName(user.getNickname());
					shipbillOperateLogSaveNewVO.setEnterpriseId(user.getEnterpriseId());
					shipbillOperateLogSaveNewVO.setEnterpriseName(user.getEnterpriseName());
					shipbillOperateLogSaveNewVO.setOperateDate(date);
					shipbillOperateLogService.addShipbillOperateLogNewData(shipbillOperateLogSaveNewVO);
				});
				List<TmsShipbillDetailModel> tmsShipbillDetailModelList = tmsShipbillDetailMapper.findByIds(TmsShipbillDetailModel.class,
						detailVOList.stream().map(StartShipmentDetailVO::getId).toArray(), null);
				tmsShipbillDetailModelList.forEach(detailModel -> {
					TmsShipbillDetailTempModel tempModel = BeanUtil.copyProperties(detailModel, TmsShipbillDetailTempModel.class);
					StartShipmentDetailVO detailVO = detailVOMap.get(detailModel.getId());
					if (ObjectUtil.isNotNull(detailVO)) {
						tempModel.setPickUpPcs(detailVO.getPickUpPcs());
					}
					tmsShipbillDetailTempMapper.save(tempModel);
				});


				Boolean startShipFlow = Boolean.FALSE;
				for (TmsShipbillHeaderModel headerModel : headerModelList) {
					if (approvalOpen(headerModel, DataDictionaryConstant.APPROVAL_FLOW_TYPE_START_SHIP, pendingPickUpStartShipmentVO.getShipbillIds())) {
						startShipFlow = Boolean.TRUE;
						break;
					}
				}
				if (startShipFlow) {
					return Lists.newArrayList();
				}
			}
		}


		// STD-BUG20220823 lhb 23991 订单没有勾选上传货物图片也有校验图片拦截 20220823 end
		List<PendingPickUpDetailQueryDTO> returndtos = new ArrayList<PendingPickUpDetailQueryDTO>();
		for (PendingPickUpDetailQueryDTO dto : dtos) {
			// 更新运输记录表
			Criteria criteriaTransportLog = Criteria.forClass(TmsShipbillTransLogModel.class);
			Restriction r1 = Restrictions.eq(TmsShipbillTransLogModel::getEnterpriseId, pendingPickUpStartShipmentVO.getEnterpriseId());
			Restriction r2 = Restrictions.eq(TmsShipbillTransLogModel::getShipbillId, dto.getShipbillId());
			criteriaTransportLog.setRestriction(Restrictions.and(r1, r2));
			List<TmsShipbillTransLogModel> transportLogModels = tmsShipbillTransportLogMapper.findByCriteria(criteriaTransportLog);
			if (ToolKits.isNotEmpty(transportLogModels)) {
				TmsShipbillTransLogModel transportLogModel = transportLogModels.get(0);
				transportLogModel.setUpdateperson(user.getNickname());
				transportLogModel.setUpdatetime(date);
				transportLogModel.setDepartureTime(date);
				tmsShipbillTransportLogMapper.update(transportLogModel);
			}

			// STD-BUG20220823 lhb 启运登记修改运单明细发货件数 20220920 start
			// 修改运单明细的商品信息
			TmsShipbillHeaderModel tmsShipbillHeaderModel = tmsShipbillHeaderMapper.findById(dto.getShipbillId(), TmsShipbillHeaderModel.class);
			Criteria criteriaShipbillDetail = Criteria.forClass(TmsShipbillDetailModel.class);
			Restriction r11 = Restrictions.eq(TmsShipbillDetailModel::getShipbillId, tmsShipbillHeaderModel.getShipbillId());
			Restriction r12 = Restrictions.eq(TmsShipbillDetailModel::getEnterpriseId, user.getEnterpriseId());
			Restriction r13 = Restrictions.ge(TmsShipbillDetailModel::getPcs, BigDecimal.ZERO);
			criteriaShipbillDetail.setRestriction(Restrictions.and(r11, r12,r13));
			List<TmsShipbillDetailModel> shipbillDetailModels = tmsShipbillDetailMapper.findByCriteria(criteriaShipbillDetail);

			BigDecimal totalDeliveryPcs = new BigDecimal(0);
			BigDecimal totalDeliveryVolume = new BigDecimal(0);
			BigDecimal totalDeliveryWeight = new BigDecimal(0);

			if (ToolKits.isNotEmpty(shipbillDetailModels)) {
				for (TmsShipbillDetailModel shipbillDetailModel : shipbillDetailModels) {
					ItemCheckVO itemCheckVO = new ItemCheckVO();
					itemCheckVO.setItemId(shipbillDetailModel.getItemId());
					RestMessage<ItemCheckDTO> restMessage3 = maindataFeign.getItem(itemCheckVO);
					if (!restMessage3.isSuccess()) {
						throw new RuntimeException("取商品资料信息失败:" + restMessage3.getMessage());
					}
					ItemCheckDTO rsItemInfo = restMessage3.getData();
					StartShipmentDetailVO detailVO = detailVOMap.get(shipbillDetailModel.getId());
					if (ObjectUtil.isNotNull(detailVO)) {
						shipbillDetailModel.setDeliveryPcs(detailVO.getPickUpPcs());
						shipbillDetailModel.setPcs(NumberUtil.sub(shipbillDetailModel.getPcs(), detailVO.getPickUpPcs()));
						shipbillDetailModel.setPickUpPcs(detailVO.getPickUpPcs());
						shipbillDetailModel.setVolume(NumberUtil.mul(shipbillDetailModel.getPcs(), rsItemInfo.getVolume()));
						shipbillDetailModel.setWeight(NumberUtil.mul(shipbillDetailModel.getPcs(), rsItemInfo.getWeight()));
					} else {
						shipbillDetailModel.setDeliveryPcs(shipbillDetailModel.getPcs());
						shipbillDetailModel.setPickUpPcs(shipbillDetailModel.getPcs());
						shipbillDetailModel.setPcs(BigDecimal.ZERO);
						shipbillDetailModel.setVolume(BigDecimal.ZERO);
						shipbillDetailModel.setWeight(BigDecimal.ZERO);
					}
					tmsShipbillDetailMapper.update(shipbillDetailModel);

					BigDecimal fatherDeliveryPcs = new BigDecimal(0);

					fatherDeliveryPcs = fatherDeliveryPcs.add(shipbillDetailModel.getDeliveryPcs());

					totalDeliveryPcs = totalDeliveryPcs.add(shipbillDetailModel.getDeliveryPcs());
					totalDeliveryVolume = totalDeliveryVolume.add(shipbillDetailModel.getDeliveryPcs().multiply(rsItemInfo.getVolume()));
					totalDeliveryWeight = totalDeliveryWeight.add(shipbillDetailModel.getDeliveryPcs().multiply(rsItemInfo.getWeight()));

					// 拆分主单对应的运单明细
					String fatherShipbillIdForDetail = tmsShipbillHeaderModel.getShipbillId();
					while (ToolKits.isNotEmpty(fatherShipbillIdForDetail)) {
						fatherShipbillIdForDetail = updateFatherShipbillDetail(fatherShipbillIdForDetail, shipbillDetailModel,fatherDeliveryPcs, date, user,rsItemInfo);
					}
				}
			}
			// STD-BUG20220823 lhb 启运登记修改运单明细发货件数 20220920 end

			// 更新运单状态 为待配送
			tmsShipbillHeaderModel.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_SD);
			tmsShipbillHeaderModel.setUpdateperson(user.getNickname());
			tmsShipbillHeaderModel.setUpdatetime(date);
			tmsShipbillHeaderModel.setTransportStatus(DataDictionaryConstant.TRANSPORT_STATUS_SHIPPING);
			tmsShipbillHeaderModel.setTotalDeliveryPcs(totalDeliveryPcs);
			tmsShipbillHeaderModel.setTotalDeliveryWeight(totalDeliveryWeight);
			tmsShipbillHeaderModel.setTotalDeliveryVolume(totalDeliveryVolume);

			tmsShipbillHeaderModel.setTotalPcs(tmsShipbillHeaderModel.getTotalPcs().subtract(totalDeliveryPcs));
			tmsShipbillHeaderModel.setTotalVolume(tmsShipbillHeaderModel.getTotalVolume().subtract(totalDeliveryVolume));
			tmsShipbillHeaderModel.setTotalWeight(tmsShipbillHeaderModel.getTotalWeight().subtract(totalDeliveryWeight));
			tmsShipbillHeaderModel.setActualTotalPcs(tmsShipbillHeaderModel.getTotalPcs());
			tmsShipbillHeaderModel.setActualTotalVolume(tmsShipbillHeaderModel.getTotalVolume());
			tmsShipbillHeaderModel.setActualTotalWeight(tmsShipbillHeaderModel.getTotalWeight());
			tmsShipbillHeaderModel.setDepartureTime(date);
			tmsShipbillHeaderModel.setVehicleDeviceId(pendingPickUpStartShipmentVO.getVehicleDeviceId());
			tmsShipbillHeaderModel.setVehicleDeviceCode(pendingPickUpStartShipmentVO.getVehicleDeviceCode());
			tmsShipbillHeaderModel.setVehicleDeviceName(pendingPickUpStartShipmentVO.getVehicleDeviceName());
			tmsShipbillHeaderModel.setDepartureTemperature(pendingPickUpStartShipmentVO.getDepartureTemperature());
			tmsShipbillHeaderModel.setContainerId(pendingPickUpStartShipmentVO.getContainerId());
			tmsShipbillHeaderModel.setContainerCode(pendingPickUpStartShipmentVO.getContainerCode());
			tmsShipbillHeaderModel.setContainerName(pendingPickUpStartShipmentVO.getContainerName());
			tmsShipbillHeaderMapper.update(tmsShipbillHeaderModel);

			// 修改派车单明细
			Criteria criteriaLoadingBillDetail = Criteria.forClass(TmsLoadingBillDetailModel.class);
			Restriction r21 = Restrictions.eq("shipbillId", tmsShipbillHeaderModel.getShipbillId());
			Restriction r22 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
			criteriaLoadingBillDetail.setRestriction(Restrictions.and(r21, r22));
			criteriaLoadingBillDetail.setOrder(Order.newInstance().desc(TmsLoadingBillDetailModel::getCreatetime));
			List<TmsLoadingBillDetailModel> loadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteriaLoadingBillDetail);
			ToolKits.isParamNull(loadingBillDetailModels, "未找到对应的调度单明细");
			TmsLoadingBillDetailModel loadingBillDetailModel = loadingBillDetailModels.get(0);

			loadingBillDetailModel.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_SD);
			loadingBillDetailModel.setUpdateperson(user.getNickname());
			loadingBillDetailModel.setUpdatetime(date);
			loadingBillDetailModel.setTransportStatus(DataDictionaryConstant.TRANSPORT_STATUS_SHIPPING);
			loadingBillDetailModel.setTotalDeliveryPcs(totalDeliveryPcs);
			loadingBillDetailModel.setTotalDeliveryWeight(totalDeliveryWeight);
			loadingBillDetailModel.setTotalDeliveryVolume(totalDeliveryVolume);

			loadingBillDetailModel.setTotalPcs(loadingBillDetailModel.getTotalPcs().subtract(totalDeliveryPcs));
			loadingBillDetailModel.setTotalVolume(loadingBillDetailModel.getTotalVolume().subtract(totalDeliveryVolume));
			loadingBillDetailModel.setTotalWeight(loadingBillDetailModel.getTotalWeight().subtract(totalDeliveryWeight));
			loadingBillDetailModel.setActualTotalPcs(loadingBillDetailModel.getTotalPcs());
			loadingBillDetailModel.setActualTotalVolume(loadingBillDetailModel.getTotalVolume());
			loadingBillDetailModel.setActualTotalWeight(loadingBillDetailModel.getTotalWeight());
			loadingBillDetailModel.setVehicleDeviceId(pendingPickUpStartShipmentVO.getVehicleDeviceId());
			loadingBillDetailModel.setVehicleDeviceCode(pendingPickUpStartShipmentVO.getVehicleDeviceCode());
			loadingBillDetailModel.setVehicleDeviceName(pendingPickUpStartShipmentVO.getVehicleDeviceName());
			loadingBillDetailModel.setDepartureTime(date);
			loadingBillDetailModel.setDepartureTemperature(pendingPickUpStartShipmentVO.getDepartureTemperature());
			loadingBillDetailModel.setContainerId(pendingPickUpStartShipmentVO.getContainerId());
			loadingBillDetailModel.setContainerCode(pendingPickUpStartShipmentVO.getContainerCode());
			loadingBillDetailModel.setContainerName(pendingPickUpStartShipmentVO.getContainerName());
			tmsLoadingBillDetailMapper.update(loadingBillDetailModel);

			// 运单节点保存
			// 获取节点ID
			RestMessage<String> restMessage = maindataFeign.getCodeNumberByCode(SeriaNnumberConstant.TMS_SHIPBILL_NODE_TRACKING_ID, "L");
			if (!restMessage.isSuccess()) {
				throw new RuntimeException("生成节点ID失败:" + restMessage.getMessage());
			}
			String id = restMessage.getData();

			String memo = StrUtil.EMPTY;
			if (CollectionUtil.isNotEmpty(pendingPickUpStartShipmentVO.getDetailVOList())) {
				memo = pendingPickUpStartShipmentVO.getDetailVOList().stream().filter(detailVO -> dto.getShipbillId().equals(detailVO.getShipbillId())).map(detailVO ->
						detailVO.getItemName() + ",计划提货件数:" + NumberUtil.null2Zero(detailVO.getPlanDeliveryPcs()).stripTrailingZeros().toPlainString() + "件,实际提货件数:" + detailVO.getPickUpPcs().stripTrailingZeros().toPlainString() + "件").collect(Collectors.joining(" "));
			}
			// 节点记录
			ShipbillNodeTracking model = new ShipbillNodeTracking();
			model.setNodeDate(date);
			model.setShipbillId(dto.getShipbillId());
			model.setShipbillNo(dto.getShipbillId());
			model.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_QY);
			model.setNodeEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_QY + " " + memo + " " + pendingPickUpStartShipmentVO.getCheckDetails());
			model.setUserId(user.getUserid());
			model.setUserName(user.getNickname());
			model.setEnterpriseId(user.getEnterpriseId());
			model.setEnterpriseName(user.getEnterpriseName());
			model.setPicUrl(departurePhoto);
			model.setId(id);
			model.setUserId(user.getUserid());
			model.setUserName(user.getNickname());
			model.setEnterpriseId(user.getEnterpriseId());
			model.setEnterpriseName(user.getEnterpriseName());
			model.setCreateperson(user.getNickname());
			model.setCreatetime(date);
			model.setUpdateperson(user.getNickname());
			model.setUpdatetime(date);
			tmsShipbillNodeTrackingMapper.save(model);

			// 运单日志保存
			// 获取日志ID
			RestMessage<String> restMessageLog = maindataFeign.getCodeNumberByCode(SeriaNnumberConstant.TMS_SHIPBILL_OPERATE_LOG_ID, "L");
			if (!restMessageLog.isSuccess()) {
				throw new RuntimeException("生成日志ID失败");
			}
			String idLog = restMessageLog.getData();
			// 日志记录
			TmsShipbillOperateLogModel logModel = new TmsShipbillOperateLogModel();
			logModel.setShipbillId(dto.getShipbillId());
			logModel.setShipbillNo(dto.getShipbillId());
			logModel.setOperateEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_QY + " " + memo+ " " + pendingPickUpStartShipmentVO.getCheckDetails());
			logModel.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_ZX_CONFIRM);
			logModel.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_SD);
			logModel.setOperateDate(date);
			logModel.setEnterpriseId(user.getEnterpriseId());
			logModel.setEnterpriseName(user.getEnterpriseName());
			logModel.setUserId(user.getUserid());
			logModel.setUserName(user.getNickname());
			logModel.setId(idLog);
			logModel.setOperateDate(date);
			logModel.setUserId(user.getUserid());
			logModel.setUserName(user.getNickname());
			logModel.setEnterpriseId(user.getEnterpriseId());
			logModel.setEnterpriseName(user.getEnterpriseName());
			logModel.setCreateperson(user.getNickname());
			logModel.setCreatetime(date);
			logModel.setUpdateperson(user.getNickname());
			logModel.setUpdatetime(date);
			tmsShipbillOperateLogMapper.save(logModel);

			// 获取运单明细
			ShipbillDetailQueryVO vo = new ShipbillDetailQueryVO();
			vo.setEnterpriseId(dto.getEnterpriseId());
			vo.setShipbillId(dto.getShipbillId());
			List<ShipbillItemDetailQueryDTO> itemDetails = tmsShipbillHeaderMapper.shipbillItemDetailQuery(vo);
			dto.setItemDetail(itemDetails);
			dto.setPackageDetailDTOList(pendingReceiptService.getPackageDetailDTO(dto.getShipbillId()));
			returndtos.add(dto);

			// 父运单的同步启运
			String fatherShipbillId = dto.getShipbillId();
			while (ToolKits.isNotEmpty(fatherShipbillId)) {
				fatherShipbillId = fatherStartShipment(fatherShipbillId, date, user, departurePhoto);
			}

			// STD-BUG20220823 lhb 4649启运登记、送达确认 需要同步回写 派车单的状态 20220915 start
			// 更新调度单状态
			Criteria criteriaDetail = Criteria.forClass(TmsLoadingBillDetailModel.class);
			Restriction r3 = Restrictions.eq(TmsLoadingBillDetailModel::getLoadingBillId, dto.getLoadingBillId());
			Restriction r4 = Restrictions.eq(TmsLoadingBillDetailModel::getEnterpriseId, user.getEnterpriseId());
			criteriaDetail.setRestriction(Restrictions.and(r3, r4));
			List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteriaDetail);
			int cnt = 0;
			if (ToolKits.isNotEmpty(tmsLoadingBillDetailModels)) {
				TmsLoadingBillDetailModel tmsLoadingBillDetail = tmsLoadingBillDetailModels.get(0);
				TmsLoadingBillHeaderModel secondLoadingBillHeaderModel = tmsLoadingBillHeaderMapper.findById(tmsLoadingBillDetail.getLoadingBillId(), TmsLoadingBillHeaderModel.class);

				// 运单，第一次调度，调度给承运商，第二次调度，承运商调度给司机或者承运商时，根据第二调度单，查询第一次的调度单
				criteriaDetail = Criteria.forClass(TmsLoadingBillDetailModel.class);
				r1 = Restrictions.eq(TmsLoadingBillDetailModel::getShipbillId, tmsLoadingBillDetail.getShipbillId());
				r2 = Restrictions.eq(TmsLoadingBillDetailModel::getEnterpriseId, user.getEnterpriseId());
				r3 = Restrictions.ne(TmsLoadingBillDetailModel::getLoadingBillId, dto.getLoadingBillId());
				criteriaDetail.setRestriction(Restrictions.and(r1, r2, r3));
				List<TmsLoadingBillDetailModel> firstLoadingBillDetails = tmsLoadingBillDetailMapper.findByCriteria(criteriaDetail);

				cnt = tmsLoadingBillDetailModels.stream().filter(t -> t.getStatus().intValue() < DataDictionaryConstant.SHIPBILL_STATUS_SD.intValue()).collect(Collectors.toList()).size();
				if (cnt == 0) {
					// 更新状态为启运
					secondLoadingBillHeaderModel.setStatus(DataDictionaryConstant.LOADING_BILL_STATUS_QY);
					loadingBillService.setLoadingBillDelivery(secondLoadingBillHeaderModel);
					tmsLoadingBillHeaderMapper.update(secondLoadingBillHeaderModel);
					// 第一次调度单状态更新
					if (ToolKits.isNotEmpty(firstLoadingBillDetails)) {
						TmsLoadingBillHeaderModel firstLoadingBillHeaderModel = tmsLoadingBillHeaderMapper.findById(firstLoadingBillDetails.get(0).getLoadingBillId(), TmsLoadingBillHeaderModel.class);
						firstLoadingBillHeaderModel.setVehicleDeviceId(pendingPickUpStartShipmentVO.getVehicleDeviceId());
						firstLoadingBillHeaderModel.setVehicleDeviceCode(pendingPickUpStartShipmentVO.getVehicleDeviceCode());
						firstLoadingBillHeaderModel.setVehicleDeviceName(pendingPickUpStartShipmentVO.getVehicleDeviceName());
						firstLoadingBillHeaderModel.setContainerId(pendingPickUpStartShipmentVO.getContainerId());
						firstLoadingBillHeaderModel.setContainerCode(pendingPickUpStartShipmentVO.getContainerCode());
						firstLoadingBillHeaderModel.setContainerName(pendingPickUpStartShipmentVO.getContainerName());
						firstLoadingBillHeaderModel.setStatus(DataDictionaryConstant.LOADING_BILL_STATUS_QY);
						loadingBillService.setLoadingBillDelivery(firstLoadingBillHeaderModel);
						tmsLoadingBillHeaderMapper.update(firstLoadingBillHeaderModel);
					}
				} else {
					// 更新状态为部分启运
					if (!secondLoadingBillHeaderModel.getStatus().equals(DataDictionaryConstant.LOADING_BILL_STATUS_QY_PART)) {
						secondLoadingBillHeaderModel.setVehicleDeviceId(pendingPickUpStartShipmentVO.getVehicleDeviceId());
						secondLoadingBillHeaderModel.setVehicleDeviceCode(pendingPickUpStartShipmentVO.getVehicleDeviceCode());
						secondLoadingBillHeaderModel.setVehicleDeviceName(pendingPickUpStartShipmentVO.getVehicleDeviceName());
						secondLoadingBillHeaderModel.setContainerId(pendingPickUpStartShipmentVO.getContainerId());
						secondLoadingBillHeaderModel.setContainerCode(pendingPickUpStartShipmentVO.getContainerCode());
						secondLoadingBillHeaderModel.setContainerName(pendingPickUpStartShipmentVO.getContainerName());
						secondLoadingBillHeaderModel.setStatus(DataDictionaryConstant.LOADING_BILL_STATUS_QY_PART);
						loadingBillService.setLoadingBillDelivery(secondLoadingBillHeaderModel);
						tmsLoadingBillHeaderMapper.update(secondLoadingBillHeaderModel);
						// 第一次调度单状态更新
						if (ToolKits.isNotEmpty(firstLoadingBillDetails)) {
							TmsLoadingBillHeaderModel firstLoadingBillHeaderModel = tmsLoadingBillHeaderMapper.findById(firstLoadingBillDetails.get(0).getLoadingBillId(), TmsLoadingBillHeaderModel.class);
							firstLoadingBillHeaderModel.setStatus(DataDictionaryConstant.LOADING_BILL_STATUS_QY_PART);
							firstLoadingBillHeaderModel.setVehicleDeviceId(pendingPickUpStartShipmentVO.getVehicleDeviceId());
							firstLoadingBillHeaderModel.setVehicleDeviceCode(pendingPickUpStartShipmentVO.getVehicleDeviceCode());
							firstLoadingBillHeaderModel.setVehicleDeviceName(pendingPickUpStartShipmentVO.getVehicleDeviceName());
							firstLoadingBillHeaderModel.setContainerId(pendingPickUpStartShipmentVO.getContainerId());
							firstLoadingBillHeaderModel.setContainerCode(pendingPickUpStartShipmentVO.getContainerCode());
							firstLoadingBillHeaderModel.setContainerName(pendingPickUpStartShipmentVO.getContainerName());
							loadingBillService.setLoadingBillDelivery(firstLoadingBillHeaderModel);
							tmsLoadingBillHeaderMapper.update(firstLoadingBillHeaderModel);
						}
					}
				}

				TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel = tmsLoadingBillHeaderMapper.findById(tmsLoadingBillDetail.getLoadingBillId(), TmsLoadingBillHeaderModel.class);
				if (StrUtil.isNotBlank(tmsLoadingBillHeaderModel.getVehicleDeviceId()) && StrUtil.isNotBlank(tmsLoadingBillHeaderModel.getVehicleDeviceCode())) {
					String deviceId = tmsLoadingBillHeaderModel.getVehicleDeviceId().split(",")[0];
					try {
						RestMessage<DeviceByOneDTO> restMessage1 = maindataFeign.deviceGetOne(Long.valueOf(deviceId));
						DeviceByOneDTO deviceByOneDTO = restMessage1.getData();
						if (BussinessConstant.E6.equals(deviceByOneDTO.getCompanyName())) {
							redisTemplate.opsForSet().add(RedisConstant.PULL_GPS_DEVICE_E6_KEY, tmsLoadingBillHeaderModel.getVehicleDeviceCode());
							log.info("易流 add loadingBillId={},vehicle={},deviceCode={}", tmsLoadingBillDetail.getLoadingBillId(), tmsLoadingBillHeaderModel.getVehiclePlateNumber(), deviceByOneDTO.getCode());
						} else if (BussinessConstant.G7.equals(deviceByOneDTO.getCompanyName())) {
							redisTemplate.opsForSet().add(RedisConstant.PULL_GPS_DEVICE_G7_KEY, tmsLoadingBillHeaderModel.getVehicleDeviceCode());
							log.info("g7 add loadingBillId={},vehicle={},deviceCode={}", tmsLoadingBillDetail.getLoadingBillId(), tmsLoadingBillHeaderModel.getVehiclePlateNumber(), deviceByOneDTO.getCode());
						}
					} catch (Exception e) {
						log.error("增加redis队列错误", e);
					}
				}
				MessageUtil.addMessage(new SendMessageDTO(MessageOrderTypeEnum.SHIP_NO.getCode(), MessageTypeEnum.START_SHIP.getCode(), Lists.newArrayList(tmsShipbillHeaderModel.getShipbillId())));
			}
			// STD-BUG20220823 lhb 4649启运登记、送达确认 需要同步回写 派车单的状态 20220915 end
		}
		return returndtos;
	}

	// STD-BUG20220823 lhb 启运登记修改运单明细发货件数 20220920 start
	/**
	 * 同步更新父运单商品明细
	 *
	 * @param shipbillId
	 * @param date
	 * @param user
	 * @return
	 */
	public String updateFatherShipbillDetail(String shipbillId, TmsShipbillDetailModel subShipbillDetailModel,BigDecimal totalDeliveryPcs, Date date, UserEntity user,ItemCheckDTO rsItemInfo) {
		// 查询运单
		TmsShipbillHeaderModel tmsShipbillHeaderModel = tmsShipbillHeaderMapper.findById(shipbillId, TmsShipbillHeaderModel.class);
		// 判断是否为原始单号
		if (ToolKits.isNotEmpty(tmsShipbillHeaderModel.getFatherShipbillId()) && !tmsShipbillHeaderModel.getFatherShipbillId().equals(shipbillId)) {
			// 查找父级单号
			TmsShipbillHeaderModel fatherShipbillHeaderModel = tmsShipbillHeaderMapper.findById(tmsShipbillHeaderModel.getFatherShipbillId(), TmsShipbillHeaderModel.class);

			Criteria criteriaShipbillDetail = Criteria.forClass(TmsShipbillDetailModel.class);
			Restriction r11 = Restrictions.eq(TmsShipbillDetailModel::getShipbillId, fatherShipbillHeaderModel.getShipbillId());
			Restriction r12 = Restrictions.eq(TmsShipbillDetailModel::getEnterpriseId, user.getEnterpriseId());
			Restriction r13 = Restrictions.eq(TmsShipbillDetailModel::getItemId, subShipbillDetailModel.getItemId());
			Restriction r14 = Restrictions.gt(TmsShipbillDetailModel::getPcs, BigDecimal.valueOf(0));
			criteriaShipbillDetail.setRestriction(Restrictions.and(r11, r12, r13,r14));
			List<TmsShipbillDetailModel> shipbillDetailModels = tmsShipbillDetailMapper.findByCriteria(criteriaShipbillDetail);

			if (ToolKits.isEmpty(shipbillDetailModels)) {
				throw new PrologException("运单【" + shipbillId + "】的父运单的运单商品明细【" + subShipbillDetailModel.getItemName() + "】不存在");
			}
			BigDecimal detailDeliveryPcs = totalDeliveryPcs;
			for (TmsShipbillDetailModel fatherShipbillDetailModel : shipbillDetailModels) {
				if (detailDeliveryPcs.intValue() <= 0) {
					break;
				}
				if (fatherShipbillDetailModel.getPcs().intValue() >= detailDeliveryPcs.intValue()) {
					fatherShipbillDetailModel.setDeliveryPcs(fatherShipbillDetailModel.getDeliveryPcs().add(detailDeliveryPcs));
					fatherShipbillDetailModel.setPickUpPcs(NumberUtil.add(fatherShipbillDetailModel.getPickUpPcs(), subShipbillDetailModel.getPickUpPcs()));

					// 剩余件数
					fatherShipbillDetailModel.setUpdateperson(user.getNickname());
					fatherShipbillDetailModel.setUpdatetime(date);
					fatherShipbillDetailModel.setPcs(fatherShipbillDetailModel.getOrigPcs().subtract(fatherShipbillDetailModel.getClosingPcs()).subtract(fatherShipbillDetailModel.getDeliveryPcs()));
					fatherShipbillDetailModel.setVolume(fatherShipbillDetailModel.getPcs().multiply(rsItemInfo.getVolume()));
					fatherShipbillDetailModel.setWeight(fatherShipbillDetailModel.getPcs().multiply(rsItemInfo.getWeight()));
					tmsShipbillDetailMapper.update(fatherShipbillDetailModel);
					detailDeliveryPcs = BigDecimal.valueOf(0);
					break;
				} else {
					fatherShipbillDetailModel.setDeliveryPcs(fatherShipbillDetailModel.getDeliveryPcs().add(fatherShipbillDetailModel.getDeliveryPcs()));
					fatherShipbillDetailModel.setPickUpPcs(NumberUtil.add(fatherShipbillDetailModel.getPickUpPcs(), subShipbillDetailModel.getPickUpPcs()));
					detailDeliveryPcs = detailDeliveryPcs.subtract(fatherShipbillDetailModel.getPcs());

					// 剩余件数
					fatherShipbillDetailModel.setUpdateperson(user.getNickname());
					fatherShipbillDetailModel.setUpdatetime(date);
					fatherShipbillDetailModel.setPcs(fatherShipbillDetailModel.getOrigPcs().subtract(fatherShipbillDetailModel.getClosingPcs()).subtract(fatherShipbillDetailModel.getDeliveryPcs()));
					fatherShipbillDetailModel.setVolume(fatherShipbillDetailModel.getPcs().multiply(rsItemInfo.getVolume()));
					fatherShipbillDetailModel.setWeight(fatherShipbillDetailModel.getPcs().multiply(rsItemInfo.getWeight()));
					tmsShipbillDetailMapper.update(fatherShipbillDetailModel);
				}
			}
			if (detailDeliveryPcs.intValue() > 0) {
				throw new PrologException("运单【" + shipbillId + "】的商品【" + subShipbillDetailModel.getItemName() + "】的件数>父运单的件数");
			}

			// 更新运单
			if (ToolKits.isEmpty(fatherShipbillHeaderModel.getTotalDeliveryPcs())) {
				fatherShipbillHeaderModel.setTotalDeliveryPcs(totalDeliveryPcs);
			} else {
				fatherShipbillHeaderModel.setTotalDeliveryPcs(fatherShipbillHeaderModel.getTotalDeliveryPcs().add(totalDeliveryPcs));
			}

			fatherShipbillHeaderModel.setTotalDeliveryVolume(fatherShipbillHeaderModel.getTotalDeliveryPcs().multiply(rsItemInfo.getVolume()));
			fatherShipbillHeaderModel.setTotalDeliveryWeight(fatherShipbillHeaderModel.getTotalDeliveryPcs().multiply(rsItemInfo.getWeight()));

			if (ToolKits.isEmpty(fatherShipbillHeaderModel.getDepartureTime())) {
				fatherShipbillHeaderModel.setDepartureTime(new Date());
			}

			fatherShipbillHeaderModel.setTotalPcs(fatherShipbillHeaderModel.getTotalPcs().subtract(totalDeliveryPcs));
			fatherShipbillHeaderModel.setTotalVolume(fatherShipbillHeaderModel.getTotalPcs().multiply(rsItemInfo.getVolume()));
			fatherShipbillHeaderModel.setTotalWeight(fatherShipbillHeaderModel.getTotalPcs().multiply(rsItemInfo.getWeight()));
			fatherShipbillHeaderModel.setActualTotalPcs(fatherShipbillHeaderModel.getTotalPcs());
			fatherShipbillHeaderModel.setActualTotalVolume(fatherShipbillHeaderModel.getTotalVolume());
			fatherShipbillHeaderModel.setActualTotalWeight(fatherShipbillHeaderModel.getTotalWeight());

			fatherShipbillHeaderModel.setUpdateperson(user.getNickname());
			fatherShipbillHeaderModel.setUpdatetime(date);
			tmsShipbillHeaderMapper.update(fatherShipbillHeaderModel);

			return fatherShipbillHeaderModel.getShipbillId();
		}
		return null;
	}
	// STD-BUG20220823 lhb 启运登记修改运单明细发货件数 20220920 end

	/**
	 * 父运单启运确认
	 *
	 * @param shipbillId
	 * @param date
	 * @param user
	 * @return
	 */
	public String fatherStartShipment(String shipbillId, Date date, UserEntity user, String departurePhoto) {
		// 查询运单
		TmsShipbillHeaderModel tmsShipbillHeaderModel = tmsShipbillHeaderMapper.findById(shipbillId, TmsShipbillHeaderModel.class);
		// 判断是否为原始单号
		if (ToolKits.isNotEmpty(tmsShipbillHeaderModel.getFatherShipbillId()) && !tmsShipbillHeaderModel.getFatherShipbillId().equals(shipbillId)) {
			// 查找父级单号
			TmsShipbillHeaderModel fatherShipbillHeaderModel = tmsShipbillHeaderMapper.findById(tmsShipbillHeaderModel.getFatherShipbillId(), TmsShipbillHeaderModel.class);

			// 判断父级单号的状态是否为开始启运
			if (!DataDictionaryConstant.SHIPBILL_STATUS_SD.equals(fatherShipbillHeaderModel.getStatus())) {
				// 修改父级运单状态
				fatherShipbillHeaderModel.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_SD);
				fatherShipbillHeaderModel.setUpdatetime(date);
				fatherShipbillHeaderModel.setUpdateperson(user.getNickname());
				fatherShipbillHeaderModel.setTransportStatus(DataDictionaryConstant.TRANSPORT_STATUS_SHIPPING);
				tmsShipbillHeaderMapper.update(fatherShipbillHeaderModel);

				// 运单日志信息
				ShipbillOperateLogSaveNewVO shipbillOperateLogSaveNewVO = new ShipbillOperateLogSaveNewVO();
				shipbillOperateLogSaveNewVO.setShipbillId(fatherShipbillHeaderModel.getShipbillId());
				shipbillOperateLogSaveNewVO.setShipbillNo(fatherShipbillHeaderModel.getShipbillId());
				shipbillOperateLogSaveNewVO.setOperateDate(date);
				shipbillOperateLogSaveNewVO.setEnterpriseId(user.getEnterpriseId());
				shipbillOperateLogSaveNewVO.setEnterpriseName(user.getEnterpriseName());
				shipbillOperateLogSaveNewVO.setUserId(user.getUserid());
				shipbillOperateLogSaveNewVO.setUserName(user.getNickname());

				// 节点记录
				ShipbillNodeTrackingSaveNewVO model = new ShipbillNodeTrackingSaveNewVO();
				model.setNodeDate(date);
				model.setShipbillId(fatherShipbillHeaderModel.getShipbillId());
				model.setShipbillNo(fatherShipbillHeaderModel.getShipbillId());
				model.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_QY);
				model.setNodeEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_QY);
				model.setUserId(user.getUserid());
				model.setUserName(user.getNickname());
				model.setEnterpriseId(user.getEnterpriseId());
				model.setEnterpriseName(user.getEnterpriseName());
				model.setPicUrl(departurePhoto);
				model.setUserId(user.getUserid());
				model.setUserName(user.getNickname());
				model.setEnterpriseId(user.getEnterpriseId());
				model.setEnterpriseName(user.getEnterpriseName());
				shipbillNodeTrackingService.addShipbillNodeTrackingNewData(model);

				// 运单日志保存
				shipbillOperateLogSaveNewVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_QY);
				shipbillOperateLogSaveNewVO.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_ZX_CONFIRM);
				shipbillOperateLogSaveNewVO.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_QY);
				shipbillOperateLogService.addShipbillOperateLogNewData(shipbillOperateLogSaveNewVO);

				return fatherShipbillHeaderModel.getShipbillId();
			}
		}
		return null;
	}

	@Override
	public WarehousePickUpNumberDataDTO warehousePickUpNumberData(WarehousePickUpNumberDataVO queryvo) throws Exception {
		ToolKits.isParamNull(queryvo, "司机待预约明细查询请求参数不为空");
		ToolKits.isParamNull(queryvo.getDriverId(), "司机ID不为空");
		ToolKits.isParamNull(queryvo.getVehiclePlateNumber(), "车牌号不为空");
		ToolKits.isParamNull(queryvo.getEnterpriseId(), "企业ID不能为空");
		ToolKits.isParamNull(queryvo.getBranchId(), "仓库ID不能为空");
		WarehousePickUpNumberDataDTO warehousePickUpNumberDataDTO = new WarehousePickUpNumberDataDTO();
		List<WarehousePickUpPendingDataDTO> dtos = tmsAppointmentHeaderMapper.warehousePickUpPendingQuery(queryvo);
		if (ObjectUtils.isEmpty(dtos)) {
			String driverQrShowType = mainDataProxy.getSystemParamByCode(DataDictionaryConstant.DRIVER_QR_SHOW_TYPE);
			if (DataDictionaryConstant.DRIVER_QR_SHOW_TYPE_SHIP_BILL.equals(driverQrShowType)) {
				warehousePickUpNumberDataDTO.setPickType("2");
				List<WarehousePickUpWaybillDataDTO> waybillDtos = tmsLoadingBillDetailMapper.warehousePickUpWaybillQuery(queryvo);
				if (ObjectUtils.isEmpty(waybillDtos)) {
					throw new RuntimeException("没有待取号的运单");
				}
				List<WarehousePickUpWaybillDataDTO> waybillnewDtos = new ArrayList<WarehousePickUpWaybillDataDTO>();
				for (WarehousePickUpWaybillDataDTO dataDto : waybillDtos) {
					ShipbillDetailQueryVO vo = new ShipbillDetailQueryVO();
					vo.setEnterpriseId(dataDto.getEnterpriseId());
					vo.setShipbillId(dataDto.getShipbillId());
					List<ShipbillItemDetailQueryDTO> itemDetails = tmsShipbillHeaderMapper.shipbillItemDetailQuery(vo);
					dataDto.setItemDetail(itemDetails);
					waybillnewDtos.add(dataDto);
				}
				warehousePickUpNumberDataDTO.setWaybillDetail(waybillnewDtos);
				return warehousePickUpNumberDataDTO;
			} else {
				warehousePickUpNumberDataDTO.setPickType("3");
				List<WarehousePickUpLoadingBillDataDTO> loadingBillList = tmsLoadingBillDetailMapper.warehousePickUpLoadingBillQuery(queryvo);
				if (ObjectUtils.isEmpty(loadingBillList)) {
					throw new BizException("没有待取号的派车单");
				}
				warehousePickUpNumberDataDTO.setLoadingBillList(loadingBillList);
				return warehousePickUpNumberDataDTO;
			}
		} else {
			warehousePickUpNumberDataDTO.setPickType("1");
			warehousePickUpNumberDataDTO.setPendingDetail(dtos.stream().peek(header -> {
				Criteria loadBillCriteria = Criteria.forClass(TmsAppointmentDetailModel.class);
				Restriction loadBillRestriction = Restrictions.eq(TmsAppointmentDetailModel::getAppointmentId, header.getAppointmentId());
				loadBillCriteria.setRestriction(Restrictions.and(loadBillRestriction));
				List<TmsAppointmentDetailModel> tmsAppointmentDetailModels = tmsAppointmentDetailMapper.findByCriteria(loadBillCriteria);
				//设置预约单的派车单
				header.setLoadingBillIds(DataUtils.getLoadingBillIds(tmsAppointmentDetailModels));
			}).collect(Collectors.toList()));
			return warehousePickUpNumberDataDTO;
		}
	}

	/**
	 * 按运单取号
	 */
	@Override
	public PendingPickUpTakeNumberDTO takeNumberByShipbill(TakeNumberByShipbillVO vo) throws Exception {
		ToolKits.isParamNull(vo, "取号请求参数不能为空");
		ToolKits.isParamNull(vo.getBranchId(), "取号仓库不能为空");
		ToolKits.isParamNull(vo.getDriverId(), "取号司机不能为空");
		ToolKits.isParamNull(vo.getIds(), "请选择要取号的运单");

		UserEntity user = PlgFxUsrUtils.getUserEntity();
		ToolKits.isParamNull(user, "当前人员没有操作权限");

		List<TmsLoadingBillDetailModel> loadingBillDetailModels = tmsLoadingBillDetailMapper.findByIds(TmsLoadingBillDetailModel.class, vo.getIds().stream().toArray(),null);
		if (ToolKits.isEmpty(loadingBillDetailModels)) {
			throw new PrologException("派车单明细不存在");
		}
		List<TmsLoadingBillDetailModel> noTakeAndCallShipbillHeaderModels = loadingBillDetailModels.stream()
																								   .filter(h->!h.getFlowConfig()
																												.contains(DataDictionaryConstant.FLOW_CONFIG_APPOINTMENT_TN_CN))
																								   .collect(Collectors.toList());
		if (ToolKits.isNotEmpty(noTakeAndCallShipbillHeaderModels) && noTakeAndCallShipbillHeaderModels.size() != vo.getIds().size()) {
			throw new PrologException("请勾选相同预约流程的运单");
		}
		List<TmsLoadingBillDetailModel> hasTakeAndCallShipbillHeaderModels = loadingBillDetailModels.stream().filter(h->h.getFlowConfig()
																														 .contains(DataDictionaryConstant.FLOW_CONFIG_APPOINTMENT_TN_CN))
																									.collect(Collectors.toList());
		if (ToolKits.isNotEmpty(hasTakeAndCallShipbillHeaderModels) && hasTakeAndCallShipbillHeaderModels.size() != vo.getIds().size()) {
			throw new PrologException("请勾选相同预约流程的运单");
		}

		Criteria appointCriteria = Criteria.forClass(TmsAppointmentDetailModel.class);
		Restriction appointRestriction = Restrictions.in(TmsAppointmentDetailModel::getShipbillId,
				loadingBillDetailModels.stream()
									   .map(TmsLoadingBillDetailModel::getShipbillId)
									   .distinct().collect(Collectors.toList()));
		appointCriteria.setRestriction(Restrictions.and(appointRestriction));
		List<TmsAppointmentDetailModel> tmsAppointmentDetailModelList = tmsAppointmentDetailMapper.findByCriteria(appointCriteria);
		if (CollectionUtil.isNotEmpty(tmsAppointmentDetailModelList)) {
			List<TmsAppointmentHeaderModel> appointmentModelList = tmsAppointmentHeaderMapper.findByIds(
					TmsAppointmentHeaderModel.class, tmsAppointmentDetailModelList.stream().map(
							TmsAppointmentDetailModel::getAppointmentId).distinct().collect(Collectors.toList()).toArray(), null);
			if (!appointmentModelList.stream().allMatch(headerModel -> DataDictionaryConstant.APPOINTMENT_STATUS_QX.equals(headerModel.getStatus()))) {
				throw new BizException("运单重复取号");
			}
		}
		// 查询仓库信息
		RestMessage<TmsBaseBranchDTO> restMessage1 = maindataFeign.getOneBranch(vo.getBranchId());
		if (!restMessage1.isSuccess()) {
			throw new PrologException("仓库查询接口调用失败：" + restMessage1.getMessage());
		}
		ToolKits.isParamNull(restMessage1.getData(), "仓库ID【" + vo.getBranchId() + "】不存在");
		// 仓库叫号处理方式
		Integer callMethod = restMessage1.getData().getCallHandleType();
		ToolKits.isParamNull(restMessage1.getData().getApTimeDTOList(), "仓库ID【" + vo.getBranchId() + "】未维护可预约时间段");
		// 最后可预约时间小时部分
		Integer hour = 0;
		// 最后可预约时间分钟部分
		String minute = "00";
		// 仓可预约时间段处理
		List<TmsBaseBranchApTimeDTO> tmsBaseBranchApTimeDTOs = restMessage1.getData().getApTimeDTOList();
		for (TmsBaseBranchApTimeDTO tmsBaseBranchApTimeDTO : tmsBaseBranchApTimeDTOs) {
			Integer endHour = Integer.parseInt(tmsBaseBranchApTimeDTO.getEndTime().split(":")[0]);
			if (endHour > hour) {
				hour = endHour;
				minute = tmsBaseBranchApTimeDTO.getEndTime().split(":")[1];
			}
		}

		// 预约时间段开始小时
		String startHour = String.format("%0" + 2 + "d", hour);
		// 预约时间段结束小时
		String endhour = String.format("%0" + 2 + "d", hour + 1);

		// 当前时间
		Date date = DateUtil.date();

		// 获取预约单ID
		RestMessage<String> restMessageId = maindataFeign.getCodeNumberByCode(SeriaNnumberConstant.TMS_APPOINTMENT_HEADER_ID, "L");
		if (!restMessageId.isSuccess()) {
			throw new PrologException("生成预约主表ID失败");
		}

		TmsAppointmentHeaderModel tmsAppointmentHeader = new TmsAppointmentHeaderModel();
		tmsAppointmentHeader.setAppointmentId(restMessageId.getData());
		tmsAppointmentHeader.setAppointmentNo(restMessageId.getData());
		tmsAppointmentHeader.setAppointmentType(DataDictionaryConstant.APPOINTMENT_TYPE_TH);
		tmsAppointmentHeader.setBranchId(vo.getBranchId());
		tmsAppointmentHeader.setBranchCode(restMessage1.getData().getCode());
		tmsAppointmentHeader.setBranchName(restMessage1.getData().getName());
		tmsAppointmentHeader.setBranchAddress(restMessage1.getData().getAddress());
		tmsAppointmentHeader.setAppointmentDate(DateUtil.parseDate(DateUtil.today()));
		tmsAppointmentHeader.setAppointmentTime(startHour + ":" + minute + "-" + endhour + ":" + minute);
		tmsAppointmentHeader.setReserveNumberTime(date);
		tmsAppointmentHeader.setCallNumberTime(date);
		tmsAppointmentHeader.setQueueNumberTime(date);
		tmsAppointmentHeader.setDriverId(vo.getDriverId());
		tmsAppointmentHeader.setDriverCode(vo.getDriverCode());
		tmsAppointmentHeader.setDriverName(vo.getDriverName());
		tmsAppointmentHeader.setDriverPhoneNumber(vo.getDriverPhoneNumber());
		tmsAppointmentHeader.setVehiclePlateNumber(vo.getVehiclePlateNumber());


		// 获取明细ID
		RestMessage<List<String>> restMessage = maindataFeign.getCodeNumberByCodes(SeriaNnumberConstant.TMS_APPOINTMENT_DETAIL_ID, "L", vo.getIds().size());
		if (!restMessage.isSuccess()) {
			throw new PrologException("批量生成预约单明细ID失败:" + restMessage.getMessage());
		}

		// 是否理货完成标识
		Boolean tallyStatus = false;
		Boolean hasTakeNumAndCallNum = false;
		Boolean hasLoading = false;
		// 紧急运单数
		Integer urgentQuantity = 0;
		BigDecimal totPcs = BigDecimal.valueOf(0);
		BigDecimal totVolume = BigDecimal.valueOf(0);
		BigDecimal totWeight = BigDecimal.valueOf(0);
		for (int i = 0; i < vo.getIds().size(); i++) {
			// 装车单明细ID
			String id = vo.getIds().get(i);

			// 查下装车单明细
			TmsLoadingBillDetailModel tmsLoadingBillDetail = tmsLoadingBillDetailMapper.findById(id, TmsLoadingBillDetailModel.class);
			ToolKits.isParamNull(tmsLoadingBillDetail, "明细ID【" + id + "】不存在");

			if (ToolKits.isNotEmpty(tmsLoadingBillDetail.getFlowConfig())
					&& tmsLoadingBillDetail.getFlowConfig().contains(DataDictionaryConstant.FLOW_CONFIG_APPOINTMENT_TN_CN)) {
				hasTakeNumAndCallNum = true;
			}

			int nextStatus = DataDictionaryConstant.SHIPBILL_STATUS_APP_ING;
			if (ToolKits.isNotEmpty(tmsLoadingBillDetail.getFlowConfig()) && tmsLoadingBillDetail.getFlowConfig().contains(DataDictionaryConstant.FLOW_CONFIG_ARRANGE_GOODS)) {
				tallyStatus = true;
				nextStatus = DataDictionaryConstant.SHIPBILL_STATUS_LH_START;
			}
			if (ToolKits.isNotEmpty(tmsLoadingBillDetail.getFlowConfig()) && tmsLoadingBillDetail.getFlowConfig().contains(DataDictionaryConstant.FLOW_CONFIG_LOAD_UNLOAD)) {
				hasLoading = true;
			}
			int flowStatus = businessFlowUtil.judgmentNextFlowSts(tmsLoadingBillDetail.getFlowConfig(), DataDictionaryConstant.FLOW_CONFIG_APPOINTMENT);
			if (hasTakeNumAndCallNum &&
					NumberUtil.isGreater(BigDecimal.valueOf(flowStatus),BigDecimal.valueOf(DataDictionaryConstant.SHIPBILL_STATUS_ZX_START))) {
				nextStatus = flowStatus;
			} else if (!hasTakeNumAndCallNum ) {
				nextStatus = flowStatus;
			}

			// 生成预约明细
			TmsAppointmentDetailModel tmsAppointmentDetail = new TmsAppointmentDetailModel();
			BeanUtils.copyProperties(tmsLoadingBillDetail, tmsAppointmentDetail);
			tmsAppointmentDetail.setId(restMessage.getData().get(i));
			tmsAppointmentDetail.setAppointmentId(tmsAppointmentHeader.getAppointmentId());
			tmsAppointmentDetail.setAppointmentNo(tmsAppointmentHeader.getAppointmentNo());
			tmsAppointmentDetail.setCreatetime(date);
			tmsAppointmentDetail.setCreateperson(user.getNickname());
			tmsAppointmentDetail.setUpdatetime(date);
			tmsAppointmentDetail.setUpdateperson(user.getNickname());
			tmsAppointmentDetail.setEnterpriseId(user.getEnterpriseId());
			tmsAppointmentDetail.setEnterpriseName(user.getEnterpriseName());
			tmsAppointmentDetail.setStatus(nextStatus);
			tmsAppointmentDetailMapper.save(tmsAppointmentDetail);

			// 同步更新装车单明细和运单状态
			tmsLoadingBillDetail.setStatus(nextStatus);
			tmsLoadingBillDetail.setUpdatetime(date);
			tmsLoadingBillDetail.setUpdateperson(user.getNickname());
			tmsLoadingBillDetailMapper.update(tmsLoadingBillDetail);

			TmsShipbillHeaderModel tmsShipbillHeader = tmsShipbillHeaderMapper.findById(tmsLoadingBillDetail.getShipbillId(), TmsShipbillHeaderModel.class);
			if (ToolKits.isNotEmpty(tmsShipbillHeader)) {
				tmsShipbillHeader.setStatus(nextStatus);
				tmsShipbillHeader.setUpdatetime(date);
				tmsShipbillHeader.setUpdateperson(user.getNickname());
				tmsShipbillHeaderMapper.update(tmsShipbillHeader);
			} else {
				throw new PrologException("运单查询失败");
			}

			if (ObjectUtil.equal(DataDictionaryConstant.ORDER_TYPE_JJ, tmsLoadingBillDetail.getOrderType()) || ObjectUtil.equal(DataDictionaryConstant.ORDER_TYPE_JJJ, tmsLoadingBillDetail.getOrderType())) {
				urgentQuantity++;
			}

			// 计算汇总的总件数 总体积 总重量
			totPcs = totPcs.add(tmsLoadingBillDetail.getTotalPcs());
			totVolume = totVolume.add(tmsLoadingBillDetail.getTotalVolume());
			totWeight = totWeight.add(tmsLoadingBillDetail.getTotalWeight());
		}

		if (hasTakeNumAndCallNum) {
			if (!hasLoading && !tallyStatus) {
				tmsAppointmentHeader.setStatus(DataDictionaryConstant.APPOINTMENT_STATUS_ZXWC);
			} else {
				// 判断仓库是否存在提货等待的车位
				RestMessage<List<TmsBaseCarportDTO>> restMessage2 = maindataFeign.queryCarportList(vo.getBranchId());
				if (!restMessage2.isSuccess()) {
					throw new PrologException("仓库车位查询接口调用失败：" + restMessage2.getMessage());
				}
				List<TmsBaseCarportDTO> filterList = Optional.ofNullable(restMessage2.getData()).orElse(new ArrayList<>()).stream().filter(dto -> ObjectUtil.equal(dto.getType(), DataDictionaryConstant.CARPORT_TYPE_THDDQ)).collect(Collectors.toList());
				// 提货等待区车位数
				int count1 = filterList.size();

				if (count1 == 0) {
					// 不存在提货等待的车位
					tmsAppointmentHeader.setStatus(DataDictionaryConstant.APPOINTMENT_STATUS_YQH);
				} else {
					// 查询预约单中,当前仓库下,预约日期为今天,预约单状态为【等待中】的预约单记录条数
					Criteria criteria = Criteria.forClass(TmsAppointmentHeaderModel.class);
					Restriction r1 = Restrictions.eq(TmsAppointmentHeaderModel::getEnterpriseId, user.getEnterpriseId());
					Restriction r2 = Restrictions.eq(TmsAppointmentHeaderModel::getBranchId, vo.getBranchId());
					Restriction r3 = Restrictions.between(TmsAppointmentHeaderModel::getAppointmentDate, DateUtil.parseDate(DateUtil.today()), DateUtil.parseDate(DateUtil.today()));
					Restriction r4 = Restrictions.eq(TmsAppointmentHeaderModel::getStatus, DataDictionaryConstant.APPOINTMENT_STATUS_DDZ);
					criteria.setRestriction(Restrictions.and(r1, r2, r3, r4));
					List<TmsAppointmentHeaderModel> list = tmsAppointmentHeaderMapper.findByCriteria(criteria);
					// 等待区已使用车位数
					int count2 = ToolKits.isEmpty(list) ? 0 : list.size();
					if (count1 - count2 > 0) {
						// 当前仓库下还存在可用的空闲车位,更新当前预约单状态为【等待中】
						tmsAppointmentHeader.setStatus(DataDictionaryConstant.APPOINTMENT_STATUS_DDZ);
					} else {
						// 当前仓库下没有可用的空闲车位,更新当前预约单状态为【已取号】
						tmsAppointmentHeader.setStatus(DataDictionaryConstant.APPOINTMENT_STATUS_YQH);
					}
				}
			}
		} else {
			if (tallyStatus) {
				tmsAppointmentHeader.setStatus(DataDictionaryConstant.APPOINTMENT_STATUS_DLH);
			} else if (hasLoading) {
				tmsAppointmentHeader.setStatus(DataDictionaryConstant.APPOINTMENT_STATUS_DZX);
			} else {
				tmsAppointmentHeader.setStatus(DataDictionaryConstant.APPOINTMENT_STATUS_ZXWC);
			}
		}

		tmsAppointmentHeader.setUrgentQuantity(urgentQuantity);
		tmsAppointmentHeader.setShipbillQuantity(vo.getIds().size());
		tmsAppointmentHeader.setTotalPcs(totPcs);
		tmsAppointmentHeader.setTotalVolume(totVolume);
		tmsAppointmentHeader.setTotalWeight(totWeight);
		tmsAppointmentHeader.setEnterpriseId(user.getEnterpriseId());
		tmsAppointmentHeader.setEnterpriseName(user.getEnterpriseName());
		tmsAppointmentHeader.setCreatetime(date);
		tmsAppointmentHeader.setCreateperson(user.getNickname());
		tmsAppointmentHeader.setUpdatetime(date);
		tmsAppointmentHeader.setUpdateperson(user.getNickname());
		tmsAppointmentHeader.setCreateMode(AppointCreateModeEnum.SHIP.getCode());

		if (tallyStatus) {
			// 未理货
			tmsAppointmentHeader.setTallyStatus(DataDictionaryConstant.TALLY_STATUS_WLH);
		} else {
			// 理货完成
			tmsAppointmentHeader.setTallyStatus(DataDictionaryConstant.TALLY_STATUS_LHWC);
		}

		// 获取取号顺序
		String number = this.getShipbillQueueNumber(user, date, tmsAppointmentHeader, callMethod, startHour, endhour);
		ToolKits.isParamNull(number, "预约取号失败");

		// 预约单保存
		tmsAppointmentHeaderMapper.save(tmsAppointmentHeader);

		PendingPickUpTakeNumberDTO pendingPickUpTakeNumberDTO = new PendingPickUpTakeNumberDTO();
		pendingPickUpTakeNumberDTO.setAppointmentDate(DateUtil.formatDate(tmsAppointmentHeader.getAppointmentDate()));
		pendingPickUpTakeNumberDTO.setAppointmentId(tmsAppointmentHeader.getAppointmentId());
		pendingPickUpTakeNumberDTO.setAppointmentTime(tmsAppointmentHeader.getAppointmentTime());
		pendingPickUpTakeNumberDTO.setAppointNumber(tmsAppointmentHeader.getAppointmentId());
		pendingPickUpTakeNumberDTO.setDriverName(tmsAppointmentHeader.getDriverName());
		pendingPickUpTakeNumberDTO.setDriverTel(tmsAppointmentHeader.getDriverPhoneNumber());
		pendingPickUpTakeNumberDTO.setQueueNumber(tmsAppointmentHeader.getQueueNumber());
		pendingPickUpTakeNumberDTO.setShipBillNums(tmsAppointmentHeader.getShipbillQuantity());
		pendingPickUpTakeNumberDTO.setShipBillPackages(tmsAppointmentHeader.getTotalPcs().intValue());
		pendingPickUpTakeNumberDTO.setShipfromDate(DateUtil.formatDate(tmsAppointmentHeader.getAppointmentDate()) + " " + tmsAppointmentHeader.getAppointmentTime());
		pendingPickUpTakeNumberDTO.setShipfromAddress(tmsAppointmentHeader.getBranchAddress());
		pendingPickUpTakeNumberDTO.setVehiclePlateNumber(tmsAppointmentHeader.getVehiclePlateNumber());
		pendingPickUpTakeNumberDTO.setShipfromName(tmsAppointmentHeader.getBranchName());
		pendingPickUpTakeNumberDTO.setShipfromId(tmsAppointmentHeader.getBranchId().toString());
		MessageUtil.addMessage(new SendMessageDTO(MessageOrderTypeEnum.SHIP_NO.getCode(), MessageTypeEnum.TAKE_NUMBER.getCode(), vo.getIds()));
		return pendingPickUpTakeNumberDTO;
	}

	/**
	 * 获取取号顺序
	 *
	 * @param user
	 * @param date
	 * @param tmsAppointmentHeader
	 * @param callMethod
	 * @param startHour
	 * @param endhour
	 * @return
	 */
	public String getShipbillQueueNumber(UserEntity user, Date date, TmsAppointmentHeaderModel tmsAppointmentHeader, Integer callMethod, String startHour, String endhour) {
		Criteria criteria = Criteria.forClass(TmsAppointmentHeaderModel.class);
		Restriction r1 = Restrictions.eq(TmsAppointmentHeaderModel::getEnterpriseId, user.getEnterpriseId());
		Restriction r2 = Restrictions.eq(TmsAppointmentHeaderModel::getBranchId, tmsAppointmentHeader.getBranchId());
		Restriction r3 = Restrictions.between(TmsAppointmentHeaderModel::getQueueNumberTime, DateUtil.beginOfDay(date), DateUtil.endOfDay(date));
		Restriction r4 = Restrictions.eq(TmsAppointmentHeaderModel::getAppointmentType, DataDictionaryConstant.APPOINTMENT_TYPE_TH);
		Restriction r5 = Restrictions.like(TmsAppointmentHeaderModel::getQueueNumber, "%" + startHour + endhour + "%");

		// 预约号
		StringBuffer number = new StringBuffer();

		// 判断当前预约单是否包含紧急加急运单
		if (tmsAppointmentHeader.getUrgentQuantity() > 0) {
			// 生成今天预约单排队号(年月日+当前仓库设置的最晚时间段后的一个小时时间段+三位自增数)
			number = new StringBuffer("急");

			Restriction r6 = Restrictions.gt(TmsAppointmentHeaderModel::getUrgentQuantity, 0);
			criteria.setRestriction(Restrictions.and(r1, r2, r3, r4, r5, r6));
			List<TmsAppointmentHeaderModel> orderList = tmsAppointmentHeaderMapper.findByCriteria(criteria);

			// 获取最大排队号+1作为当前预约单的排队号，最大排队号为空从001开始
			if (ToolKits.isNotEmpty(orderList) && orderList.size() > 0) {
				// 取出所有排队号
				List<String> queueNumberList = orderList.stream().map(TmsAppointmentHeaderModel::getQueueNumber).collect(Collectors.toList());
				// 排队号转换类型
				List<BigDecimal> queueNumbers = queueNumberList.stream().map(s -> new BigDecimal(s.replace("急", ""))).collect(Collectors.toList());
				// 获取最大排队号
				BigDecimal queueNumberMax = queueNumbers.stream().reduce(queueNumbers.get(0), BigDecimal::max);
				// 自增加1生成当前预约单的取号号码
				number.append(queueNumberMax.add(new BigDecimal("1")));
				tmsAppointmentHeader.setQueueNumber(number.toString());
			} else {
				// 生成今天预约单排队号(年月日+当前仓库设置的最晚时间段后的一个小时时间段+三位自增数)
				number.append(DateUtil.format(date, DatePattern.PURE_DATE_FORMAT)).append(startHour).append(endhour).append("001");
				tmsAppointmentHeader.setQueueNumber(number.toString());
			}

			// 生成叫号顺序
			this.getCallNumber(user, tmsAppointmentHeader, callMethod, true, date);
		} else {
			Restriction r6 = Restrictions.eq(TmsAppointmentHeaderModel::getUrgentQuantity, 0);
			criteria.setRestriction(Restrictions.and(r1, r2, r3, r4, r5, r6));
			List<TmsAppointmentHeaderModel> orderList = tmsAppointmentHeaderMapper.findByCriteria(criteria);
			if (ToolKits.isNotEmpty(orderList) && orderList.size() > 0) {
				// 取出所有排队号
				List<String> queueNumberList = orderList.stream().map(TmsAppointmentHeaderModel::getQueueNumber).collect(Collectors.toList());
				// 排队号转换类型
				List<BigDecimal> queueNumbers = queueNumberList.stream().map(s -> new BigDecimal(s)).collect(Collectors.toList());
				// 获取最大排队号
				BigDecimal queueNumberMax = queueNumbers.stream().reduce(queueNumbers.get(0), BigDecimal::max);
				// 自增加1生成当前预约单的取号号码
				number.append(queueNumberMax.add(new BigDecimal("1")));
				tmsAppointmentHeader.setQueueNumber(number.toString());
			} else {
				// 生成今天预约单排队号(年月日+当前仓库设置的最晚时间段后的一个小时时间段+三位自增数)
				number.append(DateUtil.format(date, DatePattern.PURE_DATE_FORMAT)).append(startHour).append(endhour).append("001");
				tmsAppointmentHeader.setQueueNumber(number.toString());
			}

			// 生成叫号顺序
			this.getCallNumber(user, tmsAppointmentHeader, callMethod, false, date);
		}

		return number.toString();
	}

	/**
	 * 开启审批流程
	 * @param model
	 * @param approvalFlowType
	 * @param approvalObjectId
	 * @return
	 */
	private Boolean approvalOpen(TmsShipbillHeaderModel model, Integer approvalFlowType, String approvalObjectId) {
		UserEntity user = PlgFxUsrUtils.getUserEntity();
		ApprovalOpenVO approvalOpenVO = new ApprovalOpenVO();
		approvalOpenVO.setApprovalFlowType(approvalFlowType);
		approvalOpenVO.setApprovalObjectId(approvalObjectId);
		approvalOpenVO.setApprovalObjectCode(approvalObjectId);
		approvalOpenVO.setApprovalObjectName(approvalObjectId);
		approvalOpenVO.setInitiatedUserId(user.getUserid());
		approvalOpenVO.setInitiatedUserName(user.getNickname());
		approvalOpenVO.setDeliveryMethodType(model.getDeliveryMethodType());
		approvalOpenVO.setShipperType(model.getShipperType());
		approvalOpenVO.setShipperUnitId(model.getShipperUnitId());
		approvalOpenVO.setConsigneeType(model.getConsigneeType());
		approvalOpenVO.setConsigneeUnitId(model.getConsigneeUnitId());
		approvalOpenVO.setOrderType(model.getOrderType());
		approvalOpenVO.setOrderBusinessType(model.getOrderBusinessType());
		approvalOpenVO.setTransportType(model.getTransportType());
		approvalOpenVO.setTemperatureRequirement(model.getTemperatureRequirement());
		approvalOpenVO.setCargoOwnerId(model.getCargoOwnerId());
		approvalOpenVO.setDepartmentId(model.getDepartmentId());
		RestMessage<Boolean> restMessage1 = maindataFeign.openExecute(approvalOpenVO);
		if (!restMessage1.isSuccess()) {
			throw new BizException("调用maindata服务是否开启审批流接口失败:流程类型=" + approvalFlowType + ",错误信息="+restMessage1.getMessage());
		}
		return restMessage1.getData();
	}
}
