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

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

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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.pojo.Page;
import com.prolog.framework.core.restriction.Criteria;
import com.prolog.framework.core.restriction.Order;
import com.prolog.framework.core.restriction.Restriction;
import com.prolog.framework.core.restriction.Restrictions;
import com.prolog.framework.dao.util.PageUtils;
import com.prolog.product.core.framework.entity.UserEntity;
import com.prolog.product.core.framework.util.PlgFxUsrUtils;
import com.prolog.rdc.tms.constant.BussinessConstant;
import com.prolog.rdc.tms.constant.DataDictionaryConstant;
import com.prolog.rdc.tms.constant.StatusConstant;
import com.prolog.rdc.tms.dao.mapper.TmsLoadingBillDetailMapper;
import com.prolog.rdc.tms.dao.mapper.TmsLoadingBillHeaderMapper;
import com.prolog.rdc.tms.dao.mapper.TmsShipbillDetailMapper;
import com.prolog.rdc.tms.dao.mapper.TmsShipbillHeaderMapper;
import com.prolog.rdc.tms.dao.mapper.TmsShipbillPackageMapper;
import com.prolog.rdc.tms.dao.mapper.TmsShipbillTransportLogMapper;
import com.prolog.rdc.tms.model.dto.DeliveryConfirmExportDTO;
import com.prolog.rdc.tms.model.dto.DeliveryConfirmGetShipbillDTO;
import com.prolog.rdc.tms.model.dto.DeliveryConfirmItemDetailDTO;
import com.prolog.rdc.tms.model.dto.DeliveryConfirmPackageDetailDTO;
import com.prolog.rdc.tms.model.dto.DeliveryConfirmPrintHeadDTO;
import com.prolog.rdc.tms.model.dto.DeliveryConfirmPrintTableDTO;
import com.prolog.rdc.tms.model.dto.DeliveryConfirmQueryByLoadbillDTO;
import com.prolog.rdc.tms.model.dto.DeviceByOneDTO;
import com.prolog.rdc.tms.model.dto.VehicleCheckDTO;
import com.prolog.rdc.tms.model.dto.basicConfigure.SignconfigPopDTO;
import com.prolog.rdc.tms.model.dto.message.SendMessageDTO;
import com.prolog.rdc.tms.model.entity.TmsLoadingBillDetailModel;
import com.prolog.rdc.tms.model.entity.TmsLoadingBillHeaderModel;
import com.prolog.rdc.tms.model.entity.TmsShipbillDetailModel;
import com.prolog.rdc.tms.model.entity.TmsShipbillHeaderModel;
import com.prolog.rdc.tms.model.entity.TmsShipbillPackageModel;
import com.prolog.rdc.tms.model.entity.TmsShipbillTransLogModel;
import com.prolog.rdc.tms.model.enums.MessageOrderTypeEnum;
import com.prolog.rdc.tms.model.enums.MessageTypeEnum;
import com.prolog.rdc.tms.model.vo.DeliveryConfirmAbnormalRegisterByShipbillVO;
import com.prolog.rdc.tms.model.vo.DeliveryConfirmAbnormalRegisterVO;
import com.prolog.rdc.tms.model.vo.DeliveryConfirmAdvancedQueryVO;
import com.prolog.rdc.tms.model.vo.DeliveryConfirmDeleteDetailVO;
import com.prolog.rdc.tms.model.vo.DeliveryConfirmExportAllVO;
import com.prolog.rdc.tms.model.vo.DeliveryConfirmExportPageVO;
import com.prolog.rdc.tms.model.vo.DeliveryConfirmFeedBackByShipbillVO;
import com.prolog.rdc.tms.model.vo.DeliveryConfirmFeedBackVO;
import com.prolog.rdc.tms.model.vo.DeliveryConfirmGetShipbillVO;
import com.prolog.rdc.tms.model.vo.DeliveryConfirmItemDetailVO;
import com.prolog.rdc.tms.model.vo.DeliveryConfirmPackageDetailVO;
import com.prolog.rdc.tms.model.vo.DeliveryConfirmQueryByLoadbillVO;
import com.prolog.rdc.tms.model.vo.DeliveryConfirmStartShipmentByShipbillVO;
import com.prolog.rdc.tms.model.vo.DeliveryConfirmStartShipmentVO;
import com.prolog.rdc.tms.model.vo.ShipbillNodeTrackingSaveNewVO;
import com.prolog.rdc.tms.model.vo.ShipbillNodeTrackingSaveVO;
import com.prolog.rdc.tms.model.vo.ShipbillOperateLogSaveNewVO;
import com.prolog.rdc.tms.model.vo.ShipbillOperateLogSaveVO;
import com.prolog.rdc.tms.model.vo.basicConfigure.SignconfigPopVO;
import com.prolog.rdc.tms.model.vo.fleetManagement.VehicleCheckVO;
import com.prolog.rdc.tms.rmi.feign.MaindataFeign;
import com.prolog.rdc.tms.service.DeliveryConfirmService;
import com.prolog.rdc.tms.service.ShipbillNodeTrackingService;
import com.prolog.rdc.tms.service.ShipbillOperateLogService;
import com.prolog.rdc.tms.util.MessageUtil;
import com.prolog.rdc.tms.util.PublicMethods;

import cn.hutool.core.date.DateUtil;

/**
 * 提货确认实现层
 *
 * Company: 湖北普罗格科技股份有限公司
 *
 * @author zhangsj
 * @since 2022/6/23 10:02
 */
@Service
public class DeliveryConfirmServiceImpl implements DeliveryConfirmService {
	@Autowired
	private TmsLoadingBillHeaderMapper tmsLoadingBillHeaderMapper;

	@Autowired
	private TmsLoadingBillDetailMapper tmsLoadingBillDetailMapper;

	@Autowired
	private TmsShipbillHeaderMapper tmsShipbillHeaderMapper;

	@Autowired
	private TmsShipbillDetailMapper tmsShipbillDetailMapper;

	@Autowired
	private TmsShipbillPackageMapper tmsShipbillPackageMapper;

	@Autowired
	private MaindataFeign maindataTmsResource;

	@Autowired
	private ShipbillOperateLogService shipbillOperateLogService;

	@Autowired
	private ShipbillNodeTrackingService shipbillNodeTrackingService;

	@Autowired
	private TmsShipbillTransportLogMapper tmsShipbillTransportLogMapper;

	/**
	 * 派车单查询
	 *
	 * @param deliveryConfirmQueryByLoadbillVO
	 * @return
	 */
	@SuppressWarnings("resource")
	@Override
	public Page<DeliveryConfirmQueryByLoadbillDTO> queryLoadbillPageData(DeliveryConfirmQueryByLoadbillVO deliveryConfirmQueryByLoadbillVO) {
		ToolKits.isParamNull(deliveryConfirmQueryByLoadbillVO, "汇总查询请求不为空");
		ToolKits.isParamNull(deliveryConfirmQueryByLoadbillVO.getPageNum(), "当前页码不为空");
		ToolKits.isParamNull(deliveryConfirmQueryByLoadbillVO.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.LOADING_BILL_STATUS, null, null, null);
		if (!restMessage1.isSuccess()) {
			throw new RuntimeException("已派车状态翻译失败!");
		} else {
			data1 = restMessage1.getData();
		}

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

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

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

		for (TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel : tmsLoadingBillHeaderModels) {
			DeliveryConfirmQueryByLoadbillDTO dto = new DeliveryConfirmQueryByLoadbillDTO();
			BeanUtils.copyProperties(tmsLoadingBillHeaderModel, dto);

			// 状态翻译
			dto.setStatusName(PublicMethods.change(data1, String.valueOf(dto.getStatus())));

			deliveryConfirmQueryByLoadbillDTOS.add(dto);
		}

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

	/**
	 * 派车单高级查询
	 *
	 * @param deliveryConfirmAdvancedQueryVO
	 * @return
	 */
	@Override
	public Page<DeliveryConfirmQueryByLoadbillDTO> advancedQueryLoadbillPageData(DeliveryConfirmAdvancedQueryVO deliveryConfirmAdvancedQueryVO) {
		ToolKits.isParamNull(deliveryConfirmAdvancedQueryVO, "汇总查询请求不为空");
		ToolKits.isParamNull(deliveryConfirmAdvancedQueryVO.getPageNum(), "当前页码不为空");
		ToolKits.isParamNull(deliveryConfirmAdvancedQueryVO.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.LOADING_BILL_STATUS, null, null, null);
		if (!restMessage1.isSuccess()) {
			throw new RuntimeException("已派车状态翻译失败!");
		} else {
			data1 = restMessage1.getData();
		}

		// 权限控制
		deliveryConfirmAdvancedQueryVO.setEnterpriseId(user.getEnterpriseId());
		deliveryConfirmAdvancedQueryVO.setDepts(user.getDepts().stream().toArray(String[]::new));
		deliveryConfirmAdvancedQueryVO.setCarrierType(DataDictionaryConstant.LINE_CARRIER_TYPE_SJ);
		deliveryConfirmAdvancedQueryVO.setLoadingBillType(DataDictionaryConstant.LOADING_BILL_TYPE_RK);

		// 判断调度类型
		if (user.getUserType().equals(BussinessConstant.USER_TYPE_ZY)) {
			deliveryConfirmAdvancedQueryVO.setScheduleType(DataDictionaryConstant.SCHEDULE_TYPE_ZY);
		} else {
			deliveryConfirmAdvancedQueryVO.setScheduleType(DataDictionaryConstant.SCHEDULE_TYPE_CYS);
		}

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

		PageUtils.startPage(deliveryConfirmAdvancedQueryVO.getPageNum(), deliveryConfirmAdvancedQueryVO.getPageSize());
		List<DeliveryConfirmQueryByLoadbillDTO> deliveryConfirmQueryByLoadbillDTOS = tmsLoadingBillHeaderMapper.deliveryConfirmAdvancedQuery(deliveryConfirmAdvancedQueryVO);

		for (DeliveryConfirmQueryByLoadbillDTO dto : deliveryConfirmQueryByLoadbillDTOS) {
			// 状态翻译
			dto.setStatusName(PublicMethods.change(data1, String.valueOf(dto.getStatus())));

		}
		return PageUtils.getPage(deliveryConfirmQueryByLoadbillDTOS);
	}

	/**
	 * 配载运单查询
	 *
	 * @param deliveryConfirmGetShipbillVO
	 * @return
	 */
	@SuppressWarnings("resource")
	@Override
	public Page<DeliveryConfirmGetShipbillDTO> getShipbillData(DeliveryConfirmGetShipbillVO deliveryConfirmGetShipbillVO) {
		ToolKits.isParamNull(deliveryConfirmGetShipbillVO.getPageNum(), "当前页码不为空");
		ToolKits.isParamNull(deliveryConfirmGetShipbillVO.getPageSize(), "每页条数不为空");
		ToolKits.isParamNull(deliveryConfirmGetShipbillVO.getLoadingBillId(), "派车单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(TmsLoadingBillDetailModel.class);
		Restriction r1 = Restrictions.eq("loadingBillId", deliveryConfirmGetShipbillVO.getLoadingBillId());
		criteria.setRestriction(r1);
		criteria.setOrder(Order.newInstance().asc(new String[] { "shippingOrder" }));

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

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

		for (TmsLoadingBillDetailModel model : tmsLoadingBillDetailModels) {

			DeliveryConfirmGetShipbillDTO deliveryConfirmGetShipbillDTO = new DeliveryConfirmGetShipbillDTO();
			BeanUtils.copyProperties(model, deliveryConfirmGetShipbillDTO);

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

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

			// 类型翻译
			deliveryConfirmGetShipbillDTO.setOrderTypeName(PublicMethods.change(data1, String.valueOf(model.getOrderType())));
			deliveryConfirmGetShipbillDTO.setOrderBusinessTypeName(PublicMethods.change(data2, String.valueOf(model.getOrderBusinessType())));
			deliveryConfirmGetShipbillDTO.setDeliveryMethodTypeName(PublicMethods.change(data3, String.valueOf(model.getDeliveryMethodType())));
			deliveryConfirmGetShipbillDTO.setTransportTypeName(PublicMethods.change(data4, String.valueOf(model.getTransportType())));
			deliveryConfirmGetShipbillDTO.setTemperatureRequirementName(PublicMethods.change(data5, String.valueOf(model.getTemperatureRequirement())));
			deliveryConfirmGetShipbillDTO.setShipperTypeName(PublicMethods.change(data6, String.valueOf(model.getShipperType())));
			deliveryConfirmGetShipbillDTO.setConsigneeTypeName(PublicMethods.change(data7, String.valueOf(model.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(deliveryConfirmGetShipbillDTO.getOrderTypeName()) ? deliveryConfirmGetShipbillDTO.getOrderTypeName() : "")) {
							deliveryConfirmGetShipbillDTO.setBackground(ToolKits.isEmpty(signconfigPopDTO.getBackground()) ? "" : signconfigPopDTO.getBackground());
							deliveryConfirmGetShipbillDTO.setColor(ToolKits.isEmpty(signconfigPopDTO.getColor()) ? "" : signconfigPopDTO.getColor());

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

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

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

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

							deliveryConfirmGetShipbillDTO.setSignConfigId(signconfigPopDTO.getId());

							break Signconfig;
						}
					}
					break;
				}
			}

			list.add(deliveryConfirmGetShipbillDTO);
		}

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

	/**
	 * 配载商品查询
	 *
	 * @param deliveryConfirmItemDetailVO
	 * @return
	 */
	@SuppressWarnings("resource")
	@Override
	public Page<DeliveryConfirmItemDetailDTO> itemDetailData(DeliveryConfirmItemDetailVO deliveryConfirmItemDetailVO) {
		ToolKits.isParamNull(deliveryConfirmItemDetailVO.getLoadingBillId(), "派车单ID不为空");
		ToolKits.isParamNull(deliveryConfirmItemDetailVO.getPageNum(), "当前页码不为空");
		ToolKits.isParamNull(deliveryConfirmItemDetailVO.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();
		}

		// 查询派车单明细
		Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
		Restriction r1 = Restrictions.eq("loadingBillId", deliveryConfirmItemDetailVO.getLoadingBillId());
		criteria.setRestriction(r1);

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

		// 根据运单ID查询明细数据
		criteria = Criteria.forClass(TmsShipbillDetailModel.class);
		r1 = Restrictions.in("shipbillId", tmsLoadingBillDetailModels.stream().map(TmsLoadingBillDetailModel::getShipbillId).collect(Collectors.toList()).toArray());

		criteria.setRestriction(r1);

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

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

		for (TmsShipbillDetailModel tmsShipbillDetailModel : tmsShipbillDetailModels) {
			DeliveryConfirmItemDetailDTO dto = new DeliveryConfirmItemDetailDTO();
			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<DeliveryConfirmItemDetailDTO> 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 deliveryConfirmPackageDetailVO
	 * @return
	 */
	@SuppressWarnings("resource")
	@Override
	public Page<DeliveryConfirmPackageDetailDTO> packageDetailData(DeliveryConfirmPackageDetailVO deliveryConfirmPackageDetailVO) {
		ToolKits.isParamNull(deliveryConfirmPackageDetailVO.getLoadingBillId(), "派车单ID不为空");
		ToolKits.isParamNull(deliveryConfirmPackageDetailVO.getPageNum(), "当前页码不为空");
		ToolKits.isParamNull(deliveryConfirmPackageDetailVO.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();
		}

		// 查询派车单明细
		Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
		Restriction r1 = Restrictions.eq("loadingBillId", deliveryConfirmPackageDetailVO.getLoadingBillId());
		criteria.setRestriction(r1);

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

		// 根据运单ID查询明细数据
		criteria = Criteria.forClass(TmsShipbillPackageModel.class);
		r1 = Restrictions.in("shipbillId", tmsLoadingBillDetailModels.stream().map(TmsLoadingBillDetailModel::getShipbillId).collect(Collectors.toList()).toArray());
		criteria.setRestriction(r1);

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

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

		for (TmsShipbillPackageModel tmsShipbillPackageModel : tmsShipbillPackageModels) {
			DeliveryConfirmPackageDetailDTO dto = new DeliveryConfirmPackageDetailDTO();
			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<DeliveryConfirmPackageDetailDTO> 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 deliveryConfirmStartShipmentByShipbillVO
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void shipbillStartShipmentData(DeliveryConfirmStartShipmentByShipbillVO deliveryConfirmStartShipmentByShipbillVO) {
		ToolKits.isParamNull(deliveryConfirmStartShipmentByShipbillVO.getShipbillIds(), "运单ID不能为空");
		ToolKits.isParamNull(deliveryConfirmStartShipmentByShipbillVO.getDepartureTime(), "启运时间不能为空");

		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();
		// 货物图片
		String departurePhoto = "";

		StringBuffer nodeEvent = new StringBuffer();
		nodeEvent.append("启运登记 备注:");
		nodeEvent.append(deliveryConfirmStartShipmentByShipbillVO.getDepartureMemo());

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

		List<TmsShipbillHeaderModel> tmsShipbillHeaderModels = tmsShipbillHeaderMapperByIds.stream().filter(o -> StatusConstant.WHETHER_YES.equals(o.getShipperPickUpSign())).collect(Collectors.toList());
		if (ToolKits.isNotEmpty(tmsShipbillHeaderModels)) {
			ToolKits.isParamNull(deliveryConfirmStartShipmentByShipbillVO.getDepartureSignTime(), "签到时间不能为空");
		}
		List<TmsShipbillHeaderModel> tmsShipbillHeaderModels2 = tmsShipbillHeaderMapperByIds.stream().filter(o -> StatusConstant.WHETHER_YES.equals(o.getShipperPickUpPicture())).collect(Collectors.toList());
		if (ToolKits.isNotEmpty(tmsShipbillHeaderModels2)) {
			ToolKits.isParamNull(deliveryConfirmStartShipmentByShipbillVO.getDeparturePhoto(), "货物图片不能为空");
			departurePhoto = deliveryConfirmStartShipmentByShipbillVO.getDeparturePhoto();
		}

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

		Map<String, Object> mapTransportLogUpdate = Maps.newHashMap();
		mapTransportLogUpdate.put("updateperson", user.getNickname());
		mapTransportLogUpdate.put("updatetime", date);
		// 启运时间
		mapTransportLogUpdate.put("departureTime", deliveryConfirmStartShipmentByShipbillVO.getDepartureTime());
		// 签到时间
		if (ToolKits.isNotEmpty(deliveryConfirmStartShipmentByShipbillVO.getDepartureSignTime())) {
			mapTransportLogUpdate.put("departureSignTime", deliveryConfirmStartShipmentByShipbillVO.getDepartureSignTime());
		}
		// 备注
		if (ToolKits.isNotEmpty(deliveryConfirmStartShipmentByShipbillVO.getDepartureMemo())) {
			mapTransportLogUpdate.put("departureMemo", deliveryConfirmStartShipmentByShipbillVO.getDepartureMemo());
		}

		for (TmsShipbillHeaderModel tmsShipbillHeaderModel : tmsShipbillHeaderMapperByIds) {

			// 修改运单
			tmsShipbillHeaderModel.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_QY);
			tmsShipbillHeaderModel.setUpdateperson(user.getNickname());
			tmsShipbillHeaderModel.setUpdatetime(date);

			tmsShipbillHeaderMapper.update(tmsShipbillHeaderModel);

			Restriction eq = Restrictions.eq("shipbillId", tmsShipbillHeaderModel.getShipbillId());
			criteriaTransport.setRestriction(eq);
			// 更新订单运输记录表
			tmsShipbillTransportLogMapper.updateMapByCriteria(mapTransportLogUpdate, criteriaTransport);

			// 签到时间是否为空
			boolean departureSignTime = false;

			ShipbillNodeTrackingSaveNewVO shipbillNodeTrackingSaveNewVO = new ShipbillNodeTrackingSaveNewVO();
			ShipbillOperateLogSaveNewVO shipbillOperateLogSaveNewVO = new ShipbillOperateLogSaveNewVO();
			if (ToolKits.isNotEmpty(deliveryConfirmStartShipmentByShipbillVO.getDepartureSignTime())) {
				// 运单节点保存
				shipbillNodeTrackingSaveNewVO.setNodeDate(date);
				shipbillNodeTrackingSaveNewVO.setShipbillId(tmsShipbillHeaderModel.getShipbillId());
				shipbillNodeTrackingSaveNewVO.setShipbillNo(tmsShipbillHeaderModel.getShipbillId());
				shipbillNodeTrackingSaveNewVO.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_QY);
				shipbillNodeTrackingSaveNewVO.setNodeEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_QYQD);
				shipbillNodeTrackingSaveNewVO.setUserId(user.getUserid());
				shipbillNodeTrackingSaveNewVO.setUserName(user.getNickname());
				shipbillNodeTrackingSaveNewVO.setEnterpriseId(user.getEnterpriseId());
				shipbillNodeTrackingSaveNewVO.setEnterpriseName(user.getEnterpriseName());
				shipbillNodeTrackingService.addShipbillNodeTrackingNewData(shipbillNodeTrackingSaveNewVO);

				// 运单日志保存
				shipbillOperateLogSaveNewVO.setShipbillId(tmsShipbillHeaderModel.getShipbillId());
				shipbillOperateLogSaveNewVO.setShipbillNo(tmsShipbillHeaderModel.getShipbillId());
				shipbillOperateLogSaveNewVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_QYQD);
				shipbillOperateLogSaveNewVO.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_ZX_CONFIRM);
				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);

				departureSignTime = true;
			}

			// 运单节点保存
			shipbillNodeTrackingSaveNewVO.setNodeDate(date);
			shipbillNodeTrackingSaveNewVO.setShipbillId(tmsShipbillHeaderModel.getShipbillId());
			shipbillNodeTrackingSaveNewVO.setShipbillNo(tmsShipbillHeaderModel.getShipbillId());
			shipbillNodeTrackingSaveNewVO.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_QY);
			shipbillNodeTrackingSaveNewVO.setNodeEvent(nodeEvent.toString());
			shipbillNodeTrackingSaveNewVO.setUserId(user.getUserid());
			shipbillNodeTrackingSaveNewVO.setUserName(user.getNickname());
			shipbillNodeTrackingSaveNewVO.setEnterpriseId(user.getEnterpriseId());
			shipbillNodeTrackingSaveNewVO.setEnterpriseName(user.getEnterpriseName());
			shipbillNodeTrackingSaveNewVO.setPicUrl(departurePhoto);
			shipbillNodeTrackingService.addShipbillNodeTrackingNewData(shipbillNodeTrackingSaveNewVO);

			// 运单日志保存
			shipbillOperateLogSaveNewVO.setShipbillId(tmsShipbillHeaderModel.getShipbillId());
			shipbillOperateLogSaveNewVO.setShipbillNo(tmsShipbillHeaderModel.getShipbillId());
			shipbillOperateLogSaveNewVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_QY);
			shipbillOperateLogSaveNewVO.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_ZX_CONFIRM);
			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);

			// 父运单的同步启运
			String fatherShipbillId = tmsShipbillHeaderModel.getShipbillId();
			while (ToolKits.isNotEmpty(fatherShipbillId)) {
				fatherShipbillId = fatherStartShipment(fatherShipbillId, date, user, departureSignTime, shipbillNodeTrackingSaveNewVO, mapTransportLogUpdate);
				departureSignTime = false;
			}
			MessageUtil.addMessage(new SendMessageDTO(MessageOrderTypeEnum.SHIP_NO.getCode(), MessageTypeEnum.START_SHIP.getCode(), Lists.newArrayList(tmsShipbillHeaderModel.getShipbillId())));
		}

		// 修改派车单明细
		Criteria criteriaDetail = Criteria.forClass(TmsLoadingBillDetailModel.class);
		Restriction r1 = Restrictions.in("shipbillId", deliveryConfirmStartShipmentByShipbillVO.getShipbillIds().toArray());
		criteriaDetail.setRestriction(r1);

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

		tmsLoadingBillDetailMapper.updateMapByCriteria(mapDetailUpdate, criteriaDetail);
	}

	/**
	 * 父运单启运确认
	 *
	 * @param shipbillId
	 * @param date
	 * @param user
	 * @return
	 */
	public String fatherStartShipment(String shipbillId, Date date, UserEntity user, boolean whether, ShipbillNodeTrackingSaveNewVO shipbillNodeTrackingSaveNewVO, Map<String, Object> mapTransportLogUpdate) {
		// 查询派车单明细
		Criteria criteriaDetail = Criteria.forClass(TmsLoadingBillDetailModel.class);
		Restriction rDetail = Restrictions.eq("shipbillId", shipbillId);
		criteriaDetail.setRestriction(rDetail);
		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteriaDetail);
		ToolKits.isParamNull(tmsLoadingBillDetailModels, "查询派车单明细[运单:" + shipbillId + "]为空");

		TmsLoadingBillDetailModel tmsLoadingBillDetailModel = tmsLoadingBillDetailModels.get(0);

		// 查询派车单
		TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel = tmsLoadingBillHeaderMapper.findById(tmsLoadingBillDetailModel.getLoadingBillId(), TmsLoadingBillHeaderModel.class);

		// 判断派车单是否已启运
		if (tmsLoadingBillHeaderModel.getStatus() != DataDictionaryConstant.LOADING_BILL_STATUS_QY) {
			tmsLoadingBillHeaderModel.setStatus(DataDictionaryConstant.LOADING_BILL_STATUS_QY);
			tmsLoadingBillHeaderModel.setUpdateperson(user.getNickname());
			tmsLoadingBillHeaderModel.setUpdatetime(date);

			// 修改派车单
			tmsLoadingBillHeaderMapper.update(tmsLoadingBillHeaderModel);
		}
		// 查询运单
		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() != DataDictionaryConstant.SHIPBILL_STATUS_QY) {
				// 修改父级运单状态
				fatherShipbillHeaderModel.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_QY);
				fatherShipbillHeaderModel.setUpdatetime(date);
				fatherShipbillHeaderModel.setUpdateperson(user.getNickname());
				tmsShipbillHeaderMapper.update(fatherShipbillHeaderModel);

				// 修改父级运单运输记录表
				Criteria criteriaTransport = Criteria.forClass(TmsShipbillTransLogModel.class);
				Restriction r1 = Restrictions.eq("shipbillId", fatherShipbillHeaderModel.getShipbillId());
				criteriaTransport.setRestriction(r1);
				// 更新订单运输记录表
				tmsShipbillTransportLogMapper.updateMapByCriteria(mapTransportLogUpdate, criteriaTransport);

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

				// 判断第一个子单是否有签到时间
				if (whether) {
					// 运单节点保存
					// 运单节点信息
					ShipbillNodeTrackingSaveNewVO nodeTrackingSaveNewVO = new ShipbillNodeTrackingSaveNewVO();
					nodeTrackingSaveNewVO.setNodeDate(date);
					nodeTrackingSaveNewVO.setShipbillId(fatherShipbillHeaderModel.getShipbillId());
					nodeTrackingSaveNewVO.setShipbillNo(fatherShipbillHeaderModel.getShipbillId());
					nodeTrackingSaveNewVO.setUserId(user.getUserid());
					nodeTrackingSaveNewVO.setUserName(user.getNickname());
					nodeTrackingSaveNewVO.setEnterpriseId(user.getEnterpriseId());
					nodeTrackingSaveNewVO.setEnterpriseName(user.getEnterpriseName());
					nodeTrackingSaveNewVO.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_QY);
					nodeTrackingSaveNewVO.setNodeEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_QYQD);
					shipbillNodeTrackingService.addShipbillNodeTrackingNewData(nodeTrackingSaveNewVO);

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

				// 运单节点保存
				shipbillNodeTrackingSaveNewVO.setShipbillId(fatherShipbillHeaderModel.getShipbillId());
				shipbillNodeTrackingSaveNewVO.setShipbillNo(fatherShipbillHeaderModel.getShipbillId());
				shipbillNodeTrackingService.addShipbillNodeTrackingNewData(shipbillNodeTrackingSaveNewVO);

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

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

	/**
	 * 运单客服反馈
	 *
	 * @param deliveryConfirmFeedBackByShipbillVO
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void shipbillFeedBackData(DeliveryConfirmFeedBackByShipbillVO deliveryConfirmFeedBackByShipbillVO) {
		ToolKits.isParamNull(deliveryConfirmFeedBackByShipbillVO.getShipbillIds(), "运单ID不能为空");
		ToolKits.isParamNull(deliveryConfirmFeedBackByShipbillVO.getFeedbackContent(), "反馈内容不能为空");
		ToolKits.isParamNull(deliveryConfirmFeedBackByShipbillVO.getFeedbackDate(), "反馈日期不能为空");

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

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

		// 节点内容
		StringBuffer nodeEvent = new StringBuffer();
		nodeEvent.append("客服反馈 反馈内容:");
		nodeEvent.append(deliveryConfirmFeedBackByShipbillVO.getFeedbackContent());
		nodeEvent.append(" 实时地点:");
		nodeEvent.append(deliveryConfirmFeedBackByShipbillVO.getAddress());

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

		for (TmsShipbillHeaderModel tmsShipbillHeaderModel : tmsShipbillHeaderModelList) {

			// 运单节点信息
			ShipbillNodeTrackingSaveNewVO shipbillNodeTrackingSaveNewVO = new ShipbillNodeTrackingSaveNewVO();
			shipbillNodeTrackingSaveNewVO.setNodeDate(date);
			shipbillNodeTrackingSaveNewVO.setShipbillId(tmsShipbillHeaderModel.getShipbillId());
			shipbillNodeTrackingSaveNewVO.setShipbillNo(tmsShipbillHeaderModel.getShipbillId());
			shipbillNodeTrackingSaveNewVO.setUserId(user.getUserid());
			shipbillNodeTrackingSaveNewVO.setUserName(user.getNickname());
			shipbillNodeTrackingSaveNewVO.setEnterpriseId(user.getEnterpriseId());
			shipbillNodeTrackingSaveNewVO.setEnterpriseName(user.getEnterpriseName());
			shipbillNodeTrackingSaveNewVO.setStatus(tmsShipbillHeaderModel.getStatus());
			shipbillNodeTrackingSaveNewVO.setNodeEvent(nodeEvent.toString());
			shipbillNodeTrackingService.addShipbillNodeTrackingNewData(shipbillNodeTrackingSaveNewVO);

			// 运单日志信息
			ShipbillOperateLogSaveNewVO shipbillOperateLogSaveNewVO = new ShipbillOperateLogSaveNewVO();
			shipbillOperateLogSaveNewVO.setShipbillId(tmsShipbillHeaderModel.getShipbillId());
			shipbillOperateLogSaveNewVO.setShipbillNo(tmsShipbillHeaderModel.getShipbillId());
			shipbillOperateLogSaveNewVO.setOperateDate(date);
			shipbillOperateLogSaveNewVO.setEnterpriseId(user.getEnterpriseId());
			shipbillOperateLogSaveNewVO.setEnterpriseName(user.getEnterpriseName());
			shipbillOperateLogSaveNewVO.setUserId(user.getUserid());
			shipbillOperateLogSaveNewVO.setUserName(user.getNickname());
			shipbillOperateLogSaveNewVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_KFFK);
			shipbillOperateLogSaveNewVO.setOldStatus(tmsShipbillHeaderModel.getStatus());
			shipbillOperateLogSaveNewVO.setNewStatus(tmsShipbillHeaderModel.getStatus());
			shipbillOperateLogService.addShipbillOperateLogNewData(shipbillOperateLogSaveNewVO);

			// 父运单的客服反馈
			String fatherShipbillId = tmsShipbillHeaderModel.getShipbillId();
			while (ToolKits.isNotEmpty(fatherShipbillId)) {
				fatherShipbillId = fatherFeedBack(fatherShipbillId, date, user, shipbillNodeTrackingSaveNewVO);
			}
		}

	}

	/**
	 * 父级运单客服反馈
	 * 
	 * @param shipbillId
	 * @param date
	 * @param user
	 * @return
	 */
	private String fatherFeedBack(String shipbillId, Date date, UserEntity user, ShipbillNodeTrackingSaveNewVO shipbillNodeTrackingSaveNewVO) {
		// 查询运单
		TmsShipbillHeaderModel tmsShipbillHeaderModel = tmsShipbillHeaderMapper.findById(shipbillId, TmsShipbillHeaderModel.class);

		// 判断是否为原始单号
		if (ToolKits.isNotEmpty(tmsShipbillHeaderModel.getFatherShipbillId()) && !tmsShipbillHeaderModel.getFatherShipbillId().equals(shipbillId)) {
			// 查找父级单号
			TmsShipbillHeaderModel fatherShipbillHeaderModel = tmsShipbillHeaderMapper.findById(tmsShipbillHeaderModel.getFatherShipbillId(), TmsShipbillHeaderModel.class);
			// 运单节点信息
			shipbillNodeTrackingSaveNewVO.setShipbillId(fatherShipbillHeaderModel.getShipbillId());
			shipbillNodeTrackingSaveNewVO.setShipbillNo(fatherShipbillHeaderModel.getShipbillId());
			shipbillNodeTrackingSaveNewVO.setStatus(fatherShipbillHeaderModel.getStatus());
			shipbillNodeTrackingService.addShipbillNodeTrackingNewData(shipbillNodeTrackingSaveNewVO);

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

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

	/**
	 * 运单异常登记
	 *
	 * @param deliveryConfirmAbnormalRegisterByShipbillVO
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void shipbillAbnormalRegisterData(DeliveryConfirmAbnormalRegisterByShipbillVO deliveryConfirmAbnormalRegisterByShipbillVO) {
		ToolKits.isParamNull(deliveryConfirmAbnormalRegisterByShipbillVO.getShipbillIds(), "运单ID不能为空");
		ToolKits.isParamNull(deliveryConfirmAbnormalRegisterByShipbillVO.getAbnormalTime(), "异常发生时间不能为空");
		ToolKits.isParamNull(deliveryConfirmAbnormalRegisterByShipbillVO.getAbnormalType(), "异常类型不能为空");
		ToolKits.isParamNull(deliveryConfirmAbnormalRegisterByShipbillVO.getAbnormalEvent(), "异常事件不能为空");

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

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

		// 异常类型
		RestMessage<List<Map<String, Object>>> restMessage1 = maindataTmsResource.getDropDownById(DataDictionaryConstant.ABNORMAL_TYPE, null, null, null);
		if (!restMessage1.isSuccess()) {
			throw new RuntimeException("已派车状态翻译失败!");
		} else {
			data1 = restMessage1.getData();
		}

		// 异常事件
		RestMessage<List<Map<String, Object>>> restMessage2 = maindataTmsResource.getDropDownById(DataDictionaryConstant.ABNORMAL_EVENT, null, null, null);
		if (!restMessage2.isSuccess()) {
			throw new RuntimeException("已派车状态翻译失败!");
		} else {
			data2 = restMessage2.getData();
		}

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

		// 节点内容
		StringBuffer nodeEvent = new StringBuffer();
		nodeEvent.append("异常登记,异常类型:");
		nodeEvent.append(PublicMethods.change(data1, String.valueOf(deliveryConfirmAbnormalRegisterByShipbillVO.getAbnormalType())));
		nodeEvent.append(",异常事件:");
		nodeEvent.append(PublicMethods.change(data2, String.valueOf(deliveryConfirmAbnormalRegisterByShipbillVO.getAbnormalEvent())));
		if (ToolKits.isNotEmpty(deliveryConfirmAbnormalRegisterByShipbillVO.getAbnormalContent())) {
			nodeEvent.append(",异常内容为:");
			nodeEvent.append(deliveryConfirmAbnormalRegisterByShipbillVO.getAbnormalContent());
		}

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

		for (TmsShipbillHeaderModel tmsShipbillHeaderModel : tmsShipbillHeaderModelList) {

			// 运单节点信息
			ShipbillNodeTrackingSaveNewVO shipbillNodeTrackingSaveNewVO = new ShipbillNodeTrackingSaveNewVO();
			shipbillNodeTrackingSaveNewVO.setNodeDate(deliveryConfirmAbnormalRegisterByShipbillVO.getAbnormalTime());
			shipbillNodeTrackingSaveNewVO.setShipbillId(tmsShipbillHeaderModel.getShipbillId());
			shipbillNodeTrackingSaveNewVO.setShipbillNo(tmsShipbillHeaderModel.getShipbillId());
			shipbillNodeTrackingSaveNewVO.setUserId(user.getUserid());
			shipbillNodeTrackingSaveNewVO.setUserName(user.getNickname());
			shipbillNodeTrackingSaveNewVO.setEnterpriseId(user.getEnterpriseId());
			shipbillNodeTrackingSaveNewVO.setEnterpriseName(user.getEnterpriseName());
			shipbillNodeTrackingSaveNewVO.setStatus(tmsShipbillHeaderModel.getStatus());
			shipbillNodeTrackingSaveNewVO.setNodeEvent(nodeEvent.toString());
			shipbillNodeTrackingSaveNewVO.setPicUrl(deliveryConfirmAbnormalRegisterByShipbillVO.getAbnormalPhoto());
			shipbillNodeTrackingService.addShipbillNodeTrackingNewData(shipbillNodeTrackingSaveNewVO);

			// 运单日志信息
			ShipbillOperateLogSaveNewVO shipbillOperateLogSaveNewVO = new ShipbillOperateLogSaveNewVO();
			shipbillOperateLogSaveNewVO.setShipbillId(tmsShipbillHeaderModel.getShipbillId());
			shipbillOperateLogSaveNewVO.setShipbillNo(tmsShipbillHeaderModel.getShipbillId());
			shipbillOperateLogSaveNewVO.setOperateDate(date);
			shipbillOperateLogSaveNewVO.setEnterpriseId(user.getEnterpriseId());
			shipbillOperateLogSaveNewVO.setEnterpriseName(user.getEnterpriseName());
			shipbillOperateLogSaveNewVO.setUserId(user.getUserid());
			shipbillOperateLogSaveNewVO.setUserName(user.getNickname());
			shipbillOperateLogSaveNewVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_YCDJ);
			shipbillOperateLogSaveNewVO.setOldStatus(tmsShipbillHeaderModel.getStatus());
			shipbillOperateLogSaveNewVO.setNewStatus(tmsShipbillHeaderModel.getStatus());
			shipbillOperateLogService.addShipbillOperateLogNewData(shipbillOperateLogSaveNewVO);

			// 父运单的同步送达
			String fatherShipbillId = tmsShipbillHeaderModel.getShipbillId();
			while (ToolKits.isNotEmpty(fatherShipbillId)) {
				fatherShipbillId = fatherAbnormalRegister(fatherShipbillId, date, user, shipbillNodeTrackingSaveNewVO);
			}
		}
	}

	/**
	 * 父级运单异常登记
	 *
	 * @param shipbillId
	 * @param date
	 * @param user
	 * @param shipbillNodeTrackingSaveNewVO
	 * @return
	 */
	private String fatherAbnormalRegister(String shipbillId, Date date, UserEntity user, ShipbillNodeTrackingSaveNewVO shipbillNodeTrackingSaveNewVO) {
		// 查询运单
		TmsShipbillHeaderModel tmsShipbillHeaderModel = tmsShipbillHeaderMapper.findById(shipbillId, TmsShipbillHeaderModel.class);

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

			// 运单节点信息
			shipbillNodeTrackingSaveNewVO.setShipbillId(fatherShipbillHeaderModel.getShipbillId());
			shipbillNodeTrackingSaveNewVO.setShipbillNo(fatherShipbillHeaderModel.getShipbillId());
			shipbillNodeTrackingSaveNewVO.setStatus(fatherShipbillHeaderModel.getStatus());
			shipbillNodeTrackingService.addShipbillNodeTrackingNewData(shipbillNodeTrackingSaveNewVO);

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

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

	/**
	 * 派车单启运登记
	 *
	 * @param deliveryConfirmStartShipmentVO
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void startShipmentData(DeliveryConfirmStartShipmentVO deliveryConfirmStartShipmentVO) {
		ToolKits.isParamNull(deliveryConfirmStartShipmentVO.getLoadbillIds(), "派车单ID不能为空");
		ToolKits.isParamNull(deliveryConfirmStartShipmentVO.getDepartureTime(), "启运时间不能为空");

		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();
		// 货物图片
		String departurePhoto = "";

		StringBuffer nodeEvent = new StringBuffer();
		nodeEvent.append("启运登记 备注:");
		nodeEvent.append(deliveryConfirmStartShipmentVO.getDepartureMemo());

		// 查询派车单明细
		Criteria criteriaDetail = Criteria.forClass(TmsLoadingBillDetailModel.class);
		Restriction r1 = Restrictions.in("loadingBillId", deliveryConfirmStartShipmentVO.getLoadbillIds().toArray());
		criteriaDetail.setRestriction(r1);

		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModelList = tmsLoadingBillDetailMapper.findByCriteria(criteriaDetail);
		ToolKits.isParamNull(tmsLoadingBillDetailModelList, "派车单有误,未查询到对应的运单数据");

		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels = tmsLoadingBillDetailModelList.stream().filter(o -> StatusConstant.WHETHER_YES.equals(o.getShipperPickUpSign())).collect(Collectors.toList());
		if (ToolKits.isNotEmpty(tmsLoadingBillDetailModels)) {
			ToolKits.isParamNull(deliveryConfirmStartShipmentVO.getDepartureSignTime(), "签到时间不能为空");
		}
		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels2 = tmsLoadingBillDetailModelList.stream().filter(o -> StatusConstant.WHETHER_YES.equals(o.getShipperPickUpPicture())).collect(Collectors.toList());
		if (ToolKits.isNotEmpty(tmsLoadingBillDetailModels2)) {
			ToolKits.isParamNull(deliveryConfirmStartShipmentVO.getDeparturePhoto(), "货物图片不能为空");
			departurePhoto = deliveryConfirmStartShipmentVO.getDeparturePhoto();
		}

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

		Map<String, Object> mapTransportLogUpdate = Maps.newHashMap();
		mapTransportLogUpdate.put("updateperson", user.getNickname());
		mapTransportLogUpdate.put("updatetime", date);
		// 启运时间
		mapTransportLogUpdate.put("departureTime", deliveryConfirmStartShipmentVO.getDepartureTime());
		// 签到时间
		if (ToolKits.isNotEmpty(deliveryConfirmStartShipmentVO.getDepartureSignTime())) {
			mapTransportLogUpdate.put("departureSignTime", deliveryConfirmStartShipmentVO.getDepartureSignTime());
		}
		// 备注
		if (ToolKits.isNotEmpty(deliveryConfirmStartShipmentVO.getDepartureMemo())) {
			mapTransportLogUpdate.put("departureMemo", deliveryConfirmStartShipmentVO.getDepartureMemo());
		}

		for (TmsLoadingBillDetailModel tmsLoadingBillDetailModel : tmsLoadingBillDetailModelList) {

			Restriction eq = Restrictions.eq("shipbillId", tmsLoadingBillDetailModel.getShipbillId());
			criteriaTransport.setRestriction(eq);
			// 更新订单运输记录表
			tmsShipbillTransportLogMapper.updateMapByCriteria(mapTransportLogUpdate, criteriaTransport);

			// 签到时间是否为空
			boolean departureSignTime = false;

			ShipbillNodeTrackingSaveNewVO shipbillNodeTrackingSaveNewVO = new ShipbillNodeTrackingSaveNewVO();
			ShipbillOperateLogSaveNewVO shipbillOperateLogSaveNewVO = new ShipbillOperateLogSaveNewVO();
			if (ToolKits.isNotEmpty(deliveryConfirmStartShipmentVO.getDepartureSignTime())) {
				// 运单节点保存
				shipbillNodeTrackingSaveNewVO.setNodeDate(date);
				shipbillNodeTrackingSaveNewVO.setShipbillId(tmsLoadingBillDetailModel.getShipbillId());
				shipbillNodeTrackingSaveNewVO.setShipbillNo(tmsLoadingBillDetailModel.getShipbillId());
				shipbillNodeTrackingSaveNewVO.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_QY);
				shipbillNodeTrackingSaveNewVO.setNodeEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_QYQD);
				shipbillNodeTrackingSaveNewVO.setUserId(user.getUserid());
				shipbillNodeTrackingSaveNewVO.setUserName(user.getNickname());
				shipbillNodeTrackingSaveNewVO.setEnterpriseId(user.getEnterpriseId());
				shipbillNodeTrackingSaveNewVO.setEnterpriseName(user.getEnterpriseName());
				shipbillNodeTrackingService.addShipbillNodeTrackingNewData(shipbillNodeTrackingSaveNewVO);

				// 运单日志保存
				shipbillOperateLogSaveNewVO.setShipbillId(tmsLoadingBillDetailModel.getShipbillId());
				shipbillOperateLogSaveNewVO.setShipbillNo(tmsLoadingBillDetailModel.getShipbillId());
				shipbillOperateLogSaveNewVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_QYQD);
				shipbillOperateLogSaveNewVO.setOldStatus(tmsLoadingBillDetailModel.getStatus());
				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);

				departureSignTime = true;
			}

			// 运单节点保存
			shipbillNodeTrackingSaveNewVO.setNodeDate(date);
			shipbillNodeTrackingSaveNewVO.setShipbillId(tmsLoadingBillDetailModel.getShipbillId());
			shipbillNodeTrackingSaveNewVO.setShipbillNo(tmsLoadingBillDetailModel.getShipbillId());
			shipbillNodeTrackingSaveNewVO.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_QY);
			shipbillNodeTrackingSaveNewVO.setNodeEvent(nodeEvent.toString());
			shipbillNodeTrackingSaveNewVO.setUserId(user.getUserid());
			shipbillNodeTrackingSaveNewVO.setUserName(user.getNickname());
			shipbillNodeTrackingSaveNewVO.setEnterpriseId(user.getEnterpriseId());
			shipbillNodeTrackingSaveNewVO.setEnterpriseName(user.getEnterpriseName());
			shipbillNodeTrackingSaveNewVO.setPicUrl(departurePhoto);
			shipbillNodeTrackingService.addShipbillNodeTrackingNewData(shipbillNodeTrackingSaveNewVO);

			// 运单日志保存
			shipbillOperateLogSaveNewVO.setShipbillId(tmsLoadingBillDetailModel.getShipbillId());
			shipbillOperateLogSaveNewVO.setShipbillNo(tmsLoadingBillDetailModel.getShipbillId());
			shipbillOperateLogSaveNewVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_QY);
			shipbillOperateLogSaveNewVO.setOldStatus(tmsLoadingBillDetailModel.getStatus());
			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);

			// 修改派车单明细
			tmsLoadingBillDetailModel.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_QY);
			tmsLoadingBillDetailModel.setUpdateperson(user.getNickname());
			tmsLoadingBillDetailModel.setUpdatetime(date);

			tmsLoadingBillDetailMapper.update(tmsLoadingBillDetailModel);

			// 修改运单
			Criteria criteriaShip = Criteria.forClass(TmsLoadingBillDetailModel.class);
			r1 = Restrictions.eq("shipbillId", tmsLoadingBillDetailModel.getShipbillId());
			criteriaShip.setRestriction(r1);

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

			tmsShipbillHeaderMapper.updateMapByCriteria(mapUpdate, criteriaShip);

			// 父运单的同步启运
			String fatherShipbillId = tmsLoadingBillDetailModel.getShipbillId();
			while (ToolKits.isNotEmpty(fatherShipbillId)) {
				fatherShipbillId = fatherStartShipment(fatherShipbillId, date, user, departureSignTime, shipbillNodeTrackingSaveNewVO, mapTransportLogUpdate);
				departureSignTime = false;
			}
			MessageUtil.addMessage(new SendMessageDTO(MessageOrderTypeEnum.SHIP_NO.getCode(), MessageTypeEnum.START_SHIP.getCode(), Lists.newArrayList(tmsLoadingBillDetailModel.getShipbillId())));
		}
	}

	/**
	 * 派车单客服反馈
	 *
	 * @param deliveryConfirmFeedBackVO
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void feedBackData(DeliveryConfirmFeedBackVO deliveryConfirmFeedBackVO) {
		ToolKits.isParamNull(deliveryConfirmFeedBackVO.getLoadbillIds(), "派车单ID不能为空");
		ToolKits.isParamNull(deliveryConfirmFeedBackVO.getFeedbackContent(), "反馈内容不能为空");
		ToolKits.isParamNull(deliveryConfirmFeedBackVO.getFeedbackDate(), "反馈日期不能为空");

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

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

		// 节点内容
		StringBuffer nodeEvent = new StringBuffer();
		nodeEvent.append("客服反馈 反馈内容:");
		nodeEvent.append(deliveryConfirmFeedBackVO.getFeedbackContent());
		nodeEvent.append(" 实时地点:");
		nodeEvent.append(deliveryConfirmFeedBackVO.getAddress());

		Criteria criteriaDetail = Criteria.forClass(TmsLoadingBillDetailModel.class);
		Restriction r1 = Restrictions.in("loadingBillId", deliveryConfirmFeedBackVO.getLoadbillIds().toArray());
		criteriaDetail.setRestriction(r1);

		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModelList = tmsLoadingBillDetailMapper.findByCriteria(criteriaDetail);
		ToolKits.isParamNull(tmsLoadingBillDetailModelList, "派车单有误,未查询到对应的运单数据");

		for (TmsLoadingBillDetailModel tmsLoadingBillDetailModel : tmsLoadingBillDetailModelList) {

			// 运单节点信息
			ShipbillNodeTrackingSaveNewVO shipbillNodeTrackingSaveNewVO = new ShipbillNodeTrackingSaveNewVO();
			shipbillNodeTrackingSaveNewVO.setNodeDate(deliveryConfirmFeedBackVO.getFeedbackDate());
			shipbillNodeTrackingSaveNewVO.setShipbillId(tmsLoadingBillDetailModel.getShipbillId());
			shipbillNodeTrackingSaveNewVO.setShipbillNo(tmsLoadingBillDetailModel.getShipbillId());
			shipbillNodeTrackingSaveNewVO.setUserId(user.getUserid());
			shipbillNodeTrackingSaveNewVO.setUserName(user.getNickname());
			shipbillNodeTrackingSaveNewVO.setEnterpriseId(user.getEnterpriseId());
			shipbillNodeTrackingSaveNewVO.setEnterpriseName(user.getEnterpriseName());
			shipbillNodeTrackingSaveNewVO.setStatus(tmsLoadingBillDetailModel.getStatus());
			shipbillNodeTrackingSaveNewVO.setNodeEvent(nodeEvent.toString());
			shipbillNodeTrackingSaveNewVO.setPicUrl(deliveryConfirmFeedBackVO.getFeedbackPicture());
			shipbillNodeTrackingService.addShipbillNodeTrackingNewData(shipbillNodeTrackingSaveNewVO);

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

			// 父运单的同步送达
			String fatherShipbillId = tmsLoadingBillDetailModel.getShipbillId();
			while (ToolKits.isNotEmpty(fatherShipbillId)) {
				fatherShipbillId = fatherFeedBack(fatherShipbillId, date, user, shipbillNodeTrackingSaveNewVO);
			}
		}
	}

	/**
	 * 派车单异常登记
	 *
	 * @param deliveryConfirmAbnormalRegisterVO
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void abnormalRegisterData(DeliveryConfirmAbnormalRegisterVO deliveryConfirmAbnormalRegisterVO) {
		ToolKits.isParamNull(deliveryConfirmAbnormalRegisterVO.getLoadbillIds(), "派车单ID不能为空");
		ToolKits.isParamNull(deliveryConfirmAbnormalRegisterVO.getAbnormalTime(), "异常发生时间不能为空");
		ToolKits.isParamNull(deliveryConfirmAbnormalRegisterVO.getAbnormalType(), "异常类型不能为空");
		ToolKits.isParamNull(deliveryConfirmAbnormalRegisterVO.getAbnormalEvent(), "异常事件不能为空");

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

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

		// 异常类型
		RestMessage<List<Map<String, Object>>> restMessage1 = maindataTmsResource.getDropDownById(DataDictionaryConstant.ABNORMAL_TYPE, null, null, null);
		if (!restMessage1.isSuccess()) {
			throw new RuntimeException("已派车状态翻译失败!");
		} else {
			data1 = restMessage1.getData();
		}

		// 异常事件
		RestMessage<List<Map<String, Object>>> restMessage2 = maindataTmsResource.getDropDownById(DataDictionaryConstant.ABNORMAL_EVENT, null, null, null);
		if (!restMessage2.isSuccess()) {
			throw new RuntimeException("已派车状态翻译失败!");
		} else {
			data2 = restMessage2.getData();
		}

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

		// 节点内容
		StringBuffer nodeEvent = new StringBuffer();
		nodeEvent.append("异常登记 异常类型:");
		nodeEvent.append(PublicMethods.change(data1, String.valueOf(deliveryConfirmAbnormalRegisterVO.getAbnormalType())));
		nodeEvent.append(" 异常事件:");
		nodeEvent.append(PublicMethods.change(data2, String.valueOf(deliveryConfirmAbnormalRegisterVO.getAbnormalEvent())));
		if (ToolKits.isNotEmpty(deliveryConfirmAbnormalRegisterVO.getAbnormalContent())) {
			nodeEvent.append(",异常内容为:");
			nodeEvent.append(deliveryConfirmAbnormalRegisterVO.getAbnormalContent());
		}

		Criteria criteriaDetail = Criteria.forClass(TmsLoadingBillDetailModel.class);
		Restriction r1 = Restrictions.in("loadingBillId", deliveryConfirmAbnormalRegisterVO.getLoadbillIds().toArray());
		criteriaDetail.setRestriction(r1);

		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModelList = tmsLoadingBillDetailMapper.findByCriteria(criteriaDetail);
		ToolKits.isParamNull(tmsLoadingBillDetailModelList, "派车单有误,未查询到对应的运单数据");

		for (TmsLoadingBillDetailModel tmsLoadingBillDetailModel : tmsLoadingBillDetailModelList) {

			// 运单节点信息
			ShipbillNodeTrackingSaveNewVO shipbillNodeTrackingSaveNewVO = new ShipbillNodeTrackingSaveNewVO();
			shipbillNodeTrackingSaveNewVO.setNodeDate(deliveryConfirmAbnormalRegisterVO.getAbnormalTime());
			shipbillNodeTrackingSaveNewVO.setShipbillId(tmsLoadingBillDetailModel.getShipbillId());
			shipbillNodeTrackingSaveNewVO.setShipbillNo(tmsLoadingBillDetailModel.getShipbillId());
			shipbillNodeTrackingSaveNewVO.setUserId(user.getUserid());
			shipbillNodeTrackingSaveNewVO.setUserName(user.getNickname());
			shipbillNodeTrackingSaveNewVO.setEnterpriseId(user.getEnterpriseId());
			shipbillNodeTrackingSaveNewVO.setEnterpriseName(user.getEnterpriseName());
			shipbillNodeTrackingSaveNewVO.setStatus(tmsLoadingBillDetailModel.getStatus());
			shipbillNodeTrackingSaveNewVO.setNodeEvent(nodeEvent.toString());
			shipbillNodeTrackingSaveNewVO.setPicUrl(deliveryConfirmAbnormalRegisterVO.getAbnormalPhoto());
			shipbillNodeTrackingService.addShipbillNodeTrackingNewData(shipbillNodeTrackingSaveNewVO);

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

			// 父运单的同步送达
			String fatherShipbillId = tmsLoadingBillDetailModel.getShipbillId();
			while (ToolKits.isNotEmpty(fatherShipbillId)) {
				fatherShipbillId = fatherAbnormalRegister(fatherShipbillId, date, user, shipbillNodeTrackingSaveNewVO);
			}
		}
	}

	/**
	 * 导出所有数据
	 *
	 * @param deliveryConfirmExportAllVO
	 * @return
	 */
	@Override
	public List<DeliveryConfirmExportDTO> exportAllData(DeliveryConfirmExportAllVO deliveryConfirmExportAllVO) {
		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.LOADING_BILL_STATUS, null, null, null);
		if (!restMessage1.isSuccess()) {
			throw new RuntimeException("已派车状态翻译失败!");
		} else {
			data1 = restMessage1.getData();
		}

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

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

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

		for (TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel : tmsLoadingBillHeaderModels) {
			DeliveryConfirmExportDTO dto = new DeliveryConfirmExportDTO();
			BeanUtils.copyProperties(tmsLoadingBillHeaderModel, dto);

			// 状态翻译
			dto.setStatusName(PublicMethods.change(data1, String.valueOf(tmsLoadingBillHeaderModel.getStatus())));

			deliveryConfirmExportDTOS.add(dto);
		}

		return deliveryConfirmExportDTOS;
	}

	/**
	 * 导出当前页数据
	 *
	 * @param deliveryConfirmExportPageVO
	 * @return
	 */
	@Override
	public List<DeliveryConfirmExportDTO> exportPageData(DeliveryConfirmExportPageVO deliveryConfirmExportPageVO) {
		ToolKits.isParamNull(deliveryConfirmExportPageVO.getPageNum(), "当前页码不为空");
		ToolKits.isParamNull(deliveryConfirmExportPageVO.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.LOADING_BILL_STATUS, null, null, null);
		if (!restMessage1.isSuccess()) {
			throw new RuntimeException("已派车状态翻译失败!");
		} else {
			data1 = restMessage1.getData();
		}

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

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

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

		for (TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel : tmsLoadingBillHeaderModels) {
			DeliveryConfirmExportDTO dto = new DeliveryConfirmExportDTO();
			BeanUtils.copyProperties(tmsLoadingBillHeaderModel, dto);

			// 状态翻译
			dto.setStatusName(PublicMethods.change(data1, String.valueOf(tmsLoadingBillHeaderModel.getStatus())));

			deliveryConfirmExportDTOS.add(dto);
		}

		return deliveryConfirmExportDTOS;
	}

	/**
	 * 导出选择行数据
	 *
	 * @param loadbillIds
	 * @return
	 */
	@Override
	public List<DeliveryConfirmExportDTO> exportSelectLineData(List<String> loadbillIds) {
		ToolKits.isParamNull(loadbillIds, "派车单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();

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

		// 添加查询条件
		Criteria criteria = Criteria.forClass(TmsLoadingBillHeaderModel.class);
		Restriction r1 = Restrictions.eq("loadingBillId", loadbillIds.toArray());
		Restriction r2 = Restrictions.eq("carrierType", DataDictionaryConstant.LINE_CARRIER_TYPE_SJ);
		Restriction r3 = Restrictions.eq("loadingBillType", DataDictionaryConstant.LOADING_BILL_TYPE_RK);
		Restriction r4 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
		Restriction r5 = null;
		Restriction r6 = Restrictions.in("departmentId", user.getDepts().stream().toArray(String[]::new));
		if (user.getUserType().equals(BussinessConstant.USER_TYPE_ZY)) {
			r5 = Restrictions.eq("scheduleType", DataDictionaryConstant.SCHEDULE_TYPE_ZY);
		} else {
			r5 = Restrictions.eq("scheduleType", DataDictionaryConstant.SCHEDULE_TYPE_CYS);
		}
		criteria.setRestriction(Restrictions.and(r1, r2, r3, r4, r5, r6));
		criteria.setOrder(Order.newInstance().desc(new String[] { "updatetime" }));

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

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

		for (TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel : tmsLoadingBillHeaderModels) {
			DeliveryConfirmExportDTO dto = new DeliveryConfirmExportDTO();
			BeanUtils.copyProperties(tmsLoadingBillHeaderModel, dto);

			// 状态翻译
			dto.setStatusName(PublicMethods.change(data1, String.valueOf(tmsLoadingBillHeaderModel.getStatus())));

			deliveryConfirmExportDTOS.add(dto);
		}

		return deliveryConfirmExportDTOS;
	}

	/**
	 * 提货确认打印
	 *
	 * @param loadbillIds
	 * @return
	 */
	@Override
	public Map<String, Object> printDeliveryConfirmData(List<String> loadbillIds) {
		ToolKits.isParamNull(loadbillIds, "派车单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<TmsLoadingBillHeaderModel> tmsLoadingBillHeaderModels = tmsLoadingBillHeaderMapper.findByIds(TmsLoadingBillHeaderModel.class, loadbillIds.toArray(), null);

		for (TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel : tmsLoadingBillHeaderModels) {
			DeliveryConfirmPrintHeadDTO deliveryConfirmPrintHeadDTO = new DeliveryConfirmPrintHeadDTO();
			BeanUtils.copyProperties(tmsLoadingBillHeaderModel, deliveryConfirmPrintHeadDTO);

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

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

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

				deliveryConfirmPrintTableDTOS.add(dto);
			}

		}

		// TODO print
		return null;
	}

	/**
	 * 配载运单剔除
	 *
	 * @param deliveryConfirmDeleteDetailVO
	 */
	@Override
	public void deleteDetailSendCarData(DeliveryConfirmDeleteDetailVO deliveryConfirmDeleteDetailVO) {
		ToolKits.isParamNull(deliveryConfirmDeleteDetailVO.getLoadingBillId(), "派车单ID不为空");
		ToolKits.isParamNull(deliveryConfirmDeleteDetailVO.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, "当前人员没有操作权限");
		}
		Date date = DateUtil.date();
		Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
		Restriction r1 = Restrictions.in("shipbillId", deliveryConfirmDeleteDetailVO.getShipbillIds().toArray());
		Restriction r2 = Restrictions.eq("loadingBillId", deliveryConfirmDeleteDetailVO.getLoadingBillId());
		criteria.setRestriction(Restrictions.and(r1, r2));
		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteria);

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

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

			// 修改配送顺序
			r1 = Restrictions.eq("loadingBillId", tmsLoadingBillDetailModel.getLoadingBillId());
			r2 = Restrictions.ne("shipbillId", tmsLoadingBillDetailModel.getShipbillId());
			criteria.setRestriction(Restrictions.and(r1, r2));
			List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModelList = tmsLoadingBillDetailMapper.findByCriteria(criteria);
			for (TmsLoadingBillDetailModel loadingBillDetailModel : tmsLoadingBillDetailModelList) {
				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(tmsLoadingBillDetailModel.getActualTotalVolume()));
			tmsLoadingBillHeaderModel.setActualTotalWeight(tmsLoadingBillHeaderModel.getActualTotalWeight().subtract(tmsLoadingBillDetailModel.getActualTotalWeight()));

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

			// 运单数
			tmsLoadingBillHeaderModel.setShipbillNumber(tmsLoadingBillHeaderModel.getShipbillNumber() - 1);

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

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

			// 运单操作日志保存
			ShipbillOperateLogSaveVO shipbillOperateLogSaveVO = new ShipbillOperateLogSaveVO();
			shipbillOperateLogSaveVO.setShipbillId(tmsLoadingBillDetailModel.getShipbillId());
			shipbillOperateLogSaveVO.setShipbillNo(tmsLoadingBillDetailModel.getShipbillNo());
			shipbillOperateLogSaveVO.setOperateEvent("从派车单" + tmsLoadingBillDetailModel.getShipbillId() + "中剔除");

			// 运单节点保存
			ShipbillNodeTrackingSaveVO shipbillNodeTrackingSaveVO = new ShipbillNodeTrackingSaveVO();
			shipbillNodeTrackingSaveVO.setShipbillId(tmsLoadingBillDetailModel.getShipbillId());
			shipbillNodeTrackingSaveVO.setShipbillNo(tmsLoadingBillDetailModel.getShipbillNo());

			shipbillNodeTrackingSaveVO.setNodeEvent("从派车单" + tmsLoadingBillHeaderModel.getLoadingBillId() + "中剔除");

			if (user.getUserType().equals(BussinessConstant.USER_TYPE_ZY)) {
				shipbillOperateLogSaveVO.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH);
				shipbillOperateLogSaveVO.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_REVIEW);
				shipbillNodeTrackingSaveVO.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_REVIEW);
			} else {
				shipbillOperateLogSaveVO.setOldStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED);
				shipbillOperateLogSaveVO.setNewStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_AUDITED);
				shipbillNodeTrackingSaveVO.setStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_AUDITED);
			}

			// 保存操作
			shipbillOperateLogService.addShipbillOperateLogData(shipbillOperateLogSaveVO);
			shipbillNodeTrackingService.addShipbillNodeTrackingData(shipbillNodeTrackingSaveVO);

		}

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

		// 修改汇总表
		tmsLoadingBillHeaderModel.setUpdatetime(date);
		tmsLoadingBillHeaderModel.setUpdateperson(user.getNickname());
		tmsLoadingBillHeaderMapper.update(tmsLoadingBillHeaderModel);

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

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

		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;
	}

}
