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.exception.PrologException;
import com.prolog.framework.core.pojo.Page;
import com.prolog.framework.core.restriction.Criteria;
import com.prolog.framework.core.restriction.Order;
import com.prolog.framework.core.restriction.Restriction;
import com.prolog.framework.core.restriction.Restrictions;
import com.prolog.framework.dao.util.PageUtils;
import com.prolog.product.core.framework.entity.UserEntity;
import com.prolog.product.core.framework.util.PlgFxUsrUtils;
import com.prolog.rdc.tms.constant.BussinessConstant;
import com.prolog.rdc.tms.constant.DataDictionaryConstant;
import com.prolog.rdc.tms.constant.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.DeviceByOneDTO;
import com.prolog.rdc.tms.model.dto.LoadingScanByLoadbillDTO;
import com.prolog.rdc.tms.model.dto.PickingOutboundExportDTO;
import com.prolog.rdc.tms.model.dto.PickingOutboundGetShipbillDTO;
import com.prolog.rdc.tms.model.dto.PickingOutboundItemDetailDTO;
import com.prolog.rdc.tms.model.dto.PickingOutboundLoadingScanDTO;
import com.prolog.rdc.tms.model.dto.PickingOutboundNotScannedDTO;
import com.prolog.rdc.tms.model.dto.PickingOutboundPackageDetailDTO;
import com.prolog.rdc.tms.model.dto.PickingOutboundPrintHeadDTO;
import com.prolog.rdc.tms.model.dto.PickingOutboundPrintTableDTO;
import com.prolog.rdc.tms.model.dto.PickingOutboundQueryByLoadbillDTO;
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.SysParamConfigModel;
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.PickingOutboundAbnormalRegisterByShipbillVO;
import com.prolog.rdc.tms.model.vo.PickingOutboundAbnormalRegisterVO;
import com.prolog.rdc.tms.model.vo.PickingOutboundAdvancedQueryVO;
import com.prolog.rdc.tms.model.vo.PickingOutboundConfirmVO;
import com.prolog.rdc.tms.model.vo.PickingOutboundDeleteDetailVO;
import com.prolog.rdc.tms.model.vo.PickingOutboundExportAllVO;
import com.prolog.rdc.tms.model.vo.PickingOutboundExportPageVO;
import com.prolog.rdc.tms.model.vo.PickingOutboundFeedBackByShipbillVO;
import com.prolog.rdc.tms.model.vo.PickingOutboundFeedBackVO;
import com.prolog.rdc.tms.model.vo.PickingOutboundGetShipbillVO;
import com.prolog.rdc.tms.model.vo.PickingOutboundItemDetailVO;
import com.prolog.rdc.tms.model.vo.PickingOutboundLoadingScanVO;
import com.prolog.rdc.tms.model.vo.PickingOutboundPackageDetailVO;
import com.prolog.rdc.tms.model.vo.PickingOutboundQueryByLoadbillVO;
import com.prolog.rdc.tms.model.vo.PickingOutboundStartShipmentByShipbillVO;
import com.prolog.rdc.tms.model.vo.PickingOutboundStartShipmentVO;
import com.prolog.rdc.tms.model.vo.ShipbillNodeTrackingRollbackVO;
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.PickingOutboundService;
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/27 14:25
 */
@Service
public class PickingOutboundServiceImpl implements PickingOutboundService {

	@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 pickingOutboundQueryByLoadbillVO
	 * @return
	 */
	@SuppressWarnings("resource")
	@Override
	public Page<PickingOutboundQueryByLoadbillDTO> queryLoadbillPageData(PickingOutboundQueryByLoadbillVO pickingOutboundQueryByLoadbillVO) {
		ToolKits.isParamNull(pickingOutboundQueryByLoadbillVO, "汇总查询请求不为空");
		ToolKits.isParamNull(pickingOutboundQueryByLoadbillVO.getPageNum(), "当前页码不为空");
		ToolKits.isParamNull(pickingOutboundQueryByLoadbillVO.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(pickingOutboundQueryByLoadbillVO.getLoadingBillNo()) ? null : Restrictions.like("loadingBillNo", "%" + pickingOutboundQueryByLoadbillVO.getLoadingBillNo() + "%");
		Restriction r2 = ToolKits.isEmpty(pickingOutboundQueryByLoadbillVO.getCreateStartTime()) ? null : Restrictions.ge("createtime", pickingOutboundQueryByLoadbillVO.getCreateStartTime());
		Restriction r3 = ToolKits.isEmpty(pickingOutboundQueryByLoadbillVO.getCreateEndTime()) ? null : Restrictions.le("createtime", pickingOutboundQueryByLoadbillVO.getCreateEndTime());
		Restriction r5 = Restrictions.eq("loadingBillType", DataDictionaryConstant.LOADING_BILL_TYPE_CK);
		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, r5, r6, r7, r8, r9));
		criteria.setOrder(Order.newInstance().desc(new String[] { "updatetime" }));

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

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

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

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

			pickingOutboundQueryByLoadbillDTOS.add(dto);
		}

		// 分页重组
		Page<PickingOutboundQueryByLoadbillDTO> page = PageUtils.getPage(pickingOutboundQueryByLoadbillDTOS);
		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;
	}

	@Override
	public Page<PickingOutboundQueryByLoadbillDTO> advancedQueryLoadbillPageData(PickingOutboundAdvancedQueryVO pickingOutboundAdvancedQueryVO) {
		ToolKits.isParamNull(pickingOutboundAdvancedQueryVO, "汇总查询请求不为空");
		ToolKits.isParamNull(pickingOutboundAdvancedQueryVO.getPageNum(), "当前页码不为空");
		ToolKits.isParamNull(pickingOutboundAdvancedQueryVO.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();
		}

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

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

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

		PageUtils.startPage(pickingOutboundAdvancedQueryVO.getPageNum(), pickingOutboundAdvancedQueryVO.getPageSize());
		List<PickingOutboundQueryByLoadbillDTO> pickingOutboundQueryByLoadbillDTOS = tmsLoadingBillHeaderMapper.pickingOutboundAdvancedQuery(pickingOutboundAdvancedQueryVO);

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

		}
		return PageUtils.getPage(pickingOutboundQueryByLoadbillDTOS);
	}

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

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

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

		for (TmsLoadingBillDetailModel model : tmsLoadingBillDetailModels) {

			PickingOutboundGetShipbillDTO pickingOutboundGetShipbillDTO = new PickingOutboundGetShipbillDTO();
			BeanUtils.copyProperties(model, pickingOutboundGetShipbillDTO);

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

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

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

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

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

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

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

							pickingOutboundGetShipbillDTO.setSignConfigId(signconfigPopDTO.getId());

							break Signconfig;
						}
					}
					break;
				}
			}

			list.add(pickingOutboundGetShipbillDTO);
		}

		// 分页重组
		Page<PickingOutboundGetShipbillDTO> 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 pickingOutboundItemDetailVO
	 * @return
	 */
	@SuppressWarnings("resource")
	@Override
	public Page<PickingOutboundItemDetailDTO> itemDetailData(PickingOutboundItemDetailVO pickingOutboundItemDetailVO) {
		ToolKits.isParamNull(pickingOutboundItemDetailVO.getLoadingBillId(), "派车单ID不为空");
		ToolKits.isParamNull(pickingOutboundItemDetailVO.getPageNum(), "当前页码不为空");
		ToolKits.isParamNull(pickingOutboundItemDetailVO.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", pickingOutboundItemDetailVO.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(pickingOutboundItemDetailVO.getPageNum(), pickingOutboundItemDetailVO.getPageSize());
		List<TmsShipbillDetailModel> tmsShipbillDetailModels = tmsShipbillDetailMapper.findByCriteria(criteria);

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

		for (TmsShipbillDetailModel tmsShipbillDetailModel : tmsShipbillDetailModels) {
			PickingOutboundItemDetailDTO dto = new PickingOutboundItemDetailDTO();
			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<PickingOutboundItemDetailDTO> 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 pickingOutboundPackageDetailVO
	 * @return
	 */
	@SuppressWarnings("resource")
	@Override
	public Page<PickingOutboundPackageDetailDTO> packageDetailData(PickingOutboundPackageDetailVO pickingOutboundPackageDetailVO) {
		ToolKits.isParamNull(pickingOutboundPackageDetailVO.getLoadingBillId(), "派车单ID不为空");
		ToolKits.isParamNull(pickingOutboundPackageDetailVO.getPageNum(), "当前页码不为空");
		ToolKits.isParamNull(pickingOutboundPackageDetailVO.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", pickingOutboundPackageDetailVO.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(pickingOutboundPackageDetailVO.getPageNum(), pickingOutboundPackageDetailVO.getPageSize());
		List<TmsShipbillPackageModel> tmsShipbillPackageModels = tmsShipbillPackageMapper.findByCriteria(criteria);

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

		for (TmsShipbillPackageModel tmsShipbillPackageModel : tmsShipbillPackageModels) {
			PickingOutboundPackageDetailDTO dto = new PickingOutboundPackageDetailDTO();
			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<PickingOutboundPackageDetailDTO> 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 pickingOutboundLoadingScanVO
	 * @return
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public PickingOutboundLoadingScanDTO loadingScanData(PickingOutboundLoadingScanVO pickingOutboundLoadingScanVO) {
		ToolKits.isParamNull(pickingOutboundLoadingScanVO.getScanId(), "扫描单号不为空");

		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, "当前人员没有操作权限");
		}

		PickingOutboundLoadingScanDTO pickingOutboundLoadingScanDTO = new PickingOutboundLoadingScanDTO();
		// 提示信息
		String msg = "";
		Integer flag = 0;

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

		// 判断扫描类型
		RestMessage<SysParamConfigModel> restMessage = maindataTmsResource.getValue(DataDictionaryConstant.SCANLOADING_METHED);
		if (!restMessage.isSuccess()) {
			throw new RuntimeException("获取系统参数服务失败!");
		}
		SysParamConfigModel sysParamConfigModel = restMessage.getData();
		// 先扫描派车单再扫描运单(目前只处理该情况)
		if (DataDictionaryConstant.SCANLOADING_METHED_LOADINGBILL_SHIPBILL.equals(sysParamConfigModel.getValue())) {
			// 查询派车单
			Criteria criteria = Criteria.forClass(TmsLoadingBillHeaderModel.class);
			Restriction r1 = Restrictions.eq("loadingBillId", pickingOutboundLoadingScanVO.getScanId());
			Restriction r2 = Restrictions.eq("loadingBillNo", pickingOutboundLoadingScanVO.getScanId());
			Restriction r3 = Restrictions.or(r1, r2);
			Restriction r4 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
			criteria.setRestriction(Restrictions.and(r3, r4));
			List<TmsLoadingBillHeaderModel> tmsLoadingBillHeaderModels = tmsLoadingBillHeaderMapper.findByCriteria(criteria);

			// 扫描失败返回
			if (ToolKits.isEmpty(tmsLoadingBillHeaderModels)) {
				pickingOutboundLoadingScanDTO.setMsg("派车单[" + pickingOutboundLoadingScanVO.getScanId() + "]扫描失败,未找到对应派车单!");
				pickingOutboundLoadingScanDTO.setFlag(1);
				return pickingOutboundLoadingScanDTO;
			}

			TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel = tmsLoadingBillHeaderModels.get(0);
			if (tmsLoadingBillHeaderModel.getStatus() < DataDictionaryConstant.LOADING_BILL_STATUS_LH_START || tmsLoadingBillHeaderModel.getStatus() > DataDictionaryConstant.LOADING_BILL_STATUS_ZX_FINISH) {
				pickingOutboundLoadingScanDTO.setMsg("派车单[" + pickingOutboundLoadingScanVO.getScanId() + "]扫描失败!");
				pickingOutboundLoadingScanDTO.setFlag(1);
				return pickingOutboundLoadingScanDTO;
			}

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

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

			// 修改派车单状态

			tmsLoadingBillHeaderModel.setStatus(DataDictionaryConstant.LOADING_BILL_STATUS_SCAN);
			tmsLoadingBillHeaderModel.setUpdateperson(user.getNickname());
			tmsLoadingBillHeaderModel.setUpdatetime(date);

			tmsLoadingBillHeaderMapper.update(tmsLoadingBillHeaderModel);

			LoadingScanByLoadbillDTO loadingScanByLoadbillDTO = new LoadingScanByLoadbillDTO();
			BeanUtils.copyProperties(tmsLoadingBillHeaderModel, loadingScanByLoadbillDTO);
			loadingScanByLoadbillDTO.setStatusName(PublicMethods.change(statusName, String.valueOf(loadingScanByLoadbillDTO.getStatus())));

			pickingOutboundLoadingScanDTO.setLoadingScanByLoadbillDTO(loadingScanByLoadbillDTO);

			msg = "派车单[" + pickingOutboundLoadingScanVO.getScanId() + "]扫描成功!";

			// 数据字典翻译数据集合
			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();

			// 订单类型
			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();
			}
			// 添加查询条件
			criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
			r1 = Restrictions.eq("loadingBillId", pickingOutboundLoadingScanVO.getScanId());
			r2 = Restrictions.eq("loadingBillNo", pickingOutboundLoadingScanVO.getScanId());
			r3 = Restrictions.or(r1, r2);
			r4 = Restrictions.eq("scanStatus", DataDictionaryConstant.SCAN_STATUS_INIT);
			Restriction r5 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
			criteria.setRestriction(Restrictions.and(r3, r4, r5));

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

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

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

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

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

				pickingOutboundNotScannedDTOS.add(pickingOutboundNotScannedDTO);
			}

			pickingOutboundLoadingScanDTO.setPickingOutboundNotScannedDTOS(pickingOutboundNotScannedDTOS);
		} else {
			throw new RuntimeException("系统目前只支持先扫描派车单再扫描运单");
		}

		pickingOutboundLoadingScanDTO.setMsg(msg);
		pickingOutboundLoadingScanDTO.setFlag(flag);

		return pickingOutboundLoadingScanDTO;
	}

	/**
	 * 父运单装车扫描
	 *
	 * @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 -> DataDictionaryConstant.SCAN_STATUS_INIT.equals(o.getScanStatus())).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;
	}

	/**
	 * 装车确认
	 *
	 * @param pickingOutboundConfirmVO
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void loadingConfirmData(PickingOutboundConfirmVO pickingOutboundConfirmVO) {
		ToolKits.isParamNull(pickingOutboundConfirmVO, "装车确认请求不为空");
		ToolKits.isParamNull(pickingOutboundConfirmVO.getLoadingBillId(), "派车单号不能为空");

		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();

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

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

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

		TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel = tmsLoadingBillHeaderModels.get(0);

		// 修改派车单
		tmsLoadingBillHeaderModel.setStatus(DataDictionaryConstant.LOADING_BILL_STATUS_ZC_CONFIRM);
		tmsLoadingBillHeaderModel.setUpdateperson(user.getNickname());
		tmsLoadingBillHeaderModel.setUpdatetime(date);

		tmsLoadingBillHeaderMapper.update(tmsLoadingBillHeaderModel);

		// 查询运单信息
		criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
		r1 = Restrictions.in("shipbillId", pickingOutboundConfirmVO.getNotScannedShipbillIds().toArray());
		r2 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
		criteria.setRestriction(Restrictions.and(r1, r2));

		// 查询是未装车扫描的运单
		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModelCull = tmsLoadingBillDetailMapper.findByCriteria(criteria);

		// 查询已装车扫描的运单
		r1 = Restrictions.in("shipbillId", pickingOutboundConfirmVO.getScannedShipbillIds().toArray());
		criteria.setRestriction(Restrictions.and(r1, r2));
		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModelConfirm = tmsLoadingBillDetailMapper.findByCriteria(criteria);
		// 剔除操作
		for (TmsLoadingBillDetailModel tmsLoadingBillDetailModel : tmsLoadingBillDetailModelCull) {
			String flowConfig = "";
			if (user.getUserType().equals(BussinessConstant.USER_TYPE_ZY)) {
				flowConfig = tmsLoadingBillDetailModel.getFlowConfig();
			} else if (user.getUserType().equals(BussinessConstant.USER_TYPE_CYS)) {
				flowConfig = tmsLoadingBillDetailModel.getCarrierFlowConfig();
			}
			if (!flowConfig.contains(DataDictionaryConstant.FLOW_CONFIG_SCANNING)) {
				throw new PrologException("运单【" + tmsLoadingBillDetailModel.getShipbillNo() + "】没有匹配到装车扫描的业务流程");
			}
			// 删除派车单明细
			tmsLoadingBillDetailMapper.deleteById(tmsLoadingBillDetailModel.getId(), TmsLoadingBillDetailModel.class);

			// 修改运单
			Map<String, Object> map = Maps.newHashMap();
			map.put("status", DataDictionaryConstant.SHIPBILL_STATUS_WZ);
			map.put("scanStatus", DataDictionaryConstant.SCAN_STATUS_INIT);
			map.put("updateperson", user.getNickname());
			map.put("updatetime", date);
			tmsShipbillHeaderMapper.updateMapById(tmsLoadingBillDetailModel.getShipbillId(), map, TmsShipbillHeaderModel.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);
		}

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

			Map<String, Object> map = Maps.newHashMap();
			if (DataDictionaryConstant.SHIPBILL_STATUS_ZX_FINISH.equals(tmsLoadingBillDetailModel.getStatus())) {
				tmsLoadingBillDetailModel.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_QY);
				map.put("status", DataDictionaryConstant.SHIPBILL_STATUS_QY);
			}
			tmsLoadingBillDetailModel.setUpdateperson(user.getNickname());
			tmsLoadingBillDetailModel.setUpdatetime(date);

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

			// 修改运单
			map.put("updateperson", user.getNickname());
			map.put("updatetime", date);
			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);
			}
		}
		MessageUtil.addMessage(new SendMessageDTO(MessageOrderTypeEnum.LOADING_NO.getCode(), MessageTypeEnum.LOADING.getCode(), Lists.newArrayList(pickingOutboundConfirmVO.getLoadingBillId())));
	}

	/**
	 * 父运单装车确认
	 *
	 * @param shipbillId
	 * @param date
	 * @param user
	 * @return
	 */
	public String fatherLoadingConfirm(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 -> DataDictionaryConstant.SHIPBILL_STATUS_ZX_CONFIRM.equals(o.getStatus())).collect(Collectors.toList());

			// 判断子单是否全部扫描
			if (ToolKits.isEmpty(tmsShipbillHeaderModels)) {
				// 修改父级运单状态
				fatherShipbillHeaderModel.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_ZX_CONFIRM);
				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;
	}

	/**
	 * 派车单启运登记
	 *
	 * @param pickingOutboundStartShipmentVO
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void startShipmentData(PickingOutboundStartShipmentVO pickingOutboundStartShipmentVO) {
		ToolKits.isParamNull(pickingOutboundStartShipmentVO.getLoadbillIds(), "派车单ID不能为空");
		ToolKits.isParamNull(pickingOutboundStartShipmentVO.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(pickingOutboundStartShipmentVO.getDepartureMemo());

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

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

		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels = tmsLoadingBillDetailModelList.stream().filter(o -> o.getShipperPickUpSign().equals(StatusConstant.WHETHER_YES)).collect(Collectors.toList());
		if (ToolKits.isNotEmpty(tmsLoadingBillDetailModels)) {
			ToolKits.isParamNull(pickingOutboundStartShipmentVO.getDepartureSignTime(), "签到时间不能为空");
		}
		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels2 = tmsLoadingBillDetailModelList.stream().filter(o -> o.getShipperPickUpPicture().equals(StatusConstant.WHETHER_YES)).collect(Collectors.toList());
		if (ToolKits.isNotEmpty(tmsLoadingBillDetailModels2)) {
			ToolKits.isParamNull(pickingOutboundStartShipmentVO.getDeparturePhoto(), "货物图片不能为空");
			departurePhoto = pickingOutboundStartShipmentVO.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", pickingOutboundStartShipmentVO.getDepartureTime());
		// 签到时间
		if (ToolKits.isNotEmpty(pickingOutboundStartShipmentVO.getDepartureSignTime())) {
			mapTransportLogUpdate.put("departureSignTime", pickingOutboundStartShipmentVO.getDepartureSignTime());
		}
		// 备注
		if (ToolKits.isNotEmpty(pickingOutboundStartShipmentVO.getDepartureMemo())) {
			mapTransportLogUpdate.put("departureMemo", pickingOutboundStartShipmentVO.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(pickingOutboundStartShipmentVO.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 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 pickingOutboundFeedBackVO
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void feedBackData(PickingOutboundFeedBackVO pickingOutboundFeedBackVO) {
		ToolKits.isParamNull(pickingOutboundFeedBackVO.getLoadbillIds(), "派车单ID不能为空");
		ToolKits.isParamNull(pickingOutboundFeedBackVO.getFeedbackContent(), "反馈内容不能为空");
		ToolKits.isParamNull(pickingOutboundFeedBackVO.getFeedbackDate(), "反馈日期不能为空");

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

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

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

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

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

		for (TmsLoadingBillDetailModel tmsLoadingBillDetailModel : tmsLoadingBillDetailModelList) {

			// 运单节点信息
			ShipbillNodeTrackingSaveNewVO shipbillNodeTrackingSaveNewVO = new ShipbillNodeTrackingSaveNewVO();
			shipbillNodeTrackingSaveNewVO.setNodeDate(pickingOutboundFeedBackVO.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(pickingOutboundFeedBackVO.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 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 pickingOutboundAbnormalRegisterVO
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void abnormalRegisterData(PickingOutboundAbnormalRegisterVO pickingOutboundAbnormalRegisterVO) {
		ToolKits.isParamNull(pickingOutboundAbnormalRegisterVO.getLoadbillIds(), "派车单ID不能为空");
		ToolKits.isParamNull(pickingOutboundAbnormalRegisterVO.getAbnormalTime(), "异常发生时间不能为空");
		ToolKits.isParamNull(pickingOutboundAbnormalRegisterVO.getAbnormalType(), "异常类型不能为空");
		ToolKits.isParamNull(pickingOutboundAbnormalRegisterVO.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(pickingOutboundAbnormalRegisterVO.getAbnormalType())));
		nodeEvent.append(" 异常事件:");
		nodeEvent.append(PublicMethods.change(data2, String.valueOf(pickingOutboundAbnormalRegisterVO.getAbnormalEvent())));
		if (ToolKits.isNotEmpty(pickingOutboundAbnormalRegisterVO.getAbnormalContent())) {
			nodeEvent.append(",异常内容为:");
			nodeEvent.append(pickingOutboundAbnormalRegisterVO.getAbnormalContent());
		}

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

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

		for (TmsLoadingBillDetailModel tmsLoadingBillDetailModel : tmsLoadingBillDetailModelList) {

			// 运单节点信息
			ShipbillNodeTrackingSaveNewVO shipbillNodeTrackingSaveNewVO = new ShipbillNodeTrackingSaveNewVO();
			shipbillNodeTrackingSaveNewVO.setNodeDate(pickingOutboundAbnormalRegisterVO.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(pickingOutboundAbnormalRegisterVO.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 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 pickingOutboundStartShipmentByShipbillVO
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void shipbillStartShipmentData(PickingOutboundStartShipmentByShipbillVO pickingOutboundStartShipmentByShipbillVO) {
		ToolKits.isParamNull(pickingOutboundStartShipmentByShipbillVO.getShipbillIds(), "运单ID不能为空");
		ToolKits.isParamNull(pickingOutboundStartShipmentByShipbillVO.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(pickingOutboundStartShipmentByShipbillVO.getDepartureMemo());

		List<TmsShipbillHeaderModel> tmsShipbillHeaderMapperByIds = tmsShipbillHeaderMapper.findByIds(TmsShipbillHeaderModel.class, pickingOutboundStartShipmentByShipbillVO.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(pickingOutboundStartShipmentByShipbillVO.getDepartureSignTime(), "签到时间不能为空");
		}
		List<TmsShipbillHeaderModel> tmsShipbillHeaderModels2 = tmsShipbillHeaderMapperByIds.stream().filter(o -> StatusConstant.WHETHER_YES.equals(o.getShipperPickUpPicture())).collect(Collectors.toList());
		if (ToolKits.isNotEmpty(tmsShipbillHeaderModels2)) {
			ToolKits.isParamNull(pickingOutboundStartShipmentByShipbillVO.getDeparturePhoto(), "货物图片不能为空");
			departurePhoto = pickingOutboundStartShipmentByShipbillVO.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", pickingOutboundStartShipmentByShipbillVO.getDepartureTime());
		// 签到时间
		if (ToolKits.isNotEmpty(pickingOutboundStartShipmentByShipbillVO.getDepartureSignTime())) {
			mapTransportLogUpdate.put("departureSignTime", pickingOutboundStartShipmentByShipbillVO.getDepartureSignTime());
		}
		// 备注
		if (ToolKits.isNotEmpty(pickingOutboundStartShipmentByShipbillVO.getDepartureMemo())) {
			mapTransportLogUpdate.put("departureMemo", pickingOutboundStartShipmentByShipbillVO.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(pickingOutboundStartShipmentByShipbillVO.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;
			}
		}

		// 修改派车单明细
		Criteria criteriaDetail = Criteria.forClass(TmsLoadingBillDetailModel.class);
		Restriction r1 = Restrictions.in("shipbillId", pickingOutboundStartShipmentByShipbillVO.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 pickingOutboundFeedBackByShipbillVO
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void shipbillFeedBackData(PickingOutboundFeedBackByShipbillVO pickingOutboundFeedBackByShipbillVO) {
		ToolKits.isParamNull(pickingOutboundFeedBackByShipbillVO.getShipbillIds(), "运单ID不能为空");
		ToolKits.isParamNull(pickingOutboundFeedBackByShipbillVO.getFeedbackContent(), "反馈内容不能为空");
		ToolKits.isParamNull(pickingOutboundFeedBackByShipbillVO.getFeedbackDate(), "反馈日期不能为空");

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

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

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

		List<TmsShipbillHeaderModel> tmsShipbillHeaderModelList = tmsShipbillHeaderMapper.findByIds(TmsShipbillHeaderModel.class, pickingOutboundFeedBackByShipbillVO.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 pickingOutboundAbnormalRegisterByShipbillVO
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void shipbillAbnormalRegisterData(PickingOutboundAbnormalRegisterByShipbillVO pickingOutboundAbnormalRegisterByShipbillVO) {
		ToolKits.isParamNull(pickingOutboundAbnormalRegisterByShipbillVO.getShipbillIds(), "运单ID不能为空");
		ToolKits.isParamNull(pickingOutboundAbnormalRegisterByShipbillVO.getAbnormalTime(), "异常发生时间不能为空");
		ToolKits.isParamNull(pickingOutboundAbnormalRegisterByShipbillVO.getAbnormalType(), "异常类型不能为空");
		ToolKits.isParamNull(pickingOutboundAbnormalRegisterByShipbillVO.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(pickingOutboundAbnormalRegisterByShipbillVO.getAbnormalType())));
		nodeEvent.append(",异常事件:");
		nodeEvent.append(PublicMethods.change(data2, String.valueOf(pickingOutboundAbnormalRegisterByShipbillVO.getAbnormalEvent())));
		if (ToolKits.isNotEmpty(pickingOutboundAbnormalRegisterByShipbillVO.getAbnormalContent())) {
			nodeEvent.append(",异常内容为:");
			nodeEvent.append(pickingOutboundAbnormalRegisterByShipbillVO.getAbnormalContent());
		}

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

		for (TmsShipbillHeaderModel tmsShipbillHeaderModel : tmsShipbillHeaderModelList) {

			// 运单节点信息
			ShipbillNodeTrackingSaveNewVO shipbillNodeTrackingSaveNewVO = new ShipbillNodeTrackingSaveNewVO();
			shipbillNodeTrackingSaveNewVO.setNodeDate(pickingOutboundAbnormalRegisterByShipbillVO.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(pickingOutboundAbnormalRegisterByShipbillVO.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 pickingOutboundExportAllVO
	 * @return
	 */
	@Override
	public List<PickingOutboundExportDTO> exportAllData(PickingOutboundExportAllVO pickingOutboundExportAllVO) {
		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(pickingOutboundExportAllVO.getLoadingBillNo()) ? null : Restrictions.like("loadingBillNo", "%" + pickingOutboundExportAllVO.getLoadingBillNo() + "%");
		Restriction r2 = ToolKits.isEmpty(pickingOutboundExportAllVO.getCreateStartTime()) ? null : Restrictions.ge("createtime", pickingOutboundExportAllVO.getCreateStartTime());
		Restriction r3 = ToolKits.isEmpty(pickingOutboundExportAllVO.getCreateEndTime()) ? null : Restrictions.le("createtime", pickingOutboundExportAllVO.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<PickingOutboundExportDTO> pickingOutboundExportDTOS = Lists.newArrayList();

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

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

			pickingOutboundExportDTOS.add(dto);
		}

		return pickingOutboundExportDTOS;
	}

	/**
	 * 导出当前页数据
	 *
	 * @param pickingOutboundExportPageVO
	 * @return
	 */
	@Override
	public List<PickingOutboundExportDTO> exportPageData(PickingOutboundExportPageVO pickingOutboundExportPageVO) {
		ToolKits.isParamNull(pickingOutboundExportPageVO.getPageNum(), "当前页码不为空");
		ToolKits.isParamNull(pickingOutboundExportPageVO.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(pickingOutboundExportPageVO.getLoadingBillNo()) ? null : Restrictions.like("loadingBillNo", "%" + pickingOutboundExportPageVO.getLoadingBillNo() + "%");
		Restriction r2 = ToolKits.isEmpty(pickingOutboundExportPageVO.getCreateStartTime()) ? null : Restrictions.ge("createtime", pickingOutboundExportPageVO.getCreateStartTime());
		Restriction r3 = ToolKits.isEmpty(pickingOutboundExportPageVO.getCreateEndTime()) ? null : Restrictions.le("createtime", pickingOutboundExportPageVO.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(pickingOutboundExportPageVO.getPageNum(), pickingOutboundExportPageVO.getPageSize());
		List<TmsLoadingBillHeaderModel> tmsLoadingBillHeaderModels = tmsLoadingBillHeaderMapper.findByCriteria(criteria);

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

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

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

			pickingOutboundExportDTOS.add(dto);
		}

		return pickingOutboundExportDTOS;
	}

	/**
	 * 导出选择行数据
	 *
	 * @param loadbillIds
	 * @return
	 */
	@Override
	public List<PickingOutboundExportDTO> 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<PickingOutboundExportDTO> pickingOutboundExportDTOS = Lists.newArrayList();

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

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

			pickingOutboundExportDTOS.add(dto);
		}

		return pickingOutboundExportDTOS;
	}

	/**
	 * 拣货出库打印
	 *
	 * @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) {
			PickingOutboundPrintHeadDTO pickingOutboundPrintHeadDTO = new PickingOutboundPrintHeadDTO();
			BeanUtils.copyProperties(tmsLoadingBillHeaderModel, pickingOutboundPrintHeadDTO);

			// 表格数据集
			List<PickingOutboundPrintTableDTO> pickingOutboundPrintTableDTOS = 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) {
				PickingOutboundPrintTableDTO dto = new PickingOutboundPrintTableDTO();
				BeanUtils.copyProperties(tmsLoadingBillDetailModel, dto);

				pickingOutboundPrintTableDTOS.add(dto);
			}

		}

		// TODO print
		return null;
	}

	/**
	 * 配载运单剔除
	 *
	 * @param pickingOutboundDeleteDetailVO
	 */
	@Override
	public void deleteDetailData(PickingOutboundDeleteDetailVO pickingOutboundDeleteDetailVO) {
		ToolKits.isParamNull(pickingOutboundDeleteDetailVO.getLoadingBillId(), "派车单ID不为空");
		ToolKits.isParamNull(pickingOutboundDeleteDetailVO.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", pickingOutboundDeleteDetailVO.getShipbillIds().toArray());
		Restriction r2 = Restrictions.eq("loadingBillId", pickingOutboundDeleteDetailVO.getLoadingBillId());
		criteria.setRestriction(Restrictions.and(r1, r2));
		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteria);

		TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel = tmsLoadingBillHeaderMapper.findById(pickingOutboundDeleteDetailVO.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", pickingOutboundDeleteDetailVO.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;
	}

}
