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

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
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.PrologException;
import com.prolog.framework.core.pojo.Page;
import com.prolog.framework.core.restriction.Criteria;
import com.prolog.framework.core.restriction.Order;
import com.prolog.framework.core.restriction.Restriction;
import com.prolog.framework.core.restriction.Restrictions;
import com.prolog.framework.dao.util.PageUtils;
import com.prolog.product.core.framework.entity.UserEntity;
import com.prolog.product.core.framework.util.PlgFxUsrUtils;
import com.prolog.rdc.tms.constant.BussinessConstant;
import com.prolog.rdc.tms.constant.DataDictionaryConstant;
import com.prolog.rdc.tms.constant.SeriaNnumberConstant;
import com.prolog.rdc.tms.constant.StatusConstant;
import com.prolog.rdc.tms.dao.mapper.*;
import com.prolog.rdc.tms.model.dto.*;
import com.prolog.rdc.tms.model.dto.basicConfigure.ShipbillFitBusinessFlowDTO;
import com.prolog.rdc.tms.model.dto.basicConfigure.SignconfigPopDTO;
import com.prolog.rdc.tms.model.dto.basicData.ApprovalLogDTO;
import com.prolog.rdc.tms.model.dto.basicData.ApprovalNodeSelDTO;
import com.prolog.rdc.tms.model.dto.basicData.CustomerCarrierDTO;
import com.prolog.rdc.tms.model.dto.message.SendMessageDTO;
import com.prolog.rdc.tms.model.entity.*;
import com.prolog.rdc.tms.model.enums.MessageOrderTypeEnum;
import com.prolog.rdc.tms.model.enums.MessageTypeEnum;
import com.prolog.rdc.tms.model.vo.*;
import com.prolog.rdc.tms.model.vo.basicConfigure.ApprovalBusinessNodeVO;
import com.prolog.rdc.tms.model.vo.basicConfigure.ApprovalOpenVO;
import com.prolog.rdc.tms.model.vo.basicConfigure.BusinessFlowShipbillVO;
import com.prolog.rdc.tms.model.vo.basicConfigure.SignconfigPopVO;
import com.prolog.rdc.tms.model.vo.basicData.CustomerCarrierVO;
import com.prolog.rdc.tms.model.vo.fleetManagement.VehicleCheckVO;
import com.prolog.rdc.tms.rmi.feign.MaindataFeign;
import com.prolog.rdc.tms.service.LoadingBillService;
import com.prolog.rdc.tms.service.ShipbillNodeTrackingService;
import com.prolog.rdc.tms.service.ShipbillOperateLogService;
import com.prolog.rdc.tms.service.TrailerService;
import com.prolog.rdc.tms.util.BusinessFlowUtil;
import com.prolog.rdc.tms.util.ConvertorUtil;
import com.prolog.rdc.tms.util.MessageUtil;
import com.prolog.rdc.tms.util.PublicMethods;
import org.apache.commons.lang.ArrayUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

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

/**
 * 已托运实现层
 * <p>
 * Company: 湖北普罗格科技股份有限公司
 *
 * @author zhangsj
 * @since 2022/4/18 12:43
 */
@Service
public class TrailerServiceImpl implements TrailerService {

	@Autowired
	private TmsLoadingBillHeaderMapper tmsLoadingBillHeaderMapper;

	@Autowired
	private TmsLoadingBillDetailMapper tmsLoadingBillDetailMapper;

	@Autowired
	private MaindataFeign maindataTmsResource;

	@Autowired
	private TmsShipbillHeaderMapper tmsShipbillHeaderMapper;

	@Autowired
	private ShipbillOperateLogService shipbillOperateLogService;

	@Autowired
	private ShipbillNodeTrackingService shipbillNodeTrackingService;

	@Autowired
	private TmsShipbillDetailMapper tmsShipbillDetailMapper;

	@Autowired
	private TmsShipbillPackageMapper tmsShipbillPackageMapper;

	@Autowired
	private TmsShipbillNodeTrackingMapper tmsShipbillNodeTrackingMapper;

	@Autowired
	private BusinessFlowUtil businessFlowUtil;

	@Autowired
	private TmsShipbillTransportLogMapper tmsShipbillTransportLogMapper;

	@Autowired
	private LoadingBillService loadingBillService;

	@Autowired
	private ConvertorUtil convertorUtil;

	/**
	 * 已托运分页查询
	 *
	 * @param trailerPageVO
	 * @return
	 */
	@SuppressWarnings("resource")
	@Override
	public Page<TrailerPageDTO> trailerPageData(TrailerPageVO trailerPageVO) {
		ToolKits.isParamNull(trailerPageVO, "汇总查询请求不为空");
		ToolKits.isParamNull(trailerPageVO.getPageNum(), "当前页码不为空");
		ToolKits.isParamNull(trailerPageVO.getPageSize(), "每页条数不为空");

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

		List<SysRefdatadModel> dicData = convertorUtil.getDictionary(new String[] {
				DataDictionaryConstant.LOADING_BILL_STATUS, // 已派车状态
				DataDictionaryConstant.CARRIER_SYS_FLAG, // 承运商系统标志
				DataDictionaryConstant.VEHICLE_TYPE_CATEGORY // 车辆类别
		});

		// 添加查询条件
		Criteria criteria = Criteria.forClass(TmsLoadingBillHeaderModel.class);
		Restriction r1 = ToolKits.isEmpty(trailerPageVO.getLoadingBillNo()) ? null : Restrictions.like("loadingBillNo", "%" + trailerPageVO.getLoadingBillNo() + "%");
		Restriction r2 = ToolKits.isEmpty(trailerPageVO.getStatus()) ? null : Restrictions.eq("status", trailerPageVO.getStatus());
		Restriction r3 = ToolKits.isEmpty(trailerPageVO.getCreateStartTime()) ? null : Restrictions.ge("createtime", trailerPageVO.getCreateStartTime());
		Restriction r4 = ToolKits.isEmpty(trailerPageVO.getCreateEndTime()) ? null : Restrictions.le("createtime", trailerPageVO.getCreateEndTime());
		Restriction r5 = Restrictions.eq("carrierType", DataDictionaryConstant.LINE_CARRIER_TYPE_CYF);
		Restriction r6 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
		Restriction r7 = null;
		if (user.getUserType().equals(BussinessConstant.USER_TYPE_ZY)) {
			r7 = Restrictions.eq("scheduleType", DataDictionaryConstant.SCHEDULE_TYPE_ZY);

		} else if (user.getUserType().equals(BussinessConstant.USER_TYPE_CYS)) {
			r7 = Restrictions.eq("scheduleType", DataDictionaryConstant.SCHEDULE_TYPE_CYS);
		}

		criteria.setRestriction(Restrictions.and(r1, r2, r3, r4, r5, r6, r7));
		criteria.setOrder(Order.newInstance().desc(new String[] { "updatetime" }));

		PageUtils.startPage(trailerPageVO.getPageNum(), trailerPageVO.getPageSize());
		List<TmsLoadingBillHeaderModel> tmsLoadingBillHeaderModels = tmsLoadingBillHeaderMapper.findByCriteria(criteria);

		List<TrailerPageDTO> trailerPageDTOS = Lists.newArrayList();
		for (TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel : tmsLoadingBillHeaderModels) {
			TrailerPageDTO dto = new TrailerPageDTO();
			BeanUtils.copyProperties(tmsLoadingBillHeaderModel, dto);

			dto.setStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.LOADING_BILL_STATUS, String.valueOf(dto.getStatus())));
			dto.setVehicleTypeCategoryName(ConvertorUtil.getName(dicData, DataDictionaryConstant.VEHICLE_TYPE_CATEGORY, dto.getVehicleTypeCategory()));
			dto.setCarrierSysFlagName(ConvertorUtil.getName(dicData, DataDictionaryConstant.CARRIER_SYS_FLAG, dto.getCarrierSysFlag()));

			trailerPageDTOS.add(dto);
		}

		// 分页重组
		Page<TrailerPageDTO> page = PageUtils.getPage(trailerPageDTOS);
		if (tmsLoadingBillHeaderModels instanceof com.github.pagehelper.Page) {
			com.github.pagehelper.Page<TmsLoadingBillHeaderModel> p0 = (com.github.pagehelper.Page<TmsLoadingBillHeaderModel>) tmsLoadingBillHeaderModels;
			page.setPageCount(p0.getPages());
			page.setPageNum(p0.getPageNum());
			page.setPageSize(p0.getPageSize());
			page.setTotalCount(p0.getTotal());
			page.setStartRow(p0.getStartRow());
			page.setEndRow(p0.getEndRow());
		}
		return page;
	}

	/**
	 * 已托运高级查询
	 *
	 * @param advancedQueryVO
	 * @return
	 */
	@SuppressWarnings("resource")
	public Page<TrailerPageDTO> pageAdvanced(TrailerAdsQueryVO advancedQueryVO) {
		ToolKits.isParamNull(advancedQueryVO, "汇总查询请求不为空");
		ToolKits.isParamNull(advancedQueryVO.getPageNum(), "当前页码不为空");
		ToolKits.isParamNull(advancedQueryVO.getPageSize(), "每页条数不为空");

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

		List<SysRefdatadModel> dicData = convertorUtil.getDictionary(new String[] {
				DataDictionaryConstant.LOADING_BILL_STATUS, // 已派车状态
				DataDictionaryConstant.VEHICLE_TYPE_CATEGORY // 车辆类别
		});

		// 添加查询条件
		advancedQueryVO.setEnterpriseId(user.getEnterpriseId());
		advancedQueryVO.setCarrierType(DataDictionaryConstant.LINE_CARRIER_TYPE_CYF);
		if (user.getUserType().equals(BussinessConstant.USER_TYPE_ZY)) {
			advancedQueryVO.setScheduleType(DataDictionaryConstant.SCHEDULE_TYPE_ZY);
		} else {
			advancedQueryVO.setScheduleType(DataDictionaryConstant.SCHEDULE_TYPE_CYS);
		}

		// 获取高级查询配置
		String conditions = null;
		RestMessage<String> restMessageAdvancedCfg = maindataTmsResource.getQueryConfiguration(DataDictionaryConstant.BIZ_TYPE_TRAILER);
		if (!restMessageAdvancedCfg.isSuccess()) {
			// throw new RuntimeException("订单类型翻译失败!");
		} else {
			conditions = restMessageAdvancedCfg.getData();
		}
		advancedQueryVO.setSql(conditions);

		PageUtils.startPage(advancedQueryVO.getPageNum(), advancedQueryVO.getPageSize());
		List<TrailerPageDTO> tmsLoadingBillHeaderModels = tmsLoadingBillHeaderMapper.trailerCarAdvanceQuery(advancedQueryVO);

		List<TrailerPageDTO> trailerPageDTOS = Lists.newArrayList();
		for (TrailerPageDTO tmsLoadingBillHeaderModel : tmsLoadingBillHeaderModels) {
			TrailerPageDTO dto = new TrailerPageDTO();
			BeanUtils.copyProperties(tmsLoadingBillHeaderModel, dto);
			dto.setStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.LOADING_BILL_STATUS, String.valueOf(dto.getStatus())));
			dto.setVehicleTypeCategoryName(ConvertorUtil.getName(dicData, DataDictionaryConstant.VEHICLE_TYPE_CATEGORY, dto.getVehicleTypeCategory()));
			trailerPageDTOS.add(dto);
		}

		// 分页重组
		Page<TrailerPageDTO> page = PageUtils.getPage(trailerPageDTOS);
		if (tmsLoadingBillHeaderModels instanceof com.github.pagehelper.Page) {
			com.github.pagehelper.Page<TrailerPageDTO> p0 = (com.github.pagehelper.Page<TrailerPageDTO>) tmsLoadingBillHeaderModels;
			page.setPageCount(p0.getPages());
			page.setPageNum(p0.getPageNum());
			page.setPageSize(p0.getPageSize());
			page.setTotalCount(p0.getTotal());
			page.setStartRow(p0.getStartRow());
			page.setEndRow(p0.getEndRow());
		}
		return page;
	}

	/**
	 * 已托运审核
	 *
	 * @param ids
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void trailerAuditData(List<String> ids) {
		ToolKits.isParamNull(ids, "托运单ID不为空");

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

		Date date = DateUtil.date();

		autoTrailerAuditData(ids, user, date);
	}

	/**
	 * 自动已托运审核
	 *
	 * @param ids
	 */
	public void autoTrailerAuditData(List<String> ids, UserEntity user, Date date) {
		List<TmsLoadingBillHeaderModel> tmsLoadingBillHeaderModels = tmsLoadingBillHeaderMapper.findByIds(TmsLoadingBillHeaderModel.class, ids.toArray(), null);

		// 判断托运单是否已审核
		String str = tmsLoadingBillHeaderModels.stream().filter(o -> o.getStatus().intValue() != DataDictionaryConstant.LOADING_BILL_STATUS_WSH.intValue()).map(TmsLoadingBillHeaderModel::getLoadingBillNo).collect(Collectors.joining(","));

		if (ToolKits.isNotEmpty(str)) {
			throw new RuntimeException("托运单[" + str + "]不是待审核状态,不能调度审核!");
		}
		List<String> receiveObjs = Lists.newArrayList();
		for (TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel : tmsLoadingBillHeaderModels) {

			// 更改运单状态
			Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
			Restriction r1 = Restrictions.eq("loadingBillId", tmsLoadingBillHeaderModel.getLoadingBillId());
			Restriction r2 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
			criteria.setRestriction(Restrictions.and(r1, r2));
			List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteria);

			// 记录运单日志
			int shipperTypeCnt = 0;
			int consigneeType = 0;
			Boolean matched = false;
			// 匹配调度审核审批流程
			for (TmsLoadingBillDetailModel loadingBillDetailModel : tmsLoadingBillDetailModels) {
				TmsShipbillHeaderModel tmsShipbillHeaderModel = tmsShipbillHeaderMapper.findById(loadingBillDetailModel.getShipbillId(), TmsShipbillHeaderModel.class);
				Assert.isTrue(null != tmsShipbillHeaderModel, "运单【" + tmsShipbillHeaderModel.getShipbillNo() + "】运单不存在,审核失败");
				if (user.getUserType().equals(BussinessConstant.USER_TYPE_ZY)) {
					matched = approvalOpen(tmsLoadingBillHeaderModel, tmsShipbillHeaderModel, DataDictionaryConstant.APPROVAL_FLOW_TYPE_DISPATCH, user);
				} else {
					matched = approvalOpen(tmsLoadingBillHeaderModel, tmsShipbillHeaderModel, DataDictionaryConstant.APPROVAL_FLOW_TYPE_DISPATCH_CARRIER, user);
				}
				if (matched) {
					break;
				}
			}
			if (matched) {
				tmsLoadingBillHeaderModel.setStatus(DataDictionaryConstant.LOADING_BILL_STATUS_DIS_APPROVAL);
			} else {
				tmsLoadingBillHeaderModel.setStatus(DataDictionaryConstant.LOADING_BILL_STATUS_YSH);
			}

			for (TmsLoadingBillDetailModel detailModel : tmsLoadingBillDetailModels) {
				if (detailModel.getShipperType() == DataDictionaryConstant.SHIPPER_TYPE_CK) {
					shipperTypeCnt++;
				}
				if (detailModel.getConsigneeType() == DataDictionaryConstant.CONSIGNEE_TYPE_CK) {
					consigneeType++;
				}
				ShipbillNodeTrackingSaveVO shipbillNodeTrackingSaveVO = new ShipbillNodeTrackingSaveVO();
				ShipbillOperateLogSaveVO shipbillOperateLogSaveVO = new ShipbillOperateLogSaveVO();
				Map<String, Object> mapUpdateShipbillHeader = Maps.newHashMap();
				Map<String, Object> mapUpdateLoadingDetail = Maps.newHashMap();

				mapUpdateShipbillHeader.put("updateperson", user.getNickname());
				mapUpdateShipbillHeader.put("updatetime", date);
				mapUpdateLoadingDetail.put("updateperson", user.getNickname());
				mapUpdateLoadingDetail.put("updatetime", date);
				if (!matched) {
					if (user.getUserType().equals(BussinessConstant.USER_TYPE_ZY)) {
						if (ToolKits.isNotEmpty(detailModel.getCarrierFlowConfig())) {
							// 自有账号
							int status = DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH_CHECK;

							mapUpdateLoadingDetail.put("status", status);
							mapUpdateShipbillHeader.put("status", status);
							mapUpdateLoadingDetail.put("carrierShipbillStatus", DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_WAIT_RECEIVE);
							mapUpdateShipbillHeader.put("carrierShipbillStatus", DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_WAIT_RECEIVE);

							shipbillNodeTrackingSaveVO.setStatus(status);
							shipbillNodeTrackingSaveVO.setNodeEvent(DataDictionaryConstant.SHIPBILL_NODE_STATUSNAME_TY);
							shipbillOperateLogSaveVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_NODE_STATUSNAME_TY);
							shipbillOperateLogSaveVO.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH);
							shipbillOperateLogSaveVO.setNewStatus(status);

							// 承运商是否开启接单拒绝
							if (!detailModel.getCarrierFlowConfig().contains(DataDictionaryConstant.FLOW_CONFIG_REJECT_RECEIVE)) {
								receiveObjs.add(detailModel.getShipbillId());
							}
						} else {
							// 判定下一步流程
							int status = businessFlowUtil.judgmentNextFlowSts(detailModel.getFlowConfig(), DataDictionaryConstant.FLOW_CONFIG_CHECK);
							mapUpdateLoadingDetail.put("status", status);
							mapUpdateShipbillHeader.put("status", status);
							mapUpdateLoadingDetail.put("carrierShipbillStatus", DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED_CHECK);
							mapUpdateShipbillHeader.put("carrierShipbillStatus", DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED_CHECK);

							shipbillNodeTrackingSaveVO.setStatus(status);
							shipbillNodeTrackingSaveVO.setNodeEvent(DataDictionaryConstant.SHIPBILL_NODE_STATUSNAME_TY);
							shipbillOperateLogSaveVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_NODE_STATUSNAME_TY);
							shipbillOperateLogSaveVO.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH);
							shipbillOperateLogSaveVO.setNewStatus(status);
						}

					} else if (user.getUserType().equals(BussinessConstant.USER_TYPE_CYS)) {
						// 承运商账号
						// 判定下一步流程
						int status = DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED_CHECK;

						mapUpdateLoadingDetail.put("carrierShipbillStatus", status);
						mapUpdateShipbillHeader.put("carrierShipbillStatus", status);

						shipbillNodeTrackingSaveVO.setStatus(status);
						shipbillOperateLogSaveVO.setOldStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED);
						shipbillOperateLogSaveVO.setNewStatus(status);

						shipbillNodeTrackingSaveVO.setNodeEvent(DataDictionaryConstant.CARRIER_SHIPBILL_NODE_STATUSNAME_TY);
						shipbillOperateLogSaveVO.setOperateEvent(DataDictionaryConstant.CARRIER_SHIPBILL_NODE_STATUSNAME_TY);
					}

					// 更新运输记录表的调度审核时间
					Criteria criteriaTransLog = Criteria.forClass(TmsShipbillTransLogModel.class);
					Restriction r3 = Restrictions.eq(TmsShipbillTransLogModel::getShipbillId, detailModel.getShipbillId());
					Restriction r4 = Restrictions.eq(TmsShipbillTransLogModel::getEnterpriseId, user.getEnterpriseId());
					criteriaTransLog.setRestriction(Restrictions.and(r3, r4));

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

				} else {
					if (user.getUserType().equals(BussinessConstant.USER_TYPE_ZY)) {

						mapUpdateLoadingDetail.put("status", DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH_CHECK_APPROVAL);
						mapUpdateShipbillHeader.put("status", DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH_CHECK_APPROVAL);
						mapUpdateLoadingDetail.put("carrierShipbillStatus", DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED_APPROVAL);
						mapUpdateShipbillHeader.put("carrierShipbillStatus", DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED_APPROVAL);

						shipbillNodeTrackingSaveVO.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH_CHECK_APPROVAL);
						shipbillNodeTrackingSaveVO.setNodeEvent(DataDictionaryConstant.SHIPBILL_NODE_STATUSNAME_DIS_APPROVAL);
						shipbillOperateLogSaveVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_NODE_STATUSNAME_DIS_APPROVAL);
						shipbillOperateLogSaveVO.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH);
						shipbillOperateLogSaveVO.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH_CHECK_APPROVAL);
					} else if (user.getUserType().equals(BussinessConstant.USER_TYPE_CYS)) {
						// 承运商账号
						int status = DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED_APPROVAL;
						mapUpdateLoadingDetail.put("carrierShipbillStatus", status);
						mapUpdateShipbillHeader.put("carrierShipbillStatus", status);

						shipbillNodeTrackingSaveVO.setStatus(status);
						shipbillOperateLogSaveVO.setOldStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED);
						shipbillOperateLogSaveVO.setNewStatus(status);

						shipbillNodeTrackingSaveVO.setNodeEvent(DataDictionaryConstant.CARRIER_SHIPBILL_NODE_STATUSNAME_DIS_APPROVAL);
						shipbillOperateLogSaveVO.setOperateEvent(DataDictionaryConstant.CARRIER_SHIPBILL_NODE_STATUSNAME_DIS_APPROVAL);
					}
				}
				// 调度司机
				if (DataDictionaryConstant.LINE_CARRIER_TYPE_SJ.equals(detailModel.getCarrierType())) {
					mapUpdateShipbillHeader.put("vehicleTypeCategory", tmsLoadingBillHeaderModel.getVehicleTypeCategory());
					mapUpdateLoadingDetail.put("vehicleTypeCategory", tmsLoadingBillHeaderModel.getVehicleTypeCategory());
					// 冷藏冷冻恒温的运单
					if (!DataDictionaryConstant.TEMPERATURE_REQUIREMENT_CW.equals(detailModel.getTemperatureRequirement())) {
						mapUpdateShipbillHeader.put("vehicleDeviceId", tmsLoadingBillHeaderModel.getVehicleDeviceId());
						mapUpdateShipbillHeader.put("vehicleDeviceCode", tmsLoadingBillHeaderModel.getVehicleDeviceCode());
						mapUpdateShipbillHeader.put("vehicleDeviceName", tmsLoadingBillHeaderModel.getVehicleDeviceName());
						mapUpdateLoadingDetail.put("vehicleDeviceId", tmsLoadingBillHeaderModel.getVehicleDeviceId());
						mapUpdateLoadingDetail.put("vehicleDeviceCode", tmsLoadingBillHeaderModel.getVehicleDeviceCode());
						mapUpdateLoadingDetail.put("vehicleDeviceName", tmsLoadingBillHeaderModel.getVehicleDeviceName());
					}
				}
				//更新运单计划发货件数
				Criteria shipBillCriteria = Criteria.forClass(TmsShipbillDetailModel.class);
				Restriction shipBillRestriction = Restrictions.eq("shipbillId", detailModel.getShipbillId());
				shipBillCriteria.setRestriction(shipBillRestriction);
				List<TmsShipbillDetailModel> tmsShipbillDetailModelList = tmsShipbillDetailMapper.findByCriteria(shipBillCriteria);
				if (CollectionUtil.isNotEmpty(tmsShipbillDetailModelList)) {
					tmsShipbillDetailModelList.forEach(tmsShipbillDetailModel -> {
						tmsShipbillDetailModel.setPlanDeliveryPcs(tmsShipbillDetailModel.getPcs());
						tmsShipbillDetailModel.setUpdateperson(user.getNickname());
						tmsShipbillDetailModel.setUpdatetime(date);
						tmsShipbillDetailMapper.update(tmsShipbillDetailModel);
					});
				}
				// 更改运单状态
				tmsShipbillHeaderMapper.updateMapById(detailModel.getShipbillId(), mapUpdateShipbillHeader, TmsShipbillHeaderModel.class);
				// 更新托运单明细状态
				tmsLoadingBillDetailMapper.updateMapById(detailModel.getId(), mapUpdateLoadingDetail, TmsLoadingBillDetailModel.class);
				// 新增节点信息
				shipbillNodeTrackingSaveVO.setShipbillId(detailModel.getShipbillId());
				shipbillNodeTrackingSaveVO.setShipbillNo(detailModel.getShipbillNo());
				shipbillNodeTrackingService.addShipbillNodeTrackingData(shipbillNodeTrackingSaveVO);

				// 新增日志信息
				shipbillOperateLogSaveVO.setShipbillId(detailModel.getShipbillId());
				shipbillOperateLogSaveVO.setShipbillNo(detailModel.getShipbillNo());
				shipbillOperateLogSaveVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_NODE_STATUSNAME_PC);
				shipbillOperateLogService.addShipbillOperateLogData(shipbillOperateLogSaveVO);
			}

			// 更改托运单状态
			// 装车单类型
			if (shipperTypeCnt == tmsLoadingBillDetailModels.size()) {
				tmsLoadingBillHeaderModel.setLoadingBillType(DataDictionaryConstant.LOADING_BILL_TYPE_CK);
			} else if (consigneeType == tmsLoadingBillDetailModels.size()) {
				tmsLoadingBillHeaderModel.setLoadingBillType(DataDictionaryConstant.LOADING_BILL_TYPE_RK);
			} else {
				tmsLoadingBillHeaderModel.setLoadingBillType(DataDictionaryConstant.LOADING_BILL_TYPE_QT);
			}
			tmsLoadingBillHeaderModel.setUpdateperson(user.getNickname());
			tmsLoadingBillHeaderModel.setUpdatetime(date);
			tmsLoadingBillHeaderMapper.update(tmsLoadingBillHeaderModel);
			MessageTypeEnum messageTypeEnum = MessageTypeEnum.SELF_DISPATCH_AUDIT;
			if (user.getUserType().equals(BussinessConstant.USER_TYPE_CYS)) {
				messageTypeEnum = MessageTypeEnum.CARRIER_DISPATCH_AUDIT;
			}
			MessageUtil.addMessage(new SendMessageDTO(MessageOrderTypeEnum.LOADING_NO.getCode(), messageTypeEnum.getCode(), Lists.newArrayList(tmsLoadingBillHeaderModel.getLoadingBillId())));
		}
		loadingBillService.updateStationByLoadingBillIdList(ids);
		// 承运商自动接单
		if (ToolKits.isNotEmpty(receiveObjs)) {
			autoReceiveShipbillData(receiveObjs, date, user);
		}
	}

	/**
	 * 已托运运单撤销
	 *
	 * @param ids
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void trailerUndoData(List<String> ids) {
		ToolKits.isParamNull(ids, "托运单ID不为空");

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

		List<TmsLoadingBillHeaderModel> tmsLoadingBillHeaderModels = tmsLoadingBillHeaderMapper.findByIds(TmsLoadingBillHeaderModel.class, ids.toArray(), null);

		String str = tmsLoadingBillHeaderModels.stream().filter(o -> o.getStatus().intValue() > DataDictionaryConstant.LOADING_BILL_STATUS_WSH.intValue()).map(TmsLoadingBillHeaderModel::getLoadingBillNo).collect(Collectors.joining(","));
		if (ToolKits.isNotEmpty(str)) {
			throw new RuntimeException("托运单[" + str + "]不是待审核状态,不能撤销!");
		}

		// 查询明细内容
		Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
		Restriction r1 = Restrictions.in(TmsLoadingBillDetailModel::getLoadingBillId, ids.toArray());
		Restriction r2 = Restrictions.eq(TmsLoadingBillDetailModel::getEnterpriseId, user.getEnterpriseId());
		criteria.setRestriction(Restrictions.and(r1, r2));

		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteria);

		for (TmsLoadingBillDetailModel tmsLoadingBillDetailModel : tmsLoadingBillDetailModels) {

			TmsShipbillHeaderModel tmsShipbillHeaderModel = tmsShipbillHeaderMapper.findById(tmsLoadingBillDetailModel.getShipbillId(), TmsShipbillHeaderModel.class);

			ShipbillOperateLogSaveVO shipbillOperateLogSaveVO = new ShipbillOperateLogSaveVO();
			// 运单状态回退
			Restriction r4 = null;
			if (user.getUserType().equals(BussinessConstant.USER_TYPE_ZY)) {
				Assert.isTrue(tmsShipbillHeaderModel.getStatus().intValue() <= DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH.intValue(), "当前运单已调度不可回退");

				tmsShipbillHeaderModel.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_REVIEW);

				shipbillOperateLogSaveVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_REVOKE_TRAILER);
				shipbillOperateLogSaveVO.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH);
				shipbillOperateLogSaveVO.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_REVIEW);
				r4 = Restrictions.eq("status", DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH);
			} else if (user.getUserType().equals(BussinessConstant.USER_TYPE_CYS)) {
				Assert.isTrue(tmsShipbillHeaderModel.getCarrierShipbillStatus().intValue() <= DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED.intValue(), "当前运单已调度不可回退");

				tmsShipbillHeaderModel.setCarrierShipbillStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_AUDITED);

				shipbillOperateLogSaveVO.setOperateEvent(DataDictionaryConstant.CARRIER_SHIPBILL_STATUSNAME_REVOKE_TRAILER);
				shipbillOperateLogSaveVO.setOldCarrierShipbillStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED);
				shipbillOperateLogSaveVO.setNewCarrierShipbillStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_AUDITED);
				r4 = Restrictions.eq("status", DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED);
			}
			tmsShipbillHeaderModel.setCarrierId(null);
			tmsShipbillHeaderModel.setCarrierCode(null);
			tmsShipbillHeaderModel.setCarrierName(null);
			tmsShipbillHeaderModel.setCarrierType(null);
			tmsShipbillHeaderModel.setCarrierFlowConfig(null);
			tmsShipbillHeaderModel.setUpdatetime(DateUtil.date());
			tmsShipbillHeaderModel.setUpdateperson(user.getNickname());
			tmsShipbillHeaderMapper.update(tmsShipbillHeaderModel);

			// 运单操作日志保存
			shipbillOperateLogSaveVO.setShipbillId(tmsLoadingBillDetailModel.getShipbillId());
			shipbillOperateLogSaveVO.setShipbillNo(tmsLoadingBillDetailModel.getShipbillNo());
			shipbillOperateLogService.addShipbillOperateLogData(shipbillOperateLogSaveVO);

			// 删除调度的节点信息
			Criteria criteriaNode = Criteria.forClass(ShipbillNodeTracking.class);
			Restriction r3 = Restrictions.eq("shipbillId", tmsLoadingBillDetailModel.getShipbillId());
			Restriction r5 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
			criteria.setRestriction(Restrictions.and(r3, r4, r5));
			tmsShipbillNodeTrackingMapper.deleteByCriteria(criteriaNode);
		}

		// 删除明细内容
		criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
		r1 = Restrictions.in("loadingBillId", ids.toArray());
		r2 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
		criteria.setRestriction(Restrictions.and(r1, r2));
		tmsLoadingBillDetailMapper.deleteByCriteria(criteria);

		tmsLoadingBillHeaderMapper.deleteByIds(ids.toArray(), TmsLoadingBillHeaderModel.class);

	}

	/**
	 * 托运单查看
	 *
	 * @param id
	 * @return
	 */
	@Override
	public TrailerViewDTO viewTrailerData(String id) {
		ToolKits.isParamNull(id, "托运单ID不为空");

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

		// 数据字典翻译数据集合
		List<Map<String, Object>> data1 = Lists.newArrayList();
		List<Map<String, Object>> data2 = Lists.newArrayList();
		List<Map<String, Object>> data3 = Lists.newArrayList();
		List<Map<String, Object>> data4 = Lists.newArrayList();
		List<Map<String, Object>> data5 = Lists.newArrayList();
		List<Map<String, Object>> data6 = Lists.newArrayList();
		List<Map<String, Object>> data7 = Lists.newArrayList();
		List<Map<String, Object>> data8 = Lists.newArrayList();

		// 承运方类型
		RestMessage<List<Map<String, Object>>> restMessage1 = maindataTmsResource.getDropDownById(DataDictionaryConstant.LINE_CARRIER_TYPE, null, null, null);
		if (!restMessage1.isSuccess()) {
			throw new RuntimeException("承运方类型翻译失败!");
		} else {
			data1 = restMessage1.getData();
		}

		// 订单业务类型
		RestMessage<List<Map<String, Object>>> restMessage2 = maindataTmsResource.getDropDownById(DataDictionaryConstant.ORDER_BUSINESS_TYPE, null, null, null);
		if (!restMessage2.isSuccess()) {
			throw new RuntimeException("订单业务类型翻译失败!");
		} else {
			data2 = restMessage2.getData();
		}
		// 配送方式
		RestMessage<List<Map<String, Object>>> restMessage3 = maindataTmsResource.getDropDownById(DataDictionaryConstant.DELIVERY_METHOD_TYPE, null, null, null);
		if (!restMessage3.isSuccess()) {
			throw new RuntimeException("配送方式翻译失败!");
		} else {
			data3 = restMessage3.getData();
		}
		// 运输类型(运输模式)
		RestMessage<List<Map<String, Object>>> restMessage4 = maindataTmsResource.getDropDownById(DataDictionaryConstant.TRANSPORT_TYPE, null, null, null);
		if (!restMessage4.isSuccess()) {
			throw new RuntimeException("运输类型(运输模式)翻译失败!");
		} else {
			data4 = restMessage4.getData();
		}
		// 温度要求
		RestMessage<List<Map<String, Object>>> restMessage5 = maindataTmsResource.getDropDownById(DataDictionaryConstant.TEMPERATURE_REQUIREMENT, null, null, null);
		if (!restMessage5.isSuccess()) {
			throw new RuntimeException("温度要求翻译失败!");
		} else {
			data5 = restMessage5.getData();
		}
		// 发货方类型
		RestMessage<List<Map<String, Object>>> restMessage6 = maindataTmsResource.getDropDownById(DataDictionaryConstant.SHIPPER_TYPE, null, null, null);
		if (!restMessage6.isSuccess()) {
			throw new RuntimeException("发货方类型翻译失败!");
		} else {
			data6 = restMessage6.getData();
		}
		// 收货方类型
		RestMessage<List<Map<String, Object>>> restMessage7 = maindataTmsResource.getDropDownById(DataDictionaryConstant.CONSIGNEE_TYPE, null, null, null);
		if (!restMessage7.isSuccess()) {
			throw new RuntimeException("收货方类型翻译失败!");
		} else {
			data7 = restMessage7.getData();
		}
		// 订单类型
		RestMessage<List<Map<String, Object>>> restMessage8 = maindataTmsResource.getDropDownById(DataDictionaryConstant.ORDER_TYPE, null, null, null);
		if (!restMessage8.isSuccess()) {
			throw new RuntimeException("订单类型翻译失败!");
		} else {
			data8 = restMessage8.getData();
		}

		TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel = tmsLoadingBillHeaderMapper.findById(id, TmsLoadingBillHeaderModel.class);

		TrailerViewDTO dto = new TrailerViewDTO();
		BeanUtils.copyProperties(tmsLoadingBillHeaderModel, dto);

		// 承运方类型翻译
		dto.setCarrierTypeName(PublicMethods.change(data1, String.valueOf(dto.getCarrierType())));

		// 封装运单明细
		Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
		Restriction r1 = Restrictions.eq("loadingBillId", tmsLoadingBillHeaderModel.getLoadingBillId());
		Restriction r2 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
		criteria.setRestriction(Restrictions.and(r1, r2));
		criteria.setOrder(Order.newInstance().asc(new String[] { "shippingOrder" }));

		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteria);

		// 明细集合
		List<TrailerViewDetailDTO> list = Lists.newArrayList();

		for (TmsLoadingBillDetailModel model : tmsLoadingBillDetailModels) {

			TrailerViewDetailDTO trailerViewDetailDTO = new TrailerViewDetailDTO();
			BeanUtils.copyProperties(model, trailerViewDetailDTO);

			// 收货方位置(经纬度判断)
			if (ToolKits.isNotEmpty(model.getConsigneeLongitude()) && ToolKits.isNotEmpty(model.getConsigneeLatitude())) {
				trailerViewDetailDTO.setConsigneePositioning(StatusConstant.POSITIONING_YDW);
			} else {
				trailerViewDetailDTO.setConsigneePositioning(StatusConstant.POSITIONING_WDW);
			}
			// 发货方位置(经纬度判断)
			if (ToolKits.isNotEmpty(model.getShipperLongitude()) && ToolKits.isNotEmpty(model.getShipperLatitude())) {
				trailerViewDetailDTO.setShipperPositioning(StatusConstant.POSITIONING_YDW);
			} else {
				trailerViewDetailDTO.setShipperPositioning(StatusConstant.POSITIONING_WDW);
			}

			// 类型翻译
			trailerViewDetailDTO.setOrderBusinessTypeName(PublicMethods.change(data2, String.valueOf(trailerViewDetailDTO.getOrderBusinessType())));
			trailerViewDetailDTO.setDeliveryMethodTypeName(PublicMethods.change(data3, String.valueOf(trailerViewDetailDTO.getDeliveryMethodType())));
			trailerViewDetailDTO.setTransportTypeName(PublicMethods.change(data4, String.valueOf(trailerViewDetailDTO.getTransportType())));
			trailerViewDetailDTO.setTemperatureRequirementName(PublicMethods.change(data5, String.valueOf(trailerViewDetailDTO.getTemperatureRequirement())));
			trailerViewDetailDTO.setShipperTypeName(PublicMethods.change(data6, String.valueOf(trailerViewDetailDTO.getShipperType())));
			trailerViewDetailDTO.setConsigneeTypeName(PublicMethods.change(data7, String.valueOf(trailerViewDetailDTO.getConsigneeType())));
			trailerViewDetailDTO.setOrderTypeName(PublicMethods.change(data8, String.valueOf(trailerViewDetailDTO.getOrderType())));

			list.add(trailerViewDetailDTO);
		}

		dto.setTrailerViewDetailDTOS(list);

		return dto;
	}

	/**
	 * 托运单根据单号查看
	 *
	 * @param id
	 * @return
	 */
	@Override
	public TrailerViewByIdDTO viewTrailerByIdData(String id) {
		ToolKits.isParamNull(id, "托运单ID不为空");

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

		// 数据字典翻译数据集合
		List<Map<String, Object>> data1 = Lists.newArrayList();
		List<Map<String, Object>> data2 = Lists.newArrayList();
		List<Map<String, Object>> data3 = Lists.newArrayList();
		List<Map<String, Object>> data4 = Lists.newArrayList();
		List<Map<String, Object>> data5 = Lists.newArrayList();
		List<Map<String, Object>> data6 = Lists.newArrayList();
		List<Map<String, Object>> data7 = Lists.newArrayList();
		List<Map<String, Object>> data8 = Lists.newArrayList();

		// 承运方类型
		RestMessage<List<Map<String, Object>>> restMessage1 = maindataTmsResource.getDropDownById(DataDictionaryConstant.LINE_CARRIER_TYPE, null, null, null);
		if (!restMessage1.isSuccess()) {
			throw new RuntimeException("承运方类型翻译失败!");
		} else {
			data1 = restMessage1.getData();
		}

		// 订单业务类型
		RestMessage<List<Map<String, Object>>> restMessage2 = maindataTmsResource.getDropDownById(DataDictionaryConstant.ORDER_BUSINESS_TYPE, null, null, null);
		if (!restMessage2.isSuccess()) {
			throw new RuntimeException("订单业务类型翻译失败!");
		} else {
			data2 = restMessage2.getData();
		}
		// 配送方式
		RestMessage<List<Map<String, Object>>> restMessage3 = maindataTmsResource.getDropDownById(DataDictionaryConstant.DELIVERY_METHOD_TYPE, null, null, null);
		if (!restMessage3.isSuccess()) {
			throw new RuntimeException("配送方式翻译失败!");
		} else {
			data3 = restMessage3.getData();
		}
		// 运输类型(运输模式)
		RestMessage<List<Map<String, Object>>> restMessage4 = maindataTmsResource.getDropDownById(DataDictionaryConstant.TRANSPORT_TYPE, null, null, null);
		if (!restMessage4.isSuccess()) {
			throw new RuntimeException("运输类型(运输模式)翻译失败!");
		} else {
			data4 = restMessage4.getData();
		}
		// 温度要求
		RestMessage<List<Map<String, Object>>> restMessage5 = maindataTmsResource.getDropDownById(DataDictionaryConstant.TEMPERATURE_REQUIREMENT, null, null, null);
		if (!restMessage5.isSuccess()) {
			throw new RuntimeException("温度要求翻译失败!");
		} else {
			data5 = restMessage5.getData();
		}
		// 发货方类型
		RestMessage<List<Map<String, Object>>> restMessage6 = maindataTmsResource.getDropDownById(DataDictionaryConstant.SHIPPER_TYPE, null, null, null);
		if (!restMessage6.isSuccess()) {
			throw new RuntimeException("发货方类型翻译失败!");
		} else {
			data6 = restMessage6.getData();
		}
		// 收货方类型
		RestMessage<List<Map<String, Object>>> restMessage7 = maindataTmsResource.getDropDownById(DataDictionaryConstant.CONSIGNEE_TYPE, null, null, null);
		if (!restMessage7.isSuccess()) {
			throw new RuntimeException("收货方类型翻译失败!");
		} else {
			data7 = restMessage7.getData();
		}
		// 订单类型
		RestMessage<List<Map<String, Object>>> restMessage8 = maindataTmsResource.getDropDownById(DataDictionaryConstant.ORDER_TYPE, null, null, null);
		if (!restMessage8.isSuccess()) {
			throw new RuntimeException("订单类型翻译失败!");
		} else {
			data8 = restMessage8.getData();
		}

		List<SysRefdatadModel> dicData = convertorUtil.getDictionary(new String[] {
				DataDictionaryConstant.CARRIER_SYS_FLAG // 承运商系统标志
		});

		TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel = tmsLoadingBillHeaderMapper.findById(id, TmsLoadingBillHeaderModel.class);

		TrailerViewByIdDTO dto = new TrailerViewByIdDTO();
		BeanUtils.copyProperties(tmsLoadingBillHeaderModel, dto);

		// 承运方类型翻译
		dto.setCarrierTypeName(PublicMethods.change(data1, String.valueOf(dto.getCarrierType())));
		dto.setCarrierSysFlagName(ConvertorUtil.getName(dicData, DataDictionaryConstant.CARRIER_SYS_FLAG, String.valueOf(tmsLoadingBillHeaderModel.getCarrierSysFlag())));

		// 封装运单明细
		Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
		Restriction r1 = Restrictions.eq("loadingBillId", tmsLoadingBillHeaderModel.getLoadingBillId());
		Restriction r2 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
		criteria.setRestriction(Restrictions.and(r1, r2));
		criteria.setOrder(Order.newInstance().asc(new String[] { "shippingOrder" }));

		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteria);

		// 明细集合
		List<TrailerViewDetailByIdDTO> list = Lists.newArrayList();

		for (TmsLoadingBillDetailModel model : tmsLoadingBillDetailModels) {

			TrailerViewDetailByIdDTO trailerViewDetailByIdDTO = new TrailerViewDetailByIdDTO();
			BeanUtils.copyProperties(model, trailerViewDetailByIdDTO);

			// 收货方位置(经纬度判断)
			if (ToolKits.isNotEmpty(model.getConsigneeLongitude()) && ToolKits.isNotEmpty(model.getConsigneeLatitude())) {
				trailerViewDetailByIdDTO.setConsigneePositioning(StatusConstant.POSITIONING_YDW);
			} else {
				trailerViewDetailByIdDTO.setConsigneePositioning(StatusConstant.POSITIONING_WDW);
			}
			// 发货方位置(经纬度判断)
			if (ToolKits.isNotEmpty(model.getShipperLongitude()) && ToolKits.isNotEmpty(model.getShipperLatitude())) {
				trailerViewDetailByIdDTO.setShipperPositioning(StatusConstant.POSITIONING_YDW);
			} else {
				trailerViewDetailByIdDTO.setShipperPositioning(StatusConstant.POSITIONING_WDW);
			}

			// 类型翻译
			trailerViewDetailByIdDTO.setOrderBusinessTypeName(PublicMethods.change(data2, String.valueOf(trailerViewDetailByIdDTO.getOrderBusinessType())));
			trailerViewDetailByIdDTO.setDeliveryMethodTypeName(PublicMethods.change(data3, String.valueOf(trailerViewDetailByIdDTO.getDeliveryMethodType())));
			trailerViewDetailByIdDTO.setTransportTypeName(PublicMethods.change(data4, String.valueOf(trailerViewDetailByIdDTO.getTransportType())));
			trailerViewDetailByIdDTO.setTemperatureRequirementName(PublicMethods.change(data5, String.valueOf(trailerViewDetailByIdDTO.getTemperatureRequirement())));
			trailerViewDetailByIdDTO.setShipperTypeName(PublicMethods.change(data6, String.valueOf(trailerViewDetailByIdDTO.getShipperType())));
			trailerViewDetailByIdDTO.setConsigneeTypeName(PublicMethods.change(data7, String.valueOf(trailerViewDetailByIdDTO.getConsigneeType())));
			trailerViewDetailByIdDTO.setOrderTypeName(PublicMethods.change(data8, String.valueOf(trailerViewDetailByIdDTO.getOrderType())));

			list.add(trailerViewDetailByIdDTO);
		}

		dto.setTrailerViewDetailByIdDTOS(list);

		return dto;
	}

	/**
	 * 导出所有数据
	 *
	 * @param trailerExportAllVO
	 * @return
	 */
	@Override
	public List<ExportTrailerDTO> exportAllTrailerData(TrailerExportAllVO trailerExportAllVO) {
		ToolKits.isParamNull(trailerExportAllVO, "导出请求不为空");

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

		// 数据字典翻译数据集合
		List<Map<String, Object>> data1 = Lists.newArrayList();

		// 装车单状态
		RestMessage<List<Map<String, Object>>> restMessage1 = maindataTmsResource.getDropDownById(DataDictionaryConstant.LOADING_BILL_STATUS, null, null, null);
		if (!restMessage1.isSuccess()) {
			throw new RuntimeException("已托运状态翻译失败!");
		} else {
			data1 = restMessage1.getData();
		}

		// 添加查询条件
		Criteria criteria = Criteria.forClass(TmsLoadingBillHeaderModel.class);
		Restriction r1 = ToolKits.isEmpty(trailerExportAllVO.getLoadingBillNo()) ? null : Restrictions.like("loadingBillNo", "%" + trailerExportAllVO.getLoadingBillNo() + "%");
		Restriction r2 = ToolKits.isEmpty(trailerExportAllVO.getStatus()) ? null : Restrictions.eq("status", trailerExportAllVO.getStatus());
		Restriction r3 = ToolKits.isEmpty(trailerExportAllVO.getCreateStartTime()) ? null : Restrictions.ge("createtime", trailerExportAllVO.getCreateStartTime());
		Restriction r4 = ToolKits.isEmpty(trailerExportAllVO.getCreateEndTime()) ? null : Restrictions.le("createtime", trailerExportAllVO.getCreateEndTime());
		Restriction r5 = Restrictions.eq("carrierType", DataDictionaryConstant.LINE_CARRIER_TYPE_CYF);
		Restriction r6 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
		Restriction r7 = null;
		if (user.getUserType().equals(BussinessConstant.USER_TYPE_ZY)) {
			r7 = Restrictions.eq("scheduleType", DataDictionaryConstant.SCHEDULE_TYPE_ZY);
		} else if (user.getUserType().equals(BussinessConstant.USER_TYPE_CYS)) {
			r7 = Restrictions.eq("scheduleType", DataDictionaryConstant.SCHEDULE_TYPE_CYS);
		}
		criteria.setRestriction(Restrictions.and(r1, r2, r3, r4, r5, r6, r7));
		criteria.setOrder(Order.newInstance().desc(new String[] { "updatetime" }));

		List<TmsLoadingBillHeaderModel> tmsLoadingBillHeaderModels = tmsLoadingBillHeaderMapper.findByCriteria(criteria);

		List<ExportTrailerDTO> trailerPageDTOS = Lists.newArrayList();
		for (TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel : tmsLoadingBillHeaderModels) {
			ExportTrailerDTO dto = new ExportTrailerDTO();
			BeanUtils.copyProperties(tmsLoadingBillHeaderModel, dto);

			dto.setStatusName(PublicMethods.change(data1, String.valueOf(tmsLoadingBillHeaderModel.getStatus())));

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

	/**
	 * 导出当前页数据
	 *
	 * @param trailerExportPageVO
	 * @return
	 */
	@Override
	public List<ExportTrailerDTO> exportPageTrailerData(TrailerExportPageVO trailerExportPageVO) {
		ToolKits.isParamNull(trailerExportPageVO, "导出请求不为空");
		ToolKits.isParamNull(trailerExportPageVO.getPageNum(), "当前页码不为空");
		ToolKits.isParamNull(trailerExportPageVO.getPageSize(), "每页条数不为空");

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

		// 数据字典翻译数据集合
		List<Map<String, Object>> data1 = Lists.newArrayList();

		// 装车单状态
		RestMessage<List<Map<String, Object>>> restMessage1 = maindataTmsResource.getDropDownById(DataDictionaryConstant.LOADING_BILL_STATUS, null, null, null);
		if (!restMessage1.isSuccess()) {
			throw new RuntimeException("已托运状态翻译失败!");
		} else {
			data1 = restMessage1.getData();
		}

		// 添加查询条件
		Criteria criteria = Criteria.forClass(TmsLoadingBillHeaderModel.class);
		Restriction r1 = ToolKits.isEmpty(trailerExportPageVO.getLoadingBillNo()) ? null : Restrictions.like("loadingBillNo", "%" + trailerExportPageVO.getLoadingBillNo() + "%");
		Restriction r2 = ToolKits.isEmpty(trailerExportPageVO.getStatus()) ? null : Restrictions.eq("status", trailerExportPageVO.getStatus());
		Restriction r3 = ToolKits.isEmpty(trailerExportPageVO.getCreateStartTime()) ? null : Restrictions.ge("createtime", trailerExportPageVO.getCreateStartTime());
		Restriction r4 = ToolKits.isEmpty(trailerExportPageVO.getCreateEndTime()) ? null : Restrictions.le("createtime", trailerExportPageVO.getCreateEndTime());
		Restriction r5 = Restrictions.eq("carrierType", DataDictionaryConstant.LINE_CARRIER_TYPE_CYF);
		Restriction r6 = Restrictions.eq("enterpriseId", user.getEnterpriseId());

		Restriction r7 = null;
		if (user.getUserType().equals(BussinessConstant.USER_TYPE_ZY)) {
			r7 = Restrictions.eq("scheduleType", DataDictionaryConstant.SCHEDULE_TYPE_ZY);
		} else if (user.getUserType().equals(BussinessConstant.USER_TYPE_CYS)) {
			r7 = Restrictions.eq("scheduleType", DataDictionaryConstant.SCHEDULE_TYPE_CYS);
		}

		criteria.setRestriction(Restrictions.and(r1, r2, r3, r4, r5, r6, r7));
		criteria.setOrder(Order.newInstance().desc(new String[] { "updatetime" }));

		PageUtils.startPage(trailerExportPageVO.getPageNum(), trailerExportPageVO.getPageSize());
		List<TmsLoadingBillHeaderModel> tmsLoadingBillHeaderModels = tmsLoadingBillHeaderMapper.findByCriteria(criteria);

		List<ExportTrailerDTO> exportTrailerDTOS = Lists.newArrayList();
		for (TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel : tmsLoadingBillHeaderModels) {
			ExportTrailerDTO dto = new ExportTrailerDTO();
			BeanUtils.copyProperties(tmsLoadingBillHeaderModel, dto);

			dto.setStatusName(PublicMethods.change(data1, String.valueOf(tmsLoadingBillHeaderModel.getStatus())));

			exportTrailerDTOS.add(dto);
		}

		return exportTrailerDTOS;
	}

	/**
	 * 导出选中数据
	 *
	 * @param ids
	 * @return
	 */
	@Override
	public List<ExportTrailerDTO> exportChooseTrailerData(List<String> ids) {
		ToolKits.isParamNull(ids, "导出请求不为空");

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

		// 数据字典翻译数据集合
		List<Map<String, Object>> data1 = Lists.newArrayList();

		// 装车单状态
		RestMessage<List<Map<String, Object>>> restMessage1 = maindataTmsResource.getDropDownById(DataDictionaryConstant.LOADING_BILL_STATUS, null, null, null);
		if (!restMessage1.isSuccess()) {
			throw new RuntimeException("已托运状态翻译失败!");
		} else {
			data1 = restMessage1.getData();
		}

		// 添加查询条件
		Criteria criteria = Criteria.forClass(TmsLoadingBillHeaderModel.class);
		Restriction r1 = Restrictions.in("loadingBillNo", ids.toArray());
		Restriction r2 = Restrictions.eq("carrierType", DataDictionaryConstant.LINE_CARRIER_TYPE_CYF);
		Restriction r3 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
		criteria.setRestriction(Restrictions.and(r1, r2, r3));
		criteria.setOrder(Order.newInstance().desc(new String[] { "updatetime" }));

		List<TmsLoadingBillHeaderModel> tmsLoadingBillHeaderModels = tmsLoadingBillHeaderMapper.findByCriteria(criteria);

		List<ExportTrailerDTO> exportTrailerDTOS = Lists.newArrayList();
		for (TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel : tmsLoadingBillHeaderModels) {
			ExportTrailerDTO dto = new ExportTrailerDTO();
			BeanUtils.copyProperties(tmsLoadingBillHeaderModel, dto);

			dto.setStatusName(PublicMethods.change(data1, String.valueOf(tmsLoadingBillHeaderModel.getStatus())));

			exportTrailerDTOS.add(dto);
		}

		return exportTrailerDTOS;
	}

	/**
	 * 打印托车单
	 *
	 * @param id
	 * @return
	 */
	@Override
	public Map<String, Object> printTrailerData(String id) {
		ToolKits.isParamNull(id, "托运单ID不为空");

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

		TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel = tmsLoadingBillHeaderMapper.findById(id, TmsLoadingBillHeaderModel.class);

		TrailerPrintHeadDTO trailerPrintHeadDTO = new TrailerPrintHeadDTO();
		BeanUtils.copyProperties(tmsLoadingBillHeaderModel, trailerPrintHeadDTO);

		// 表格数据集
		List<TrailerPrintTableDTO> trailerPrintTableDTOS = Lists.newArrayList();

		Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
		Restriction r1 = Restrictions.eq("loadingBillId", id);
		Restriction r2 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
		criteria.setRestriction(Restrictions.and(r1, r2));
		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteria);

		for (TmsLoadingBillDetailModel tmsLoadingBillDetailModel : tmsLoadingBillDetailModels) {
			TrailerPrintTableDTO dto = new TrailerPrintTableDTO();
			BeanUtils.copyProperties(tmsLoadingBillDetailModel, dto);

			trailerPrintTableDTOS.add(dto);
		}

		// TODO print

		return null;
	}

	/**
	 * 已托运配载运单查询
	 *
	 * @param trailerPageDetailVO
	 * @return
	 */
	@SuppressWarnings("resource")
	@Override
	public Page<TrailerPageDetailDTO> pageDetailTrailerData(TrailerPageDetailVO trailerPageDetailVO) {
		ToolKits.isParamNull(trailerPageDetailVO, "明细查询请求不为空");
		ToolKits.isParamNull(trailerPageDetailVO.getPageNum(), "当前页码不为空");
		ToolKits.isParamNull(trailerPageDetailVO.getPageSize(), "每页条数不为空");
		ToolKits.isParamNull(trailerPageDetailVO.getLoadingBillId(), "托运单ID不为空");

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

		// 数据字典翻译数据集合
		List<Map<String, Object>> data1 = Lists.newArrayList();
		List<Map<String, Object>> data2 = Lists.newArrayList();
		List<Map<String, Object>> data3 = Lists.newArrayList();
		List<Map<String, Object>> data4 = Lists.newArrayList();
		List<Map<String, Object>> data5 = Lists.newArrayList();
		List<Map<String, Object>> data6 = Lists.newArrayList();
		List<Map<String, Object>> data7 = Lists.newArrayList();
		List<SignconfigPopDTO> data8 = Lists.newArrayList();

		// 订单类型
		RestMessage<List<Map<String, Object>>> restMessage1 = maindataTmsResource.getDropDownById(DataDictionaryConstant.ORDER_TYPE, null, null, null);
		if (!restMessage1.isSuccess()) {
			throw new RuntimeException("订单类型翻译失败!");
		} else {
			data1 = restMessage1.getData();
		}
		// 订单业务类型
		RestMessage<List<Map<String, Object>>> restMessage2 = maindataTmsResource.getDropDownById(DataDictionaryConstant.ORDER_BUSINESS_TYPE, null, null, null);
		if (!restMessage2.isSuccess()) {
			throw new RuntimeException("订单业务类型翻译失败!");
		} else {
			data2 = restMessage2.getData();
		}
		// 配送方式
		RestMessage<List<Map<String, Object>>> restMessage3 = maindataTmsResource.getDropDownById(DataDictionaryConstant.DELIVERY_METHOD_TYPE, null, null, null);
		if (!restMessage3.isSuccess()) {
			throw new RuntimeException("配送方式翻译失败!");
		} else {
			data3 = restMessage3.getData();
		}
		// 运输类型(运输模式)
		RestMessage<List<Map<String, Object>>> restMessage4 = maindataTmsResource.getDropDownById(DataDictionaryConstant.TRANSPORT_TYPE, null, null, null);
		if (!restMessage4.isSuccess()) {
			throw new RuntimeException("运输类型(运输模式)翻译失败!");
		} else {
			data4 = restMessage4.getData();
		}
		// 温度要求
		RestMessage<List<Map<String, Object>>> restMessage5 = maindataTmsResource.getDropDownById(DataDictionaryConstant.TEMPERATURE_REQUIREMENT, null, null, null);
		if (!restMessage5.isSuccess()) {
			throw new RuntimeException("温度要求翻译失败!");
		} else {
			data5 = restMessage5.getData();
		}
		// 发货方类型
		RestMessage<List<Map<String, Object>>> restMessage6 = maindataTmsResource.getDropDownById(DataDictionaryConstant.SHIPPER_TYPE, null, null, null);
		if (!restMessage6.isSuccess()) {
			throw new RuntimeException("发货方类型翻译失败!");
		} else {
			data6 = restMessage6.getData();
		}
		// 收货方类型
		RestMessage<List<Map<String, Object>>> restMessage7 = maindataTmsResource.getDropDownById(DataDictionaryConstant.CONSIGNEE_TYPE, null, null, null);
		if (!restMessage7.isSuccess()) {
			throw new RuntimeException("收货方类型翻译失败!");
		} else {
			data7 = restMessage7.getData();
		}
		// 标记配置
		SignconfigPopVO signconfigPopVO = new SignconfigPopVO();
		RestMessage<List<SignconfigPopDTO>> restMessage8 = maindataTmsResource.getSignConfig(signconfigPopVO);
		if (!restMessage8.isSuccess()) {
			throw new RuntimeException("标记配置查询失败!");
		} else {
			data8 = restMessage8.getData();
		}

		// 封装运单明细
		Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
		Restriction r1 = Restrictions.eq("loadingBillId", trailerPageDetailVO.getLoadingBillId());
		Restriction r2 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
		criteria.setRestriction(Restrictions.and(r1, r2));
		criteria.setOrder(Order.newInstance().asc(new String[] { "shippingOrder" }));

		PageUtils.startPage(trailerPageDetailVO.getPageNum(), trailerPageDetailVO.getPageSize());
		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteria);

		// 明细集合
		List<TrailerPageDetailDTO> list = Lists.newArrayList();

		for (TmsLoadingBillDetailModel model : tmsLoadingBillDetailModels) {

			TrailerPageDetailDTO trailerPageDetailDTO = new TrailerPageDetailDTO();
			BeanUtils.copyProperties(model, trailerPageDetailDTO);

			// 收货方位置(经纬度判断)
			if (ToolKits.isNotEmpty(model.getConsigneeLongitude()) && ToolKits.isNotEmpty(model.getConsigneeLatitude())) {
				trailerPageDetailDTO.setConsigneePositioning(StatusConstant.POSITIONING_YDW);
			} else {
				trailerPageDetailDTO.setConsigneePositioning(StatusConstant.POSITIONING_WDW);
			}
			// 发货方位置(经纬度判断)
			if (ToolKits.isNotEmpty(model.getShipperLongitude()) && ToolKits.isNotEmpty(model.getShipperLatitude())) {
				trailerPageDetailDTO.setShipperPositioning(StatusConstant.POSITIONING_YDW);
			} else {
				trailerPageDetailDTO.setShipperPositioning(StatusConstant.POSITIONING_WDW);
			}

			StringBuffer consigneeProvinceCityDistrict = new StringBuffer();
			// 目的地
			consigneeProvinceCityDistrict.append(model.getConsigneeProvinceName());
			consigneeProvinceCityDistrict.append(model.getConsigneeCityName());
			consigneeProvinceCityDistrict.append(model.getConsigneeDistrictName());
			trailerPageDetailDTO.setConsigneeProvinceCityDistrict(consigneeProvinceCityDistrict.toString());
			// 始发地
			StringBuffer shipperProvinceCityDistrict = new StringBuffer();
			shipperProvinceCityDistrict.append(model.getShipperProvinceName());
			shipperProvinceCityDistrict.append(model.getShipperCityName());
			shipperProvinceCityDistrict.append(model.getShipperDistrictName());
			trailerPageDetailDTO.setShipperProvinceCityDistrict(shipperProvinceCityDistrict.toString());

			// 类型翻译
			trailerPageDetailDTO.setOrderTypeName(PublicMethods.change(data1, String.valueOf(trailerPageDetailDTO.getOrderType())));
			trailerPageDetailDTO.setOrderBusinessTypeName(PublicMethods.change(data2, String.valueOf(trailerPageDetailDTO.getOrderBusinessType())));
			trailerPageDetailDTO.setDeliveryMethodTypeName(PublicMethods.change(data3, String.valueOf(trailerPageDetailDTO.getDeliveryMethodType())));
			trailerPageDetailDTO.setTransportTypeName(PublicMethods.change(data4, String.valueOf(trailerPageDetailDTO.getTransportType())));
			trailerPageDetailDTO.setTemperatureRequirementName(PublicMethods.change(data5, String.valueOf(trailerPageDetailDTO.getTemperatureRequirement())));
			trailerPageDetailDTO.setShipperTypeName(PublicMethods.change(data6, String.valueOf(trailerPageDetailDTO.getShipperType())));
			trailerPageDetailDTO.setConsigneeTypeName(PublicMethods.change(data7, String.valueOf(trailerPageDetailDTO.getConsigneeType())));

			// 获取背景颜色和字体颜色
			Signconfig: for (SignconfigPopDTO signconfigPopDTO : data8) {
				// 标记类型匹配
				switch (signconfigPopDTO.getType()) {
				case DataDictionaryConstant.SIGNCONFIG_TYPE_DDLX: // 订单类型
					if (ToolKits.isNotEmpty(signconfigPopDTO.getMatching())) {
						if (ToolKits.isEmpty(trailerPageDetailDTO.getOrderTypeName())) {
							break;
						}
						// 判断是否匹配
						if (PublicMethods.compare(signconfigPopDTO.getMatching(), ToolKits.isNotEmpty(signconfigPopDTO.getStoredValue()) ? signconfigPopDTO.getStoredValue() : "", ToolKits.isNotEmpty(trailerPageDetailDTO.getOrderTypeName()) ? trailerPageDetailDTO.getOrderTypeName() : "")) {
							trailerPageDetailDTO.setBackground(ToolKits.isEmpty(signconfigPopDTO.getBackground()) ? "" : signconfigPopDTO.getBackground());
							trailerPageDetailDTO.setColor(ToolKits.isEmpty(signconfigPopDTO.getColor()) ? "" : signconfigPopDTO.getColor());

							trailerPageDetailDTO.setSignConfigId(signconfigPopDTO.getId());

							// 匹配上结束循环
							break Signconfig;
						}
					}
					break;
				case DataDictionaryConstant.SIGNCONFIG_TYPE_YWLX: // 业务类型
					if (ToolKits.isNotEmpty(signconfigPopDTO.getMatching())) {
						if (PublicMethods.compare(signconfigPopDTO.getMatching(), ToolKits.isNotEmpty(signconfigPopDTO.getStoredValue()) ? signconfigPopDTO.getStoredValue() : "", ToolKits.isNotEmpty(trailerPageDetailDTO.getOrderBusinessTypeName()) ? trailerPageDetailDTO.getOrderBusinessTypeName() : "")) {
							trailerPageDetailDTO.setBackground(ToolKits.isEmpty(signconfigPopDTO.getBackground()) ? "" : signconfigPopDTO.getBackground());
							trailerPageDetailDTO.setColor(ToolKits.isEmpty(signconfigPopDTO.getColor()) ? "" : signconfigPopDTO.getColor());

							trailerPageDetailDTO.setSignConfigId(signconfigPopDTO.getId());

							break Signconfig;
						}
					}
					break;
				case DataDictionaryConstant.SIGNCONFIG_TYPE_WDYQ: // 温度要求
					if (ToolKits.isNotEmpty(signconfigPopDTO.getMatching())) {
						if (PublicMethods.compare(signconfigPopDTO.getMatching(), ToolKits.isNotEmpty(signconfigPopDTO.getStoredValue()) ? signconfigPopDTO.getStoredValue() : "", ToolKits.isNotEmpty(trailerPageDetailDTO.getTemperatureRequirementName()) ? trailerPageDetailDTO.getTemperatureRequirementName() : "")) {
							trailerPageDetailDTO.setBackground(ToolKits.isEmpty(signconfigPopDTO.getBackground()) ? "" : signconfigPopDTO.getBackground());
							trailerPageDetailDTO.setColor(ToolKits.isEmpty(signconfigPopDTO.getColor()) ? "" : signconfigPopDTO.getColor());

							trailerPageDetailDTO.setSignConfigId(signconfigPopDTO.getId());

							break Signconfig;
						}
					}
					break;
				case DataDictionaryConstant.SIGNCONFIG_TYPE_PSFS: // 配送方式
					if (ToolKits.isNotEmpty(signconfigPopDTO.getMatching())) {
						if (PublicMethods.compare(signconfigPopDTO.getMatching(), ToolKits.isNotEmpty(signconfigPopDTO.getStoredValue()) ? signconfigPopDTO.getStoredValue() : "", ToolKits.isNotEmpty(trailerPageDetailDTO.getDeliveryMethodTypeName()) ? trailerPageDetailDTO.getDeliveryMethodTypeName() : "")) {
							trailerPageDetailDTO.setBackground(ToolKits.isEmpty(signconfigPopDTO.getBackground()) ? "" : signconfigPopDTO.getBackground());
							trailerPageDetailDTO.setColor(ToolKits.isEmpty(signconfigPopDTO.getColor()) ? "" : signconfigPopDTO.getColor());

							trailerPageDetailDTO.setSignConfigId(signconfigPopDTO.getId());

							break Signconfig;
						}
					}
					break;
				case DataDictionaryConstant.SIGNCONFIG_TYPE_DDBZ: // 订单备注
					if (ToolKits.isNotEmpty(signconfigPopDTO.getMatching())) {
						if (ToolKits.isEmpty(model.getMemo())) {
							break;
						}
						if (PublicMethods.compare(signconfigPopDTO.getMatching(), ToolKits.isNotEmpty(signconfigPopDTO.getStoredValue()) ? signconfigPopDTO.getStoredValue() : "", ToolKits.isNotEmpty(model.getMemo()) ? model.getMemo() : "")) {
							trailerPageDetailDTO.setBackground(ToolKits.isEmpty(signconfigPopDTO.getBackground()) ? "" : signconfigPopDTO.getBackground());
							trailerPageDetailDTO.setColor(ToolKits.isEmpty(signconfigPopDTO.getColor()) ? "" : signconfigPopDTO.getColor());

							trailerPageDetailDTO.setSignConfigId(signconfigPopDTO.getId());

							break Signconfig;
						}
					}
					break;
				}
			}

			list.add(trailerPageDetailDTO);
		}

		// 分页重组
		Page<TrailerPageDetailDTO> page = PageUtils.getPage(list);
		if (tmsLoadingBillDetailModels instanceof com.github.pagehelper.Page) {
			com.github.pagehelper.Page<TmsLoadingBillDetailModel> p0 = (com.github.pagehelper.Page<TmsLoadingBillDetailModel>) tmsLoadingBillDetailModels;
			page.setPageCount(p0.getPages());
			page.setPageNum(p0.getPageNum());
			page.setPageSize(p0.getPageSize());
			page.setTotalCount(p0.getTotal());
			page.setStartRow(p0.getStartRow());
			page.setEndRow(p0.getEndRow());
		}
		return page;
	}

	/**
	 * 已托运配载运单添加
	 *
	 * @param trailerAddDetailVO
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public List<ShipbillHeaderPageDTO> addDetailTrailerData(TrailerAddDetailVO trailerAddDetailVO) {
		ToolKits.isParamNull(trailerAddDetailVO.getLoadingBillId(), "托运单ID不为空");
		ToolKits.isParamNull(trailerAddDetailVO.getShipbillIds(), "运单ID不为空");

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

		// 数据字典翻译数据集合
		List<Map<String, Object>> data1 = Lists.newArrayList();
		List<Map<String, Object>> data2 = Lists.newArrayList();
		List<Map<String, Object>> data3 = Lists.newArrayList();
		List<Map<String, Object>> data4 = Lists.newArrayList();
		List<Map<String, Object>> data5 = Lists.newArrayList();
		List<Map<String, Object>> data6 = Lists.newArrayList();
		List<Map<String, Object>> data7 = Lists.newArrayList();
		List<Map<String, Object>> data8 = Lists.newArrayList();
		List<SignconfigPopDTO> data9 = Lists.newArrayList();

		// 订单类型
		RestMessage<List<Map<String, Object>>> restMessage1 = maindataTmsResource.getDropDownById(DataDictionaryConstant.ORDER_TYPE, null, null, null);
		if (!restMessage1.isSuccess()) {
			throw new RuntimeException("订单类型翻译失败!");
		} else {
			data1 = restMessage1.getData();
		}
		// 订单业务类型
		RestMessage<List<Map<String, Object>>> restMessage2 = maindataTmsResource.getDropDownById(DataDictionaryConstant.ORDER_BUSINESS_TYPE, null, null, null);
		if (!restMessage2.isSuccess()) {
			throw new RuntimeException("订单业务类型翻译失败!");
		} else {
			data2 = restMessage2.getData();
		}
		// 配送方式
		RestMessage<List<Map<String, Object>>> restMessage3 = maindataTmsResource.getDropDownById(DataDictionaryConstant.DELIVERY_METHOD_TYPE, null, null, null);
		if (!restMessage3.isSuccess()) {
			throw new RuntimeException("配送方式翻译失败!");
		} else {
			data3 = restMessage3.getData();
		}
		// 运输类型(运输模式)
		RestMessage<List<Map<String, Object>>> restMessage4 = maindataTmsResource.getDropDownById(DataDictionaryConstant.TRANSPORT_TYPE, null, null, null);
		if (!restMessage4.isSuccess()) {
			throw new RuntimeException("运输类型(运输模式)翻译失败!");
		} else {
			data4 = restMessage4.getData();
		}
		// 温度要求
		RestMessage<List<Map<String, Object>>> restMessage5 = maindataTmsResource.getDropDownById(DataDictionaryConstant.TEMPERATURE_REQUIREMENT, null, null, null);
		if (!restMessage5.isSuccess()) {
			throw new RuntimeException("温度要求翻译失败!");
		} else {
			data5 = restMessage5.getData();
		}
		// 发货方类型
		RestMessage<List<Map<String, Object>>> restMessage6 = maindataTmsResource.getDropDownById(DataDictionaryConstant.SHIPPER_TYPE, null, null, null);
		if (!restMessage6.isSuccess()) {
			throw new RuntimeException("发货方类型翻译失败!");
		} else {
			data6 = restMessage6.getData();
		}
		// 收货方类型
		RestMessage<List<Map<String, Object>>> restMessage7 = maindataTmsResource.getDropDownById(DataDictionaryConstant.CONSIGNEE_TYPE, null, null, null);
		if (!restMessage7.isSuccess()) {
			throw new RuntimeException("收货方类型翻译失败!");
		} else {
			data7 = restMessage7.getData();
		}

		// 运单状态
		RestMessage<List<Map<String, Object>>> restMessage8 = maindataTmsResource.getDropDownById(DataDictionaryConstant.SHIPBILL_STATUS, null, null, null);
		if (!restMessage8.isSuccess()) {
			throw new RuntimeException("运单状态翻译失败!");
		} else {
			data8 = restMessage8.getData();
		}

		// 标记配置
		SignconfigPopVO signconfigPopVO = new SignconfigPopVO();
		RestMessage<List<SignconfigPopDTO>> restMessage9 = maindataTmsResource.getSignConfig(signconfigPopVO);
		if (!restMessage9.isSuccess()) {
			throw new RuntimeException("标记配置查询失败!");
		} else {
			data9 = restMessage9.getData();
		}

		TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel = tmsLoadingBillHeaderMapper.findById(trailerAddDetailVO.getLoadingBillId(), TmsLoadingBillHeaderModel.class);
		ToolKits.isParamNull(tmsLoadingBillHeaderModel, "托运单ID[" + trailerAddDetailVO.getLoadingBillId() + "]有误");

		// 判断托运单是否已审核
		if (!tmsLoadingBillHeaderModel.getStatus().equals(DataDictionaryConstant.LOADING_BILL_STATUS_WSH)) {
			throw new RuntimeException("托运单[" + tmsLoadingBillHeaderModel.getLoadingBillId() + "]不是待审核状态,不能添加运单!");
		}

		List<TmsShipbillHeaderModel> tmsShipbillHeaderModels = tmsShipbillHeaderMapper.findByIds(TmsShipbillHeaderModel.class, trailerAddDetailVO.getShipbillIds().toArray(), null);

		Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
		Restriction r1 = Restrictions.eq("loadingBillId", trailerAddDetailVO.getLoadingBillId());
		Restriction r2 = Restrictions.in("shipbillId", trailerAddDetailVO.getShipbillIds().toArray());
		Restriction r3 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
		criteria.setRestriction(Restrictions.and(r1, r2, r3));
		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModelList = tmsLoadingBillDetailMapper.findByCriteria(criteria);
		if (ToolKits.isNotEmpty(tmsLoadingBillDetailModelList)) {
			throw new PrologException("运单ID[" + tmsLoadingBillDetailModelList.stream().map(TmsLoadingBillDetailModel::getShipbillId).collect(Collectors.joining(",")) + "]已被添加");
		}

		criteria.setRestriction(Restrictions.and(r1, r3));
		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteria);
		List<Integer> indexList = tmsLoadingBillDetailModels.stream().filter(o -> ToolKits.isNotEmpty(o.getShippingOrder())).map(TmsLoadingBillDetailModel::getShippingOrder).collect(Collectors.toList());
		Integer index = null;
		if (ToolKits.isEmpty(indexList)) {
			index = 1;
		} else {
			index = Collections.max(indexList);
		}

		// 客户数
		List<String> customerList = tmsLoadingBillDetailModels.stream().filter(o -> ToolKits.isNotEmpty(o.getConsigneeUnitName())).map(TmsLoadingBillDetailModel::getConsigneeUnitName).distinct().collect(Collectors.toList());

		// 站点数
		List<String> siteList = tmsLoadingBillDetailModels.stream().filter(o -> ToolKits.isNotEmpty(o.getConsigneeAddress())).map(TmsLoadingBillDetailModel::getConsigneeAddress).distinct().collect(Collectors.toList());

		Date date = DateUtil.date();
		List<ShipbillHeaderPageDTO> dtoList = Lists.newArrayList();
		for (TmsShipbillHeaderModel tmsShipbillHeaderModel : tmsShipbillHeaderModels) {
			ShipbillHeaderPageDTO dto = new ShipbillHeaderPageDTO();
			BeanUtils.copyProperties(tmsShipbillHeaderModel, dto);

			dtoList.add(dto);

			// 收货方位置(经纬度判断)
			if (ToolKits.isNotEmpty(tmsShipbillHeaderModel.getConsigneeLongitude()) && ToolKits.isNotEmpty(tmsShipbillHeaderModel.getConsigneeLatitude())) {
				dto.setConsigneePositioning(StatusConstant.POSITIONING_YDW);
			} else {
				dto.setConsigneePositioning(StatusConstant.POSITIONING_WDW);
			}
			// 发货方位置(经纬度判断)
			if (ToolKits.isNotEmpty(tmsShipbillHeaderModel.getShipperLongitude()) && ToolKits.isNotEmpty(tmsShipbillHeaderModel.getShipperLatitude())) {
				dto.setShipperPositioning(StatusConstant.POSITIONING_YDW);
			} else {
				dto.setShipperPositioning(StatusConstant.POSITIONING_WDW);
			}

			// 类型翻译
			dto.setOrderTypeName(PublicMethods.change(data1, String.valueOf(dto.getOrderType())));
			dto.setOrderBusinessTypeName(PublicMethods.change(data2, String.valueOf(dto.getOrderBusinessType())));
			dto.setDeliveryMethodTypeName(PublicMethods.change(data3, String.valueOf(dto.getDeliveryMethodType())));
			dto.setTransportTypeName(PublicMethods.change(data4, String.valueOf(dto.getTransportType())));
			dto.setTemperatureRequirementName(PublicMethods.change(data5, String.valueOf(dto.getTemperatureRequirement())));
			dto.setShipperTypeName(PublicMethods.change(data6, String.valueOf(dto.getShipperType())));
			dto.setConsigneeTypeName(PublicMethods.change(data7, String.valueOf(dto.getConsigneeType())));
			dto.setStatusName(PublicMethods.change(data8, String.valueOf(dto.getStatus())));

			// 获取背景颜色和字体颜色
			Signconfig: for (SignconfigPopDTO signconfigPopDTO : data9) {
				// 标记类型匹配
				switch (signconfigPopDTO.getType()) {
				case DataDictionaryConstant.SIGNCONFIG_TYPE_DDLX: // 订单类型
					if (ToolKits.isNotEmpty(signconfigPopDTO.getMatching())) {
						// 判断是否匹配
						if (PublicMethods.compare(signconfigPopDTO.getMatching(), ToolKits.isNotEmpty(signconfigPopDTO.getStoredValue()) ? signconfigPopDTO.getStoredValue() : "", ToolKits.isNotEmpty(dto.getOrderTypeName()) ? dto.getOrderTypeName() : "")) {
							dto.setBackground(ToolKits.isEmpty(signconfigPopDTO.getBackground()) ? "" : signconfigPopDTO.getBackground());
							dto.setColor(ToolKits.isEmpty(signconfigPopDTO.getColor()) ? "" : signconfigPopDTO.getColor());

							// 返回前端所需标记ID
							dto.setSignConfigId(signconfigPopDTO.getId());

							// 匹配上结束循环
							break Signconfig;
						}
					}
					break;
				case DataDictionaryConstant.SIGNCONFIG_TYPE_YWLX: // 业务类型
					if (ToolKits.isNotEmpty(signconfigPopDTO.getMatching())) {
						if (PublicMethods.compare(signconfigPopDTO.getMatching(), ToolKits.isNotEmpty(signconfigPopDTO.getStoredValue()) ? signconfigPopDTO.getStoredValue() : "", ToolKits.isNotEmpty(dto.getOrderBusinessTypeName()) ? dto.getOrderBusinessTypeName() : "")) {
							dto.setBackground(ToolKits.isEmpty(signconfigPopDTO.getBackground()) ? "" : signconfigPopDTO.getBackground());
							dto.setColor(ToolKits.isEmpty(signconfigPopDTO.getColor()) ? "" : signconfigPopDTO.getColor());

							// 返回前端所需标记ID
							dto.setSignConfigId(signconfigPopDTO.getId());

							break Signconfig;
						}
					}
					break;
				case DataDictionaryConstant.SIGNCONFIG_TYPE_WDYQ: // 配送方式
					if (ToolKits.isNotEmpty(signconfigPopDTO.getMatching())) {
						if (PublicMethods.compare(signconfigPopDTO.getMatching(), ToolKits.isNotEmpty(signconfigPopDTO.getStoredValue()) ? signconfigPopDTO.getStoredValue() : "", ToolKits.isNotEmpty(dto.getTemperatureRequirementName()) ? dto.getTemperatureRequirementName() : "")) {
							dto.setBackground(ToolKits.isEmpty(signconfigPopDTO.getBackground()) ? "" : signconfigPopDTO.getBackground());
							dto.setColor(ToolKits.isEmpty(signconfigPopDTO.getColor()) ? "" : signconfigPopDTO.getColor());

							// 返回前端所需标记ID
							dto.setSignConfigId(signconfigPopDTO.getId());

							break Signconfig;
						}
					}
					break;
				case DataDictionaryConstant.SIGNCONFIG_TYPE_PSFS: // 订单备注
					if (ToolKits.isNotEmpty(signconfigPopDTO.getMatching())) {
						if (PublicMethods.compare(signconfigPopDTO.getMatching(), ToolKits.isNotEmpty(signconfigPopDTO.getStoredValue()) ? signconfigPopDTO.getStoredValue() : "", ToolKits.isNotEmpty(dto.getDeliveryMethodTypeName()) ? dto.getDeliveryMethodTypeName() : "")) {
							dto.setBackground(ToolKits.isEmpty(signconfigPopDTO.getBackground()) ? "" : signconfigPopDTO.getBackground());
							dto.setColor(ToolKits.isEmpty(signconfigPopDTO.getColor()) ? "" : signconfigPopDTO.getColor());

							// 返回前端所需标记ID
							dto.setSignConfigId(signconfigPopDTO.getId());

							break Signconfig;
						}
					}
					break;
				case DataDictionaryConstant.SIGNCONFIG_TYPE_DDBZ:
					if (ToolKits.isNotEmpty(signconfigPopDTO.getMatching())) {
						if (PublicMethods.compare(signconfigPopDTO.getMatching(), ToolKits.isNotEmpty(signconfigPopDTO.getStoredValue()) ? signconfigPopDTO.getStoredValue() : "", ToolKits.isNotEmpty(dto.getMemo()) ? dto.getMemo() : "")) {
							dto.setBackground(ToolKits.isEmpty(signconfigPopDTO.getBackground()) ? "" : signconfigPopDTO.getBackground());
							dto.setColor(ToolKits.isEmpty(signconfigPopDTO.getColor()) ? "" : signconfigPopDTO.getColor());

							// 返回前端所需标记ID
							dto.setSignConfigId(signconfigPopDTO.getId());

							break Signconfig;
						}
					}
					break;
				}
			}
			// 配送顺序
			index++;

			TmsLoadingBillDetailModel tmsLoadingBillDetailModel = new TmsLoadingBillDetailModel();
			BeanUtils.copyProperties(tmsShipbillHeaderModel, tmsLoadingBillDetailModel);

			ShipbillOperateLogSaveVO shipbillOperateLogSaveVO = new ShipbillOperateLogSaveVO();
			ShipbillNodeTrackingSaveVO shipbillNodeTrackingSaveVO = new ShipbillNodeTrackingSaveVO();
			if (user.getUserType().equals(BussinessConstant.USER_TYPE_ZY)) {
				// 修改装车单明细状态
				tmsLoadingBillDetailModel.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH);
				// 修改运单状态
				tmsShipbillHeaderModel.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH);
				shipbillOperateLogSaveVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_DIS_ADD + trailerAddDetailVO.getLoadingBillId());
				shipbillOperateLogSaveVO.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_YTJ);
				shipbillOperateLogSaveVO.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH);
				shipbillNodeTrackingSaveVO.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH);
			} else if (user.getUserType().equals(BussinessConstant.USER_TYPE_CYS)) {
				// 修改装车单明细状态
				tmsLoadingBillDetailModel.setCarrierShipbillStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED);
				// 修改运单状态
				tmsShipbillHeaderModel.setCarrierShipbillStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED);
				shipbillOperateLogSaveVO.setOperateEvent(DataDictionaryConstant.CARRIER_SHIPBILL_NODE_STATUSNAME_DI_ADD + trailerAddDetailVO.getLoadingBillId());
				shipbillOperateLogSaveVO.setOldCarrierShipbillStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_AUDITED);
				shipbillOperateLogSaveVO.setNewCarrierShipbillStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED);
				shipbillNodeTrackingSaveVO.setStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED);
			}

			// 获取托运单明细ID
			RestMessage<String> restMessage = maindataTmsResource.getCodeNumberByCode(SeriaNnumberConstant.TMS_LOADING_BILL_DETAIL_ID, "L");
			if (!restMessage.isSuccess()) {
				throw new RuntimeException("生成托运单明细ID失败");
			}
			String id = restMessage.getData();

			tmsLoadingBillDetailModel.setCreateperson(user.getNickname());
			tmsLoadingBillDetailModel.setCreatetime(date);
			tmsLoadingBillDetailModel.setId(id);
			tmsLoadingBillDetailModel.setShippingOrder(index);
			tmsLoadingBillDetailModel.setLoadingBillId(trailerAddDetailVO.getLoadingBillId());
			tmsLoadingBillDetailModel.setLoadingBillNo(trailerAddDetailVO.getLoadingBillId());

			// 重量体积件数
			tmsLoadingBillHeaderModel.setTotalPcs(tmsLoadingBillHeaderModel.getTotalPcs().add(tmsLoadingBillDetailModel.getTotalPcs()));
			tmsLoadingBillHeaderModel.setTotalVolume(tmsLoadingBillHeaderModel.getTotalVolume().add(tmsLoadingBillDetailModel.getTotalVolume()));
			tmsLoadingBillHeaderModel.setTotalWeight(tmsLoadingBillHeaderModel.getTotalWeight().add(tmsLoadingBillDetailModel.getTotalWeight()));

			// 实际重量体积件数
			tmsLoadingBillHeaderModel.setActualTotalPcs(tmsLoadingBillHeaderModel.getActualTotalPcs().add(tmsLoadingBillDetailModel.getActualTotalPcs()));
			tmsLoadingBillHeaderModel.setActualTotalVolume(tmsLoadingBillHeaderModel.getActualTotalVolume().add(tmsLoadingBillDetailModel.getActualTotalVolume()));
			tmsLoadingBillHeaderModel.setActualTotalWeight(tmsLoadingBillHeaderModel.getActualTotalWeight().add(tmsLoadingBillDetailModel.getActualTotalWeight()));

			// 整件数拼箱数
			if (ToolKits.isNotEmpty(tmsLoadingBillDetailModel.getPackageWholePiece())) {
				tmsLoadingBillHeaderModel.setTotalWholePiece(tmsLoadingBillHeaderModel.getTotalWholePiece().subtract(tmsLoadingBillDetailModel.getPackageWholePiece()));
			}
			if (ToolKits.isNotEmpty(tmsLoadingBillDetailModel.getPackageLclPiece())) {
				tmsLoadingBillHeaderModel.setTotalLclPiece(tmsLoadingBillHeaderModel.getTotalLclPiece().subtract(tmsLoadingBillDetailModel.getPackageLclPiece()));
			}
			// 运单数
			tmsLoadingBillHeaderModel.setShipbillNumber(tmsLoadingBillHeaderModel.getShipbillNumber() + 1);

			// 客户数
			if (!customerList.contains(tmsShipbillHeaderModel.getConsigneeName())) {
				tmsLoadingBillHeaderModel.setCustomerNumber(tmsLoadingBillHeaderModel.getCustomerNumber() + 1);
			}

			// 站点数
			if (!siteList.contains(tmsShipbillHeaderModel.getConsigneeAddress())) {
				tmsLoadingBillHeaderModel.setSiteNumber(tmsLoadingBillHeaderModel.getSiteNumber() + 1);
			}
			// 承运商配置业务流程
			ShipbillFitBusinessFlowDTO flowData = shipbillMatchBusinessFlow(tmsShipbillHeaderModel);
			tmsShipbillHeaderModel.setCarrierFlowConfig(flowData.getFlowConfig());
			tmsShipbillHeaderModel.setCarrierId(tmsLoadingBillHeaderModel.getCarrierId());
			tmsShipbillHeaderModel.setCarrierCode(tmsLoadingBillHeaderModel.getCarrierCode());
			tmsShipbillHeaderModel.setCarrierName(tmsLoadingBillHeaderModel.getCarrierName());
			tmsShipbillHeaderModel.setCarrierType(tmsLoadingBillHeaderModel.getCarrierType());
			tmsShipbillHeaderModel.setUpdateperson(user.getNickname());
			tmsShipbillHeaderModel.setUpdatetime(date);
			tmsShipbillHeaderMapper.update(tmsShipbillHeaderModel);

			tmsLoadingBillDetailModel.setCarrierFlowConfig(tmsShipbillHeaderModel.getCarrierFlowConfig());
			tmsLoadingBillDetailModel.setFlowConfig(tmsShipbillHeaderModel.getFlowConfig());
//			saveList.add(tmsLoadingBillDetailModel);

			// 批量添加托运单明细
			tmsLoadingBillDetailMapper.save(tmsLoadingBillDetailModel);

			// 运单操作日志保存
			shipbillOperateLogSaveVO.setShipbillId(tmsLoadingBillDetailModel.getShipbillId());
			shipbillOperateLogSaveVO.setShipbillNo(tmsLoadingBillDetailModel.getShipbillNo());
			shipbillOperateLogService.addShipbillOperateLogData(shipbillOperateLogSaveVO);

			// 运单节点保存
			shipbillNodeTrackingSaveVO.setShipbillId(tmsShipbillHeaderModel.getShipbillId());
			shipbillNodeTrackingSaveVO.setShipbillNo(tmsShipbillHeaderModel.getShipbillNo());
			shipbillNodeTrackingSaveVO.setNodeEvent(DataDictionaryConstant.CARRIER_SHIPBILL_NODE_STATUSNAME_DI_ADD + trailerAddDetailVO.getLoadingBillId());
			shipbillNodeTrackingService.addShipbillNodeTrackingData(shipbillNodeTrackingSaveVO);

		}

		// 计算装载率
		if (ToolKits.isNotEmpty(tmsLoadingBillHeaderModel.getVehicleId())) {
			Map<String, String> map = this.calculateLoadingRate(tmsLoadingBillHeaderModel.getVehicleId(), tmsLoadingBillHeaderModel.getTotalWeight(), tmsLoadingBillHeaderModel.getTotalVolume());
			tmsLoadingBillHeaderModel.setVolumeLoadingRate(map.get("volume"));
			tmsLoadingBillHeaderModel.setWeightLoadingRate(map.get("weight"));
		}

		// 修改托运单
		tmsLoadingBillHeaderModel.setUpdateperson(user.getNickname());
		tmsLoadingBillHeaderModel.setUpdatetime(date);
		tmsLoadingBillHeaderMapper.update(tmsLoadingBillHeaderModel);

		return dtoList;
	}

	/**
	 * 已托运配载运单剔除
	 *
	 * @param trailerDeleteDetailVO
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void deleteDetailTrailerData(TrailerDeleteDetailVO trailerDeleteDetailVO) {
		ToolKits.isParamNull(trailerDeleteDetailVO.getLoadingBillId(), "托运单ID不为空");
		ToolKits.isParamNull(trailerDeleteDetailVO.getShipbillIds(), "运单ID不为空");

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

		TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel = tmsLoadingBillHeaderMapper.findById(trailerDeleteDetailVO.getLoadingBillId(), TmsLoadingBillHeaderModel.class);
		if (ToolKits.isEmpty(tmsLoadingBillHeaderModel)) {
			throw new PrologException(StrUtil.format("托运单{}不存在",trailerDeleteDetailVO.getLoadingBillId()));
		}
		if (ToolKits.isEmpty(tmsLoadingBillHeaderModel.getStatus()) || DataDictionaryConstant.LOADING_BILL_STATUS_ZC_CONFIRM.intValue() < tmsLoadingBillHeaderModel.getStatus().intValue()  ) {
			throw new PrologException(StrUtil.format("托运单{}已启运，请不要剔除运单", trailerDeleteDetailVO.getLoadingBillId()));
		}

		Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
		Restriction r1 = Restrictions.eq(TmsLoadingBillDetailModel::getLoadingBillId, trailerDeleteDetailVO.getLoadingBillId());
		Restriction r2 = Restrictions.in(TmsLoadingBillDetailModel::getShipbillId, trailerDeleteDetailVO.getShipbillIds().stream().toArray());
		Restriction r3 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
		criteria.setRestriction(Restrictions.and(r1, r2,r3));
		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteria);

		// 修改配送顺序以及总重量体积件数等数据
		for (TmsLoadingBillDetailModel tmsLoadingBillDetailModel : tmsLoadingBillDetailModels) {
			// 修改配送顺序
			r1 = Restrictions.eq("loadingBillId", tmsLoadingBillDetailModel.getLoadingBillId());
			r2 = Restrictions.ne("shipbillId", tmsLoadingBillDetailModel.getShipbillId());
			criteria.setRestriction(Restrictions.and(r1, r2, r3));
			List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModelList = tmsLoadingBillDetailMapper.findByCriteria(criteria);
			for (TmsLoadingBillDetailModel loadingBillDetailModel : tmsLoadingBillDetailModelList) {
				if (ToolKits.isEmpty(loadingBillDetailModel.getShippingOrder()) || ToolKits.isEmpty(tmsLoadingBillDetailModel.getShippingOrder())){
					continue;
				}
				if (loadingBillDetailModel.getShippingOrder() > tmsLoadingBillDetailModel.getShippingOrder()) {
					loadingBillDetailModel.setShippingOrder(loadingBillDetailModel.getShippingOrder() - 1);
				}
				tmsLoadingBillDetailMapper.update(loadingBillDetailModel);
			}

			/*// 客户数
			Integer customerNumber = tmsLoadingBillDetailModelList.stream().filter(o -> ToolKits.isNotEmpty(o.getConsigneeName())).map(TmsLoadingBillDetailModel::getConsigneeName).distinct().collect(Collectors.toList()).size();

			// 站点数
			Integer siteNumber = tmsLoadingBillDetailModelList.stream().filter(o -> ToolKits.isNotEmpty(o.getConsigneeAddress())).map(TmsLoadingBillDetailModel::getConsigneeAddress).distinct().collect(Collectors.toList()).size();

			// 重量体积件数
			tmsLoadingBillHeaderModel.setTotalPcs(tmsLoadingBillHeaderModel.getTotalPcs().subtract(tmsLoadingBillDetailModel.getTotalPcs()));
			tmsLoadingBillHeaderModel.setTotalVolume(tmsLoadingBillHeaderModel.getTotalVolume().subtract(tmsLoadingBillDetailModel.getTotalVolume()));
			tmsLoadingBillHeaderModel.setTotalWeight(tmsLoadingBillHeaderModel.getTotalWeight().subtract(tmsLoadingBillDetailModel.getTotalWeight()));

			// 实际重量体积件数
			tmsLoadingBillHeaderModel.setActualTotalPcs(tmsLoadingBillHeaderModel.getActualTotalPcs().subtract(tmsLoadingBillDetailModel.getActualTotalPcs()));
			tmsLoadingBillHeaderModel.setActualTotalVolume(tmsLoadingBillHeaderModel.getActualTotalVolume().subtract(tmsLoadingBillDetailModel.getActualTotalVolume()));
			tmsLoadingBillHeaderModel.setActualTotalWeight(tmsLoadingBillHeaderModel.getActualTotalWeight().subtract(tmsLoadingBillDetailModel.getActualTotalWeight()));

			// 整件数拼箱数
			if (ToolKits.isNotEmpty(tmsLoadingBillDetailModel.getPackageWholePiece())) {
				tmsLoadingBillHeaderModel.setTotalWholePiece(tmsLoadingBillHeaderModel.getTotalWholePiece().subtract(tmsLoadingBillDetailModel.getPackageWholePiece()));
			}
			if (ToolKits.isNotEmpty(tmsLoadingBillDetailModel.getPackageLclPiece())) {
				tmsLoadingBillHeaderModel.setTotalLclPiece(tmsLoadingBillHeaderModel.getTotalLclPiece().subtract(tmsLoadingBillDetailModel.getPackageLclPiece()));
			}
			// 运单数
			tmsLoadingBillHeaderModel.setShipbillNumber(tmsLoadingBillHeaderModel.getShipbillNumber() - 1);
			// 客户数
			tmsLoadingBillHeaderModel.setCustomerNumber(customerNumber);
			// 站点数
			tmsLoadingBillHeaderModel.setSiteNumber(siteNumber);*/

			// 删除明细内容
			tmsLoadingBillDetailMapper.deleteById(tmsLoadingBillDetailModel.getId(), TmsLoadingBillDetailModel.class);

			ShipbillOperateLogSaveVO shipbillOperateLogSaveVO = new ShipbillOperateLogSaveVO();
			ShipbillNodeTrackingSaveVO shipbillNodeTrackingSaveVO = new ShipbillNodeTrackingSaveVO();
			if (user.getUserType().equals(BussinessConstant.USER_TYPE_ZY)) {
				shipbillOperateLogSaveVO.setOperateEvent("从托运单" + tmsLoadingBillHeaderModel.getLoadingBillId() + "中剔除");
				shipbillOperateLogSaveVO.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH);
				shipbillOperateLogSaveVO.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_REVIEW);

				shipbillNodeTrackingSaveVO.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_REVIEW);
				shipbillNodeTrackingSaveVO.setNodeEvent("从托运单" + tmsLoadingBillHeaderModel.getLoadingBillId() + "中剔除");
			} else if (user.getUserType().equals(BussinessConstant.USER_TYPE_CYS)) {
				shipbillOperateLogSaveVO.setOperateEvent("承运商 从托运单" + tmsLoadingBillHeaderModel.getLoadingBillId() + "中剔除");
				shipbillOperateLogSaveVO.setOldStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED);
				shipbillOperateLogSaveVO.setNewStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_AUDITED);

				shipbillNodeTrackingSaveVO.setStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_AUDITED);
				shipbillNodeTrackingSaveVO.setNodeEvent("承运商 从托运单" + tmsLoadingBillHeaderModel.getLoadingBillId() + "中剔除");
			}
			// 运单操作日志保存
			shipbillOperateLogSaveVO.setShipbillId(tmsLoadingBillDetailModel.getShipbillId());
			shipbillOperateLogSaveVO.setShipbillNo(tmsLoadingBillDetailModel.getShipbillNo());
			shipbillOperateLogService.addShipbillOperateLogData(shipbillOperateLogSaveVO);

			// 运单节点保存
			shipbillNodeTrackingSaveVO.setShipbillId(tmsLoadingBillDetailModel.getShipbillId());
			shipbillNodeTrackingSaveVO.setShipbillNo(tmsLoadingBillDetailModel.getShipbillNo());
			shipbillNodeTrackingService.addShipbillNodeTrackingData(shipbillNodeTrackingSaveVO);
		}
		// 重新计算
		calculateLoadingData(tmsLoadingBillHeaderModel);

		// 计算装载率
		if (ToolKits.isNotEmpty(tmsLoadingBillHeaderModel.getVehicleId())) {
			Map<String, String> map = this.calculateLoadingRate(tmsLoadingBillHeaderModel.getVehicleId(), tmsLoadingBillHeaderModel.getTotalWeight(), tmsLoadingBillHeaderModel.getTotalVolume());
			tmsLoadingBillHeaderModel.setVolumeLoadingRate(map.get("volume"));
			tmsLoadingBillHeaderModel.setWeightLoadingRate(map.get("weight"));
		}
		Date date = DateUtil.date();
		// 修改汇总表
		tmsLoadingBillHeaderModel.setUpdatetime(date);
		tmsLoadingBillHeaderModel.setUpdateperson(user.getNickname());
		tmsLoadingBillHeaderMapper.update(tmsLoadingBillHeaderModel);

		// 运单状态回退
		criteria = Criteria.forClass(TmsShipbillHeaderModel.class);
		r1 = Restrictions.in("shipbillId", trailerDeleteDetailVO.getShipbillIds().toArray());
		criteria.setRestriction(r1);

		Map<String, Object> map = Maps.newHashMap();
		map.put("updateperson", user.getNickname());
		map.put("updatetime", date);
		if (user.getUserType().equals(BussinessConstant.USER_TYPE_ZY)) {
			map.put("carrierFlowConfig", null);
			map.put("carrierId", null);
			map.put("carrierCode", null);
			map.put("carrierName", null);
			map.put("carrierType", null);
			map.put("status", DataDictionaryConstant.SHIPBILL_STATUS_REVIEW);
		} else if (user.getUserType().equals(BussinessConstant.USER_TYPE_CYS)) {
			map.put("carrierFlowConfig", null);
			map.put("carrierId", null);
			map.put("carrierCode", null);
			map.put("carrierName", null);
			map.put("carrierType", null);
			map.put("carrierShipbillStatus", DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_AUDITED);
		}
		tmsShipbillHeaderMapper.updateMapByCriteria(map, criteria);
	}

	/**
	 * 已托运配载运单移动
	 *
	 * @param trailerMobileDetailVO
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void mobileDetailTrailerData(TrailerMobileDetailVO trailerMobileDetailVO) {
		ToolKits.isParamNull(trailerMobileDetailVO.getOriginalLoadingBillId(), "原托运单ID不为空");
		ToolKits.isParamNull(trailerMobileDetailVO.getNowLoadingBillId(), "目标托运单ID不为空");
		ToolKits.isParamNull(trailerMobileDetailVO.getShipbillIds(), "运单ID不为空");

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

		Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
		Restriction r1 = Restrictions.in("shipbillId", trailerMobileDetailVO.getShipbillIds().toArray());
		Restriction r2 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
		criteria.setRestriction(Restrictions.and(r1, r2));

		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteria);

		// 原托运单
		TmsLoadingBillHeaderModel originalModel = tmsLoadingBillHeaderMapper.findById(trailerMobileDetailVO.getOriginalLoadingBillId(), TmsLoadingBillHeaderModel.class);
		// 目标托运单
		TmsLoadingBillHeaderModel nowModel = tmsLoadingBillHeaderMapper.findById(trailerMobileDetailVO.getNowLoadingBillId(), TmsLoadingBillHeaderModel.class);

		criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
		r1 = Restrictions.eq("loadingBillId", trailerMobileDetailVO.getNowLoadingBillId());
		criteria.setRestriction(Restrictions.and(r1, r2));

		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailNowModels = tmsLoadingBillDetailMapper.findByCriteria(criteria);
		List<Integer> indexList = tmsLoadingBillDetailNowModels.stream().filter(o -> ToolKits.isNotEmpty(o.getShippingOrder())).map(TmsLoadingBillDetailModel::getShippingOrder).collect(Collectors.toList());
		Integer index = null;
		if (ToolKits.isEmpty(indexList)) {
			index = 1;
		} else {
			index = Collections.max(indexList);
		}

		// 目标托运单客户集合
		List<String> customerList = tmsLoadingBillDetailNowModels.stream().filter(o -> ToolKits.isNotEmpty(o.getConsigneeName())).map(TmsLoadingBillDetailModel::getConsigneeName).distinct().collect(Collectors.toList());

		// 目标托运单站点集合
		List<String> siteList = tmsLoadingBillDetailNowModels.stream().filter(o -> ToolKits.isNotEmpty(o.getConsigneeAddress())).map(TmsLoadingBillDetailModel::getConsigneeAddress).distinct().collect(Collectors.toList());
		Date date = DateUtil.date();
		// 修改配送顺序以及总重量体积件数等数据
		for (TmsLoadingBillDetailModel tmsLoadingBillDetailModel : tmsLoadingBillDetailModels) {
			index++;
			// 修改配送顺序
			r1 = Restrictions.eq("loadingBillId", tmsLoadingBillDetailModel.getLoadingBillId());
			Restriction r3 = Restrictions.ne("shipbillId", tmsLoadingBillDetailModel.getShipbillId());
			criteria.setRestriction(Restrictions.and(r1, r2, r3));
			List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModelList = tmsLoadingBillDetailMapper.findByCriteria(criteria);
			for (TmsLoadingBillDetailModel loadingBillDetailModel : tmsLoadingBillDetailModelList) {
				if (ToolKits.isEmpty(loadingBillDetailModel.getShippingOrder()) || ToolKits.isEmpty(tmsLoadingBillDetailModel.getShippingOrder())){
					continue;
				}
				if (loadingBillDetailModel.getShippingOrder() > tmsLoadingBillDetailModel.getShippingOrder()) {
					loadingBillDetailModel.setShippingOrder(loadingBillDetailModel.getShippingOrder() - 1);
				}
				loadingBillDetailModel.setUpdateperson(user.getNickname());
				loadingBillDetailModel.setUpdatetime(date);
				tmsLoadingBillDetailMapper.update(loadingBillDetailModel);
			}

			// 原托运单客户数
			Integer customerNumber = tmsLoadingBillDetailModelList.stream().filter(o -> ToolKits.isNotEmpty(o.getConsigneeName())).map(TmsLoadingBillDetailModel::getConsigneeName).distinct().collect(Collectors.toList()).size();

			// 原托运单站点数
			Integer siteNumber = tmsLoadingBillDetailModelList.stream().filter(o -> ToolKits.isNotEmpty(o.getConsigneeAddress())).map(TmsLoadingBillDetailModel::getConsigneeAddress).distinct().collect(Collectors.toList()).size();

			// 原托运单重量体积件数
			originalModel.setTotalPcs(originalModel.getTotalPcs().subtract(tmsLoadingBillDetailModel.getTotalPcs()));
			originalModel.setTotalVolume(originalModel.getTotalVolume().subtract(tmsLoadingBillDetailModel.getTotalVolume()));
			originalModel.setTotalWeight(originalModel.getTotalWeight().subtract(tmsLoadingBillDetailModel.getTotalWeight()));

			// 原托运单实际重量体积件数
			originalModel.setActualTotalPcs(originalModel.getActualTotalPcs().subtract(tmsLoadingBillDetailModel.getActualTotalPcs()));
			originalModel.setActualTotalVolume(originalModel.getActualTotalVolume().subtract(tmsLoadingBillDetailModel.getActualTotalVolume()));
			originalModel.setActualTotalWeight(originalModel.getActualTotalWeight().subtract(tmsLoadingBillDetailModel.getActualTotalWeight()));

			// 原托运单整件数拼箱数
			if (ToolKits.isNotEmpty(tmsLoadingBillDetailModel.getPackageWholePiece())) {
				originalModel.setTotalWholePiece(originalModel.getTotalWholePiece().subtract(tmsLoadingBillDetailModel.getPackageWholePiece()));
			}
			if (ToolKits.isNotEmpty(tmsLoadingBillDetailModel.getPackageLclPiece())) {
				originalModel.setTotalLclPiece(originalModel.getTotalLclPiece().subtract(tmsLoadingBillDetailModel.getPackageLclPiece()));
			}
			// 原托运单运单数
			originalModel.setShipbillNumber(originalModel.getShipbillNumber() - 1);

			// 原托运单客户数
			originalModel.setCustomerNumber(customerNumber);
			// 原托运单站点数
			originalModel.setSiteNumber(siteNumber);

			// 目标托运单重量体积件数
			nowModel.setTotalPcs(nowModel.getTotalPcs().add(tmsLoadingBillDetailModel.getTotalPcs()));
			nowModel.setTotalVolume(nowModel.getTotalVolume().add(tmsLoadingBillDetailModel.getTotalVolume()));
			nowModel.setTotalWeight(nowModel.getTotalWeight().add(tmsLoadingBillDetailModel.getTotalWeight()));

			// 目标托运单实际重量体积件数
			nowModel.setActualTotalPcs(nowModel.getActualTotalPcs().add(tmsLoadingBillDetailModel.getActualTotalPcs()));
			nowModel.setActualTotalVolume(nowModel.getActualTotalVolume().add(tmsLoadingBillDetailModel.getActualTotalVolume()));
			nowModel.setActualTotalWeight(nowModel.getActualTotalWeight().add(tmsLoadingBillDetailModel.getActualTotalWeight()));

			// 目标托运单整件数拼箱数
			if (ToolKits.isNotEmpty(tmsLoadingBillDetailModel.getPackageWholePiece())) {
				nowModel.setTotalWholePiece(nowModel.getTotalWholePiece().add(tmsLoadingBillDetailModel.getPackageWholePiece()));
			}
			if (ToolKits.isNotEmpty(tmsLoadingBillDetailModel.getPackageLclPiece())) {
				nowModel.setTotalLclPiece(nowModel.getTotalLclPiece().add(tmsLoadingBillDetailModel.getPackageLclPiece()));
			}
			// 目标托运单运单数
			nowModel.setShipbillNumber(nowModel.getShipbillNumber() + 1);

			// 目标托运单客户数
			if (!customerList.contains(tmsLoadingBillDetailModel.getConsigneeName())) {
				nowModel.setCustomerNumber(nowModel.getCustomerNumber() + 1);
			}

			// 目标托运单站点数
			if (!siteList.contains(tmsLoadingBillDetailModel.getConsigneeAddress())) {
				nowModel.setSiteNumber(nowModel.getSiteNumber() + 1);
			}

			// 修改明细内容
			Map<String, Object> map = Maps.newHashMap();
			map.put("updateperson", user.getNickname());
			map.put("updatetime", date);
			map.put("loadingBillId", trailerMobileDetailVO.getNowLoadingBillId());
			map.put("loadingBillNo", trailerMobileDetailVO.getNowLoadingBillId());
			map.put("shippingOrder", index);

			tmsLoadingBillDetailMapper.updateMapById(tmsLoadingBillDetailModel.getId(), map, TmsLoadingBillDetailModel.class);

			ShipbillOperateLogSaveVO shipbillOperateLogSaveVO = new ShipbillOperateLogSaveVO();
			ShipbillNodeTrackingSaveVO shipbillNodeTrackingSaveVO = new ShipbillNodeTrackingSaveVO();
			if (user.getUserType().equals(BussinessConstant.USER_TYPE_ZY)) {
				shipbillOperateLogSaveVO.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH);
				shipbillOperateLogSaveVO.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH);
				shipbillNodeTrackingSaveVO.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH);
			} else if (user.getUserType().equals(BussinessConstant.USER_TYPE_CYS)) {
				shipbillOperateLogSaveVO.setOldStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED);
				shipbillOperateLogSaveVO.setNewStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED);
				shipbillNodeTrackingSaveVO.setStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED);
			}
			// 运单操作日志保存
			shipbillOperateLogSaveVO.setShipbillId(tmsLoadingBillDetailModel.getShipbillId());
			shipbillOperateLogSaveVO.setShipbillNo(tmsLoadingBillDetailModel.getShipbillNo());
			shipbillOperateLogSaveVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_NODE_STATUSNAME_MOVE_TY + trailerMobileDetailVO.getNowLoadingBillId());
			shipbillOperateLogService.addShipbillOperateLogData(shipbillOperateLogSaveVO);

			// 运单节点保存
			StringBuffer nodeEvent = new StringBuffer(DataDictionaryConstant.SHIPBILL_NODE_STATUSNAME_MOVE_TY + trailerMobileDetailVO.getNowLoadingBillId());
			nodeEvent.append(" ");
			if (DataDictionaryConstant.LINE_CARRIER_TYPE_CYF == nowModel.getCarrierType()) {
				nodeEvent.append(nowModel.getCarrierName());
			} else {
				nodeEvent.append(ToolKits.isEmpty(nowModel.getDriverName()) ? "" : nowModel.getDriverName() + " ");
				nodeEvent.append(ToolKits.isEmpty(nowModel.getDeliverymanName()) ? "" : nowModel.getDeliverymanName() + " ");
				nodeEvent.append(ToolKits.isEmpty(nowModel.getVehiclePlateNumber()) ? "" : nowModel.getVehiclePlateNumber() + " ");
			}
			shipbillNodeTrackingSaveVO.setShipbillId(tmsLoadingBillDetailModel.getShipbillId());
			shipbillNodeTrackingSaveVO.setShipbillNo(tmsLoadingBillDetailModel.getShipbillNo());
			shipbillNodeTrackingSaveVO.setNodeEvent(nodeEvent.toString());
			shipbillNodeTrackingService.addShipbillNodeTrackingData(shipbillNodeTrackingSaveVO);
		}

		// 原托运单计算装载率
		if (ToolKits.isNotEmpty(originalModel.getVehicleId())) {
			Map<String, String> map = this.calculateLoadingRate(originalModel.getVehicleId(), originalModel.getTotalWeight(), originalModel.getTotalVolume());
			originalModel.setVolumeLoadingRate(map.get("volume"));
			originalModel.setWeightLoadingRate(map.get("weight"));
		}

		// 目标托运单计算装载率
		if (ToolKits.isNotEmpty(nowModel.getVehicleId())) {
			Map<String, String> map = this.calculateLoadingRate(nowModel.getVehicleId(), nowModel.getTotalWeight(), nowModel.getTotalVolume());
			nowModel.setVolumeLoadingRate(map.get("volume"));
			nowModel.setWeightLoadingRate(map.get("weight"));
		}

		// 修改汇总表
		tmsLoadingBillHeaderMapper.update(originalModel);
		tmsLoadingBillHeaderMapper.update(nowModel);
	}

	/**
	 * 已托运配载商品查询
	 *
	 * @param trailerItemDetailVO
	 * @return
	 */
	@SuppressWarnings("resource")
	@Override
	public Page<TrailerItemPageDTO> itemDetailTrailerData(TrailerItemDetailVO trailerItemDetailVO) {
		ToolKits.isParamNull(trailerItemDetailVO.getLoadingBillId(), "托运单ID不为空");
		ToolKits.isParamNull(trailerItemDetailVO.getPageNum(), "当前页码不为空");
		ToolKits.isParamNull(trailerItemDetailVO.getPageSize(), "每页条数不为空");

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

		// 数据字典翻译数据集合
		List<Map<String, Object>> data1 = Lists.newArrayList();
		List<Map<String, Object>> data2 = Lists.newArrayList();

		// 包装类型
		RestMessage<List<Map<String, Object>>> restMessage1 = maindataTmsResource.getDropDownById(DataDictionaryConstant.PACK_TYPE, null, null, null);
		if (!restMessage1.isSuccess()) {
			throw new RuntimeException("订单类型翻译失败!");
		} else {
			data1 = restMessage1.getData();
		}
		// 货物温层
		RestMessage<List<Map<String, Object>>> restMessage2 = maindataTmsResource.getDropDownById(DataDictionaryConstant.CARGO_THERMOSPHERE, null, null, null);
		if (!restMessage2.isSuccess()) {
			throw new RuntimeException("货物温层翻译失败!");
		} else {
			data2 = restMessage2.getData();
		}

		Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
		Restriction r1 = Restrictions.eq("loadingBillId", trailerItemDetailVO.getLoadingBillId());
		Restriction r2 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
		criteria.setRestriction(Restrictions.and(r1, r2));

		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteria);
		List<String> shipbillIds = tmsLoadingBillDetailModels.stream().filter(o -> ToolKits.isNotEmpty(o.getShipbillId())).map(TmsLoadingBillDetailModel::getShipbillId).distinct().collect(Collectors.toList());

		// 根据运单ID查询明细数据
		criteria = Criteria.forClass(TmsShipbillDetailModel.class);
		r1 = Restrictions.in("shipbillId", shipbillIds.toArray());
		criteria.setRestriction(Restrictions.and(r1, r2));

		PageUtils.startPage(trailerItemDetailVO.getPageNum(), trailerItemDetailVO.getPageSize());
		List<TmsShipbillDetailModel> tmsShipbillDetailModels = tmsShipbillDetailMapper.findByCriteria(criteria);

		// 返回数据集
		List<TrailerItemPageDTO> list = Lists.newArrayList();

		for (TmsShipbillDetailModel tmsShipbillDetailModel : tmsShipbillDetailModels) {
			TrailerItemPageDTO dto = new TrailerItemPageDTO();
			BeanUtils.copyProperties(tmsShipbillDetailModel, dto);

			// 数据字典翻译
			dto.setPackTypeName(PublicMethods.change(data1, String.valueOf(dto.getPackType())));
			dto.setCargoThermosphereName(PublicMethods.change(data2, String.valueOf(dto.getCargoThermosphere())));

			list.add(dto);
		}

		// 分页重组
		Page<TrailerItemPageDTO> page = PageUtils.getPage(list);
		if (tmsShipbillDetailModels instanceof com.github.pagehelper.Page) {
			com.github.pagehelper.Page<TmsShipbillDetailModel> p0 = (com.github.pagehelper.Page<TmsShipbillDetailModel>) tmsShipbillDetailModels;
			page.setPageCount(p0.getPages());
			page.setPageNum(p0.getPageNum());
			page.setPageSize(p0.getPageSize());
			page.setTotalCount(p0.getTotal());
			page.setStartRow(p0.getStartRow());
			page.setEndRow(p0.getEndRow());
		}

		return page;
	}

	/**
	 * 已托运配载包裹查询
	 *
	 * @param trailerPackageDetailVO
	 * @return
	 */
	@SuppressWarnings("resource")
	@Override
	public Page<TrailerPackagePageDTO> packageDetailTrailerData(TrailerPackageDetailVO trailerPackageDetailVO) {
		ToolKits.isParamNull(trailerPackageDetailVO.getLoadingBillId(), "托运单ID不为空");
		ToolKits.isParamNull(trailerPackageDetailVO.getPageNum(), "当前页码不为空");
		ToolKits.isParamNull(trailerPackageDetailVO.getPageSize(), "每页条数不为空");

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

		// 数据字典翻译数据集合
		List<Map<String, Object>> data1 = Lists.newArrayList();

		// 包裹类型
		RestMessage<List<Map<String, Object>>> restMessage1 = maindataTmsResource.getDropDownById(DataDictionaryConstant.PACKAGE_TYPE, null, null, null);
		if (!restMessage1.isSuccess()) {
			throw new RuntimeException("包裹类型翻译失败!");
		} else {
			data1 = restMessage1.getData();
		}

		Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
		Restriction r1 = Restrictions.eq("loadingBillId", trailerPackageDetailVO.getLoadingBillId());
		Restriction r2 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
		criteria.setRestriction(Restrictions.and(r1, r2));
		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteria);
		List<String> shipbillIds = tmsLoadingBillDetailModels.stream().filter(o -> ToolKits.isNotEmpty(o.getShipbillId())).map(TmsLoadingBillDetailModel::getShipbillId).distinct().collect(Collectors.toList());

		// 根据运单ID查询明细数据
		criteria = Criteria.forClass(TmsShipbillPackageModel.class);
		r1 = Restrictions.in("shipbillId", shipbillIds.toArray());
		criteria.setRestriction(Restrictions.and(r1, r2));

		PageUtils.startPage(trailerPackageDetailVO.getPageNum(), trailerPackageDetailVO.getPageSize());
		List<TmsShipbillPackageModel> tmsShipbillPackageModels = tmsShipbillPackageMapper.findByCriteria(criteria);

		// 返回数据集
		List<TrailerPackagePageDTO> list = Lists.newArrayList();

		for (TmsShipbillPackageModel tmsShipbillPackageModel : tmsShipbillPackageModels) {
			TrailerPackagePageDTO dto = new TrailerPackagePageDTO();
			BeanUtils.copyProperties(tmsShipbillPackageModel, dto);

			// 数据字典翻译
			dto.setPackageTypeName(PublicMethods.change(data1, String.valueOf(dto.getPackageType())));

			// 设备类型翻译
			if (ToolKits.isNotEmpty(tmsShipbillPackageModel.getDeviceId())) {
				RestMessage<DeviceByOneDTO> deviceByOneDTORestMessage = maindataTmsResource.deviceGetOne(tmsShipbillPackageModel.getDeviceId());
				if (!deviceByOneDTORestMessage.isSuccess()) {
					throw new RuntimeException("获取设备失败!");
				}
				DeviceByOneDTO data = deviceByOneDTORestMessage.getData();
				ToolKits.isParamNull(data, "获取设备为空");

				dto.setDeviceTypeName(data.getTypeName());
			}

			list.add(dto);
		}

		// 分页重组
		Page<TrailerPackagePageDTO> page = PageUtils.getPage(list);
		if (tmsShipbillPackageModels instanceof com.github.pagehelper.Page) {
			com.github.pagehelper.Page<TmsShipbillPackageModel> p0 = (com.github.pagehelper.Page<TmsShipbillPackageModel>) tmsShipbillPackageModels;
			page.setPageCount(p0.getPages());
			page.setPageNum(p0.getPageNum());
			page.setPageSize(p0.getPageSize());
			page.setTotalCount(p0.getTotal());
			page.setStartRow(p0.getStartRow());
			page.setEndRow(p0.getEndRow());
		}

		return page;
	}

	/**
	 * 已托运修改
	 *
	 * @param trailerUpdateVO
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void updateTrailerData(TrailerUpdateVO trailerUpdateVO) {
		ToolKits.isParamNull(trailerUpdateVO.getLoadingBillId(), "托运单ID不为空");

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

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

		// 修改托运单
		TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel = tmsLoadingBillHeaderMapper.findById(trailerUpdateVO.getLoadingBillId(), TmsLoadingBillHeaderModel.class);
		ToolKits.isParamNull(tmsLoadingBillHeaderModel, "托运单ID[" + trailerUpdateVO.getLoadingBillId() + "]有误,查询为空!");

		if (tmsLoadingBillHeaderModel.getStatus().intValue() > DataDictionaryConstant.LOADING_BILL_STATUS_WSH.intValue()) {
			throw new RuntimeException("托运单[" + trailerUpdateVO.getLoadingBillId() + "]已审核,不能撤销!");
		}

		BeanUtils.copyProperties(trailerUpdateVO, tmsLoadingBillHeaderModel);
		tmsLoadingBillHeaderModel.setUpdatetime(date);
		tmsLoadingBillHeaderModel.setUpdateperson(user.getNickname());

		tmsLoadingBillHeaderMapper.update(tmsLoadingBillHeaderModel);
	}

	/**
	 * 已托运修改—运单添加
	 *
	 * @param trailerUpdateAddDetailVO
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public List<ShipbillHeaderPageDTO> updateAddDetailTrailerData(TrailerUpdateAddDetailVO trailerUpdateAddDetailVO) {
		ToolKits.isParamNull(trailerUpdateAddDetailVO.getLoadingBillId(), "托运单ID不为空");
		ToolKits.isParamNull(trailerUpdateAddDetailVO.getShipbillIds(), "运单ID不为空");

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

		// 数据字典翻译数据集合
		List<Map<String, Object>> data1 = Lists.newArrayList();
		List<Map<String, Object>> data2 = Lists.newArrayList();
		List<Map<String, Object>> data3 = Lists.newArrayList();
		List<Map<String, Object>> data4 = Lists.newArrayList();
		List<Map<String, Object>> data5 = Lists.newArrayList();
		List<Map<String, Object>> data6 = Lists.newArrayList();
		List<Map<String, Object>> data7 = Lists.newArrayList();
		List<Map<String, Object>> data8 = Lists.newArrayList();
		List<SignconfigPopDTO> data9 = Lists.newArrayList();

		// 订单类型
		RestMessage<List<Map<String, Object>>> restMessage1 = maindataTmsResource.getDropDownById(DataDictionaryConstant.ORDER_TYPE, null, null, null);
		if (!restMessage1.isSuccess()) {
			throw new RuntimeException("订单类型翻译失败!");
		} else {
			data1 = restMessage1.getData();
		}
		// 订单业务类型
		RestMessage<List<Map<String, Object>>> restMessage2 = maindataTmsResource.getDropDownById(DataDictionaryConstant.ORDER_BUSINESS_TYPE, null, null, null);
		if (!restMessage2.isSuccess()) {
			throw new RuntimeException("订单业务类型翻译失败!");
		} else {
			data2 = restMessage2.getData();
		}
		// 配送方式
		RestMessage<List<Map<String, Object>>> restMessage3 = maindataTmsResource.getDropDownById(DataDictionaryConstant.DELIVERY_METHOD_TYPE, null, null, null);
		if (!restMessage3.isSuccess()) {
			throw new RuntimeException("配送方式翻译失败!");
		} else {
			data3 = restMessage3.getData();
		}
		// 运输类型(运输模式)
		RestMessage<List<Map<String, Object>>> restMessage4 = maindataTmsResource.getDropDownById(DataDictionaryConstant.TRANSPORT_TYPE, null, null, null);
		if (!restMessage4.isSuccess()) {
			throw new RuntimeException("运输类型(运输模式)翻译失败!");
		} else {
			data4 = restMessage4.getData();
		}
		// 温度要求
		RestMessage<List<Map<String, Object>>> restMessage5 = maindataTmsResource.getDropDownById(DataDictionaryConstant.TEMPERATURE_REQUIREMENT, null, null, null);
		if (!restMessage5.isSuccess()) {
			throw new RuntimeException("温度要求翻译失败!");
		} else {
			data5 = restMessage5.getData();
		}
		// 发货方类型
		RestMessage<List<Map<String, Object>>> restMessage6 = maindataTmsResource.getDropDownById(DataDictionaryConstant.SHIPPER_TYPE, null, null, null);
		if (!restMessage6.isSuccess()) {
			throw new RuntimeException("发货方类型翻译失败!");
		} else {
			data6 = restMessage6.getData();
		}
		// 收货方类型
		RestMessage<List<Map<String, Object>>> restMessage7 = maindataTmsResource.getDropDownById(DataDictionaryConstant.CONSIGNEE_TYPE, null, null, null);
		if (!restMessage7.isSuccess()) {
			throw new RuntimeException("收货方类型翻译失败!");
		} else {
			data7 = restMessage7.getData();
		}

		// 运单状态
		RestMessage<List<Map<String, Object>>> restMessage8 = maindataTmsResource.getDropDownById(DataDictionaryConstant.SHIPBILL_STATUS, null, null, null);
		if (!restMessage8.isSuccess()) {
			throw new RuntimeException("运单状态翻译失败!");
		} else {
			data8 = restMessage8.getData();
		}

		// 标记配置
		SignconfigPopVO signconfigPopVO = new SignconfigPopVO();
		RestMessage<List<SignconfigPopDTO>> restMessage9 = maindataTmsResource.getSignConfig(signconfigPopVO);
		if (!restMessage9.isSuccess()) {
			throw new RuntimeException("标记配置查询失败!");
		} else {
			data9 = restMessage9.getData();
		}

		TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel = tmsLoadingBillHeaderMapper.findById(trailerUpdateAddDetailVO.getLoadingBillId(), TmsLoadingBillHeaderModel.class);
		ToolKits.isParamNull(tmsLoadingBillHeaderModel, "托运单ID[" + trailerUpdateAddDetailVO.getLoadingBillId() + "]有误");

		List<TmsShipbillHeaderModel> tmsShipbillHeaderModels = tmsShipbillHeaderMapper.findByIds(TmsShipbillHeaderModel.class, trailerUpdateAddDetailVO.getShipbillIds().toArray(), null);

		Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
		Restriction r1 = Restrictions.eq("loadingBillId", trailerUpdateAddDetailVO.getLoadingBillId());
		Restriction r2 = Restrictions.in("shipbillId", trailerUpdateAddDetailVO.getShipbillIds().toArray());
		Restriction r3 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
		criteria.setRestriction(Restrictions.and(r1, r2, r3));
		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModelList = tmsLoadingBillDetailMapper.findByCriteria(criteria);
		if (ToolKits.isNotEmpty(tmsLoadingBillDetailModelList)) {
			throw new PrologException("运单ID[" + tmsLoadingBillDetailModelList.stream().map(TmsLoadingBillDetailModel::getShipbillId).collect(Collectors.joining(",")) + "]已被添加");
		}

		criteria.setRestriction(Restrictions.and(r1, r2));
		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteria);
		List<Integer> indexList = tmsLoadingBillDetailModels.stream().filter(o -> ToolKits.isNotEmpty(o.getShippingOrder())).map(TmsLoadingBillDetailModel::getShippingOrder).collect(Collectors.toList());
		Integer index = null;
		if (ToolKits.isEmpty(indexList)) {
			index = 1;
		} else {
			index = Collections.max(indexList);
		}

		// 客户数
		List<String> customerList = tmsLoadingBillDetailModels.stream().filter(o -> ToolKits.isNotEmpty(o.getConsigneeName())).map(TmsLoadingBillDetailModel::getConsigneeName).distinct().collect(Collectors.toList());

		// 站点数
		List<String> siteList = tmsLoadingBillDetailModels.stream().filter(o -> ToolKits.isNotEmpty(o.getConsigneeAddress())).map(TmsLoadingBillDetailModel::getConsigneeAddress).distinct().collect(Collectors.toList());

		// 明细保存集合
		List<TmsLoadingBillDetailModel> saveList = Lists.newArrayList();

		List<ShipbillHeaderPageDTO> dtoList = Lists.newArrayList();
		for (TmsShipbillHeaderModel tmsShipbillHeaderModel : tmsShipbillHeaderModels) {
			ShipbillHeaderPageDTO dto = new ShipbillHeaderPageDTO();
			BeanUtils.copyProperties(tmsShipbillHeaderModel, dto);

			dtoList.add(dto);

			// 收货方位置(经纬度判断)
			if (ToolKits.isNotEmpty(tmsShipbillHeaderModel.getConsigneeLongitude()) && ToolKits.isNotEmpty(tmsShipbillHeaderModel.getConsigneeLatitude())) {
				dto.setConsigneePositioning(StatusConstant.POSITIONING_YDW);
			} else {
				dto.setConsigneePositioning(StatusConstant.POSITIONING_WDW);
			}
			// 发货方位置(经纬度判断)
			if (ToolKits.isNotEmpty(tmsShipbillHeaderModel.getShipperLongitude()) && ToolKits.isNotEmpty(tmsShipbillHeaderModel.getShipperLatitude())) {
				dto.setShipperPositioning(StatusConstant.POSITIONING_YDW);
			} else {
				dto.setShipperPositioning(StatusConstant.POSITIONING_WDW);
			}

			// 类型翻译
			dto.setOrderTypeName(PublicMethods.change(data1, String.valueOf(dto.getOrderType())));
			dto.setOrderBusinessTypeName(PublicMethods.change(data2, String.valueOf(dto.getOrderBusinessType())));
			dto.setDeliveryMethodTypeName(PublicMethods.change(data3, String.valueOf(dto.getDeliveryMethodType())));
			dto.setTransportTypeName(PublicMethods.change(data4, String.valueOf(dto.getTransportType())));
			dto.setTemperatureRequirementName(PublicMethods.change(data5, String.valueOf(dto.getTemperatureRequirement())));
			dto.setShipperTypeName(PublicMethods.change(data6, String.valueOf(dto.getShipperType())));
			dto.setConsigneeTypeName(PublicMethods.change(data7, String.valueOf(dto.getConsigneeType())));
			dto.setStatusName(PublicMethods.change(data8, String.valueOf(dto.getStatus())));

			// 获取背景颜色和字体颜色
			Signconfig: for (SignconfigPopDTO signconfigPopDTO : data9) {
				// 标记类型匹配
				switch (signconfigPopDTO.getType()) {
				case DataDictionaryConstant.SIGNCONFIG_TYPE_DDLX: // 订单类型
					if (ToolKits.isNotEmpty(signconfigPopDTO.getMatching())) {
						// 判断是否匹配
						if (PublicMethods.compare(signconfigPopDTO.getMatching(), ToolKits.isNotEmpty(signconfigPopDTO.getStoredValue()) ? signconfigPopDTO.getStoredValue() : "", ToolKits.isNotEmpty(dto.getOrderTypeName()) ? dto.getOrderTypeName() : "")) {
							dto.setBackground(ToolKits.isEmpty(signconfigPopDTO.getBackground()) ? "" : signconfigPopDTO.getBackground());
							dto.setColor(ToolKits.isEmpty(signconfigPopDTO.getColor()) ? "" : signconfigPopDTO.getColor());

							// 返回前端所需标记ID
							dto.setSignConfigId(signconfigPopDTO.getId());

							// 匹配上结束循环
							break Signconfig;
						}
					}
					break;
				case DataDictionaryConstant.SIGNCONFIG_TYPE_YWLX: // 业务类型
					if (ToolKits.isNotEmpty(signconfigPopDTO.getMatching())) {
						if (PublicMethods.compare(signconfigPopDTO.getMatching(), ToolKits.isNotEmpty(signconfigPopDTO.getStoredValue()) ? signconfigPopDTO.getStoredValue() : "", ToolKits.isNotEmpty(dto.getOrderBusinessTypeName()) ? dto.getOrderBusinessTypeName() : "")) {
							dto.setBackground(ToolKits.isEmpty(signconfigPopDTO.getBackground()) ? "" : signconfigPopDTO.getBackground());
							dto.setColor(ToolKits.isEmpty(signconfigPopDTO.getColor()) ? "" : signconfigPopDTO.getColor());

							// 返回前端所需标记ID
							dto.setSignConfigId(signconfigPopDTO.getId());

							break Signconfig;
						}
					}
					break;
				case DataDictionaryConstant.SIGNCONFIG_TYPE_WDYQ: // 配送方式
					if (ToolKits.isNotEmpty(signconfigPopDTO.getMatching())) {
						if (PublicMethods.compare(signconfigPopDTO.getMatching(), ToolKits.isNotEmpty(signconfigPopDTO.getStoredValue()) ? signconfigPopDTO.getStoredValue() : "", ToolKits.isNotEmpty(dto.getTemperatureRequirementName()) ? dto.getTemperatureRequirementName() : "")) {
							dto.setBackground(ToolKits.isEmpty(signconfigPopDTO.getBackground()) ? "" : signconfigPopDTO.getBackground());
							dto.setColor(ToolKits.isEmpty(signconfigPopDTO.getColor()) ? "" : signconfigPopDTO.getColor());

							// 返回前端所需标记ID
							dto.setSignConfigId(signconfigPopDTO.getId());

							break Signconfig;
						}
					}
					break;
				case DataDictionaryConstant.SIGNCONFIG_TYPE_PSFS: // 订单备注
					if (ToolKits.isNotEmpty(signconfigPopDTO.getMatching())) {
						if (PublicMethods.compare(signconfigPopDTO.getMatching(), ToolKits.isNotEmpty(signconfigPopDTO.getStoredValue()) ? signconfigPopDTO.getStoredValue() : "", ToolKits.isNotEmpty(dto.getDeliveryMethodTypeName()) ? dto.getDeliveryMethodTypeName() : "")) {
							dto.setBackground(ToolKits.isEmpty(signconfigPopDTO.getBackground()) ? "" : signconfigPopDTO.getBackground());
							dto.setColor(ToolKits.isEmpty(signconfigPopDTO.getColor()) ? "" : signconfigPopDTO.getColor());

							// 返回前端所需标记ID
							dto.setSignConfigId(signconfigPopDTO.getId());

							break Signconfig;
						}
					}
					break;
				case DataDictionaryConstant.SIGNCONFIG_TYPE_DDBZ:
					if (ToolKits.isNotEmpty(signconfigPopDTO.getMatching())) {
						if (PublicMethods.compare(signconfigPopDTO.getMatching(), ToolKits.isNotEmpty(signconfigPopDTO.getStoredValue()) ? signconfigPopDTO.getStoredValue() : "", ToolKits.isNotEmpty(dto.getMemo()) ? dto.getMemo() : "")) {
							dto.setBackground(ToolKits.isEmpty(signconfigPopDTO.getBackground()) ? "" : signconfigPopDTO.getBackground());
							dto.setColor(ToolKits.isEmpty(signconfigPopDTO.getColor()) ? "" : signconfigPopDTO.getColor());

							// 返回前端所需标记ID
							dto.setSignConfigId(signconfigPopDTO.getId());

							break Signconfig;
						}
					}
					break;
				}
			}

			ShipbillOperateLogSaveVO shipbillOperateLogSaveVO = new ShipbillOperateLogSaveVO();
			ShipbillNodeTrackingSaveVO shipbillNodeTrackingSaveVO = new ShipbillNodeTrackingSaveVO();

			if (user.getUserType().equals(BussinessConstant.USER_TYPE_ZY)) {
				// 修改运单状态
				tmsShipbillHeaderModel.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH);

				shipbillOperateLogSaveVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_DIS_ADD + trailerUpdateAddDetailVO.getLoadingBillId());
				shipbillOperateLogSaveVO.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_REVIEW);
				shipbillOperateLogSaveVO.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH);

				shipbillNodeTrackingSaveVO.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH);
			} else if (user.getUserType().equals(BussinessConstant.USER_TYPE_CYS)) {
				// 修改运单状态
				tmsShipbillHeaderModel.setCarrierShipbillStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED);

				shipbillOperateLogSaveVO.setOperateEvent(DataDictionaryConstant.CARRIER_SHIPBILL_NODE_STATUSNAME_DI_ADD + trailerUpdateAddDetailVO.getLoadingBillId());
				shipbillOperateLogSaveVO.setOldStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_AUDITED);
				shipbillOperateLogSaveVO.setNewStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED);

				shipbillNodeTrackingSaveVO.setStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED);
			}
			ShipbillFitBusinessFlowDTO flowData = shipbillMatchBusinessFlow(tmsShipbillHeaderModel);
			tmsShipbillHeaderModel.setCarrierFlowConfig(flowData.getFlowConfig());
			tmsShipbillHeaderModel.setCarrierId(tmsLoadingBillHeaderModel.getCarrierId());
			tmsShipbillHeaderModel.setCarrierCode(tmsLoadingBillHeaderModel.getCarrierCode());
			tmsShipbillHeaderModel.setCarrierName(tmsLoadingBillHeaderModel.getCarrierName());
			tmsShipbillHeaderModel.setCarrierType(tmsLoadingBillHeaderModel.getCarrierType());
			tmsShipbillHeaderMapper.update(tmsShipbillHeaderModel);

			// 配送顺序
			index++;

			TmsLoadingBillDetailModel tmsLoadingBillDetailModel = new TmsLoadingBillDetailModel();
			BeanUtils.copyProperties(tmsShipbillHeaderModel, tmsLoadingBillDetailModel);

			// 获取托运单明细ID
			RestMessage<String> restMessage = maindataTmsResource.getCodeNumberByCode(SeriaNnumberConstant.TMS_LOADING_BILL_DETAIL_ID, "L");
			if (!restMessage.isSuccess()) {
				throw new RuntimeException("生成托运单明细ID失败");
			}
			String id = restMessage.getData();
			tmsLoadingBillDetailModel.setId(id);
			tmsLoadingBillDetailModel.setShippingOrder(index);
			tmsLoadingBillDetailModel.setLoadingBillId(trailerUpdateAddDetailVO.getLoadingBillId());
			tmsLoadingBillDetailModel.setLoadingBillNo(trailerUpdateAddDetailVO.getLoadingBillId());

			// 重量体积件数
			tmsLoadingBillHeaderModel.setTotalPcs(tmsLoadingBillHeaderModel.getTotalPcs().add(tmsLoadingBillDetailModel.getTotalPcs()));
			tmsLoadingBillHeaderModel.setTotalVolume(tmsLoadingBillHeaderModel.getTotalVolume().add(tmsLoadingBillDetailModel.getTotalVolume()));
			tmsLoadingBillHeaderModel.setTotalWeight(tmsLoadingBillHeaderModel.getTotalWeight().add(tmsLoadingBillDetailModel.getTotalWeight()));

			// 实际重量体积件数
			tmsLoadingBillHeaderModel.setActualTotalPcs(tmsLoadingBillHeaderModel.getActualTotalPcs().add(tmsLoadingBillDetailModel.getActualTotalPcs()));
			tmsLoadingBillHeaderModel.setActualTotalVolume(tmsLoadingBillHeaderModel.getActualTotalVolume().add(tmsLoadingBillDetailModel.getActualTotalVolume()));
			tmsLoadingBillHeaderModel.setActualTotalWeight(tmsLoadingBillHeaderModel.getActualTotalWeight().add(tmsLoadingBillDetailModel.getActualTotalWeight()));

			// 整件数拼箱数
			if (ToolKits.isNotEmpty(tmsLoadingBillDetailModel.getPackageWholePiece())) {
				tmsLoadingBillHeaderModel.setTotalWholePiece(tmsLoadingBillHeaderModel.getTotalWholePiece().subtract(tmsLoadingBillDetailModel.getPackageWholePiece()));
			}
			if (ToolKits.isNotEmpty(tmsLoadingBillDetailModel.getPackageLclPiece())) {
				tmsLoadingBillHeaderModel.setTotalLclPiece(tmsLoadingBillHeaderModel.getTotalLclPiece().subtract(tmsLoadingBillDetailModel.getPackageLclPiece()));
			}
			// 运单数
			tmsLoadingBillHeaderModel.setShipbillNumber(tmsLoadingBillHeaderModel.getShipbillNumber() + 1);

			// 客户数
			if (!customerList.contains(tmsShipbillHeaderModel.getConsigneeName())) {
				tmsLoadingBillHeaderModel.setCustomerNumber(tmsLoadingBillHeaderModel.getCustomerNumber() + 1);
			}

			// 站点数
			if (!siteList.contains(tmsShipbillHeaderModel.getConsigneeAddress())) {
				tmsLoadingBillHeaderModel.setSiteNumber(tmsLoadingBillHeaderModel.getSiteNumber() + 1);
			}

			// 运单操作日志保存

			shipbillOperateLogSaveVO.setShipbillId(tmsLoadingBillDetailModel.getShipbillId());
			shipbillOperateLogSaveVO.setShipbillNo(tmsLoadingBillDetailModel.getShipbillNo());

			shipbillOperateLogService.addShipbillOperateLogData(shipbillOperateLogSaveVO);

			StringBuffer nodeEvent = new StringBuffer();
			nodeEvent.append(tmsLoadingBillHeaderModel.getDriverName() + " ");
			nodeEvent.append(tmsLoadingBillHeaderModel.getDeliverymanName() + " ");
			nodeEvent.append(tmsLoadingBillHeaderModel.getVehiclePlateNumber() + " ");
			// 运单节点保存
			shipbillNodeTrackingSaveVO.setShipbillId(tmsShipbillHeaderModel.getShipbillId());
			shipbillNodeTrackingSaveVO.setShipbillNo(tmsShipbillHeaderModel.getShipbillNo());
			shipbillNodeTrackingSaveVO.setNodeEvent(nodeEvent.toString());
			shipbillNodeTrackingService.addShipbillNodeTrackingData(shipbillNodeTrackingSaveVO);

			tmsLoadingBillDetailModel.setCarrierFlowConfig(tmsShipbillHeaderModel.getCarrierFlowConfig());
			tmsLoadingBillDetailModel.setFlowConfig(tmsShipbillHeaderModel.getFlowConfig());
			saveList.add(tmsLoadingBillDetailModel);
		}

		// 计算装载率
		if (ToolKits.isNotEmpty(tmsLoadingBillHeaderModel.getVehicleId())) {
			Map<String, String> map = this.calculateLoadingRate(tmsLoadingBillHeaderModel.getVehicleId(), tmsLoadingBillHeaderModel.getTotalWeight(), tmsLoadingBillHeaderModel.getTotalVolume());
			tmsLoadingBillHeaderModel.setVolumeLoadingRate(map.get("volume"));
			tmsLoadingBillHeaderModel.setWeightLoadingRate(map.get("weight"));
		}

		// 批量添加托运单明细
		tmsLoadingBillDetailMapper.saveBatch(saveList);
		// 修改托运单
		tmsLoadingBillHeaderMapper.update(tmsLoadingBillHeaderModel);

		return dtoList;
	}

	/**
	 * 已托运修改—运单剔除
	 *
	 * @param trailerUpdateDeleteDetailVO
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void updateDeleteDetailTrailerData(TrailerUpdateDeleteDetailVO trailerUpdateDeleteDetailVO) {
		ToolKits.isParamNull(trailerUpdateDeleteDetailVO.getLoadingBillId(), "托运单ID不为空");
		ToolKits.isParamNull(trailerUpdateDeleteDetailVO.getShipbillIds(), "运单ID不为空");

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

		TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel = tmsLoadingBillHeaderMapper.findById(trailerUpdateDeleteDetailVO.getLoadingBillId(), TmsLoadingBillHeaderModel.class);
		if (ToolKits.isEmpty(tmsLoadingBillHeaderModel)) {
			throw new PrologException(StrUtil.format("托运单{}不存在",trailerUpdateDeleteDetailVO.getLoadingBillId()));
		}
		if (ToolKits.isEmpty(tmsLoadingBillHeaderModel.getStatus()) || DataDictionaryConstant.LOADING_BILL_STATUS_ZC_CONFIRM.intValue() < tmsLoadingBillHeaderModel.getStatus().intValue()  ) {
			throw new PrologException(StrUtil.format("托运单{}已启运，请不要剔除运单", trailerUpdateDeleteDetailVO.getLoadingBillId()));
		}

		Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
		Restriction r1 = Restrictions.in("shipbillId", trailerUpdateDeleteDetailVO.getShipbillIds().toArray());
		Restriction r3 = Restrictions.eq(TmsLoadingBillDetailModel::getLoadingBillId, trailerUpdateDeleteDetailVO.getLoadingBillId());
		Restriction r2 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
		criteria.setRestriction(Restrictions.and(r1, r2,r3));
		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteria);

		// 修改配送顺序以及总重量体积件数等数据
		for (TmsLoadingBillDetailModel tmsLoadingBillDetailModel : tmsLoadingBillDetailModels) {

			// 修改配送顺序
			r1 = Restrictions.eq("loadingBillId", tmsLoadingBillDetailModel.getLoadingBillId());
			r3 = Restrictions.ne("shipbillId", tmsLoadingBillDetailModel.getShipbillId());
			criteria.setRestriction(Restrictions.and(r1, r3));
			List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModelList = tmsLoadingBillDetailMapper.findByCriteria(criteria);
			for (TmsLoadingBillDetailModel loadingBillDetailModel : tmsLoadingBillDetailModelList) {
				if (ToolKits.isEmpty(loadingBillDetailModel.getShippingOrder()) || ToolKits.isEmpty(tmsLoadingBillDetailModel.getShippingOrder())){
					continue;
				}
				if (loadingBillDetailModel.getShippingOrder() > tmsLoadingBillDetailModel.getShippingOrder()) {
					loadingBillDetailModel.setShippingOrder(loadingBillDetailModel.getShippingOrder() - 1);
				}
				tmsLoadingBillDetailMapper.update(loadingBillDetailModel);
			}

			/*// 客户数
			Integer customerNumber = tmsLoadingBillDetailModelList.stream().filter(o -> ToolKits.isNotEmpty(o.getConsigneeName())).map(TmsLoadingBillDetailModel::getConsigneeName).distinct().collect(Collectors.toList()).size();

			// 站点数
			Integer siteNumber = tmsLoadingBillDetailModelList.stream().filter(o -> ToolKits.isNotEmpty(o.getConsigneeAddress())).map(TmsLoadingBillDetailModel::getConsigneeAddress).distinct().collect(Collectors.toList()).size();

			// 重量体积件数
			tmsLoadingBillHeaderModel.setTotalPcs(tmsLoadingBillHeaderModel.getTotalPcs().subtract(tmsLoadingBillDetailModel.getTotalPcs()));
			tmsLoadingBillHeaderModel.setTotalVolume(tmsLoadingBillHeaderModel.getTotalVolume().subtract(tmsLoadingBillDetailModel.getTotalVolume()));
			tmsLoadingBillHeaderModel.setTotalWeight(tmsLoadingBillHeaderModel.getTotalWeight().subtract(tmsLoadingBillDetailModel.getTotalWeight()));

			// 实际重量体积件数
			tmsLoadingBillHeaderModel.setActualTotalPcs(tmsLoadingBillHeaderModel.getActualTotalPcs().subtract(tmsLoadingBillDetailModel.getActualTotalPcs()));
			tmsLoadingBillHeaderModel.setActualTotalVolume(tmsLoadingBillHeaderModel.getActualTotalVolume().subtract(tmsLoadingBillDetailModel.getActualTotalVolume()));
			tmsLoadingBillHeaderModel.setActualTotalWeight(tmsLoadingBillHeaderModel.getActualTotalWeight().subtract(tmsLoadingBillDetailModel.getActualTotalWeight()));

			// 整件数拼箱数
			if (ToolKits.isNotEmpty(tmsLoadingBillDetailModel.getPackageWholePiece())) {
				tmsLoadingBillHeaderModel.setTotalWholePiece(tmsLoadingBillHeaderModel.getTotalWholePiece().subtract(tmsLoadingBillDetailModel.getPackageWholePiece()));
			}
			if (ToolKits.isNotEmpty(tmsLoadingBillDetailModel.getPackageLclPiece())) {
				tmsLoadingBillHeaderModel.setTotalLclPiece(tmsLoadingBillHeaderModel.getTotalLclPiece().subtract(tmsLoadingBillDetailModel.getPackageLclPiece()));
			}
			// 运单数
			tmsLoadingBillHeaderModel.setShipbillNumber(tmsLoadingBillHeaderModel.getShipbillNumber() - 1);

			// 客户数
			tmsLoadingBillHeaderModel.setCustomerNumber(customerNumber);
			// 站点数
			tmsLoadingBillHeaderModel.setSiteNumber(siteNumber);*/

			// 删除明细内容
			tmsLoadingBillDetailMapper.deleteById(tmsLoadingBillDetailModel.getId(), TmsLoadingBillDetailModel.class);
			ShipbillOperateLogSaveVO shipbillOperateLogSaveVO = new ShipbillOperateLogSaveVO();
			ShipbillNodeTrackingSaveVO shipbillNodeTrackingSaveVO = new ShipbillNodeTrackingSaveVO();
			if (user.getUserType().equals(BussinessConstant.USER_TYPE_ZY)) {
				shipbillOperateLogSaveVO.setOperateEvent("从托运单" + tmsLoadingBillHeaderModel.getLoadingBillId() + "中剔除");
				shipbillOperateLogSaveVO.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH);
				shipbillOperateLogSaveVO.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_REVIEW);

				shipbillNodeTrackingSaveVO.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_REVIEW);
				shipbillNodeTrackingSaveVO.setNodeEvent("从托运单" + tmsLoadingBillHeaderModel.getLoadingBillId() + "中剔除");
			} else if (user.getUserType().equals(BussinessConstant.USER_TYPE_CYS)) {

				shipbillOperateLogSaveVO.setOperateEvent("从托运单" + tmsLoadingBillHeaderModel.getLoadingBillId() + "中剔除");
				shipbillOperateLogSaveVO.setOldStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED);
				shipbillOperateLogSaveVO.setNewStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_AUDITED);

				shipbillNodeTrackingSaveVO.setStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_AUDITED);
				shipbillNodeTrackingSaveVO.setNodeEvent("从托运单" + tmsLoadingBillHeaderModel.getLoadingBillId() + "中剔除");
			}

			// 运单操作日志保存
			shipbillOperateLogSaveVO.setShipbillId(tmsLoadingBillDetailModel.getShipbillId());
			shipbillOperateLogSaveVO.setShipbillNo(tmsLoadingBillDetailModel.getShipbillNo());
			shipbillOperateLogService.addShipbillOperateLogData(shipbillOperateLogSaveVO);

			// 运单节点保存
			shipbillNodeTrackingSaveVO.setShipbillId(tmsLoadingBillDetailModel.getShipbillId());
			shipbillNodeTrackingSaveVO.setShipbillNo(tmsLoadingBillDetailModel.getShipbillNo());
			shipbillNodeTrackingService.addShipbillNodeTrackingData(shipbillNodeTrackingSaveVO);
		}
		// 重新计算
		calculateLoadingData(tmsLoadingBillHeaderModel);

		// 计算装载率
		if (ToolKits.isNotEmpty(tmsLoadingBillHeaderModel.getVehicleId())) {
			Map<String, String> map = this.calculateLoadingRate(tmsLoadingBillHeaderModel.getVehicleId(), tmsLoadingBillHeaderModel.getTotalWeight(), tmsLoadingBillHeaderModel.getTotalVolume());
			tmsLoadingBillHeaderModel.setVolumeLoadingRate(map.get("volume"));
			tmsLoadingBillHeaderModel.setWeightLoadingRate(map.get("weight"));
		}

		// 修改汇总表
		tmsLoadingBillHeaderMapper.update(tmsLoadingBillHeaderModel);

		// 运单状态回退
		criteria = Criteria.forClass(TmsShipbillHeaderModel.class);
		r1 = Restrictions.in("shipbillId", trailerUpdateDeleteDetailVO.getShipbillIds().toArray());
		criteria.setRestriction(Restrictions.and(r1, r2));

		Map<String, Object> map = Maps.newHashMap();
		if (user.getUserType().equals(BussinessConstant.USER_TYPE_ZY)) {
			map.put("status", DataDictionaryConstant.SHIPBILL_STATUS_REVIEW);
		} else if (user.getUserType().equals(BussinessConstant.USER_TYPE_CYS)) {
			map.put("carrierShipbillStatus", DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_AUDITED);
		}

		tmsShipbillHeaderMapper.updateMapByCriteria(map, criteria);
	}

	/**
	 * 已托运修改—运单移动
	 *
	 * @param trailerUpdateMobileDetailVO
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void updateMobileDetailTrailerData(TrailerUpdateMobileDetailVO trailerUpdateMobileDetailVO) {
		ToolKits.isParamNull(trailerUpdateMobileDetailVO.getOriginalLoadingBillId(), "原托运单ID不为空");
		ToolKits.isParamNull(trailerUpdateMobileDetailVO.getNowLoadingBillId(), "目标托运单ID不为空");
		ToolKits.isParamNull(trailerUpdateMobileDetailVO.getShipbillIds(), "运单ID不为空");

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

		Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
		Restriction r1 = Restrictions.in("shipbillId", trailerUpdateMobileDetailVO.getShipbillIds().toArray());
		Restriction r2 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
		criteria.setRestriction(Restrictions.and(r1, r2));
		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteria);

		// 原托运单
		TmsLoadingBillHeaderModel originalModel = tmsLoadingBillHeaderMapper.findById(trailerUpdateMobileDetailVO.getOriginalLoadingBillId(), TmsLoadingBillHeaderModel.class);
		// 目标托运单
		TmsLoadingBillHeaderModel nowModel = tmsLoadingBillHeaderMapper.findById(trailerUpdateMobileDetailVO.getNowLoadingBillId(), TmsLoadingBillHeaderModel.class);

		criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
		r1 = Restrictions.eq("loadingBillId", trailerUpdateMobileDetailVO.getNowLoadingBillId());
		criteria.setRestriction(Restrictions.and(r1, r2));

		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailNowModels = tmsLoadingBillDetailMapper.findByCriteria(criteria);
		List<Integer> indexList = tmsLoadingBillDetailNowModels.stream().filter(o -> ToolKits.isNotEmpty(o.getShippingOrder())).map(TmsLoadingBillDetailModel::getShippingOrder).collect(Collectors.toList());
		Integer index = null;
		if (ToolKits.isEmpty(indexList)) {
			index = 1;
		} else {
			index = Collections.max(indexList);
		}

		// 目标托运单客户集合
		List<String> customerList = tmsLoadingBillDetailNowModels.stream().filter(o -> ToolKits.isNotEmpty(o.getConsigneeName())).map(TmsLoadingBillDetailModel::getConsigneeName).distinct().collect(Collectors.toList());

		// 目标托运单站点集合
		List<String> siteList = tmsLoadingBillDetailNowModels.stream().filter(o -> ToolKits.isNotEmpty(o.getConsigneeAddress())).map(TmsLoadingBillDetailModel::getConsigneeAddress).distinct().collect(Collectors.toList());

		// 修改配送顺序以及总重量体积件数等数据
		for (TmsLoadingBillDetailModel tmsLoadingBillDetailModel : tmsLoadingBillDetailModels) {
			index++;
			// 修改配送顺序
			r1 = Restrictions.eq("loadingBillId", tmsLoadingBillDetailModel.getLoadingBillId());
			Restriction r3 = Restrictions.ne("shipbillId", tmsLoadingBillDetailModel.getShipbillId());
			criteria.setRestriction(Restrictions.and(r1, r2, r3));
			List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModelList = tmsLoadingBillDetailMapper.findByCriteria(criteria);
			for (TmsLoadingBillDetailModel loadingBillDetailModel : tmsLoadingBillDetailModelList) {
				if (loadingBillDetailModel.getShippingOrder() > tmsLoadingBillDetailModel.getShippingOrder()) {
					loadingBillDetailModel.setShippingOrder(loadingBillDetailModel.getShippingOrder() - 1);
				}
				tmsLoadingBillDetailMapper.update(loadingBillDetailModel);
			}

			// 原托运单客户数
			Integer customerNumber = tmsLoadingBillDetailModelList.stream().filter(o -> ToolKits.isNotEmpty(o.getConsigneeName())).map(TmsLoadingBillDetailModel::getConsigneeName).distinct().collect(Collectors.toList()).size();

			// 原托运单站点数
			Integer siteNumber = tmsLoadingBillDetailModelList.stream().filter(o -> ToolKits.isNotEmpty(o.getConsigneeAddress())).map(TmsLoadingBillDetailModel::getConsigneeAddress).distinct().collect(Collectors.toList()).size();

			// 原托运单重量体积件数
			originalModel.setTotalPcs(originalModel.getTotalPcs().subtract(tmsLoadingBillDetailModel.getTotalPcs()));
			originalModel.setTotalVolume(originalModel.getTotalVolume().subtract(tmsLoadingBillDetailModel.getTotalVolume()));
			originalModel.setTotalWeight(originalModel.getTotalWeight().subtract(tmsLoadingBillDetailModel.getTotalWeight()));

			// 原托运单实际重量体积件数
			originalModel.setActualTotalPcs(originalModel.getActualTotalPcs().subtract(tmsLoadingBillDetailModel.getActualTotalPcs()));
			originalModel.setActualTotalVolume(originalModel.getActualTotalVolume().subtract(tmsLoadingBillDetailModel.getActualTotalVolume()));
			originalModel.setActualTotalWeight(originalModel.getActualTotalWeight().subtract(tmsLoadingBillDetailModel.getActualTotalWeight()));

			// 原托运单整件数拼箱数
			if (ToolKits.isNotEmpty(tmsLoadingBillDetailModel.getPackageWholePiece())) {
				originalModel.setTotalWholePiece(originalModel.getTotalWholePiece().subtract(tmsLoadingBillDetailModel.getPackageWholePiece()));
			}
			if (ToolKits.isNotEmpty(tmsLoadingBillDetailModel.getPackageLclPiece())) {
				originalModel.setTotalLclPiece(originalModel.getTotalLclPiece().subtract(tmsLoadingBillDetailModel.getPackageLclPiece()));
			}
			// 原托运单运单数
			originalModel.setShipbillNumber(originalModel.getShipbillNumber() - 1);

			// 原托运单客户数
			originalModel.setCustomerNumber(customerNumber);
			// 原托运单站点数
			originalModel.setSiteNumber(siteNumber);

			// 目标托运单重量体积件数
			nowModel.setTotalPcs(nowModel.getTotalPcs().add(tmsLoadingBillDetailModel.getTotalPcs()));
			nowModel.setTotalVolume(nowModel.getTotalVolume().add(tmsLoadingBillDetailModel.getTotalVolume()));
			nowModel.setTotalWeight(nowModel.getTotalWeight().add(tmsLoadingBillDetailModel.getTotalWeight()));

			// 目标托运单实际重量体积件数
			nowModel.setActualTotalPcs(nowModel.getActualTotalPcs().add(tmsLoadingBillDetailModel.getActualTotalPcs()));
			nowModel.setActualTotalVolume(nowModel.getActualTotalVolume().add(tmsLoadingBillDetailModel.getActualTotalVolume()));
			nowModel.setActualTotalWeight(nowModel.getActualTotalWeight().add(tmsLoadingBillDetailModel.getActualTotalWeight()));

			// 目标托运单整件数拼箱数
			if (ToolKits.isNotEmpty(tmsLoadingBillDetailModel.getPackageWholePiece())) {
				nowModel.setTotalWholePiece(nowModel.getTotalWholePiece().add(tmsLoadingBillDetailModel.getPackageWholePiece()));
			}
			if (ToolKits.isNotEmpty(tmsLoadingBillDetailModel.getPackageLclPiece())) {
				nowModel.setTotalLclPiece(nowModel.getTotalLclPiece().add(tmsLoadingBillDetailModel.getPackageLclPiece()));
			}
			// 目标托运单运单数
			nowModel.setShipbillNumber(nowModel.getShipbillNumber() + 1);

			// 目标托运单客户数
			if (!customerList.contains(tmsLoadingBillDetailModel.getConsigneeName())) {
				nowModel.setCustomerNumber(nowModel.getCustomerNumber() + 1);
			}

			// 目标托运单站点数
			if (!siteList.contains(tmsLoadingBillDetailModel.getConsigneeAddress())) {
				nowModel.setSiteNumber(nowModel.getSiteNumber() + 1);
			}

			// 修改明细内容
			Map<String, Object> map = Maps.newHashMap();
			map.put("loadingBillId", trailerUpdateMobileDetailVO.getNowLoadingBillId());
			map.put("loadingBillNo", trailerUpdateMobileDetailVO.getNowLoadingBillId());
			map.put("shippingOrder", index);

			tmsLoadingBillDetailMapper.updateMapById(tmsLoadingBillDetailModel.getId(), map, TmsLoadingBillDetailModel.class);

			// 运单操作日志保存
			ShipbillOperateLogSaveVO shipbillOperateLogSaveVO = new ShipbillOperateLogSaveVO();
			shipbillOperateLogSaveVO.setShipbillId(tmsLoadingBillDetailModel.getShipbillId());
			shipbillOperateLogSaveVO.setShipbillNo(tmsLoadingBillDetailModel.getShipbillNo());
			shipbillOperateLogSaveVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_NODE_STATUSNAME_YD + trailerUpdateMobileDetailVO.getNowLoadingBillId());
			shipbillOperateLogSaveVO.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH);
			shipbillOperateLogSaveVO.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH);
			shipbillOperateLogService.addShipbillOperateLogData(shipbillOperateLogSaveVO);

			// 运单节点保存
			ShipbillNodeTrackingSaveVO shipbillNodeTrackingSaveVO = new ShipbillNodeTrackingSaveVO();
			shipbillNodeTrackingSaveVO.setShipbillId(tmsLoadingBillDetailModel.getShipbillId());
			shipbillNodeTrackingSaveVO.setShipbillNo(tmsLoadingBillDetailModel.getShipbillNo());
			shipbillNodeTrackingSaveVO.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_REVIEW);
			shipbillNodeTrackingSaveVO.setNodeEvent("移动到托运单" + nowModel.getLoadingBillId() + "中");
			shipbillNodeTrackingService.addShipbillNodeTrackingData(shipbillNodeTrackingSaveVO);
		}

		// 原托运单计算装载率
		if (ToolKits.isNotEmpty(originalModel.getVehicleId())) {
			Map<String, String> map = this.calculateLoadingRate(originalModel.getVehicleId(), originalModel.getTotalWeight(), originalModel.getTotalVolume());
			originalModel.setVolumeLoadingRate(map.get("volume"));
			originalModel.setWeightLoadingRate(map.get("weight"));
		}

		// 目标托运单计算装载率
		if (ToolKits.isNotEmpty(nowModel.getVehicleId())) {
			Map<String, String> map = this.calculateLoadingRate(nowModel.getVehicleId(), nowModel.getTotalWeight(), nowModel.getTotalVolume());
			nowModel.setVolumeLoadingRate(map.get("volume"));
			nowModel.setWeightLoadingRate(map.get("weight"));
		}

		// 修改汇总表
		tmsLoadingBillHeaderMapper.update(originalModel);
		tmsLoadingBillHeaderMapper.update(nowModel);
	}

	/**
	 * 计算装载率
	 *
	 * @param id
	 * @param weight
	 * @param volume
	 * @return
	 */
	private Map<String, String> calculateLoadingRate(Long id, BigDecimal weight, BigDecimal volume) {

		VehicleCheckVO vehicleCheckVO = new VehicleCheckVO();
		vehicleCheckVO.setVehicleId(id);

		RestMessage<VehicleCheckDTO> data = maindataTmsResource.getVehicle(vehicleCheckVO);
		if (!data.isSuccess()) {
			throw new RuntimeException("获取车辆失败");
		}
		VehicleCheckDTO vehicleCheckDTO = data.getData();

		StringBuffer weightStr = new StringBuffer();
		StringBuffer volumeStr = new StringBuffer();

		if (ToolKits.isNotEmpty(weight)) {
			BigDecimal divide = ToolKits.isEmpty(vehicleCheckDTO.getWeight()) ? BigDecimal.ZERO : weight.divide(vehicleCheckDTO.getWeight(), 2, BigDecimal.ROUND_HALF_UP);
			BigDecimal multiply = divide.multiply(new BigDecimal("100"));
			weightStr.append(multiply.intValue());
			weightStr.append("%");
		}
		if (ToolKits.isNotEmpty(volume)) {
			BigDecimal divide = ToolKits.isEmpty(vehicleCheckDTO.getVolume()) ? BigDecimal.ZERO : volume.divide(vehicleCheckDTO.getVolume(), 2, BigDecimal.ROUND_HALF_UP);
			BigDecimal multiply = divide.multiply(new BigDecimal("100"));
			volumeStr.append(multiply.intValue());
			volumeStr.append("%");
		}

		Map<String, String> map = Maps.newHashMap();
		map.put("weight", weightStr.toString());
		map.put("volume", volumeStr.toString());

		return map;
	}

	/**
	 * 计算派车单统计数据
	 *
	 * @param tmsLoadingBillHeaderModel
	 * @return
	 */
	private void calculateLoadingData(TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel) {
		// 重新计算
		Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
		Restriction r1 = Restrictions.eq(TmsLoadingBillDetailModel::getLoadingBillId, tmsLoadingBillHeaderModel.getLoadingBillId());
		criteria.setRestriction(Restrictions.and(r1));
		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModelList = tmsLoadingBillDetailMapper.findByCriteria(criteria);
		if (ToolKits.isEmpty(tmsLoadingBillDetailModelList)) {
			// 货主数
			tmsLoadingBillHeaderModel.setCargoOwnerNumber(Long.valueOf(0));
			// 客户数
			tmsLoadingBillHeaderModel.setCustomerNumber(0);
			// 运单数
			tmsLoadingBillHeaderModel.setShipbillNumber(0);
			// 总提货点数
			tmsLoadingBillHeaderModel.setPickupStations(Long.valueOf(0));
			// 总配送点数
			tmsLoadingBillHeaderModel.setDeliveryStations(Long.valueOf(0));
			// 总站数
			tmsLoadingBillHeaderModel.setTotalStations(Long.valueOf(0));
			tmsLoadingBillHeaderModel.setSiteNumber(tmsLoadingBillHeaderModel.getTotalStations().intValue());
			// 冷链运单数
			tmsLoadingBillHeaderModel.setColdShipbillNumber(Long.valueOf(0));

			// 紧急加急运单数
			tmsLoadingBillHeaderModel.setUrgentShipbillNumber(Long.valueOf(0));

			// 商品/包裹 总件数
			tmsLoadingBillHeaderModel.setTotalPcs(BigDecimal.ZERO);
			tmsLoadingBillHeaderModel.setTotalLclPiece(BigDecimal.ZERO);
			tmsLoadingBillHeaderModel.setTotalWholePiece(BigDecimal.ZERO);
			// 商品/包裹 总重量
			tmsLoadingBillHeaderModel.setTotalWeight(BigDecimal.ZERO);
			// 商品/包裹 总体积
			tmsLoadingBillHeaderModel.setTotalVolume(BigDecimal.ZERO);

			tmsLoadingBillHeaderModel.setActualTotalPcs(tmsLoadingBillHeaderModel.getTotalPcs());
			tmsLoadingBillHeaderModel.setActualTotalWeight(tmsLoadingBillHeaderModel.getTotalWeight());
			tmsLoadingBillHeaderModel.setActualTotalVolume(tmsLoadingBillHeaderModel.getTotalVolume());;
			tmsLoadingBillHeaderModel.setTotalMileage(BigDecimal.ZERO);
		} else {
			// 货主数
			tmsLoadingBillHeaderModel.setCargoOwnerNumber(Long.valueOf(tmsLoadingBillDetailModelList.stream().map(TmsLoadingBillDetailModel::getCargoOwnerName).distinct().collect(Collectors.toList()).size()));
			// 客户数
			tmsLoadingBillHeaderModel.setCustomerNumber(tmsLoadingBillDetailModelList.stream().map(TmsLoadingBillDetailModel::getConsigneeUnitName).distinct().collect(Collectors.toList()).size());
			// 运单数
			tmsLoadingBillHeaderModel.setShipbillNumber(tmsLoadingBillDetailModelList.size());
			// 总提货点数
			tmsLoadingBillHeaderModel.setPickupStations(Long.valueOf(tmsLoadingBillDetailModelList.stream().map(TmsLoadingBillDetailModel::getShipperAddress).distinct().collect(Collectors.toList()).size()));
			// 总配送点数
			tmsLoadingBillHeaderModel.setDeliveryStations(Long.valueOf(tmsLoadingBillDetailModelList.stream().map(TmsLoadingBillDetailModel::getConsigneeAddress).distinct().collect(Collectors.toList()).size()));
			// 总站数
			tmsLoadingBillHeaderModel.setTotalStations(tmsLoadingBillHeaderModel.getPickupStations().longValue() + tmsLoadingBillHeaderModel.getDeliveryStations().longValue());
			tmsLoadingBillHeaderModel.setSiteNumber(tmsLoadingBillHeaderModel.getTotalStations().intValue());
			// 冷链运单数
			long coldChainShipbillQty = tmsLoadingBillDetailModelList.stream().filter(s -> ToolKits.isNotEmpty(s.getTemperatureRequirement()) && s.getTemperatureRequirement().intValue() > 1).collect(Collectors.toList()).size();
			tmsLoadingBillHeaderModel.setColdShipbillNumber(coldChainShipbillQty);

			// 紧急加急运单数
			long urgentShipbillQty = tmsLoadingBillDetailModelList.stream().filter(s -> ToolKits.isNotEmpty(s.getOrderType()) && s.getOrderType().intValue() > 1).collect(Collectors.toList()).size();
			tmsLoadingBillHeaderModel.setUrgentShipbillNumber(urgentShipbillQty);

			BigDecimal pcs1 = tmsLoadingBillDetailModelList.stream().filter(dto -> ToolKits.isNotEmpty(dto.getTotalPcs())).map(TmsLoadingBillDetailModel::getTotalPcs).reduce(BigDecimal.ZERO, BigDecimal::add);
			BigDecimal pcs2 = tmsLoadingBillDetailModelList.stream().filter(dto -> ToolKits.isNotEmpty(dto.getPackageLclPiece())).map(TmsLoadingBillDetailModel::getPackageLclPiece).reduce(BigDecimal.ZERO, BigDecimal::add);
			BigDecimal pcs3 = tmsLoadingBillDetailModelList.stream().filter(dto -> ToolKits.isNotEmpty(dto.getPackageWholePiece())).map(TmsLoadingBillDetailModel::getPackageWholePiece).reduce(BigDecimal.ZERO, BigDecimal::add);
			BigDecimal weigth1 = tmsLoadingBillDetailModelList.stream().filter(dto -> ToolKits.isNotEmpty(dto.getTotalWeight())).map(TmsLoadingBillDetailModel::getTotalWeight).reduce(BigDecimal.ZERO, BigDecimal::add);
			BigDecimal weigth2 = tmsLoadingBillDetailModelList.stream().filter(dto -> ToolKits.isNotEmpty(dto.getPackageTotalWeight())).map(TmsLoadingBillDetailModel::getPackageTotalWeight).reduce(BigDecimal.ZERO, BigDecimal::add);
			BigDecimal volume1 = tmsLoadingBillDetailModelList.stream().filter(dto -> ToolKits.isNotEmpty(dto.getTotalVolume())).map(TmsLoadingBillDetailModel::getTotalVolume).reduce(BigDecimal.ZERO, BigDecimal::add);
			BigDecimal volume2 = tmsLoadingBillDetailModelList.stream().filter(dto -> ToolKits.isNotEmpty(dto.getPackageTotalVolume())).map(TmsLoadingBillDetailModel::getPackageTotalVolume).reduce(BigDecimal.ZERO, BigDecimal::add);

			// 商品/包裹 总件数
			tmsLoadingBillHeaderModel.setTotalPcs(pcs1);
			tmsLoadingBillHeaderModel.setTotalLclPiece(pcs2);
			tmsLoadingBillHeaderModel.setTotalWholePiece(pcs3);
			// 商品/包裹 总重量
			tmsLoadingBillHeaderModel.setTotalWeight(weigth1.add(weigth2));
			// 商品/包裹 总体积
			tmsLoadingBillHeaderModel.setTotalVolume(volume1.add(volume2));

			tmsLoadingBillHeaderModel.setActualTotalPcs(tmsLoadingBillHeaderModel.getTotalPcs());
			tmsLoadingBillHeaderModel.setActualTotalWeight(tmsLoadingBillHeaderModel.getTotalWeight());
			tmsLoadingBillHeaderModel.setActualTotalVolume(tmsLoadingBillHeaderModel.getTotalVolume());
		}
	}

	/**
	 * 运单匹配业务流程
	 *
	 * @param model
	 * @return
	 */
	public ShipbillFitBusinessFlowDTO shipbillMatchBusinessFlow(TmsShipbillHeaderModel model) {
		// 新增后自动提交判定
		BusinessFlowShipbillVO matchFlowVO = new BusinessFlowShipbillVO();
		// 流程类型 承运商
		matchFlowVO.setFlowType(1);
		// 配送方式
		matchFlowVO.setDeliveryMethodType(model.getDeliveryMethodType());
		// 发货方类型
		matchFlowVO.setShipperType(model.getShipperType());
		// 发货方单位ID
		matchFlowVO.setShipperUnitId(model.getShipperUnitId());
		// 收货方类型
		matchFlowVO.setConsigneeType(model.getConsigneeType());
		// 收货方单位ID
		matchFlowVO.setConsigneeUnitId(model.getConsigneeUnitId());
		// 订单类型
		matchFlowVO.setOrderType(model.getOrderType());
		// 订单业务类型
		matchFlowVO.setOrderBusinessType(model.getOrderBusinessType());
		// 运输模式
		matchFlowVO.setTransportType(model.getTransportType());
		// 温度要求
		matchFlowVO.setTemperatureRequirement(model.getTemperatureRequirement());
		// 货主ID
		matchFlowVO.setCargoOwnerId(model.getCargoOwnerId());
		matchFlowVO.setCarriersType(model.getCarriersType());
		RestMessage<ShipbillFitBusinessFlowDTO> matchRs = maindataTmsResource.shipbillMatchFlowQuery(matchFlowVO);
		if (!matchRs.isSuccess()) {
			throw new PrologException("运单【" + model.getShipbillNo() + "】调用maindata服务运单匹配业务流程失败");
		}
		return matchRs.getData();
	}

	/**
	 * 自动运单接单
	 *
	 * @param ids
	 * @throws Exception
	 */
	@Override
	public void autoReceiveShipbillData(List<String> ids, Date date, UserEntity user) {
		ToolKits.isParamNull(ids, "运单接单请求不为空");
		Assert.isTrue(ids.size() > 0, "运单接单请求不为空");

		ToolKits.isParamNull(user, "当前人员没有操作权限");
		// 当前时间
		List<String> commitObjs = Lists.newArrayList();
		for (String id : ids) {
			ToolKits.isParamNull(id, "运单ID不为空");
			// 更新
			TmsShipbillHeaderModel tmsShipbillHeaderModel = tmsShipbillHeaderMapper.findById(id, TmsShipbillHeaderModel.class);
			Assert.isTrue(tmsShipbillHeaderModel.getCarrierShipbillStatus() != DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_RECEIVED, "运单【" + id + "】已接单!");

			// 运单状态更新
			tmsShipbillHeaderModel.setCarrierShipbillStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_RECEIVED);
			tmsShipbillHeaderModel.setUpdateperson(user.getNickname());
			tmsShipbillHeaderModel.setUpdatetime(date);
			tmsShipbillHeaderMapper.update(tmsShipbillHeaderModel);

			// 承运商运单操作日志保存
			ShipbillOperateLogSaveVO shipbillOperateLogSaveVO = new ShipbillOperateLogSaveVO();
			shipbillOperateLogSaveVO.setShipbillId(id);
			shipbillOperateLogSaveVO.setShipbillNo(id);
			shipbillOperateLogSaveVO.setOperateEvent(DataDictionaryConstant.CARRIER_SHIPBILL_NODE_STATUSNAME_RECEIVED);
			shipbillOperateLogSaveVO.setOldStatus(tmsShipbillHeaderModel.getCarrierShipbillStatus());
			shipbillOperateLogSaveVO.setNewStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_RECEIVED);
			shipbillOperateLogService.addShipbillOperateLogData(shipbillOperateLogSaveVO);

			if (tmsShipbillHeaderModel.getCarrierFlowConfig().contains(DataDictionaryConstant.FLOW_CONFIG_RECEIVE_COMMIT)) {
				commitObjs.add(id);
			}
			MessageUtil.addMessage(new SendMessageDTO(MessageOrderTypeEnum.SHIP_NO.getCode(), MessageTypeEnum.CARRIER_RECEIVE.getCode(), Lists.newArrayList(id)));
		}
		if (ToolKits.isNotEmpty(commitObjs)) {
			try {
				// 调用提交处理
				submitShipbillData(commitObjs, date, user);
			} catch (Exception e) {
				throw new PrologException("运单保存自动提交处理失败", e);
			}
		}
	}

	/**
	 * 提交处理
	 *
	 * @param ids
	 * @throws Exception
	 */
	public void submitShipbillData(List<String> ids, Date date, UserEntity user) throws Exception {
		ToolKits.isParamNull(ids, "运单批量提交请求不为空");

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

		List<String> reviewObjs = Lists.newArrayList();
		for (String id : ids) {
			ToolKits.isParamNull(id, "运单ID不为空");

			// 更新
			TmsShipbillHeaderModel tmsShipbillHeaderModel = tmsShipbillHeaderMapper.findById(id, TmsShipbillHeaderModel.class);

			Assert.isTrue(tmsShipbillHeaderModel.getCarrierShipbillStatus() != DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_COMMIT, "运单【" + tmsShipbillHeaderModel.getShipbillNo() + "】已提交");

			tmsShipbillHeaderModel.setCarrierShipbillStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_COMMIT);

			tmsShipbillHeaderModel.setUpdateperson(user.getNickname());
			tmsShipbillHeaderModel.setUpdatetime(date);
			// 运单汇总表更新
			tmsShipbillHeaderMapper.update(tmsShipbillHeaderModel);

			// 节点保存
			ShipbillNodeTrackingSaveVO shipbillNodeTrackingSaveVO = new ShipbillNodeTrackingSaveVO();
			shipbillNodeTrackingSaveVO.setShipbillId(tmsShipbillHeaderModel.getShipbillId());
			shipbillNodeTrackingSaveVO.setShipbillNo(tmsShipbillHeaderModel.getShipbillNo());
			shipbillNodeTrackingSaveVO.setStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_COMMIT);
			shipbillNodeTrackingSaveVO.setNodeDate(date);
			shipbillNodeTrackingSaveVO.setNodeEvent(DataDictionaryConstant.CARRIER_SHIPBILL_NODE_STATUSNAME_TJ);
			shipbillNodeTrackingService.addShipbillNodeTrackingData(shipbillNodeTrackingSaveVO);

			// 日志保存
			ShipbillOperateLogSaveVO shipbillOperateLogSaveVO = new ShipbillOperateLogSaveVO();
			shipbillOperateLogSaveVO.setShipbillId(tmsShipbillHeaderModel.getShipbillId());
			shipbillOperateLogSaveVO.setShipbillNo(tmsShipbillHeaderModel.getShipbillNo());
			shipbillOperateLogSaveVO.setOperateDate(date);
			shipbillOperateLogSaveVO.setOperateEvent(DataDictionaryConstant.CARRIER_SHIPBILL_STATUSNAME_YTJ);
			shipbillOperateLogSaveVO.setOldStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_RECEIVED);
			shipbillOperateLogSaveVO.setNewStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_COMMIT);
			shipbillOperateLogService.addShipbillOperateLogData(shipbillOperateLogSaveVO);

			// 更新运输记录表的审核时间
			Criteria criteriaTransLog = Criteria.forClass(TmsShipbillTransLogModel.class);
			Restriction r1 = Restrictions.eq(TmsShipbillTransLogModel::getShipbillId, tmsShipbillHeaderModel.getShipbillId());
			Restriction r2 = Restrictions.eq(TmsShipbillTransLogModel::getEnterpriseId, user.getEnterpriseId());
			criteriaTransLog.setRestriction(Restrictions.and(r1, r2));

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

			// 判定提交后是否自动审核
			if (tmsShipbillHeaderModel.getCarrierFlowConfig().contains(DataDictionaryConstant.FLOW_CONFIG_COMMIT_REVIEW)) {
				reviewObjs.add(id);
			}
			MessageUtil.addMessage(new SendMessageDTO(MessageOrderTypeEnum.SHIP_NO.getCode(), MessageTypeEnum.CARRIER_SUBMIT.getCode(), Lists.newArrayList(id)));
		}
		// 提交后，调用自动审核处理
		if (ToolKits.isNotEmpty(reviewObjs)) {
			reviewShipbillData(reviewObjs, date, user);
		}
	}

	/**
	 * 自动审核处理
	 *
	 * @param shipbillIds
	 * @throws Exception
	 */
	public void reviewShipbillData(List<String> shipbillIds, Date date, UserEntity user) {
		ToolKits.isParamNull(shipbillIds, "运单审核请求不为空");

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

		for (String id : shipbillIds) {
			ToolKits.isParamNull(id, "运单ID不为空");
			// 更新
			TmsShipbillHeaderModel tmsShipbillHeaderModel = tmsShipbillHeaderMapper.findById(id, TmsShipbillHeaderModel.class);
			ShipbillNodeTrackingSaveVO shipbillNodeTrackingSaveVO = new ShipbillNodeTrackingSaveVO();
			ShipbillOperateLogSaveVO shipbillOperateLogSaveVO = new ShipbillOperateLogSaveVO();

			Assert.isTrue(tmsShipbillHeaderModel.getCarrierShipbillStatus() == DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_COMMIT, "运单【" + tmsShipbillHeaderModel.getShipbillNo() + "】非待审核状态,审核失败");
			tmsShipbillHeaderModel.setCarrierShipbillStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_AUDITED);
			shipbillNodeTrackingSaveVO.setNodeEvent(DataDictionaryConstant.CARRIER_SHIPBILL_NODE_STATUSNAME_RE);
			shipbillOperateLogSaveVO.setOperateEvent(DataDictionaryConstant.CARRIER_SHIPBILL_NODE_STATUSNAME_RE);

			// 运单审核
			tmsShipbillHeaderModel.setUpdateperson(user.getNickname());
			tmsShipbillHeaderModel.setUpdatetime(date);
			tmsShipbillHeaderMapper.update(tmsShipbillHeaderModel);

			// 运单节点保存
			shipbillNodeTrackingSaveVO.setNodeDate(date);
			shipbillNodeTrackingSaveVO.setShipbillId(tmsShipbillHeaderModel.getShipbillId());
			shipbillNodeTrackingSaveVO.setShipbillNo(tmsShipbillHeaderModel.getShipbillNo());
			shipbillNodeTrackingSaveVO.setStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_AUDITED);
			shipbillNodeTrackingService.addShipbillNodeTrackingData(shipbillNodeTrackingSaveVO);

			// 运单日志保存
			shipbillOperateLogSaveVO.setOperateDate(date);
			shipbillOperateLogSaveVO.setShipbillId(tmsShipbillHeaderModel.getShipbillId());
			shipbillOperateLogSaveVO.setShipbillNo(tmsShipbillHeaderModel.getShipbillNo());
			shipbillOperateLogSaveVO.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_YTJ);
			shipbillOperateLogSaveVO.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_REVIEW);
			shipbillOperateLogService.addShipbillOperateLogData(shipbillOperateLogSaveVO);

			// 更新运输记录表的审核时间
			Criteria criteriaTransLog = Criteria.forClass(TmsShipbillTransLogModel.class);
			Restriction r1 = Restrictions.eq(TmsShipbillTransLogModel::getShipbillId, tmsShipbillHeaderModel.getShipbillId());
			Restriction r2 = Restrictions.eq(TmsShipbillTransLogModel::getEnterpriseId, user.getEnterpriseId());
			criteriaTransLog.setRestriction(Restrictions.and(r1, r2));

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

			// 运单匹配唯一承运方是否自动调度
			TmsShipbillHeaderModel shipbillHeaderModel = tmsShipbillHeaderMapper.findById(id, TmsShipbillHeaderModel.class);
			boolean autoDispatch = false;
			boolean autoSplit = false;
			if (DataDictionaryConstant.DELIVERY_METHOD_TYPE_SEND == shipbillHeaderModel.getDeliveryMethodType()) {
				String flowConfig = null;
				flowConfig = shipbillHeaderModel.getCarrierFlowConfig();

				if (ToolKits.isNotEmpty(flowConfig) && flowConfig.contains(DataDictionaryConstant.FLOW_CONFIG_REVIEW_DISPATCH)) {
					autoDispatch = true;
				}
				if (shipbillHeaderModel.getFlowConfig().contains(DataDictionaryConstant.FLOW_CONFIG_REVIEW_SPLIT)) {
					autoSplit = true;
				}
			}
			// 自动拆分
			List<TmsShipbillHeaderModel> autoDispatchOjbs = Lists.newArrayList();
			if (autoSplit) {
				// autoDispatchOjbs.addAll(autoSplit(id, date, user));
			}
			// 自动拆分做了时，子单参加调度，没有自动拆分时，原单参加自动调度
			if (ToolKits.isEmpty(autoDispatchOjbs)) {
				autoDispatchOjbs.add(shipbillHeaderModel);
			}
			if (autoDispatch) {
				for (TmsShipbillHeaderModel disHeaderModel : autoDispatchOjbs) {
					if (!DataDictionaryConstant.CONSIGNEE_TYPE_KH.equals(disHeaderModel.getConsigneeType())) {
						return;
					}
					CustomerCarrierVO carrierVO = new CustomerCarrierVO();
					carrierVO.setConsigneeId(disHeaderModel.getConsigneeId());
					RestMessage<CustomerCarrierDTO> restRs = maindataTmsResource.customerCarrierExecute(carrierVO);
					if (!restRs.isSuccess()) {
						throw new PrologException("调用maindata服务,客户收货方匹配唯一承运方失败");
					}
					CustomerCarrierDTO carrierDTO = restRs.getData();

					PendingDispatchVO pendingDispatchVO = new PendingDispatchVO();
					LoadingBillHeaderVO loadingBillHeaderVO = new LoadingBillHeaderVO();
					List<LoadingBillDetailVO> loadingBillDetailVOS = Lists.newArrayList();
					LoadingBillDetailVO loadingBillDetailVO = new LoadingBillDetailVO();
					if (ToolKits.isNotEmpty(carrierDTO) && ToolKits.isNotEmpty(carrierDTO.getCarrierId())) {
						// 唯一匹配承运方
						// 承运方类型
						loadingBillHeaderVO.setCarrierType(carrierDTO.getCarrierType());
						if (DataDictionaryConstant.LINE_CARRIER_TYPE_SJ == carrierDTO.getCarrierType()) {
							// 司机ID
							loadingBillHeaderVO.setDriverId(String.valueOf(carrierDTO.getCarrierId()));
							loadingBillHeaderVO.setDriverCode(carrierDTO.getCarrierCode());
							loadingBillHeaderVO.setDriverName(carrierDTO.getCarrierName());
						} else {
							// 承运商ID
							loadingBillHeaderVO.setCarrierId(carrierDTO.getCarrierId());
							loadingBillHeaderVO.setCarrierCode(carrierDTO.getCarrierCode());
							loadingBillHeaderVO.setCarrierName(carrierDTO.getCarrierName());
						}
						// 司机手机号
						loadingBillHeaderVO.setDriverPhoneNumber(carrierDTO.getCarrierPhoneNumber());
						// 车牌号
						loadingBillHeaderVO.setVehiclePlateNumber(carrierDTO.getVehiclePlateNumber());
						// 运单数
						loadingBillHeaderVO.setShipbillNumber(1);
						// 站点数
						loadingBillHeaderVO.setSiteNumber(1);
						// 客户数
						loadingBillHeaderVO.setCustomerNumber(1);
						// 总件数
						loadingBillHeaderVO.setTotalPcs(disHeaderModel.getTotalPcs());
						// 总体积
						loadingBillHeaderVO.setTotalVolume(disHeaderModel.getTotalVolume());
						// 总重量
						loadingBillHeaderVO.setTotalWeight(disHeaderModel.getTotalWeight());
						// 实际总件数
						loadingBillHeaderVO.setActualTotalPcs(disHeaderModel.getTotalPcs());
						// 实际总体积
						loadingBillHeaderVO.setActualTotalVolume(disHeaderModel.getTotalVolume());
						// 实际总重量
						loadingBillHeaderVO.setActualTotalWeight(disHeaderModel.getTotalWeight());
						// 总整件数
						loadingBillHeaderVO.setTotalWholePiece(disHeaderModel.getPackageWholePiece());
						// 总拼箱数
						loadingBillHeaderVO.setTotalLclPiece(disHeaderModel.getPackageLclPiece());
						// 备注
						loadingBillHeaderVO.setMemo("待审核后自动调度");

						loadingBillHeaderVO.setVehicleId(carrierDTO.getVehicleId());
						loadingBillHeaderVO.setVehicleCode(carrierDTO.getVehicleCode());
						loadingBillHeaderVO.setVehicleName(carrierDTO.getVehicleName());

						// 设置调度单数据
						pendingDispatchVO.setLoadingBillHeaderVO(loadingBillHeaderVO);
						// 设置调度单明细
						BeanUtils.copyProperties(disHeaderModel, loadingBillDetailVO);
						loadingBillDetailVOS.add(loadingBillDetailVO);
						pendingDispatchVO.setLoadingBillDetailVO(loadingBillDetailVOS);
						// 自动调度
						autoDispatch(pendingDispatchVO, date, user);
					}
				}
			}
			MessageUtil.addMessage(new SendMessageDTO(MessageOrderTypeEnum.SHIP_NO.getCode(), MessageTypeEnum.CARRIER_AUDIT.getCode(), Lists.newArrayList(id)));
		}
	}

	/**
	 * 调度
	 *
	 * @param vo
	 * @return
	 */
	public void autoDispatch(PendingDispatchVO vo, Date date, UserEntity user) {
		ToolKits.isParamNull(vo, "运单调度请求不为空");

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

		// 装车单汇总
		LoadingBillHeaderVO headerVO = vo.getLoadingBillHeaderVO();
		// 装车单明细
		List<LoadingBillDetailVO> detailVOS = vo.getLoadingBillDetailVO();

		// 装车单汇总保存
		// 获取装车单ID
		RestMessage<String> restMessage1 = maindataTmsResource.getCodeNumberByCode(SeriaNnumberConstant.TMS_LOADING_BILL_HEADER_ID, "L");
		if (!restMessage1.isSuccess()) {
			throw new RuntimeException("生成装车单ID失败");
		}

		String loadingBillId = restMessage1.getData();
		TmsLoadingBillHeaderModel loadingBillHeaderModel = new TmsLoadingBillHeaderModel();
		BeanUtils.copyProperties(headerVO, loadingBillHeaderModel);

		loadingBillHeaderModel.setScheduleType(DataDictionaryConstant.SCHEDULE_TYPE_CYS);

		loadingBillHeaderModel.setLoadingBillId(loadingBillId);
		loadingBillHeaderModel.setLoadingBillNo(loadingBillId);
		loadingBillHeaderModel.setStatus(DataDictionaryConstant.LOADING_BILL_STATUS_WSH);
		loadingBillHeaderModel.setEnterpriseId(user.getEnterpriseId());
		loadingBillHeaderModel.setEnterpriseName(user.getEnterpriseName());
		loadingBillHeaderModel.setCreateperson(user.getNickname());
		loadingBillHeaderModel.setCreatetime(date);
		loadingBillHeaderModel.setUpdateperson(user.getNickname());
		loadingBillHeaderModel.setUpdatetime(date);

		loadingBillHeaderModel.setLoadingBillDate(date);
		// 解析司机名称
		String driverName = this.getFirstStr(headerVO.getDriverName());
		// 解析送货员
		String deliverymanName = this.getFirstStr(headerVO.getDeliverymanName());
		if (DataDictionaryConstant.LINE_CARRIER_TYPE_SJ == headerVO.getCarrierType()) {
			// 解析司机ID
			String driverId = this.getFirstStr(headerVO.getDriverId());
			// 解析司机编号
			String driverCode = this.getFirstStr(headerVO.getDriverCode());
			// 解析司机手机号
			String phoneNumber = this.getFirstStr(headerVO.getDriverPhoneNumber());
			// 司机信息
			loadingBillHeaderModel.setDriverId(driverId == null ? null : Long.valueOf(driverId));
			loadingBillHeaderModel.setDriverCode(driverCode == null ? null : driverCode);
			loadingBillHeaderModel.setDriverName(driverName == null ? null : driverName);
			loadingBillHeaderModel.setDriverPhoneNumber(phoneNumber == null ? null : phoneNumber);
			// 副司机信息
			String viceDriverId = this.subArrToString(headerVO.getDriverId());
			loadingBillHeaderModel.setViceDriverId(viceDriverId == null ? null : viceDriverId);
			String viceDriverCode = this.subArrToString(headerVO.getDriverCode());
			loadingBillHeaderModel.setViceDriverCode(viceDriverCode == null ? null : viceDriverCode);
			String viceDriverName = this.subArrToString(headerVO.getDriverName());
			loadingBillHeaderModel.setViceDriverName(viceDriverName == null ? null : viceDriverName);
			String vicephoneNumber = this.subArrToString(headerVO.getDriverPhoneNumber());
			loadingBillHeaderModel.setViceDriverPhoneNumber(vicephoneNumber == null ? null : vicephoneNumber);
			// 送货员信息
			// 解析送货员ID
			String deliverymanId = this.getFirstStr(headerVO.getDeliverymanId());
			// 解析送货员编号
			String deliverymanCode = this.getFirstStr(headerVO.getDeliverymanCode());
			// 解析送货员手机号
			String deliverymanPhoneNumber = this.getFirstStr(headerVO.getDeliverymanPhoneNumber());
			loadingBillHeaderModel.setDeliverymanId(deliverymanId == null ? null : Long.valueOf(deliverymanId));
			loadingBillHeaderModel.setDeliverymanCode(deliverymanCode == null ? null : deliverymanCode);
			loadingBillHeaderModel.setDeliverymanName(deliverymanName == null ? null : deliverymanName);
			loadingBillHeaderModel.setDeliverymanPhoneNumber(deliverymanPhoneNumber == null ? null : deliverymanPhoneNumber);
			// 副送货员信息
			String viceDeliverymanId = this.subArrToString(headerVO.getDeliverymanId());
			loadingBillHeaderModel.setViceDriverId(viceDeliverymanId == null ? null : viceDeliverymanId);
			String viceDeliverymanCode = this.subArrToString(headerVO.getDeliverymanCode());
			loadingBillHeaderModel.setViceDriverCode(viceDeliverymanCode == null ? null : viceDeliverymanCode);
			String viceDeliverymanName = this.subArrToString(headerVO.getDeliverymanName());
			loadingBillHeaderModel.setViceDeliverymanName(viceDeliverymanName == null ? null : viceDeliverymanName);
			String viceDeliverymanphoneNumber = this.subArrToString(headerVO.getDeliverymanPhoneNumber());
			loadingBillHeaderModel.setViceDeliverymanPhoneNumber(viceDeliverymanphoneNumber == null ? null : viceDeliverymanphoneNumber);
		}

		Integer totalWholePiece = 0;
		Integer totalLclPiece = 0;
		boolean autoDispatchCheck = false;
		int order = 1;
		for (LoadingBillDetailVO loadingBillDetailVO : detailVOS) {
			ToolKits.isParamNull(loadingBillDetailVO.getShipbillId(), "运单ID不为空");
			// 装车单明细保存
			// 获取装车单明细ID
			RestMessage<String> restMessage2 = maindataTmsResource.getCodeNumberByCode(SeriaNnumberConstant.TMS_LOADING_BILL_DETAIL_ID, "L");
			if (!restMessage2.isSuccess()) {
				throw new RuntimeException("生成装车单明细ID失败");
			}

			TmsShipbillHeaderModel tmsShipbillHeaderModel = tmsShipbillHeaderMapper.findById(loadingBillDetailVO.getShipbillId(), TmsShipbillHeaderModel.class);
			Assert.isTrue(null != tmsShipbillHeaderModel, "运单【" + tmsShipbillHeaderModel.getShipbillNo() + "】运单不存在,调度失败");

			String loadingBillDetailId = restMessage2.getData();
			TmsLoadingBillDetailModel loadingBillDetailModel = new TmsLoadingBillDetailModel();
			BeanUtils.copyProperties(tmsShipbillHeaderModel, loadingBillDetailModel);

			ShipbillNodeTrackingSaveVO shipbillNodeTrackingSaveVO = new ShipbillNodeTrackingSaveVO();
			ShipbillOperateLogSaveVO shipbillOperateLogSaveVO = new ShipbillOperateLogSaveVO();
			// 节点内容
			StringBuffer nodeEvent = new StringBuffer();

			Assert.isTrue(tmsShipbillHeaderModel.getCarrierShipbillStatus() == DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_AUDITED, "运单【" + tmsShipbillHeaderModel.getShipbillNo() + "】非待调度状态,调度失败");
			loadingBillDetailModel.setCarrierShipbillStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED);
			tmsShipbillHeaderModel.setCarrierShipbillStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED);
			shipbillNodeTrackingSaveVO.setStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED);
			shipbillOperateLogSaveVO.setOldStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_AUDITED);
			shipbillOperateLogSaveVO.setNewStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED);
			nodeEvent.append(DataDictionaryConstant.CARRIER_SHIPBILL_NODE_STATUSNAME_DI);

			// 判定是否调度后审核
			if (!autoDispatchCheck && tmsShipbillHeaderModel.getCarrierFlowConfig().contains(DataDictionaryConstant.FLOW_CONFIG_DISPATCH_CHECK)) {
				autoDispatchCheck = true;
			}

			loadingBillDetailModel.setId(loadingBillDetailId);
			loadingBillDetailModel.setLoadingBillId(loadingBillId);
			loadingBillDetailModel.setLoadingBillNo(loadingBillId);
			loadingBillDetailModel.setEnterpriseId(user.getEnterpriseId());
			loadingBillDetailModel.setEnterpriseName(user.getEnterpriseName());
			loadingBillDetailModel.setCreateperson(user.getNickname());
			loadingBillDetailModel.setCreatetime(date);
			loadingBillDetailModel.setUpdateperson(user.getNickname());
			loadingBillDetailModel.setUpdatetime(date);

			loadingBillDetailModel.setCarrierType(headerVO.getCarrierType());

			loadingBillDetailModel.setSource(tmsShipbillHeaderModel.getSource());
			nodeEvent.append(" ");
			if (DataDictionaryConstant.LINE_CARRIER_TYPE_CYF == headerVO.getCarrierType()) {

				loadingBillDetailModel.setCarrierId(headerVO.getCarrierId());
				loadingBillDetailModel.setCarrierCode(headerVO.getCarrierCode());
				loadingBillDetailModel.setCarrierName(headerVO.getCarrierName());

				tmsShipbillHeaderModel.setCarrierId(headerVO.getCarrierId());
				tmsShipbillHeaderModel.setCarrierCode(headerVO.getCarrierCode());
				tmsShipbillHeaderModel.setCarrierName(headerVO.getCarrierName());

				// 承运商
				nodeEvent.append(ToolKits.isEmpty(headerVO.getCarrierName()) ? "" : headerVO.getCarrierName());
				ShipbillFitBusinessFlowDTO flowData = shipbillMatchBusinessFlow(tmsShipbillHeaderModel);
				tmsShipbillHeaderModel.setCarrierFlowConfig(flowData.getFlowConfig());
			} else if (DataDictionaryConstant.LINE_CARRIER_TYPE_SJ == headerVO.getCarrierType()) {
				// 司机
				nodeEvent.append(ToolKits.isEmpty(driverName) ? "" : driverName);
				nodeEvent.append(" ");
				// 送货员名称
				nodeEvent.append(ToolKits.isEmpty(deliverymanName) ? "" : deliverymanName);
				nodeEvent.append(" ");
				// 车牌号
				nodeEvent.append(ToolKits.isEmpty(headerVO.getVehiclePlateNumber()) ? "" : headerVO.getVehiclePlateNumber());
			}
			// 保存调度单明细
			loadingBillDetailModel.setFlowConfig(tmsShipbillHeaderModel.getFlowConfig());
			loadingBillDetailModel.setCarrierFlowConfig(tmsShipbillHeaderModel.getCarrierFlowConfig());
			loadingBillDetailModel.setShippingOrder(order);
			order++;
			tmsLoadingBillDetailMapper.save(loadingBillDetailModel);
			// 运单调度
			tmsShipbillHeaderModel.setUpdateperson(user.getNickname());
			tmsShipbillHeaderModel.setUpdatetime(date);

			tmsShipbillHeaderModel.setCarrierType(headerVO.getCarrierType());
			tmsShipbillHeaderMapper.update(tmsShipbillHeaderModel);
			// 运单节点保存
			shipbillNodeTrackingSaveVO.setShipbillId(tmsShipbillHeaderModel.getShipbillId());
			shipbillNodeTrackingSaveVO.setShipbillNo(tmsShipbillHeaderModel.getShipbillNo());
			shipbillNodeTrackingSaveVO.setNodeEvent(nodeEvent.toString());
			shipbillNodeTrackingService.addShipbillNodeTrackingData(shipbillNodeTrackingSaveVO);

			// 运单日志保存
			shipbillOperateLogSaveVO.setShipbillId(tmsShipbillHeaderModel.getShipbillId());
			shipbillOperateLogSaveVO.setShipbillNo(tmsShipbillHeaderModel.getShipbillNo());
			shipbillOperateLogSaveVO.setOperateEvent(nodeEvent.toString());
			shipbillOperateLogService.addShipbillOperateLogData(shipbillOperateLogSaveVO);

			// 更新运输记录表的调度时间
			Criteria criteriaTransLog = Criteria.forClass(TmsShipbillTransLogModel.class);
			Restriction r1 = Restrictions.eq(TmsShipbillTransLogModel::getShipbillId, tmsShipbillHeaderModel.getShipbillId());
			Restriction r2 = Restrictions.eq(TmsShipbillTransLogModel::getEnterpriseId, user.getEnterpriseId());
			criteriaTransLog.setRestriction(Restrictions.and(r1, r2));

			Map<String, Object> mapUpdate = Maps.newHashMap();
			mapUpdate.put("updateperson", user.getNickname());
			mapUpdate.put("updatetime", date);
			mapUpdate.put("disDt", date);
			mapUpdate.put("loadingBillDetailId", loadingBillDetailId);
			tmsShipbillTransportLogMapper.updateMapByCriteria(mapUpdate, criteriaTransLog);

			totalWholePiece = totalWholePiece + (ToolKits.isEmpty(tmsShipbillHeaderModel.getPackageWholePiece()) ? 0 : tmsShipbillHeaderModel.getPackageWholePiece().intValue());
			totalLclPiece = totalLclPiece + (ToolKits.isEmpty(tmsShipbillHeaderModel.getPackageLclPiece()) ? 0 : tmsShipbillHeaderModel.getPackageLclPiece().intValue());

		}
		// 总整件数
		loadingBillHeaderModel.setTotalWholePiece(BigDecimal.valueOf(totalWholePiece));
		// 总拼箱数
		loadingBillHeaderModel.setTotalLclPiece(BigDecimal.valueOf(totalLclPiece));
		loadingBillHeaderModel.setScanStatus(DataDictionaryConstant.SCAN_STATUS_INIT);
		tmsLoadingBillHeaderMapper.save(loadingBillHeaderModel);
		loadingBillService.updateStationByLoadingBillId(loadingBillId);
		MessageUtil.addMessage(new SendMessageDTO(MessageOrderTypeEnum.LOADING_NO.getCode(), MessageTypeEnum.CARRIER_DISPATCH.getCode(), Lists.newArrayList(loadingBillId)));
		// 调度后自动审核
		if (autoDispatchCheck) {
			List<String> ids = Lists.newArrayList();
			ids.add(loadingBillId);
			if (DataDictionaryConstant.LINE_CARRIER_TYPE_SJ == headerVO.getCarrierType()) {
				// 调用派车单审核
				autoSendcarAuditData(ids, date, user);
			} else {
				// 调用托运单审核
				autoSelfTrailerAuditData(ids, date, user);
			}
		}
	}

	/**
	 * 已派车审核
	 *
	 * @param ids
	 */
	public void autoSendcarAuditData(List<String> ids, Date date, UserEntity user) {
		ToolKits.isParamNull(ids, "派车单ID不为空");

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

		List<TmsLoadingBillHeaderModel> tmsLoadingBillHeaderModels = tmsLoadingBillHeaderMapper.findByIds(TmsLoadingBillHeaderModel.class, ids.toArray(), null);

		// 判断派车单是否已审核
		String str = tmsLoadingBillHeaderModels.stream().filter(o -> DataDictionaryConstant.LOADING_BILL_STATUS_YSH == o.getStatus()).map(TmsLoadingBillHeaderModel::getLoadingBillNo).collect(Collectors.joining(","));

		if (ToolKits.isNotEmpty(str)) {
			throw new RuntimeException("派车单[" + str + "]已审核!");
		}

		for (TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel : tmsLoadingBillHeaderModels) {

			Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
			Restriction r1 = Restrictions.eq("loadingBillId", tmsLoadingBillHeaderModel.getLoadingBillId());
			criteria.setRestriction(r1);
			List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteria);

			int shipperTypeCnt = 0;
			int consigneeType = 0;
			for (TmsLoadingBillDetailModel detailModel : tmsLoadingBillDetailModels) {
				if (detailModel.getShipperType() == DataDictionaryConstant.SHIPPER_TYPE_CK) {
					shipperTypeCnt++;
				}
				if (detailModel.getConsigneeType() == DataDictionaryConstant.CONSIGNEE_TYPE_CK) {
					consigneeType++;
				}
				ShipbillNodeTrackingSaveVO shipbillNodeTrackingSaveVO = new ShipbillNodeTrackingSaveVO();
				ShipbillOperateLogSaveVO shipbillOperateLogSaveVO = new ShipbillOperateLogSaveVO();
				Map<String, Object> mapUpdateShipbillHeader = Maps.newHashMap();
				Map<String, Object> mapUpdateLoadingDetail = Maps.newHashMap();

				mapUpdateShipbillHeader.put("updateperson", user.getNickname());
				mapUpdateShipbillHeader.put("updatetime", date);
				mapUpdateLoadingDetail.put("updateperson", user.getNickname());
				mapUpdateLoadingDetail.put("updatetime", date);

				// 承运商账号
				// 判定下一步流程
				String flowConfig = null;
				if (ToolKits.isNotEmpty(detailModel.getCarrierFlowConfig())) {
					flowConfig = detailModel.getCarrierFlowConfig();
				} else {
					flowConfig = detailModel.getFlowConfig();
				}
				int status = businessFlowUtil.judgmentNextFlowSts(flowConfig, DataDictionaryConstant.FLOW_CONFIG_CHECK);

				mapUpdateLoadingDetail.put("carrierShipbillStatus", DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED_CHECK);
				mapUpdateLoadingDetail.put("status", status);

				mapUpdateShipbillHeader.put("carrierShipbillStatus", DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED_CHECK);
				mapUpdateShipbillHeader.put("status", status);

				shipbillNodeTrackingSaveVO.setStatus(status);
				shipbillOperateLogSaveVO.setOldStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED);
				shipbillOperateLogSaveVO.setNewStatus(status);

				shipbillNodeTrackingSaveVO.setNodeEvent(DataDictionaryConstant.CARRIER_SHIPBILL_NODE_STATUSNAME_PC);
				shipbillOperateLogSaveVO.setOperateEvent(DataDictionaryConstant.CARRIER_SHIPBILL_NODE_STATUSNAME_PC);

				// 更改运单状态
				tmsShipbillHeaderMapper.updateMapById(detailModel.getShipbillId(), mapUpdateShipbillHeader, TmsShipbillHeaderModel.class);
				// 更新派车单明细状态
				tmsLoadingBillDetailMapper.updateMapById(detailModel.getId(), mapUpdateLoadingDetail, TmsLoadingBillDetailModel.class);
				// 新增节点信息
				shipbillNodeTrackingSaveVO.setShipbillId(detailModel.getShipbillId());
				shipbillNodeTrackingSaveVO.setShipbillNo(detailModel.getShipbillNo());
				shipbillNodeTrackingService.addShipbillNodeTrackingData(shipbillNodeTrackingSaveVO);

				// 新增日志信息
				shipbillOperateLogSaveVO.setShipbillId(detailModel.getShipbillId());
				shipbillOperateLogSaveVO.setShipbillNo(detailModel.getShipbillNo());
				shipbillOperateLogSaveVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_NODE_STATUSNAME_PC);
				shipbillOperateLogService.addShipbillOperateLogData(shipbillOperateLogSaveVO);

				// 更新运输记录表的调度审核时间
				Criteria criteriaTransLog = Criteria.forClass(TmsShipbillTransLogModel.class);
				Restriction r3 = Restrictions.eq(TmsShipbillTransLogModel::getShipbillId, detailModel.getShipbillId());
				Restriction r4 = Restrictions.eq(TmsShipbillTransLogModel::getEnterpriseId, user.getEnterpriseId());
				criteriaTransLog.setRestriction(Restrictions.and(r3, r4));

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

			}
			// 更改派车单状态
			// 装车单类型
			if (shipperTypeCnt == tmsLoadingBillDetailModels.size()) {
				tmsLoadingBillHeaderModel.setLoadingBillType(DataDictionaryConstant.LOADING_BILL_TYPE_CK);
			} else if (consigneeType == tmsLoadingBillDetailModels.size()) {
				tmsLoadingBillHeaderModel.setLoadingBillType(DataDictionaryConstant.LOADING_BILL_TYPE_RK);
			} else {
				tmsLoadingBillHeaderModel.setLoadingBillType(DataDictionaryConstant.LOADING_BILL_TYPE_QT);
			}
			tmsLoadingBillHeaderModel.setUpdateperson(user.getNickname());
			tmsLoadingBillHeaderModel.setUpdatetime(date);
			tmsLoadingBillHeaderModel.setStatus(DataDictionaryConstant.LOADING_BILL_STATUS_YSH);
			tmsLoadingBillHeaderMapper.update(tmsLoadingBillHeaderModel);
			MessageUtil.addMessage(new SendMessageDTO(MessageOrderTypeEnum.LOADING_NO.getCode(), MessageTypeEnum.CARRIER_DISPATCH_AUDIT.getCode(), Lists.newArrayList(tmsLoadingBillHeaderModel.getLoadingBillId())));
		}
	}

	/**
	 * 已托运审核
	 *
	 * @param ids
	 */
	public void autoSelfTrailerAuditData(List<String> ids, Date date, UserEntity user) {
		ToolKits.isParamNull(ids, "托运单ID不为空");

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

		List<TmsLoadingBillHeaderModel> tmsLoadingBillHeaderModels = tmsLoadingBillHeaderMapper.findByIds(TmsLoadingBillHeaderModel.class, ids.toArray(), null);

		// 判断托运单是否已审核
		String str = tmsLoadingBillHeaderModels.stream().filter(o -> DataDictionaryConstant.LOADING_BILL_STATUS_YSH == o.getStatus()).map(TmsLoadingBillHeaderModel::getLoadingBillNo).collect(Collectors.joining(","));

		if (ToolKits.isNotEmpty(str)) {
			throw new RuntimeException("托运单[" + str + "]已审核!");
		}
		for (TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel : tmsLoadingBillHeaderModels) {

			// 更改运单状态
			Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
			Restriction r1 = Restrictions.eq("loadingBillId", tmsLoadingBillHeaderModel.getLoadingBillId());
			Restriction r2 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
			criteria.setRestriction(Restrictions.and(r1, r2));
			List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteria);

			// 记录运单日志
			int shipperTypeCnt = 0;
			int consigneeType = 0;
			for (TmsLoadingBillDetailModel detailModel : tmsLoadingBillDetailModels) {
				if (detailModel.getShipperType() == DataDictionaryConstant.SHIPPER_TYPE_CK) {
					shipperTypeCnt++;
				}
				if (detailModel.getConsigneeType() == DataDictionaryConstant.CONSIGNEE_TYPE_CK) {
					consigneeType++;
				}
				ShipbillNodeTrackingSaveVO shipbillNodeTrackingSaveVO = new ShipbillNodeTrackingSaveVO();
				ShipbillOperateLogSaveVO shipbillOperateLogSaveVO = new ShipbillOperateLogSaveVO();
				Map<String, Object> mapUpdateShipbillHeader = Maps.newHashMap();
				Map<String, Object> mapUpdateLoadingDetail = Maps.newHashMap();

				mapUpdateShipbillHeader.put("updateperson", user.getNickname());
				mapUpdateShipbillHeader.put("updatetime", date);
				mapUpdateLoadingDetail.put("updateperson", user.getNickname());
				mapUpdateLoadingDetail.put("updatetime", date);

				int status = DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED_CHECK;

				mapUpdateLoadingDetail.put("carrierShipbillStatus", status);
				mapUpdateShipbillHeader.put("carrierShipbillStatus", status);

				shipbillNodeTrackingSaveVO.setStatus(status);
				shipbillOperateLogSaveVO.setOldStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED);
				shipbillOperateLogSaveVO.setNewStatus(status);

				shipbillNodeTrackingSaveVO.setNodeEvent(DataDictionaryConstant.CARRIER_SHIPBILL_NODE_STATUSNAME_TY);
				shipbillOperateLogSaveVO.setOperateEvent(DataDictionaryConstant.CARRIER_SHIPBILL_NODE_STATUSNAME_TY);

				// 更改运单状态
				tmsShipbillHeaderMapper.updateMapById(detailModel.getShipbillId(), mapUpdateShipbillHeader, TmsShipbillHeaderModel.class);
				// 更新托运单明细状态
				tmsLoadingBillDetailMapper.updateMapById(detailModel.getId(), mapUpdateLoadingDetail, TmsLoadingBillDetailModel.class);
				// 新增节点信息
				shipbillNodeTrackingSaveVO.setShipbillId(detailModel.getShipbillId());
				shipbillNodeTrackingSaveVO.setShipbillNo(detailModel.getShipbillNo());
				shipbillNodeTrackingService.addShipbillNodeTrackingData(shipbillNodeTrackingSaveVO);

				// 新增日志信息
				shipbillOperateLogSaveVO.setShipbillId(detailModel.getShipbillId());
				shipbillOperateLogSaveVO.setShipbillNo(detailModel.getShipbillNo());
				shipbillOperateLogSaveVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_NODE_STATUSNAME_PC);
				shipbillOperateLogService.addShipbillOperateLogData(shipbillOperateLogSaveVO);

				// 更新运输记录表的调度审核时间
				Criteria criteriaTransLog = Criteria.forClass(TmsShipbillTransLogModel.class);
				Restriction r3 = Restrictions.eq(TmsShipbillTransLogModel::getShipbillId, detailModel.getShipbillId());
				Restriction r4 = Restrictions.eq(TmsShipbillTransLogModel::getEnterpriseId, user.getEnterpriseId());
				criteriaTransLog.setRestriction(Restrictions.and(r3, r4));

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

			}

			// 更改托运单状态
			// 装车单类型
			if (shipperTypeCnt == tmsLoadingBillDetailModels.size()) {
				tmsLoadingBillHeaderModel.setLoadingBillType(DataDictionaryConstant.LOADING_BILL_TYPE_CK);
			} else if (consigneeType == tmsLoadingBillDetailModels.size()) {
				tmsLoadingBillHeaderModel.setLoadingBillType(DataDictionaryConstant.LOADING_BILL_TYPE_RK);
			} else {
				tmsLoadingBillHeaderModel.setLoadingBillType(DataDictionaryConstant.LOADING_BILL_TYPE_QT);
			}
			tmsLoadingBillHeaderModel.setUpdateperson(user.getNickname());
			tmsLoadingBillHeaderModel.setUpdatetime(date);
			tmsLoadingBillHeaderModel.setStatus(DataDictionaryConstant.LOADING_BILL_STATUS_YSH);
			tmsLoadingBillHeaderMapper.update(tmsLoadingBillHeaderModel);
			MessageUtil.addMessage(new SendMessageDTO(MessageOrderTypeEnum.LOADING_NO.getCode(), MessageTypeEnum.CARRIER_DISPATCH_AUDIT.getCode(), Lists.newArrayList(tmsLoadingBillHeaderModel.getLoadingBillId())));
		}
	}

	/**
	 * 获得第一个字符
	 *
	 * @param str
	 * @return
	 */
	public String getFirstStr(String str) {
		if (ToolKits.isEmpty(str)) {
			return null;
		}
		String[] arr1 = str.split(",");
		return arr1[0];
	}

	/**
	 * 去掉数组第一个元素
	 *
	 * @param str
	 * @return
	 */
	public String subArrToString(String str) {
		if (ToolKits.isEmpty(str)) {
			return null;
		}
		String[] arr1 = str.split(",");
		if (null == arr1) {
			return null;
		} else if (1 == arr1.length) {
			return null;
		} else if (1 < arr1.length) {
			String[] arr2 = (String[]) ArrayUtils.subarray(arr1, 1, arr1.length);
			return Arrays.stream(arr2).collect(Collectors.joining(","));
		}
		return null;
	}

	// 调度审核匹配审批流程
	public Boolean approvalOpen(TmsLoadingBillHeaderModel loadingBillHeaderModel, TmsShipbillHeaderModel model, Integer approvalFlowType, UserEntity user) {
		// 封装判断所需数据
		ApprovalOpenVO approvalOpenVO = new ApprovalOpenVO();
		approvalOpenVO.setApprovalFlowType(approvalFlowType);
		approvalOpenVO.setApprovalObjectId(loadingBillHeaderModel.getLoadingBillId());
		approvalOpenVO.setApprovalObjectCode(loadingBillHeaderModel.getLoadingBillNo());
		approvalOpenVO.setApprovalObjectName(loadingBillHeaderModel.getLoadingBillNo());
		approvalOpenVO.setInitiatedUserId(user.getUserid());
		approvalOpenVO.setInitiatedUserName(user.getNickname());

		// 配送方式
		approvalOpenVO.setDeliveryMethodType(model.getDeliveryMethodType());
		// 发货方类型
		approvalOpenVO.setShipperType(model.getShipperType());
		// 发货方单位ID
		approvalOpenVO.setShipperUnitId(model.getShipperUnitId());
		// 收货方类型
		approvalOpenVO.setConsigneeType(model.getConsigneeType());
		// 收货方单位ID
		approvalOpenVO.setConsigneeUnitId(model.getConsigneeUnitId());
		// 订单类型
		approvalOpenVO.setOrderType(model.getOrderType());
		// 订单业务类型
		approvalOpenVO.setOrderBusinessType(model.getOrderBusinessType());
		// 运输模式
		approvalOpenVO.setTransportType(model.getTransportType());
		// 温度要求
		approvalOpenVO.setTemperatureRequirement(model.getTemperatureRequirement());
		// 货主ID
		approvalOpenVO.setCargoOwnerId(model.getCargoOwnerId());
		// 部门ID
		approvalOpenVO.setDepartmentId(model.getDepartmentId());

		RestMessage<Boolean> restMessage1 = maindataTmsResource.openExecute(approvalOpenVO);
		if (!restMessage1.isSuccess()) {
			throw new RuntimeException("调用maindata服务是否开启审批流接口失败:" + restMessage1.getMessage());
		}
		return restMessage1.getData();
	}

	/**
	 * 调度单审核信息查询
	 *
	 * @param approvalInfoVO
	 * @return
	 */
	public DispatchCkApprovalSCDTO getApprovalInfoData(DispatchApprovalInfoVO approvalInfoVO) {
		ToolKits.isParamNull(approvalInfoVO, "调度单审核信息查询请求不为空");
		ToolKits.isParamNull(approvalInfoVO.getLoadingBillId(), "派车单ID不为空");
		ToolKits.isParamNull(approvalInfoVO.getApprovalBusinessId(), "审批业务ID不为空");

		UserEntity user = PlgFxUsrUtils.getUserEntity();
		ToolKits.isParamNull(user, "当前人员没有操作权限");
		DispatchCkApprovalSCDTO approvalSCDTO = new DispatchCkApprovalSCDTO();
		// 数据字典翻译数据集合
		List<Map<String, Object>> data1 = Lists.newArrayList();
		List<Map<String, Object>> data2 = Lists.newArrayList();
		List<Map<String, Object>> data3 = Lists.newArrayList();
		List<Map<String, Object>> data4 = Lists.newArrayList();
		List<Map<String, Object>> data5 = Lists.newArrayList();
		List<Map<String, Object>> data6 = Lists.newArrayList();
		List<Map<String, Object>> data7 = Lists.newArrayList();
		List<Map<String, Object>> data8 = Lists.newArrayList();
		List<Map<String, Object>> data9 = Lists.newArrayList();
		// 承运方类型
		RestMessage<List<Map<String, Object>>> restMessage9 = maindataTmsResource.getDropDownById(DataDictionaryConstant.LINE_CARRIER_TYPE, null, null, null);
		if (!restMessage9.isSuccess()) {
			throw new RuntimeException("承运方类型翻译失败");
		} else {
			data9 = restMessage9.getData();
		}

		TmsLoadingBillHeaderModel loadingBillHeaderModel = tmsLoadingBillHeaderMapper.findById(approvalInfoVO.getLoadingBillId(), TmsLoadingBillHeaderModel.class);
		if (ToolKits.isEmpty(loadingBillHeaderModel)) {
			throw new PrologException("调度单【" + approvalInfoVO.getLoadingBillId() + "】信息不存在");
		}
		// 设定调度单信息
		BeanUtils.copyProperties(loadingBillHeaderModel, approvalSCDTO);
		approvalSCDTO.setCarrierTypeName(PublicMethods.change(data9, String.valueOf(loadingBillHeaderModel.getCarrierType())));

		// 查询明细内容
		Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
		Restriction r1 = Restrictions.eq(TmsLoadingBillDetailModel::getLoadingBillId, approvalInfoVO.getLoadingBillId());
		criteria.setRestriction(r1);
		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteria);
		if (ToolKits.isEmpty(tmsLoadingBillDetailModels)) {
			throw new PrologException("调度单【" + approvalInfoVO.getLoadingBillId() + "】的明细信息不存在");
		}

		List<ShipbillInfoDTO> shipbillInfoDTOS = Lists.newArrayList();

		// 订单类型
		RestMessage<List<Map<String, Object>>> restMessage1 = maindataTmsResource.getDropDownById(DataDictionaryConstant.ORDER_TYPE, null, null, null);
		if (!restMessage1.isSuccess()) {
			throw new RuntimeException("订单类型翻译失败!");
		} else {
			data1 = restMessage1.getData();
		}
		// 订单业务类型
		RestMessage<List<Map<String, Object>>> restMessage2 = maindataTmsResource.getDropDownById(DataDictionaryConstant.ORDER_BUSINESS_TYPE, null, null, null);
		if (!restMessage2.isSuccess()) {
			throw new RuntimeException("订单业务类型翻译失败!");
		} else {
			data2 = restMessage2.getData();
		}
		// 配送方式
		RestMessage<List<Map<String, Object>>> restMessage3 = maindataTmsResource.getDropDownById(DataDictionaryConstant.DELIVERY_METHOD_TYPE, null, null, null);
		if (!restMessage3.isSuccess()) {
			throw new RuntimeException("配送方式翻译失败!");
		} else {
			data3 = restMessage3.getData();
		}
		// 运输类型(运输模式)
		RestMessage<List<Map<String, Object>>> restMessage4 = maindataTmsResource.getDropDownById(DataDictionaryConstant.TRANSPORT_TYPE, null, null, null);
		if (!restMessage4.isSuccess()) {
			throw new RuntimeException("运输类型(运输模式)翻译失败!");
		} else {
			data4 = restMessage4.getData();
		}
		// 温度要求
		RestMessage<List<Map<String, Object>>> restMessage5 = maindataTmsResource.getDropDownById(DataDictionaryConstant.TEMPERATURE_REQUIREMENT, null, null, null);
		if (!restMessage5.isSuccess()) {
			throw new RuntimeException("温度要求翻译失败!");
		} else {
			data5 = restMessage5.getData();
		}
		// 发货方类型
		RestMessage<List<Map<String, Object>>> restMessage6 = maindataTmsResource.getDropDownById(DataDictionaryConstant.SHIPPER_TYPE, null, null, null);
		if (!restMessage6.isSuccess()) {
			throw new RuntimeException("发货方类型翻译失败!");
		} else {
			data6 = restMessage6.getData();
		}
		// 收货方类型
		RestMessage<List<Map<String, Object>>> restMessage7 = maindataTmsResource.getDropDownById(DataDictionaryConstant.CONSIGNEE_TYPE, null, null, null);
		if (!restMessage7.isSuccess()) {
			throw new RuntimeException("收货方类型翻译失败!");
		} else {
			data7 = restMessage7.getData();
		}
		// 运单状态
		RestMessage<List<Map<String, Object>>> restMessage8 = maindataTmsResource.getDropDownById(DataDictionaryConstant.SHIPBILL_STATUS, null, null, null);
		if (!restMessage8.isSuccess()) {
			throw new RuntimeException("运单状态翻译失败!");
		} else {
			data8 = restMessage8.getData();
		}

		// 运单信息
		for (TmsLoadingBillDetailModel detailModel : tmsLoadingBillDetailModels) {
			ShipbillInfoDTO shipbillInfoDTO = new ShipbillInfoDTO();
			BeanUtils.copyProperties(detailModel, shipbillInfoDTO);

			shipbillInfoDTO.setOrderTypeName(PublicMethods.change(data1, String.valueOf(detailModel.getOrderType())));
			shipbillInfoDTO.setOrderBusinessTypeName(PublicMethods.change(data2, String.valueOf(detailModel.getOrderBusinessType())));
			shipbillInfoDTO.setDeliveryMethodTypeName(PublicMethods.change(data3, String.valueOf(detailModel.getDeliveryMethodType())));
			shipbillInfoDTO.setTransportTypeName(PublicMethods.change(data4, String.valueOf(detailModel.getTransportType())));
			shipbillInfoDTO.setTemperatureRequirementName(PublicMethods.change(data5, String.valueOf(detailModel.getTemperatureRequirement())));
			shipbillInfoDTO.setShipperTypeName(PublicMethods.change(data6, String.valueOf(detailModel.getShipperType())));
			shipbillInfoDTO.setConsigneeTypeName(PublicMethods.change(data7, String.valueOf(detailModel.getConsigneeType())));
			shipbillInfoDTO.setStatusName(PublicMethods.change(data8, String.valueOf(detailModel.getStatus())));

			// 收货方位置(经纬度判断)
			if (ToolKits.isNotEmpty(detailModel.getConsigneeLongitude()) && ToolKits.isNotEmpty(detailModel.getConsigneeLatitude())) {
				shipbillInfoDTO.setConsigneePositioning(StatusConstant.POSITIONING_YDW);
			} else {
				shipbillInfoDTO.setConsigneePositioning(StatusConstant.POSITIONING_WDW);
			}
			// 发货方位置(经纬度判断)
			if (ToolKits.isNotEmpty(detailModel.getShipperLongitude()) && ToolKits.isNotEmpty(detailModel.getShipperLatitude())) {
				shipbillInfoDTO.setShipperPositioning(StatusConstant.POSITIONING_YDW);
			} else {
				shipbillInfoDTO.setShipperPositioning(StatusConstant.POSITIONING_WDW);
			}

			// 目的地
			StringBuffer consigneeProvinceCityDistrict = new StringBuffer();
			consigneeProvinceCityDistrict.append(detailModel.getConsigneeProvinceName());
			consigneeProvinceCityDistrict.append(detailModel.getConsigneeCityName());
			consigneeProvinceCityDistrict.append(detailModel.getConsigneeDistrictName());
			shipbillInfoDTO.setConsigneeProvinceCityDistrict(consigneeProvinceCityDistrict.toString());

			// 始发地
			StringBuffer shipperProvinceCityDistrict = new StringBuffer();
			shipperProvinceCityDistrict.append(detailModel.getShipperProvinceName());
			shipperProvinceCityDistrict.append(detailModel.getShipperCityName());
			shipperProvinceCityDistrict.append(detailModel.getShipperDistrictName());
			shipbillInfoDTO.setShipperProvinceCityDistrict(shipperProvinceCityDistrict.toString());

			shipbillInfoDTOS.add(shipbillInfoDTO);
		}
		approvalSCDTO.setShipbillInfoDTOList(shipbillInfoDTOS);

		RestMessage<List<ApprovalLogDTO>> resourceBusLog = maindataTmsResource.getBusLog(approvalInfoVO.getApprovalBusinessId());
		if (!resourceBusLog.isSuccess()) {
			throw new PrologException("调用审批日志服务失败!");
		}
		approvalSCDTO.setShipbillApprovalLogDTOList(resourceBusLog.getData());

		RestMessage<List<ApprovalNodeSelDTO>> resourceBusDetail = maindataTmsResource.getBusDetail(approvalInfoVO.getApprovalBusinessId());
		if (!resourceBusLog.isSuccess()) {
			throw new PrologException("调用审批节点服务失败!");
		}
		approvalSCDTO.setShipbillApprovalNodeDTOList(resourceBusDetail.getData());

		return approvalSCDTO;
	}

	/**
	 * 调度单审批作废
	 *
	 * @param approvalInvalidVO
	 */
	public void dispatchApprovalInvalidData(DispatchCkApprovalInvalidVO approvalInvalidVO) {
		ToolKits.isParamNull(approvalInvalidVO, "调度单审批作废请求不为空");
		ToolKits.isParamNull(approvalInvalidVO.getLoadingBillId(), "派车单ID不为空");
		ToolKits.isParamNull(approvalInvalidVO.getApprovalBusinessId(), "审批业务ID不为空");

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

		// 审核业务作废
		RestMessage<Object> restMessage = maindataTmsResource.approvalInvalidExecute(approvalInvalidVO.getApprovalBusinessId());
		if (!restMessage.isSuccess()) {
			throw new RuntimeException("调用审核作废失败");
		}
		Date date = DateUtils.nowDate();
		Map<String, Object> map = Maps.newHashMap();
		map.put("status", DataDictionaryConstant.LOADING_BILL_STATUS_WSH);
		map.put("updatetime", date);
		map.put("updateperson", user.getNickname());
		// 调度单状态更新
		tmsLoadingBillHeaderMapper.updateMapById(approvalInvalidVO.getLoadingBillId(), map, TmsLoadingBillHeaderModel.class);

		// 调度单明细更新
		// 查询明细内容
		Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
		Restriction r1 = Restrictions.eq(TmsLoadingBillDetailModel::getLoadingBillId, approvalInvalidVO.getLoadingBillId());
		criteria.setRestriction(r1);
		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteria);

		if (ToolKits.isEmpty(tmsLoadingBillDetailModels)) {
			throw new PrologException("调度单【" + approvalInvalidVO.getLoadingBillId() + "】的明细信息不存在");
		}

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

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

		for (TmsLoadingBillDetailModel detailModel : tmsLoadingBillDetailModels) {
			mapUpdateLoadingDetail.put("carrierShipbillStatus", DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED);
			mapUpdateShipbillHeader.put("carrierShipbillStatus", DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED);
			mapUpdateLoadingDetail.put("status", DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH_CHECK);
			mapUpdateShipbillHeader.put("status", DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH_CHECK);

			// 更改运单状态
			tmsShipbillHeaderMapper.updateMapById(detailModel.getShipbillId(), mapUpdateShipbillHeader, TmsShipbillHeaderModel.class);
			// 更新派车单明细状态
			tmsLoadingBillDetailMapper.updateMapById(detailModel.getId(), mapUpdateLoadingDetail, TmsLoadingBillDetailModel.class);
		}
	}

	/**
	 * 调度单审批流撤回
	 *
	 * @param approvalRetractVO
	 */
	public void dispatchApprovalRetractData(DispatchApprovalRetractVO approvalRetractVO) {

		ToolKits.isParamNull(approvalRetractVO, "调度单审批撤回请求不为空");
		ToolKits.isParamNull(approvalRetractVO.getLoadingBillId(), "派车单ID不为空");
		ToolKits.isParamNull(approvalRetractVO.getApprovalBusinessId(), "审批业务ID不为空");

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

		// 审核业务撤回
		RestMessage<Object> restMessage = maindataTmsResource.approvalRetractExecute(approvalRetractVO.getApprovalBusinessId());
		if (!restMessage.isSuccess()) {
			throw new RuntimeException("调用审核撤回失败");
		}
	}

	/**
	 * 调度单审批流提交
	 *
	 * @param approvalSubmitVO
	 */
	public void dispatchApprovalSubmitData(DispatchApprovalSubmitVO approvalSubmitVO) {
		ToolKits.isParamNull(approvalSubmitVO, "调度单审批提交请求不为空");
		ToolKits.isParamNull(approvalSubmitVO.getLoadingBillId(), "派车单ID不为空");
		ToolKits.isParamNull(approvalSubmitVO.getApprovalBusinessId(), "审批业务ID不为空");

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

		// 提交当前审批
		RestMessage<Object> restMessage1 = maindataTmsResource.approvalSubmitExecute(approvalSubmitVO.getApprovalBusinessId());
		if (!restMessage1.isSuccess()) {
			throw new RuntimeException("调用审批提交失败");
		}
	}

	/**
	 * 调度单审批流审核
	 *
	 * @param approvalVO
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void dispatchApprovalData(DispatchApprovalVO approvalVO) {
		ToolKits.isParamNull(approvalVO, "调度单审核请求不为空");
		ToolKits.isParamNull(approvalVO.getApprovalObjectId(), "运单ID不为空");
		ToolKits.isParamNull(approvalVO.getApprovalBusinessId(), "审批业务ID不为空");
		ToolKits.isParamNull(approvalVO.getApprovalObjectName(), "审批对象名称不为空");
		ToolKits.isParamNull(approvalVO.getApprovalId(), "审批流程ID不为空");
		ToolKits.isParamNull(approvalVO.getNextApproverNodeId(), "下一审批节点ID不为空");
		ToolKits.isParamNull(approvalVO.getNextApprovalOrder(), "下一节点顺序不为空");

		ToolKits.isParamNull(approvalVO.getResult(), "审批结果不为空");

		if (!approvalVO.getResult().equals(DataDictionaryConstant.NODE_APPROVAL_RESULT_PASS)) {
			ToolKits.isParamNull(approvalVO.getApprovalOpinion(), "驳回意见不为空");
		}

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

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

		TmsLoadingBillHeaderModel loadingBillHeaderModel = tmsLoadingBillHeaderMapper.findById(approvalVO.getApprovalObjectId(), TmsLoadingBillHeaderModel.class);
		if (ToolKits.isEmpty(loadingBillHeaderModel)) {
			throw new PrologException("调度单【" + approvalVO.getApprovalObjectId() + "】不存在");
		}
		if (!loadingBillHeaderModel.getStatus().equals(DataDictionaryConstant.LOADING_BILL_STATUS_DIS_APPROVAL)) {
			throw new PrologException("运单【" + approvalVO.getApprovalObjectId() +"】已审批");
		}

		// 封装审核所需数据
		ApprovalBusinessNodeVO approvalBusinessNodeVO = new ApprovalBusinessNodeVO();
		approvalBusinessNodeVO.setApprovalObjectName(approvalVO.getApprovalObjectName());
		approvalBusinessNodeVO.setApprovalBusinessId(approvalVO.getApprovalBusinessId());
		approvalBusinessNodeVO.setApprovalId(approvalVO.getApprovalId());
		approvalBusinessNodeVO.setNextApprovalNodeId(approvalVO.getNextApproverNodeId());
		approvalBusinessNodeVO.setNextApprovalOrder(approvalVO.getNextApprovalOrder());
		approvalBusinessNodeVO.setNextApproverRoleId(approvalVO.getNextApproverRoleId());
		approvalBusinessNodeVO.setNextApproverRoleName(approvalVO.getNextApproverRoleName());
		approvalBusinessNodeVO.setNextApproverUserId(approvalVO.getNextApproverUserId());
		approvalBusinessNodeVO.setNextApproverUserName(approvalVO.getNextApproverUserName());
		approvalBusinessNodeVO.setApproverPersonId(user.getUserid());
		approvalBusinessNodeVO.setApproverPersonName(user.getNickname());
		approvalBusinessNodeVO.setApprovalOpinion(ToolKits.isEmpty(approvalVO.getApprovalOpinion()) ? "" : approvalVO.getApprovalOpinion());
		approvalBusinessNodeVO.setApprovalTime(date);
		approvalBusinessNodeVO.setResult(approvalVO.getResult());

		approvalBusinessNodeVO.setApproverPersonRoleId(user.getRoles().stream().map(role -> String.valueOf(role)).collect(Collectors.joining(",")));
		approvalBusinessNodeVO.setApproverPersonRoleName("");

		// 节点审批者类型 数据字典 NODE_APPROVER_TYPE 1 角色 2 用户
		approvalBusinessNodeVO.setNodeApproverType(approvalVO.getNodeApproverType());
		// 审批方式 数据字典 NODE_APPROVAL_TYPE: 1 会签 2 或签
		approvalBusinessNodeVO.setNodeApprovalType(approvalVO.getNodeApprovalType());

		// 流程节点审批
		RestMessage<Boolean> restMessage1 = maindataTmsResource.nodeApprovalExecute(approvalBusinessNodeVO);
		if (!restMessage1.isSuccess()) {
			throw new RuntimeException("调用审核失败");
		}
		Boolean isFinish = restMessage1.getData();

		// 判断是否已结束流程
		if (isFinish) {
			// 流程结束
			Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
			Restriction r1 = Restrictions.eq("loadingBillId", loadingBillHeaderModel.getLoadingBillId());
			criteria.setRestriction(r1);
			List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteria);

			if (ToolKits.isEmpty(tmsLoadingBillDetailModels)) {
				throw new PrologException("调度单【" + approvalVO.getApprovalObjectId() + "】的明细信息不存在");
			}

			int shipperTypeCnt = 0;
			int consigneeType = 0;
			for (TmsLoadingBillDetailModel detailModel : tmsLoadingBillDetailModels) {
				if (detailModel.getShipperType() == DataDictionaryConstant.SHIPPER_TYPE_CK) {
					shipperTypeCnt++;
				}
				if (detailModel.getConsigneeType() == DataDictionaryConstant.CONSIGNEE_TYPE_CK) {
					consigneeType++;
				}
				ShipbillNodeTrackingSaveVO shipbillNodeTrackingSaveVO = new ShipbillNodeTrackingSaveVO();
				ShipbillOperateLogSaveVO shipbillOperateLogSaveVO = new ShipbillOperateLogSaveVO();
				Map<String, Object> mapUpdateShipbillHeader = Maps.newHashMap();
				Map<String, Object> mapUpdateLoadingDetail = Maps.newHashMap();

				mapUpdateShipbillHeader.put("updateperson", user.getNickname());
				mapUpdateShipbillHeader.put("updatetime", date);
				mapUpdateLoadingDetail.put("updateperson", user.getNickname());
				mapUpdateLoadingDetail.put("updatetime", date);

				if (DataDictionaryConstant.LINE_CARRIER_TYPE_SJ.equals(loadingBillHeaderModel.getCarrierType())) {
					String flowConfig = detailModel.getFlowConfig();
					if (ToolKits.isNotEmpty(detailModel.getCarrierFlowConfig())) {
						flowConfig = detailModel.getCarrierFlowConfig();
					}
					// 判定下一步流程
					int status = businessFlowUtil.judgmentNextFlowSts(flowConfig, DataDictionaryConstant.FLOW_CONFIG_CHECK);
					mapUpdateLoadingDetail.put("status", status);
					mapUpdateShipbillHeader.put("status", status);
					mapUpdateLoadingDetail.put("carrierShipbillStatus", DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED_CHECK);
					mapUpdateShipbillHeader.put("carrierShipbillStatus", DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED_CHECK);

					shipbillNodeTrackingSaveVO.setStatus(status);
					shipbillOperateLogSaveVO.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH);
					shipbillOperateLogSaveVO.setNewStatus(status);

					shipbillNodeTrackingSaveVO.setNodeEvent(DataDictionaryConstant.CARRIER_SHIPBILL_NODE_STATUSNAME_PC);
					shipbillOperateLogSaveVO.setOperateEvent(DataDictionaryConstant.CARRIER_SHIPBILL_NODE_STATUSNAME_PC);
				} else {
					// 承运商账号
					// 判定下一步流程
					int status = DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED_CHECK;

					mapUpdateLoadingDetail.put("carrierShipbillStatus", status);
					mapUpdateShipbillHeader.put("carrierShipbillStatus", status);

					shipbillNodeTrackingSaveVO.setStatus(status);
					shipbillOperateLogSaveVO.setOldStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED);
					shipbillOperateLogSaveVO.setNewStatus(status);

					shipbillNodeTrackingSaveVO.setNodeEvent(DataDictionaryConstant.CARRIER_SHIPBILL_NODE_STATUSNAME_TY);
					shipbillOperateLogSaveVO.setOperateEvent(DataDictionaryConstant.CARRIER_SHIPBILL_NODE_STATUSNAME_TY);
				}

				// 更改运单状态
				tmsShipbillHeaderMapper.updateMapById(detailModel.getShipbillId(), mapUpdateShipbillHeader, TmsShipbillHeaderModel.class);
				// 更新派车单明细状态
				tmsLoadingBillDetailMapper.updateMapById(detailModel.getId(), mapUpdateLoadingDetail, TmsLoadingBillDetailModel.class);
				// 新增节点信息
				shipbillNodeTrackingSaveVO.setShipbillId(detailModel.getShipbillId());
				shipbillNodeTrackingSaveVO.setShipbillNo(detailModel.getShipbillNo());
				shipbillNodeTrackingService.addShipbillNodeTrackingData(shipbillNodeTrackingSaveVO);

				// 新增日志信息
				shipbillOperateLogSaveVO.setShipbillId(detailModel.getShipbillId());
				shipbillOperateLogSaveVO.setShipbillNo(detailModel.getShipbillNo());
				shipbillOperateLogSaveVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_NODE_STATUSNAME_PC);
				shipbillOperateLogService.addShipbillOperateLogData(shipbillOperateLogSaveVO);

				// 更新运输记录表的调度审核时间
				Criteria criteriaTransLog = Criteria.forClass(TmsShipbillTransLogModel.class);
				Restriction r3 = Restrictions.eq(TmsShipbillTransLogModel::getShipbillId, detailModel.getShipbillId());
				Restriction r4 = Restrictions.eq(TmsShipbillTransLogModel::getEnterpriseId, user.getEnterpriseId());
				criteriaTransLog.setRestriction(Restrictions.and(r3, r4));

				Map<String, Object> mapUpdate = Maps.newHashMap();
				mapUpdate.put("updateperson", user.getNickname());
				mapUpdate.put("updatetime", date);
				mapUpdate.put("disCheckDt", date);
				tmsShipbillTransportLogMapper.updateMapByCriteria(mapUpdate, criteriaTransLog);
			}
			// 更改派车单状态
			// 装车单类型
			if (shipperTypeCnt == tmsLoadingBillDetailModels.size()) {
				loadingBillHeaderModel.setLoadingBillType(DataDictionaryConstant.LOADING_BILL_TYPE_CK);
			} else if (consigneeType == tmsLoadingBillDetailModels.size()) {
				loadingBillHeaderModel.setLoadingBillType(DataDictionaryConstant.LOADING_BILL_TYPE_RK);
			} else {
				loadingBillHeaderModel.setLoadingBillType(DataDictionaryConstant.LOADING_BILL_TYPE_QT);
			}
			loadingBillHeaderModel.setUpdateperson(user.getNickname());
			loadingBillHeaderModel.setUpdatetime(date);
			loadingBillHeaderModel.setStatus(DataDictionaryConstant.LOADING_BILL_STATUS_YSH);
			tmsLoadingBillHeaderMapper.update(loadingBillHeaderModel);
			MessageTypeEnum messageTypeEnum = MessageTypeEnum.SELF_DISPATCH_AUDIT;
			if (user.getUserType().equals(BussinessConstant.USER_TYPE_CYS)) {
				messageTypeEnum = MessageTypeEnum.CARRIER_DISPATCH_AUDIT;
			}
			MessageUtil.addMessage(new SendMessageDTO(MessageOrderTypeEnum.LOADING_NO.getCode(), messageTypeEnum.getCode(), Lists.newArrayList(loadingBillHeaderModel.getLoadingBillId())));
		}
	}
}
