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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.prolog.common.util.DateUtils;
import com.prolog.common.util.ToolKits;
import com.prolog.framework.common.message.RestMessage;
import com.prolog.framework.core.exception.BizException;
import com.prolog.framework.core.exception.PrologException;
import com.prolog.framework.core.pojo.Page;
import com.prolog.framework.core.restriction.*;
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.constant.enums.LoadingScanOrderTypeEnum;
import com.prolog.rdc.tms.constant.enums.intelligent.IntelligentLockEnum;
import com.prolog.rdc.tms.dao.mapper.*;
import com.prolog.rdc.tms.model.TmsShipbillDetailScanModel;
import com.prolog.rdc.tms.model.dto.*;
import com.prolog.rdc.tms.model.dto.basicConfigure.SignconfigPopDTO;
import com.prolog.rdc.tms.model.dto.basicData.ItemCheckDTO;
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.SignconfigPopVO;
import com.prolog.rdc.tms.model.vo.basicData.ItemCheckVO;
import com.prolog.rdc.tms.model.vo.fleetManagement.VehicleCheckVO;
import com.prolog.rdc.tms.rmi.feign.MaindataFeign;
import com.prolog.rdc.tms.service.BookingService;
import com.prolog.rdc.tms.service.ShipbillNodeTrackingService;
import com.prolog.rdc.tms.service.ShipbillOperateLogService;
import com.prolog.rdc.tms.service.WaitLoadingAndUnloadingService;
import com.prolog.rdc.tms.util.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 待装卸实现层
 * <p>
 * Company: 湖北普罗格科技股份有限公司
 *
 * @author zhangsj
 * @since 2022/6/6 10:35
 */
@Service
public class WaitLoadingAndUnloadingServiceImpl implements WaitLoadingAndUnloadingService {

	@Autowired
	private TmsLoadingBillHeaderMapper tmsLoadingBillHeaderMapper;

	@Autowired
	private TmsLoadingBillDetailMapper tmsLoadingBillDetailMapper;

	@Autowired
	private TmsShipbillHeaderMapper tmsShipbillHeaderMapper;

	@Autowired
	private TmsShipbillDetailMapper tmsShipbillDetailMapper;

	@Autowired
	private TmsShipbillDetailScanMapper tmsShipbillDetailScanMapper;

	@Autowired
	private TmsShipbillPackageMapper tmsShipbillPackageMapper;

	@Autowired
	private MaindataFeign maindataTmsResource;

	@Autowired
	private ShipbillOperateLogService shipbillOperateLogService;

	@Autowired
	private TmsShipbillTransportLogMapper tmsShipbillTransportLogMapper;

	@Autowired
	private ShipbillNodeTrackingService shipbillNodeTrackingService;

	@Autowired
	private BusinessFlowUtil businessFlowUtil;

	@Autowired
	private TmsAppointmentHeaderMapper tmsAppointmentHeaderMapper;

	@Autowired
	private TmsAppointmentDetailMapper tmsAppointmentDetailMapper;

	SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

	@Autowired
	private ConvertorUtil convertorUtil;

	@Autowired
	private BookingService bookingService;

	/**
	 * 运单模式分页查询
	 *
	 * @param queryTypeByShipbillVO
	 * @return
	 */
	@Override
	public Page<QueryTypeByShipbillDTO> queryTypeByShipbillPageData(QueryTypeByShipbillVO queryTypeByShipbillVO) {
		ToolKits.isParamNull(queryTypeByShipbillVO.getPageNum(), "当前页码不为空");
		ToolKits.isParamNull(queryTypeByShipbillVO.getPageSize(), "每页条数不为空");

		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<Map<String, Object>> data9 = Lists.newArrayList();
		List<Map<String, Object>> data10 = Lists.newArrayList();
		List<Map<String, Object>> data11 = Lists.newArrayList();
		List<Map<String, Object>> data12 = 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();
		}

		// 承运方类型
		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();
		}

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

		// 异常状态
		RestMessage<List<Map<String, Object>>> restMessage11 = maindataTmsResource.getDropDownById(DataDictionaryConstant.ABNORMAL_STATUS, null, null, null);
		if (!restMessage11.isSuccess()) {
			throw new RuntimeException("异常状态翻译失败!");
		} else {
			data11 = restMessage11.getData();
		}

		// 扫描状态
		RestMessage<List<Map<String, Object>>> restMessage12 = maindataTmsResource.getDropDownById(DataDictionaryConstant.SCAN_STATUS, null, null, null);
		if (!restMessage12.isSuccess()) {
			throw new RuntimeException("扫描状态翻译失败!");
		} else {
			data12 = restMessage12.getData();
		}

		// 权限控制
		if (user.getUserType().equals(BussinessConstant.USER_TYPE_ZY)) {
			// 判断是否是部门权限
			if (user.getOwnedAllDataAuthFlag().equals(BussinessConstant.USER_DEPARTMENT_AUTH_Y)) {
				queryTypeByShipbillVO.setIsDept(StatusConstant.IS_DEPT_YES);
				queryTypeByShipbillVO.setDepts(user.getDepts().toArray(new String[] {}));
			} else {
				queryTypeByShipbillVO.setIsDept(StatusConstant.IS_DEPT_NO);
				// 设置部门权限
				queryTypeByShipbillVO.setDepts(user.getDepts().toArray(new String[] {}));
				// 设置数据权限
				queryTypeByShipbillVO.setConsignors(user.getConsignors().toArray(new Long[] {}));
				queryTypeByShipbillVO.setWsarehouses(user.getWarehouses().toArray(new Long[] {}));
				queryTypeByShipbillVO.setCustomers(user.getCustomers().toArray(new Long[] {}));
				queryTypeByShipbillVO.setSuppliers(user.getSuppliers().toArray(new Long[] {}));
			}
		} else if (user.getUserType().equals(BussinessConstant.USER_TYPE_CYS)) {
			queryTypeByShipbillVO.setCarrierId(Long.valueOf(user.getLoginUserCompanyInfo().getId()));
		} else {
			throw new PrologException("当前人员没有操作权限");
		}
		queryTypeByShipbillVO.setUserType(user.getUserType());
		queryTypeByShipbillVO.setEnterpriseId(user.getEnterpriseId());

		PageUtils.startPage(queryTypeByShipbillVO.getPageNum(), queryTypeByShipbillVO.getPageSize());
		List<QueryTypeByShipbillDTO> queryTypeByShipbillDTOS = tmsLoadingBillHeaderMapper.queryTypeByShipbillPage(queryTypeByShipbillVO);

		for (QueryTypeByShipbillDTO queryTypeByShipbillDTO : queryTypeByShipbillDTOS) {
			// 类型翻译
			queryTypeByShipbillDTO.setOrderTypeName(PublicMethods.change(data1, String.valueOf(queryTypeByShipbillDTO.getOrderType())));
			queryTypeByShipbillDTO.setOrderBusinessTypeName(PublicMethods.change(data2, String.valueOf(queryTypeByShipbillDTO.getOrderBusinessType())));
			queryTypeByShipbillDTO.setDeliveryMethodTypeName(PublicMethods.change(data3, String.valueOf(queryTypeByShipbillDTO.getDeliveryMethodType())));
			queryTypeByShipbillDTO.setTransportTypeName(PublicMethods.change(data4, String.valueOf(queryTypeByShipbillDTO.getTransportType())));
			queryTypeByShipbillDTO.setTemperatureRequirementName(PublicMethods.change(data5, String.valueOf(queryTypeByShipbillDTO.getTemperatureRequirement())));
			queryTypeByShipbillDTO.setShipperTypeName(PublicMethods.change(data6, String.valueOf(queryTypeByShipbillDTO.getShipperType())));
			queryTypeByShipbillDTO.setConsigneeTypeName(PublicMethods.change(data7, String.valueOf(queryTypeByShipbillDTO.getConsigneeType())));
			queryTypeByShipbillDTO.setStatusName(PublicMethods.change(data8, String.valueOf(queryTypeByShipbillDTO.getStatus())));
			queryTypeByShipbillDTO.setCarrierTypeName(PublicMethods.change(data9, String.valueOf(queryTypeByShipbillDTO.getCarrierType())));
			queryTypeByShipbillDTO.setTransportStatusName(PublicMethods.change(data10, String.valueOf(queryTypeByShipbillDTO.getTransportStatus())));
			queryTypeByShipbillDTO.setAbnormalStatusName(PublicMethods.change(data11, String.valueOf(queryTypeByShipbillDTO.getAbnormalStatus())));
			queryTypeByShipbillDTO.setScanStatusName(PublicMethods.change(data12, String.valueOf(queryTypeByShipbillDTO.getScanStatus())));

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

	/**
	 * 运单模式高级查询
	 *
	 * @param advancedQueryTypeByShipbillVO
	 * @return
	 */
	@Override
	public Page<QueryTypeByShipbillDTO> advancedQueryTypeByShipbillPageData(AdvancedQueryTypeByShipbillVO advancedQueryTypeByShipbillVO) {
		ToolKits.isParamNull(advancedQueryTypeByShipbillVO.getPageNum(), "当前页码不为空");
		ToolKits.isParamNull(advancedQueryTypeByShipbillVO.getPageSize(), "每页条数不为空");

		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<Map<String, Object>> data9 = Lists.newArrayList();
		List<Map<String, Object>> data10 = Lists.newArrayList();
		List<Map<String, Object>> data11 = Lists.newArrayList();
		List<Map<String, Object>> data12 = 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();
		}

		// 承运方类型
		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();
		}

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

		// 异常状态
		RestMessage<List<Map<String, Object>>> restMessage11 = maindataTmsResource.getDropDownById(DataDictionaryConstant.ABNORMAL_STATUS, null, null, null);
		if (!restMessage11.isSuccess()) {
			throw new RuntimeException("异常状态翻译失败!");
		} else {
			data11 = restMessage11.getData();
		}

		// 扫描状态
		RestMessage<List<Map<String, Object>>> restMessage12 = maindataTmsResource.getDropDownById(DataDictionaryConstant.SCAN_STATUS, null, null, null);
		if (!restMessage12.isSuccess()) {
			throw new RuntimeException("扫描状态翻译失败!");
		} else {
			data12 = restMessage12.getData();
		}

		// 权限控制
		if (user.getUserType().equals(BussinessConstant.USER_TYPE_ZY)) {
			// 判断是否是部门权限
			if (user.getOwnedAllDataAuthFlag().equals(BussinessConstant.USER_DEPARTMENT_AUTH_Y)) {
				advancedQueryTypeByShipbillVO.setIsDept(StatusConstant.IS_DEPT_YES);
				advancedQueryTypeByShipbillVO.setDepts(user.getDepts().toArray(new String[] {}));
			} else {
				advancedQueryTypeByShipbillVO.setIsDept(StatusConstant.IS_DEPT_NO);
				// 设置部门权限
				advancedQueryTypeByShipbillVO.setDepts(user.getDepts().toArray(new String[] {}));
				// 设置数据权限
				advancedQueryTypeByShipbillVO.setConsignors(user.getConsignors().toArray(new Long[] {}));
				advancedQueryTypeByShipbillVO.setWsarehouses(user.getWarehouses().toArray(new Long[] {}));
				advancedQueryTypeByShipbillVO.setCustomers(user.getCustomers().toArray(new Long[] {}));
				advancedQueryTypeByShipbillVO.setSuppliers(user.getSuppliers().toArray(new Long[] {}));
			}
		} else if (user.getUserType().equals(BussinessConstant.USER_TYPE_CYS)) {
			advancedQueryTypeByShipbillVO.setUnitId(Long.valueOf(user.getLoginUserCompanyInfo().getId()));
		} else {
			throw new PrologException("当前人员没有操作权限");
		}
		advancedQueryTypeByShipbillVO.setUserType(user.getUserType());
		advancedQueryTypeByShipbillVO.setEnterpriseId(user.getEnterpriseId());

		// 获取高级查询配置
		String conditions = null;
		RestMessage<String> restMessageAdvancedCfg = maindataTmsResource.getQueryConfiguration(DataDictionaryConstant.BIZ_TYPE_WAITLOADINGANDUNLOADING);
		if (!restMessageAdvancedCfg.isSuccess()) {
			throw new RuntimeException("获取高级查询配置失败!");
		} else {
			conditions = restMessageAdvancedCfg.getData();
		}
		advancedQueryTypeByShipbillVO.setSql(conditions);

		PageUtils.startPage(advancedQueryTypeByShipbillVO.getPageNum(), advancedQueryTypeByShipbillVO.getPageSize());
		List<QueryTypeByShipbillDTO> queryTypeByShipbillDTOS = tmsLoadingBillHeaderMapper.advancedQueryTypeByShipbillPage(advancedQueryTypeByShipbillVO);

		for (QueryTypeByShipbillDTO queryTypeByShipbillDTO : queryTypeByShipbillDTOS) {
			// 类型翻译
			queryTypeByShipbillDTO.setOrderTypeName(PublicMethods.change(data1, String.valueOf(queryTypeByShipbillDTO.getOrderType())));
			queryTypeByShipbillDTO.setOrderBusinessTypeName(PublicMethods.change(data2, String.valueOf(queryTypeByShipbillDTO.getOrderBusinessType())));
			queryTypeByShipbillDTO.setDeliveryMethodTypeName(PublicMethods.change(data3, String.valueOf(queryTypeByShipbillDTO.getDeliveryMethodType())));
			queryTypeByShipbillDTO.setTransportTypeName(PublicMethods.change(data4, String.valueOf(queryTypeByShipbillDTO.getTransportType())));
			queryTypeByShipbillDTO.setTemperatureRequirementName(PublicMethods.change(data5, String.valueOf(queryTypeByShipbillDTO.getTemperatureRequirement())));
			queryTypeByShipbillDTO.setShipperTypeName(PublicMethods.change(data6, String.valueOf(queryTypeByShipbillDTO.getShipperType())));
			queryTypeByShipbillDTO.setConsigneeTypeName(PublicMethods.change(data7, String.valueOf(queryTypeByShipbillDTO.getConsigneeType())));
			queryTypeByShipbillDTO.setStatusName(PublicMethods.change(data8, String.valueOf(queryTypeByShipbillDTO.getStatus())));
			queryTypeByShipbillDTO.setCarrierTypeName(PublicMethods.change(data9, String.valueOf(queryTypeByShipbillDTO.getCarrierType())));
			queryTypeByShipbillDTO.setTransportStatusName(PublicMethods.change(data10, String.valueOf(queryTypeByShipbillDTO.getTransportStatus())));
			queryTypeByShipbillDTO.setAbnormalStatusName(PublicMethods.change(data11, String.valueOf(queryTypeByShipbillDTO.getAbnormalStatus())));
			queryTypeByShipbillDTO.setScanStatusName(PublicMethods.change(data12, String.valueOf(queryTypeByShipbillDTO.getScanStatus())));

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

	/**
	 * 收货方模式分页查询
	 *
	 * @param queryTypeByReceiverVO
	 * @return
	 */
	@Override
	public Page<QueryTypeByReceiverDTO> queryTypeByReceiverPageData(QueryTypeByReceiverVO queryTypeByReceiverVO) {

		ToolKits.isParamNull(queryTypeByReceiverVO.getPageNum(), "当前页码不为空");
		ToolKits.isParamNull(queryTypeByReceiverVO.getPageSize(), "每页条数不为空");

		UserEntity user = PlgFxUsrUtils.getUserEntity();
		ToolKits.isParamNull(user, "当前人员没有操作权限");
		// 权限控制
		if (user.getUserType().equals(BussinessConstant.USER_TYPE_ZY)) {
			// 判断是否是部门权限
			if (user.getOwnedAllDataAuthFlag().equals(BussinessConstant.USER_DEPARTMENT_AUTH_Y)) {
				queryTypeByReceiverVO.setIsDept(StatusConstant.IS_DEPT_YES);
				queryTypeByReceiverVO.setDepts(user.getDepts().toArray(new String[] {}));
			} else {
				queryTypeByReceiverVO.setIsDept(StatusConstant.IS_DEPT_NO);
				// 设置部门权限
				queryTypeByReceiverVO.setDepts(user.getDepts().toArray(new String[] {}));
				// 设置数据权限
				queryTypeByReceiverVO.setConsignors(user.getConsignors().toArray(new Long[] {}));
				queryTypeByReceiverVO.setWsarehouses(user.getWarehouses().toArray(new Long[] {}));
				queryTypeByReceiverVO.setCustomers(user.getCustomers().toArray(new Long[] {}));
				queryTypeByReceiverVO.setSuppliers(user.getSuppliers().toArray(new Long[] {}));
			}
		} else if (user.getUserType().equals(BussinessConstant.USER_TYPE_CYS)) {
			queryTypeByReceiverVO.setUnitId(Long.valueOf(user.getLoginUserCompanyInfo().getId()));
		} else {
			throw new PrologException("当前人员没有操作权限");
		}
		queryTypeByReceiverVO.setUserType(user.getUserType());
		queryTypeByReceiverVO.setEnterpriseId(user.getEnterpriseId());
		// 是否开启装卸
		queryTypeByReceiverVO.setFlowConfig(DataDictionaryConstant.FLOW_CONFIG_LOAD_UNLOAD);
		PageUtils.startPage(queryTypeByReceiverVO.getPageNum(), queryTypeByReceiverVO.getPageSize());

		List<QueryTypeByReceiverDTO> queryTypeByReceiverDTOS = tmsLoadingBillHeaderMapper.queryTypeByReceiverPage(queryTypeByReceiverVO);

		// 行号
		int id = 1;
		for (QueryTypeByReceiverDTO dto : queryTypeByReceiverDTOS) {
			// 设置行id
			dto.setId(id);
			// 目的地
			dto.setConsigneeProvinceCityDistrict(dto.getConsigneeProvinceName() + dto.getConsigneeCityName() + dto.getConsigneeDistrictName());
			// 行号自增长
			id++;
		}

		return PageUtils.getPage(queryTypeByReceiverDTOS);
	}

	/**
	 * 预约单模式分页查询
	 *
	 * @param queryTypeByAppointmentVO
	 * @return
	 */
	@SuppressWarnings("resource")
	@Override
	public Page<QueryTypeByAppointmentDTO> queryAppointmentTypePage(QueryTypeByAppointmentVO queryTypeByAppointmentVO) {
		UserEntity user = PlgFxUsrUtils.getUserEntity();
		ToolKits.isParamNull(user, "当前人员没有操作权限");
		// 权限控制 仅支持自有账号操作
		if (!user.getUserType().equals(BussinessConstant.USER_TYPE_ZY)) {
			throw new PrologException("当前人员没有操作权限");
		}

		List<Map<String, Object>> data1 = Lists.newArrayList();
		List<Map<String, Object>> data2 = Lists.newArrayList();
		List<Map<String, Object>> data3 = Lists.newArrayList();

		// 预约状态
		RestMessage<List<Map<String, Object>>> restMessage1 = maindataTmsResource.getDropDownById(DataDictionaryConstant.APPOINTMENT_STATUS, null, null, null);
		if (!restMessage1.isSuccess()) {
			throw new RuntimeException("预约状态翻译失败!");
		} else {
			data1 = restMessage1.getData();
		}
		// 预约类型
		RestMessage<List<Map<String, Object>>> restMessage2 = maindataTmsResource.getDropDownById(DataDictionaryConstant.APPOINTMENT_TYPE, null, null, null);
		if (!restMessage2.isSuccess()) {
			throw new RuntimeException("预约类型翻译失败!");
		} else {
			data2 = restMessage2.getData();
		}

		// 理货状态
		RestMessage<List<Map<String, Object>>> restMessage3 = maindataTmsResource.getDropDownById(DataDictionaryConstant.TALLY_STATUS, null, null, null);
		if (!restMessage3.isSuccess()) {
			throw new RuntimeException("理货状态翻译失败!");
		} else {
			data3 = restMessage3.getData();
		}

		Criteria criteria = Criteria.forClass(TmsAppointmentHeaderModel.class);
		Restriction r1 = ToolKits.isEmpty(queryTypeByAppointmentVO.getAppointmentNo()) ? null : Restrictions.like("appointmentNo", "%" + queryTypeByAppointmentVO.getAppointmentNo() + "%");
		Restriction r2 = ToolKits.isEmpty(queryTypeByAppointmentVO.getBranchAddress()) ? null : Restrictions.like("branchAddress", "%" + queryTypeByAppointmentVO.getBranchAddress() + "%");
		Restriction r3 = ToolKits.isEmpty(queryTypeByAppointmentVO.getDriverName()) ? null : Restrictions.like("driverName", "%" + queryTypeByAppointmentVO.getDriverName() + "%");
		Restriction r4 = ToolKits.isEmpty(queryTypeByAppointmentVO.getDriverPhoneNumber()) ? null : Restrictions.like("driverPhoneNumber", "%" + queryTypeByAppointmentVO.getDriverPhoneNumber() + "%");
		Restriction r5 = ToolKits.isEmpty(queryTypeByAppointmentVO.getVehiclePlateNumber()) ? null : Restrictions.like("vehiclePlateNumber", "%" + queryTypeByAppointmentVO.getVehiclePlateNumber() + "%");
		Restriction r6 = ToolKits.isEmpty(queryTypeByAppointmentVO.getAppointmentType()) ? null : Restrictions.eq("appointmentType", queryTypeByAppointmentVO.getAppointmentType());
		Restriction r7 = Restrictions.in("branchId", queryTypeByAppointmentVO.getBranchId().split(","));
		Restriction r8 = Restrictions.in("status", new Integer[] { DataDictionaryConstant.APPOINTMENT_STATUS_YJH, DataDictionaryConstant.APPOINTMENT_STATUS_KSZX });
		Restriction r9 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
		Restriction r10 = Restrictions.eq(TmsAppointmentHeaderModel::getTallyStatus, DataDictionaryConstant.TALLY_STATUS_LHWC);
		Restriction r11 = ToolKits.isEmpty(queryTypeByAppointmentVO.getReserveNumber()) ? null : Restrictions.like(TmsAppointmentHeaderModel::getReserveNumber, "%" + queryTypeByAppointmentVO.getReserveNumber() + "%");

		PageUtils.startPage(queryTypeByAppointmentVO.getPageNum(), queryTypeByAppointmentVO.getPageSize());
		criteria.setRestriction(Restrictions.and(r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11));
		criteria.setOrder(Order.newInstance().asc(new String[] { "reserveNumber" }));

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

		PageUtils.startPage(queryTypeByAppointmentVO.getPageNum(), queryTypeByAppointmentVO.getPageSize());
		List<TmsAppointmentHeaderModel> tmsAppointmentHeaderModels = tmsAppointmentHeaderMapper.findByCriteria(criteria);

		for (TmsAppointmentHeaderModel tmsAppointmentHeaderModel : tmsAppointmentHeaderModels) {
			QueryTypeByAppointmentDTO dto = new QueryTypeByAppointmentDTO();
			BeanUtils.copyProperties(tmsAppointmentHeaderModel, dto);

			dto.setAppointmentTime(sdf.format(dto.getAppointmentDate()) + " " + dto.getAppointmentTime());

			// 数据翻译
			dto.setStatusName(PublicMethods.change(data1, String.valueOf(dto.getStatus())));
			dto.setAppointmentTypeName(PublicMethods.change(data2, String.valueOf(dto.getAppointmentType())));
			dto.setTallyStatusName(PublicMethods.change(data3, String.valueOf(dto.getTallyStatus())));

			criteria = Criteria.forClass(TmsAppointmentDetailModel.class);
			r1 = Restrictions.eq(TmsAppointmentDetailModel::getAppointmentId, tmsAppointmentHeaderModel.getAppointmentId());
			criteria.setRestriction(r1);
			List<TmsAppointmentDetailModel> tmsAppointmentDetailModels = tmsAppointmentDetailMapper.findByCriteria(criteria);

			// 获取预约单下的运单
			String shipbillIds = tmsAppointmentDetailModels.stream().map(TmsAppointmentDetailModel::getShipbillId).distinct().collect(Collectors.joining(","));
			dto.setShipbillIds(shipbillIds);

			// 设置预约单的派车单
			dto.setLoadingBillIds(DataUtils.getLoadingBillIds(tmsAppointmentDetailModels));
			dto.setLoadingBillNo(dto.getLoadingBillIds());

			// 是否包含紧急订单
			if (ToolKits.isNotEmpty(tmsAppointmentHeaderModel.getUrgentQuantity()) && tmsAppointmentHeaderModel.getUrgentQuantity().intValue() > 0) {
				dto.setUrgentShipbill("是");
			} else {
				dto.setUrgentShipbill("否");
			}
			// 封装数据集
			queryTypeByAppointmentDTOS.add(dto);
		}

		// 分页重组
		Page<QueryTypeByAppointmentDTO> page = PageUtils.getPage(queryTypeByAppointmentDTOS);
		if (tmsAppointmentHeaderModels instanceof com.github.pagehelper.Page) {
			com.github.pagehelper.Page<TmsAppointmentHeaderModel> p0 = (com.github.pagehelper.Page<TmsAppointmentHeaderModel>) tmsAppointmentHeaderModels;
			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 receiverGetShipbillVO
	 * @return
	 */
	@SuppressWarnings("resource")
	@Override
	public Page<ReceiverGetShipbillDTO> receiverGetShipbillData(ReceiverGetShipbillVO receiverGetShipbillVO) {
		ToolKits.isParamNull(receiverGetShipbillVO, "明细查询请求不为空");
		ToolKits.isParamNull(receiverGetShipbillVO.getPageNum(), "当前页码不为空");
		ToolKits.isParamNull(receiverGetShipbillVO.getPageSize(), "每页条数不为空");
		ToolKits.isParamNull(receiverGetShipbillVO.getShipbillIds(), "运单ID不为空");

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

		if (!user.getUserType().equals(BussinessConstant.USER_TYPE_ZY) && !user.getUserType().equals(BussinessConstant.USER_TYPE_CYS)) {
			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(TmsShipbillHeaderModel.class);
		Restriction r1 = Restrictions.in("shipbillId", receiverGetShipbillVO.getShipbillIds().toArray());
		criteria.setRestriction(r1);
		criteria.setOrder(Order.newInstance().asc(new String[] { "updatetime" }));

		PageUtils.startPage(receiverGetShipbillVO.getPageNum(), receiverGetShipbillVO.getPageSize());
		List<TmsShipbillHeaderModel> tmsShipbillHeaderModels = tmsShipbillHeaderMapper.findByCriteria(criteria);

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

		for (TmsShipbillHeaderModel model : tmsShipbillHeaderModels) {

			ReceiverGetShipbillDTO receiverGetShipbillDTO = new ReceiverGetShipbillDTO();
			BeanUtils.copyProperties(model, receiverGetShipbillDTO);

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

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

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

			// 获取背景颜色和字体颜色
			Signconfig: for (SignconfigPopDTO signconfigPopDTO : data8) {
				// 标记类型匹配
				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(receiverGetShipbillDTO.getOrderTypeName()) ? receiverGetShipbillDTO.getOrderTypeName() : "")) {
							receiverGetShipbillDTO.setBackground(ToolKits.isEmpty(signconfigPopDTO.getBackground()) ? "" : signconfigPopDTO.getBackground());
							receiverGetShipbillDTO.setColor(ToolKits.isEmpty(signconfigPopDTO.getColor()) ? "" : signconfigPopDTO.getColor());

							receiverGetShipbillDTO.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(receiverGetShipbillDTO.getOrderBusinessTypeName()) ? receiverGetShipbillDTO.getOrderBusinessTypeName() : "")) {
							receiverGetShipbillDTO.setBackground(ToolKits.isEmpty(signconfigPopDTO.getBackground()) ? "" : signconfigPopDTO.getBackground());
							receiverGetShipbillDTO.setColor(ToolKits.isEmpty(signconfigPopDTO.getColor()) ? "" : signconfigPopDTO.getColor());

							receiverGetShipbillDTO.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(receiverGetShipbillDTO.getTemperatureRequirementName()) ? receiverGetShipbillDTO.getTemperatureRequirementName() : "")) {
							receiverGetShipbillDTO.setBackground(ToolKits.isEmpty(signconfigPopDTO.getBackground()) ? "" : signconfigPopDTO.getBackground());
							receiverGetShipbillDTO.setColor(ToolKits.isEmpty(signconfigPopDTO.getColor()) ? "" : signconfigPopDTO.getColor());

							receiverGetShipbillDTO.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(receiverGetShipbillDTO.getDeliveryMethodTypeName()) ? receiverGetShipbillDTO.getDeliveryMethodTypeName() : "")) {
							receiverGetShipbillDTO.setBackground(ToolKits.isEmpty(signconfigPopDTO.getBackground()) ? "" : signconfigPopDTO.getBackground());
							receiverGetShipbillDTO.setColor(ToolKits.isEmpty(signconfigPopDTO.getColor()) ? "" : signconfigPopDTO.getColor());

							receiverGetShipbillDTO.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(receiverGetShipbillDTO.getMemo()) ? receiverGetShipbillDTO.getMemo() : "")) {
							receiverGetShipbillDTO.setBackground(ToolKits.isEmpty(signconfigPopDTO.getBackground()) ? "" : signconfigPopDTO.getBackground());
							receiverGetShipbillDTO.setColor(ToolKits.isEmpty(signconfigPopDTO.getColor()) ? "" : signconfigPopDTO.getColor());

							receiverGetShipbillDTO.setSignConfigId(signconfigPopDTO.getId());

							break Signconfig;
						}
					}
					break;
				}
			}

			list.add(receiverGetShipbillDTO);
		}

		// 分页重组
		Page<ReceiverGetShipbillDTO> page = PageUtils.getPage(list);
		if (tmsShipbillHeaderModels instanceof com.github.pagehelper.Page) {
			com.github.pagehelper.Page<TmsShipbillHeaderModel> p0 = (com.github.pagehelper.Page<TmsShipbillHeaderModel>) tmsShipbillHeaderModels;
			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 dzxItemDetailVO
	 * @return
	 */
	@SuppressWarnings("resource")
	@Override
	public Page<DzxItemDetailDTO> itemDetailData(DzxItemDetailVO dzxItemDetailVO) {
		ToolKits.isParamNull(dzxItemDetailVO.getShipbillIds(), "运单ID不为空");
		ToolKits.isParamNull(dzxItemDetailVO.getPageNum(), "当前页码不为空");
		ToolKits.isParamNull(dzxItemDetailVO.getPageSize(), "每页条数不为空");

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

		if (!user.getUserType().equals(BussinessConstant.USER_TYPE_ZY) && !user.getUserType().equals(BussinessConstant.USER_TYPE_CYS)) {
			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();
		}

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

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

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

		for (TmsShipbillDetailModel tmsShipbillDetailModel : tmsShipbillDetailModels) {
			DzxItemDetailDTO dto = new DzxItemDetailDTO();
			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<DzxItemDetailDTO> 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 dzxPackageDetailVO
	 * @return
	 */
	@SuppressWarnings("resource")
	@Override
	public Page<DzxPackageDetailDTO> packageDetailData(DzxPackageDetailVO dzxPackageDetailVO) {
		ToolKits.isParamNull(dzxPackageDetailVO.getShipbillIds(), "运单ID不为空");
		ToolKits.isParamNull(dzxPackageDetailVO.getPageNum(), "当前页码不为空");
		ToolKits.isParamNull(dzxPackageDetailVO.getPageSize(), "每页条数不为空");

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

		if (!user.getUserType().equals(BussinessConstant.USER_TYPE_ZY) && !user.getUserType().equals(BussinessConstant.USER_TYPE_CYS)) {
			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();
		}
		// 根据运单ID查询明细数据
		Criteria criteria = Criteria.forClass(TmsShipbillPackageModel.class);
		Restriction r1 = Restrictions.in("shipbillId", dzxPackageDetailVO.getShipbillIds().toArray());
		criteria.setRestriction(r1);

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

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

		for (TmsShipbillPackageModel tmsShipbillPackageModel : tmsShipbillPackageModels) {
			DzxPackageDetailDTO dto = new DzxPackageDetailDTO();
			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<DzxPackageDetailDTO> 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 shipbillIds
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void startedWorkData(List<String> shipbillIds) {
		ToolKits.isParamNull(shipbillIds, "运单ID不为空");

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

		if (!user.getUserType().equals(BussinessConstant.USER_TYPE_ZY) && !user.getUserType().equals(BussinessConstant.USER_TYPE_CYS)) {
			ToolKits.isParamNull(user, "当前人员没有操作权限");
		}

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

		// 更新调度单
		Map<String, Object> mapHeaderUpdate = Maps.newHashMap();
		mapHeaderUpdate.put("updateperson", user.getNickname());
		mapHeaderUpdate.put("updatetime", date);
		mapHeaderUpdate.put("status", DataDictionaryConstant.LOADING_BILL_STATUS_ZX_START);

		Map<String, Object> mapTransportLogUpdate = Maps.newHashMap();
		mapTransportLogUpdate.put("updateperson", user.getNickname());
		mapTransportLogUpdate.put("updatetime", date);
		// 开始装卸时间
		mapTransportLogUpdate.put("loadAndUnloadStartTime", new Date());

		Criteria criteriaTransport = Criteria.forClass(TmsShipbillTransLogModel.class);
		Criteria criteriaLoadingHeader = Criteria.forClass(TmsLoadingBillHeaderModel.class);

		shipbillIds = Stream.of((shipbillIds.stream().collect(Collectors.joining(","))).split(",")).collect(Collectors.toList());
		for (String shipbillId : shipbillIds) {
			Restriction r1 = Restrictions.eq("shipbillId", shipbillId);
			Restriction r2 = Restrictions.eq("enterpriseId", user.getEnterpriseId());

			Criteria criteriaLoadingDetail = Criteria.forClass(TmsLoadingBillDetailModel.class);
			criteriaLoadingDetail.setRestriction(Restrictions.and(r1, r2));
			criteriaLoadingDetail.setOrder(Order.newInstance().desc(new String[] { "createtime" }));
			List<TmsLoadingBillDetailModel> loadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteriaLoadingDetail);
			if (ToolKits.isEmpty(loadingBillDetailModels)) {
				throw new PrologException("运单【" + shipbillId + "】不存在");
			}
			TmsLoadingBillDetailModel loadingBillDetailModel = loadingBillDetailModels.get(0);
			if (loadingBillDetailModel.getStatus().intValue() > DataDictionaryConstant.SHIPBILL_STATUS_ZX_START.intValue()) {
				throw new PrologException("运单【" + shipbillId + "】已开始装卸或已装车扫描");
			}

			// 判定下一步流程,取下一步流程的状态
			String flowConfig = null;
			if (user.getUserType().equals(BussinessConstant.USER_TYPE_CYS)) {
				flowConfig = loadingBillDetailModel.getCarrierFlowConfig();
			} else {
				flowConfig = loadingBillDetailModel.getFlowConfig();
			}
			int status = 0;
			if (flowConfig.contains(DataDictionaryConstant.FLOW_CONFIG_SCANNING)) {
				status = DataDictionaryConstant.SHIPBILL_STATUS_ZC_SCAN;
			} else {
				status = DataDictionaryConstant.SHIPBILL_STATUS_ZX_FINISH;
			}

			if (ObjectUtil.notEqual(DataDictionaryConstant.SHIPBILL_STATUS_ZC_SCAN, status) && ObjectUtil.equal(loadingBillDetailModel.getStatus(), DataDictionaryConstant.SHIPBILL_STATUS_ZC_SCAN)) {
				throw new PrologException("运单【" + shipbillId + "】已装车扫描");
			}

			// 更新装车单明细
			criteriaLoadingDetail = Criteria.forClass(TmsLoadingBillDetailModel.class);
			criteriaLoadingDetail.setRestriction(Restrictions.and(r1, r2));
			Map<String, Object> mapUpdate = Maps.newHashMap();
			mapUpdate.put("updateperson", user.getNickname());
			mapUpdate.put("updatetime", date);
			mapUpdate.put("status", status);
			tmsLoadingBillDetailMapper.updateMapById(loadingBillDetailModel.getId(), mapUpdate, TmsLoadingBillDetailModel.class);

			// 更新运单表
			Criteria criteriaShipbillHeader = Criteria.forClass(TmsShipbillHeaderModel.class);
			criteriaShipbillHeader.setRestriction(Restrictions.and(r1, r2));
			tmsShipbillHeaderMapper.updateMapByCriteria(mapUpdate, criteriaShipbillHeader);

			// 查询预约单明细
			Criteria criteriaAppointment = Criteria.forClass(TmsAppointmentDetailModel.class);
			Restriction appointment = Restrictions.eq(TmsAppointmentDetailModel::getShipbillId, shipbillId);
			Restriction criteriaStatus = Restrictions.ge(TmsAppointmentDetailModel::getStatus, DataDictionaryConstant.SHIPBILL_STATUS_PENDING_APP);
			criteriaAppointment.setRestriction(Restrictions.and(appointment, criteriaStatus));
			List<TmsAppointmentDetailModel> tmsAppointmentDetailModels = tmsAppointmentDetailMapper.findByCriteria(criteriaAppointment);

			if (ToolKits.isNotEmpty(tmsAppointmentDetailModels)) {
				if (tmsAppointmentDetailModels.size() > 1) {
					throw new RuntimeException("运单[" + shipbillId + "]被重复预约!");
				}
				TmsAppointmentDetailModel tmsAppointmentDetailModel = tmsAppointmentDetailModels.get(0);

				if (user.getUserType().equals(BussinessConstant.USER_TYPE_ZY)) {
					if (ToolKits.isEmpty(tmsAppointmentDetailModel.getFlowConfig()) || !tmsAppointmentDetailModel.getFlowConfig().contains(DataDictionaryConstant.FLOW_CONFIG_LOAD_UNLOAD)) {
						throw new PrologException("运单【" + tmsAppointmentDetailModel.getShipbillId() + "】没有待装卸流程，不能做装卸");
					}
				} else {
					if (ToolKits.isEmpty(tmsAppointmentDetailModel.getCarrierFlowConfig()) || !tmsAppointmentDetailModel.getCarrierFlowConfig().contains(DataDictionaryConstant.FLOW_CONFIG_LOAD_UNLOAD)) {
						throw new PrologException("运单【" + tmsAppointmentDetailModel.getShipbillId() + "】没有待装卸流程，不能做装卸");
					}
				}

				// 查询预约单
				TmsAppointmentHeaderModel tmsAppointmentHeaderModel = tmsAppointmentHeaderMapper.findById(tmsAppointmentDetailModel.getAppointmentId(), TmsAppointmentHeaderModel.class);
				ToolKits.isParamNull(tmsAppointmentHeaderModel, "未找到对应预约单[" + tmsAppointmentDetailModel.getAppointmentId() + "]");

				// 判断是否为叫号状态
				if (DataDictionaryConstant.APPOINTMENT_STATUS_YJH.equals(tmsAppointmentHeaderModel.getStatus())) {
					// STD-DEVELOP20220823 lhb bwc0823006 运单表增加理货状态的需求变更 20220824 start
					// 修改预约单明细表
					tmsAppointmentDetailModel.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_ZX_FINISH);
					tmsAppointmentDetailMapper.update(tmsAppointmentDetailModel);

					Criteria criteriaAppointmentAll = Criteria.forClass(TmsAppointmentDetailModel.class);
					Restriction appointmentId = Restrictions.eq(TmsAppointmentDetailModel::getAppointmentId, tmsAppointmentDetailModel.getAppointmentId());
					criteriaAppointmentAll.setRestriction(appointmentId);
					List<TmsAppointmentDetailModel> allAppointmentDetailModels = tmsAppointmentDetailMapper.findByCriteria(criteriaAppointmentAll);
					List<TmsAppointmentDetailModel> tmsAppointmentDetails = allAppointmentDetailModels.stream().filter(o -> o.getStatus().intValue() < DataDictionaryConstant.SHIPBILL_STATUS_ZX_FINISH.intValue()).collect(Collectors.toList());
					// 预约明细全部开始装卸完成，预约主单才更新开始装卸
					if (ToolKits.isEmpty(tmsAppointmentDetails)) {
						tmsAppointmentHeaderModel.setLoadAndUnloadStartTime(date);
						tmsAppointmentHeaderModel.setStatus(DataDictionaryConstant.APPOINTMENT_STATUS_KSZX);
					}
					// STD-DEVELOP20220823 lhb 4273 20220902 start
					tmsAppointmentHeaderModel.setLoadAndUnloadWorkerId(user.getUserid());
					tmsAppointmentHeaderModel.setLoadAndUnloadWorkerCode(String.valueOf(user.getUserid()));
					tmsAppointmentHeaderModel.setLoadAndUnloadWorkerName(user.getNickname());
					tmsAppointmentHeaderMapper.update(tmsAppointmentHeaderModel);
					// STD-DEVELOP20220823 lhb 4273 20220902 end
					// STD-DEVELOP20220823 lhb bwc0823006 运单表增加理货状态的需求变更 20220824 end
				}
			}

			// 运单节点保存
			ShipbillNodeTrackingSaveNewVO shipbillNodeTrackingSaveNewVO = new ShipbillNodeTrackingSaveNewVO();
			shipbillNodeTrackingSaveNewVO.setNodeDate(date);
			shipbillNodeTrackingSaveNewVO.setShipbillId(shipbillId);
			shipbillNodeTrackingSaveNewVO.setShipbillNo(shipbillId);
			shipbillNodeTrackingSaveNewVO.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_ZX_FINISH);
			shipbillNodeTrackingSaveNewVO.setNodeEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_ZX_START);
			shipbillNodeTrackingSaveNewVO.setUserId(user.getUserid());
			shipbillNodeTrackingSaveNewVO.setUserName(user.getNickname());
			shipbillNodeTrackingSaveNewVO.setEnterpriseId(user.getEnterpriseId());
			shipbillNodeTrackingSaveNewVO.setEnterpriseName(user.getEnterpriseName());
			shipbillNodeTrackingService.addShipbillNodeTrackingNewData(shipbillNodeTrackingSaveNewVO);

			// 运单日志保存
			ShipbillOperateLogSaveNewVO shipbillOperateLogSaveNewVO = new ShipbillOperateLogSaveNewVO();
			shipbillOperateLogSaveNewVO.setShipbillId(shipbillId);
			shipbillOperateLogSaveNewVO.setShipbillNo(shipbillId);
			shipbillOperateLogSaveNewVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_ZX_START);
			shipbillOperateLogSaveNewVO.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_LH_FINISH);
			shipbillOperateLogSaveNewVO.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_ZX_FINISH);
			shipbillOperateLogSaveNewVO.setOperateDate(date);
			shipbillOperateLogSaveNewVO.setEnterpriseId(user.getEnterpriseId());
			shipbillOperateLogSaveNewVO.setEnterpriseName(user.getEnterpriseName());
			shipbillOperateLogSaveNewVO.setUserId(user.getUserid());
			shipbillOperateLogSaveNewVO.setUserName(user.getNickname());
			shipbillOperateLogService.addShipbillOperateLogNewData(shipbillOperateLogSaveNewVO);

			// 父运单的开始装卸
			String fatherShipbillId = shipbillId;
			while (ToolKits.isNotEmpty(fatherShipbillId)) {
				fatherShipbillId = fatherStartedWork(fatherShipbillId, date, user, status);
			}
			// 更新订单运输记录表
			criteriaTransport.setRestriction(r1);
			tmsShipbillTransportLogMapper.updateMapByCriteria(mapTransportLogUpdate, criteriaTransport);

			// 更新调度单状态 开始装卸
			Restriction r3 = Restrictions.eq("loadingBillId", loadingBillDetailModels.get(0).getLoadingBillId());
			Restriction r4 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
			criteriaLoadingHeader.setRestriction(Restrictions.and(r3, r4));
			List<TmsLoadingBillHeaderModel> headerModel = tmsLoadingBillHeaderMapper.findByCriteria(criteriaLoadingHeader);

			if (ToolKits.isNotEmpty(headerModel) && headerModel.get(0).getStatus() != status) {
				tmsLoadingBillHeaderMapper.updateMapByCriteria(mapHeaderUpdate, criteriaLoadingHeader);
			}
		}

	}

	/**
	 * 装卸完成
	 *
	 * @param shipbillIds
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void completeWorkData(List<String> shipbillIds) {
		ToolKits.isParamNull(shipbillIds, "运单ID不为空");

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

		if (!user.getUserType().equals(BussinessConstant.USER_TYPE_ZY) && !user.getUserType().equals(BussinessConstant.USER_TYPE_CYS)) {
			ToolKits.isParamNull(user, "当前人员没有操作权限");
		}
		// 当前时间
		Date date = DateUtils.nowDate();

		Map<String, Object> mapTransportLogUpdate = Maps.newHashMap();
		mapTransportLogUpdate.put("updateperson", user.getNickname());
		mapTransportLogUpdate.put("updatetime", date);
		// 装卸完成时间
		mapTransportLogUpdate.put("loadAndUnloadEndTime", date);

		shipbillIds = Stream.of((shipbillIds.stream().collect(Collectors.joining(","))).split(",")).collect(Collectors.toList());
		for (String shipbillId : shipbillIds) {

			Criteria criteriaLoadingDetail = Criteria.forClass(TmsLoadingBillDetailModel.class);
			Restriction r1 = Restrictions.eq("shipbillId", shipbillId);
			Restriction r2 = Restrictions.eq("status", DataDictionaryConstant.SHIPBILL_STATUS_ZX_FINISH);
			Restriction r3 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
			criteriaLoadingDetail.setRestriction(Restrictions.and(r1, r2, r3));
			criteriaLoadingDetail.setOrder(Order.newInstance().desc(new String[] { "createtime" }));

			List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteriaLoadingDetail);
			if (ToolKits.isEmpty(tmsLoadingBillDetailModels)) {
				throw new PrologException("运单【" + shipbillId + "】的开始装卸或者装车扫描没有做，还不能完成装卸");
			}
			TmsLoadingBillDetailModel loadingBillDetailModel = tmsLoadingBillDetailModels.get(0);

			// 判定下一步流程,取下一步流程的状态
			String flowConfig = null;
			if (user.getUserType().equals(BussinessConstant.USER_TYPE_ZY)) {
				flowConfig = loadingBillDetailModel.getFlowConfig();
			} else if (user.getUserType().equals(BussinessConstant.USER_TYPE_CYS)) {
				flowConfig = loadingBillDetailModel.getCarrierFlowConfig();
			}
			int status = businessFlowUtil.judgmentNextFlowSts(flowConfig, DataDictionaryConstant.FLOW_CONFIG_LOAD_UNLOAD);

			// 更新装车单明细
			Map<String, Object> mapUpdate = Maps.newHashMap();
			mapUpdate.put("updateperson", user.getNickname());
			mapUpdate.put("updatetime", date);
			mapUpdate.put("status", status);

			Criteria criteriaLoadingBillDetail = Criteria.forClass(TmsLoadingBillDetailModel.class);
			Restriction r4 = Restrictions.eq("shipbillId", shipbillId);
			Restriction r5 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
			criteriaLoadingBillDetail.setRestriction(Restrictions.and(r4, r5));
			tmsLoadingBillDetailMapper.updateMapById(loadingBillDetailModel.getId(), mapUpdate, TmsLoadingBillDetailModel.class);

			// 更新运单表
			Criteria criteriaShipbillHeader = Criteria.forClass(TmsShipbillHeaderModel.class);
			criteriaShipbillHeader.setRestriction(Restrictions.and(r4, r5));
			tmsShipbillHeaderMapper.updateMapByCriteria(mapUpdate, criteriaShipbillHeader);

			// 查询预约单明细
			Criteria criteriaAppointment = Criteria.forClass(TmsAppointmentDetailModel.class);
			Restriction appointment = Restrictions.eq(TmsAppointmentDetailModel::getShipbillId, shipbillId);
			Restriction criteriaStatus = Restrictions.gt(TmsAppointmentDetailModel::getStatus, DataDictionaryConstant.SHIPBILL_STATUS_APP_ING);
			criteriaAppointment.setRestriction(Restrictions.and(appointment, criteriaStatus));
			List<TmsAppointmentDetailModel> tmsAppointmentDetailModels = tmsAppointmentDetailMapper.findByCriteria(criteriaAppointment);
			if (ToolKits.isNotEmpty(tmsAppointmentDetailModels)) {
				if (tmsAppointmentDetailModels.size() > 1) {
					throw new RuntimeException("运单[" + shipbillId + "]被重复预约!");
				}
				// 获取剩余预约运单信息
				Restriction appointment2 = Restrictions.ne(TmsAppointmentDetailModel::getShipbillId, shipbillId);
				Restriction appointment3 = Restrictions.eq(TmsAppointmentDetailModel::getAppointmentId, tmsAppointmentDetailModels.get(0).getAppointmentId());
				criteriaAppointment.setRestriction(Restrictions.and(appointment2, appointment3));
				List<TmsAppointmentDetailModel> tmsAppointmentDetailModelList = tmsAppointmentDetailMapper.findByCriteria(criteriaAppointment);

				if (ToolKits.isNotEmpty(tmsAppointmentDetailModelList)) {
					// 获取是否还有未装卸完成的单子
					List<TmsAppointmentDetailModel> tmsAppointmentDetails = tmsAppointmentDetailModelList.stream().filter(o -> o.getStatus().intValue() <= DataDictionaryConstant.SHIPBILL_STATUS_ZX_FINISH.intValue()).collect(Collectors.toList());
					if (ToolKits.isEmpty(tmsAppointmentDetails)) {
						// 修改预约单主表
						Map<String, Object> map = Maps.newHashMap();
						map.put("updateperson", user.getNickname());
						map.put("updatetime", date);
						map.put("loadAndUnloadEndTime", date);
						map.put("status", DataDictionaryConstant.APPOINTMENT_STATUS_ZXWC);
						tmsAppointmentHeaderMapper.updateMapById(tmsAppointmentDetailModels.get(0).getAppointmentId(), map, TmsAppointmentHeaderModel.class);
					}

					// 修改预约单明细表
					Restriction appointment4 = Restrictions.eq(TmsAppointmentDetailModel::getShipbillId, shipbillId);
					criteriaAppointment.setRestriction(appointment4);
					Map<String, Object> updateDetail = Maps.newHashMap();
					updateDetail.put("status", status);
					tmsAppointmentDetailMapper.updateMapByCriteria(updateDetail, criteriaAppointment);
				} else {
					// 修改预约单主表
					Map<String, Object> map = Maps.newHashMap();
					map.put("updateperson", user.getNickname());
					map.put("updatetime", date);
					map.put("loadAndUnloadEndTime", date);
					map.put("status", DataDictionaryConstant.APPOINTMENT_STATUS_ZXWC);
					tmsAppointmentHeaderMapper.updateMapById(tmsAppointmentDetailModels.get(0).getAppointmentId(), map, TmsAppointmentHeaderModel.class);

					// 修改预约单明细表
					Restriction appointment5 = Restrictions.eq(TmsAppointmentDetailModel::getShipbillId, shipbillId);
					criteriaAppointment.setRestriction(appointment5);
					Map<String, Object> updateDetail = Maps.newHashMap();
					updateDetail.put("status", status);
					tmsAppointmentDetailMapper.updateMapByCriteria(updateDetail, criteriaAppointment);
				}

			}

			// 运单节点保存
			ShipbillNodeTrackingSaveNewVO shipbillNodeTrackingSaveNewVO = new ShipbillNodeTrackingSaveNewVO();
			shipbillNodeTrackingSaveNewVO.setNodeDate(date);
			shipbillNodeTrackingSaveNewVO.setShipbillId(shipbillId);
			shipbillNodeTrackingSaveNewVO.setShipbillNo(shipbillId);
			shipbillNodeTrackingSaveNewVO.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_ZX_FINISH);
			shipbillNodeTrackingSaveNewVO.setNodeEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_ZX_FINISH);
			shipbillNodeTrackingSaveNewVO.setUserId(user.getUserid());
			shipbillNodeTrackingSaveNewVO.setUserName(user.getNickname());
			shipbillNodeTrackingSaveNewVO.setEnterpriseId(user.getEnterpriseId());
			shipbillNodeTrackingSaveNewVO.setEnterpriseName(user.getEnterpriseName());
			shipbillNodeTrackingService.addShipbillNodeTrackingNewData(shipbillNodeTrackingSaveNewVO);

			// 运单日志保存
			ShipbillOperateLogSaveNewVO shipbillOperateLogSaveNewVO = new ShipbillOperateLogSaveNewVO();
			shipbillOperateLogSaveNewVO.setShipbillId(shipbillId);
			shipbillOperateLogSaveNewVO.setShipbillNo(shipbillId);
			shipbillOperateLogSaveNewVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_ZX_FINISH);
			shipbillOperateLogSaveNewVO.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_ZX_START);
			shipbillOperateLogSaveNewVO.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_ZX_FINISH);
			shipbillOperateLogSaveNewVO.setOperateDate(date);
			shipbillOperateLogSaveNewVO.setEnterpriseId(user.getEnterpriseId());
			shipbillOperateLogSaveNewVO.setEnterpriseName(user.getEnterpriseName());
			shipbillOperateLogSaveNewVO.setUserId(user.getUserid());
			shipbillOperateLogSaveNewVO.setUserName(user.getNickname());
			shipbillOperateLogService.addShipbillOperateLogNewData(shipbillOperateLogSaveNewVO);

			// 维护运输日志
			Criteria criteriaTransport = Criteria.forClass(TmsShipbillTransLogModel.class);
			criteriaTransport.setRestriction(r1);
			tmsShipbillTransportLogMapper.updateMapByCriteria(mapTransportLogUpdate, criteriaTransport);

			// 父运单的装卸完成
			String fatherShipbillId = shipbillId;
			while (ToolKits.isNotEmpty(fatherShipbillId)) {
				fatherShipbillId = fatherCompleteWork(fatherShipbillId, date, user, status);
			}

			// 更新调度单状态
			Restriction r6 = Restrictions.eq("loadingBillId", loadingBillDetailModel.getLoadingBillId());
			Restriction r7 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
			criteriaLoadingBillDetail.setRestriction(Restrictions.and(r6, r7));
			tmsLoadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteriaLoadingBillDetail);
			if (ToolKits.isNotEmpty(tmsLoadingBillDetailModels)) {
				List<TmsLoadingBillDetailModel> filterTmsLoadingBillDetailModels = tmsLoadingBillDetailModels.stream().filter(dto -> dto.getStatus().intValue() < DataDictionaryConstant.SHIPBILL_STATUS_QY.intValue()).collect(Collectors.toList());
				if (ToolKits.isEmpty(filterTmsLoadingBillDetailModels)) {
					// 更新调度单
					Map<String, Object> mapHeaderUpdate = Maps.newHashMap();
					mapHeaderUpdate.put("updateperson", user.getNickname());
					mapHeaderUpdate.put("updatetime", date);
					mapHeaderUpdate.put("status", DataDictionaryConstant.LOADING_BILL_STATUS_ZX_FINISH);
					tmsLoadingBillHeaderMapper.updateMapById(loadingBillDetailModel.getLoadingBillId(), mapHeaderUpdate, TmsLoadingBillHeaderModel.class);
				}
			}
			MessageUtil.addMessage(new SendMessageDTO(MessageOrderTypeEnum.SHIP_NO.getCode(), MessageTypeEnum.LOADING.getCode(), Lists.newArrayList(shipbillId)));
		}
	}

	/**
	 * 导出所有数据
	 *
	 * @param dzxExportAllVO
	 * @return
	 */
	@Override
	public List<DzxExportShipbillDTO> exportAllShipbillData(DzxExportAllVO dzxExportAllVO) {
		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<Map<String, Object>> data9 = Lists.newArrayList();
		List<Map<String, Object>> data10 = Lists.newArrayList();
		List<Map<String, Object>> data11 = Lists.newArrayList();
		List<Map<String, Object>> data12 = 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();
		}

		// 承运方类型
		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();
		}

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

		// 异常状态
		RestMessage<List<Map<String, Object>>> restMessage11 = maindataTmsResource.getDropDownById(DataDictionaryConstant.ABNORMAL_STATUS, null, null, null);
		if (!restMessage11.isSuccess()) {
			throw new RuntimeException("异常状态翻译失败!");
		} else {
			data11 = restMessage11.getData();
		}

		// 扫描状态
		RestMessage<List<Map<String, Object>>> restMessage12 = maindataTmsResource.getDropDownById(DataDictionaryConstant.SCAN_STATUS, null, null, null);
		if (!restMessage12.isSuccess()) {
			throw new RuntimeException("扫描状态翻译失败!");
		} else {
			data12 = restMessage12.getData();
		}

		// 权限控制
		if (user.getUserType().equals(BussinessConstant.USER_TYPE_ZY)) {
			// 判断是否是部门权限
			if (user.getOwnedAllDataAuthFlag().equals(BussinessConstant.USER_DEPARTMENT_AUTH_Y)) {
				dzxExportAllVO.setIsDept(StatusConstant.IS_DEPT_YES);
				dzxExportAllVO.setDepts(user.getDepts().toArray(new String[] {}));
			} else {
				dzxExportAllVO.setIsDept(StatusConstant.IS_DEPT_NO);
				// 设置部门权限
				dzxExportAllVO.setDepts(user.getDepts().toArray(new String[] {}));
				// 设置数据权限
				dzxExportAllVO.setConsignors(user.getConsignors().toArray(new Long[] {}));
				dzxExportAllVO.setWsarehouses(user.getWarehouses().toArray(new Long[] {}));
				dzxExportAllVO.setCustomers(user.getCustomers().toArray(new Long[] {}));
				dzxExportAllVO.setSuppliers(user.getSuppliers().toArray(new Long[] {}));
			}
		} else if (user.getUserType().equals(BussinessConstant.USER_TYPE_CYS)) {
			dzxExportAllVO.setUnitId(Long.valueOf(user.getLoginUserCompanyInfo().getId()));
		} else {
			throw new PrologException("当前人员没有操作权限");
		}
		dzxExportAllVO.setUserType(user.getUserType());
		dzxExportAllVO.setEnterpriseId(user.getEnterpriseId());

		// 返回数据集
		List<DzxExportShipbillDTO> list = Lists.newArrayList();
		// 是否开启装卸
		dzxExportAllVO.setFlowConfig(DataDictionaryConstant.FLOW_CONFIG_LOAD_UNLOAD);
		List<QueryTypeByShipbillDTO> queryTypeByShipbillDTOS = tmsLoadingBillHeaderMapper.exportAllShipbillData(dzxExportAllVO);

		for (QueryTypeByShipbillDTO queryTypeByShipbillDTO : queryTypeByShipbillDTOS) {

			DzxExportShipbillDTO dzxExportShipbillDTO = new DzxExportShipbillDTO();
			BeanUtils.copyProperties(queryTypeByShipbillDTO, dzxExportShipbillDTO);

			// 类型翻译
			dzxExportShipbillDTO.setOrderTypeName(PublicMethods.change(data1, String.valueOf(queryTypeByShipbillDTO.getOrderType())));
			dzxExportShipbillDTO.setOrderBusinessTypeName(PublicMethods.change(data2, String.valueOf(queryTypeByShipbillDTO.getOrderBusinessType())));
			dzxExportShipbillDTO.setDeliveryMethodTypeName(PublicMethods.change(data3, String.valueOf(queryTypeByShipbillDTO.getDeliveryMethodType())));
			dzxExportShipbillDTO.setTransportTypeName(PublicMethods.change(data4, String.valueOf(queryTypeByShipbillDTO.getTransportType())));
			dzxExportShipbillDTO.setTemperatureRequirementName(PublicMethods.change(data5, String.valueOf(queryTypeByShipbillDTO.getTemperatureRequirement())));
			dzxExportShipbillDTO.setShipperTypeName(PublicMethods.change(data6, String.valueOf(queryTypeByShipbillDTO.getShipperType())));
			dzxExportShipbillDTO.setConsigneeTypeName(PublicMethods.change(data7, String.valueOf(queryTypeByShipbillDTO.getConsigneeType())));
			dzxExportShipbillDTO.setStatusName(PublicMethods.change(data8, String.valueOf(queryTypeByShipbillDTO.getStatus())));
			dzxExportShipbillDTO.setCarrierTypeName(PublicMethods.change(data9, String.valueOf(queryTypeByShipbillDTO.getCarrierType())));
			dzxExportShipbillDTO.setTransportStatusName(PublicMethods.change(data10, String.valueOf(queryTypeByShipbillDTO.getTransportStatus())));
			dzxExportShipbillDTO.setAbnormalStatusName(PublicMethods.change(data11, String.valueOf(queryTypeByShipbillDTO.getAbnormalStatus())));
			dzxExportShipbillDTO.setScanStatusName(PublicMethods.change(data12, String.valueOf(queryTypeByShipbillDTO.getScanStatus())));

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

			StringBuffer consigneeProvinceCityDistrict = new StringBuffer();
			// 目的地
			consigneeProvinceCityDistrict.append(queryTypeByShipbillDTO.getConsigneeProvinceName());
			consigneeProvinceCityDistrict.append(queryTypeByShipbillDTO.getConsigneeCityName());
			consigneeProvinceCityDistrict.append(queryTypeByShipbillDTO.getConsigneeDistrictName());
			dzxExportShipbillDTO.setConsigneeProvinceCity(consigneeProvinceCityDistrict.toString());

			// 始发地
			StringBuffer shipperProvinceCityDistrict = new StringBuffer();
			shipperProvinceCityDistrict.append(queryTypeByShipbillDTO.getShipperProvinceName());
			shipperProvinceCityDistrict.append(queryTypeByShipbillDTO.getShipperCityName());
			shipperProvinceCityDistrict.append(queryTypeByShipbillDTO.getShipperDistrictName());
			dzxExportShipbillDTO.setShipperProvinceCity(shipperProvinceCityDistrict.toString());

			if (ObjectUtil.equal(DataDictionaryConstant.LINE_CARRIER_TYPE_SJ, queryTypeByShipbillDTO.getCarrierType())) {// 承运方类型为司机时展示司机姓名
				dzxExportShipbillDTO.setCarrierName(queryTypeByShipbillDTO.getDriverName());
				dzxExportShipbillDTO.setCarrierPhoneNumber(queryTypeByShipbillDTO.getDriverPhoneNumber());
			}

			list.add(dzxExportShipbillDTO);
		}
		return list;
	}

	/**
	 * 导出当前页数据
	 *
	 * @param dzxExportPageVO
	 * @return
	 */
	@Override
	public List<DzxExportShipbillDTO> exportPageShipbill(DzxExportPageVO dzxExportPageVO) {
		ToolKits.isParamNull(dzxExportPageVO.getPageNum(), "当前页码不为空");
		ToolKits.isParamNull(dzxExportPageVO.getPageSize(), "每页条数不为空");
		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<Map<String, Object>> data9 = Lists.newArrayList();
		List<Map<String, Object>> data10 = Lists.newArrayList();
		List<Map<String, Object>> data11 = Lists.newArrayList();
		List<Map<String, Object>> data12 = 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();
		}

		// 承运方类型
		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();
		}

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

		// 异常状态
		RestMessage<List<Map<String, Object>>> restMessage11 = maindataTmsResource.getDropDownById(DataDictionaryConstant.ABNORMAL_STATUS, null, null, null);
		if (!restMessage11.isSuccess()) {
			throw new RuntimeException("异常状态翻译失败!");
		} else {
			data11 = restMessage11.getData();
		}

		// 扫描状态
		RestMessage<List<Map<String, Object>>> restMessage12 = maindataTmsResource.getDropDownById(DataDictionaryConstant.SCAN_STATUS, null, null, null);
		if (!restMessage12.isSuccess()) {
			throw new RuntimeException("扫描状态翻译失败!");
		} else {
			data12 = restMessage12.getData();
		}

		// 权限控制
		if (user.getUserType().equals(BussinessConstant.USER_TYPE_ZY)) {
			// 判断是否是部门权限
			if (user.getOwnedAllDataAuthFlag().equals(BussinessConstant.USER_DEPARTMENT_AUTH_Y)) {
				dzxExportPageVO.setIsDept(StatusConstant.IS_DEPT_YES);
				dzxExportPageVO.setDepts(user.getDepts().toArray(new String[] {}));
			} else {
				dzxExportPageVO.setIsDept(StatusConstant.IS_DEPT_NO);
				// 设置部门权限
				dzxExportPageVO.setDepts(user.getDepts().toArray(new String[] {}));
				// 设置数据权限
				dzxExportPageVO.setConsignors(user.getConsignors().toArray(new Long[] {}));
				dzxExportPageVO.setWsarehouses(user.getWarehouses().toArray(new Long[] {}));
				dzxExportPageVO.setCustomers(user.getCustomers().toArray(new Long[] {}));
				dzxExportPageVO.setSuppliers(user.getSuppliers().toArray(new Long[] {}));
			}
		} else if (user.getUserType().equals(BussinessConstant.USER_TYPE_CYS)) {
			dzxExportPageVO.setUnitId(Long.valueOf(user.getLoginUserCompanyInfo().getId()));
		} else {
			throw new PrologException("当前人员没有操作权限");
		}
		dzxExportPageVO.setUserType(user.getUserType());
		dzxExportPageVO.setEnterpriseId(user.getEnterpriseId());

		// 返回数据集
		List<DzxExportShipbillDTO> list = Lists.newArrayList();
		// 是否开启装卸
		dzxExportPageVO.setFlowConfig(DataDictionaryConstant.FLOW_CONFIG_LOAD_UNLOAD);
		PageUtils.startPage(dzxExportPageVO.getPageNum(), dzxExportPageVO.getPageSize());
		List<QueryTypeByShipbillDTO> queryTypeByShipbillDTOS = tmsLoadingBillHeaderMapper.exportPageShipbillData(dzxExportPageVO);

		for (QueryTypeByShipbillDTO queryTypeByShipbillDTO : queryTypeByShipbillDTOS) {

			DzxExportShipbillDTO dzxExportShipbillDTO = new DzxExportShipbillDTO();
			BeanUtils.copyProperties(queryTypeByShipbillDTO, dzxExportShipbillDTO);

			// 类型翻译
			dzxExportShipbillDTO.setOrderTypeName(PublicMethods.change(data1, String.valueOf(queryTypeByShipbillDTO.getOrderType())));
			dzxExportShipbillDTO.setOrderBusinessTypeName(PublicMethods.change(data2, String.valueOf(queryTypeByShipbillDTO.getOrderBusinessType())));
			dzxExportShipbillDTO.setDeliveryMethodTypeName(PublicMethods.change(data3, String.valueOf(queryTypeByShipbillDTO.getDeliveryMethodType())));
			dzxExportShipbillDTO.setTransportTypeName(PublicMethods.change(data4, String.valueOf(queryTypeByShipbillDTO.getTransportType())));
			dzxExportShipbillDTO.setTemperatureRequirementName(PublicMethods.change(data5, String.valueOf(queryTypeByShipbillDTO.getTemperatureRequirement())));
			dzxExportShipbillDTO.setShipperTypeName(PublicMethods.change(data6, String.valueOf(queryTypeByShipbillDTO.getShipperType())));
			dzxExportShipbillDTO.setConsigneeTypeName(PublicMethods.change(data7, String.valueOf(queryTypeByShipbillDTO.getConsigneeType())));
			dzxExportShipbillDTO.setStatusName(PublicMethods.change(data8, String.valueOf(queryTypeByShipbillDTO.getStatus())));
			dzxExportShipbillDTO.setCarrierTypeName(PublicMethods.change(data9, String.valueOf(queryTypeByShipbillDTO.getCarrierType())));
			dzxExportShipbillDTO.setTransportStatusName(PublicMethods.change(data10, String.valueOf(queryTypeByShipbillDTO.getTransportStatus())));
			dzxExportShipbillDTO.setAbnormalStatusName(PublicMethods.change(data11, String.valueOf(queryTypeByShipbillDTO.getAbnormalStatus())));
			dzxExportShipbillDTO.setScanStatusName(PublicMethods.change(data12, String.valueOf(queryTypeByShipbillDTO.getScanStatus())));

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

			list.add(dzxExportShipbillDTO);
		}
		return list;
	}

	/**
	 * ` 导出选择行数据
	 *
	 * @param shipbillIds
	 * @return
	 */
	@Override
	public List<DzxExportShipbillDTO> exportSelectLineShipbillData(List<String> shipbillIds) {
		ToolKits.isParamNull(shipbillIds, "运单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<Map<String, Object>> data9 = Lists.newArrayList();
		List<Map<String, Object>> data10 = Lists.newArrayList();
		List<Map<String, Object>> data11 = Lists.newArrayList();
		List<Map<String, Object>> data12 = 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();
		}
		// 承运方类型
		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();
		}
		// 运输状态
		RestMessage<List<Map<String, Object>>> restMessage10 = maindataTmsResource.getDropDownById(DataDictionaryConstant.TRANSPORT_STATUS, null, null, null);
		if (!restMessage10.isSuccess()) {
			throw new RuntimeException("运输状态翻译失败!");
		} else {
			data10 = restMessage10.getData();
		}
		// 异常状态
		RestMessage<List<Map<String, Object>>> restMessage11 = maindataTmsResource.getDropDownById(DataDictionaryConstant.ABNORMAL_STATUS, null, null, null);
		if (!restMessage11.isSuccess()) {
			throw new RuntimeException("异常状态翻译失败!");
		} else {
			data11 = restMessage11.getData();
		}
		// 扫描状态
		RestMessage<List<Map<String, Object>>> restMessage12 = maindataTmsResource.getDropDownById(DataDictionaryConstant.SCAN_STATUS, null, null, null);
		if (!restMessage12.isSuccess()) {
			throw new RuntimeException("扫描状态翻译失败!");
		} else {
			data12 = restMessage12.getData();
		}

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

		List<QueryTypeByShipbillDTO> queryTypeByShipbillDTOS = tmsLoadingBillHeaderMapper.exportSelectLineShipbillData(shipbillIds.toArray(new String[] {}));

		for (QueryTypeByShipbillDTO queryTypeByShipbillDTO : queryTypeByShipbillDTOS) {

			DzxExportShipbillDTO dzxExportShipbillDTO = new DzxExportShipbillDTO();
			BeanUtils.copyProperties(queryTypeByShipbillDTO, dzxExportShipbillDTO);

			// 类型翻译
			dzxExportShipbillDTO.setOrderTypeName(PublicMethods.change(data1, String.valueOf(queryTypeByShipbillDTO.getOrderType())));
			dzxExportShipbillDTO.setOrderBusinessTypeName(PublicMethods.change(data2, String.valueOf(queryTypeByShipbillDTO.getOrderBusinessType())));
			dzxExportShipbillDTO.setDeliveryMethodTypeName(PublicMethods.change(data3, String.valueOf(queryTypeByShipbillDTO.getDeliveryMethodType())));
			dzxExportShipbillDTO.setTransportTypeName(PublicMethods.change(data4, String.valueOf(queryTypeByShipbillDTO.getTransportType())));
			dzxExportShipbillDTO.setTemperatureRequirementName(PublicMethods.change(data5, String.valueOf(queryTypeByShipbillDTO.getTemperatureRequirement())));
			dzxExportShipbillDTO.setShipperTypeName(PublicMethods.change(data6, String.valueOf(queryTypeByShipbillDTO.getShipperType())));
			dzxExportShipbillDTO.setConsigneeTypeName(PublicMethods.change(data7, String.valueOf(queryTypeByShipbillDTO.getConsigneeType())));
			dzxExportShipbillDTO.setStatusName(PublicMethods.change(data8, String.valueOf(queryTypeByShipbillDTO.getStatus())));
			dzxExportShipbillDTO.setCarrierTypeName(PublicMethods.change(data9, String.valueOf(queryTypeByShipbillDTO.getCarrierType())));
			dzxExportShipbillDTO.setTransportStatusName(PublicMethods.change(data10, String.valueOf(queryTypeByShipbillDTO.getTransportStatus())));
			dzxExportShipbillDTO.setAbnormalStatusName(PublicMethods.change(data11, String.valueOf(queryTypeByShipbillDTO.getAbnormalStatus())));
			dzxExportShipbillDTO.setScanStatusName(PublicMethods.change(data12, String.valueOf(queryTypeByShipbillDTO.getScanStatus())));

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

			list.add(dzxExportShipbillDTO);
		}
		return list;
	}

	/**
	 * 待装卸打印
	 *
	 * @param shipbillId
	 * @return
	 */
	@Override
	public Map<String, Object> printShipbillData(String shipbillId) {
		ToolKits.isParamNull(shipbillId, "运单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<Map<String, Object>> data9 = Lists.newArrayList();
		List<Map<String, Object>> data10 = Lists.newArrayList();
		List<Map<String, Object>> data11 = Lists.newArrayList();
		List<Map<String, Object>> data12 = Lists.newArrayList();
		List<Map<String, Object>> data13 = Lists.newArrayList();
		List<Map<String, Object>> data14 = 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();
		}
		// 承运方类型
		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();
		}
		// 运输状态
		RestMessage<List<Map<String, Object>>> restMessage10 = maindataTmsResource.getDropDownById(DataDictionaryConstant.TRANSPORT_STATUS, null, null, null);
		if (!restMessage10.isSuccess()) {
			throw new RuntimeException("运输状态翻译失败!");
		} else {
			data10 = restMessage10.getData();
		}
		// 异常状态
		RestMessage<List<Map<String, Object>>> restMessage11 = maindataTmsResource.getDropDownById(DataDictionaryConstant.ABNORMAL_STATUS, null, null, null);
		if (!restMessage11.isSuccess()) {
			throw new RuntimeException("异常状态翻译失败!");
		} else {
			data11 = restMessage11.getData();
		}
		// 扫描状态
		RestMessage<List<Map<String, Object>>> restMessage12 = maindataTmsResource.getDropDownById(DataDictionaryConstant.SCAN_STATUS, null, null, null);
		if (!restMessage12.isSuccess()) {
			throw new RuntimeException("扫描状态翻译失败!");
		} else {
			data12 = restMessage12.getData();
		}

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

		// 查询条件
		String[] shipbillIds = new String[] { shipbillId };

		List<QueryTypeByShipbillDTO> queryTypeByShipbillDTOS = tmsLoadingBillHeaderMapper.exportSelectLineShipbillData(shipbillIds);
		ToolKits.isParamNull(queryTypeByShipbillDTOS, "运单ID[" + shipbillId + "]有误,查询为空!");

		DzxPrintHeadDTO dzxPrintHeadDTO = new DzxPrintHeadDTO();
		QueryTypeByShipbillDTO queryTypeByShipbillDTO = queryTypeByShipbillDTOS.get(0);
		BeanUtils.copyProperties(queryTypeByShipbillDTO, dzxPrintHeadDTO);

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

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

		// 类型翻译
		dzxPrintHeadDTO.setOrderTypeName(PublicMethods.change(data1, String.valueOf(queryTypeByShipbillDTO.getOrderType())));
		dzxPrintHeadDTO.setOrderBusinessTypeName(PublicMethods.change(data2, String.valueOf(queryTypeByShipbillDTO.getOrderBusinessType())));
		dzxPrintHeadDTO.setDeliveryMethodTypeName(PublicMethods.change(data3, String.valueOf(queryTypeByShipbillDTO.getDeliveryMethodType())));
		dzxPrintHeadDTO.setTransportTypeName(PublicMethods.change(data4, String.valueOf(queryTypeByShipbillDTO.getTransportType())));
		dzxPrintHeadDTO.setTemperatureRequirementName(PublicMethods.change(data5, String.valueOf(queryTypeByShipbillDTO.getTemperatureRequirement())));
		dzxPrintHeadDTO.setShipperTypeName(PublicMethods.change(data6, String.valueOf(queryTypeByShipbillDTO.getShipperType())));
		dzxPrintHeadDTO.setConsigneeTypeName(PublicMethods.change(data7, String.valueOf(queryTypeByShipbillDTO.getConsigneeType())));
		dzxPrintHeadDTO.setStatusName(PublicMethods.change(data8, String.valueOf(queryTypeByShipbillDTO.getStatus())));
		dzxPrintHeadDTO.setCarrierTypeName(PublicMethods.change(data9, String.valueOf(queryTypeByShipbillDTO.getCarrierType())));
		dzxPrintHeadDTO.setTransportStatusName(PublicMethods.change(data10, String.valueOf(queryTypeByShipbillDTO.getTransportStatus())));
		dzxPrintHeadDTO.setAbnormalStatusName(PublicMethods.change(data11, String.valueOf(queryTypeByShipbillDTO.getAbnormalStatus())));
		dzxPrintHeadDTO.setScanStatusName(PublicMethods.change(data12, String.valueOf(queryTypeByShipbillDTO.getScanStatus())));

		Criteria criteria = Criteria.forClass(TmsShipbillDetailModel.class);
		Restriction r1 = Restrictions.eq("shipbillId", shipbillId);
		criteria.setRestriction(r1);
		List<TmsShipbillDetailModel> tmsShipbillDetailModels = tmsShipbillDetailMapper.findByCriteria(criteria);

		List<DzxPrintDetailDTO> dzxPrintDetailDTOS = new ArrayList<>();

		for (TmsShipbillDetailModel detail : tmsShipbillDetailModels) {
			DzxPrintDetailDTO dto = new DzxPrintDetailDTO();
			BeanUtils.copyProperties(detail, dto);
			dto.setPackTypeName(PublicMethods.change(data13, String.valueOf(detail.getPackType())));
			dto.setCargoThermosphereName(PublicMethods.change(data14, String.valueOf(detail.getCargoThermosphere())));
			dzxPrintDetailDTOS.add(dto);
		}

		// TODO print

		return null;
	}

	/**
	 * 父级运单开始装卸流程
	 *
	 * @param shipbillId
	 * @param date
	 * @param user
	 * @return
	 */
	public String fatherStartedWork(String shipbillId, Date date, UserEntity user, int status) {
		// 查询运单
		TmsShipbillHeaderModel tmsShipbillHeaderModel = tmsShipbillHeaderMapper.findById(shipbillId, TmsShipbillHeaderModel.class);

		// 判断是否为原始单号
		if (ToolKits.isNotEmpty(tmsShipbillHeaderModel.getFatherShipbillId()) && !tmsShipbillHeaderModel.getFatherShipbillId().equals(shipbillId)) {
			// 查找父级单号
			TmsShipbillHeaderModel fatherShipbillHeaderModel = tmsShipbillHeaderMapper.findById(tmsShipbillHeaderModel.getFatherShipbillId(), TmsShipbillHeaderModel.class);

			// 判断父级单号的状态是否为开始装卸
			if (fatherShipbillHeaderModel.getStatus() != status) {
				// 修改父级运单状态
				fatherShipbillHeaderModel.setStatus(status);
				fatherShipbillHeaderModel.setUpdatetime(date);
				fatherShipbillHeaderModel.setUpdateperson(user.getNickname());
				tmsShipbillHeaderMapper.update(fatherShipbillHeaderModel);

				// 更新装车单明细
				Map<String, Object> mapUpdate = Maps.newHashMap();
				mapUpdate.put("updateperson", user.getNickname());
				mapUpdate.put("updatetime", date);
				mapUpdate.put("status", status);
				Criteria criteriaFatherLoadingBillDetail = Criteria.forClass(TmsLoadingBillDetailModel.class);
				Restriction r5 = Restrictions.eq("shipbillId", tmsShipbillHeaderModel.getFatherShipbillId());
				Restriction r6 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
				criteriaFatherLoadingBillDetail.setRestriction(Restrictions.and(r5, r6));
				tmsLoadingBillDetailMapper.updateMapByCriteria(mapUpdate, criteriaFatherLoadingBillDetail);

				// 运单节点保存
				ShipbillNodeTrackingSaveNewVO shipbillNodeTrackingSaveNewVO = new ShipbillNodeTrackingSaveNewVO();
				shipbillNodeTrackingSaveNewVO.setNodeDate(date);
				shipbillNodeTrackingSaveNewVO.setShipbillId(fatherShipbillHeaderModel.getShipbillId());
				shipbillNodeTrackingSaveNewVO.setShipbillNo(fatherShipbillHeaderModel.getShipbillId());
				shipbillNodeTrackingSaveNewVO.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_ZX_START);
				shipbillNodeTrackingSaveNewVO.setNodeEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_ZX_START);
				shipbillNodeTrackingSaveNewVO.setUserId(user.getUserid());
				shipbillNodeTrackingSaveNewVO.setUserName(user.getNickname());
				shipbillNodeTrackingSaveNewVO.setEnterpriseId(user.getEnterpriseId());
				shipbillNodeTrackingSaveNewVO.setEnterpriseName(user.getEnterpriseName());
				shipbillNodeTrackingService.addShipbillNodeTrackingNewData(shipbillNodeTrackingSaveNewVO);

				// 运单日志保存
				ShipbillOperateLogSaveNewVO shipbillOperateLogSaveNewVO = new ShipbillOperateLogSaveNewVO();
				shipbillOperateLogSaveNewVO.setShipbillId(fatherShipbillHeaderModel.getShipbillId());
				shipbillOperateLogSaveNewVO.setShipbillNo(fatherShipbillHeaderModel.getShipbillId());
				shipbillOperateLogSaveNewVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_ZX_START);
				shipbillOperateLogSaveNewVO.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_LH_FINISH);
				shipbillOperateLogSaveNewVO.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_ZX_START);
				shipbillOperateLogSaveNewVO.setOperateDate(date);
				shipbillOperateLogSaveNewVO.setEnterpriseId(user.getEnterpriseId());
				shipbillOperateLogSaveNewVO.setEnterpriseName(user.getEnterpriseName());
				shipbillOperateLogSaveNewVO.setUserId(user.getUserid());
				shipbillOperateLogSaveNewVO.setUserName(user.getNickname());
				shipbillOperateLogService.addShipbillOperateLogNewData(shipbillOperateLogSaveNewVO);

				// 更新订单运输记录表
				Criteria criteriaTransport = Criteria.forClass(TmsShipbillTransLogModel.class);
				criteriaTransport.setRestriction(r5);
				// 订单运输记录表
				Map<String, Object> mapTransportLogUpdate = Maps.newHashMap();
				mapTransportLogUpdate.put("updateperson", user.getNickname());
				mapTransportLogUpdate.put("updatetime", date);
				// 开始装卸时间
				mapTransportLogUpdate.put("loadAndUnloadStartTime", new Date());
				tmsShipbillTransportLogMapper.updateMapByCriteria(mapTransportLogUpdate, criteriaTransport);

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

	}

	/**
	 * 父级运单装卸完成流程
	 *
	 * @param shipbillId
	 * @param date
	 * @param user
	 * @return
	 */
	public String fatherCompleteWork(String shipbillId, Date date, UserEntity user, int status) {
		// 查询运单
		TmsShipbillHeaderModel tmsShipbillHeaderModel = tmsShipbillHeaderMapper.findById(shipbillId, TmsShipbillHeaderModel.class);

		// 判断是否为原始单号
		if (ToolKits.isNotEmpty(tmsShipbillHeaderModel.getFatherShipbillId()) && !tmsShipbillHeaderModel.getFatherShipbillId().equals(shipbillId)) {
			// 查找父级单号
			TmsShipbillHeaderModel fatherShipbillHeaderModel = tmsShipbillHeaderMapper.findById(tmsShipbillHeaderModel.getFatherShipbillId(), TmsShipbillHeaderModel.class);

			// 查找同级的所有子单
			Criteria criteria = Criteria.forClass(TmsShipbillHeaderModel.class);
			Restriction r1 = Restrictions.eq("fatherShipbillId", tmsShipbillHeaderModel.getFatherShipbillId());
			criteria.setRestriction(r1);
			List<TmsShipbillHeaderModel> tmsShipbillHeaderModelList = tmsShipbillHeaderMapper.findByCriteria(criteria);

			// 查找是否还有未完成的运单
			List<TmsShipbillHeaderModel> tmsShipbillHeaderModels = tmsShipbillHeaderModelList.stream().filter(o -> o.getStatus().intValue() < DataDictionaryConstant.SHIPBILL_STATUS_QY.intValue()).collect(Collectors.toList());

			// 判断子单是否全部完成
			if (ToolKits.isEmpty(tmsShipbillHeaderModels)) {
				// 修改父级运单状态
				fatherShipbillHeaderModel.setStatus(status);
				fatherShipbillHeaderModel.setUpdatetime(date);
				fatherShipbillHeaderModel.setUpdateperson(user.getNickname());
				tmsShipbillHeaderMapper.update(fatherShipbillHeaderModel);

				// 运单节点保存
				ShipbillNodeTrackingSaveNewVO shipbillNodeTrackingSaveNewVO = new ShipbillNodeTrackingSaveNewVO();
				shipbillNodeTrackingSaveNewVO.setNodeDate(date);
				shipbillNodeTrackingSaveNewVO.setShipbillId(fatherShipbillHeaderModel.getShipbillId());
				shipbillNodeTrackingSaveNewVO.setShipbillNo(fatherShipbillHeaderModel.getShipbillId());
				shipbillNodeTrackingSaveNewVO.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_ZX_FINISH);
				shipbillNodeTrackingSaveNewVO.setNodeEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_ZX_FINISH);
				shipbillNodeTrackingSaveNewVO.setUserId(user.getUserid());
				shipbillNodeTrackingSaveNewVO.setUserName(user.getNickname());
				shipbillNodeTrackingSaveNewVO.setEnterpriseId(user.getEnterpriseId());
				shipbillNodeTrackingSaveNewVO.setEnterpriseName(user.getEnterpriseName());
				shipbillNodeTrackingService.addShipbillNodeTrackingNewData(shipbillNodeTrackingSaveNewVO);

				// 运单日志保存
				ShipbillOperateLogSaveNewVO shipbillOperateLogSaveNewVO = new ShipbillOperateLogSaveNewVO();
				shipbillOperateLogSaveNewVO.setShipbillId(fatherShipbillHeaderModel.getShipbillId());
				shipbillOperateLogSaveNewVO.setShipbillNo(fatherShipbillHeaderModel.getShipbillId());
				shipbillOperateLogSaveNewVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_ZX_FINISH);
				shipbillOperateLogSaveNewVO.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_ZX_START);
				shipbillOperateLogSaveNewVO.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_ZX_FINISH);
				shipbillOperateLogSaveNewVO.setOperateDate(date);
				shipbillOperateLogSaveNewVO.setEnterpriseId(user.getEnterpriseId());
				shipbillOperateLogSaveNewVO.setEnterpriseName(user.getEnterpriseName());
				shipbillOperateLogSaveNewVO.setUserId(user.getUserid());
				shipbillOperateLogSaveNewVO.setUserName(user.getNickname());
				shipbillOperateLogService.addShipbillOperateLogNewData(shipbillOperateLogSaveNewVO);

				// 更新订单运输记录表
				Criteria criteriaTransport = Criteria.forClass(TmsShipbillTransLogModel.class);
				r1 = Restrictions.eq("shipbillId", tmsShipbillHeaderModel.getFatherShipbillId());
				criteriaTransport.setRestriction(r1);
				Map<String, Object> mapTransportLogUpdate = Maps.newHashMap();
				mapTransportLogUpdate.put("updateperson", user.getNickname());
				mapTransportLogUpdate.put("updatetime", date);
				// 装卸完成时间
				mapTransportLogUpdate.put("loadAndUnloadEndTime", date);
				tmsShipbillTransportLogMapper.updateMapByCriteria(mapTransportLogUpdate, criteriaTransport);

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

	}

	/**
	 * 扫描单号
	 * @param vo
	 * @return
	 */
	@Transactional(rollbackFor = Exception.class)
	@Override
	public LoadingScanDTO loadingScanData(LoadingScanVO vo) {
		// 判断扫描类型
		RestMessage<SysParamConfigModel> restMessage = maindataTmsResource.getValue(DataDictionaryConstant.SCANLOADING_METHED);
		if (!restMessage.isSuccess()) {
			throw new RuntimeException("获取系统参数服务失败:" + restMessage.getMessage());
		}
		SysParamConfigModel sysParamConfigModel = restMessage.getData();
		String scanLoadingMethod = sysParamConfigModel.getValue();
		LoadingScanDTO loadingScanDTO;
		if (DataDictionaryConstant.SCANLOADING_METHED_LOADINGBILL_SHIPBILL.equals(scanLoadingMethod)) {
			TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel = tmsLoadingBillHeaderMapper.findById(vo.getBillCode(), TmsLoadingBillHeaderModel.class);
			if (ObjectUtil.isNotNull(tmsLoadingBillHeaderModel)) {
				loadingScanDTO = scanLoadingBill(vo,tmsLoadingBillHeaderModel,scanLoadingMethod);
			} else {
				loadingScanDTO = scanShipBill(vo);
				updateLoadingTime(vo.getBillCode(),DateUtil.date(),null);
			}
		} else if (DataDictionaryConstant.SCANLOADING_METHED_SHIPBILL.equals(scanLoadingMethod)) {
			loadingScanDTO = scanShipBill(vo);
			updateLoadingTime(vo.getBillCode(),DateUtil.date(),null);
		}  else if (DataDictionaryConstant.SCANLOADING_METHED_LOADINGBILL.equals(scanLoadingMethod)) {
			loadingScanDTO = scanLoadingBillOnly(vo);
			updateLoadingTime(vo.getBillCode(),DateUtil.date(),null);
		} else if (DataDictionaryConstant.SCANLOADING_METHED_LOADINGBILL_ITEM.equals(scanLoadingMethod)) {
			TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel = tmsLoadingBillHeaderMapper.findById(vo.getBillCode(), TmsLoadingBillHeaderModel.class);
			if (ObjectUtil.isNotNull(tmsLoadingBillHeaderModel)) {
				loadingScanDTO = scanLoadingBill(vo, tmsLoadingBillHeaderModel,scanLoadingMethod);
			} else {
				loadingScanDTO = scanShipBillDetail(vo);
				loadingScanDTO.getScannedShipbillDetailList().stream()
				   .map(DzxItemDetailDTO::getShipbillId).distinct()
				   .collect(Collectors.toList())
				   .forEach(shipbillId-> {
					   updateLoadingTime(shipbillId,DateUtil.date(),null);
				   });
			}
		} else {
			throw new BizException("不支持的装车扫描类型");
		}
		return loadingScanDTO;
	}

	/**
	 * 装车扫描运单
	 * @param vo
	 * @return
	 */
	private LoadingScanDTO scanShipBill(LoadingScanVO vo) {
		LoadingScanDTO dto = new LoadingScanDTO();
		UserEntity user = PlgFxUsrUtils.getUserEntity();
		TmsShipbillHeaderModel tmsShipbillHeaderModel = tmsShipbillHeaderMapper.findById(vo.getBillCode(), TmsShipbillHeaderModel.class);
		if (ObjectUtil.isEmpty(tmsShipbillHeaderModel)) {
			throw new BizException("运单【" + vo.getBillCode() + "】不存在！");
		}
		if (DataDictionaryConstant.SCAN_STATUS_LOADED.equals(tmsShipbillHeaderModel.getScanStatus())) {
			throw new BizException("运单【" + vo.getBillCode() + "】已扫描！");
		}
		if (!tmsShipbillHeaderModel.getFlowConfig().contains(DataDictionaryConstant.FLOW_CONFIG_SCANNING)) {
			throw new BizException("运单【" + vo.getBillCode() + "】没有匹配到装车扫描的业务流程");
		}
		Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
		Restriction r1 = Restrictions.eq(TmsLoadingBillDetailModel::getEnterpriseId, user.getEnterpriseId());
		Restriction r2 = Restrictions.eq(TmsLoadingBillDetailModel::getShipbillId, tmsShipbillHeaderModel.getShipbillId());
		criteria.setRestriction(Restrictions.and(r1, r2));
		criteria.setOrder(Order.newInstance().desc(new String[] { "createtime" }));
		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModelList = tmsLoadingBillDetailMapper.findByCriteria(criteria);
		if (CollectionUtil.isEmpty(tmsLoadingBillDetailModelList)) {
			throw new BizException("运单【" + vo.getBillCode() + "】对应派车单明细不存在！");
		}
		TmsLoadingBillHeaderModel loadingBillHeaderModel = tmsLoadingBillHeaderMapper.findById(
				tmsLoadingBillDetailModelList.get(0).getLoadingBillId(), TmsLoadingBillHeaderModel.class);
		if (ObjectUtil.isEmpty(loadingBillHeaderModel)) {
			throw new BizException("运单【" + vo.getBillCode() + "】对应派车单不存在！");
		}
		if (!DataDictionaryConstant.SCAN_STATUS_LOADED.equals(loadingBillHeaderModel.getScanStatus())) {
			scanLoadingBill(vo,loadingBillHeaderModel,DataDictionaryConstant.SCANLOADING_METHED_SHIPBILL);
		}
		updateShipBillScan(tmsShipbillHeaderModel);
		dto.setCodeType(LoadingScanOrderTypeEnum.SHIP_NO.getCode());

		LoadingScanDTO shipbillDTO = queryShipbillByLoadingBillData(loadingBillHeaderModel.getLoadingBillId());
		if (ObjectUtil.isNotEmpty(shipbillDTO)) {
			dto.setScannedShipbillList(shipbillDTO.getScannedShipbillList());
			dto.setNoScannedShipbillList(shipbillDTO.getNoScannedShipbillList());
		}
		return dto;
	}

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

	/**
	 * checkLoadingBill
	 * @param vo
	 * @param tmsLoadingBillHeaderModel
	 */
	private void checkLoadingBill(LoadingScanVO vo, TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel) {
		if (DataDictionaryConstant.SCAN_STATUS_LOADED.equals(tmsLoadingBillHeaderModel.getScanStatus())) {
			throw new BizException("派车单【" + vo.getBillCode() + "】已扫描！");
		}
	}

	/**
	 * scanLoadingBill
	 * @param loadingScanVO
	 * @param tmsLoadingBillHeaderModel
	 * @return
	 */
	private LoadingScanDTO scanLoadingBill(LoadingScanVO loadingScanVO,
										   TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel,String scanLoadingMethod) {
		UserEntity user = PlgFxUsrUtils.getUserEntity();
		LoadingScanDTO loadingScanDTO = new LoadingScanDTO();
		// 扫描失败返回
		if (ObjectUtil.isEmpty(tmsLoadingBillHeaderModel)) {
			throw new BizException("派车单【" + loadingScanVO.getBillCode() + "】扫描失败！");
		}
		if (tmsLoadingBillHeaderModel.getStatus().intValue() < DataDictionaryConstant.LOADING_BILL_STATUS_YSH.intValue()
				|| (tmsLoadingBillHeaderModel.getStatus().intValue() >= DataDictionaryConstant.LOADING_BILL_STATUS_ZX_FINISH.intValue()
				&& tmsLoadingBillHeaderModel.getStatus().intValue() != DataDictionaryConstant.LOADING_BILL_STATUS_SCAN.intValue())) {
			throw new BizException("派车单【" + loadingScanVO.getBillCode() + "】扫描失败！");
		}
		if (!DataDictionaryConstant.SCANLOADING_METHED_LOADINGBILL_ITEM.equals(scanLoadingMethod)
				&& DataDictionaryConstant.SCAN_STATUS_LOADED.equals(tmsLoadingBillHeaderModel.getScanStatus())) {
			throw new BizException("派车单【" + loadingScanVO.getBillCode() + "】已扫描！");
		}
		// 修改派车单状态
		if (!DataDictionaryConstant.SCAN_STATUS_LOADED.equals(tmsLoadingBillHeaderModel.getScanStatus())) {
			tmsLoadingBillHeaderModel.setStatus(DataDictionaryConstant.LOADING_BILL_STATUS_SCAN);
			tmsLoadingBillHeaderModel.setUpdateperson(user.getNickname());
			tmsLoadingBillHeaderModel.setUpdatetime(new Date());
			tmsLoadingBillHeaderModel.setScanStatus(DataDictionaryConstant.SCAN_STATUS_LOADED);
			tmsLoadingBillHeaderModel.setLoadingStartDate(DateUtil.date());
			tmsLoadingBillHeaderMapper.update(tmsLoadingBillHeaderModel);
		}

		loadingScanDTO.setCodeType(LoadingScanOrderTypeEnum.LOADING_NO.getCode());
		List<String> loadingBillIds = Lists.newArrayList();
		loadingBillIds.add(tmsLoadingBillHeaderModel.getLoadingBillId());
		loadingScanDTO.setScannedLoadingBillDTOList(getScannedLoadingBill(loadingBillIds));

		if (DataDictionaryConstant.SCANLOADING_METHED_LOADINGBILL_ITEM.equals(scanLoadingMethod)) {
			LoadingScanDTO detailDTO = queryShipbillDetailByLoadingBillData(tmsLoadingBillHeaderModel.getLoadingBillId());
			if (ObjectUtil.isNotEmpty(detailDTO)) {
				loadingScanDTO.setScannedShipbillDetailList(detailDTO.getScannedShipbillDetailList());
				loadingScanDTO.setNoScannedShipbillDetailList(detailDTO.getNoScannedShipbillDetailList());
			}
		} else {
			LoadingScanDTO shipbillDTO = queryShipbillByLoadingBillData(tmsLoadingBillHeaderModel.getLoadingBillId());
			if (ObjectUtil.isNotEmpty(shipbillDTO)) {
				loadingScanDTO.setScannedShipbillList(shipbillDTO.getScannedShipbillList());
				loadingScanDTO.setNoScannedShipbillList(shipbillDTO.getNoScannedShipbillList());
			}
		}
		return loadingScanDTO;
	}

	/**
	 * 装车扫描运单明细
	 * @param vo
	 * @return
	 */
	private LoadingScanDTO scanShipBillDetail(LoadingScanVO vo) {
		if (ObjectUtil.isEmpty(vo.getLoadingBillNo())) {
			throw new BizException("派车单不为空！");
		}
		LoadingScanDTO dto = new LoadingScanDTO();
		UserEntity user = PlgFxUsrUtils.getUserEntity();
		Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
		Restriction r1 = Restrictions.eq(TmsLoadingBillDetailModel::getEnterpriseId, user.getEnterpriseId());
		Restriction r2 = Restrictions.eq(TmsLoadingBillDetailModel::getLoadingBillNo, vo.getLoadingBillNo());
		criteria.setRestriction(Restrictions.and(r1, r2));
		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModelList = tmsLoadingBillDetailMapper.findByCriteria(criteria);
		if (ObjectUtil.isEmpty(tmsLoadingBillDetailModelList)) {
			throw new BizException("商品【" + vo.getBillCode() + "】对应派车单明细不存在！");
		}
		List<String> shipBillList = tmsLoadingBillDetailModelList.stream().map(TmsLoadingBillDetailModel::getShipbillId).collect(Collectors.toList());

		Criteria criteriaShipbillDetail = Criteria.forClass(TmsShipbillDetailModel.class);
		Restriction r11 = Restrictions.eq(TmsShipbillDetailModel::getEnterpriseId, user.getEnterpriseId());
		Restriction r12 = Restrictions.in(TmsShipbillDetailModel::getShipbillId, shipBillList);
		Restriction r13 = Restrictions.eq(TmsShipbillDetailModel::getItemCode, vo.getBillCode());
		criteriaShipbillDetail.setRestriction(Restrictions.and(r11, r12, r13));
		List<TmsShipbillDetailModel> shipbillDetailModels = tmsShipbillDetailMapper.findByCriteria(criteriaShipbillDetail);
		if (ObjectUtil.isEmpty(shipbillDetailModels)) {
			throw new BizException("商品【" + vo.getBillCode() + "】对应运单明细不存在！");
		}
		if (shipbillDetailModels.stream().allMatch(d->DataDictionaryConstant.SCAN_STATUS_LOADED.equals(d.getScanStatus()))) {
			throw new BizException("商品【" + vo.getBillCode() + "】已扫描！");
		}

		shipbillDetailModels.stream().filter(d->DataDictionaryConstant.SCAN_STATUS_INIT.equals(d.getScanStatus()))
							.map(TmsShipbillDetailModel::getShipbillId).distinct().collect(Collectors.toList())
							.stream().forEach(billId->{
			TmsShipbillHeaderModel tmsShipbillHeaderModel = tmsShipbillHeaderMapper.findById(billId, TmsShipbillHeaderModel.class);

			if (!tmsShipbillHeaderModel.getFlowConfig().contains(DataDictionaryConstant.FLOW_CONFIG_SCANNING)) {
				throw new BizException("商品【" + vo.getBillCode() + "】没有匹配到装车扫描的业务流程");
			}
			Criteria criteriaLoadingBillDetail = Criteria.forClass(TmsLoadingBillDetailModel.class);
			Restriction r3 = Restrictions.eq(TmsLoadingBillDetailModel::getEnterpriseId, user.getEnterpriseId());
			Restriction r4 = Restrictions.eq(TmsLoadingBillDetailModel::getShipbillId, tmsShipbillHeaderModel.getShipbillId());
			criteriaLoadingBillDetail.setRestriction(Restrictions.and(r3, r4));
			criteriaLoadingBillDetail.setOrder(Order.newInstance().desc(new String[] { "createtime" }));
			List<TmsLoadingBillDetailModel> loadingBillDetailModelList = tmsLoadingBillDetailMapper.findByCriteria(criteriaLoadingBillDetail);
			if (CollectionUtil.isEmpty(loadingBillDetailModelList)) {
				throw new BizException("商品【" + vo.getBillCode() + "】对应派车单明细不存在！");
			}
			TmsLoadingBillDetailModel loadingBillDetailModel = loadingBillDetailModelList.get(0);
			TmsLoadingBillHeaderModel loadingBillHeaderModel = tmsLoadingBillHeaderMapper.findById(
					loadingBillDetailModel.getLoadingBillId(), TmsLoadingBillHeaderModel.class);
			if (ObjectUtil.isEmpty(loadingBillHeaderModel)) {
				throw new BizException("商品【" + vo.getBillCode() + "】对应派车单不存在！");
			}
			if (!DataDictionaryConstant.SCAN_STATUS_LOADED.equals(loadingBillHeaderModel.getScanStatus())) {
				throw new BizException("请先扫描派车单！");
			}
			if (!DataDictionaryConstant.SCAN_STATUS_LOADED.equals(loadingBillDetailModel.getScanStatus())) {
				updateShipBillScan(tmsShipbillHeaderModel);

			}
			updateShipBillDetailScan(tmsShipbillHeaderModel,vo);
		});

		LoadingScanDTO detailDTO = queryShipbillDetailByLoadingBillData(vo.getLoadingBillNo());
		if (ObjectUtil.isNotEmpty(detailDTO)) {
			dto.setScannedShipbillDetailList(detailDTO.getScannedShipbillDetailList());
			dto.setNoScannedShipbillDetailList(detailDTO.getNoScannedShipbillDetailList());
		}
		dto.setCodeType(LoadingScanOrderTypeEnum.ITEM_NO.getCode());
		return dto;
	}

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

		Criteria criteriaShipbillDetail = Criteria.forClass(TmsShipbillDetailModel.class);
		Restriction r11 = Restrictions.eq(TmsShipbillDetailModel::getEnterpriseId, user.getEnterpriseId());
		Restriction r12 = Restrictions.eq(TmsShipbillDetailModel::getShipbillId, tmsShipbillHeaderModel.getShipbillId());
		Restriction r13 = Restrictions.eq(TmsShipbillDetailModel::getItemCode, vo.getBillCode());
		Restriction r14 = Restrictions.eq(TmsShipbillDetailModel::getScanStatus, DataDictionaryConstant.SCAN_STATUS_INIT);
		criteriaShipbillDetail.setRestriction(Restrictions.and(r11, r12, r13,r14));
		List<TmsShipbillDetailModel> shipbillDetailModels = tmsShipbillDetailMapper.findByCriteria(criteriaShipbillDetail);

		shipbillDetailModels.stream().forEach(detail->{
			TmsShipbillDetailScanModel detailScanModel = new TmsShipbillDetailScanModel();
			RestMessage<String> restMessage = maindataTmsResource.getCodeNumberByCode(SeriaNnumberConstant.TMS_SHIPBILL_DETAIL_SCAN_ID, "L");
			if (!restMessage.isSuccess()) {
				throw new RuntimeException("生成运单明细扫描表ID失败");
			}
			String id = restMessage.getData();
			detailScanModel.setId(id);
			detailScanModel.setLoadingBillNo(vo.getLoadingBillNo());
			detailScanModel.setShipbillId(tmsShipbillHeaderModel.getShipbillId());
			detailScanModel.setShipbillNo(tmsShipbillHeaderModel.getShipbillNo());
			detailScanModel.setShipbillDetailId(detail.getId());
			detailScanModel.setItemId(detail.getItemId());
			detailScanModel.setItemCode(detail.getItemCode());
			detailScanModel.setItemName(detail.getItemName());
			detailScanModel.setConfirmStatus(20);
			detailScanModel.setScanStatus(20);
			detailScanModel.setPcs(detail.getPcs());
			detailScanModel.setScannedPcs(detail.getPcs());
			detailScanModel.setStagingLocation(detail.getStagingLocation());
			detailScanModel.setCreateperson(user.getNickname());
			detailScanModel.setCreatetime(DateUtil.date());
			tmsShipbillDetailScanMapper.save(detailScanModel);

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

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

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

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

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

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

	public String Dateformat(Date start, Date end) {
		String startStr = ToolKits.isEmpty(start) ? "" : DateUtils.format(start);
		String endStr = ToolKits.isEmpty(end) ? "" : DateUtils.format(end);
		return startStr + "-" + endStr;
	}

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

			// 查找同级的所有子单
			Criteria criteria = Criteria.forClass(TmsShipbillHeaderModel.class);
			Restriction r1 = Restrictions.eq("fatherShipbillId", tmsShipbillHeaderModel.getFatherShipbillId());
			criteria.setRestriction(r1);
			List<TmsShipbillHeaderModel> tmsShipbillHeaderModelList = tmsShipbillHeaderMapper.findByCriteria(criteria);

			// 查找是否还有未扫描的运单
			List<TmsShipbillHeaderModel> tmsShipbillHeaderModels = tmsShipbillHeaderModelList.stream().filter(o -> o.getScanStatus() == DataDictionaryConstant.SCAN_STATUS_INIT).collect(Collectors.toList());

			// 判断子单是否全部扫描
			if (ToolKits.isEmpty(tmsShipbillHeaderModels)) {
				// 修改父级运单状态
				fatherShipbillHeaderModel.setScanStatus(DataDictionaryConstant.SCAN_STATUS_LOADED);
				fatherShipbillHeaderModel.setUpdatetime(date);
				fatherShipbillHeaderModel.setUpdateperson(user.getNickname());
				tmsShipbillHeaderMapper.update(fatherShipbillHeaderModel);

				// 运单节点保存
				ShipbillNodeTrackingSaveNewVO shipbillNodeTrackingSaveNewVO = new ShipbillNodeTrackingSaveNewVO();
				shipbillNodeTrackingSaveNewVO.setNodeDate(date);
				shipbillNodeTrackingSaveNewVO.setShipbillId(fatherShipbillHeaderModel.getShipbillId());
				shipbillNodeTrackingSaveNewVO.setShipbillNo(fatherShipbillHeaderModel.getShipbillId());
				shipbillNodeTrackingSaveNewVO.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_ZX_START);
				shipbillNodeTrackingSaveNewVO.setNodeEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_ZC_SCAN);
				shipbillNodeTrackingSaveNewVO.setUserId(user.getUserid());
				shipbillNodeTrackingSaveNewVO.setUserName(user.getNickname());
				shipbillNodeTrackingSaveNewVO.setEnterpriseId(user.getEnterpriseId());
				shipbillNodeTrackingSaveNewVO.setEnterpriseName(user.getEnterpriseName());
				shipbillNodeTrackingService.addShipbillNodeTrackingNewData(shipbillNodeTrackingSaveNewVO);

				// 运单日志保存
				ShipbillOperateLogSaveNewVO shipbillOperateLogSaveNewVO = new ShipbillOperateLogSaveNewVO();
				shipbillOperateLogSaveNewVO.setShipbillId(fatherShipbillHeaderModel.getShipbillId());
				shipbillOperateLogSaveNewVO.setShipbillNo(fatherShipbillHeaderModel.getShipbillId());
				shipbillOperateLogSaveNewVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_ZC_SCAN);
				shipbillOperateLogSaveNewVO.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_ZX_START);
				shipbillOperateLogSaveNewVO.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_ZX_START);
				shipbillOperateLogSaveNewVO.setOperateDate(date);
				shipbillOperateLogSaveNewVO.setEnterpriseId(user.getEnterpriseId());
				shipbillOperateLogSaveNewVO.setEnterpriseName(user.getEnterpriseName());
				shipbillOperateLogSaveNewVO.setUserId(user.getUserid());
				shipbillOperateLogSaveNewVO.setUserName(user.getNickname());
				shipbillOperateLogService.addShipbillOperateLogNewData(shipbillOperateLogSaveNewVO);

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

	@Override
	public void shipBillOut(WaitPickUpConfirmVO vo) {
		ToolKits.isParamNull(vo, "运单剔除请求不为空");
		ToolKits.isParamNull(vo.getLoadingBillId(), "派车单号不能为空");

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

		// 查询运单信息
		Criteria criteriaLoadingBillDetail = Criteria.forClass(TmsLoadingBillDetailModel.class);
		Restriction r1 = Restrictions.eq(TmsLoadingBillDetailModel::getLoadingBillId, vo.getLoadingBillId());
		Restriction r2 = Restrictions.eq(TmsLoadingBillDetailModel::getLoadingBillNo, vo.getLoadingBillId());
		Restriction r3 = Restrictions.or(r1, r2);
		Restriction r4 = Restrictions.eq(TmsLoadingBillDetailModel::getEnterpriseId, user.getEnterpriseId());
		Restriction r5 = Restrictions.eq(TmsLoadingBillDetailModel::getScanStatus, DataDictionaryConstant.SCAN_STATUS_INIT);
		criteriaLoadingBillDetail.setRestriction(Restrictions.and( r3,r4,r5));
		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModelCull = tmsLoadingBillDetailMapper.findByCriteria(criteriaLoadingBillDetail);
		if (ToolKits.isNotEmpty(tmsLoadingBillDetailModelCull)) {
			// 未装明细，剔除操作
			List<String> ids = tmsLoadingBillDetailModelCull.stream().map(o -> o.getShipbillId()).collect(Collectors.toList());
			SendCarDeleteDetailVO deleteDetailVO = new SendCarDeleteDetailVO();
			deleteDetailVO.setLoadingBillId(tmsLoadingBillDetailModelCull.get(0).getLoadingBillId());
			deleteDetailVO.setShipbillIds(ids);
			deleteDetailSendCarData(deleteDetailVO, DateUtil.date());

			bookingService.cancelAppointment(ids);
		}
	}
	/**
	 * 装车确认
	 *
	 * @param waitPickUpConfirmVO
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public LoadingScanConfirmDTO loadingConfirmData(WaitPickUpConfirmVO waitPickUpConfirmVO) {
		ToolKits.isParamNull(waitPickUpConfirmVO, "装车确认请求不为空");
		ToolKits.isParamNull(waitPickUpConfirmVO.getLoadingBillId(), "派车单号不能为空");
		//ToolKits.isParamNull(waitPickUpConfirmVO.getContainerWithVehicle(), "容器是否随车不为空");
		ToolKits.isParamNull(waitPickUpConfirmVO.getScanLoadingMethod(), "扫描方式不为空");

		UserEntity user = PlgFxUsrUtils.getUserEntity();
		ToolKits.isParamNull(user, "当前人员没有操作权限");
		LoadingScanConfirmDTO confirmDTO = new LoadingScanConfirmDTO();
		confirmDTO.setType("3");
		if (!user.getUserType().equals(BussinessConstant.USER_TYPE_ZY) && !user.getUserType().equals(BussinessConstant.USER_TYPE_CYS)) {
			ToolKits.isParamNull(user, "当前人员没有操作权限");
		}
		// 当前时间
		Date date = DateUtils.nowDate();
		List<String> allShipbillIds = Lists.newArrayList();

		// 查询已装车扫描的运单
		Criteria criteriaLoadingBillDetail = Criteria.forClass(TmsLoadingBillDetailModel.class);
		Restriction r1 = Restrictions.eq(TmsLoadingBillDetailModel::getLoadingBillId, waitPickUpConfirmVO.getLoadingBillId());
		Restriction r2 = Restrictions.eq(TmsLoadingBillDetailModel::getLoadingBillNo, waitPickUpConfirmVO.getLoadingBillId());
		Restriction r3 = Restrictions.or(r1, r2);
		Restriction r4 = Restrictions.eq(TmsLoadingBillDetailModel::getEnterpriseId, user.getEnterpriseId());
		Restriction r5 = Restrictions.eq(TmsLoadingBillDetailModel::getScanStatus, DataDictionaryConstant.SCAN_STATUS_LOADED);
		criteriaLoadingBillDetail.setRestriction(Restrictions.and( r3,r4,r5));
		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModelConfirm = tmsLoadingBillDetailMapper.findByCriteria(criteriaLoadingBillDetail);
		if (ToolKits.isEmpty(tmsLoadingBillDetailModelConfirm)) {
			throw new PrologException(StrUtil.format("派车单{}下没有已扫描的单据",waitPickUpConfirmVO.getLoadingBillId()));
		}
		allShipbillIds.addAll(tmsLoadingBillDetailModelConfirm.stream().map(TmsLoadingBillDetailModel::getShipbillId).distinct().collect(Collectors.toList()));

		// 查询运单信息
		r1 = Restrictions.eq(TmsLoadingBillDetailModel::getLoadingBillId, waitPickUpConfirmVO.getLoadingBillId());
		r2 = Restrictions.eq(TmsLoadingBillDetailModel::getLoadingBillNo, waitPickUpConfirmVO.getLoadingBillId());
		r3 = Restrictions.or(r1, r2);
		r4 = Restrictions.eq(TmsLoadingBillDetailModel::getEnterpriseId, user.getEnterpriseId());
		r5 = Restrictions.eq(TmsLoadingBillDetailModel::getScanStatus, DataDictionaryConstant.SCAN_STATUS_INIT);
		criteriaLoadingBillDetail.setRestriction(Restrictions.and( r3,r4,r5));
		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModelCull = tmsLoadingBillDetailMapper.findByCriteria(criteriaLoadingBillDetail);
		if (ToolKits.isNotEmpty(tmsLoadingBillDetailModelCull)) {
			shipBillOut(waitPickUpConfirmVO);
		}

		// 查询调度单
		Criteria criteria = Criteria.forClass(TmsLoadingBillHeaderModel.class);
		r1 = Restrictions.eq("loadingBillId", waitPickUpConfirmVO.getLoadingBillId());
		r2 = Restrictions.eq("loadingBillNo", waitPickUpConfirmVO.getLoadingBillId());
		r3 = Restrictions.or(r1, r2);
		r4 = Restrictions.eq("status", DataDictionaryConstant.LOADING_BILL_STATUS_SCAN);
		r5 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
		criteria.setRestriction(Restrictions.and(r3, r4, r5));
		List<TmsLoadingBillHeaderModel> tmsLoadingBillHeaderModels = tmsLoadingBillHeaderMapper.findByCriteria(criteria);

		ToolKits.isParamNull(tmsLoadingBillHeaderModels, "派车单号[" + waitPickUpConfirmVO.getLoadingBillId() + "]有误,查询为空!");

		TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel = tmsLoadingBillHeaderModels.get(0);

		if (ToolKits.isNotEmpty(tmsLoadingBillHeaderModel.getColdShipbillNumber()) && tmsLoadingBillHeaderModel.getColdShipbillNumber().intValue() > 0) {
			if (ToolKits.isNotEmpty(tmsLoadingBillHeaderModel.getVehicleTypeCategory())
					&& !tmsLoadingBillHeaderModel.getVehicleTypeCategory().equals(DataDictionaryConstant.VEHICLE_TYPE_CATEGORY_CLOUD.toString())
					&& ToolKits.isEmpty(waitPickUpConfirmVO.getVehicleDeviceCode()))  {
				throw new PrologException("请先绑定设备号！");
			}
		}

		// 修改派车单
		if (ToolKits.isNotEmpty(waitPickUpConfirmVO.getVehicleDeviceCode())) {
			tmsLoadingBillHeaderModel.setVehicleDeviceId(waitPickUpConfirmVO.getVehicleDeviceId());
			tmsLoadingBillHeaderModel.setVehicleDeviceCode(waitPickUpConfirmVO.getVehicleDeviceCode());
			tmsLoadingBillHeaderModel.setVehicleDeviceName(waitPickUpConfirmVO.getVehicleDeviceName());
		}
		tmsLoadingBillHeaderModel.setStatus(DataDictionaryConstant.LOADING_BILL_STATUS_ZC_CONFIRM);
		tmsLoadingBillHeaderModel.setContainerWithVehicle(waitPickUpConfirmVO.getContainerWithVehicle());
		tmsLoadingBillHeaderModel.setUpdateperson(user.getNickname());
		tmsLoadingBillHeaderModel.setUpdatetime(date);
		tmsLoadingBillHeaderModel.setLoadingEndDate(date);
		tmsLoadingBillHeaderMapper.update(tmsLoadingBillHeaderModel);

		// 修改派车单明细
		for (TmsLoadingBillDetailModel tmsLoadingBillDetailModel : tmsLoadingBillDetailModelConfirm) {
			String flowConfig = "";
			if (user.getUserType().equals(BussinessConstant.USER_TYPE_CYS)) {
				flowConfig = tmsLoadingBillDetailModel.getCarrierFlowConfig();
			} else {
				flowConfig = tmsLoadingBillDetailModel.getFlowConfig();
			}
			if (!flowConfig.contains(DataDictionaryConstant.FLOW_CONFIG_SCANNING)) {
				throw new PrologException("运单【" + tmsLoadingBillDetailModel.getShipbillNo() + "】没有匹配到装车扫描的业务流程");
			}

			if (!tmsLoadingBillDetailModel.getStatus().equals(DataDictionaryConstant.SHIPBILL_STATUS_ZC_SCAN)) {
				throw new PrologException("运单【" + tmsLoadingBillDetailModel.getShipbillNo() + "】不是待扫描状态，不能扫描");
			}

			// 判断下一步流程
			int status = businessFlowUtil.judgmentNextFlowSts(flowConfig, DataDictionaryConstant.FLOW_CONFIG_SCANNING);
			Map<String, Object> map = Maps.newHashMap();

			tmsLoadingBillDetailModel.setStatus(status);

			tmsLoadingBillDetailModel.setScanStatus(DataDictionaryConstant.SCAN_STATUS_LOADED);
			tmsLoadingBillDetailModel.setUpdateperson(user.getNickname());
			tmsLoadingBillDetailModel.setUpdatetime(date);

			if (ToolKits.isNotEmpty(waitPickUpConfirmVO.getVehicleDeviceCode())) {
				tmsLoadingBillDetailModel.setVehicleDeviceId(String.valueOf(waitPickUpConfirmVO.getVehicleDeviceId()));
				tmsLoadingBillDetailModel.setVehicleDeviceCode(waitPickUpConfirmVO.getVehicleDeviceCode());
				tmsLoadingBillDetailModel.setVehicleDeviceName(waitPickUpConfirmVO.getVehicleDeviceName());

				map.put("vehicleDeviceId", String.valueOf(waitPickUpConfirmVO.getVehicleDeviceId()));
				map.put("vehicleDeviceCode", waitPickUpConfirmVO.getVehicleDeviceCode());
				map.put("vehicleDeviceName", waitPickUpConfirmVO.getVehicleDeviceName());
			}

			// 修改派车单明细
			tmsLoadingBillDetailMapper.update(tmsLoadingBillDetailModel);

			// 修改运单
			map.put("status", status);
			map.put("updateperson", user.getNickname());
			map.put("updatetime", date);
			map.put("scanStatus", DataDictionaryConstant.SCAN_STATUS_LOADED);
			tmsShipbillHeaderMapper.updateMapById(tmsLoadingBillDetailModel.getShipbillId(), map, TmsShipbillHeaderModel.class);

			// 运单节点保存
			ShipbillNodeTrackingSaveNewVO shipbillNodeTrackingSaveNewVO = new ShipbillNodeTrackingSaveNewVO();
			shipbillNodeTrackingSaveNewVO.setNodeDate(date);
			shipbillNodeTrackingSaveNewVO.setShipbillId(tmsLoadingBillDetailModel.getShipbillId());
			shipbillNodeTrackingSaveNewVO.setShipbillNo(tmsLoadingBillDetailModel.getShipbillId());
			shipbillNodeTrackingSaveNewVO.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_ZX_START);
			shipbillNodeTrackingSaveNewVO.setNodeEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_ZC_SCAN);
			shipbillNodeTrackingSaveNewVO.setUserId(user.getUserid());
			shipbillNodeTrackingSaveNewVO.setUserName(user.getNickname());
			shipbillNodeTrackingSaveNewVO.setEnterpriseId(user.getEnterpriseId());
			shipbillNodeTrackingSaveNewVO.setEnterpriseName(user.getEnterpriseName());
			shipbillNodeTrackingService.addShipbillNodeTrackingNewData(shipbillNodeTrackingSaveNewVO);

			// 运单日志保存
			ShipbillOperateLogSaveNewVO shipbillOperateLogSaveNewVO = new ShipbillOperateLogSaveNewVO();
			shipbillOperateLogSaveNewVO.setShipbillId(tmsLoadingBillDetailModel.getShipbillId());
			shipbillOperateLogSaveNewVO.setShipbillNo(tmsLoadingBillDetailModel.getShipbillId());
			shipbillOperateLogSaveNewVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_ZC_SCAN);
			shipbillOperateLogSaveNewVO.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_ZX_START);
			shipbillOperateLogSaveNewVO.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_ZX_START);
			shipbillOperateLogSaveNewVO.setOperateDate(date);
			shipbillOperateLogSaveNewVO.setEnterpriseId(user.getEnterpriseId());
			shipbillOperateLogSaveNewVO.setEnterpriseName(user.getEnterpriseName());
			shipbillOperateLogSaveNewVO.setUserId(user.getUserid());
			shipbillOperateLogSaveNewVO.setUserName(user.getNickname());
			shipbillOperateLogService.addShipbillOperateLogNewData(shipbillOperateLogSaveNewVO);

			// 运单节点保存
			shipbillNodeTrackingSaveNewVO.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_QY);
			shipbillNodeTrackingSaveNewVO.setNodeEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_ZC_SCAN);
			shipbillNodeTrackingService.addShipbillNodeTrackingNewData(shipbillNodeTrackingSaveNewVO);

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

			// 父运单的同步装车扫描
			String fatherShipbillId = tmsLoadingBillDetailModel.getShipbillId();
			while (ToolKits.isNotEmpty(fatherShipbillId)) {
				fatherShipbillId = fatherLoadingScan(fatherShipbillId, date, user);
			}

			// 父运单的同步装车确认
			String fatherShipbillId2 = tmsLoadingBillDetailModel.getShipbillId();
			while (ToolKits.isNotEmpty(fatherShipbillId2)) {
				fatherShipbillId2 = fatherLoadingConfirm(fatherShipbillId2, date, user, status);
			}

			updateLoadingTime(tmsLoadingBillDetailModel.getShipbillId(),null,DateUtil.date());
		}

		if (DataDictionaryConstant.SCANLOADING_METHED_LOADINGBILL_ITEM.equals(waitPickUpConfirmVO.getScanLoadingMethod())) {
			splitScanConfirm(allShipbillIds.stream().distinct().collect(Collectors.toList()));
		}
		return confirmDTO;
	}

	/**
	 * 运单明细拆分
	 * @param shipbillIds
	 * @return
	 */
	public void splitScanConfirm(List<String> shipbillIds) {
		Criteria criteriaShipbillDetail = Criteria.forClass(TmsShipbillDetailModel.class);
		Restriction r1 = Restrictions.in(TmsShipbillDetailModel::getShipbillId, shipbillIds);
		Restriction r2 = Restrictions.eq(TmsShipbillDetailModel::getScanStatus, DataDictionaryConstant.SCAN_STATUS_INIT);
		criteriaShipbillDetail.setRestriction(Restrictions.and(r1,r2));
		List<TmsShipbillDetailModel> noScanTmsShipbillDetailModels = tmsShipbillDetailMapper.findByCriteria(criteriaShipbillDetail);

		if (ObjectUtil.isNotEmpty(noScanTmsShipbillDetailModels)) {
			createNewShipbill(noScanTmsShipbillDetailModels);
		}
	}

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

			// 查找同级的所有子单
			Criteria criteria = Criteria.forClass(TmsShipbillHeaderModel.class);
			Restriction r1 = Restrictions.eq("fatherShipbillId", tmsShipbillHeaderModel.getFatherShipbillId());
			criteria.setRestriction(r1);
			List<TmsShipbillHeaderModel> tmsShipbillHeaderModelList = tmsShipbillHeaderMapper.findByCriteria(criteria);

			// 查找是否还有未扫描的运单
			List<TmsShipbillHeaderModel> tmsShipbillHeaderModels = tmsShipbillHeaderModelList.stream().filter(o -> o.getStatus().intValue() < DataDictionaryConstant.SHIPBILL_STATUS_ZX_FINISH.intValue()).collect(Collectors.toList());

			// 判断子单是否全部扫描
			if (ToolKits.isEmpty(tmsShipbillHeaderModels)) {
				// 修改父级运单状态
				fatherShipbillHeaderModel.setStatus(status);
				fatherShipbillHeaderModel.setUpdatetime(date);
				fatherShipbillHeaderModel.setUpdateperson(user.getNickname());
				tmsShipbillHeaderMapper.update(fatherShipbillHeaderModel);

				// 运单节点保存
				ShipbillNodeTrackingSaveNewVO shipbillNodeTrackingSaveNewVO = new ShipbillNodeTrackingSaveNewVO();
				shipbillNodeTrackingSaveNewVO.setNodeDate(date);
				shipbillNodeTrackingSaveNewVO.setShipbillId(fatherShipbillHeaderModel.getShipbillId());
				shipbillNodeTrackingSaveNewVO.setShipbillNo(fatherShipbillHeaderModel.getShipbillId());
				shipbillNodeTrackingSaveNewVO.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_ZX_CONFIRM);
				shipbillNodeTrackingSaveNewVO.setNodeEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_ZC_CONFIRM);
				shipbillNodeTrackingSaveNewVO.setUserId(user.getUserid());
				shipbillNodeTrackingSaveNewVO.setUserName(user.getNickname());
				shipbillNodeTrackingSaveNewVO.setEnterpriseId(user.getEnterpriseId());
				shipbillNodeTrackingSaveNewVO.setEnterpriseName(user.getEnterpriseName());
				shipbillNodeTrackingService.addShipbillNodeTrackingNewData(shipbillNodeTrackingSaveNewVO);

				// 运单日志保存
				ShipbillOperateLogSaveNewVO shipbillOperateLogSaveNewVO = new ShipbillOperateLogSaveNewVO();
				shipbillOperateLogSaveNewVO.setShipbillId(fatherShipbillHeaderModel.getShipbillId());
				shipbillOperateLogSaveNewVO.setShipbillNo(fatherShipbillHeaderModel.getShipbillId());
				shipbillOperateLogSaveNewVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_ZC_CONFIRM);
				shipbillOperateLogSaveNewVO.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_ZC_SCAN);
				shipbillOperateLogSaveNewVO.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_ZX_CONFIRM);
				shipbillOperateLogSaveNewVO.setOperateDate(date);
				shipbillOperateLogSaveNewVO.setEnterpriseId(user.getEnterpriseId());
				shipbillOperateLogSaveNewVO.setEnterpriseName(user.getEnterpriseName());
				shipbillOperateLogSaveNewVO.setUserId(user.getUserid());
				shipbillOperateLogSaveNewVO.setUserName(user.getNickname());
				shipbillOperateLogService.addShipbillOperateLogNewData(shipbillOperateLogSaveNewVO);

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

	public void deleteDetailSendCarData(SendCarDeleteDetailVO sendCarDeleteDetailVO, Date date) {
		ToolKits.isParamNull(sendCarDeleteDetailVO.getLoadingBillId(), "派车单ID不为空");
		ToolKits.isParamNull(sendCarDeleteDetailVO.getShipbillIds(), "运单ID不为空");

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

		Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
		Restriction r1 = Restrictions.in("shipbillId", sendCarDeleteDetailVO.getShipbillIds().toArray());
		criteria.setRestriction(r1);
		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteria);

		TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel = tmsLoadingBillHeaderMapper.findById(sendCarDeleteDetailVO.getLoadingBillId(), TmsLoadingBillHeaderModel.class);

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

			// 修改配送顺序
			r1 = Restrictions.eq("loadingBillId", tmsLoadingBillDetailModel.getLoadingBillId());
			Restriction r2 = Restrictions.ne("shipbillId", tmsLoadingBillDetailModel.getShipbillId());
			criteria.setRestriction(Restrictions.and(r1, r2));
			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.setUpdatetime(date);
				loadingBillDetailModel.setUpdateperson(user.getNickname());
				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(ToolKits.isEmpty(tmsLoadingBillDetailModel.getActualTotalVolume()) ? BigDecimal.ZERO : tmsLoadingBillDetailModel.getActualTotalVolume()));
			tmsLoadingBillHeaderModel.setActualTotalWeight(tmsLoadingBillHeaderModel.getActualTotalWeight().subtract(ToolKits.isEmpty(tmsLoadingBillDetailModel.getActualTotalWeight()) ? BigDecimal.ZERO : 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);

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

			// 运单日志保存
			ShipbillOperateLogSaveNewVO shipbillOperateLogSaveNewVO = new ShipbillOperateLogSaveNewVO();
			shipbillOperateLogSaveNewVO.setShipbillId(tmsLoadingBillDetailModel.getShipbillId());
			shipbillOperateLogSaveNewVO.setShipbillNo(tmsLoadingBillDetailModel.getShipbillId());
			shipbillOperateLogSaveNewVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_ZC_CONFIRM);
			shipbillOperateLogSaveNewVO.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_ZC_SCAN);
			shipbillOperateLogSaveNewVO.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_QY);
			shipbillOperateLogSaveNewVO.setOperateDate(date);
			shipbillOperateLogSaveNewVO.setEnterpriseId(user.getEnterpriseId());
			shipbillOperateLogSaveNewVO.setEnterpriseName(user.getEnterpriseName());
			shipbillOperateLogSaveNewVO.setUserId(user.getUserid());
			shipbillOperateLogSaveNewVO.setUserName(user.getNickname());
			shipbillOperateLogService.addShipbillOperateLogNewData(shipbillOperateLogSaveNewVO);
		}

		// 计算装载率
		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.setUpdatetime(date);
		tmsLoadingBillHeaderModel.setUpdateperson(user.getNickname());
		tmsLoadingBillHeaderMapper.update(tmsLoadingBillHeaderModel);

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

		Map<String, Object> map = Maps.newHashMap();
		map.put("updateperson", user.getNickname());
		map.put("updatetime", date);
		map.put("status", DataDictionaryConstant.SHIPBILL_STATUS_REVIEW);
		map.put("scanStatus", DataDictionaryConstant.SCAN_STATUS_INIT);
		tmsShipbillHeaderMapper.updateMapByCriteria(map, criteria);
	}

	/**
	 * 计算装载率
	 *
	 * @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 loadingBillId
	 */
	public LoadingScanDTO queryShipbillByLoadingBillData(String loadingBillId) {
		ToolKits.isParamNull(loadingBillId, "装车单ID不为空");

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

		if (!user.getUserType().equals(BussinessConstant.USER_TYPE_ZY) && !user.getUserType().equals(BussinessConstant.USER_TYPE_CYS)) {
			ToolKits.isParamNull(user, "当前人员没有操作权限");
		}

		// 数据字典翻译数据集合
		List<SysRefdatadModel> dicData = convertorUtil.getDictionary(new String[] {
				DataDictionaryConstant.LOADING_BILL_STATUS,
				DataDictionaryConstant.ORDER_TYPE,
				DataDictionaryConstant.ORDER_BUSINESS_TYPE,
				DataDictionaryConstant.DELIVERY_METHOD_TYPE,
				DataDictionaryConstant.TRANSPORT_TYPE,
				DataDictionaryConstant.TEMPERATURE_REQUIREMENT,
				DataDictionaryConstant.SHIPPER_TYPE,
				DataDictionaryConstant.CONSIGNEE_TYPE,
				DataDictionaryConstant.SHIPBILL_STATUS,
				DataDictionaryConstant.TRANSPORT_STATUS,
				DataDictionaryConstant.ABNORMAL_STATUS,
				DataDictionaryConstant.LINE_CARRIER_TYPE,
				DataDictionaryConstant.SCAN_STATUS
		});
		// 添加查询条件
		Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
		Restriction r1 = Restrictions.eq(TmsLoadingBillDetailModel::getLoadingBillId, loadingBillId);
		Restriction r2 = Restrictions.eq(TmsLoadingBillDetailModel::getLoadingBillNo, loadingBillId);
		Restriction r3 = Restrictions.or(r1, r2);
		Restriction r4 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
		Restriction r5 = Restrictions.eq(TmsLoadingBillDetailModel::getStatus, DataDictionaryConstant.SHIPBILL_STATUS_ZC_SCAN);
		criteria.setRestriction(Restrictions.and(r3, r4, r5));
		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteria);

		// 返回数据集
		List<WaitPickUpGoodsNotScannedDTO> notScannedDTOS = Lists.newArrayList();
		List<WaitPickUpGoodsNotScannedDTO> scannedDTOS = Lists.newArrayList();

		// 未扫描运单数据封装
		for (TmsLoadingBillDetailModel tmsLoadingBillDetailModel : tmsLoadingBillDetailModels) {
			WaitPickUpGoodsNotScannedDTO waitPickUpGoodsNotScannedDTO = new WaitPickUpGoodsNotScannedDTO();
			BeanUtils.copyProperties(tmsLoadingBillDetailModel, waitPickUpGoodsNotScannedDTO);
			// 收货方位置(经纬度判断)
			if (ToolKits.isNotEmpty(tmsLoadingBillDetailModel.getConsigneeLongitude()) && ToolKits.isNotEmpty(tmsLoadingBillDetailModel.getConsigneeLatitude())) {
				waitPickUpGoodsNotScannedDTO.setConsigneePositioning(StatusConstant.POSITIONING_YDW);
			} else {
				waitPickUpGoodsNotScannedDTO.setConsigneePositioning(StatusConstant.POSITIONING_WDW);
			}
			// 发货方位置(经纬度判断)
			if (ToolKits.isNotEmpty(tmsLoadingBillDetailModel.getShipperLongitude()) && ToolKits.isNotEmpty(tmsLoadingBillDetailModel.getShipperLatitude())) {
				waitPickUpGoodsNotScannedDTO.setShipperPositioning(StatusConstant.POSITIONING_YDW);
			} else {
				waitPickUpGoodsNotScannedDTO.setShipperPositioning(StatusConstant.POSITIONING_WDW);
			}

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

			// 类型翻译
			waitPickUpGoodsNotScannedDTO.setOrderTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.ORDER_TYPE, String.valueOf(waitPickUpGoodsNotScannedDTO.getOrderType())));
			waitPickUpGoodsNotScannedDTO.setOrderBusinessTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.ORDER_BUSINESS_TYPE, String.valueOf(waitPickUpGoodsNotScannedDTO.getOrderBusinessType())));
			waitPickUpGoodsNotScannedDTO.setDeliveryMethodTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.DELIVERY_METHOD_TYPE, String.valueOf(waitPickUpGoodsNotScannedDTO.getDeliveryMethodType())));
			waitPickUpGoodsNotScannedDTO.setTransportTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.TRANSPORT_TYPE, String.valueOf(waitPickUpGoodsNotScannedDTO.getTransportType())));
			waitPickUpGoodsNotScannedDTO.setTemperatureRequirementName(ConvertorUtil.getName(dicData, DataDictionaryConstant.TEMPERATURE_REQUIREMENT, String.valueOf(waitPickUpGoodsNotScannedDTO.getTemperatureRequirement())));
			waitPickUpGoodsNotScannedDTO.setShipperTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.SHIPPER_TYPE, String.valueOf(waitPickUpGoodsNotScannedDTO.getShipperType())));
			waitPickUpGoodsNotScannedDTO.setConsigneeTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.CONSIGNEE_TYPE, String.valueOf(waitPickUpGoodsNotScannedDTO.getConsigneeType())));
			waitPickUpGoodsNotScannedDTO.setStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.SHIPBILL_STATUS, String.valueOf(waitPickUpGoodsNotScannedDTO.getStatus())));
			waitPickUpGoodsNotScannedDTO.setTransportStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.TRANSPORT_STATUS, String.valueOf(waitPickUpGoodsNotScannedDTO.getTransportStatus())));
			waitPickUpGoodsNotScannedDTO.setAbnormalStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.ABNORMAL_STATUS, String.valueOf(waitPickUpGoodsNotScannedDTO.getAbnormalStatus())));
			waitPickUpGoodsNotScannedDTO.setCarrierTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.LINE_CARRIER_TYPE, String.valueOf(waitPickUpGoodsNotScannedDTO.getCarrierType())));
			waitPickUpGoodsNotScannedDTO.setScanStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.SCAN_STATUS, String.valueOf(waitPickUpGoodsNotScannedDTO.getScanStatus())));
			waitPickUpGoodsNotScannedDTO.setEstimatedPickupTime(Dateformat(tmsLoadingBillDetailModel.getEstimatedPickupStartTime(), tmsLoadingBillDetailModel.getEstimatedPickupEndTime()));
			waitPickUpGoodsNotScannedDTO.setEstimatedDeliveryEndTime(Dateformat(tmsLoadingBillDetailModel.getEstimatedDeliveryStartTime(), tmsLoadingBillDetailModel.getEstimatedDeliveryEndTime()));
			waitPickUpGoodsNotScannedDTO.setLoadingBillNo(tmsLoadingBillDetailModel.getLoadingBillNo());

			if (DataDictionaryConstant.SCAN_STATUS_LOADED.equals(tmsLoadingBillDetailModel.getScanStatus())) {
				scannedDTOS.add(waitPickUpGoodsNotScannedDTO);
			} else {
				notScannedDTOS.add(waitPickUpGoodsNotScannedDTO);
			}
		}
		loadingScanDTO.setScannedShipbillList(scannedDTOS);
		loadingScanDTO.setNoScannedShipbillList(notScannedDTOS);
		return loadingScanDTO;
	}

	/**
	 * 获取派车单扫描信息
	 *
	 * @param vo
	 */
	public LoadingScanDTO queryLoadingBillScanInfo(QueryTypeByShipbillVO vo) {
		UserEntity user = PlgFxUsrUtils.getUserEntity();
		ToolKits.isParamNull(user, "当前人员没有操作权限");
		LoadingScanDTO loadingScanDTO = new LoadingScanDTO();
		// 权限控制
		if (user.getUserType().equals(BussinessConstant.USER_TYPE_ZY)) {
			// 判断是否是部门权限
			if (user.getOwnedAllDataAuthFlag().equals(BussinessConstant.USER_DEPARTMENT_AUTH_Y)) {
				vo.setIsDept(StatusConstant.IS_DEPT_YES);
				vo.setDepts(user.getDepts().toArray(new String[] {}));
			} else {
				vo.setIsDept(StatusConstant.IS_DEPT_NO);
				// 设置部门权限
				vo.setDepts(user.getDepts().toArray(new String[] {}));
				// 设置数据权限
				vo.setConsignors(user.getConsignors().toArray(new Long[] {}));
				vo.setWsarehouses(user.getWarehouses().toArray(new Long[] {}));
				vo.setCustomers(user.getCustomers().toArray(new Long[] {}));
				vo.setSuppliers(user.getSuppliers().toArray(new Long[] {}));
			}
		} else if (user.getUserType().equals(BussinessConstant.USER_TYPE_CYS)) {
			vo.setCarrierId(Long.valueOf(user.getLoginUserCompanyInfo().getId()));
		} else {
			throw new PrologException("当前人员没有操作权限");
		}
		vo.setUserType(user.getUserType());
		vo.setEnterpriseId(user.getEnterpriseId());
		vo.setScanStatus(DataDictionaryConstant.SCAN_STATUS_LOADED);
		List<String> scannedLoadingBillIds = tmsLoadingBillHeaderMapper.getLoadingScanLoadingBill(vo);

		loadingScanDTO.setScannedLoadingBillDTOList(getScannedLoadingBill(scannedLoadingBillIds));
		return loadingScanDTO;
	}

	private List<LoadingScanByLoadbillDTO> getScannedLoadingBill(List<String> loadingBillIds) {
		List<LoadingScanByLoadbillDTO> scannedLoadingBillDTOList = Lists.newArrayList();
		if (ObjectUtil.isEmpty(loadingBillIds)) {
			return scannedLoadingBillDTOList;
		}
		List<SysRefdatadModel> dicData = convertorUtil.getDictionary(new String[] {
				DataDictionaryConstant.LOADING_BILL_STATUS
		});
		List<TmsLoadingBillHeaderModel> billHeaderModels = tmsLoadingBillHeaderMapper.findByIds(TmsLoadingBillHeaderModel.class,loadingBillIds.stream().toArray(),null);
		billHeaderModels.stream().forEach(h->{
			LoadingScanByLoadbillDTO loadingBillDTO = BeanUtil.copyProperties(h,LoadingScanByLoadbillDTO.class);
			loadingBillDTO.setStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.LOADING_BILL_STATUS, String.valueOf(loadingBillDTO.getStatus())));
			loadingBillDTO.setVehicleId(h.getVehicleId());
			scannedLoadingBillDTOList.add(loadingBillDTO);
		});
		return scannedLoadingBillDTOList;
	}

	/**
	 * 根据装车单查询运单明细
	 *
	 * @param loadingBillId
	 */
	public LoadingScanDTO queryShipbillDetailByLoadingBillData(String loadingBillId) {
		UserEntity user = PlgFxUsrUtils.getUserEntity();
		ToolKits.isParamNull(user, "当前人员没有操作权限");
		LoadingScanDTO loadingScanDTO = new LoadingScanDTO();

		// 数据字典翻译数据集合
		List<SysRefdatadModel> dicData = convertorUtil.getDictionary(new String[] {
				DataDictionaryConstant.PACK_TYPE,
				DataDictionaryConstant.CARGO_THERMOSPHERE
		});

		// 添加查询条件
		Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
		Restriction r1 = Restrictions.eq(TmsLoadingBillDetailModel::getLoadingBillId, loadingBillId);
		Restriction r2 = Restrictions.eq(TmsLoadingBillDetailModel::getLoadingBillNo, loadingBillId);
		Restriction r3 = Restrictions.or(r1, r2);
		Restriction r4 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
		Restriction r5 = Restrictions.eq(TmsLoadingBillDetailModel::getStatus, DataDictionaryConstant.SHIPBILL_STATUS_ZC_SCAN);
		criteria.setRestriction(Restrictions.and(r3, r4, r5));
		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteria);
		if (ToolKits.isEmpty(tmsLoadingBillDetailModels)) {
			throw new PrologException(StrUtil.format("派车单{}对应的派车单明细不存在",loadingBillId));
		}

		// 根据运单ID查询明细数据
		Criteria criteriaShipbillDetail = Criteria.forClass(TmsShipbillDetailModel.class);
		r1 = Restrictions.in("shipbillId", tmsLoadingBillDetailModels.stream().map(TmsLoadingBillDetailModel::getShipbillId).collect(Collectors.toList()));
		criteriaShipbillDetail.setRestriction(r1);
		List<TmsShipbillDetailModel> tmsShipbillDetailModels = tmsShipbillDetailMapper.findByCriteria(criteriaShipbillDetail);

		// 返回数据集
		List<DzxItemDetailDTO> noScannedShipbillDetailList = Lists.newArrayList();
		List<DzxItemDetailDTO> scannedShipbillDetailList = Lists.newArrayList();

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

			// 数据字典翻译
			dto.setPackTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.PACK_TYPE, String.valueOf(tmsShipbillDetailModel.getPackType())));
			dto.setCargoThermosphereName(ConvertorUtil.getName(dicData, DataDictionaryConstant.CARGO_THERMOSPHERE, String.valueOf(tmsShipbillDetailModel.getCargoThermosphere())));

			if (DataDictionaryConstant.SCAN_STATUS_LOADED.equals(tmsShipbillDetailModel.getScanStatus())) {
				scannedShipbillDetailList.add(dto);
			} else {
				noScannedShipbillDetailList.add(dto);
			}
		}
		loadingScanDTO.setScannedShipbillDetailList(scannedShipbillDetailList);
		loadingScanDTO.setNoScannedShipbillDetailList(noScannedShipbillDetailList);
		return loadingScanDTO;
	}



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

				BeanUtils.copyProperties(newShibillDetail, subTmsShipbillDetailModel);
				// 取商品资料
				ItemCheckDTO rsItemInfo = itemMap.get(Long.valueOf(subTmsShipbillDetailModel.getItemId()));
				if (ToolKits.isEmpty(rsItemInfo)) {
					ItemCheckVO itemCheckVO = new ItemCheckVO();
					itemCheckVO.setItemId(subTmsShipbillDetailModel.getItemId());
					RestMessage<ItemCheckDTO> restMessage3 = maindataTmsResource.getItem(itemCheckVO);
					if (!restMessage3.isSuccess()) {
						throw new RuntimeException("取商品资料信息失败:" + restMessage3.getMessage());
					}
					rsItemInfo = restMessage3.getData();
					itemMap.put(subTmsShipbillDetailModel.getItemId(), rsItemInfo);
				}

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

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

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

				tmsShipbillDetailMapper.save(subTmsShipbillDetailModel);

				if (ToolKits.isNotEmpty(subTmsShipbillDetailModel.getPcs())) {
					newGoodsTotalPcs = newGoodsTotalPcs.add(subTmsShipbillDetailModel.getPcs());
				}
				if (ToolKits.isNotEmpty(subTmsShipbillDetailModel.getVolume())) {
					newGoodsTotalVolume = newGoodsTotalVolume.add(subTmsShipbillDetailModel.getVolume());
				}
				if (ToolKits.isNotEmpty(subTmsShipbillDetailModel.getWeight())) {
					newGoodsTotalWeight = newGoodsTotalWeight.add(subTmsShipbillDetailModel.getWeight());
				}
				tmsShipbillDetailMapper.deleteById(newShibillDetail.getId(),TmsShipbillDetailModel.class);
			}
			// 作成运单
			TmsShipbillHeaderModel newHeaderModel = new TmsShipbillHeaderModel();
			TmsShipbillHeaderModel oldHeaderModel = tmsShipbillHeaderMapper.findById(addDetailModels.get(0).getShipbillId(), TmsShipbillHeaderModel.class);
			BeanUtils.copyProperties(oldHeaderModel, newHeaderModel);
			newHeaderModel.setShipbillId(newShipbillId);
			newHeaderModel.setShipbillNo(newShipbillId);
			// 总件数
			newHeaderModel.setTotalPcs(newGoodsTotalPcs);
			// 总体积
			newHeaderModel.setTotalVolume(newGoodsTotalVolume);
			// 总重量
			newHeaderModel.setTotalWeight(newGoodsTotalWeight);
			// 实际总件数
			newHeaderModel.setActualTotalPcs(newGoodsTotalPcs);
			// 实际总体积
			newHeaderModel.setActualTotalVolume(newGoodsTotalVolume);
			// 实际总重量
			newHeaderModel.setActualTotalWeight(newGoodsTotalWeight);
			newHeaderModel.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_REVIEW);
			newHeaderModel.setSplitOrderStatus(DataDictionaryConstant.SPLIT_ORDER_STATUS_UN);
			newHeaderModel.setSplitOrderType(DataDictionaryConstant.SPLIT_ORDER_TYPE_UN);
			newHeaderModel.setCarrierSplitOrderStatus(DataDictionaryConstant.CARRIER_SPLIT_ORDER_STATUS_UN);
			newHeaderModel.setCarrierSplitOrderType(DataDictionaryConstant.CARRIER_SPLIT_ORDER_TYPE_UN);
			newHeaderModel.setCreateperson(user.getNickname());
			newHeaderModel.setCreatetime(DateUtil.date());
			newHeaderModel.setShipbillType("N");
			newHeaderModel.setSignInStatus("N");
			newHeaderModel.setDriverReceiveStatus("N");

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

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

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

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

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

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

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

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

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

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

	public void saveTransportLog(String shipbillId, Date date, Date pickUpStartDt) {
		TmsShipbillTransLogModel logModel = new TmsShipbillTransLogModel();
		RestMessage<String> restMessage = maindataTmsResource.getCodeNumberByCode(SeriaNnumberConstant.TMS_SHIPBILL_TRANSPORT_LOG_ID, "L");
		if (!restMessage.isSuccess()) {
			throw new RuntimeException("生成运单记录ID失败");
		}
		String id = restMessage.getData();
		UserEntity user = PlgFxUsrUtils.getUserEntity();
		logModel.setId(id);
		logModel.setShipbillId(shipbillId);
		logModel.setShipbillNo(shipbillId);

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

		tmsShipbillTransportLogMapper.save(logModel);
	}

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

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

}
