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

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
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 org.springframework.util.Assert;

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.app.constant.BussinessConstant;
import com.prolog.rdc.tms.app.constant.DataDictionaryConstant;
import com.prolog.rdc.tms.app.dao.mapper.TmsAppointmentDetailMapper;
import com.prolog.rdc.tms.app.dao.mapper.TmsAppointmentHeaderMapper;
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.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.TmsShipbillPackageMapper;
import com.prolog.rdc.tms.app.dao.mapper.TmsShipbillTransportLogMapper;
import com.prolog.rdc.tms.app.model.dto.business.DispatchCheckPackageDTO;
import com.prolog.rdc.tms.app.model.dto.business.DispatchCheckQueryDTO;
import com.prolog.rdc.tms.app.model.dto.business.DispatchCheckShipBillDtlDTO;
import com.prolog.rdc.tms.app.model.dto.business.SendCarQueryDTO;
import com.prolog.rdc.tms.app.model.entity.ShipbillNodeTracking;
import com.prolog.rdc.tms.app.model.entity.TmsAppointmentDetailModel;
import com.prolog.rdc.tms.app.model.entity.TmsAppointmentHeaderModel;
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.TmsShipbillDetailModel;
import com.prolog.rdc.tms.app.model.entity.TmsShipbillHeaderModel;
import com.prolog.rdc.tms.app.model.entity.TmsShipbillPackageModel;
import com.prolog.rdc.tms.app.model.entity.TmsShipbillTransLogModel;
import com.prolog.rdc.tms.app.model.vo.SendCarUndoAuditVO;
import com.prolog.rdc.tms.app.model.vo.business.SendCarDeleteDetailVO;
import com.prolog.rdc.tms.app.model.vo.business.SendCarQueryVO;
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.ShipbillQueryVO;
import com.prolog.rdc.tms.app.service.business.LoadingBillService;
import com.prolog.rdc.tms.app.service.business.SendCarService;
import com.prolog.rdc.tms.app.service.business.ShipbillNodeTrackingService;
import com.prolog.rdc.tms.app.service.business.ShipbillOperateLogService;
import com.prolog.rdc.tms.app.util.BusinessFlowUtil;
import com.prolog.rdc.tms.app.util.CommonUtil;
import com.prolog.rdc.tms.app.util.ConvertorUtil;
import com.prolog.rdc.tms.app.util.MessageUtil;
import com.prolog.rdc.tms.model.dto.message.SendMessageDTO;
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.ApprovalOpenVO;
import com.prolog.rdc.tms.rmi.feign.MaindataFeign;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;

/**
 * 已派车实现层
 *
 * @author zhangsj
 * @since 2022-04-13 14:32:31
 */
@Service
public class SendCarServiceImpl implements SendCarService {

	@Autowired
	private TmsLoadingBillHeaderMapper tmsLoadingBillHeaderMapper;

	@Autowired
	private TmsLoadingBillDetailMapper tmsLoadingBillDetailMapper;

	@Autowired
	private MaindataFeign maindataTmsResource;

	@Autowired
	private TmsShipbillHeaderMapper tmsShipbillHeaderMapper;

	@Autowired
	private ShipbillOperateLogService shipbillOperateLogService;

	@Autowired
	private ShipbillNodeTrackingService shipbillNodeTrackingService;

	@Autowired
	private TmsShipbillNodeTrackingMapper tmsShipbillNodeTrackingMapper;

	@Autowired
	private BusinessFlowUtil businessFlowUtil;

	@Autowired
	private TmsShipbillTransportLogMapper tmsShipbillTransportLogMapper;

	@Autowired
	private TmsShipbillDetailMapper tmsShipbillDetailMapper;

	@Autowired
	private TmsShipbillPackageMapper tmsShipbillPackageMapper;

	@Autowired
	private LoadingBillService loadingBillService;

	@Autowired
	private TmsAppointmentHeaderMapper tmsAppointmentHeaderMapper;

	@Autowired
	private TmsAppointmentDetailMapper tmsAppointmentDetailMapper;

	@Autowired
	private ConvertorUtil convertorUtil;

	@Autowired
	private CommonUtil commonUtil;



	/**
	 * 已派车查询
	 *
	 * @param sendCarVO
	 * @return
	 */
	@SuppressWarnings("resource")
	@Override
	public Page<SendCarQueryDTO> loadingBillQuery(SendCarQueryVO sendCarVO) {
		ToolKits.isParamNull(sendCarVO, "已派车查询请求不为空");
		ToolKits.isParamNull(sendCarVO.getPageNum(), "当前页码不为空");
		ToolKits.isParamNull(sendCarVO.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<SysRefdatadModel> dicData = convertorUtil.getDictionary(new String[] {
				DataDictionaryConstant.LOADING_BILL_STATUS, // 派车单状态
				DataDictionaryConstant.APPOINTMENT_STATUS, // 预约单状态
				DataDictionaryConstant.TALLY_STATUS,// 理货状态
				DataDictionaryConstant.VEHICLE_TYPE_CATEGORY,// 车辆类别
				DataDictionaryConstant.VEHICLE_TYPE
		});

		// 添加查询条件
		Criteria criteria = Criteria.forClass(TmsLoadingBillHeaderModel.class);
		Restriction r1 = ToolKits.isEmpty(sendCarVO.getCreateStartTime()) ? null : Restrictions.ge(TmsLoadingBillHeaderModel::getCreatetime, sendCarVO.getCreateStartTime());
		Restriction r2 = ToolKits.isEmpty(sendCarVO.getCreateEndTime()) ? null : Restrictions.le(TmsLoadingBillHeaderModel::getCreatetime, sendCarVO.getCreateEndTime());
		Restriction r3 = Restrictions.eq(TmsLoadingBillHeaderModel::getCarrierType, DataDictionaryConstant.LINE_CARRIER_TYPE_SJ);
		Restriction r4 = null;
		r4 = Restrictions.eq(TmsLoadingBillHeaderModel::getEnterpriseId, user.getEnterpriseId());
		Restriction r5 = null;
		if (user.getUserType().equals(BussinessConstant.USER_TYPE_ZY)) {
			r5 = Restrictions.eq(TmsLoadingBillHeaderModel::getScheduleType, DataDictionaryConstant.SCHEDULE_TYPE_ZY);
		} else {
			r5 = Restrictions.eq(TmsLoadingBillHeaderModel::getScheduleType, DataDictionaryConstant.SCHEDULE_TYPE_CYS);
		}
		Restriction r6 = ToolKits.isEmpty(sendCarVO.getLoadingBillNo()) ? null : Restrictions.eq(TmsLoadingBillHeaderModel::getLoadingBillNo, sendCarVO.getLoadingBillNo());
		criteria.setRestriction(Restrictions.and(r1, r2, r3, r4, r5, r6));
		criteria.setOrder(Order.newInstance().desc(new String[] { "updatetime" }));

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

		Map<String, TmsAppointmentHeaderModel> loadingAppointMap = Maps.newHashMap();
		if (CollectionUtil.isNotEmpty(tmsLoadingBillHeaderModels)) {
			List<String> loadingBillIdList = tmsLoadingBillHeaderModels.stream().map(TmsLoadingBillHeaderModel::getLoadingBillId).collect(Collectors.toList());
			Criteria appointDetailCriteria = Criteria.forClass(TmsAppointmentDetailModel.class);
			Restriction appointDetailRestriction = Restrictions.in(TmsAppointmentDetailModel::getLoadingBillId, loadingBillIdList.toArray());
			appointDetailCriteria.setRestriction(appointDetailRestriction);
			List<TmsAppointmentDetailModel> tmsAppointmentDetailModelList = tmsAppointmentDetailMapper.findByCriteria(appointDetailCriteria);
			Map<String, String> loadingAppointIdMap =
					tmsAppointmentDetailModelList.stream().collect(Collectors.toMap(t1 -> t1.getLoadingBillId(),
							t2 -> t2.getAppointmentId(), (t1, t2) -> t2));
			List<String> appointmentIdList = tmsAppointmentDetailModelList.stream().map(TmsAppointmentDetailModel::getAppointmentId).collect(Collectors.toList());
			Criteria appointCriteria = Criteria.forClass(TmsAppointmentHeaderModel.class);
			Restriction appointRestriction = Restrictions.in(TmsAppointmentHeaderModel::getAppointmentId, appointmentIdList.toArray());
			appointCriteria.setRestriction(appointRestriction);
			List<TmsAppointmentHeaderModel> tmsAppointmentHeaderModelList = tmsAppointmentHeaderMapper.findByCriteria(appointCriteria);
			Map<String, TmsAppointmentHeaderModel> appointMap =
					tmsAppointmentHeaderModelList.stream().collect(Collectors.toMap(t1 -> t1.getAppointmentId(),
							t2 -> t2, (t1, t2) -> t2));
			loadingAppointIdMap.forEach((key, value) -> loadingAppointMap.put(key, appointMap.get(value)));
		}

		List<SendCarQueryDTO> sendCarDTOS = Lists.newArrayList();
		for (TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel : tmsLoadingBillHeaderModels) {
			SendCarQueryDTO dto = new SendCarQueryDTO();
			BeanUtils.copyProperties(tmsLoadingBillHeaderModel, dto);
			dto.setVehicleAscriptionName(ConvertorUtil.getName(dicData, DataDictionaryConstant.VEHICLE_TYPE, String.valueOf(dto.getVehicleAscription())));
			dto.setStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.LOADING_BILL_STATUS, String.valueOf(dto.getStatus())));
			dto.setVehicleTypeCategoryName(ConvertorUtil.getName(dicData, DataDictionaryConstant.VEHICLE_TYPE_CATEGORY, String.valueOf(dto.getVehicleTypeCategory())));
			TmsAppointmentHeaderModel appointmentHeaderModel = loadingAppointMap.get(tmsLoadingBillHeaderModel.getLoadingBillId());
			if (Objects.nonNull(appointmentHeaderModel)) {
				dto.setAppointStatus(appointmentHeaderModel.getStatus());
				dto.setAppointTallyStatus(appointmentHeaderModel.getTallyStatus());
				dto.setAppointStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.APPOINTMENT_STATUS, String.valueOf(dto.getAppointStatus())));
				dto.setAppointTallyStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.TALLY_STATUS, String.valueOf(dto.getAppointTallyStatus())));
			}
			Criteria loadDetailCriteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
			Restriction loadDetailRestriction = Restrictions.eq(TmsLoadingBillDetailModel::getLoadingBillId, tmsLoadingBillHeaderModel.getLoadingBillId());
			loadDetailCriteria.setRestriction(loadDetailRestriction);
			List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModelList = tmsLoadingBillDetailMapper.findByCriteria(loadDetailCriteria);
			dto.setShipBillIdList(tmsLoadingBillDetailModelList.stream().
					filter(model -> StrUtil.isNotBlank(model.getShipbillId())).
					map(TmsLoadingBillDetailModel::getShipbillId).distinct().collect(Collectors.joining(",")));
			dto.setColdShipBillIdList(tmsLoadingBillDetailModelList.stream().
					filter(model -> ObjectUtil.isNotNull(model.getTemperatureRequirement()) &&
							!DataDictionaryConstant.TEMPERATURE_REQUIREMENT_CW.equals(model.getTemperatureRequirement()) &&
							StrUtil.isNotBlank(model.getShipbillId())).
					map(TmsLoadingBillDetailModel::getShipbillId).distinct().collect(Collectors.joining(",")));
			dto.setUrgentShipBillIdList(tmsLoadingBillDetailModelList.stream().
					filter(model -> ObjectUtil.isNotNull(model.getOrderType()) &&
							!DataDictionaryConstant.ORDER_TYPE_P.equals(model.getOrderType()) &&
							StrUtil.isNotBlank(model.getShipbillId())).
					map(TmsLoadingBillDetailModel::getShipbillId).distinct().collect(Collectors.joining(",")));
			sendCarDTOS.add(dto);
		}
		// 分页重组
		Page<SendCarQueryDTO> page = PageUtils.getPage(sendCarDTOS);
		if (tmsLoadingBillHeaderModels instanceof com.github.pagehelper.Page) {
			com.github.pagehelper.Page<TmsLoadingBillHeaderModel> p0 = (com.github.pagehelper.Page<TmsLoadingBillHeaderModel>) tmsLoadingBillHeaderModels;
			page.setPageCount(p0.getPages());
			page.setPageNum(p0.getPageNum());
			page.setPageSize(p0.getPageSize());
			page.setTotalCount(p0.getTotal());
			page.setStartRow(p0.getStartRow());
			page.setEndRow(p0.getEndRow());
		}
		return page;
	}

	/**
	 * 已派车运单撤销
	 *
	 * @param ids
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void sendcarUndoData(List<String> ids) {
		ToolKits.isParamNull(ids, "派车单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, ids.toArray(), null);

		int size = tmsLoadingBillHeaderModels.stream().filter(m -> m.getStatus().intValue() > DataDictionaryConstant.LOADING_BILL_STATUS_WSH.intValue()).collect(Collectors.toList()).size();
		if (size > 0) {
			throw new PrologException("派车单已审核，不能撤销");
		}
		// 查询明细内容
		Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
		Restriction r1 = Restrictions.in(TmsLoadingBillDetailModel::getLoadingBillId, ids.toArray());
		criteria.setRestriction(r1);

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

		for (TmsLoadingBillDetailModel tmsLoadingBillDetailModel : tmsLoadingBillDetailModels) {

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

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

				tmsShipbillHeaderModel.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_REVIEW);

				shipbillOperateLogSaveVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_REVOKE_SEND_CAR);
				shipbillOperateLogSaveVO.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH);
				shipbillOperateLogSaveVO.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_REVIEW);

				r4 = Restrictions.eq("status", DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH);
			} else {
				Assert.isTrue(tmsShipbillHeaderModel.getCarrierShipbillStatus().intValue() <= DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED.intValue(), "当前已调度审核不可回退");

				tmsShipbillHeaderModel.setCarrierShipbillStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_AUDITED);

				shipbillOperateLogSaveVO.setOperateEvent(DataDictionaryConstant.CARRIER_SHIPBILL_STATUSNAME_REVOKE_SEND_CAR);
				shipbillOperateLogSaveVO.setOldStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED);
				shipbillOperateLogSaveVO.setNewStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_AUDITED);
				r4 = Restrictions.eq("status", DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED);
			}
			tmsShipbillHeaderModel.setUpdatetime(DateUtil.date());
			tmsShipbillHeaderModel.setUpdateperson(user.getNickname());
			tmsShipbillHeaderMapper.update(tmsShipbillHeaderModel);

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

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

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

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

	}

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

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

		autoSendcarAuditData(ids, user, date);
	}

	/**
	 * 自动已派车审核
	 *
	 * @param ids
	 */
	public void autoSendcarAuditData(List<String> ids, UserEntity user, Date date) {

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

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

		if (ToolKits.isNotEmpty(str)) {
			throw new RuntimeException("托运单[" + str + "]不是待审核状态,不能调度审核!");
		}

		List<String> loadingBillIds = Lists.newArrayList();
		for (TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel : tmsLoadingBillHeaderModels) {
			if (user.getUserType().equals(BussinessConstant.USER_TYPE_ZY)) {
				if (DataDictionaryConstant.SCHEDULE_TYPE_CYS.equals(tmsLoadingBillHeaderModel.getScheduleType())) {
					throw new RuntimeException("派车单类型只能为自有");
				}
			} else {
				if (DataDictionaryConstant.SCHEDULE_TYPE_ZY.equals(tmsLoadingBillHeaderModel.getScheduleType())) {
					throw new RuntimeException("派车单类型只能为承运商");
				}
			}

			// 反审核的派车单跳过运单处理
			if (ToolKits.isEmpty(tmsLoadingBillHeaderModel.getOldStatus())) {
				Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
				Restriction r1 = Restrictions.eq("loadingBillId", tmsLoadingBillHeaderModel.getLoadingBillId());
				criteria.setRestriction(r1);
				List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteria);

				int shipperTypeCnt = 0;
				int consigneeType = 0;
				Boolean matched = false;

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

				for (TmsLoadingBillDetailModel detailModel : tmsLoadingBillDetailModels) {

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

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

					if (!matched) {
						// 没有匹配到调度审核流程
						if (user.getUserType().equals(BussinessConstant.USER_TYPE_ZY)) {
							// 自有账号
							// 判定下一步流程
							int status = businessFlowUtil.judgmentNextFlowSts(detailModel.getFlowConfig(), DataDictionaryConstant.FLOW_CONFIG_CHECK);

							mapUpdateLoadingDetail.put("status", status);
							mapUpdateShipbillHeader.put("status", status);
							shipbillNodeTrackingSaveVO.setStatus(status);
							shipbillNodeTrackingSaveVO.setNodeEvent(DataDictionaryConstant.SHIPBILL_NODE_STATUSNAME_PC);
							shipbillOperateLogSaveVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_NODE_STATUSNAME_PC);
							shipbillOperateLogSaveVO.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH);
							shipbillOperateLogSaveVO.setNewStatus(status);

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

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

							mapUpdateShipbillHeader.put("status", status);
							mapUpdateShipbillHeader.put("carrierShipbillStatus", DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED_CHECK);
							shipbillNodeTrackingSaveVO.setStatus(status);
							shipbillOperateLogSaveVO.setOldStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED);
							shipbillOperateLogSaveVO.setNewStatus(status);

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

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

					} else {
						// 匹配到调度审核流程
						if (user.getUserType().equals(BussinessConstant.USER_TYPE_ZY)) {
							// 自有账号
							mapUpdateLoadingDetail.put("status", DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH_CHECK_APPROVAL);
							mapUpdateShipbillHeader.put("status", DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH_CHECK_APPROVAL);
							shipbillNodeTrackingSaveVO.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH_CHECK_APPROVAL);
							shipbillNodeTrackingSaveVO.setNodeEvent(DataDictionaryConstant.SHIPBILL_NODE_STATUSNAME_DIS_APPROVAL);
							shipbillOperateLogSaveVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_NODE_STATUSNAME_DIS_APPROVAL);
							shipbillOperateLogSaveVO.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH);
							shipbillOperateLogSaveVO.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH_CHECK_APPROVAL);

						} else if (user.getUserType().equals(BussinessConstant.USER_TYPE_CYS)) {
							// 承运商账号
							mapUpdateLoadingDetail.put("carrierShipbillStatus", DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED_APPROVAL);
							mapUpdateShipbillHeader.put("carrierShipbillStatus", DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED_APPROVAL);
							shipbillNodeTrackingSaveVO.setStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED_APPROVAL);
							shipbillOperateLogSaveVO.setOldStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED);
							shipbillOperateLogSaveVO.setNewStatus(DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED_APPROVAL);

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

					// 新增日志信息
					shipbillOperateLogSaveVO.setShipbillId(detailModel.getShipbillId());
					shipbillOperateLogSaveVO.setShipbillNo(detailModel.getShipbillNo());
					shipbillOperateLogSaveVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_NODE_STATUSNAME_PC);
					shipbillOperateLogService.addShipbillOperateLogData(shipbillOperateLogSaveVO);
				}
				// 更改派车单状态
				// 装车单类型
				if (shipperTypeCnt == tmsLoadingBillDetailModels.size()) {
					tmsLoadingBillHeaderModel.setLoadingBillType(DataDictionaryConstant.LOADING_BILL_TYPE_CK);
				} else if (consigneeType == tmsLoadingBillDetailModels.size()) {
					tmsLoadingBillHeaderModel.setLoadingBillType(DataDictionaryConstant.LOADING_BILL_TYPE_RK);
				} else {
					tmsLoadingBillHeaderModel.setLoadingBillType(DataDictionaryConstant.LOADING_BILL_TYPE_QT);
				}
				tmsLoadingBillHeaderModel.setUpdateperson(user.getNickname());
				tmsLoadingBillHeaderModel.setUpdatetime(date);
				tmsLoadingBillHeaderMapper.update(tmsLoadingBillHeaderModel);

				loadingBillIds.add(tmsLoadingBillHeaderModel.getLoadingBillId());
			} else {
				tmsLoadingBillHeaderModel.setStatus(tmsLoadingBillHeaderModel.getOldStatus());
				tmsLoadingBillHeaderModel.setOldStatus(null);
				tmsLoadingBillHeaderModel.setUpdateperson(user.getNickname());
				tmsLoadingBillHeaderModel.setUpdatetime(date);
				tmsLoadingBillHeaderMapper.update(tmsLoadingBillHeaderModel);
			}

			MessageTypeEnum messageTypeEnum = MessageTypeEnum.SELF_DISPATCH_AUDIT;
			if (user.getUserType().equals(BussinessConstant.USER_TYPE_CYS)) {
				messageTypeEnum = MessageTypeEnum.CARRIER_DISPATCH_AUDIT;
			}
			MessageUtil.addMessage(new SendMessageDTO(MessageOrderTypeEnum.LOADING_NO.getCode(), messageTypeEnum.getCode(), Lists.newArrayList(tmsLoadingBillHeaderModel.getLoadingBillId())));
		}

		loadingBillService.updateStationByLoadingBillIdList(loadingBillIds);
	}

	/**
	 * 运单查询
	 *
	 * @param shipbillQueryVO
	 */
	@SuppressWarnings("resource")
	public Page<DispatchCheckQueryDTO> shipbillQuery(ShipbillQueryVO shipbillQueryVO) {
		ToolKits.isParamNull(shipbillQueryVO, "待调度查询请求不为空");
		ToolKits.isParamNull(shipbillQueryVO.getPageNum(), "当前页码不为空");
		ToolKits.isParamNull(shipbillQueryVO.getPageSize(), "每页条数不为空");
		ToolKits.isParamNull(shipbillQueryVO.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, "当前人员没有操作权限");
		}

		// 添加查询条件
		Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
//		Restriction r1 = Restrictions.eq(TmsLoadingBillDetailModel::getLoadingBillId, shipbillQueryVO.getLoadingBillId());
//		criteria.setRestriction(Restrictions.and(r1));

		Restriction r1 = null;
		if (StrUtil.isNotBlank(shipbillQueryVO.getLoadingBillId())) {
			r1 = Restrictions.eq(TmsLoadingBillDetailModel::getLoadingBillId, shipbillQueryVO.getLoadingBillId());
		}
		Restriction r2 = null;
		if (StrUtil.isNotBlank(shipbillQueryVO.getShipBillIdList())) {
			r2 = Restrictions.in(TmsLoadingBillDetailModel::getShipbillId, shipbillQueryVO.getShipBillIdList().split(","));
		}
		criteria.setRestriction(Restrictions.and(r1,r2));

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

		// 响应对象集合
		List<DispatchCheckQueryDTO> pendingDispatchDTOs = Lists.newArrayList();

		for (TmsLoadingBillDetailModel loadingBillDetailModel : tmsLoadingBillDetailModels) {
			DispatchCheckQueryDTO pendingDispatchDTO = new DispatchCheckQueryDTO();
			BeanUtils.copyProperties(loadingBillDetailModel, pendingDispatchDTO);

			StringBuffer consigneeProvinceCityDistrict = new StringBuffer();
			// 目的地
			consigneeProvinceCityDistrict.append(ToolKits.isEmpty(loadingBillDetailModel.getConsigneeProvinceName()) ? "" : loadingBillDetailModel.getConsigneeProvinceName());
			consigneeProvinceCityDistrict.append(ToolKits.isEmpty(loadingBillDetailModel.getConsigneeCityName()) ? "" : loadingBillDetailModel.getConsigneeCityName());
			consigneeProvinceCityDistrict.append(ToolKits.isEmpty(loadingBillDetailModel.getConsigneeDistrictName()) ? "" : loadingBillDetailModel.getConsigneeDistrictName());
			pendingDispatchDTO.setConsigneeProvinceCityDistrict(consigneeProvinceCityDistrict.toString());
			// 始发地
			StringBuffer shipperProvinceCityDistrict = new StringBuffer();
			shipperProvinceCityDistrict.append(ToolKits.isEmpty(loadingBillDetailModel.getShipperProvinceName()) ? "" : loadingBillDetailModel.getShipperProvinceName());
			shipperProvinceCityDistrict.append(ToolKits.isEmpty(loadingBillDetailModel.getShipperCityName()) ? "" : loadingBillDetailModel.getShipperCityName());
			shipperProvinceCityDistrict.append(ToolKits.isEmpty(loadingBillDetailModel.getShipperDistrictName()) ? "" : loadingBillDetailModel.getShipperDistrictName());
			pendingDispatchDTO.setShipperProvinceCityDistrict(shipperProvinceCityDistrict.toString());

			// 发货方类型
			if (DataDictionaryConstant.SHIPPER_TYPE_KH.equals(pendingDispatchDTO.getShipperType())) {
				// 发货方名称
				pendingDispatchDTO.setShipperName(pendingDispatchDTO.getShipperUnitName() + DataDictionaryConstant.Line_SYMBOL + pendingDispatchDTO.getShipperName());
			}

			// 收货方电话
			StringBuffer tel = new StringBuffer();
			if (ToolKits.isNotEmpty(pendingDispatchDTO.getConsigneeLandlineNumber()) && ToolKits.isNotEmpty(pendingDispatchDTO.getConsigneePhoneNumber())) {
				tel.append(pendingDispatchDTO.getConsigneeLandlineNumber());
				tel.append(DataDictionaryConstant.Line_SYMBOL);
				tel.append(pendingDispatchDTO.getConsigneePhoneNumber());
			} else if (ToolKits.isNotEmpty(pendingDispatchDTO.getConsigneeLandlineNumber())) {
				tel.append(pendingDispatchDTO.getConsigneeLandlineNumber());
			} else if (ToolKits.isNotEmpty(pendingDispatchDTO.getConsigneePhoneNumber())) {
				tel.append(pendingDispatchDTO.getConsigneePhoneNumber());
			}
			if (ToolKits.isNotEmpty(tel.toString())) {
				pendingDispatchDTO.setConsigneeTel(tel.toString());
			}
			// 收货方类型
			if (DataDictionaryConstant.CONSIGNEE_TYPE_KH.equals(pendingDispatchDTO.getConsigneeType())) {
				// 收货方名称
				pendingDispatchDTO.setConsigneeName(pendingDispatchDTO.getConsigneeUnitName() + DataDictionaryConstant.Line_SYMBOL + pendingDispatchDTO.getConsigneeName());
			} else if (DataDictionaryConstant.CONSIGNEE_TYPE_GYS.equals(pendingDispatchDTO.getConsigneeType())) {
				// 收货方名称
				pendingDispatchDTO.setConsigneeName(pendingDispatchDTO.getConsigneeName() + DataDictionaryConstant.Line_SYMBOL + pendingDispatchDTO.getShipperName());
			}

			// 获取包裹信息
			Criteria criteriaPkg = Criteria.forClass(TmsShipbillPackageModel.class);
			Restriction r29 = Restrictions.eq(TmsShipbillPackageModel::getShipbillId, pendingDispatchDTO.getShipbillId());
			Restriction r30 = Restrictions.eq(TmsShipbillPackageModel::getEnterpriseId, user.getEnterpriseId());
			criteriaPkg.setRestriction(Restrictions.and(r29, r30));
			criteriaPkg.setOrder(Order.newInstance().desc(new String[] { "updatetime" }));

			List<TmsShipbillPackageModel> tmsShipbillPackageModels = tmsShipbillPackageMapper.findByCriteria(criteriaPkg);

			List<DispatchCheckPackageDTO> loadingPackageDTOList = Lists.newArrayList();
			for (TmsShipbillPackageModel packageModel : tmsShipbillPackageModels) {
				DispatchCheckPackageDTO packageDTO = new DispatchCheckPackageDTO();
				BeanUtils.copyProperties(packageModel, packageDTO);
				loadingPackageDTOList.add(packageDTO);
			}
			pendingDispatchDTO.setDisPackageDTOS(loadingPackageDTOList);

			if (loadingPackageDTOList.size() == 0) {
				// 获取商品信息
				Criteria criteriaDetail = Criteria.forClass(TmsShipbillDetailModel.class);
				criteriaDetail.setRestriction(Restrictions.and(r29, r30));
				criteriaDetail.setOrder(Order.newInstance().desc(new String[] { "updatetime" }));
				List<TmsShipbillDetailModel> tmsShipbillDetailModels = tmsShipbillDetailMapper.findByCriteria(criteriaDetail);

				List<DispatchCheckShipBillDtlDTO> detailDTOList = Lists.newArrayList();
				for (TmsShipbillDetailModel detailModel : tmsShipbillDetailModels) {
					DispatchCheckShipBillDtlDTO detailDTO = new DispatchCheckShipBillDtlDTO();
					BeanUtils.copyProperties(detailModel, detailDTO);
					detailDTOList.add(detailDTO);
				}
				// 商品信息
				pendingDispatchDTO.setShipBillDetailDTOS(detailDTOList);
			}
			pendingDispatchDTOs.add(pendingDispatchDTO);
		}
		// 分页重组
		Page<DispatchCheckQueryDTO> page = PageUtils.getPage(pendingDispatchDTOs);
		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;
	}

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

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

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

	/**
	 * 已派车配载运单剔除
	 *
	 * @param sendCarDeleteDetailVO
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void deleteDetailSendCarData(SendCarDeleteDetailVO sendCarDeleteDetailVO) {
		ToolKits.isParamNull(sendCarDeleteDetailVO.getLoadingBillId(), "派车单ID不为空");
		ToolKits.isParamNull(sendCarDeleteDetailVO.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, "当前人员没有操作权限");
		}
		TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel = tmsLoadingBillHeaderMapper.findById(sendCarDeleteDetailVO.getLoadingBillId(), TmsLoadingBillHeaderModel.class);
		if (ToolKits.isEmpty(tmsLoadingBillHeaderModel)) {
			throw new PrologException(StrUtil.format("派车单{}不存在",sendCarDeleteDetailVO.getLoadingBillId()));
		}

		Assert.isTrue(ToolKits.isEmpty(tmsLoadingBillHeaderModel.getOldStatus()), "反审核派车单【" + tmsLoadingBillHeaderModel.getLoadingBillId() + "】不能剔除运单！");

		if (ToolKits.isEmpty(tmsLoadingBillHeaderModel.getStatus()) || DataDictionaryConstant.LOADING_BILL_STATUS_ZC_CONFIRM.intValue() < tmsLoadingBillHeaderModel.getStatus().intValue()  ) {
			throw new PrologException(StrUtil.format("派车单{}已启运，请不要剔除运单", sendCarDeleteDetailVO.getLoadingBillId()));
		}
		Date date = DateUtil.date();
		Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
		Restriction r1 = Restrictions.eq(TmsLoadingBillDetailModel::getLoadingBillId, sendCarDeleteDetailVO.getLoadingBillId());
		Restriction r2 = Restrictions.in(TmsLoadingBillDetailModel::getShipbillId, sendCarDeleteDetailVO.getShipbillIds().stream().toArray());
		criteria.setRestriction(Restrictions.and(r1,r2));
		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteria);

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

			// 修改配送顺序
			r1 = Restrictions.eq("loadingBillId", tmsLoadingBillDetailModel.getLoadingBillId());
			r2 = Restrictions.ne("shipbillId", tmsLoadingBillDetailModel.getShipbillId());
			criteria.setRestriction(Restrictions.and(r1, r2));
			List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModelList = tmsLoadingBillDetailMapper.findByCriteria(criteria);

			/*// 客户数
			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);
		}

		// 重新计算
		calculateLoadingData(tmsLoadingBillHeaderModel);

		// 计算装载率
		if (ToolKits.isNotEmpty(tmsLoadingBillHeaderModel.getVehicleId())) {
			Map<String, String> map = commonUtil.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", sendCarDeleteDetailVO.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 tmsLoadingBillHeaderModel
	 * @return
	 */
	private void calculateLoadingData(TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel) {
		// 重新计算
		Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
		Restriction r1 = Restrictions.eq(TmsLoadingBillDetailModel::getLoadingBillId, tmsLoadingBillHeaderModel.getLoadingBillId());
		criteria.setRestriction(Restrictions.and(r1));
		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModelList = tmsLoadingBillDetailMapper.findByCriteria(criteria);
		if (ToolKits.isEmpty(tmsLoadingBillDetailModelList)) {
			// 货主数
			tmsLoadingBillHeaderModel.setCargoOwnerNumber(Long.valueOf(0));
			// 客户数
			tmsLoadingBillHeaderModel.setCustomerNumber(0);
			// 运单数
			tmsLoadingBillHeaderModel.setShipbillNumber(0);
			// 总提货点数
			tmsLoadingBillHeaderModel.setPickupStations(Long.valueOf(0));
			// 总配送点数
			tmsLoadingBillHeaderModel.setDeliveryStations(Long.valueOf(0));
			// 总站数
			tmsLoadingBillHeaderModel.setTotalStations(Long.valueOf(0));
			tmsLoadingBillHeaderModel.setSiteNumber(tmsLoadingBillHeaderModel.getTotalStations().intValue());
			// 冷链运单数
			tmsLoadingBillHeaderModel.setColdShipbillNumber(Long.valueOf(0));

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

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

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

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

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

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

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

	/**
	 * 反审核
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void undoAuditSendCarData(SendCarUndoAuditVO sendCarUndoAuditVO) {
		ToolKits.isParamNull(sendCarUndoAuditVO, "请求参数不为空");
		ToolKits.isParamNull(sendCarUndoAuditVO.getLoadingBillIds(), "请选择需要反审核的派车单");

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

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

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

		List<String> loadingBillIds = sendCarUndoAuditVO.getLoadingBillIds();
		for (String loadingBillId : loadingBillIds) {
			// 派车单对象
			TmsLoadingBillHeaderModel loadingBillHeaderModel = tmsLoadingBillHeaderMapper.findById(loadingBillId, TmsLoadingBillHeaderModel.class);

			// 反审核只能处理审核后的派车单包含审核
			Assert.isTrue(loadingBillHeaderModel.getStatus().intValue() >= DataDictionaryConstant.LOADING_BILL_STATUS_YSH.intValue(), "派车单【" + loadingBillId + "】不为已审核及之后的状态，不可反审核！");

			// 送达后（包括部分送达）的派车单不可反审核
			Assert.isTrue(loadingBillHeaderModel.getStatus().intValue() < DataDictionaryConstant.LOADING_BILL_STATUS_SD_PART.intValue(), "派车单【" + loadingBillId + "】已送达，不可反审核！");

			// 查询对应的派车单明细
			Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
			Restriction r1 = Restrictions.eq(TmsLoadingBillDetailModel::getLoadingBillId, loadingBillId);
			criteria.setRestriction(Restrictions.and(r1));
			List<TmsLoadingBillDetailModel> loadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteria);
			Assert.isTrue(loadingBillDetailModels.size() > 0, "派车单【" + loadingBillId + "】明细为空，反审核失败！");
			for (TmsLoadingBillDetailModel loadingBillDetailModel : loadingBillDetailModels) {
				// 运单节点记录
				ShipbillNodeTrackingSaveVO shipbillNodeTrackingSaveVO = new ShipbillNodeTrackingSaveVO();
				shipbillNodeTrackingSaveVO.setShipbillId(loadingBillDetailModel.getShipbillId());
				shipbillNodeTrackingSaveVO.setShipbillNo(loadingBillDetailModel.getShipbillNo());
				shipbillNodeTrackingSaveVO.setStatus(loadingBillDetailModel.getStatus());
				shipbillNodeTrackingSaveVO.setNodeEvent("运单反审核操作");
				shipbillNodeTrackingSaveVO.setCarrierShipbillStatus(loadingBillDetailModel.getCarrierShipbillStatus());
				shipbillNodeTrackingSaveVO.setNodeDate(date);
				shipbillNodeTrackingService.addShipbillNodeTrackingData(shipbillNodeTrackingSaveVO);

				// 运单操作日志
				ShipbillOperateLogSaveVO shipbillOperateLogSaveVO = new ShipbillOperateLogSaveVO();
				shipbillOperateLogSaveVO.setShipbillId(loadingBillDetailModel.getShipbillId());
				shipbillOperateLogSaveVO.setShipbillNo(loadingBillDetailModel.getShipbillNo());
				shipbillOperateLogSaveVO.setOperateDate(date);
				shipbillOperateLogSaveVO.setOperateEvent("运单反审核操作");
				shipbillOperateLogSaveVO.setOldStatus(loadingBillDetailModel.getStatus());
				shipbillOperateLogSaveVO.setNewStatus(loadingBillDetailModel.getStatus());
				shipbillOperateLogSaveVO.setOldCarrierShipbillStatus(loadingBillDetailModel.getCarrierShipbillStatus());
				shipbillOperateLogSaveVO.setNewCarrierShipbillStatus(loadingBillDetailModel.getCarrierShipbillStatus());
				shipbillOperateLogService.addShipbillOperateLogData(shipbillOperateLogSaveVO);
			}

			loadingBillHeaderModel.setOldStatus(loadingBillHeaderModel.getStatus());
			loadingBillHeaderModel.setStatus(DataDictionaryConstant.LOADING_BILL_STATUS_WSH);
			loadingBillHeaderModel.setUpdateperson(user.getNickname());
			loadingBillHeaderModel.setUpdatetime(date);
			tmsLoadingBillHeaderMapper.update(loadingBillHeaderModel);
		}
	}
}
