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

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

import com.prolog.rdc.tms.app.constant.enums.IntelligentLockEnum;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.prolog.common.util.ToolKits;
import com.prolog.framework.common.message.RestMessage;
import com.prolog.framework.core.exception.BizException;
import com.prolog.framework.core.exception.PrologException;
import com.prolog.framework.core.pojo.Page;
import com.prolog.framework.core.restriction.Criteria;
import com.prolog.framework.core.restriction.Order;
import com.prolog.framework.core.restriction.Restriction;
import com.prolog.framework.core.restriction.RestrictionBuilder;
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.app.constant.BussinessConstant;
import com.prolog.rdc.tms.app.constant.DataDictionaryConstant;
import com.prolog.rdc.tms.app.constant.SeriaNnumberConstant;
import com.prolog.rdc.tms.app.constant.StatusConstant;
import com.prolog.rdc.tms.app.constant.enums.ArriveNotequalDeliveryHandleTypeEnum;
import com.prolog.rdc.tms.app.constant.enums.DriverReceiveStatusEnum;
import com.prolog.rdc.tms.app.constant.enums.ShipBillReturnTypeEnum;
import com.prolog.rdc.tms.app.constant.enums.ShipBillTypeEnum;
import com.prolog.rdc.tms.app.constant.enums.SignInStatusEnum;
import com.prolog.rdc.tms.app.constant.enums.SigninNotequalDeliveryHandleTypeEnum;
import com.prolog.rdc.tms.app.dao.mapper.TmsLoadingBillDetailMapper;
import com.prolog.rdc.tms.app.dao.mapper.TmsLoadingBillHeaderMapper;
import com.prolog.rdc.tms.app.dao.mapper.TmsShipbillContainerTempMapper;
import com.prolog.rdc.tms.app.dao.mapper.TmsShipbillDetailMapper;
import com.prolog.rdc.tms.app.dao.mapper.TmsShipbillHeaderMapper;
import com.prolog.rdc.tms.app.dao.mapper.TmsShipbillNodeTrackingMapper;
import com.prolog.rdc.tms.app.dao.mapper.TmsShipbillOperateLogMapper;
import com.prolog.rdc.tms.app.dao.mapper.TmsShipbillTransportLogMapper;
import com.prolog.rdc.tms.app.model.dto.business.AllShipbillItemDetailDTO;
import com.prolog.rdc.tms.app.model.dto.business.AllShipbillPageDTO;
import com.prolog.rdc.tms.app.model.dto.business.ContainerTemperatureDTO;
import com.prolog.rdc.tms.app.model.dto.business.ShowContainerTemperatureDTO;
import com.prolog.rdc.tms.app.model.dto.business.StrategyBusinessTemperatureDTO;
import com.prolog.rdc.tms.app.model.entity.ShipbillNodeTracking;
import com.prolog.rdc.tms.app.model.entity.TmsLoadingBillDetailModel;
import com.prolog.rdc.tms.app.model.entity.TmsLoadingBillHeaderModel;
import com.prolog.rdc.tms.app.model.entity.TmsShipbillContainerTemp;
import com.prolog.rdc.tms.app.model.entity.TmsShipbillDetailModel;
import com.prolog.rdc.tms.app.model.entity.TmsShipbillHeaderModel;
import com.prolog.rdc.tms.app.model.entity.TmsShipbillOperateLogModel;
import com.prolog.rdc.tms.app.model.entity.TmsShipbillTransLogModel;
import com.prolog.rdc.tms.app.model.vo.PendingDeliveryConfirmVO;
import com.prolog.rdc.tms.app.model.vo.SignInItemVO;
import com.prolog.rdc.tms.app.model.vo.business.AllShipbillQueryVO;
import com.prolog.rdc.tms.app.model.vo.business.ShipBillReceiptPhotoVO;
import com.prolog.rdc.tms.app.model.vo.business.ShipbillDetailSaveVO;
import com.prolog.rdc.tms.app.model.vo.business.ShipbillHeaderSaveVO;
import com.prolog.rdc.tms.app.model.vo.business.ShipbillNodeTrackingSaveVO;
import com.prolog.rdc.tms.app.model.vo.business.ShipbillOperateLogSaveVO;
import com.prolog.rdc.tms.app.model.vo.business.ShowContainerTemperatureVO;
import com.prolog.rdc.tms.app.model.vo.business.SignInShipBillVO;
import com.prolog.rdc.tms.app.proxy.MainDataProxy;
import com.prolog.rdc.tms.app.service.PendingDeliveryService;
import com.prolog.rdc.tms.app.service.business.LoadingBillService;
import com.prolog.rdc.tms.app.service.business.PendingSubmitService;
import com.prolog.rdc.tms.app.service.business.ShipbillNodeTrackingService;
import com.prolog.rdc.tms.app.service.business.ShipbillOperateLogService;
import com.prolog.rdc.tms.app.service.business.ShipbillService;
import com.prolog.rdc.tms.app.service.flow.chain.ReturnShipBillChain;
import com.prolog.rdc.tms.app.util.ConvertorUtil;
import com.prolog.rdc.tms.app.util.DataUtils;
import com.prolog.rdc.tms.app.util.MessageUtil;
import com.prolog.rdc.tms.app.util.StrategyUtil;
import com.prolog.rdc.tms.model.dto.basicConfigure.ShipbillFitBusinessFlowDTO;
import com.prolog.rdc.tms.model.dto.basicConfigure.ShipbillMatchLineDTO;
import com.prolog.rdc.tms.model.dto.basicConfigure.StrategyBusinessMatchingDTO;
import com.prolog.rdc.tms.model.dto.basicData.ItemCheckDTO;
import com.prolog.rdc.tms.model.dto.basicData.ProviderShipperCheckDTO;
import com.prolog.rdc.tms.model.dto.basicData.TmsBaseBranchDTO;
import com.prolog.rdc.tms.model.dto.basicData.TmsBaseCustomerReceiverNewDTO;
import com.prolog.rdc.tms.model.dto.fleetManagement.ContainerDTO;
import com.prolog.rdc.tms.model.dto.message.SendMessageDTO;
import com.prolog.rdc.tms.model.entity.SysParamConfigModel;
import com.prolog.rdc.tms.model.entity.SysRefdatadModel;
import com.prolog.rdc.tms.model.enums.MessageOrderTypeEnum;
import com.prolog.rdc.tms.model.enums.MessageTypeEnum;
import com.prolog.rdc.tms.model.vo.basicConfigure.BusinessFlowShipbillVO;
import com.prolog.rdc.tms.rmi.feign.MaindataFeign;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * 快速开单实现层
 *
 * @author zhangsj
 * @since 2022/7/19 16:44
 */
@Service
@Slf4j
public class ShipbillServiceImpl implements ShipbillService {

	@Autowired
	private TmsShipbillHeaderMapper tmsShipbillHeaderMapper;

	@Autowired
	private MaindataFeign maindataTmsResource;

	@Autowired
	private TmsShipbillDetailMapper tmsShipbillDetailMapper;

	@Autowired
	private PendingSubmitService pendingSubmitService;

	@Autowired
	private TmsShipbillTransportLogMapper tmsShipbillTransportLogMapper;

	@Autowired
	private ShipbillNodeTrackingService shipbillNodeTrackingService;

	@Autowired
	private ShipbillOperateLogService shipbillOperateLogService;

	@Autowired
	private ReturnShipBillChain returnShipBillChain;

	@Autowired
	private PendingDeliveryService pendingDeliveryService;

	@Autowired
	private MainDataProxy mainDataProxy;

	@Autowired
	private TmsShipbillNodeTrackingMapper tmsShipbillNodeTrackingMapper;

	@Autowired
	private TmsShipbillOperateLogMapper tmsShipbillOperateLogMapper;

	@Autowired
	private TmsLoadingBillHeaderMapper tmsLoadingBillHeaderMapper;

	@Autowired
	private TmsLoadingBillDetailMapper tmsLoadingBillDetailMapper;

	@Autowired
	private ConvertorUtil convertorUtil;

	@Autowired
	private StrategyUtil strategyUtil;

	@Autowired
	private LoadingBillService loadingBillService;

	@Autowired
	private TmsShipbillContainerTempMapper shipbillContainerTempMapper;


	/**
	 * 快速开单
	 *
	 * @param shipbillHeaderSaveVO
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void quickShipbillData(ShipbillHeaderSaveVO shipbillHeaderSaveVO) {
		ToolKits.isParamNull(shipbillHeaderSaveVO, "运单保存请求不为空！");
		ToolKits.isParamNull(shipbillHeaderSaveVO.getCargoOwnerId(), "货主ID不为空");
		ToolKits.isParamNull(shipbillHeaderSaveVO.getCargoOwnerCode(), "货主编码不为空");
		ToolKits.isParamNull(shipbillHeaderSaveVO.getCargoOwnerName(), "货主名称不为空");
		ToolKits.isParamNull(shipbillHeaderSaveVO.getOrderType(), "订单类型不为空");
		ToolKits.isParamNull(shipbillHeaderSaveVO.getOrderBusinessType(), "订单业务类型不为空");
		ToolKits.isParamNull(shipbillHeaderSaveVO.getDeliveryMethodType(), "配送方式不为空");
		ToolKits.isParamNull(shipbillHeaderSaveVO.getTransportType(), "运输模式不为空");
		ToolKits.isParamNull(shipbillHeaderSaveVO.getTemperatureRequirement(), "温度要求不为空");
		ToolKits.isParamNull(shipbillHeaderSaveVO.getShipperType(), "发货方类型不为空");
		ToolKits.isParamNull(shipbillHeaderSaveVO.getShipperId(), "发货方id不为空");
		ToolKits.isParamNull(shipbillHeaderSaveVO.getShipperUnitId(), "发货方单位ID不为空");
		ToolKits.isParamNull(shipbillHeaderSaveVO.getShipperUnitCode(), "发货方单位编码不为空");
		ToolKits.isParamNull(shipbillHeaderSaveVO.getShipperUnitName(), "发货方单位名称不为空");
		ToolKits.isParamNull(shipbillHeaderSaveVO.getShipperProvince(), "发货方省编码不为空");
		ToolKits.isParamNull(shipbillHeaderSaveVO.getShipperProvinceName(), "发货方省名称不为空");
		ToolKits.isParamNull(shipbillHeaderSaveVO.getShipperCity(), "发货方市编码不为空");
		ToolKits.isParamNull(shipbillHeaderSaveVO.getShipperCityName(), "发货方市名称不为空");
		ToolKits.isParamNull(shipbillHeaderSaveVO.getShipperDistrict(), "发货方区/县编码不为空");
		ToolKits.isParamNull(shipbillHeaderSaveVO.getShipperDistrictName(), "发货方区/县名称不为空");
		ToolKits.isParamNull(shipbillHeaderSaveVO.getShipperAddress(), "发货方详细地址不为空");
		ToolKits.isParamNull(shipbillHeaderSaveVO.getConsigneeType(), "收货方类型不为空");
		ToolKits.isParamNull(shipbillHeaderSaveVO.getConsigneeId(), "收货方id不为空");
		ToolKits.isParamNull(shipbillHeaderSaveVO.getConsigneeUnitId(), "收货方单位ID不为空");
		ToolKits.isParamNull(shipbillHeaderSaveVO.getConsigneeUnitCode(), "收货方单位编码不为空");
		ToolKits.isParamNull(shipbillHeaderSaveVO.getConsigneeUnitName(), "收货方单位名称不为空");
		ToolKits.isParamNull(shipbillHeaderSaveVO.getConsigneeProvince(), "收货方省编码不为空");
		ToolKits.isParamNull(shipbillHeaderSaveVO.getConsigneeProvinceName(), "收货方省名称不为空");
		ToolKits.isParamNull(shipbillHeaderSaveVO.getConsigneeCity(), "收货方市编码不为空");
		ToolKits.isParamNull(shipbillHeaderSaveVO.getConsigneeCityName(), "收货方市名称不为空");
		ToolKits.isParamNull(shipbillHeaderSaveVO.getConsigneeDistrict(), "收货方区/县编码不为空");
		ToolKits.isParamNull(shipbillHeaderSaveVO.getConsigneeDistrictName(), "收货方区/县名称不为空");
		ToolKits.isParamNull(shipbillHeaderSaveVO.getConsigneeAddress(), "收货方详细地址不为空");

		ToolKits.isParamNull(shipbillHeaderSaveVO.getDepartmentId(), "结算部门ID不为空");
		ToolKits.isParamNull(shipbillHeaderSaveVO.getDepartmentCode(), "结算部门编号不为空");
		ToolKits.isParamNull(shipbillHeaderSaveVO.getDepartmentName(), "结算部门名称不为空");
		ToolKits.isParamNull(shipbillHeaderSaveVO.getExtStr4(), "所属部门不为空");

		UserEntity user = PlgFxUsrUtils.getUserEntity();
		ToolKits.isParamNull(user, "当前人员没有操作权限");
		ToolKits.isParamNull(user.getDepts(), "当前账号没有所属部门");

		Integer shipperStatus = null;
		if (DataDictionaryConstant.SHIPPER_TYPE_KH.equals(shipbillHeaderSaveVO.getShipperType())) {
			TmsBaseCustomerReceiverNewDTO tmsBaseCustomerReceiverNewDTO = mainDataProxy.viewCustomerReceiver(shipbillHeaderSaveVO.getShipperId());
			shipperStatus = tmsBaseCustomerReceiverNewDTO.getStatus();
		} else if (DataDictionaryConstant.SHIPPER_TYPE_CK.equals(shipbillHeaderSaveVO.getShipperType())) {
			TmsBaseBranchDTO tmsBaseBranchDTO = mainDataProxy.viewBranch(shipbillHeaderSaveVO.getShipperId());
			shipperStatus = tmsBaseBranchDTO.getStatus();
		} else if (DataDictionaryConstant.SHIPPER_TYPE_GYS.equals(shipbillHeaderSaveVO.getShipperType())) {
			ProviderShipperCheckDTO providerShipperCheckDTO = mainDataProxy.getShipperExecute(shipbillHeaderSaveVO.getShipperId());
			shipperStatus = providerShipperCheckDTO.getStatus();
		}
		if (!DataDictionaryConstant.STATUS_ENABLE.equals(shipperStatus)) {
			throw new BizException(shipbillHeaderSaveVO.getShipperName() + "未启用");
		}

		Integer consigneeStatus = null;
		if (DataDictionaryConstant.CONSIGNEE_TYPE_KH.equals(shipbillHeaderSaveVO.getConsigneeType())) {
			TmsBaseCustomerReceiverNewDTO tmsBaseCustomerReceiverNewDTO = mainDataProxy.viewCustomerReceiver(shipbillHeaderSaveVO.getConsigneeId());
			consigneeStatus = tmsBaseCustomerReceiverNewDTO.getStatus();
		} else if (DataDictionaryConstant.CONSIGNEE_TYPE_CK.equals(shipbillHeaderSaveVO.getConsigneeType())) {
			TmsBaseBranchDTO tmsBaseBranchDTO = mainDataProxy.viewBranch(shipbillHeaderSaveVO.getConsigneeId());
			consigneeStatus = tmsBaseBranchDTO.getStatus();
		} else if (DataDictionaryConstant.CONSIGNEE_TYPE_GYS.equals(shipbillHeaderSaveVO.getConsigneeType())) {
			ProviderShipperCheckDTO providerShipperCheckDTO = mainDataProxy.getShipperExecute(shipbillHeaderSaveVO.getConsigneeId());
			consigneeStatus = providerShipperCheckDTO.getStatus();
		}
		if (!DataDictionaryConstant.STATUS_ENABLE.equals(consigneeStatus)) {
			throw new BizException(shipbillHeaderSaveVO.getConsigneeName() + "未启用");
		}

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

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

		TmsShipbillHeaderModel tmsShipbillHeaderModel = new TmsShipbillHeaderModel();
		BeanUtils.copyProperties(shipbillHeaderSaveVO, tmsShipbillHeaderModel);
		tmsShipbillHeaderModel.setPickUpOrder(1);
		tmsShipbillHeaderModel.setShippingOrder(2);
		tmsShipbillHeaderModel.setShipbillId(id);
		tmsShipbillHeaderModel.setShipbillNo(id);
		tmsShipbillHeaderModel.setOrderDate(ToolKits.isEmpty(tmsShipbillHeaderModel.getOrderDate()) ? date : tmsShipbillHeaderModel.getOrderDate());
		tmsShipbillHeaderModel.setDeliveryMethodType(ToolKits.isEmpty(shipbillHeaderSaveVO.getDeliveryMethodType()) ? DataDictionaryConstant.DELIVERY_METHOD_TYPE_SEND : shipbillHeaderSaveVO.getDeliveryMethodType());
		tmsShipbillHeaderModel.setTransportType(DataDictionaryConstant.TRANSPORT_TYPE_LD);
		tmsShipbillHeaderModel.setTransportStatus(DataDictionaryConstant.TRANSPORT_STATUS_PENDING_SHIP);
		tmsShipbillHeaderModel.setAbnormalStatus(DataDictionaryConstant.SHIPBILL_ABNORMAL_STATUS_NO);
		tmsShipbillHeaderModel.setSplitOrderStatus(DataDictionaryConstant.SPLIT_ORDER_STATUS_UN);
		tmsShipbillHeaderModel.setSplitOrderType(DataDictionaryConstant.SPLIT_ORDER_TYPE_UN);
		// 拆单状态 0承运商未拆单
		tmsShipbillHeaderModel.setCarrierSplitOrderStatus(DataDictionaryConstant.CARRIER_SPLIT_ORDER_STATUS_UN);
		// 拆单类型 1承运商未拆单
		tmsShipbillHeaderModel.setCarrierSplitOrderType(DataDictionaryConstant.CARRIER_SPLIT_ORDER_TYPE_UN);
		tmsShipbillHeaderModel.setScanStatus(DataDictionaryConstant.SCAN_STATUS_INIT);
		tmsShipbillHeaderModel.setTemperatureRequirement(DataDictionaryConstant.TEMPERATURE_REQUIREMENT_CW);
		tmsShipbillHeaderModel.setEstimatedPickupEndTime(shipbillHeaderSaveVO.getEstimatedPickupStartTime());
		tmsShipbillHeaderModel.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_CSH);
		tmsShipbillHeaderModel.setSource(DataDictionaryConstant.SOURCE_ADD);
		tmsShipbillHeaderModel.setActualTotalPcs(shipbillHeaderSaveVO.getTotalPcs());
		tmsShipbillHeaderModel.setActualTotalWeight(shipbillHeaderSaveVO.getTotalWeight());
		tmsShipbillHeaderModel.setActualTotalVolume(shipbillHeaderSaveVO.getTotalVolume());
		tmsShipbillHeaderModel.setEnterpriseId(user.getEnterpriseId());
		tmsShipbillHeaderModel.setEnterpriseName(user.getEnterpriseName());
		tmsShipbillHeaderModel.setCreateperson(user.getNickname());
		tmsShipbillHeaderModel.setCreatetime(date);
		tmsShipbillHeaderModel.setUpdateperson(user.getNickname());
		tmsShipbillHeaderModel.setUpdatetime(date);
		tmsShipbillHeaderModel.setReturnOrderFlag(ToolKits.isEmpty(shipbillHeaderSaveVO.getReturnOrderFlag()) ? StatusConstant.WHETHER_NO : shipbillHeaderSaveVO.getReturnOrderFlag());

		// 查询用户的关联部门信息
		// RestMessage<List<Organization>> orgRestMessage =
		// userTmsResource.selectByUserId(String.valueOf(user.getUserid()));
//		Assert.isTrue(orgRestMessage.isSuccess(), "查询用户部门信息失败:" + orgRestMessage.getMessage());
//		Assert.isTrue(ToolKits.isNotEmpty(orgRestMessage.getData()), "用户【" + user.getNickname() + "】未绑定部门");
//		// 部门对象
//		Organization organization = orgRestMessage.getData().get(0);
//
		tmsShipbillHeaderModel.setDepartmentId(shipbillHeaderSaveVO.getDepartmentId());
		tmsShipbillHeaderModel.setDepartmentCode(shipbillHeaderSaveVO.getDepartmentCode());
		tmsShipbillHeaderModel.setDepartmentName(shipbillHeaderSaveVO.getDepartmentName());
		tmsShipbillHeaderModel.setExtStr4(shipbillHeaderSaveVO.getExtStr4());

		// 发货方为仓库，收货方为 客户，能匹配上 线路，则自动 将匹配的线路 填入
		/*
		 * if (ToolKits.isEmpty(shipbillHeaderSaveVO.getLineId())) { if
		 * (shipbillHeaderSaveVO.getShipperType().equals(DataDictionaryConstant.
		 * SHIPPER_TYPE_CK) &&
		 * shipbillHeaderSaveVO.getConsigneeType().equals(DataDictionaryConstant.
		 * CONSIGNEE_TYPE_KH)) { LineByCustomerQueryVO lineByCustomerQueryVO = new
		 * LineByCustomerQueryVO();
		 * lineByCustomerQueryVO.setCustomerId(shipbillHeaderSaveVO.getConsigneeUnitId()
		 * );
		 * lineByCustomerQueryVO.setConsigneeId(shipbillHeaderSaveVO.getConsigneeId());
		 * RestMessage<LineByCustomerQueryDTO> restMessage1 =
		 * maindataTmsResource.getLineByCustomerExecute(lineByCustomerQueryVO); if
		 * (restMessage1.isSuccess()) { if (ToolKits.isNotEmpty(restMessage1.getData()))
		 * { tmsShipbillHeaderModel.setLineId(restMessage1.getData().getLineId());
		 * tmsShipbillHeaderModel.setLineCode(restMessage1.getData().getLineCode());
		 * tmsShipbillHeaderModel.setLineName(restMessage1.getData().getLineName()); } }
		 * else { throw new ParameterException(restMessage1.getMessage()); } } }
		 */

		// 运单业务流程匹配
		ShipbillFitBusinessFlowDTO flowData = shipbillMatchBusinessFlow(tmsShipbillHeaderModel);
		// 订单绑定流程配置
		tmsShipbillHeaderModel.setFlowConfig(flowData.getFlowConfig());

		Map<Long, ItemCheckDTO> itemCheckDTOMap = mainDataProxy.getItemByIdList(shipbillHeaderSaveVO.getDetails().stream().map(ShipbillDetailSaveVO::getItemId).collect(Collectors.toList()));
		Integer seqno = 1;
		List<TmsShipbillDetailModel> detailModels = Lists.newArrayList();
		for (ShipbillDetailSaveVO detail : shipbillHeaderSaveVO.getDetails()) {
			ToolKits.isParamNull(detail.getItemId(), "商品ID不为空");
			ToolKits.isParamNull(detail.getItemCode(), "商品编码不为空");
			ToolKits.isParamNull(detail.getItemName(), "商品名称不为空");
			ToolKits.isParamNull(detail.getPcs(), "商品件数不为空");

			TmsShipbillDetailModel tmsShipbillDetailModel = new TmsShipbillDetailModel();
			BeanUtils.copyProperties(detail, tmsShipbillDetailModel);

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

			tmsShipbillDetailModel.setId(tmsShipbillDetailId);
			tmsShipbillDetailModel.setSeqno(seqno);
			tmsShipbillDetailModel.setOriginalSeqno(seqno);
			tmsShipbillDetailModel.setShipbillId(id);
			tmsShipbillDetailModel.setShipbillNo(id);
			tmsShipbillDetailModel.setCargoOwnerId(tmsShipbillHeaderModel.getCargoOwnerId());
			tmsShipbillDetailModel.setCargoOwnerCode(tmsShipbillHeaderModel.getCargoOwnerCode());
			tmsShipbillDetailModel.setCargoOwnerName(tmsShipbillHeaderModel.getCargoOwnerName());
			tmsShipbillDetailModel.setEnterpriseId(user.getEnterpriseId());
			tmsShipbillDetailModel.setEnterpriseName(user.getEnterpriseName());
			tmsShipbillDetailModel.setCreateperson(user.getNickname());
			tmsShipbillDetailModel.setCreatetime(date);
			tmsShipbillDetailModel.setUpdateperson(user.getNickname());
			tmsShipbillDetailModel.setUpdatetime(date);

			tmsShipbillDetailModel.setOrigPcs(tmsShipbillDetailModel.getPcs());
			tmsShipbillDetailModel.setClosingPcs(BigDecimal.valueOf(0));
			tmsShipbillDetailModel.setDeliveryPcs(BigDecimal.valueOf(0));

			ItemCheckDTO itemCheckDTO = itemCheckDTOMap.get(detail.getItemId());
			if (ObjectUtil.isNotNull(itemCheckDTO)) {
				tmsShipbillDetailModel.setItemCategoryId(itemCheckDTO.getItemCategoryId());
				tmsShipbillDetailModel.setItemCategoryCode(itemCheckDTO.getItemCategoryCode());
				tmsShipbillDetailModel.setItemCategoryName(itemCheckDTO.getItemCategoryName());
				tmsShipbillDetailModel.setPackType(itemCheckDTO.getPackType());
				tmsShipbillDetailModel.setCargoThermosphere(itemCheckDTO.getCargoThermosphere());
				tmsShipbillDetailModel.setStagingLocation(itemCheckDTO.getStagingLocation());
				tmsShipbillDetailModel.setInventoryPcs(itemCheckDTO.getInventoryPcs());
			}
			tmsShipbillDetailModel.setScanStatus(DataDictionaryConstant.SCAN_STATUS_INIT);
			tmsShipbillDetailMapper.save(tmsShipbillDetailModel);
			seqno++;
			detailModels.add(tmsShipbillDetailModel);
		}

		// 运单匹配线路
		if (StrUtil.isNotBlank(tmsShipbillHeaderModel.getFlowConfig()) && tmsShipbillHeaderModel.getFlowConfig().contains(DataDictionaryConstant.FLOW_CONFIG_ADD_LINE_STRATEGY)) {
			ShipbillMatchLineDTO lineData = strategyUtil.shipbillMatchLine(tmsShipbillHeaderModel);
			if (ToolKits.isNotEmpty(lineData) && ToolKits.isNotEmpty(lineData.getLineId())) {
				// 订单绑定线路
				tmsShipbillHeaderModel.setLineId(lineData.getLineId());
				tmsShipbillHeaderModel.setLineCode(lineData.getLineCode());
				tmsShipbillHeaderModel.setLineName(lineData.getLineName());
				tmsShipbillHeaderModel.setLineDirection(lineData.getLineDirection());
				tmsShipbillHeaderModel.setShippingOrder(lineData.getShippingOrder());
				tmsShipbillHeaderModel.setPickUpOrder(lineData.getPickUpOrder());
				tmsShipbillHeaderModel.setShipperDeliveryOrder(NumberUtil.toBigDecimal(lineData.getPickUpOrder()));
				tmsShipbillHeaderModel.setConsigneeDeliveryOrder(NumberUtil.toBigDecimal(lineData.getShippingOrder()));
				DataUtils.setEstimatedTime(tmsShipbillHeaderModel, lineData, "CR");
			} else {
				tmsShipbillHeaderModel.setLineDirection(DataDictionaryConstant.LINE_DIRECTION_F);
			}
		}
		tmsShipbillHeaderModel.setShipbillType(ShipBillTypeEnum.NORMAL.getCode());
		tmsShipbillHeaderModel.setSignInStatus(SignInStatusEnum.NOT_SIGN.getCode());
		tmsShipbillHeaderModel.setDriverReceiveStatus(DriverReceiveStatusEnum.N.getCode());

		// 匹配业务规则
		if (StrUtil.isNotBlank(tmsShipbillHeaderModel.getFlowConfig()) && tmsShipbillHeaderModel.getFlowConfig().contains(DataDictionaryConstant.FLOW_CONFIG_ADD_BUSINESS_STRATEGY)) {
			strategyUtil.updateShipbillHeaderByBusinessRule(tmsShipbillHeaderModel, detailModels);
		}
		tmsShipbillHeaderModel.setIntelligentLock(IntelligentLockEnum.UN_LOCK.getCode());
		tmsShipbillHeaderMapper.save(tmsShipbillHeaderModel);

		// 运单节点保存
		ShipbillNodeTrackingSaveVO shipbillNodeTrackingSaveVO = new ShipbillNodeTrackingSaveVO();
		shipbillNodeTrackingSaveVO.setShipbillId(id);
		shipbillNodeTrackingSaveVO.setShipbillNo(id);
		shipbillNodeTrackingSaveVO.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_CSH);
		shipbillNodeTrackingSaveVO.setNodeEvent(DataDictionaryConstant.SHIPBILL_NODE_STATUSNAME_SC);
		shipbillNodeTrackingService.addShipbillNodeTrackingData(shipbillNodeTrackingSaveVO);

		// 运单操作日志保存
		ShipbillOperateLogSaveVO shipbillOperateLogSaveVO = new ShipbillOperateLogSaveVO();
		shipbillOperateLogSaveVO.setShipbillId(id);
		shipbillOperateLogSaveVO.setShipbillNo(id);
		shipbillOperateLogSaveVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_CSH + " 匹配业务流程：" + flowData.getFlowName());
		shipbillOperateLogSaveVO.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_CSH);
		shipbillOperateLogSaveVO.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_CSH);
		shipbillOperateLogService.addShipbillOperateLogData(shipbillOperateLogSaveVO);

		// 初期化订单运输记录表
		saveTransportLog(id, date, DataDictionaryConstant.ACTION_SAVE, tmsShipbillHeaderModel.getEstimatedPickupStartTime());

		// 保存自动提交判定
		if (tmsShipbillHeaderModel.getFlowConfig().contains(DataDictionaryConstant.FLOW_CONFIG_ADD_COMMIT)) {
			List<String> list = Lists.newArrayList();
			list.add(tmsShipbillHeaderModel.getShipbillId());
			try {
				// 调用提交处理
				pendingSubmitService.autoSubmitShipbillData(list, user, date);
			} catch (Exception e) {
				throw new PrologException("运单保存自动提交处理失败", e);
			}
		}
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void createReturnShipBill(SignInShipBillVO signInShipBillVO) {
		ToolKits.isParamNull(signInShipBillVO.getShipBillId(), "运单ID不能为空！");
		ToolKits.isParamNull(signInShipBillVO.getItemVOList(), "运单明细不能为空！");
		log.info("createReturnShipBill={}", JSON.toJSONString(signInShipBillVO));
		// 自动生成一个退回运单并调度当前司机
		if (autoReturn(signInShipBillVO.getReturnType())) {
			List<SignInItemVO> itemVOList = signInShipBillVO.getItemVOList();
			List<TmsShipbillDetailModel> tmsShipBillDetailModelList = tmsShipbillDetailMapper.findByIds(TmsShipbillDetailModel.class, itemVOList.stream().map(SignInItemVO::getId).collect(Collectors.toList()).toArray(), null);
			if (tmsShipBillDetailModelList.size() != itemVOList.size()) {
				throw new BizException("明细不匹配，存在非" + signInShipBillVO.getShipBillId() + "的明细，id=" + itemVOList.stream().map(SignInItemVO::getId).collect(Collectors.joining(",")));
			}
			Map<String, SignInItemVO> itemVOMap = itemVOList.stream().collect(Collectors.toMap(t1 -> t1.getId(), t2 -> t2, (t1, t2) -> t2));
			tmsShipBillDetailModelList = tmsShipBillDetailModelList.stream().filter(tmsShipBillDetailModel -> {
				SignInItemVO itemVO = itemVOMap.get(tmsShipBillDetailModel.getId());
				return NumberUtil.isGreater(tmsShipBillDetailModel.getPickUpPcs(), itemVO.getSignInPcs());
			}).peek(tmsShipBillDetailModel -> {
				SignInItemVO itemVO = itemVOMap.get(tmsShipBillDetailModel.getId());
				tmsShipBillDetailModel.setPcs(NumberUtil.sub(tmsShipBillDetailModel.getPickUpPcs(), itemVO.getSignInPcs()));
				tmsShipBillDetailModel.setOrigPcs(tmsShipBillDetailModel.getPcs());
				tmsShipBillDetailModel.setDeliveryPcs(BigDecimal.ZERO);
				tmsShipBillDetailModel.setPickUpPcs(BigDecimal.ZERO);
				tmsShipBillDetailModel.setSignInPcs(BigDecimal.ZERO);
			}).collect(Collectors.toList());
			// 过滤出需要退货的运单明细
			if (CollectionUtil.isNotEmpty(tmsShipBillDetailModelList)) {
				log.info("itemVOList={}", JSON.toJSONString(itemVOList));
				TmsShipbillHeaderModel tmsShipBillHeaderModel = tmsShipbillHeaderMapper.findById(signInShipBillVO.getShipBillId(), TmsShipbillHeaderModel.class);
				returnShipBillChain.execute(tmsShipBillHeaderModel, tmsShipBillDetailModelList);
			}
		}
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void updateSignInPcs(SignInShipBillVO signInShipBillVO) {
		UserEntity user = PlgFxUsrUtils.getUserEntity();
		// 修改运单明细签收数量
		List<SignInItemVO> itemVOList = signInShipBillVO.getItemVOList();
		Map<Long, SignInItemVO> itemVOMap = itemVOList.stream().collect(Collectors.toMap(t1 -> t1.getItemId(), t2 -> t2, (t1, t2) -> t2));
		Criteria criteria = Criteria.forClass(TmsShipbillDetailModel.class);
		Restriction restriction = new RestrictionBuilder().eq("shipbillId", signInShipBillVO.getShipBillId()).build();
		criteria.setRestriction(restriction);
		List<TmsShipbillDetailModel> shipBillDetailModelList = tmsShipbillDetailMapper.findByCriteria(criteria);
		shipBillDetailModelList.stream().forEach(shipBillDetailModel -> {
			SignInItemVO itemVO = itemVOMap.get(shipBillDetailModel.getItemId());
			if (ObjectUtil.isNotNull(itemVO)) {
				shipBillDetailModel.setUpdatetime(new Date());
				shipBillDetailModel.setUpdateperson(user.getNickname());
				shipBillDetailModel.setSignInPcs(NumberUtil.add(shipBillDetailModel.getSignInPcs(), itemVO.getSignInPcs()));
				tmsShipbillDetailMapper.update(shipBillDetailModel);
			}
		});
		TmsShipbillHeaderModel tmsShipBillHeaderModel = tmsShipbillHeaderMapper.findById(signInShipBillVO.getShipBillId(), TmsShipbillHeaderModel.class);
		// 递归更新父级运单明细签收数量
		String fatherShipBillId = tmsShipBillHeaderModel.getFatherShipbillId();
		while (StrUtil.isNotBlank(fatherShipBillId)) {
			Criteria fatherDetailCriteria = Criteria.forClass(TmsShipbillDetailModel.class);
			Restriction fatherDetailRestriction = new RestrictionBuilder().eq("shipbillId", fatherShipBillId).build();
			fatherDetailCriteria.setRestriction(fatherDetailRestriction);
			List<TmsShipbillDetailModel> fatherDetail = tmsShipbillDetailMapper.findByCriteria(fatherDetailCriteria);
			// 父级明细统计下一级明细数量并更新
			List<TmsShipbillHeaderModel> tmsShipBillHeaderModelList = getChildTmsShipBillHeaderModel(fatherShipBillId);
			if (CollectionUtil.isNotEmpty(tmsShipBillHeaderModelList)) {
				List<String> shipBillIdList = tmsShipBillHeaderModelList.stream().map(TmsShipbillHeaderModel::getShipbillId).collect(Collectors.toList());
				// 查询子单对应商品的明细
				List<TmsShipbillDetailModel> childDetail = getTmsShipBillDetailModel(shipBillIdList, Lists.newArrayList(itemVOMap.keySet()));
				Map<Long, List<TmsShipbillDetailModel>> itemMap = childDetail.stream().collect(Collectors.groupingBy(TmsShipbillDetailModel::getItemId));
				fatherDetail.stream().forEach(shipBillDetailModel -> {
					List<TmsShipbillDetailModel> childDetailList = itemMap.get(shipBillDetailModel.getItemId());
					if (CollectionUtil.isNotEmpty(childDetailList)) {
						shipBillDetailModel.setUpdatetime(new Date());
						shipBillDetailModel.setUpdateperson(user.getNickname());
						shipBillDetailModel.setSignInPcs(childDetailList.stream().map(TmsShipbillDetailModel::getSignInPcs).reduce(BigDecimal.ZERO, NumberUtil::add));
						tmsShipbillDetailMapper.update(shipBillDetailModel);
					}
				});
			}
			TmsShipbillHeaderModel fatherHeader = tmsShipbillHeaderMapper.findById(fatherShipBillId, TmsShipbillHeaderModel.class);
			if (ObjectUtil.isNotNull(fatherHeader)) {
				fatherShipBillId = fatherHeader.getFatherShipbillId();
			} else {
				fatherShipBillId = StrUtil.EMPTY;
			}
		}
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void signIn(SignInShipBillVO signInShipBillVO) {
		signInShipBillVO.setReturnType(ShipBillReturnTypeEnum.Q.getCode());
		TmsShipbillHeaderModel tmsShipBillHeaderModel = tmsShipbillHeaderMapper.findById(signInShipBillVO.getShipBillId(), TmsShipbillHeaderModel.class);
		if (!DataDictionaryConstant.SHIPBILL_STATUS_SD.equals(tmsShipBillHeaderModel.getStatus()) && !DataDictionaryConstant.SHIPBILL_STATUS_HD_PIC.equals(tmsShipBillHeaderModel.getStatus()) && !DataDictionaryConstant.SHIPBILL_STATUS_HD_ZB.equals(tmsShipBillHeaderModel.getStatus())) {
			throw new BizException("运单【" + signInShipBillVO.getShipBillId() + "】状态不为启运，送达，回单状态，不能签收");
		}
		if (SignInStatusEnum.SIGN.getCode().equals(tmsShipBillHeaderModel.getSignInStatus())) {
			throw new BizException("运单【" + signInShipBillVO.getShipBillId() + "】已签收");
		}
		// 运单状态为启运先做送达
		if (DataDictionaryConstant.SHIPBILL_STATUS_SD.equals(tmsShipBillHeaderModel.getStatus())) {
			PendingDeliveryConfirmVO pendingDeliveryConfirmVO = new PendingDeliveryConfirmVO();
			pendingDeliveryConfirmVO.setDriverId(signInShipBillVO.getDriverId());
			pendingDeliveryConfirmVO.setEnterpriseId(signInShipBillVO.getEnterpriseId());
			pendingDeliveryConfirmVO.setShipbillId(signInShipBillVO.getShipBillId());
			pendingDeliveryConfirmVO.setGoodsPicUrl(signInShipBillVO.getGoodsPicUrl());
			pendingDeliveryConfirmVO.setReceiptPicUrl(signInShipBillVO.getReceiptPicUrl());
			pendingDeliveryConfirmVO.setSignPerson(signInShipBillVO.getSignPerson());
			pendingDeliveryConfirmVO.setSignRemark(signInShipBillVO.getSignRemark());
			pendingDeliveryConfirmVO.setLongitude(signInShipBillVO.getLongitude());
			pendingDeliveryConfirmVO.setLatitude(signInShipBillVO.getLatitude());
			pendingDeliveryConfirmVO.setDeliveryTemperature(signInShipBillVO.getDeliveryTemperature());
			pendingDeliveryConfirmVO.setReceiptPhotoVOList(Lists.newArrayList(new ShipBillReceiptPhotoVO(signInShipBillVO.getShipBillId(), signInShipBillVO.getReceiptPicUrl())));
			try {
				pendingDeliveryService.pendingDeliveryConfirm(pendingDeliveryConfirmVO);
			} catch (Exception e) {
				log.error("签收自动送达确认失败", e);
				throw new BizException(e.getMessage());
			}
		} else {
			if (StrUtil.isNotBlank(signInShipBillVO.getGoodsPicUrl())) {
				updateShipBillNodePic(signInShipBillVO.getShipBillId(), DataDictionaryConstant.SHIPBILL_STATUSNAME_SD, signInShipBillVO.getGoodsPicUrl());
			}
			if (StrUtil.isNotBlank(signInShipBillVO.getReceiptPicUrl())) {
				updateShipBillNodePic(signInShipBillVO.getShipBillId(), DataDictionaryConstant.SHIPBILL_STATUSNAME_HD_PIC, signInShipBillVO.getGoodsPicUrl());
			}
		}
		tmsShipBillHeaderModel = tmsShipbillHeaderMapper.findById(signInShipBillVO.getShipBillId(), TmsShipbillHeaderModel.class);
		// 更新运单签收状态并记录日志
		updateShipBillSignInStatus(tmsShipBillHeaderModel, signInShipBillVO);
		// 更新派车单签收状态
		updateLoadingBillSignInStatus(tmsShipBillHeaderModel);
		if (CollectionUtil.isNotEmpty(signInShipBillVO.getItemVOList())) {
			// 更新签收数量
			updateSignInPcs(signInShipBillVO);
			// 签收自动退
			createReturnShipBill(signInShipBillVO);
		}
		MessageUtil.addMessage(new SendMessageDTO(MessageOrderTypeEnum.SHIP_NO.getCode(), MessageTypeEnum.SIGN.getCode(), Lists.newArrayList(signInShipBillVO.getShipBillId())));
	}

	/**
	 * 销售单模式查询
	 * 
	 * @param
	 * @return
	 */
	@Override
	public Page<AllShipbillPageDTO> querySellAllShipbillPage(AllShipbillQueryVO vo) {
		ToolKits.isParamNull(vo, "运单分页查询请求不为空");
		UserEntity user = PlgFxUsrUtils.getUserEntity();
		ToolKits.isParamNull(user, "当前人员没有操作权限");
		List<SysRefdatadModel> dicData = convertorUtil.getDictionary(new String[] { DataDictionaryConstant.SHIPBILL_STATUS, // 运单状态
				DataDictionaryConstant.TRANSPORT_STATUS, // 运输状态
				DataDictionaryConstant.ABNORMAL_STATUS, // 异常状态
				DataDictionaryConstant.SCAN_STATUS, // 扫描状态
				DataDictionaryConstant.LINE_CARRIER_TYPE, // 承运方类型
				DataDictionaryConstant.DELIVERY_METHOD_TYPE, // 配送方式
				DataDictionaryConstant.TRANSPORT_TYPE, // 运输类型(运输模式)
				DataDictionaryConstant.TEMPERATURE_REQUIREMENT, // 温度要求
				DataDictionaryConstant.SHIPPER_TYPE, // 发货方类型
				DataDictionaryConstant.CONSIGNEE_TYPE, // 收货方类型
				DataDictionaryConstant.ORDER_TYPE, // 订单类型
				DataDictionaryConstant.ORDER_BUSINESS_TYPE, // 订单业务类型
				DataDictionaryConstant.CARRIER_SPLIT_ORDER_STATUS, // 承运商拆单状态
				DataDictionaryConstant.CARRIER_SPLIT_ORDER_TYPE// 承运商拆单类型
		});
		vo.setEnterpriseId(user.getEnterpriseId());
		vo.setUserType(user.getUserType());
		vo.setIsSell("YES");
		if (ObjectUtil.equal(user.getUserType(), BussinessConstant.USER_TYPE_ZY)) {// 自有账号
			vo.setDepts(ToolKits.isEmpty(user.getDepts()) ? null : user.getDepts().stream().toArray(String[]::new));
			if (BussinessConstant.USER_DEPARTMENT_AUTH_Y.equals(user.getOwnedAllDataAuthFlag())) {// 部门权限
				vo.setIsDept("YES");
			} else {// 业务员权限
				vo.setIsDept("NO");
				// 货主
				vo.setConsignors(ToolKits.isEmpty(user.getConsignors()) ? null : user.getConsignors().stream().toArray(Long[]::new));
				// 客户
				vo.setCustomers(ToolKits.isEmpty(user.getCustomers()) ? null : user.getCustomers().stream().toArray(Long[]::new));
				// 供应商
				vo.setSuppliers(ToolKits.isEmpty(user.getSuppliers()) ? null : user.getSuppliers().stream().toArray(Long[]::new));
				// 仓库
				vo.setWsarehouses(ToolKits.isEmpty(user.getWarehouses()) ? null : user.getWarehouses().stream().toArray(Long[]::new));
			}
		} else if (user.getUserType().equals(BussinessConstant.USER_TYPE_HZ)) {
			// 货主
			Long[] consignor = { Long.valueOf(user.getLoginUserCompanyInfo().getId()) };
			vo.setConsignors(consignor);
		}
		if (ObjectUtil.equal(user.getUserType(), BussinessConstant.USER_TYPE_CYS)) {// 承运商账号
			vo.setCarrierId(Long.valueOf(user.getLoginUserCompanyInfo().getId()));
		}
		PageUtils.startPage(vo.getPageNum(), vo.getPageSize());
		List<AllShipbillPageDTO> dtos = tmsShipbillHeaderMapper.querySellAllShipbill(vo);
		for (AllShipbillPageDTO dto : dtos) {
//			if (!DataDictionaryConstant.SHIPPER_TYPE_CK.equals(dto.getShipperType())) {
//				dto.setShipperName(dto.getShipperUnitName() + DataDictionaryConstant.Line_SYMBOL + dto.getShipperName());
//			}
//			if (!DataDictionaryConstant.CONSIGNEE_TYPE_CK.equals(dto.getConsigneeType())) {
//				dto.setConsigneeName(dto.getConsigneeUnitName() + DataDictionaryConstant.Line_SYMBOL + dto.getConsigneeName());
//			}
			// 字典翻译
			dto.setStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.SHIPBILL_STATUS, String.valueOf(dto.getStatus())));
			dto.setTransportStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.TRANSPORT_STATUS, String.valueOf(dto.getTransportStatus())));
			dto.setAbnormalStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.ABNORMAL_STATUS, String.valueOf(dto.getAbnormalStatus())));
			dto.setScanStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.SCAN_STATUS, String.valueOf(dto.getScanStatus())));
			dto.setOrderTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.ORDER_TYPE, String.valueOf(dto.getOrderType())));
			dto.setOrderBusinessTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.ORDER_BUSINESS_TYPE, String.valueOf(dto.getOrderBusinessType())));
			dto.setDeliveryMethodTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.DELIVERY_METHOD_TYPE, String.valueOf(dto.getDeliveryMethodType())));
			dto.setTransportTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.TRANSPORT_TYPE, String.valueOf(dto.getTransportType())));
			dto.setTemperatureRequirementName(ConvertorUtil.getName(dicData, DataDictionaryConstant.TEMPERATURE_REQUIREMENT, String.valueOf(dto.getTemperatureRequirement())));
			dto.setShipperTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.SHIPPER_TYPE, String.valueOf(dto.getShipperType())));
			dto.setConsigneeTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.CONSIGNEE_TYPE, String.valueOf(dto.getConsigneeType())));
			dto.setAllShipbillItemDetailDTOList(getItemDetailDTO(dto.getShipbillId()));
		}
		return PageUtils.getPage(dtos);
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public void reject(List<String> shipBillIdList) {
		if (CollectionUtil.isNotEmpty(shipBillIdList)) {
			UserEntity user = PlgFxUsrUtils.getUserEntity();
			shipBillIdList = shipBillIdList.stream().flatMap(s -> Arrays.stream(s.split(","))).collect(Collectors.toList());
			List<TmsShipbillHeaderModel> tmsShipbillHeaderModelList = tmsShipbillHeaderMapper.findByIds(TmsShipbillHeaderModel.class, shipBillIdList.toArray(), null);
			List<String> loadingBillIdList = Lists.newArrayList();
			tmsShipbillHeaderModelList.forEach(tmsShipbillHeaderModel -> {
				if (!Lists.newArrayList(DataDictionaryConstant.SHIPBILL_STATUS_PENDING_APP, DataDictionaryConstant.SHIPBILL_STATUS_THQD, DataDictionaryConstant.SHIPBILL_STATUS_QY, DataDictionaryConstant.SHIPBILL_STATUS_HD_ZT).contains(tmsShipbillHeaderModel.getStatus())) {
					throw new BizException("运单状态发生变化，请刷新后重试！");
				}
				if (DriverReceiveStatusEnum.A.getCode().equals(tmsShipbillHeaderModel.getDriverReceiveStatus())) {
					throw new BizException("运单" + tmsShipbillHeaderModel.getShipbillId() + "已接单，不能拒绝！");
				}
				Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
				Restriction restriction = Restrictions.eq("shipbillId", tmsShipbillHeaderModel.getShipbillId());
				criteria.setRestriction(restriction);
				criteria.setOrder(Order.newInstance().desc(new String[] { "createtime" }));
				List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModelList = tmsLoadingBillDetailMapper.findByCriteria(criteria);
				TmsLoadingBillDetailModel tmsLoadingBillDetailModel = tmsLoadingBillDetailModelList.get(0);
				tmsLoadingBillDetailMapper.deleteByIds(tmsLoadingBillDetailModelList.stream().map(TmsLoadingBillDetailModel::getId).toArray(), TmsLoadingBillDetailModel.class);
				TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel = tmsLoadingBillHeaderMapper.findById(tmsLoadingBillDetailModel.getLoadingBillId(), TmsLoadingBillHeaderModel.class);
				if (DataDictionaryConstant.SCHEDULE_TYPE_ZY.equals(tmsLoadingBillHeaderModel.getScheduleType())) {
					tmsShipbillHeaderModel.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_REVIEW);
				} else {
					tmsShipbillHeaderModel.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH_CHECK);
					tmsShipbillHeaderModel.setCarrierShipbillStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_AUDITED);
				}
				tmsShipbillHeaderModel.setUpdatetime(new Date());
				tmsShipbillHeaderModel.setUpdateperson(user.getNickname());
				tmsShipbillHeaderMapper.update(tmsShipbillHeaderModel);

				ShipbillOperateLogSaveVO shipbillOperateLogSaveVO = new ShipbillOperateLogSaveVO();
				shipbillOperateLogSaveVO.setShipbillId(tmsShipbillHeaderModel.getShipbillId());
				shipbillOperateLogSaveVO.setShipbillNo(tmsShipbillHeaderModel.getShipbillNo());
				shipbillOperateLogSaveVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_SJJJ);
				shipbillOperateLogSaveVO.setOldStatus(tmsShipbillHeaderModel.getStatus());
				if (DataDictionaryConstant.SCHEDULE_TYPE_ZY.equals(tmsLoadingBillHeaderModel.getScheduleType())) {
					shipbillOperateLogSaveVO.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_REVIEW);
				} else {
					shipbillOperateLogSaveVO.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH_CHECK);
				}
				shipbillOperateLogService.addShipbillOperateLogData(shipbillOperateLogSaveVO);
				loadingBillIdList.addAll(tmsLoadingBillDetailModelList.stream().map(TmsLoadingBillDetailModel::getLoadingBillId).distinct().collect(Collectors.toList()));
			});
			loadingBillService.reCalLoadingBill(loadingBillIdList);
		}
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public void receive(List<String> shipBillIdList) {
		if (CollectionUtil.isNotEmpty(shipBillIdList)) {
			UserEntity user = PlgFxUsrUtils.getUserEntity();
			shipBillIdList = shipBillIdList.stream().flatMap(s -> Arrays.stream(s.split(","))).collect(Collectors.toList());
			List<TmsShipbillHeaderModel> tmsShipbillHeaderModelList = tmsShipbillHeaderMapper.findByIds(TmsShipbillHeaderModel.class, shipBillIdList.toArray(), null);
			tmsShipbillHeaderModelList.forEach(tmsShipbillHeaderModel -> {
				if (!Lists.newArrayList(DataDictionaryConstant.SHIPBILL_STATUS_PENDING_APP, DataDictionaryConstant.SHIPBILL_STATUS_THQD, DataDictionaryConstant.SHIPBILL_STATUS_QY, DataDictionaryConstant.SHIPBILL_STATUS_HD_ZT).contains(tmsShipbillHeaderModel.getStatus())) {
					throw new BizException("运单状态发生变化，请刷新后重试！");
				}
				if (!DriverReceiveStatusEnum.A.getCode().equals(tmsShipbillHeaderModel.getDriverReceiveStatus())) {
					tmsShipbillHeaderModel.setDriverReceiveStatus(DriverReceiveStatusEnum.A.getCode());
					tmsShipbillHeaderModel.setUpdatetime(new Date());
					tmsShipbillHeaderModel.setUpdateperson(user.getNickname());
					tmsShipbillHeaderMapper.update(tmsShipbillHeaderModel);

					ShipbillOperateLogSaveVO shipbillOperateLogSaveVO = new ShipbillOperateLogSaveVO();
					shipbillOperateLogSaveVO.setShipbillId(tmsShipbillHeaderModel.getShipbillId());
					shipbillOperateLogSaveVO.setShipbillNo(tmsShipbillHeaderModel.getShipbillNo());
					shipbillOperateLogSaveVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_SJJD);
					shipbillOperateLogSaveVO.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_PENDING_APP);
					shipbillOperateLogSaveVO.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_PENDING_APP);
					shipbillOperateLogService.addShipbillOperateLogData(shipbillOperateLogSaveVO);

					Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
					Restriction restriction = Restrictions.eq("shipbillId", tmsShipbillHeaderModel.getShipbillId());
					criteria.setRestriction(restriction);
					criteria.setOrder(Order.newInstance().desc(new String[] { "createtime" }));
					List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModelList = tmsLoadingBillDetailMapper.findByCriteria(criteria);
					TmsLoadingBillDetailModel tmsLoadingBillDetailModel = tmsLoadingBillDetailModelList.get(0);
					tmsLoadingBillDetailModel.setDriverReceiveStatus(DriverReceiveStatusEnum.A.getCode());
					tmsLoadingBillDetailModel.setUpdatetime(new Date());
					tmsLoadingBillDetailModel.setUpdateperson(user.getNickname());
					tmsLoadingBillDetailMapper.update(tmsLoadingBillDetailModel);
				}
			});
		}
	}

	/**
	 * 业务规则匹配-是否显示温度
	 *
	 * @param shipBillIdList
	 * @return
	 */
	@Override
	public StrategyBusinessTemperatureDTO showTemperature(List<String> shipBillIdList) {
		shipBillIdList = shipBillIdList.stream().flatMap(s -> Arrays.stream(s.split(","))).collect(Collectors.toList());
		List<TmsShipbillHeaderModel> tmsShipbillHeaderModelList = tmsShipbillHeaderMapper.findByIds(TmsShipbillHeaderModel.class, shipBillIdList.toArray(), null);
		List<StrategyBusinessMatchingDTO> dtoList = Lists.newArrayList();
		tmsShipbillHeaderModelList.forEach(tmsShipbillHeaderModel -> {
			Criteria criteria = Criteria.forClass(TmsShipbillDetailModel.class);
			Restriction r1 = Restrictions.eq(TmsShipbillDetailModel::getShipbillId, tmsShipbillHeaderModel.getShipbillId());
			criteria.setRestriction(Restrictions.and(r1));
			List<TmsShipbillDetailModel> tmsShipbillDetailModelList = tmsShipbillDetailMapper.findByCriteria(criteria);
			StrategyBusinessMatchingDTO businessData = strategyUtil.shipbillMatchBusinessRule(tmsShipbillHeaderModel, tmsShipbillDetailModelList);
			if (ObjectUtil.isNotNull(businessData)) {
				dtoList.add(businessData);
			}
		});
		StrategyBusinessTemperatureDTO dto = new StrategyBusinessTemperatureDTO();
		dto.setShowDepartureTemperature(Boolean.FALSE);
		dto.setShowDeliveryTemperature(Boolean.FALSE);
		dto.setDtoList(dtoList);
		if (CollectionUtil.isNotEmpty(dtoList)) {
			if (dtoList.stream().anyMatch(strategyBusinessMatchingDTO -> DataDictionaryConstant.TEMPERATURE_SELECT_YES.equals(strategyBusinessMatchingDTO.getDepartureTemperatureSelect()) && DataDictionaryConstant.TEMPERATURE_ENABLE_YES.equals(strategyBusinessMatchingDTO.getDepartureTemperatureEnable()))) {
				dto.setShowDepartureTemperature(Boolean.TRUE);
			}
			if (dtoList.stream().anyMatch(strategyBusinessMatchingDTO -> DataDictionaryConstant.TEMPERATURE_SELECT_YES.equals(strategyBusinessMatchingDTO.getDeliveryTemperatureSelect()) && DataDictionaryConstant.TEMPERATURE_ENABLE_YES.equals(strategyBusinessMatchingDTO.getDeliveryTemperatureEnable()))) {
				dto.setShowDeliveryTemperature(Boolean.TRUE);
			}
		}
		return dto;
	}

	@Override
	public ShowContainerTemperatureDTO containerTemperature(ShowContainerTemperatureVO vo) {
		ShowContainerTemperatureDTO dto = new ShowContainerTemperatureDTO();
		dto.setShowContainerTemperature(false);
		if (CollectionUtil.isNotEmpty(vo.getContainerIdList())) {
			List<String> shipbillIdList = vo.getShipbillIdList().stream().flatMap(s -> Arrays.stream(s.split(","))).collect(Collectors.toList());
			UserEntity user = PlgFxUsrUtils.getUserEntity();
			List<ContainerDTO> dtoList = mainDataProxy.findContainerByIdList(vo.getContainerIdList().stream().map(Long::parseLong).collect(Collectors.toList()));
			Criteria criteria = Criteria.forClass(TmsShipbillContainerTemp.class);
			Restriction r1 = Restrictions.eq(TmsShipbillContainerTemp::getEnterpriseId, user.getEnterpriseId());
			Restriction r2 = Restrictions.in(TmsShipbillContainerTemp::getShipbillId, shipbillIdList);
			criteria.setRestriction(Restrictions.and(r1, r2));
			List<TmsShipbillContainerTemp> tempList = shipbillContainerTempMapper.findByCriteria(criteria);
			Map<Long, BigDecimal> containerTempMap = tempList.stream().collect(Collectors.toMap(TmsShipbillContainerTemp::getContainerId, TmsShipbillContainerTemp::getDepartureTemp, (t1, t2) -> t2));
			List<ContainerTemperatureDTO> resultDtoList = dtoList.stream().filter(containerDTO ->
					DataDictionaryConstant.CONTAINER_TYPE_3.equals(containerDTO.getType())).map(containerDTO -> {
				ContainerTemperatureDTO containerTemperatureDTO = BeanUtil.copyProperties(containerDTO, ContainerTemperatureDTO.class);
				containerTemperatureDTO.setTemperature(containerTempMap.get(containerTemperatureDTO.getId()));
				return containerTemperatureDTO;
			}).collect(Collectors.toList());
			dto.setDtoList(resultDtoList);
			if (CollectionUtil.isNotEmpty(resultDtoList)) {
				dto.setShowContainerTemperature(true);
			}
		}
		return dto;
	}

	/**
	 * 获取商品明细
	 * 
	 * @param shipBillId
	 * @return
	 */
	private List<AllShipbillItemDetailDTO> getItemDetailDTO(String shipBillId) {
		List<AllShipbillItemDetailDTO> result = Lists.newArrayList();
		Criteria ctr = Criteria.forClass(TmsShipbillDetailModel.class);
		Restriction rt1 = new RestrictionBuilder().eq("shipbillId", shipBillId).build();
		ctr.setRestriction(rt1);
		List<TmsShipbillDetailModel> detailModelList = tmsShipbillDetailMapper.findByCriteria(ctr);
		if (CollectionUtil.isNotEmpty(detailModelList)) {
			Map<Long, ItemCheckDTO> itemCheckDTOMap = mainDataProxy.getItemByIdList(detailModelList.stream().map(TmsShipbillDetailModel::getItemId).distinct().collect(Collectors.toList()));
			result = detailModelList.stream().map(detailModel -> {
				AllShipbillItemDetailDTO detailDTO = new AllShipbillItemDetailDTO();
				BeanUtils.copyProperties(detailModel, detailDTO);
				ItemCheckDTO itemCheckDTO = itemCheckDTOMap.get(detailDTO.getItemId());
				if (ObjectUtil.isNotNull(itemCheckDTO)) {
					detailDTO.setWeight(itemCheckDTO.getWeight());
					detailDTO.setVolume(itemCheckDTO.getVolume());
					detailDTO.setToweight(NumberUtil.mul(detailDTO.getOrigPcs(), detailDTO.getWeight()));
					detailDTO.setTovolume(NumberUtil.mul(detailDTO.getOrigPcs(), detailDTO.getVolume()));
				}
				return detailDTO;
			}).collect(Collectors.toList());
		}
		return result;
	}

	/**
	 * 更新节点图片
	 * 
	 * @param shipBillId
	 * @param nodeEvent
	 * @param picUrl
	 */
	private void updateShipBillNodePic(String shipBillId, String nodeEvent, String picUrl) {
		UserEntity user = PlgFxUsrUtils.getUserEntity();
		do {
			Criteria criteria = Criteria.forClass(ShipbillNodeTracking.class);
			Restriction restriction = new RestrictionBuilder().eq("shipbillId", shipBillId).eq("nodeEvent", nodeEvent).build();
			criteria.setRestriction(restriction);
			List<ShipbillNodeTracking> shipbillNodeTrackingList = tmsShipbillNodeTrackingMapper.findByCriteria(criteria);
			if (CollectionUtil.isNotEmpty(shipbillNodeTrackingList)) {
				shipbillNodeTrackingList.forEach(shipbillNodeTracking -> {
					if (StrUtil.isNotBlank(shipbillNodeTracking.getPicUrl())) {
						shipbillNodeTracking.setPicUrl(shipbillNodeTracking.getPicUrl() + "," + picUrl);
					} else {
						shipbillNodeTracking.setPicUrl(picUrl);
					}
					shipbillNodeTracking.setUpdatetime(new Date());
					shipbillNodeTracking.setUpdateperson(user.getNickname());
					tmsShipbillNodeTrackingMapper.update(shipbillNodeTracking);
				});
			}
			TmsShipbillHeaderModel fatherShipBill = tmsShipbillHeaderMapper.findById(shipBillId, TmsShipbillHeaderModel.class);
			if (ObjectUtil.isNotNull(fatherShipBill)) {
				shipBillId = fatherShipBill.getFatherShipbillId();
			} else {
				shipBillId = StrUtil.EMPTY;
			}
		} while (StrUtil.isNotBlank(shipBillId));
	}

	/**
	 * 更新派车单签收状态
	 * 
	 * @param tmsShipBillHeaderModel
	 */
	private void updateLoadingBillSignInStatus(TmsShipbillHeaderModel tmsShipBillHeaderModel) {
		UserEntity user = PlgFxUsrUtils.getUserEntity();
		List<TmsShipbillHeaderModel> allRelationShipBill = Lists.newArrayList(tmsShipBillHeaderModel);
		String fatherShipBillId = tmsShipBillHeaderModel.getFatherShipbillId();
		while (StrUtil.isNotBlank(fatherShipBillId)) {
			TmsShipbillHeaderModel fatherShipBill = tmsShipbillHeaderMapper.findById(fatherShipBillId, TmsShipbillHeaderModel.class);
			if (ObjectUtil.isNotNull(fatherShipBill)) {
				allRelationShipBill.add(fatherShipBill);
				fatherShipBillId = fatherShipBill.getFatherShipbillId();
			} else {
				fatherShipBillId = StrUtil.EMPTY;
			}
		}
		Map<String, TmsShipbillHeaderModel> allRelationShipBillIdMap = allRelationShipBill.stream().collect(Collectors.toMap(t1 -> t1.getShipbillId(), t2 -> t2, (t1, t2) -> t2));
		Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
		Restriction restriction = new RestrictionBuilder().in("shipbillId", allRelationShipBillIdMap.keySet().toArray()).build();
		criteria.setRestriction(restriction);
		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModelList = tmsLoadingBillDetailMapper.findByCriteria(criteria);
		tmsLoadingBillDetailModelList.forEach(tmsLoadingBillDetailModel -> {
			TmsShipbillHeaderModel tmsShipbillHeaderModel = allRelationShipBillIdMap.get(tmsLoadingBillDetailModel.getShipbillId());
			if (ObjectUtil.isNotNull(tmsShipbillHeaderModel)) {
				tmsLoadingBillDetailModel.setSignInStatus(tmsShipbillHeaderModel.getSignInStatus());
				tmsLoadingBillDetailModel.setUpdateperson(user.getNickname());
				tmsLoadingBillDetailModel.setUpdatetime(new Date());
				tmsLoadingBillDetailMapper.update(tmsLoadingBillDetailModel);
			}
		});
		List<String> loadingBillIdList = tmsLoadingBillDetailModelList.stream().map(TmsLoadingBillDetailModel::getLoadingBillId).distinct().collect(Collectors.toList());
		criteria = Criteria.forClass(TmsLoadingBillHeaderModel.class);
		restriction = new RestrictionBuilder().in("loadingBillId", loadingBillIdList.toArray()).build();
		criteria.setRestriction(restriction);
		List<TmsLoadingBillHeaderModel> tmsLoadingBillHeaderModelList = tmsLoadingBillHeaderMapper.findByCriteria(criteria);
		tmsLoadingBillHeaderModelList.forEach(tmsLoadingBillHeaderModel -> {
			Criteria detailCriteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
			Restriction detailRestriction = new RestrictionBuilder().eq("loadingBillId", tmsLoadingBillHeaderModel.getLoadingBillId()).build();
			detailCriteria.setRestriction(detailRestriction);
			List<TmsLoadingBillDetailModel> detailModelList = tmsLoadingBillDetailMapper.findByCriteria(detailCriteria);
			if (detailModelList.stream().allMatch(detailModel -> SignInStatusEnum.SIGN.getCode().equals(detailModel.getSignInStatus()))) {
				tmsLoadingBillHeaderModel.setSignInStatus(SignInStatusEnum.SIGN.getCode());
			} else {
				tmsLoadingBillHeaderModel.setSignInStatus(SignInStatusEnum.PART.getCode());
			}
			tmsLoadingBillHeaderModel.setUpdateperson(user.getNickname());
			tmsLoadingBillHeaderModel.setUpdatetime(new Date());
			tmsLoadingBillHeaderMapper.update(tmsLoadingBillHeaderModel);
		});
	}

	/**
	 * 更新运单签收状态
	 * 
	 * @param tmsShipBillHeaderModel
	 * @param signInShipBillVO
	 */
	private void updateShipBillSignInStatus(TmsShipbillHeaderModel tmsShipBillHeaderModel, SignInShipBillVO signInShipBillVO) {
		UserEntity user = PlgFxUsrUtils.getUserEntity();
		tmsShipBillHeaderModel.setSignInStatus(SignInStatusEnum.SIGN.getCode());
		tmsShipBillHeaderModel.setUpdateperson(user.getNickname());
		tmsShipBillHeaderModel.setUpdatetime(new Date());
		tmsShipbillHeaderMapper.update(tmsShipBillHeaderModel);
		shipBillLog(tmsShipBillHeaderModel, signInShipBillVO);
		// 递归更新父级运单签收状态
		String fatherShipBillId = tmsShipBillHeaderModel.getFatherShipbillId();
		while (StrUtil.isNotBlank(fatherShipBillId)) {
			TmsShipbillHeaderModel fatherShipBill = tmsShipbillHeaderMapper.findById(fatherShipBillId, TmsShipbillHeaderModel.class);
			if (ObjectUtil.isNotNull(fatherShipBill)) {
				List<TmsShipbillHeaderModel> childShipBillList = getChildTmsShipBillHeaderModel(fatherShipBillId);
				if (childShipBillList.stream().allMatch(childShipBill -> SignInStatusEnum.SIGN.getCode().equals(childShipBill.getSignInStatus()))) {
					fatherShipBill.setSignInStatus(SignInStatusEnum.SIGN.getCode());
					shipBillLog(fatherShipBill, signInShipBillVO);
				} else {
					fatherShipBill.setSignInStatus(SignInStatusEnum.PART.getCode());
				}
				fatherShipBill.setUpdateperson(user.getNickname());
				fatherShipBill.setUpdatetime(new Date());
				tmsShipbillHeaderMapper.update(fatherShipBill);
				fatherShipBillId = fatherShipBill.getFatherShipbillId();
			} else {
				fatherShipBillId = StrUtil.EMPTY;
			}
		}
	}

	/**
	 * 记录运单日志
	 * 
	 * @param tmsShipbillHeaderModel
	 * @param signInShipBillVO
	 */
	private void shipBillLog(TmsShipbillHeaderModel tmsShipbillHeaderModel, SignInShipBillVO signInShipBillVO) {
		UserEntity user = PlgFxUsrUtils.getUserEntity();
		ShipbillNodeTracking shipbillNodeTracking = new ShipbillNodeTracking();
		shipbillNodeTracking.setStatus(tmsShipbillHeaderModel.getStatus());
		shipbillNodeTracking.setNodeEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_QS);
		String id = mainDataProxy.getCodeNumberByCode(SeriaNnumberConstant.TMS_SHIPBILL_NODE_TRACKING_ID);
		shipbillNodeTracking.setId(id);
		shipbillNodeTracking.setShipbillId(tmsShipbillHeaderModel.getShipbillId());
		shipbillNodeTracking.setShipbillNo(tmsShipbillHeaderModel.getShipbillNo());
		shipbillNodeTracking.setNodeDate(new Date());
		shipbillNodeTracking.setUserId(user.getUserid());
		shipbillNodeTracking.setUserName(user.getNickname());
		shipbillNodeTracking.setEnterpriseId(user.getEnterpriseId());
		shipbillNodeTracking.setEnterpriseName(user.getEnterpriseName());
		shipbillNodeTracking.setCreateperson(user.getNickname());
		shipbillNodeTracking.setCreatetime(new Date());
		shipbillNodeTracking.setUpdateperson(user.getNickname());
		shipbillNodeTracking.setUpdatetime(new Date());
		tmsShipbillNodeTrackingMapper.save(shipbillNodeTracking);

		TmsShipbillOperateLogModel tmsShipbillOperateLogModel = new TmsShipbillOperateLogModel();
		tmsShipbillOperateLogModel.setOperateEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_QS);
		tmsShipbillOperateLogModel.setOldStatus(tmsShipbillHeaderModel.getStatus());
		tmsShipbillOperateLogModel.setNewStatus(tmsShipbillHeaderModel.getStatus());
		String operateId = mainDataProxy.getCodeNumberByCode(SeriaNnumberConstant.TMS_SHIPBILL_OPERATE_LOG_ID);
		tmsShipbillOperateLogModel.setId(operateId);
		tmsShipbillOperateLogModel.setShipbillId(tmsShipbillHeaderModel.getShipbillId());
		tmsShipbillOperateLogModel.setShipbillNo(tmsShipbillHeaderModel.getShipbillNo());
		tmsShipbillOperateLogModel.setOperateDate(new Date());
		tmsShipbillOperateLogModel.setUserId(user.getUserid());
		tmsShipbillOperateLogModel.setUserName(user.getNickname());
		tmsShipbillOperateLogModel.setEnterpriseId(user.getEnterpriseId());
		tmsShipbillOperateLogModel.setEnterpriseName(user.getEnterpriseName());
		tmsShipbillOperateLogModel.setCreateperson(user.getNickname());
		tmsShipbillOperateLogModel.setCreatetime(new Date());
		tmsShipbillOperateLogModel.setUpdateperson(user.getNickname());
		tmsShipbillOperateLogModel.setUpdatetime(new Date());
		tmsShipbillOperateLogMapper.save(tmsShipbillOperateLogModel);

		Criteria criteria = Criteria.forClass(TmsShipbillTransLogModel.class);
		Restriction r1 = Restrictions.eq(TmsShipbillTransLogModel::getShipbillId, tmsShipbillHeaderModel.getShipbillId());
		Restriction r2 = Restrictions.eq(TmsShipbillTransLogModel::getEnterpriseId, tmsShipbillHeaderModel.getEnterpriseId());
		criteria.setRestriction(Restrictions.and(r1, r2));
		List<TmsShipbillTransLogModel> logModelList = tmsShipbillTransportLogMapper.findByCriteria(criteria);
		TmsShipbillTransLogModel dbLogModel = logModelList.get(0);
		dbLogModel.setSignInTime(new Date());
		dbLogModel.setSignInPerson(signInShipBillVO.getSignPerson());
		dbLogModel.setUpdateperson(user.getNickname());
		dbLogModel.setUpdatetime(new Date());
		tmsShipbillTransportLogMapper.update(dbLogModel);
	}

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

	/**
	 * 通过运单和商品id找运单明细
	 * 
	 * @param shipBillIdList
	 * @param itemIdList
	 * @return
	 */
	private List<TmsShipbillDetailModel> getTmsShipBillDetailModel(List<String> shipBillIdList, List<Long> itemIdList) {
		Criteria criteria = Criteria.forClass(TmsShipbillDetailModel.class);
		Restriction restriction = new RestrictionBuilder().in("shipbillId", shipBillIdList.toArray()).in("itemId", itemIdList.toArray()).build();
		criteria.setRestriction(restriction);
		return tmsShipbillDetailMapper.findByCriteria(criteria);
	}

	/**
	 * 判断是否需要自动退
	 * 
	 * @param returnType
	 * @return
	 */
	private Boolean autoReturn(String returnType) {
		String handleType = getHandleType(returnType);
		return ShipBillReturnTypeEnum.S.getCode().equals(returnType) ? ArriveNotequalDeliveryHandleTypeEnum.AUTO_CREATE.getCode().equals(handleType) : SigninNotequalDeliveryHandleTypeEnum.AUTO_CREATE.getCode().equals(handleType);
	}

	/**
	 * 送达数量不等于配送数量处理方式
	 * 
	 * @return
	 */
	private String getHandleType(String returnType) {
		String sysParamName = ShipBillReturnTypeEnum.S.getCode().equals(returnType) ? ArriveNotequalDeliveryHandleTypeEnum.ENUM_NAME : SigninNotequalDeliveryHandleTypeEnum.ENUM_NAME;
		SysParamConfigModel sysParamConfig;
		try {
			RestMessage<SysParamConfigModel> restMessage = maindataTmsResource.getValue(sysParamName);
			if (!restMessage.isSuccess()) {
				throw new BizException(restMessage.getMessage());
			}
			sysParamConfig = restMessage.getData();
		} catch (Exception e) {
			throw new BizException(e.getMessage());
		}
		if (ToolKits.isEmpty(sysParamConfig)) {
			throw new BizException("系统参数【" + sysParamName + "】查询失败");
		}
		String handleType = sysParamConfig.getValue();
		if (StrUtil.isBlank(handleType)) {
			throw new BizException("系统参数【" + sysParamName + "】参数值");
		}
		return handleType;
	}

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

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

		logModel.setOrderDt(date);
		if (DataDictionaryConstant.ACTION_COMMIT.equals(act)) {
			logModel.setCommitDt(date);
		}
		logModel.setEstimatedPickupStartTime(pickUpStartDt);
		logModel.setEnterpriseId(user.getEnterpriseId());
		logModel.setEnterpriseName(user.getEnterpriseName());
		logModel.setCreateperson(user.getNickname());
		logModel.setCreatetime(date);
		logModel.setUpdateperson(user.getNickname());
		logModel.setUpdatetime(date);

		tmsShipbillTransportLogMapper.save(logModel);
	}
}
