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

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

import javax.annotation.Resource;

import com.prolog.rdc.tms.app.model.vo.business.ShipBillReceiptPhotoVO;
import com.prolog.rdc.tms.app.service.business.*;
import cn.hutool.core.util.StrUtil;
import com.prolog.rdc.tms.app.dao.mapper.TmsShipbillContainerTempMapper;
import com.prolog.rdc.tms.app.dao.mapper.TmsShipbillDetailMapper;
import com.prolog.rdc.tms.app.model.dto.business.DeliveryShipbillQueryDTO;
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.vo.SignInItemVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
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.BizException;
import com.prolog.framework.core.exception.PrologException;
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.utils.ObjectUtils;
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.EventFeedbackModeEnum;
import com.prolog.rdc.tms.app.constant.enums.EventTypeEnum;
import com.prolog.rdc.tms.app.constant.enums.ShipBillReturnTypeEnum;
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.TmsShipbillAbnormalMapper;
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.PendingDeliveryTaskQueryDTO;
import com.prolog.rdc.tms.app.model.dto.ShipbillItemDetailQueryDTO;
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.TmsShipbillAbnormalModel;
import com.prolog.rdc.tms.app.model.entity.TmsShipbillEventFeedback;
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.PendingDeliveryAbnormalReportVO;
import com.prolog.rdc.tms.app.model.vo.PendingDeliveryConfirmVO;
import com.prolog.rdc.tms.app.model.vo.PendingDeliverySignInVO;
import com.prolog.rdc.tms.app.model.vo.PendingDeliveryTaskQueryVO;
import com.prolog.rdc.tms.app.model.vo.ShipbillDetailQueryVO;
import com.prolog.rdc.tms.app.model.vo.ShipbillServiceEvaluationVO;
import com.prolog.rdc.tms.app.model.vo.business.AddShipbillEventFeedbackVO;
import com.prolog.rdc.tms.app.model.vo.business.ShipbillEvaluationAddOrUpdateVO;
import com.prolog.rdc.tms.app.model.vo.business.ShipbillNodeTrackingSaveNewVO;
import com.prolog.rdc.tms.app.model.vo.business.ShipbillOperateLogSaveNewVO;
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.util.AutoSignJudge;
import com.prolog.rdc.tms.app.util.DistanceUtil;
import com.prolog.rdc.tms.app.util.MessageUtil;
import com.prolog.rdc.tms.app.util.PublicMethods;
import com.prolog.rdc.tms.model.constant.RedisConstant;
import com.prolog.rdc.tms.model.dto.DeviceByOneDTO;
import com.prolog.rdc.tms.model.dto.message.SendMessageDTO;
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.model.vo.fleetManagement.VehicleGpsSaveVO;
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 lombok.extern.slf4j.Slf4j;

/**
 *
 *
 * 司机APP-待预约实现层
 *
 * @className :PendingAppointmentServiceImpl
 * @author :qian.yh
 * @creationTime :2022/07/04
 * @description :
 *
 * @modifier :
 * @modifyTime :
 * @reviseRemarks:
 *
 * @version :1.0.0
 *
 */
@Slf4j
@Service
public class PendingDeliveryServiceImpl implements PendingDeliveryService {
	@Resource
	private TmsShipbillHeaderMapper tmsShipbillHeaderMapper;

	@Resource
	private TmsShipbillTransportLogMapper tmsShipbillTransportLogMapper;

	@Resource
	private TmsShipbillNodeTrackingMapper tmsShipbillNodeTrackingMapper;

	@Resource
	private TmsShipbillOperateLogMapper tmsShipbillOperateLogMapper;

	@Resource
	private MaindataFeign maindataFeign;

	@Resource
	private TmsLoadingBillDetailMapper tmsLoadingBillDetailMapper;

	@Resource
	private TmsLoadingBillHeaderMapper tmsLoadingBillHeaderMapper;

	@Autowired
	private ShipbillOperateLogService shipbillOperateLogService;

	@Autowired
	private MaindataFeign maindataTmsResource;

	@Autowired
	private TmsShipbillAbnormalMapper tmsShipbillAbnormalMapper;

	@Autowired
	private ShipbillNodeTrackingService shipbillNodeTrackingService;

	@Autowired
	private ShipbillService shipbillService;

	@Autowired
	private ShipbillEvaluationService shipbillEvaluationService;

	@Autowired
	private AutoSignJudge autoSignJudge;

	@Autowired
	private MainDataProxy mainDataProxy;

	@Autowired
	private ShipbillEventFeedbackService shipbillEventFeedbackService;

	@Autowired
	private ShipbillCommonService shipbillCommonService;

	@Autowired
	private TmsShipbillContainerTempMapper shipbillContainerTempMapper;

	@Autowired
	private RedisTemplate redisTemplate;

	@Autowired
	private TmsShipbillDetailMapper tmsShipbillDetailMapper;

	@Override
	public List<PendingDeliveryTaskQueryDTO> pendingDeliveryTaskQuery(PendingDeliveryTaskQueryVO pendingDeliveryTaskQueryVO) throws Exception {
		ToolKits.isParamNull(pendingDeliveryTaskQueryVO, "司机待预约明细查询请求参数不为空");
		ToolKits.isParamNull(pendingDeliveryTaskQueryVO.getDriverId(), "司机ID不为空");
		ToolKits.isParamNull(pendingDeliveryTaskQueryVO.getVehiclePlateNumber(), "车牌号不为空");
		ToolKits.isParamNull(pendingDeliveryTaskQueryVO.getEnterpriseId(), "企业ID不能为空");
		List<PendingDeliveryTaskQueryDTO> dtos = tmsShipbillHeaderMapper.pendingDeliveryTaskQuery(pendingDeliveryTaskQueryVO);
		if (ObjectUtils.isEmpty(dtos)) {
			throw new RuntimeException("未找到对应的运单明细！");
		}

		// STD-DEVELOP20220823 lhb 自动签到 20220901 start
		// 判断是否 自动送达签到
		if (ToolKits.isNotEmpty(pendingDeliveryTaskQueryVO.getDriverLongitude()) && ToolKits.isNotEmpty(pendingDeliveryTaskQueryVO.getDriverLatitude())) {
			boolean query = false;
			for (PendingDeliveryTaskQueryDTO deliveryDTO : dtos) {
				if (deliveryDTO.getConsigneeDeliveryRail().doubleValue() > 0 && deliveryDTO.getStatus().intValue() == DataDictionaryConstant.SHIPBILL_STATUS_SD.intValue() && ToolKits.isNotEmpty(deliveryDTO.getShipToLongitude()) && ToolKits.isNotEmpty(deliveryDTO.getShipToLatitude()) && deliveryDTO.getConsigneeDeliverySign().intValue() > 0 && deliveryDTO.getConsigneeAutoDeliverySign().intValue() > 0) {
					// 司机和仓库之间的距离
					double pos = DistanceUtil.getDistance(pendingDeliveryTaskQueryVO.getDriverLongitude().doubleValue(), pendingDeliveryTaskQueryVO.getDriverLatitude().doubleValue(), Double.valueOf(deliveryDTO.getShipToLongitude()).doubleValue(), Double.valueOf(deliveryDTO.getShipToLatitude()).doubleValue());
					if (Double.compare(pos, deliveryDTO.getConsigneeDeliveryRail().doubleValue()) <= 0 && autoSignJudge.autoSignJudge(deliveryDTO.getShipbillId(), "2")) {
						PendingDeliverySignInVO pendingDeliverySignInVO = new PendingDeliverySignInVO();
						pendingDeliverySignInVO.setDriverId(pendingDeliveryTaskQueryVO.getDriverId());
						pendingDeliverySignInVO.setEnterpriseId(pendingDeliveryTaskQueryVO.getEnterpriseId());
						pendingDeliverySignInVO.setShipbillId(deliveryDTO.getShipbillId());

						// 调用自动签到
						pendingDeliverySignIn(pendingDeliverySignInVO);
						query = true;
					}
				}
			}
			// 重新查询
			if (query) {
				dtos = tmsShipbillHeaderMapper.pendingDeliveryTaskQuery(pendingDeliveryTaskQueryVO);
				if (ObjectUtils.isEmpty(dtos)) {
					throw new RuntimeException("未找到对应的运单明细！");
				}
			}
		}
		// STD-DEVELOP20220823 lhb 自动签到 20220901 end

		for (PendingDeliveryTaskQueryDTO dto : dtos) {
			ShipbillDetailQueryVO vo = new ShipbillDetailQueryVO();
			vo.setEnterpriseId(dto.getEnterpriseId());
			vo.setShipbillId(dto.getShipbillId());
			List<ShipbillItemDetailQueryDTO> itemDetails = tmsShipbillHeaderMapper.shipbillItemDetailQuery(vo);
			DeliveryShipbillQueryDTO shipbillQueryDTO = new DeliveryShipbillQueryDTO();
			shipbillQueryDTO.setShipbillId(dto.getShipbillId());
			shipbillQueryDTO.setItemDetail(itemDetails);
			dto.setItemDetail(itemDetails);
			dto.setShipbillDTOList(Lists.newArrayList(shipbillQueryDTO));
			TmsShipbillHeaderModel tmsShipbillHeaderModel = tmsShipbillHeaderMapper.findById(vo.getShipbillId(), TmsShipbillHeaderModel.class);
			dto.setShipbillType(tmsShipbillHeaderModel.getShipbillType());
			dto.setContainerId(tmsShipbillHeaderModel.getContainerId());
			dto.setContainerCode(tmsShipbillHeaderModel.getContainerCode());
			dto.setContainerName(tmsShipbillHeaderModel.getContainerName());
			dto.setVehicleDeviceId(tmsShipbillHeaderModel.getVehicleDeviceId());
			dto.setVehicleDeviceCode(tmsShipbillHeaderModel.getVehicleDeviceCode());
			dto.setVehicleDeviceName(tmsShipbillHeaderModel.getVehicleDeviceName());
		}
		return dtos;
	}

	@Override
	public List<PendingDeliveryTaskQueryDTO> pendingDeliveryTaskQueryGroupByConsignee(PendingDeliveryTaskQueryVO pendingDeliveryTaskQueryVO) {
		List<PendingDeliveryTaskQueryDTO> dtoList = tmsShipbillHeaderMapper.pendingDeliveryTaskQueryGroupByConsignee(pendingDeliveryTaskQueryVO);
		if (CollectionUtil.isNotEmpty(dtoList)) {
			if (ToolKits.isNotEmpty(pendingDeliveryTaskQueryVO.getDriverLongitude()) && ToolKits.isNotEmpty(pendingDeliveryTaskQueryVO.getDriverLatitude())) {
				AtomicBoolean query = new AtomicBoolean(false);
				for (PendingDeliveryTaskQueryDTO deliveryDTO : dtoList) {
					if (deliveryDTO.getConsigneeDeliveryRail().doubleValue() > 0 && deliveryDTO.getStatus().intValue() == DataDictionaryConstant.SHIPBILL_STATUS_SD.intValue() && ToolKits.isNotEmpty(deliveryDTO.getShipToLongitude()) && ToolKits.isNotEmpty(deliveryDTO.getShipToLatitude()) && deliveryDTO.getConsigneeDeliverySign().intValue() > 0 && deliveryDTO.getConsigneeAutoDeliverySign().intValue() > 0) {
						// 司机和仓库之间的距离
						double pos = DistanceUtil.getDistance(pendingDeliveryTaskQueryVO.getDriverLongitude().doubleValue(), pendingDeliveryTaskQueryVO.getDriverLatitude().doubleValue(), Double.valueOf(deliveryDTO.getShipToLongitude()).doubleValue(), Double.valueOf(deliveryDTO.getShipToLatitude()).doubleValue());
						Arrays.stream(deliveryDTO.getShipbillId().split(",")).distinct().forEach(shipbillId -> {
							if (Double.compare(pos, deliveryDTO.getConsigneeDeliveryRail().doubleValue()) <= 0 && autoSignJudge.autoSignJudge(shipbillId, "2")) {
								PendingDeliverySignInVO pendingDeliverySignInVO = new PendingDeliverySignInVO();
								pendingDeliverySignInVO.setDriverId(pendingDeliveryTaskQueryVO.getDriverId());
								pendingDeliverySignInVO.setEnterpriseId(pendingDeliveryTaskQueryVO.getEnterpriseId());
								pendingDeliverySignInVO.setShipbillId(deliveryDTO.getShipbillId());
								// 调用自动签到
								pendingDeliverySignIn(pendingDeliverySignInVO);
								query.set(true);
							}
						});
					}
				}
				// 重新查询
				if (query.get()) {
					dtoList = tmsShipbillHeaderMapper.pendingDeliveryTaskQueryGroupByConsignee(pendingDeliveryTaskQueryVO);
				}
			}
			if (CollectionUtil.isNotEmpty(dtoList)) {
				dtoList.forEach(dto -> {
					List<String> shipBillIdList = Arrays.stream(dto.getShipbillId().split(",")).distinct().collect(Collectors.toList());
					List<String> loadingBillIdList = Arrays.stream(dto.getLoadingBillId().split(",")).distinct().collect(Collectors.toList());
					List<TmsShipbillHeaderModel> tmsShipbillHeaderModelList = tmsShipbillHeaderMapper.findByIds(TmsShipbillHeaderModel.class, shipBillIdList.toArray(), null);
					if (CollectionUtil.isNotEmpty(tmsShipbillHeaderModelList)) {
						List<TmsShipbillHeaderModel> filterContainer = tmsShipbillHeaderModelList.stream().filter(tmsShipbillHeaderModel -> StrUtil.isNotBlank(tmsShipbillHeaderModel.getContainerId())).collect(Collectors.toList());
						dto.setContainerId(filterContainer.stream().flatMap(tmsShipbillHeaderModel -> Arrays.stream(tmsShipbillHeaderModel.getContainerId().split(","))).distinct().collect(Collectors.joining(",")));
						dto.setContainerCode(filterContainer.stream().flatMap(tmsShipbillHeaderModel -> Arrays.stream(tmsShipbillHeaderModel.getContainerCode().split(","))).distinct().collect(Collectors.joining(",")));
						dto.setContainerName(filterContainer.stream().flatMap(tmsShipbillHeaderModel -> Arrays.stream(tmsShipbillHeaderModel.getContainerName().split(","))).distinct().collect(Collectors.joining(",")));
						List<TmsShipbillHeaderModel> filterVehicleDevice = tmsShipbillHeaderModelList.stream().filter(tmsShipbillHeaderModel -> StrUtil.isNotBlank(tmsShipbillHeaderModel.getVehicleDeviceId())).collect(Collectors.toList());
						dto.setVehicleDeviceId(filterVehicleDevice.stream().flatMap(tmsShipbillHeaderModel -> Arrays.stream(tmsShipbillHeaderModel.getVehicleDeviceId().split(","))).distinct().collect(Collectors.joining(",")));
						dto.setVehicleDeviceCode(filterVehicleDevice.stream().flatMap(tmsShipbillHeaderModel -> Arrays.stream(tmsShipbillHeaderModel.getVehicleDeviceCode().split(","))).distinct().collect(Collectors.joining(",")));
						dto.setVehicleDeviceName(filterVehicleDevice.stream().flatMap(tmsShipbillHeaderModel -> Arrays.stream(tmsShipbillHeaderModel.getVehicleDeviceName().split(","))).distinct().collect(Collectors.joining(",")));
						dto.setShipbillType(tmsShipbillHeaderModelList.stream().map(TmsShipbillHeaderModel::getShipbillType).filter(StrUtil::isNotBlank).distinct().collect(Collectors.joining(",")));
					}
					dto.setShipbillId(shipBillIdList.stream().collect(Collectors.joining(",")));
					dto.setShipbillNo(shipBillIdList.stream().collect(Collectors.joining(",")));
					dto.setLoadingBillId(loadingBillIdList.stream().collect(Collectors.joining(",")));
					List<DeliveryShipbillQueryDTO> shipbillQueryDTOList = shipBillIdList.stream().map(shipBillId -> {
						ShipbillDetailQueryVO vo = new ShipbillDetailQueryVO();
						vo.setEnterpriseId(pendingDeliveryTaskQueryVO.getEnterpriseId());
						vo.setShipbillId(shipBillId);
						DeliveryShipbillQueryDTO shipbillQueryDTO = new DeliveryShipbillQueryDTO();
						shipbillQueryDTO.setShipbillId(shipBillId);
						shipbillQueryDTO.setItemDetail(tmsShipbillHeaderMapper.shipbillItemDetailQuery(vo));
						return shipbillQueryDTO;
					}).collect(Collectors.toList());
					dto.setShipbillDTOList(shipbillQueryDTOList);
					dto.setItemDetail(shipbillQueryDTOList.stream().filter(
							shipbillQueryDTO -> CollectionUtil.isNotEmpty(shipbillQueryDTO.getItemDetail())).flatMap(
							shipbillQueryDTO -> shipbillQueryDTO.getItemDetail().stream()).collect(Collectors.toList()));
					dto.setShipBillNums(shipBillIdList.size());
				});
			}
		}
		return dtoList;
	}

	@Override
	public void pendingDeliverySignIn(PendingDeliverySignInVO pendingDeliverySignInVO) {
		// STD-DEVELOP20220823 lhb 自动签到 20220901 start
		// 只更新运输记录表中的启运签到时间
		UserEntity user = PlgFxUsrUtils.getUserEntity();
		com.prolog.common.util.ToolKits.isParamNull(user, "当前人员没有操作权限");
		Date date = DateUtil.date();

		Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
		Restriction r1 = Restrictions.in(TmsLoadingBillDetailModel::getShipbillId, pendingDeliverySignInVO.getShipbillId().split(","));
		Restriction r2 = Restrictions.eq(TmsLoadingBillDetailModel::getStatus, DataDictionaryConstant.SHIPBILL_STATUS_SD);
		Restriction r3 = Restrictions.eq(TmsLoadingBillDetailModel::getEnterpriseId, user.getEnterpriseId());
		criteria.setRestriction(Restrictions.and(r1, r2, r3));
		List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteria);
		Assert.isTrue(tmsLoadingBillDetailModels.size() != 0, "待签到运单不存在");
		for (TmsLoadingBillDetailModel tmsLoadingBillDetailModel : tmsLoadingBillDetailModels) {
			// 原状态
			Integer oldStatus = tmsLoadingBillDetailModel.getStatus();

			tmsLoadingBillDetailModel.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_SDQD);
			tmsLoadingBillDetailModel.setUpdateperson(user.getNickname());
			tmsLoadingBillDetailModel.setUpdatetime(date);
			tmsLoadingBillDetailMapper.update(tmsLoadingBillDetailModel);

			ShipbillOperateLogSaveNewVO shipbillOperateLogSaveNewVO = new ShipbillOperateLogSaveNewVO();
			shipbillOperateLogSaveNewVO.setShipbillId(tmsLoadingBillDetailModel.getShipbillId());
			shipbillOperateLogSaveNewVO.setShipbillNo(tmsLoadingBillDetailModel.getShipbillId());
			shipbillOperateLogSaveNewVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_SDQD);
			shipbillOperateLogSaveNewVO.setOldStatus(oldStatus);
			shipbillOperateLogSaveNewVO.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_SDQD);
			shipbillOperateLogSaveNewVO.setOperateDate(DateUtil.date());
			shipbillOperateLogSaveNewVO.setEnterpriseId(user.getEnterpriseId());
			shipbillOperateLogSaveNewVO.setEnterpriseName(user.getEnterpriseName());
			shipbillOperateLogSaveNewVO.setUserId(user.getUserid());
			shipbillOperateLogSaveNewVO.setUserName(user.getNickname());
			shipbillOperateLogService.addShipbillOperateLogNewData(shipbillOperateLogSaveNewVO);

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

			// 更新运输记录表
			Criteria criteriaTransportLog = Criteria.forClass(TmsShipbillTransLogModel.class);
			Restriction r4 = Restrictions.eq(TmsShipbillTransLogModel::getEnterpriseId, tmsLoadingBillDetailModel.getEnterpriseId());
			Restriction r5 = Restrictions.eq(TmsShipbillTransLogModel::getShipbillId, tmsLoadingBillDetailModel.getShipbillId());
			criteriaTransportLog.setRestriction(Restrictions.and(r4, r5));
			tmsShipbillTransportLogMapper.updateMapByCriteria(mapUpdate, criteriaTransportLog);
		}
		// STD-DEVELOP20220823 lhb 自动签到 20220901 end
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void pendingDeliveryConfirm(PendingDeliveryConfirmVO pendingDeliveryConfirmVO) throws Exception {
		ToolKits.isParamNull(pendingDeliveryConfirmVO.getShipbillId(), "运单ID不能为空");
		ToolKits.isParamNull(pendingDeliveryConfirmVO.getEnterpriseId(), "企业ID不能为空");
		UserEntity user = PlgFxUsrUtils.getUserEntity();
		ToolKits.isParamNull(user, "当前人员没有操作权限");

		List<TmsShipbillHeaderModel> tmsShipbillHeaderModelList = tmsShipbillHeaderMapper.findByIds(TmsShipbillHeaderModel.class, pendingDeliveryConfirmVO.getShipbillId().split(","), null);
//		if (!DataDictionaryConstant.TEMPERATURE_REQUIREMENT_CW.equals(tmsShipbillHeaderModel.getTemperatureRequirement())) {
//			if (Boolean.TRUE.equals(pendingDeliveryConfirmVO.getShowDeliveryTemperature()) && ObjectUtil.isNull(pendingDeliveryConfirmVO.getDeliveryTemperature())) {
//				throw new BizException("送达温度不能为空");
//			}
//		}

		tmsShipbillHeaderModelList.forEach(tmsShipbillHeaderModel -> {
			if (ToolKits.isNotEmpty(tmsShipbillHeaderModel) && ObjectUtil.equal(StatusConstant.WHETHER_YES, tmsShipbillHeaderModel.getConsigneeDeliveryPicture()) && ToolKits.isEmpty(pendingDeliveryConfirmVO.getGoodsPicUrl())) {
				throw new PrologException("送货图片不能为空");
			}
		});

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

		if (Boolean.TRUE.equals(pendingDeliveryConfirmVO.getShowContainerTemperature())) {
			if (CollectionUtil.isEmpty(pendingDeliveryConfirmVO.getTemperatureVOList())) {
				throw new BizException("容器温度集合不存在");
			}
			pendingDeliveryConfirmVO.getTemperatureVOList().forEach(vo -> {
				if (ObjectUtil.isNull(vo.getTemperature())) {
					throw new BizException("容器" + vo.getName() + "温度为空");
				}
			});
			Map<Long, BigDecimal> deliveryTempMap = pendingDeliveryConfirmVO.getTemperatureVOList().stream().collect(Collectors.toMap(
					t1 -> t1.getId(), t2 -> t2.getTemperature(), (t1, t2) -> t2));
			tmsShipbillHeaderModelList.forEach(model -> {
				Criteria criteria = Criteria.forClass(TmsShipbillContainerTemp.class);
				Restriction r1 = Restrictions.eq(TmsShipbillContainerTemp::getEnterpriseId, user.getEnterpriseId());
				Restriction r2 = Restrictions.eq(TmsShipbillContainerTemp::getShipbillId, model.getShipbillId());
				criteria.setRestriction(Restrictions.and(r1, r2));
				List<TmsShipbillContainerTemp> tempList = shipbillContainerTempMapper.findByCriteria(criteria);
				if (CollectionUtil.isNotEmpty(tempList)) {
					tempList.forEach(temp -> {
						temp.setDeliveryTemp(deliveryTempMap.getOrDefault(temp.getContainerId(), BigDecimal.ZERO));
						temp.setDeliveryTempTime(DateUtil.date());
						temp.setUpdatetime(DateUtil.date());
						temp.setUpdateperson(user.getNickname());
						shipbillContainerTempMapper.update(temp);
					});
				}
			});
		}

		Map<String, String> receiptPicUrlMap = Maps.newHashMap();
		List<ShipBillReceiptPhotoVO> receiptPhotoVOList = pendingDeliveryConfirmVO.getReceiptPhotoVOList();
		if (StrUtil.isNotBlank(pendingDeliveryConfirmVO.getReceiptPicUrl())) {
			receiptPhotoVOList = Lists.newArrayList(new ShipBillReceiptPhotoVO(pendingDeliveryConfirmVO.getShipbillId(), pendingDeliveryConfirmVO.getReceiptPicUrl()));
		}
		if (CollectionUtil.isNotEmpty(receiptPhotoVOList)) {
			receiptPicUrlMap = receiptPhotoVOList.stream().collect(Collectors.toMap(ShipBillReceiptPhotoVO::getShipbillId, ShipBillReceiptPhotoVO::getReceiptPicUrl));
		}

		Map<String, String> finalReceiptPicUrlMap = receiptPicUrlMap;
		tmsShipbillHeaderModelList.forEach(tmsShipbillHeaderModel -> {
			// 经纬度都有值时 才写入数据到GPS表
			if (ToolKits.isNotEmpty(pendingDeliveryConfirmVO.getLongitude()) && ToolKits.isNotEmpty(pendingDeliveryConfirmVO.getLatitude())) {
				// 写入司机GPS数据
				VehicleGpsSaveVO savevo = new VehicleGpsSaveVO();
				savevo.setDeliveryTime(date);
				savevo.setLongitude(pendingDeliveryConfirmVO.getLongitude());
				savevo.setLatitude(pendingDeliveryConfirmVO.getLatitude());
				savevo.setShipbillId(tmsShipbillHeaderModel.getShipbillId());
				savevo.setShipbillNo(tmsShipbillHeaderModel.getShipbillId());
				savevo.setTemperature(pendingDeliveryConfirmVO.getDeliveryTemperature());
				savevo.setFlag("1");
				maindataFeign.saveVehicleGps(savevo);
			}

			String eventFeedbackMode = mainDataProxy.getSystemParamByCode(EventFeedbackModeEnum.ENUM_NAME);
			if (eventFeedbackMode.contains(EventFeedbackModeEnum.OPEN_DELIVERY_EVENT.getCode())) {
				AddShipbillEventFeedbackVO vo = new AddShipbillEventFeedbackVO();
				vo.setType(EventTypeEnum.DELIVERY.getCode());
				vo.setShipbillId(tmsShipbillHeaderModel.getShipbillId());
				vo.setMileage(pendingDeliveryConfirmVO.getMileage());
				vo.setAddress(pendingDeliveryConfirmVO.getAddress());
				vo.setLongitude(pendingDeliveryConfirmVO.getLongitude());
				vo.setLatitude(pendingDeliveryConfirmVO.getLatitude());
				vo.setEventType(pendingDeliveryConfirmVO.getEventType());
				vo.setEventContent(pendingDeliveryConfirmVO.getEventContent());
				vo.setEventPic(pendingDeliveryConfirmVO.getEventPic());
				TmsShipbillEventFeedback model = shipbillEventFeedbackService.add(vo);
				Boolean eventFeedbackFlow = approvalOpen(tmsShipbillHeaderModel, DataDictionaryConstant.APPROVAL_FLOW_TYPE_EVENT_FEEDBACK, model.getId());
				if (!eventFeedbackFlow) {
					shipbillEventFeedbackService.eventFeedback(model.getId());
				}
			}

			// 签到时间是否为空
			boolean deliverySignTime = false;
			// 货物图片
			String goodsPhoto = pendingDeliveryConfirmVO.getGoodsPicUrl();
			// 回单图片
			String receiptPhoto = finalReceiptPicUrlMap.get(tmsShipbillHeaderModel.getShipbillId());
			// 节点内容
			StringBuffer nodeEvent = new StringBuffer();
			nodeEvent.append("送达确认 送达签收人:");
			nodeEvent.append(ToolKits.isEmpty(pendingDeliveryConfirmVO.getSignPerson()) ? "" : pendingDeliveryConfirmVO.getSignPerson());
			nodeEvent.append(" 送达备注:");
			nodeEvent.append(ToolKits.isEmpty(pendingDeliveryConfirmVO.getSignRemark()) ? "" : pendingDeliveryConfirmVO.getSignRemark());

			int status = DataDictionaryConstant.SHIPBILL_STATUS_END;

			Criteria criteriaTransportLog = Criteria.forClass(TmsShipbillTransLogModel.class);
			Restriction r1 = Restrictions.eq(TmsShipbillTransLogModel::getEnterpriseId, pendingDeliveryConfirmVO.getEnterpriseId());
			Restriction r2 = Restrictions.eq(TmsShipbillTransLogModel::getShipbillId, tmsShipbillHeaderModel.getShipbillId());
			criteriaTransportLog.setRestriction(Restrictions.and(r1, r2));
			List<TmsShipbillTransLogModel> transportLogModels = tmsShipbillTransportLogMapper.findByCriteria(criteriaTransportLog);
			for (TmsShipbillTransLogModel transportLogModel : transportLogModels) {
				TmsShipbillHeaderModel tmsShipbillHeader = tmsShipbillHeaderMapper.findById(tmsShipbillHeaderModel.getShipbillId(), TmsShipbillHeaderModel.class);
				if (ToolKits.isNotEmpty(tmsShipbillHeader) && ObjectUtil.equal(StatusConstant.WHETHER_YES, tmsShipbillHeader.getConsigneeDeliveryPicture()) && ToolKits.isEmpty(pendingDeliveryConfirmVO.getGoodsPicUrl())) {
					throw new PrologException("送货图片不能为空");
				}
				// 判断签到时间是否为空
				if (transportLogModel.getDeliverySignTime() == null) {
					// throw new RuntimeException("请先配送签到！");
				}
				transportLogModel.setDeliverySignPerson(pendingDeliveryConfirmVO.getSignPerson());
				transportLogModel.setDeliveryMemo(pendingDeliveryConfirmVO.getSignRemark());
				transportLogModel.setUpdateperson(user.getNickname());
				transportLogModel.setUpdatetime(date);
				transportLogModel.setDeliveryTime(date);
				transportLogModel.setDeliveryStatus(30);
				tmsShipbillTransportLogMapper.update(transportLogModel);
				Map<String, Object> mapTransportLogUpdate = Maps.newHashMap();
				mapTransportLogUpdate.put("updateperson", user.getNickname());
				mapTransportLogUpdate.put("updatetime", date);
				// 送达时间
				mapTransportLogUpdate.put("deliveryTime", date);
				// 配送状态
				mapTransportLogUpdate.put("deliveryStatus", 30);
				// 运单节点保存
				// 获取节点ID
				RestMessage<String> restMessage = maindataFeign.getCodeNumberByCode(SeriaNnumberConstant.TMS_SHIPBILL_NODE_TRACKING_ID, "L");
				if (!restMessage.isSuccess()) {
					throw new RuntimeException("生成节点ID失败");
				}
				String id = restMessage.getData();
				// 节点记录
				ShipbillNodeTracking model = new ShipbillNodeTracking();
				model.setNodeDate(date);
				model.setShipbillId(transportLogModel.getShipbillId());
				model.setShipbillNo(transportLogModel.getShipbillId());
				model.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_SD);
				model.setNodeEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_SD);
				model.setUserId(user.getUserid());
				model.setUserName(user.getNickname());
				model.setEnterpriseId(user.getEnterpriseId());
				model.setEnterpriseName(user.getEnterpriseName());
				model.setPicUrl(goodsPhoto);
				model.setId(id);
				model.setUserId(user.getUserid());
				model.setUserName(user.getNickname());
				model.setEnterpriseId(user.getEnterpriseId());
				model.setEnterpriseName(user.getEnterpriseName());
				model.setCreateperson(user.getNickname());
				model.setCreatetime(date);
				model.setUpdateperson(user.getNickname());
				model.setUpdatetime(date);
				tmsShipbillNodeTrackingMapper.save(model);
				// 运单日志保存
				// 获取日志ID
				RestMessage<String> restMessageLog = maindataFeign.getCodeNumberByCode(SeriaNnumberConstant.TMS_SHIPBILL_OPERATE_LOG_ID, "L");
				if (!restMessageLog.isSuccess()) {
					throw new RuntimeException("生成日志ID失败");
				}
				String idLog = restMessageLog.getData();
				// 日志记录
				TmsShipbillOperateLogModel logModel = new TmsShipbillOperateLogModel();
				logModel.setShipbillId(transportLogModel.getShipbillId());
				logModel.setShipbillNo(transportLogModel.getShipbillId());
				logModel.setOperateEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_SD);
				logModel.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_QY);
				logModel.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_SD);
				logModel.setOperateDate(date);
				logModel.setEnterpriseId(user.getEnterpriseId());
				logModel.setEnterpriseName(user.getEnterpriseName());
				logModel.setUserId(user.getUserid());
				logModel.setUserName(user.getNickname());
				logModel.setId(idLog);
				logModel.setOperateDate(date);
				logModel.setUserId(user.getUserid());
				logModel.setUserName(user.getNickname());
				logModel.setEnterpriseId(user.getEnterpriseId());
				logModel.setEnterpriseName(user.getEnterpriseName());
				logModel.setCreateperson(user.getNickname());
				logModel.setCreatetime(date);
				logModel.setUpdateperson(user.getNickname());
				logModel.setUpdatetime(date);
				tmsShipbillOperateLogMapper.save(logModel);

				if (ToolKits.isNotEmpty(receiptPhoto)) {
					// STD-BUG20220823 lhb 24852 20220913 start
					if (DataDictionaryConstant.WHETHER_YES.equals(tmsShipbillHeader.getReturnOrderFlag())) {
						status = DataDictionaryConstant.SHIPBILL_STATUS_HD_ZB;
					}
					// STD-BUG20220823 lhb 24852 20220913 end
					// 运单节点保存
					// 获取节点ID
					RestMessage<String> restMessage1 = maindataFeign.getCodeNumberByCode(SeriaNnumberConstant.TMS_SHIPBILL_NODE_TRACKING_ID, "L");
					if (!restMessage1.isSuccess()) {
						throw new RuntimeException("生成节点ID失败");
					}
					String id1 = restMessage1.getData();
					// 节点记录
					ShipbillNodeTracking model1 = new ShipbillNodeTracking();
					model1.setNodeDate(date);
					model1.setShipbillId(transportLogModel.getShipbillId());
					model1.setShipbillNo(transportLogModel.getShipbillId());
					model1.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_HD_PIC);
					model1.setNodeEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_HD_PIC);
					model1.setUserId(user.getUserid());
					model1.setUserName(user.getNickname());
					model1.setEnterpriseId(user.getEnterpriseId());
					model1.setEnterpriseName(user.getEnterpriseName());
					model1.setPicUrl(receiptPhoto);
					model1.setId(id1);
					model1.setUserId(user.getUserid());
					model1.setUserName(user.getNickname());
					model1.setEnterpriseId(user.getEnterpriseId());
					model1.setEnterpriseName(user.getEnterpriseName());
					model1.setCreateperson(user.getNickname());
					model1.setCreatetime(date);
					model1.setUpdateperson(user.getNickname());
					model1.setUpdatetime(date);
					tmsShipbillNodeTrackingMapper.save(model1);
					// 运单日志保存
					// 获取日志ID
					RestMessage<String> restMessageLog1 = maindataFeign.getCodeNumberByCode(SeriaNnumberConstant.TMS_SHIPBILL_OPERATE_LOG_ID, "L");
					if (!restMessageLog1.isSuccess()) {
						throw new RuntimeException("生成日志ID失败");
					}
					String idLog1 = restMessageLog1.getData();
					// 日志记录
					TmsShipbillOperateLogModel logModel1 = new TmsShipbillOperateLogModel();
					logModel1.setShipbillId(transportLogModel.getShipbillId());
					logModel1.setShipbillNo(transportLogModel.getShipbillId());
					logModel1.setOperateEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_HD_PIC);
					logModel1.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_QY);
					logModel1.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_HD_PIC);
					logModel1.setOperateDate(date);
					logModel1.setEnterpriseId(user.getEnterpriseId());
					logModel1.setEnterpriseName(user.getEnterpriseName());
					logModel1.setUserId(user.getUserid());
					logModel1.setUserName(user.getNickname());
					logModel1.setId(idLog1);
					logModel1.setOperateDate(date);
					logModel1.setUserId(user.getUserid());
					logModel1.setUserName(user.getNickname());
					logModel1.setEnterpriseId(user.getEnterpriseId());
					logModel1.setEnterpriseName(user.getEnterpriseName());
					logModel1.setCreateperson(user.getNickname());
					logModel1.setCreatetime(date);
					logModel1.setUpdateperson(user.getNickname());
					logModel1.setUpdatetime(date);
					tmsShipbillOperateLogMapper.save(logModel1);
				} else {
					if (DataDictionaryConstant.WHETHER_YES.equals(tmsShipbillHeader.getConsigneeReturnOrderPicture())) {
						status = DataDictionaryConstant.SHIPBILL_STATUS_HD_PIC;
					} else if (DataDictionaryConstant.WHETHER_YES.equals(tmsShipbillHeader.getReturnOrderFlag())) {
						status = DataDictionaryConstant.SHIPBILL_STATUS_HD_ZB;
					}
				}
				// 更新运单状态 为待配送
				Map<String, Object> mapUpdate = Maps.newHashMap();
				mapUpdate.put("status", status);
				mapUpdate.put("transportStatus", "30");
				mapUpdate.put("updateperson", user.getNickname());
				mapUpdate.put("updatetime", new Date());
				mapUpdate.put("deliveryTime", new Date());
				mapUpdate.put("deliveryTemperature", pendingDeliveryConfirmVO.getDeliveryTemperature());
				Criteria criteriaTmsShipbillHeader = Criteria.forClass(TmsShipbillHeaderModel.class);
				Restriction r1TmsShipbillHeader = Restrictions.eq(TmsShipbillHeaderModel::getEnterpriseId, transportLogModel.getEnterpriseId());
				Restriction r2TmsShipbillHeader = Restrictions.eq(TmsShipbillHeaderModel::getShipbillId, transportLogModel.getShipbillId());
				Restriction r3TmsShipbillHeader = Restrictions.eq(TmsShipbillHeaderModel::getStatus, DataDictionaryConstant.SHIPBILL_STATUS_SD);
				criteriaTmsShipbillHeader.setRestriction(Restrictions.and(r1TmsShipbillHeader, r2TmsShipbillHeader,r3TmsShipbillHeader));
				long upCnt = tmsShipbillHeaderMapper.updateMapByCriteria(mapUpdate, criteriaTmsShipbillHeader);
				if (1 > upCnt) {
					throw new PrologException(StrUtil.format("运单已送达确认",transportLogModel.getShipbillId()));
				}
				// 修改派车单明细
				Criteria criteriaDetail = Criteria.forClass(TmsLoadingBillDetailModel.class);
				r1 = Restrictions.eq(TmsLoadingBillDetailModel::getShipbillId, transportLogModel.getShipbillId());
				Restriction r3 = Restrictions.eq(TmsLoadingBillDetailModel::getStatus, DataDictionaryConstant.SHIPBILL_STATUS_SDQD);
				Restriction r4 = Restrictions.eq(TmsLoadingBillDetailModel::getStatus, DataDictionaryConstant.SHIPBILL_STATUS_SD);
				r2 = Restrictions.or(r3, r4);
				criteriaDetail.setRestriction(Restrictions.and(r1, r2));
				List<TmsLoadingBillDetailModel> loadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteriaDetail);
				if (ToolKits.isEmpty(loadingBillDetailModels)) {
					throw new PrologException("运单【" + transportLogModel.getShipbillId() + "】调度明细不存在");
				}
				Map<String, Object> mapDetailUpdate = Maps.newHashMap();
				mapDetailUpdate.put("status", status);
				mapDetailUpdate.put("transportStatus", "30");
				mapDetailUpdate.put("transportStatus", DataDictionaryConstant.TRANSPORT_STATUS_ARRIVED);
				mapDetailUpdate.put("updateperson", user.getNickname());
				mapDetailUpdate.put("updatetime", date);
				mapDetailUpdate.put("deliveryTemperature", pendingDeliveryConfirmVO.getDeliveryTemperature());
				tmsLoadingBillDetailMapper.updateMapByCriteria(mapDetailUpdate, criteriaDetail);
				// 父运单的同步送达
				String fatherShipbillId = transportLogModel.getShipbillId();
				while (com.prolog.common.util.ToolKits.isNotEmpty(fatherShipbillId)) {
					fatherShipbillId = fatherDeliveredConfirm(status, fatherShipbillId, date, user, deliverySignTime, goodsPhoto, receiptPhoto, nodeEvent.toString(), mapTransportLogUpdate);
					deliverySignTime = false;
				}
				// STD-BUG20220823 lhb 4649启运登记、送达确认 需要同步回写 派车单的状态 20220915 start
				TmsLoadingBillDetailModel tmsLoadingBillDetail = loadingBillDetailModels.get(0);
				// 更新调度单状态
				Restriction r5 = Restrictions.eq("loadingBillId", tmsLoadingBillDetail.getLoadingBillId());
				Restriction r6 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
				criteriaDetail.setRestriction(Restrictions.and(r5, r6));
				List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteriaDetail);
				int cnt = 0;
				if (ToolKits.isNotEmpty(tmsLoadingBillDetailModels)) {
					TmsLoadingBillHeaderModel secondLoadingBillHeaderModel = tmsLoadingBillHeaderMapper.findById(tmsLoadingBillDetail.getLoadingBillId(), TmsLoadingBillHeaderModel.class);
					// 运单，第一次调度，调度给承运商，第二次调度，承运商调度给司机或者承运商时，根据第二调度单，查询第一次的调度单
					criteriaDetail = Criteria.forClass(TmsLoadingBillDetailModel.class);
					r1 = Restrictions.eq(TmsLoadingBillDetailModel::getShipbillId, tmsLoadingBillDetail.getShipbillId());
					r2 = Restrictions.eq(TmsLoadingBillDetailModel::getEnterpriseId, user.getEnterpriseId());
					r3 = Restrictions.ne(TmsLoadingBillDetailModel::getLoadingBillId, tmsLoadingBillDetail.getLoadingBillId());
					criteriaDetail.setRestriction(Restrictions.and(r1, r2, r3));
					List<TmsLoadingBillDetailModel> firstLoadingBillDetails = tmsLoadingBillDetailMapper.findByCriteria(criteriaDetail);
					cnt = tmsLoadingBillDetailModels.stream().filter(t -> t.getStatus().intValue() < DataDictionaryConstant.SHIPBILL_STATUS_HD_PIC.intValue()).collect(Collectors.toList()).size();
					if (cnt == 0) {
						// 更新状态为送达确认
						secondLoadingBillHeaderModel.setStatus(DataDictionaryConstant.LOADING_BILL_STATUS_SD);
						tmsLoadingBillHeaderMapper.update(secondLoadingBillHeaderModel);
						// 第一次调度单状态更新
						if (ToolKits.isNotEmpty(firstLoadingBillDetails)) {
							TmsLoadingBillHeaderModel firstLoadingBillHeaderModel = tmsLoadingBillHeaderMapper.findById(firstLoadingBillDetails.get(0).getLoadingBillId(), TmsLoadingBillHeaderModel.class);
							firstLoadingBillHeaderModel.setStatus(DataDictionaryConstant.LOADING_BILL_STATUS_SD);
							tmsLoadingBillHeaderMapper.update(firstLoadingBillHeaderModel);
						}
					} else {
						// 更新状态为部分送达确认
						if (!secondLoadingBillHeaderModel.getStatus().equals(DataDictionaryConstant.LOADING_BILL_STATUS_SD_PART)) {
							secondLoadingBillHeaderModel.setStatus(DataDictionaryConstant.LOADING_BILL_STATUS_SD_PART);
							tmsLoadingBillHeaderMapper.update(secondLoadingBillHeaderModel);
							// 第一次调度单状态更新
							if (ToolKits.isNotEmpty(firstLoadingBillDetails)) {
								TmsLoadingBillHeaderModel firstLoadingBillHeaderModel = tmsLoadingBillHeaderMapper.findById(firstLoadingBillDetails.get(0).getLoadingBillId(), TmsLoadingBillHeaderModel.class);
								firstLoadingBillHeaderModel.setStatus(DataDictionaryConstant.LOADING_BILL_STATUS_SD_PART);
								tmsLoadingBillHeaderMapper.update(firstLoadingBillHeaderModel);
							}
						}
					}
				}
				if (CollectionUtil.isNotEmpty(pendingDeliveryConfirmVO.getItemVOList())) {
					Criteria detailCriteria = Criteria.forClass(TmsShipbillDetailModel.class);
					Restriction detailR1 = Restrictions.eq(TmsShipbillDetailModel::getEnterpriseId, tmsShipbillHeaderModel.getEnterpriseId());
					Restriction detailR2 = Restrictions.eq(TmsShipbillDetailModel::getShipbillId, tmsShipbillHeaderModel.getShipbillId());
					detailCriteria.setRestriction(Restrictions.and(detailR1, detailR2));
					List<TmsShipbillDetailModel> detailModelList = tmsShipbillDetailMapper.findByCriteria(detailCriteria);
					if (CollectionUtil.isNotEmpty(detailModelList)) {
						List<String> detailIdList = detailModelList.stream().map(TmsShipbillDetailModel::getId).collect(Collectors.toList());
						List<SignInItemVO> filterVOList = pendingDeliveryConfirmVO.getItemVOList().stream().filter(signInItemVO -> detailIdList.contains(signInItemVO.getId())).collect(Collectors.toList());
						if (CollectionUtil.isNotEmpty(filterVOList)) {
							String flowConfig = tmsShipbillHeader.getFlowConfig();
							// 没有签收流程，更新签收数量，自动退
							if (!flowConfig.contains(DataDictionaryConstant.FLOW_CONFIG_SIGN_IN)) {
								SignInShipBillVO signInShipBillVO = new SignInShipBillVO();
								signInShipBillVO.setShipBillId(tmsShipbillHeaderModel.getShipbillId());
								signInShipBillVO.setItemVOList(filterVOList);
								signInShipBillVO.setReturnType(ShipBillReturnTypeEnum.S.getCode());
								shipbillService.updateSignInPcs(signInShipBillVO);
								shipbillService.createReturnShipBill(signInShipBillVO);
							}
						}
					}
				}
			}

			Criteria criteriaDetail = Criteria.forClass(TmsLoadingBillDetailModel.class);
			r1 = Restrictions.eq("shipbillId", tmsShipbillHeaderModel.getShipbillId());
			r2 = Restrictions.eq(TmsLoadingBillDetailModel::getEnterpriseId, user.getEnterpriseId());
			criteriaDetail.setRestriction(Restrictions.and(r1, r2));
			criteriaDetail.setOrder(Order.newInstance().desc(new String[] { "createtime" }));
			List<TmsLoadingBillDetailModel> tmsLoadingBillDetails = tmsLoadingBillDetailMapper.findByCriteria(criteriaDetail);
			if (ToolKits.isEmpty(tmsLoadingBillDetails)) {
				throw new PrologException("装车单明细【" + tmsShipbillHeaderModel.getShipbillId() + "】查询失败");
			}
			TmsLoadingBillDetailModel tmsLoadingBillDetail = tmsLoadingBillDetails.get(0);
			TmsLoadingBillHeaderModel tmsLoadingBillHeaderModel = tmsLoadingBillHeaderMapper.findById(tmsLoadingBillDetail.getLoadingBillId(), TmsLoadingBillHeaderModel.class);
			if (StrUtil.isNotBlank(tmsLoadingBillHeaderModel.getVehicleDeviceId()) && StrUtil.isNotBlank(tmsLoadingBillHeaderModel.getVehicleDeviceCode())) {
				Criteria criteria = Criteria.forClass(TmsLoadingBillHeaderModel.class);
				Restriction restriction1 = Restrictions.eq(TmsLoadingBillHeaderModel::getVehicleDeviceCode, tmsLoadingBillHeaderModel.getVehicleDeviceCode());
				Restriction restriction2 = Restrictions.between(TmsLoadingBillHeaderModel::getStatus, DataDictionaryConstant.LOADING_BILL_STATUS_QY_PART, DataDictionaryConstant.LOADING_BILL_STATUS_SD_PART);
				criteria.setRestriction(Restrictions.and(restriction1, restriction2));
				if (tmsLoadingBillHeaderMapper.findCountByCriteria(criteria) == 0) {
					String deviceId = tmsLoadingBillHeaderModel.getVehicleDeviceId().split(",")[0];
					try {
						RestMessage<DeviceByOneDTO> restMessage = maindataTmsResource.deviceGetOne(Long.valueOf(deviceId));
						DeviceByOneDTO deviceByOneDTO = restMessage.getData();
						if (BussinessConstant.E6.equals(deviceByOneDTO.getCompanyName())) {
							redisTemplate.opsForSet().remove(RedisConstant.PULL_GPS_DEVICE_E6_KEY, tmsLoadingBillHeaderModel.getVehicleDeviceCode());
							log.info("易流 remove loadingBillId={},vehicle={},deviceCode={}", tmsLoadingBillDetail.getLoadingBillId(), tmsLoadingBillHeaderModel.getVehiclePlateNumber(), deviceByOneDTO.getCode());
						} else if (BussinessConstant.G7.equals(deviceByOneDTO.getCompanyName())) {
							redisTemplate.opsForSet().remove(RedisConstant.PULL_GPS_DEVICE_G7_KEY, tmsLoadingBillHeaderModel.getVehicleDeviceCode());
							log.info("g7 remove loadingBillId={},vehicle={},deviceCode={}", tmsLoadingBillDetail.getLoadingBillId(), tmsLoadingBillHeaderModel.getVehiclePlateNumber(), deviceByOneDTO.getCode());
						}
					} catch (Exception e) {
						log.error("移除redis队列错误", e);
					}
				}
			}

			// 运单同步BMS
			List<String> loadingDetailIds = Lists.newArrayList();
			if (DataDictionaryConstant.SHIPBILL_STATUS_END.equals(Integer.valueOf(status))
					&& !DataDictionaryConstant.SHIPBILL_ABNORMAL_STATUS.equals(tmsShipbillHeaderModel.getAbnormalStatus())) {
				loadingDetailIds.add(tmsLoadingBillDetail.getId());
				shipbillCommonService.pushShipbillBmsData(loadingDetailIds);
			}
			MessageUtil.addMessage(new SendMessageDTO(MessageOrderTypeEnum.SHIP_NO.getCode(), MessageTypeEnum.DELIVERY.getCode(), Lists.newArrayList(tmsShipbillHeaderModel.getShipbillId())));
		});
	}

	/**
	 * 父运单同步送达
	 *
	 * @param shipbillId
	 * @param date
	 * @param user
	 * @param deliverySignTime
	 * @param goodsPhoto
	 * @param receiptPhoto
	 * @param mapTransportLogUpdate
	 * @return
	 */
	private String fatherDeliveredConfirm(Integer status, String shipbillId, Date date, UserEntity user, boolean deliverySignTime, String goodsPhoto, String receiptPhoto, String nodeEvent, Map<String, Object> mapTransportLogUpdate) {
		// 查询运单
		TmsShipbillHeaderModel tmsShipbillHeaderModel = tmsShipbillHeaderMapper.findById(shipbillId, TmsShipbillHeaderModel.class);

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

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

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

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

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

				// 运单节点保存
				// 获取节点ID
				RestMessage<String> restMessage = maindataFeign.getCodeNumberByCode(SeriaNnumberConstant.TMS_SHIPBILL_NODE_TRACKING_ID, "L");
				if (!restMessage.isSuccess()) {
					throw new RuntimeException("生成节点ID失败");
				}
				String id = restMessage.getData();

				// 节点记录
				ShipbillNodeTracking model = new ShipbillNodeTracking();
				model.setNodeDate(date);
				model.setShipbillId(shipbillId);
				model.setShipbillNo(shipbillId);
				model.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_SD);
				model.setNodeEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_SD);
				model.setUserId(user.getUserid());
				model.setUserName(user.getNickname());
				model.setEnterpriseId(user.getEnterpriseId());
				model.setEnterpriseName(user.getEnterpriseName());
				model.setPicUrl(goodsPhoto);
				model.setId(id);
				model.setUserId(user.getUserid());
				model.setUserName(user.getNickname());
				model.setEnterpriseId(user.getEnterpriseId());
				model.setEnterpriseName(user.getEnterpriseName());
				model.setCreateperson(user.getNickname());
				model.setCreatetime(date);
				model.setUpdateperson(user.getNickname());
				model.setUpdatetime(date);
				tmsShipbillNodeTrackingMapper.save(model);

				// 运单日志保存
				// 获取日志ID
				RestMessage<String> restMessageLog = maindataFeign.getCodeNumberByCode(SeriaNnumberConstant.TMS_SHIPBILL_OPERATE_LOG_ID, "L");
				if (!restMessageLog.isSuccess()) {
					throw new RuntimeException("生成日志ID失败");
				}
				String idLog = restMessageLog.getData();
				// 日志记录
				TmsShipbillOperateLogModel logModel = new TmsShipbillOperateLogModel();
				logModel.setShipbillId(shipbillId);
				logModel.setShipbillNo(shipbillId);
				logModel.setOperateEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_SD);
				logModel.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_QY);
				logModel.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_SD);
				logModel.setOperateDate(date);
				logModel.setEnterpriseId(user.getEnterpriseId());
				logModel.setEnterpriseName(user.getEnterpriseName());
				logModel.setUserId(user.getUserid());
				logModel.setUserName(user.getNickname());
				logModel.setId(idLog);
				logModel.setOperateDate(date);
				logModel.setUserId(user.getUserid());
				logModel.setUserName(user.getNickname());
				logModel.setEnterpriseId(user.getEnterpriseId());
				logModel.setEnterpriseName(user.getEnterpriseName());
				logModel.setCreateperson(user.getNickname());
				logModel.setCreatetime(date);
				logModel.setUpdateperson(user.getNickname());
				logModel.setUpdatetime(date);

				tmsShipbillOperateLogMapper.save(logModel);

				if (com.prolog.common.util.ToolKits.isNotEmpty(receiptPhoto)) {
					// 运单节点保存
					// 获取节点ID
					RestMessage<String> restMessage1 = maindataFeign.getCodeNumberByCode(SeriaNnumberConstant.TMS_SHIPBILL_NODE_TRACKING_ID, "L");
					if (!restMessage1.isSuccess()) {
						throw new RuntimeException("生成节点ID失败");
					}
					String id1 = restMessage1.getData();

					// 节点记录
					ShipbillNodeTracking model1 = new ShipbillNodeTracking();
					model1.setNodeDate(date);
					model1.setShipbillId(shipbillId);
					model1.setShipbillNo(shipbillId);
					model1.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_HD_PIC);
					model1.setNodeEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_HD_PIC);
					model1.setUserId(user.getUserid());
					model1.setUserName(user.getNickname());
					model1.setEnterpriseId(user.getEnterpriseId());
					model1.setEnterpriseName(user.getEnterpriseName());
					model1.setPicUrl(receiptPhoto);
					model1.setId(id1);
					model1.setUserId(user.getUserid());
					model1.setUserName(user.getNickname());
					model1.setEnterpriseId(user.getEnterpriseId());
					model1.setEnterpriseName(user.getEnterpriseName());
					model1.setCreateperson(user.getNickname());
					model1.setCreatetime(date);
					model1.setUpdateperson(user.getNickname());
					model1.setUpdatetime(date);
					tmsShipbillNodeTrackingMapper.save(model1);

					// 运单日志保存
					// 获取日志ID
					RestMessage<String> restMessageLog1 = maindataFeign.getCodeNumberByCode(SeriaNnumberConstant.TMS_SHIPBILL_OPERATE_LOG_ID, "L");
					if (!restMessageLog1.isSuccess()) {
						throw new RuntimeException("生成日志ID失败");
					}
					String idLog1 = restMessageLog1.getData();
					// 日志记录
					TmsShipbillOperateLogModel logModel1 = new TmsShipbillOperateLogModel();
					logModel1.setShipbillId(shipbillId);
					logModel1.setShipbillNo(shipbillId);
					logModel1.setOperateEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_HD_PIC);
					logModel1.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_QY);
					logModel1.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_HD_PIC);
					logModel1.setOperateDate(date);
					logModel1.setEnterpriseId(user.getEnterpriseId());
					logModel1.setEnterpriseName(user.getEnterpriseName());
					logModel1.setUserId(user.getUserid());
					logModel1.setUserName(user.getNickname());
					logModel1.setId(idLog);
					logModel1.setOperateDate(date);
					logModel1.setUserId(user.getUserid());
					logModel1.setUserName(user.getNickname());
					logModel1.setEnterpriseId(user.getEnterpriseId());
					logModel1.setEnterpriseName(user.getEnterpriseName());
					logModel1.setCreateperson(user.getNickname());
					logModel1.setCreatetime(date);
					logModel1.setUpdateperson(user.getNickname());
					logModel1.setUpdatetime(date);

					tmsShipbillOperateLogMapper.save(logModel);
				}
				fatherShipbillHeaderModel.setStatus(status);
				tmsShipbillHeaderMapper.update(fatherShipbillHeaderModel);
				return fatherShipbillHeaderModel.getShipbillId();
			}
		}
		return null;
	}

	/*
	 * 异常登记
	 */
	@Override
	public void pendingDeliveryAbnormalReport(PendingDeliveryAbnormalReportVO pendingDeliveryAbnormalReportVO) throws Exception {
		ToolKits.isParamNull(pendingDeliveryAbnormalReportVO, "请求参数不能为空");
		ToolKits.isParamNull(pendingDeliveryAbnormalReportVO.getShipbillId(), "运单ID不能为空");
		ToolKits.isParamNull(pendingDeliveryAbnormalReportVO.getAbnormalType(), "异常原因不能为空");
//		ToolKits.isParamNull(pendingDeliveryAbnormalReportVO.getAbnormalContent(), "异常内容不能为空");

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

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

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

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

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

		StringBuffer nodeEvent = new StringBuffer(DataDictionaryConstant.SHIPBILL_NODE_ABNORMAL_REGISTER);
		nodeEvent.append("异常类型为:");
		nodeEvent.append(PublicMethods.change(data1, String.valueOf(pendingDeliveryAbnormalReportVO.getAbnormalType())));
		nodeEvent.append(",异常事件为:");
		nodeEvent.append(PublicMethods.change(data2, String.valueOf(pendingDeliveryAbnormalReportVO.getAbnormalEvent())));
		nodeEvent.append(",客户是否投诉为:");
		nodeEvent.append(ObjectUtil.equal(1, pendingDeliveryAbnormalReportVO.getIsComplaint()) ? "是" : "否");
		if (ToolKits.isNotEmpty(pendingDeliveryAbnormalReportVO.getAbnormalContent())) {
			nodeEvent.append(",异常内容为:");
			nodeEvent.append(pendingDeliveryAbnormalReportVO.getAbnormalContent());
		}

		Criteria criteriaTransportLog = Criteria.forClass(TmsShipbillTransLogModel.class);
		Restriction r1 = Restrictions.eq(TmsShipbillTransLogModel::getEnterpriseId, user.getEnterpriseId());
		Restriction r2 = Restrictions.in(TmsShipbillTransLogModel::getShipbillId, pendingDeliveryAbnormalReportVO.getShipbillId().split(","));
		criteriaTransportLog.setRestriction(Restrictions.and(r1, r2));
		List<TmsShipbillTransLogModel> transportLogModels = tmsShipbillTransportLogMapper.findByCriteria(criteriaTransportLog);

		if (ObjectUtils.isEmpty(transportLogModels)) {
			throw new RuntimeException("未找到对应的运单！");
		}

		for (TmsShipbillTransLogModel logModel : transportLogModels) {
			logModel.setAbnormalTime(date);
			logModel.setAbnormalType(pendingDeliveryAbnormalReportVO.getAbnormalType());
			logModel.setAbnormalContent(pendingDeliveryAbnormalReportVO.getAbnormalContent());
			logModel.setAbnormalEvent(pendingDeliveryAbnormalReportVO.getAbnormalEvent());
			logModel.setAbnormalComplain(pendingDeliveryAbnormalReportVO.getIsComplaint());
			logModel.setAbnormalPicture(pendingDeliveryAbnormalReportVO.getAbnormalPicUrl());
			logModel.setUpdateperson(user.getNickname());
			logModel.setUpdatetime(date);
			tmsShipbillTransportLogMapper.update(logModel);

			// 更新运单异常状态
			TmsShipbillHeaderModel tmsShipbillHeaderModel = tmsShipbillHeaderMapper.findById(logModel.getShipbillId(), TmsShipbillHeaderModel.class);
			ToolKits.isParamNull(tmsShipbillHeaderModel, "运单ID【" + tmsShipbillHeaderModel.getShipbillId() + "】不存在");
			tmsShipbillHeaderModel.setAbnormalStatus(DataDictionaryConstant.SHIPBILL_ABNORMAL_STATUS);
			tmsShipbillHeaderModel.setUpdateperson(user.getNickname());
			tmsShipbillHeaderModel.setUpdatetime(date);
			tmsShipbillHeaderMapper.update(tmsShipbillHeaderModel);

			// 更新装车单明细异常状态
			Criteria criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
			Restriction r3 = Restrictions.eq(TmsLoadingBillDetailModel::getEnterpriseId, user.getEnterpriseId());
			Restriction r4 = Restrictions.eq(TmsLoadingBillDetailModel::getShipbillId, tmsShipbillHeaderModel.getShipbillId());
			criteria.setRestriction(Restrictions.and(r3, r4));
			List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteria);
			ToolKits.isParamNull(tmsLoadingBillDetailModels, "装车运单【" + logModel.getShipbillId() + "】不存在");
			for (TmsLoadingBillDetailModel tmsLoadingBillDetailModel : tmsLoadingBillDetailModels) {
				tmsLoadingBillDetailModel.setAbnormalStatus(DataDictionaryConstant.SHIPBILL_ABNORMAL_STATUS);
				tmsLoadingBillDetailModel.setUpdateperson(user.getNickname());
				tmsLoadingBillDetailModel.setUpdatetime(date);
				tmsLoadingBillDetailMapper.update(tmsLoadingBillDetailModel);
			}

			// STD-DEVELOP20220823 lhb 异常登记 20220914 start
			// 运单节点保存
			ShipbillNodeTrackingSaveNewVO nodeTrackingVO = new ShipbillNodeTrackingSaveNewVO();
			nodeTrackingVO.setNodeDate(date);
			nodeTrackingVO.setShipbillId(tmsShipbillHeaderModel.getShipbillId());
			nodeTrackingVO.setShipbillNo(tmsShipbillHeaderModel.getShipbillId());
			nodeTrackingVO.setStatus(tmsShipbillHeaderModel.getStatus());
			nodeTrackingVO.setNodeEvent(nodeEvent.toString());
			nodeTrackingVO.setUserId(user.getUserid());
			nodeTrackingVO.setUserName(user.getNickname());
			nodeTrackingVO.setEnterpriseId(user.getEnterpriseId());
			nodeTrackingVO.setEnterpriseName(user.getEnterpriseName());
			nodeTrackingVO.setPicUrl(pendingDeliveryAbnormalReportVO.getAbnormalPicUrl());
			shipbillNodeTrackingService.addShipbillNodeTrackingNewData(nodeTrackingVO);

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

			// 获取运单异常表ID
			RestMessage<String> restMessageDetailId = maindataTmsResource.getCodeNumberByCode(SeriaNnumberConstant.TMS_SHIPBILL_ABNORMAL_ID, "L");
			if (!restMessageDetailId.isSuccess()) {
				throw new RuntimeException("生成运单异常表ID失败:" + restMessageDetailId.getMessage());
			}
			TmsShipbillAbnormalModel abnormalModel = new TmsShipbillAbnormalModel();
			abnormalModel.setId(restMessageDetailId.getData());
			abnormalModel.setShipbillId(tmsShipbillHeaderModel.getShipbillId());
			abnormalModel.setShipbillNo(tmsShipbillHeaderModel.getShipbillId());
			abnormalModel.setAbnormalTime(date);
			abnormalModel.setAbnormalType(pendingDeliveryAbnormalReportVO.getAbnormalType());
			abnormalModel.setAbnormalEvent(pendingDeliveryAbnormalReportVO.getAbnormalEvent());
			abnormalModel.setAbnormalComplain(pendingDeliveryAbnormalReportVO.getIsComplaint());
			abnormalModel.setAbnormalContent(pendingDeliveryAbnormalReportVO.getAbnormalContent());
			abnormalModel.setAbnormalPhoto(pendingDeliveryAbnormalReportVO.getAbnormalPicUrl());
			abnormalModel.setAbnormalStatus(DataDictionaryConstant.SHIPBILL_ABNORMAL_STATUS);
			abnormalModel.setEnterpriseId(user.getEnterpriseId());
			abnormalModel.setEnterpriseName(user.getEnterpriseName());
			abnormalModel.setCreateperson(user.getNickname());
			abnormalModel.setCreatetime(date);
			tmsShipbillAbnormalMapper.save(abnormalModel);
			// 递归对上级运单进行异常上报
			String fatherShipbillId = tmsShipbillHeaderModel.getFatherShipbillId();
			while (ToolKits.isNotEmpty(fatherShipbillId)) {
				fatherShipbillId = abnormalSendFather(fatherShipbillId, nodeTrackingVO, operateLogVO, pendingDeliveryAbnormalReportVO, date, user);
			}
			// STD-DEVELOP20220823 lhb 异常登记 20220914 end
		}
	}

	/**
	 * 递归对上级运单进行异常上报
	 *
	 */
	private String abnormalSendFather(String shipbillId, ShipbillNodeTrackingSaveNewVO nodeTrackingVO, ShipbillOperateLogSaveNewVO operateLogVO, PendingDeliveryAbnormalReportVO vo, Date date, UserEntity user) {
		TmsShipbillHeaderModel fatherShipbill = tmsShipbillHeaderMapper.findById(shipbillId, TmsShipbillHeaderModel.class);
		if (ToolKits.isNotEmpty(fatherShipbill.getFatherShipbillId()) && !fatherShipbill.getFatherShipbillId().equals(shipbillId)) {
			// 更新运单异常状态为【异常】
			fatherShipbill.setAbnormalStatus(DataDictionaryConstant.SHIPBILL_ABNORMAL_STATUS);
			fatherShipbill.setUpdateperson(nodeTrackingVO.getUserName());
			fatherShipbill.setUpdatetime(date);
			tmsShipbillHeaderMapper.update(fatherShipbill);

			// 更新运单运输记录
			Map<String, Object> queryMap = Maps.newHashMap();
			queryMap.put("shipbillId", fatherShipbill.getShipbillId());
			List<TmsShipbillTransLogModel> tmsShipbillTransportLogs = tmsShipbillTransportLogMapper.findByMap(queryMap, TmsShipbillTransLogModel.class);
			if (ToolKits.isNotEmpty(tmsShipbillTransportLogs) && tmsShipbillTransportLogs.size() > 0) {
				TmsShipbillTransLogModel tmsShipbillTransportLog = tmsShipbillTransportLogs.get(0);
				tmsShipbillTransportLog.setAbnormalType(vo.getAbnormalType());
				tmsShipbillTransportLog.setAbnormalEvent(vo.getAbnormalEvent());
				tmsShipbillTransportLog.setAbnormalComplain(vo.getIsComplaint());
				tmsShipbillTransportLog.setAbnormalContent(vo.getAbnormalContent());
				tmsShipbillTransportLog.setAbnormalTime(date);
				tmsShipbillTransportLogMapper.update(tmsShipbillTransportLog);
			}

			// 运单节点保存
			nodeTrackingVO.setNodeDate(DateUtil.date());
			nodeTrackingVO.setShipbillId(fatherShipbill.getShipbillId());
			nodeTrackingVO.setShipbillNo(fatherShipbill.getShipbillId());
			shipbillNodeTrackingService.addShipbillNodeTrackingNewData(nodeTrackingVO);

			// 运单日志保存
			operateLogVO.setOperateDate(DateUtil.date());
			operateLogVO.setShipbillId(fatherShipbill.getShipbillId());
			operateLogVO.setShipbillNo(fatherShipbill.getShipbillId());
			shipbillOperateLogService.addShipbillOperateLogNewData(operateLogVO);

			// STD-DEVELOP20220823 lhb 异常登记 20220914 start
			// 获取运单异常表ID
			RestMessage<String> restMessageDetailId = maindataTmsResource.getCodeNumberByCode(SeriaNnumberConstant.TMS_SHIPBILL_ABNORMAL_ID, "L");
			if (!restMessageDetailId.isSuccess()) {
				throw new RuntimeException("生成运单异常表ID失败:" + restMessageDetailId.getMessage());
			}
			TmsShipbillAbnormalModel abnormalModel = new TmsShipbillAbnormalModel();
			abnormalModel.setId(restMessageDetailId.getData());
			abnormalModel.setShipbillId(fatherShipbill.getShipbillId());
			abnormalModel.setShipbillNo(fatherShipbill.getShipbillId());
			abnormalModel.setAbnormalTime(date);
			abnormalModel.setAbnormalType(vo.getAbnormalType());
			abnormalModel.setAbnormalEvent(vo.getAbnormalEvent());
			abnormalModel.setAbnormalComplain(vo.getIsComplaint());
			abnormalModel.setAbnormalContent(vo.getAbnormalContent());
			abnormalModel.setAbnormalPhoto(vo.getAbnormalPicUrl());
			abnormalModel.setAbnormalStatus(DataDictionaryConstant.SHIPBILL_ABNORMAL_STATUS);
			abnormalModel.setEnterpriseId(user.getEnterpriseId());
			abnormalModel.setEnterpriseName(user.getEnterpriseName());
			abnormalModel.setCreateperson(user.getNickname());
			abnormalModel.setCreatetime(DateUtil.date());
			tmsShipbillAbnormalMapper.save(abnormalModel);
			// STD-DEVELOP20220823 lhb 异常登记 20220914 end

			return fatherShipbill.getFatherShipbillId();
		}
		return null;
	}

	@Override
	public void shipbillServiceEvaluation(ShipbillServiceEvaluationVO shipbillServiceEvaluationVO) throws Exception {
		ToolKits.isParamNull(shipbillServiceEvaluationVO, "请求参数不能为空");
		ToolKits.isParamNull(shipbillServiceEvaluationVO.getShipbillId(), "运单ID不能为空");
		ToolKits.isParamNull(shipbillServiceEvaluationVO.getEnterpriseId(), "企业ID不能为空");
		ToolKits.isParamNull(shipbillServiceEvaluationVO.getServiceRating(), "服务评价评分不能为空");
		ToolKits.isParamNull(shipbillServiceEvaluationVO.getServiceProblem(), "服务评价问题不能为空");
		// ToolKits.isParamNull(shipbillServiceEvaluationVO.getServicePictures(),
		// "异常内容不能为空");
		ToolKits.isParamNull(shipbillServiceEvaluationVO.getServiceObject(), "服务评价对象不能为空");

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

		Criteria criteriaTransportLog = Criteria.forClass(TmsShipbillTransLogModel.class);
		Restriction r1 = Restrictions.eq(TmsShipbillTransLogModel::getEnterpriseId, shipbillServiceEvaluationVO.getEnterpriseId());
		Restriction r2 = Restrictions.eq(TmsShipbillTransLogModel::getShipbillId, shipbillServiceEvaluationVO.getShipbillId());
		criteriaTransportLog.setRestriction(Restrictions.and(r1, r2));
		List<TmsShipbillTransLogModel> transportLogModels = tmsShipbillTransportLogMapper.findByCriteria(criteriaTransportLog);

		if (ObjectUtils.isEmpty(transportLogModels)) {
			throw new RuntimeException("未找到对应的运单！");
		}

		for (TmsShipbillTransLogModel logModel : transportLogModels) {
//			logModel.setServiceDate(new Date());
//			logModel.setServiceDescription(shipbillServiceEvaluationVO.getServiceDescription());
//			logModel.setServiceObject(shipbillServiceEvaluationVO.getServiceObject());
//			logModel.setServicePictures(shipbillServiceEvaluationVO.getServicePictures());
//			logModel.setServiceProblem(shipbillServiceEvaluationVO.getServiceProblem());
//			logModel.setServiceRating(shipbillServiceEvaluationVO.getServiceRating());
//			tmsShipbillTransportLogMapper.update(logModel);
			ShipbillEvaluationAddOrUpdateVO vo = new ShipbillEvaluationAddOrUpdateVO();
			vo.setShipbillId(logModel.getShipbillId());
			vo.setEvaluationStar(BigDecimal.valueOf(shipbillServiceEvaluationVO.getServiceRating()));
			vo.setEvaluationTarget(shipbillServiceEvaluationVO.getServiceObject());
			vo.setProblemType(shipbillServiceEvaluationVO.getServiceProblem());
			vo.setProblemDesc(shipbillServiceEvaluationVO.getServiceDescription());
			vo.setPicUrl(shipbillServiceEvaluationVO.getServicePictures());
			shipbillEvaluationService.addOrUpdate(vo);
		}
	}

	/**
	 * 开启审批流程
	 * 
	 * @param model
	 * @param approvalFlowType
	 * @param approvalObjectId
	 * @return
	 */
	private Boolean approvalOpen(TmsShipbillHeaderModel model, Integer approvalFlowType, String approvalObjectId) {
		UserEntity user = PlgFxUsrUtils.getUserEntity();
		ApprovalOpenVO approvalOpenVO = new ApprovalOpenVO();
		approvalOpenVO.setApprovalFlowType(approvalFlowType);
		approvalOpenVO.setApprovalObjectId(approvalObjectId);
		approvalOpenVO.setApprovalObjectCode(approvalObjectId);
		approvalOpenVO.setApprovalObjectName(approvalObjectId);
		approvalOpenVO.setInitiatedUserId(user.getUserid());
		approvalOpenVO.setInitiatedUserName(user.getNickname());
		approvalOpenVO.setDeliveryMethodType(model.getDeliveryMethodType());
		approvalOpenVO.setShipperType(model.getShipperType());
		approvalOpenVO.setShipperUnitId(model.getShipperUnitId());
		approvalOpenVO.setConsigneeType(model.getConsigneeType());
		approvalOpenVO.setConsigneeUnitId(model.getConsigneeUnitId());
		approvalOpenVO.setOrderType(model.getOrderType());
		approvalOpenVO.setOrderBusinessType(model.getOrderBusinessType());
		approvalOpenVO.setTransportType(model.getTransportType());
		approvalOpenVO.setTemperatureRequirement(model.getTemperatureRequirement());
		approvalOpenVO.setCargoOwnerId(model.getCargoOwnerId());
		approvalOpenVO.setDepartmentId(model.getDepartmentId());
		RestMessage<Boolean> restMessage1 = maindataFeign.openExecute(approvalOpenVO);
		if (!restMessage1.isSuccess()) {
			throw new BizException("调用maindata服务是否开启审批流接口失败:流程类型=" + approvalFlowType + ",错误信息=" + restMessage1.getMessage());
		}
		return restMessage1.getData();
	}
}
