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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
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.core.exception.BizException;
import com.prolog.framework.core.exception.PrologException;
import com.prolog.framework.core.pojo.Page;
import com.prolog.framework.core.restriction.Criteria;
import com.prolog.framework.core.restriction.Order;
import com.prolog.framework.core.restriction.Restriction;
import com.prolog.framework.core.restriction.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.*;
import com.prolog.rdc.tms.app.model.dto.AppointmentHeaderDTO;
import com.prolog.rdc.tms.app.model.dto.business.PendingDisPackageDTO;
import com.prolog.rdc.tms.app.model.dto.business.PendingDisShipBillDtlDTO;
import com.prolog.rdc.tms.app.model.dto.business.QueryTypeByAppointmentDTO;
import com.prolog.rdc.tms.app.model.dto.business.QueryTypeByShipbillDTO;
import com.prolog.rdc.tms.app.model.entity.*;
import com.prolog.rdc.tms.app.model.vo.business.*;
import com.prolog.rdc.tms.app.service.business.ShipbillNodeTrackingService;
import com.prolog.rdc.tms.app.service.business.ShipbillOperateLogService;
import com.prolog.rdc.tms.app.service.business.WaitLoadingAndUnloadingService;
import com.prolog.rdc.tms.app.util.BusinessFlowUtil;
import com.prolog.rdc.tms.app.util.DataUtils;
import com.prolog.rdc.tms.app.util.MessageUtil;
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.rmi.feign.MaindataFeign;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 待装卸实现层
 *
 * @author xiaoyf
 * @since 2022/6/6 10:35
 */
@Service
public class WaitLoadingAndUnloadingServiceImpl implements WaitLoadingAndUnloadingService {

	@Autowired
	private TmsLoadingBillHeaderMapper tmsLoadingBillHeaderMapper;

	@Autowired
	private TmsLoadingBillDetailMapper tmsLoadingBillDetailMapper;

	@Autowired
	private TmsShipbillHeaderMapper tmsShipbillHeaderMapper;

	@Autowired
	private TmsShipbillDetailMapper tmsShipbillDetailMapper;

	@Autowired
	private TmsShipbillPackageMapper tmsShipbillPackageMapper;

	@Autowired
	private MaindataFeign maindataTmsResource;

	@Autowired
	private ShipbillOperateLogService shipbillOperateLogService;

	@Autowired
	private TmsShipbillTransportLogMapper tmsShipbillTransportLogMapper;

	@Autowired
	private ShipbillNodeTrackingService shipbillNodeTrackingService;

	@Autowired
	private BusinessFlowUtil businessFlowUtil;

	@Autowired
	private TmsAppointmentHeaderMapper tmsAppointmentHeaderMapper;

	@Autowired
	private TmsAppointmentDetailMapper tmsAppointmentDetailMapper;

	SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

	/**
	 * 预约单查询
	 *
	 * @param
	 * @return
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public Page<QueryTypeByAppointmentDTO> queryAppointment(QueryTypeByAppointmentVO vo) throws Exception {
		UserEntity user = PlgFxUsrUtils.getUserEntity();
		ToolKits.isParamNull(user, "当前人员没有操作权限");

		if (!user.getUserType().equals(BussinessConstant.USER_TYPE_ZY)) {
			throw new PrologException("当前人员没有操作权限");
		}
		List<QueryTypeByAppointmentDTO> dtos = Lists.newArrayList();
		// 查询装卸工已经做了开始装卸的预约单
		Criteria ulCriteria = Criteria.forClass(TmsAppointmentHeaderModel.class);
		Restriction r11 = Restrictions.eq(TmsAppointmentHeaderModel::getLoadAndUnloadWorkerId, user.getUserid());
		Restriction r22 = Restrictions.eq(TmsAppointmentHeaderModel::getBranchId, vo.getBranchId());
		Integer[] status = { DataDictionaryConstant.APPOINTMENT_STATUS_YJH,
				DataDictionaryConstant.APPOINTMENT_STATUS_KSZX };
		Restriction r44 = Restrictions.in(TmsAppointmentHeaderModel::getStatus, status);
		//Restriction r55 = Restrictions.between(TmsAppointmentHeaderModel::getAppointmentDate, sdf.parse(sdf.format(new Date())), sdf.parse(sdf.format(new Date())));
		ulCriteria.setRestriction(Restrictions.and(r11, r22, r44));
		ulCriteria.setOrder(Order.newInstance().asc(TmsAppointmentHeaderModel::getCallNumber));

		PageUtils.startPage(vo.getPageNum(), vo.getPageSize());
		List<TmsAppointmentHeaderModel> ulTmsAppointmentHeaderModels = tmsAppointmentHeaderMapper.findByCriteria(ulCriteria);
		if (ToolKits.isNotEmpty(ulTmsAppointmentHeaderModels)) {
			for (TmsAppointmentHeaderModel model:ulTmsAppointmentHeaderModels) {
				QueryTypeByAppointmentDTO dto = new QueryTypeByAppointmentDTO();
				BeanUtils.copyProperties(model, dto);

				dto.setHasTakeNumAndCallNum(false);
				Map<String, Object> queryMap = Maps.newHashMap();
				queryMap.put("appointmentId", model.getAppointmentId());
				List<TmsAppointmentDetailModel> tmsAppointmentDetails = tmsAppointmentDetailMapper.findByMap(queryMap, TmsAppointmentDetailModel.class);
				//设置预约单的派车单
				dto.setLoadingBillIds(DataUtils.getLoadingBillIds(tmsAppointmentDetails));
				List<String> shipbillIds = Lists.newArrayList();
				for (TmsAppointmentDetailModel tmsAppointmentDetail : tmsAppointmentDetails) {
					if (tmsAppointmentDetail.getFlowConfig().contains(DataDictionaryConstant.FLOW_CONFIG_APPOINTMENT_TN_CN)) {
						dto.setHasTakeNumAndCallNum(true);
					}
					shipbillIds.add(tmsAppointmentDetail.getShipbillId());
				}
				if (shipbillIds.size() == 0) {
					throw new PrologException("预约单明细不能为空");
				}
				// 获取包裹信息
				Criteria criteriaPkg = Criteria.forClass(TmsShipbillPackageModel.class);
				Restriction rr1 = Restrictions.in(TmsShipbillPackageModel::getShipbillId, shipbillIds.toArray());
				Restriction rr2 = Restrictions.eq(TmsShipbillPackageModel::getEnterpriseId, user.getEnterpriseId());
				criteriaPkg.setRestriction(Restrictions.and(rr1, rr2));
				criteriaPkg.setOrder(Order.newInstance().desc(new String[]{"updatetime"}));

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

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

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

					List<PendingDisShipBillDtlDTO> detailDTOList = Lists.newArrayList();
					for (TmsShipbillDetailModel detailModel : tmsShipbillDetailModels) {
						PendingDisShipBillDtlDTO detailDTO = new PendingDisShipBillDtlDTO();
						BeanUtils.copyProperties(detailModel, detailDTO);
						detailDTOList.add(detailDTO);
					}
					// 商品信息
					dto.setShipBillDetailDTOS(detailDTOList);
				}
				dtos.add(dto);
			}
			Page<QueryTypeByAppointmentDTO> page = PageUtils.getPage(dtos);
			if (ulTmsAppointmentHeaderModels instanceof com.github.pagehelper.Page) {
				com.github.pagehelper.Page<TmsAppointmentHeaderModel> p0 = (com.github.pagehelper.Page<TmsAppointmentHeaderModel>) ulTmsAppointmentHeaderModels;
				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;
		}

		Page<QueryTypeByAppointmentDTO> pageNoTakeNumAndCallNum = queryNoTakeNumAndCallNum(vo);
		if (ToolKits.isNotEmpty(pageNoTakeNumAndCallNum)) {
			return pageNoTakeNumAndCallNum;
		}

		Criteria criteria = Criteria.forClass(TmsAppointmentHeaderModel.class);
		Restriction r1 = Restrictions.eq("branchId", vo.getBranchId());
		Restriction r2 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
		Restriction r4 = Restrictions.in(TmsAppointmentHeaderModel::getStatus, new Integer[] { DataDictionaryConstant.APPOINTMENT_STATUS_DDZ, DataDictionaryConstant.APPOINTMENT_STATUS_YQH });
		Restriction r5 = Restrictions.eq(TmsAppointmentHeaderModel::getTallyStatus, DataDictionaryConstant.TALLY_STATUS_LHWC);
		criteria.setRestriction(Restrictions.and(r1, r2, r4, r5));
		criteria.setOrder(Order.newInstance().asc(new String[] { "callNumber" }));
		List<TmsAppointmentHeaderModel> tmsAppointmentHeaderModels = tmsAppointmentHeaderMapper.findByCriteria(criteria);
		if (ToolKits.isEmpty(tmsAppointmentHeaderModels)) {
			throw new PrologException("当前没有可以叫号的预约单!");
		}
		// 当前时间
		Date date = DateUtils.nowDate();
		TmsAppointmentHeaderModel model = tmsAppointmentHeaderModels.get(0);
		// 更新当前被叫号的预约单状态为【已叫号】
		model.setStatus(DataDictionaryConstant.APPOINTMENT_STATUS_YJH);
		model.setUpdateperson(user.getNickname());
		model.setUpdatetime(date);

		model.setLoadAndUnloadWorkerId(user.getUserid());
		model.setLoadAndUnloadWorkerCode(String.valueOf(user.getUserid()));
		model.setLoadAndUnloadWorkerName(user.getNickname());
		tmsAppointmentHeaderMapper.update(model);

		// 更新装车单明细为开始装卸
		upLoadingDetail(model, user, date);

		QueryTypeByAppointmentDTO dto = new QueryTypeByAppointmentDTO();
		BeanUtils.copyProperties(model, dto);
		dto.setHasTakeNumAndCallNum(true);

		Map<String, Object> queryMap = Maps.newHashMap();
		queryMap.put("appointmentId", model.getAppointmentId());
		List<TmsAppointmentDetailModel> tmsAppointmentDetails = tmsAppointmentDetailMapper.findByMap(queryMap, TmsAppointmentDetailModel.class);

		//设置预约单的派车单
		dto.setLoadingBillIds(DataUtils.getLoadingBillIds(tmsAppointmentDetails));
		List<String> shipbillIds = Lists.newArrayList();
		for (TmsAppointmentDetailModel tmsAppointmentDetail : tmsAppointmentDetails) {
			if (!tmsAppointmentDetail.getFlowConfig().contains(DataDictionaryConstant.FLOW_CONFIG_APPOINTMENT_TN_CN)) {
				throw new PrologException("预约单没有叫号流程");
			}
			shipbillIds.add(tmsAppointmentDetail.getShipbillId());
		}

		if (shipbillIds.size() == 0) {
			throw new PrologException("预约单明细不能为空");
		}

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

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

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

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

			List<PendingDisShipBillDtlDTO> detailDTOList = Lists.newArrayList();
			for (TmsShipbillDetailModel detailModel : tmsShipbillDetailModels) {
				PendingDisShipBillDtlDTO detailDTO = new PendingDisShipBillDtlDTO();
				BeanUtils.copyProperties(detailModel, detailDTO);
				detailDTOList.add(detailDTO);
			}
			// 商品信息
			dto.setShipBillDetailDTOS(detailDTOList);
		}
		dtos.add(dto);
		Page<QueryTypeByAppointmentDTO> page = PageUtils.getPage(dtos);
		page.setPageCount(1);
		page.setPageNum(10);
		page.setPageSize(10);
		page.setTotalCount(1);
		page.setStartRow(1);
		page.setEndRow(1);
		return page;
	}

	/**
	 * 更新装车单明细为待装卸
	 *
	 * @param firstNumberAppointment
	 * @param user
	 * @param date
	 */
	public void upLoadingDetail(TmsAppointmentHeaderModel firstNumberAppointment, UserEntity user, Date date) {
		// 查询预约单明细
		Criteria criteriaAppointment = Criteria.forClass(TmsAppointmentDetailModel.class);
		Restriction appointment = Restrictions.eq(TmsAppointmentDetailModel::getAppointmentId, firstNumberAppointment.getAppointmentId());
		criteriaAppointment.setRestriction(appointment);
		List<TmsAppointmentDetailModel> tmsAppointmentDetailModels = tmsAppointmentDetailMapper.findByCriteria(criteriaAppointment);
		for (TmsAppointmentDetailModel tmsAppointmentDetailModel : tmsAppointmentDetailModels) {
			// 查询装车单明细
			Criteria criteria1 = Criteria.forClass(TmsLoadingBillDetailModel.class);
			Restriction r11 = Restrictions.eq(TmsLoadingBillDetailModel::getShipbillId, tmsAppointmentDetailModel.getShipbillId());
			Restriction r12 = Restrictions.eq(TmsLoadingBillDetailModel::getEnterpriseId, user.getEnterpriseId());
			criteria1.setRestriction(Restrictions.and(r11, r12));
			criteria1.setOrder(Order.newInstance().desc(new String[] { "createtime" }));

			List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteria1);
			Assert.isTrue(tmsLoadingBillDetailModels.size() > 0, "运单【" + tmsAppointmentDetailModel.getShipbillId() + "】查询失败");
			TmsLoadingBillDetailModel tmsLoadingBillDetailModel = tmsLoadingBillDetailModels.get(0);
			// 装车单明细更新为开始装卸状态
			tmsLoadingBillDetailModel.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_ZX_START);
			tmsLoadingBillDetailModel.setUpdateperson(user.getNickname());
			tmsLoadingBillDetailModel.setUpdatetime(date);
			tmsLoadingBillDetailMapper.update(tmsLoadingBillDetailModel);

			// 更新调度单状态
			Criteria criteria2 = Criteria.forClass(TmsLoadingBillDetailModel.class);
			Restriction r21 = Restrictions.eq(TmsLoadingBillDetailModel::getLoadingBillId, tmsLoadingBillDetailModel.getLoadingBillId());
			Restriction r22 = Restrictions.eq(TmsLoadingBillDetailModel::getEnterpriseId, user.getEnterpriseId());
			criteria2.setRestriction(Restrictions.and(r21, r22));
			List<TmsLoadingBillDetailModel> loadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteria2);
			if (ToolKits.isNotEmpty(loadingBillDetailModels)) {
				List<TmsLoadingBillDetailModel> filterTmsLoadingBillDetailModels = loadingBillDetailModels.stream().filter(dto -> dto.getStatus().intValue() < DataDictionaryConstant.SHIPBILL_STATUS_ZX_START.intValue()).collect(Collectors.toList());
				if (ToolKits.isEmpty(filterTmsLoadingBillDetailModels)) {
					// 更新调度单状态为开始装卸
					Map<String, Object> map = Maps.newHashMap();
					map.put("updateperson", user.getNickname());
					map.put("updatetime", date);
					map.put("status", DataDictionaryConstant.LOADING_BILL_STATUS_ZX_START);
					tmsLoadingBillHeaderMapper.updateMapById(tmsLoadingBillDetailModel.getLoadingBillId(), map, TmsLoadingBillHeaderModel.class);
				}
			}

			// 运单更新
			Map<String, Object> mapUpdate = Maps.newHashMap();
			mapUpdate.put("updateperson", user.getNickname());
			mapUpdate.put("updatetime", date);
			mapUpdate.put("status", DataDictionaryConstant.SHIPBILL_STATUS_ZX_START);
			tmsShipbillHeaderMapper.updateMapById(tmsAppointmentDetailModel.getShipbillId(), mapUpdate, TmsShipbillHeaderModel.class);

			// 更新预约明细状态
			tmsAppointmentDetailModel.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_ZX_START);
			tmsAppointmentDetailModel.setUpdateperson(user.getNickname());
			tmsAppointmentDetailModel.setUpdatetime(date);
			tmsAppointmentDetailMapper.update(tmsAppointmentDetailModel);

			// 更新父单状态
			String fatherShipbillId = tmsAppointmentDetailModel.getShipbillId();
			while (ToolKits.isNotEmpty(fatherShipbillId)) {
				fatherShipbillId = updateFatherShipBillEndArrange(fatherShipbillId, DataDictionaryConstant.SHIPBILL_STATUS_ZX_START, date);
			}
		}
	}

	private Page<QueryTypeByAppointmentDTO> queryNoTakeNumAndCallNum(QueryTypeByAppointmentVO vo) {
		UserEntity user = PlgFxUsrUtils.getUserEntity();
		List<QueryTypeByAppointmentDTO> dtos = Lists.newArrayList();
		Criteria criteriaAppointmentHeader = Criteria.forClass(TmsAppointmentHeaderModel.class);
		Restriction r1 = Restrictions.eq(TmsAppointmentHeaderModel::getStatus, DataDictionaryConstant.APPOINTMENT_STATUS_DZX);
		Restriction r2 = Restrictions.eq(TmsAppointmentHeaderModel::getBranchId, vo.getBranchId());
		Restriction r3 = Restrictions.eq(TmsAppointmentHeaderModel::getTallyStatus, DataDictionaryConstant.TALLY_STATUS_LHWC);
		criteriaAppointmentHeader.setRestriction(Restrictions.and(r1, r2, r3));
		criteriaAppointmentHeader.setOrder(Order.newInstance().desc(TmsAppointmentHeaderModel::getUpdatetime));

		PageUtils.startPage(vo.getPageNum(), vo.getPageSize());
		List<TmsAppointmentHeaderModel> tmsAppointmentHeaderModels = tmsAppointmentHeaderMapper.findByCriteria(criteriaAppointmentHeader);
		if (ToolKits.isEmpty(tmsAppointmentHeaderModels)) {
			return null;
		}

		for (TmsAppointmentHeaderModel headerModel:tmsAppointmentHeaderModels ) {
			QueryTypeByAppointmentDTO dto = BeanUtil.copyProperties(headerModel,QueryTypeByAppointmentDTO.class);

			Map<String, Object> queryMap = Maps.newHashMap();
			queryMap.put("appointmentId", headerModel.getAppointmentId());
			List<TmsAppointmentDetailModel> tmsAppointmentDetails = tmsAppointmentDetailMapper.findByMap(queryMap, TmsAppointmentDetailModel.class);
			if (ToolKits.isEmpty(tmsAppointmentDetails)) {
				throw new PrologException("预约明细不存在");
			}
			//设置预约单的派车单
			dto.setLoadingBillIds(DataUtils.getLoadingBillIds(tmsAppointmentDetails));
			List<String> shipbillIds = Lists.newArrayList();
			shipbillIds.addAll(tmsAppointmentDetails.stream().map(TmsAppointmentDetailModel::getShipbillId).distinct().collect(Collectors.toList()));

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

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

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

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

				List<PendingDisShipBillDtlDTO> detailDTOList = Lists.newArrayList();
				for (TmsShipbillDetailModel detailModel : tmsShipbillDetailModels) {
					PendingDisShipBillDtlDTO detailDTO = new PendingDisShipBillDtlDTO();
					BeanUtils.copyProperties(detailModel, detailDTO);
					detailDTOList.add(detailDTO);
				}
				// 商品信息
				dto.setShipBillDetailDTOS(detailDTOList);
			}
			dto.setHasTakeNumAndCallNum(false);
			dtos.add(dto);
		}
		Page<QueryTypeByAppointmentDTO> page = PageUtils.getPage(dtos);
		if (tmsAppointmentHeaderModels instanceof com.github.pagehelper.Page) {
			com.github.pagehelper.Page<TmsAppointmentHeaderModel> p0 = (com.github.pagehelper.Page<TmsAppointmentHeaderModel>) tmsAppointmentHeaderModels;
			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
	 * @return
	 */
	public String updateFatherShipBillEndArrange(String shipbillId, int status, Date date) {
		UserEntity user = PlgFxUsrUtils.getUserEntity();

		Map<String, Object> mapFatherUpdate = Maps.newHashMap();
		mapFatherUpdate.put("updateperson", user.getNickname());
		mapFatherUpdate.put("updatetime", date);
		mapFatherUpdate.put("status", status);
		TmsShipbillHeaderModel tmsShipbillHeaderModel = tmsShipbillHeaderMapper.findById(shipbillId, TmsShipbillHeaderModel.class);

		if (ToolKits.isNotEmpty(tmsShipbillHeaderModel.getFatherShipbillId()) && !tmsShipbillHeaderModel.getFatherShipbillId().equals(shipbillId)) {
			Map<String, Object> queryMap = Maps.newHashMap();
			queryMap.put("fatherShipbillId", tmsShipbillHeaderModel.getFatherShipbillId());
			List<TmsShipbillHeaderModel> list = tmsShipbillHeaderMapper.findByMap(queryMap, TmsShipbillHeaderModel.class);
			if (ToolKits.isNotEmpty(list) && list.size() > 0) {
				List<TmsShipbillHeaderModel> filterList = list.stream().filter(dto -> dto.getStatus().intValue() < status).collect(Collectors.toList());
				// 所有子单都理货完成了
				if (ToolKits.isEmpty(filterList)) {
					// 运单状态更新
					Criteria headerCriteria = Criteria.forClass(TmsShipbillHeaderModel.class);
					Restriction r1 = Restrictions.eq("shipbillId", tmsShipbillHeaderModel.getFatherShipbillId());
					Restriction r2 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
					headerCriteria.setRestriction(Restrictions.and(r1, r2));
					tmsShipbillHeaderMapper.updateMapByCriteria(mapFatherUpdate, headerCriteria);

					// 调度单明细状态更新
					Criteria criteriaFatherLoadingBillDetail = Criteria.forClass(TmsLoadingBillDetailModel.class);
					criteriaFatherLoadingBillDetail.setRestriction(Restrictions.and(r1, r2));
					tmsLoadingBillDetailMapper.updateMapByCriteria(mapFatherUpdate, criteriaFatherLoadingBillDetail);

					// 维护运单节点数据
					ShipbillNodeTrackingSaveVO shipbillNodeTrackingSaveVO = new ShipbillNodeTrackingSaveVO();
					shipbillNodeTrackingSaveVO.setShipbillId(tmsShipbillHeaderModel.getShipbillId());
					shipbillNodeTrackingSaveVO.setShipbillNo(tmsShipbillHeaderModel.getShipbillNo());
					shipbillNodeTrackingSaveVO.setStatus(status);
					shipbillNodeTrackingSaveVO.setNodeEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_LH_END);
					shipbillNodeTrackingService.addShipbillNodeTrackingData(shipbillNodeTrackingSaveVO);

					// 维护运单日志保存
					ShipbillOperateLogSaveVO shipbillOperateLogSaveVO = new ShipbillOperateLogSaveVO();
					shipbillOperateLogSaveVO.setShipbillId(tmsShipbillHeaderModel.getShipbillId());
					shipbillOperateLogSaveVO.setShipbillNo(tmsShipbillHeaderModel.getShipbillNo());
					shipbillOperateLogSaveVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_LH_END);
					shipbillOperateLogSaveVO.setOldStatus(tmsShipbillHeaderModel.getStatus());
					shipbillOperateLogSaveVO.setNewStatus(status);
					shipbillOperateLogService.addShipbillOperateLogData(shipbillOperateLogSaveVO);

					// 更新订单运输记录表
					Criteria criteriaTransport = Criteria.forClass(TmsShipbillTransLogModel.class);
					criteriaTransport.setRestriction(r1);
					Map<String, Object> mapTransportLogUpdate = Maps.newHashMap();
					mapTransportLogUpdate.put("updateperson", user.getNickname());
					mapTransportLogUpdate.put("updatetime", date);
					// 理货完成时间
					mapTransportLogUpdate.put("arrangeGoodsEndTime", date);
					tmsShipbillTransportLogMapper.updateMapByCriteria(mapTransportLogUpdate, criteriaTransport);

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

	/**
	 * 运单分页查询
	 *
	 * @param
	 * @return
	 */
	@SuppressWarnings("resource")
	@Override
	public Page<QueryTypeByShipbillDTO> queryTypeByShipbillPageData(QueryTypeByShipbillVO vo) {
		UserEntity user = PlgFxUsrUtils.getUserEntity();
		ToolKits.isParamNull(user, "当前人员没有操作权限");

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

		Criteria criteria = Criteria.forClass(TmsAppointmentDetailModel.class);
		Restriction r1 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
		Restriction r2 = null;
		Restriction r3 = null;
		Restriction r4 = null;
		Restriction r5 = null;
		Restriction r6 = null;
		Restriction r7 = null;
		Restriction r8 = null;
		if (ObjectUtil.equal(user.getUserType(), BussinessConstant.USER_TYPE_ZY)) {// 自有账号
			r2 = ToolKits.isEmpty(user.getDepts()) ? null : Restrictions.in("departmentId", user.getDepts().stream().toArray(String[]::new));
			if (BussinessConstant.USER_DEPARTMENT_AUTH_Y.equals(user.getOwnedAllDataAuthFlag())) {// 部门权限

			} else {// 业务员权限
				r3 = ToolKits.isEmpty(user.getSuppliers()) ? null : Restrictions.in("consigneeUnitId", user.getSuppliers().stream().toArray(Long[]::new));
				r4 = ToolKits.isEmpty(user.getCustomers()) ? null : Restrictions.in("consigneeUnitId", user.getCustomers().stream().toArray(Long[]::new));
				r5 = ToolKits.isEmpty(user.getWarehouses()) ? null : Restrictions.in("consigneeUnitId", user.getWarehouses().stream().toArray(Long[]::new));
				r6 = Restrictions.or(r3, r4, r5);
				r7 = ToolKits.isEmpty(user.getConsignors()) ? null : Restrictions.in("cargoOwnerId", user.getConsignors().stream().toArray(Long[]::new));
			}
		}
		if (ObjectUtil.equal(user.getUserType(), BussinessConstant.USER_TYPE_CYS)) {// 承运商账号
			r8 = Restrictions.eq("carrierId", Long.valueOf(user.getLoginUserCompanyInfo().getId()));
		}

		Restriction r9 = Restrictions.eq("appointmentId", vo.getAppointmentId());

		Restriction r50 = ToolKits.isEmpty(vo.getShipbillNo()) ? null : Restrictions.eq(TmsAppointmentDetailModel::getShipbillNo, vo.getShipbillNo());
		Restriction r51 = ToolKits.isEmpty(vo.getOrderNo()) ? null : Restrictions.eq(TmsAppointmentDetailModel::getOrderNo, vo.getOrderNo());

		criteria.setRestriction(Restrictions.and(r1, r2, r6, r7, r8, r9, r50, r51));
		criteria.setOrder(Order.newInstance().desc(new String[] { "updatetime" }));
		PageUtils.startPage(vo.getPageNum(), vo.getPageSize());
		List<TmsAppointmentDetailModel> list = tmsAppointmentDetailMapper.findByCriteria(criteria);

		List<QueryTypeByShipbillDTO> dtos = Lists.newArrayList();
		for (TmsAppointmentDetailModel model : list) {
			QueryTypeByShipbillDTO dto = new QueryTypeByShipbillDTO();
			BeanUtils.copyProperties(model, dto);

			if (ObjectUtil.equal(model.getShipperType(), DataDictionaryConstant.SHIPPER_TYPE_KH) || ObjectUtil.equal(model.getShipperType(), DataDictionaryConstant.SHIPPER_TYPE_GYS)) {
				dto.setShipperName(model.getShipperUnitName() + "/" + model.getShipperName());
			}

			if (ObjectUtil.equal(model.getShipperType(), DataDictionaryConstant.CONSIGNEE_TYPE_KH) || ObjectUtil.equal(model.getShipperType(), DataDictionaryConstant.CONSIGNEE_TYPE_GYS)) {
				dto.setConsigneeName(model.getConsigneeUnitName() + "/" + model.getConsigneeName());
			}

			StringBuffer tel = new StringBuffer();
			if (ToolKits.isNotEmpty(model.getConsigneeLandlineNumber()) && ToolKits.isNotEmpty(model.getConsigneePhoneNumber())) {
				tel.append(model.getConsigneeLandlineNumber());
				tel.append(DataDictionaryConstant.Line_SYMBOL);
				tel.append(model.getConsigneePhoneNumber());
			} else if (ToolKits.isNotEmpty(model.getConsigneeLandlineNumber())) {
				tel.append(model.getConsigneeLandlineNumber());
			} else if (ToolKits.isNotEmpty(model.getConsigneePhoneNumber())) {
				tel.append(model.getConsigneePhoneNumber());
			}
			if (ToolKits.isNotEmpty(tel.toString())) {
				dto.setContact(tel.toString());
			}

			dtos.add(dto);
		}

		Page<QueryTypeByShipbillDTO> page = PageUtils.getPage(dtos);
		if (list instanceof com.github.pagehelper.Page) {
			com.github.pagehelper.Page<TmsAppointmentDetailModel> p0 = (com.github.pagehelper.Page<TmsAppointmentDetailModel>) list;
			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
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void startedWorkData(StartLoadVO vo) {
		UserEntity user = PlgFxUsrUtils.getUserEntity();
		ToolKits.isParamNull(user, "当前人员没有操作权限");
		ToolKits.isParamNull(vo.getAppointmentIds(), "预约单ID不为空");

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

		// 更新调度单
		Map<String, Object> mapHeaderUpdate = Maps.newHashMap();
		mapHeaderUpdate.put("updateperson", user.getNickname());
		mapHeaderUpdate.put("updatetime", DateUtil.date());
		mapHeaderUpdate.put("status", DataDictionaryConstant.LOADING_BILL_STATUS_ZX_START);

		Map<String, Object> mapTransportLogUpdate = Maps.newHashMap();
		mapTransportLogUpdate.put("updateperson", user.getNickname());
		mapTransportLogUpdate.put("updatetime", DateUtil.date());
		// 开始装卸时间
		mapTransportLogUpdate.put("loadAndUnloadStartTime", new Date());
		Criteria criteriaTransport = Criteria.forClass(TmsShipbillTransLogModel.class);
		Criteria criteriaLoadingHeader = Criteria.forClass(TmsLoadingBillHeaderModel.class);

		Criteria criteriaAppointmentDetail = Criteria.forClass(TmsAppointmentDetailModel.class);
		Restriction r1 = Restrictions.in(TmsAppointmentDetailModel::getAppointmentId, vo.getAppointmentIds());
		Restriction r2 = Restrictions.eq(TmsAppointmentDetailModel::getEnterpriseId, user.getEnterpriseId());
		criteriaAppointmentDetail.setRestriction(Restrictions.and(r1, r2));
		criteriaAppointmentDetail.setOrder(Order.newInstance().desc(TmsAppointmentHeaderModel::getAppointmentId));
		List<TmsAppointmentDetailModel> tmsAppointmentDetails = tmsAppointmentDetailMapper.findByCriteria(criteriaAppointmentDetail);
		if (ToolKits.isEmpty(tmsAppointmentDetails)) {
			throw new PrologException("预约明细不存在");
		}
		List<String> shipbillIds = Lists.newArrayList();
		shipbillIds.addAll(tmsAppointmentDetails.stream().map(TmsAppointmentDetailModel::getShipbillId).distinct().collect(Collectors.toList()));
		if (ToolKits.isEmpty(shipbillIds)) {
			throw new PrologException("运单不存在");
		}
		for (String shipbillId : shipbillIds) {
			r1 = Restrictions.eq("shipbillId", shipbillId);
			r2 = Restrictions.eq("enterpriseId", user.getEnterpriseId());

			Criteria criteriaLoadingDetail = Criteria.forClass(TmsLoadingBillDetailModel.class);
			criteriaLoadingDetail.setRestriction(Restrictions.and(r1, r2));
			criteriaLoadingDetail.setOrder(Order.newInstance().desc(new String[] { "createtime" }));
			List<TmsLoadingBillDetailModel> loadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteriaLoadingDetail);
			if (ToolKits.isEmpty(loadingBillDetailModels)) {
				throw new PrologException("运单【" + shipbillId + "】不存在");
			}
			TmsLoadingBillDetailModel loadingBillDetailModel = loadingBillDetailModels.get(0);

			if (loadingBillDetailModel.getStatus().intValue() > DataDictionaryConstant.SHIPBILL_STATUS_ZX_START.intValue()) {
				throw new PrologException("运单【" + shipbillId + "】已开始装卸或装车扫描");
			}
			// 判定下一步流程,取下一步流程的状态
			String flowConfig = null;
			if (user.getUserType().equals(BussinessConstant.USER_TYPE_CYS)) {
				flowConfig = loadingBillDetailModel.getCarrierFlowConfig();
			} else {
				flowConfig = loadingBillDetailModel.getFlowConfig();
			}
			int status = 0;
			if (flowConfig.contains(DataDictionaryConstant.FLOW_CONFIG_SCANNING)) {
				status = DataDictionaryConstant.SHIPBILL_STATUS_ZC_SCAN;
			} else {
				status = DataDictionaryConstant.SHIPBILL_STATUS_ZX_FINISH;
			}

			// 更新装车单明细
			Map<String, Object> mapUpdate = Maps.newHashMap();
			mapUpdate.put("updateperson", user.getNickname());
			mapUpdate.put("updatetime", DateUtil.date());
			mapUpdate.put("status", status);
			tmsLoadingBillDetailMapper.updateMapById(loadingBillDetailModel.getId(), mapUpdate, TmsLoadingBillDetailModel.class);

			// 更新运单表
			Criteria criteriaShipbillHeader = Criteria.forClass(TmsShipbillHeaderModel.class);
			criteriaShipbillHeader.setRestriction(Restrictions.and(r1, r2));
			tmsShipbillHeaderMapper.updateMapByCriteria(mapUpdate, criteriaShipbillHeader);

			// 查询预约单明细
			Criteria criteriaAppointment = Criteria.forClass(TmsAppointmentDetailModel.class);
			Restriction appointment = Restrictions.eq(TmsAppointmentDetailModel::getShipbillId, shipbillId);
			Restriction restrictionSts = Restrictions.ge(TmsAppointmentDetailModel::getStatus, DataDictionaryConstant.SHIPBILL_STATUS_PENDING_APP);
			criteriaAppointment.setRestriction(Restrictions.and(appointment, restrictionSts));
			List<TmsAppointmentDetailModel> tmsAppointmentDetailModels = tmsAppointmentDetailMapper.findByCriteria(criteriaAppointment);
			if (ToolKits.isNotEmpty(tmsAppointmentDetailModels)) {
				if (tmsAppointmentDetailModels.size() > 1) {
					throw new RuntimeException("运单[" + shipbillId + "]被重复预约!");
				}
				TmsAppointmentDetailModel tmsAppointmentDetailModel = tmsAppointmentDetailModels.get(0);

				if (user.getUserType().equals(BussinessConstant.USER_TYPE_ZY)) {
					if (ToolKits.isEmpty(tmsAppointmentDetailModel.getFlowConfig()) || !tmsAppointmentDetailModel.getFlowConfig().contains(DataDictionaryConstant.FLOW_CONFIG_LOAD_UNLOAD)) {
						throw new PrologException("运单【" + tmsAppointmentDetailModel.getShipbillId() + "】没有待装卸流程，不能做装卸");
					}
				} else {
					if (ToolKits.isEmpty(tmsAppointmentDetailModel.getCarrierFlowConfig()) || !tmsAppointmentDetailModel.getCarrierFlowConfig().contains(DataDictionaryConstant.FLOW_CONFIG_LOAD_UNLOAD)) {
						throw new PrologException("运单【" + tmsAppointmentDetailModel.getShipbillId() + "】没有待装卸流程，不能做装卸");
					}
				}

				// 查询预约单
				TmsAppointmentHeaderModel tmsAppointmentHeaderModel = tmsAppointmentHeaderMapper.findById(tmsAppointmentDetailModel.getAppointmentId(), TmsAppointmentHeaderModel.class);
				ToolKits.isParamNull(tmsAppointmentHeaderModel, "未找到对应预约单[" + tmsAppointmentDetailModel.getAppointmentId() + "]");

				// 判断是否为叫号状态
				if (DataDictionaryConstant.APPOINTMENT_STATUS_YJH.equals(tmsAppointmentHeaderModel.getStatus()) ||
						DataDictionaryConstant.APPOINTMENT_STATUS_DZX.equals(tmsAppointmentHeaderModel.getStatus())) {
					tmsAppointmentHeaderModel.setLoadAndUnloadStartTime(DateUtil.date());
					tmsAppointmentHeaderModel.setStatus(DataDictionaryConstant.APPOINTMENT_STATUS_KSZX);
				}
				tmsAppointmentHeaderModel.setLoadAndUnloadWorkerId(user.getUserid());
				tmsAppointmentHeaderModel.setLoadAndUnloadWorkerCode(String.valueOf(user.getUserid()));
				tmsAppointmentHeaderModel.setLoadAndUnloadWorkerName(user.getNickname());
				tmsAppointmentHeaderMapper.update(tmsAppointmentHeaderModel);

				// 修改预约单明细表
				tmsAppointmentDetailModel.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_ZX_FINISH);
				tmsAppointmentDetailMapper.update(tmsAppointmentDetailModel);
			}

			// 运单节点保存
			ShipbillNodeTrackingSaveNewVO shipbillNodeTrackingSaveNewVO = new ShipbillNodeTrackingSaveNewVO();
			shipbillNodeTrackingSaveNewVO.setNodeDate(DateUtil.date());
			shipbillNodeTrackingSaveNewVO.setShipbillId(shipbillId);
			shipbillNodeTrackingSaveNewVO.setShipbillNo(shipbillId);
			shipbillNodeTrackingSaveNewVO.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_ZX_FINISH);
			shipbillNodeTrackingSaveNewVO.setNodeEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_ZX_START);
			shipbillNodeTrackingSaveNewVO.setUserId(user.getUserid());
			shipbillNodeTrackingSaveNewVO.setUserName(user.getNickname());
			shipbillNodeTrackingSaveNewVO.setEnterpriseId(user.getEnterpriseId());
			shipbillNodeTrackingSaveNewVO.setEnterpriseName(user.getEnterpriseName());
			shipbillNodeTrackingService.addShipbillNodeTrackingNewData(shipbillNodeTrackingSaveNewVO);

			// 运单日志保存
			ShipbillOperateLogSaveNewVO shipbillOperateLogSaveNewVO = new ShipbillOperateLogSaveNewVO();
			shipbillOperateLogSaveNewVO.setShipbillId(shipbillId);
			shipbillOperateLogSaveNewVO.setShipbillNo(shipbillId);
			shipbillOperateLogSaveNewVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_ZX_START);
			shipbillOperateLogSaveNewVO.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_LH_FINISH);
			shipbillOperateLogSaveNewVO.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_ZX_FINISH);
			shipbillOperateLogSaveNewVO.setOperateDate(DateUtil.date());
			shipbillOperateLogSaveNewVO.setEnterpriseId(user.getEnterpriseId());
			shipbillOperateLogSaveNewVO.setEnterpriseName(user.getEnterpriseName());
			shipbillOperateLogSaveNewVO.setUserId(user.getUserid());
			shipbillOperateLogSaveNewVO.setUserName(user.getNickname());
			shipbillOperateLogService.addShipbillOperateLogNewData(shipbillOperateLogSaveNewVO);

			// 父运单的开始装卸
			String fatherShipbillId = shipbillId;
			while (ToolKits.isNotEmpty(fatherShipbillId)) {
				fatherShipbillId = fatherStartedWork(fatherShipbillId, DateUtil.date(), user, status);
			}
			// 更新订单运输记录表
			criteriaTransport.setRestriction(r1);
			tmsShipbillTransportLogMapper.updateMapByCriteria(mapTransportLogUpdate, criteriaTransport);

			// 更新调度单状态 开始装卸
			Restriction r3 = Restrictions.eq("loadingBillId", loadingBillDetailModels.get(0).getLoadingBillId());
			Restriction r4 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
			criteriaLoadingHeader.setRestriction(Restrictions.and(r3, r4));
			List<TmsLoadingBillHeaderModel> headerModel = tmsLoadingBillHeaderMapper.findByCriteria(criteriaLoadingHeader);

			if (ToolKits.isNotEmpty(headerModel) && headerModel.get(0).getStatus() != status) {
				tmsLoadingBillHeaderMapper.updateMapByCriteria(mapHeaderUpdate, criteriaLoadingHeader);
			}
		}
	}

	/**
	 * 装卸完成
	 *
	 * @param
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void completeWorkData(StartLoadVO vo) {
		UserEntity user = PlgFxUsrUtils.getUserEntity();
		ToolKits.isParamNull(user, "当前人员没有操作权限");
		ToolKits.isParamNull(vo.getAppointmentIds(), "预约单ID不为空");

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

		Map<String, Object> mapTransportLogUpdate = Maps.newHashMap();
		mapTransportLogUpdate.put("updateperson", user.getNickname());
		mapTransportLogUpdate.put("updatetime", DateUtil.date());
		// 装卸完成时间
		mapTransportLogUpdate.put("loadAndUnloadEndTime", DateUtil.date());

		Criteria criteriaAppointmentDetail = Criteria.forClass(TmsAppointmentDetailModel.class);
		Restriction r1 = Restrictions.in(TmsAppointmentDetailModel::getAppointmentId, vo.getAppointmentIds());
		Restriction r2 = Restrictions.eq(TmsAppointmentDetailModel::getEnterpriseId, user.getEnterpriseId());
		Restriction r3 = Restrictions.gt(TmsAppointmentDetailModel::getStatus, DataDictionaryConstant.APPOINTMENT_STATUS_QX);
		criteriaAppointmentDetail.setRestriction(Restrictions.and(r1, r2,r3));
		criteriaAppointmentDetail.setOrder(Order.newInstance().desc(TmsAppointmentHeaderModel::getAppointmentId));
		List<TmsAppointmentDetailModel> tmsAppointmentDetails = tmsAppointmentDetailMapper.findByCriteria(criteriaAppointmentDetail);
		if (ToolKits.isEmpty(tmsAppointmentDetails)) {
			throw new PrologException("预约明细不存在");
		}
		List<String> shipbillIds = Lists.newArrayList();
		shipbillIds.addAll(tmsAppointmentDetails.stream().map(TmsAppointmentDetailModel::getShipbillId).distinct().collect(Collectors.toList()));
		if (ToolKits.isEmpty(shipbillIds)) {
			throw new PrologException("运单不存在");
		}
		for (String shipbillId : shipbillIds) {
			Criteria criteriaLoadingDetail = Criteria.forClass(TmsLoadingBillDetailModel.class);
			r1 = Restrictions.eq("shipbillId", shipbillId);
			r2 = Restrictions.eq("status", DataDictionaryConstant.SHIPBILL_STATUS_ZX_FINISH);
			r3 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
			criteriaLoadingDetail.setRestriction(Restrictions.and(r1, r2, r3));
			criteriaLoadingDetail.setOrder(Order.newInstance().desc(new String[] { "createtime" }));

			List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteriaLoadingDetail);
			if (ToolKits.isEmpty(tmsLoadingBillDetailModels)) {
				throw new PrologException("运单【" + shipbillId + "】的开始装卸或者装车扫描没有做，还不能完成装卸");
			}
			TmsLoadingBillDetailModel loadingBillDetailModel = tmsLoadingBillDetailModels.get(0);

			// 判定下一步流程,取下一步流程的状态
			String flowConfig = null;
			if (user.getUserType().equals(BussinessConstant.USER_TYPE_ZY)) {
				flowConfig = loadingBillDetailModel.getFlowConfig();
			} else if (user.getUserType().equals(BussinessConstant.USER_TYPE_CYS)) {
				flowConfig = loadingBillDetailModel.getCarrierFlowConfig();
			}
			int status = businessFlowUtil.judgmentNextFlowSts(flowConfig, DataDictionaryConstant.FLOW_CONFIG_LOAD_UNLOAD);

			// 更新装车单明细
			Map<String, Object> mapUpdate = Maps.newHashMap();
			mapUpdate.put("updateperson", user.getNickname());
			mapUpdate.put("updatetime", DateUtil.date());
			mapUpdate.put("status", status);
			tmsLoadingBillDetailMapper.updateMapById(loadingBillDetailModel.getId(), mapUpdate, TmsLoadingBillDetailModel.class);

			// 更新运单表
			Criteria criteriaShipbillHeader = Criteria.forClass(TmsShipbillHeaderModel.class);
			Restriction r4 = Restrictions.eq("shipbillId", shipbillId);
			Restriction r5 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
			criteriaShipbillHeader.setRestriction(Restrictions.and(r4, r5));
			tmsShipbillHeaderMapper.updateMapByCriteria(mapUpdate, criteriaShipbillHeader);

			// 查询预约单明细
			Criteria criteriaAppointment = Criteria.forClass(TmsAppointmentDetailModel.class);
			Restriction appointment = Restrictions.eq(TmsAppointmentDetailModel::getShipbillId, shipbillId);
			criteriaAppointment.setRestriction(appointment);
			List<TmsAppointmentDetailModel> tmsAppointmentDetailModels = tmsAppointmentDetailMapper.findByCriteria(criteriaAppointment);
			if (ToolKits.isNotEmpty(tmsAppointmentDetailModels)) {
				// 获取剩余预约运单信息
				Restriction appointment2 = Restrictions.ne(TmsAppointmentDetailModel::getShipbillId, shipbillId);
				Restriction appointment3 = Restrictions.eq(TmsAppointmentDetailModel::getAppointmentId, tmsAppointmentDetailModels.get(0).getAppointmentId());
				criteriaAppointment.setRestriction(Restrictions.and(appointment2, appointment3));
				List<TmsAppointmentDetailModel> tmsAppointmentDetailModelList = tmsAppointmentDetailMapper.findByCriteria(criteriaAppointment);

				if (ToolKits.isNotEmpty(tmsAppointmentDetailModelList)) {
					// 获取是否还有未装卸完成的单子
					List<TmsAppointmentDetailModel> tmsAppointmentDetailList = tmsAppointmentDetailModelList.stream().filter(o -> o.getStatus().intValue() < DataDictionaryConstant.SHIPBILL_STATUS_QY.intValue()).collect(Collectors.toList());
					if (ToolKits.isEmpty(tmsAppointmentDetailList)) {
						// 修改预约单主表
						Map<String, Object> map = Maps.newHashMap();
						map.put("updateperson", user.getNickname());
						map.put("updatetime", DateUtil.date());
						map.put("loadAndUnloadEndTime", DateUtil.date());
						map.put("status", DataDictionaryConstant.APPOINTMENT_STATUS_ZXWC);
						tmsAppointmentHeaderMapper.updateMapById(tmsAppointmentDetailModels.get(0).getAppointmentId(), map, TmsAppointmentHeaderModel.class);
					}
					// 修改预约单明细表
					Restriction appointment4 = Restrictions.eq(TmsAppointmentDetailModel::getShipbillId, shipbillId);
					criteriaAppointment.setRestriction(appointment4);
					Map<String, Object> updateDetail = Maps.newHashMap();
					updateDetail.put("status", status);
					tmsAppointmentDetailMapper.updateMapByCriteria(updateDetail, criteriaAppointment);
				} else {
					// 修改预约单主表
					Map<String, Object> map = Maps.newHashMap();
					map.put("updateperson", user.getNickname());
					map.put("updatetime", DateUtil.date());
					map.put("loadAndUnloadEndTime", DateUtil.date());
					map.put("status", DataDictionaryConstant.APPOINTMENT_STATUS_ZXWC);
					tmsAppointmentHeaderMapper.updateMapById(tmsAppointmentDetailModels.get(0).getAppointmentId(), map, TmsAppointmentHeaderModel.class);

					// 修改预约单明细表
					Restriction appointment5 = Restrictions.eq(TmsAppointmentDetailModel::getShipbillId, shipbillId);
					criteriaAppointment.setRestriction(appointment5);
					Map<String, Object> updateDetail = Maps.newHashMap();
					updateDetail.put("status", status);
					tmsAppointmentDetailMapper.updateMapByCriteria(updateDetail, criteriaAppointment);
				}
			}

			// 运单节点保存
			ShipbillNodeTrackingSaveNewVO shipbillNodeTrackingSaveNewVO = new ShipbillNodeTrackingSaveNewVO();
			shipbillNodeTrackingSaveNewVO.setNodeDate(DateUtil.date());
			shipbillNodeTrackingSaveNewVO.setShipbillId(shipbillId);
			shipbillNodeTrackingSaveNewVO.setShipbillNo(shipbillId);
			shipbillNodeTrackingSaveNewVO.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_ZX_FINISH);
			shipbillNodeTrackingSaveNewVO.setNodeEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_ZX_FINISH);
			shipbillNodeTrackingSaveNewVO.setUserId(user.getUserid());
			shipbillNodeTrackingSaveNewVO.setUserName(user.getNickname());
			shipbillNodeTrackingSaveNewVO.setEnterpriseId(user.getEnterpriseId());
			shipbillNodeTrackingSaveNewVO.setEnterpriseName(user.getEnterpriseName());
			shipbillNodeTrackingService.addShipbillNodeTrackingNewData(shipbillNodeTrackingSaveNewVO);

			// 运单日志保存
			ShipbillOperateLogSaveNewVO shipbillOperateLogSaveNewVO = new ShipbillOperateLogSaveNewVO();
			shipbillOperateLogSaveNewVO.setShipbillId(shipbillId);
			shipbillOperateLogSaveNewVO.setShipbillNo(shipbillId);
			shipbillOperateLogSaveNewVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_ZX_FINISH);
			shipbillOperateLogSaveNewVO.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_ZX_START);
			shipbillOperateLogSaveNewVO.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_ZX_FINISH);
			shipbillOperateLogSaveNewVO.setOperateDate(DateUtil.date());
			shipbillOperateLogSaveNewVO.setEnterpriseId(user.getEnterpriseId());
			shipbillOperateLogSaveNewVO.setEnterpriseName(user.getEnterpriseName());
			shipbillOperateLogSaveNewVO.setUserId(user.getUserid());
			shipbillOperateLogSaveNewVO.setUserName(user.getNickname());
			shipbillOperateLogService.addShipbillOperateLogNewData(shipbillOperateLogSaveNewVO);

			// 维护运输日志
			Criteria criteriaTransport = Criteria.forClass(TmsShipbillTransLogModel.class);
			criteriaTransport.setRestriction(r1);
			tmsShipbillTransportLogMapper.updateMapByCriteria(mapTransportLogUpdate, criteriaTransport);

			// 父运单的装卸完成
			String fatherShipbillId = shipbillId;
			while (ToolKits.isNotEmpty(fatherShipbillId)) {
				fatherShipbillId = fatherCompleteWork(fatherShipbillId, DateUtil.date(), user, status);
			}

			// 更新调度单状态
			Criteria criteriaLoadingBillDetail = Criteria.forClass(TmsLoadingBillDetailModel.class);
			Restriction r6 = Restrictions.eq("loadingBillId", loadingBillDetailModel.getLoadingBillId());
			Restriction r7 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
			criteriaLoadingBillDetail.setRestriction(Restrictions.and(r6, r7));
			tmsLoadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteriaLoadingBillDetail);
			if (ToolKits.isNotEmpty(tmsLoadingBillDetailModels)) {
				List<TmsLoadingBillDetailModel> filterTmsLoadingBillDetailModels = tmsLoadingBillDetailModels.stream().filter(dto -> dto.getStatus().intValue() < DataDictionaryConstant.SHIPBILL_STATUS_QY.intValue()).collect(Collectors.toList());
				if (ToolKits.isEmpty(filterTmsLoadingBillDetailModels)) {
					// 更新调度单
					Map<String, Object> mapHeaderUpdate = Maps.newHashMap();
					mapHeaderUpdate.put("updateperson", user.getNickname());
					mapHeaderUpdate.put("updatetime", DateUtil.date());
					mapHeaderUpdate.put("status", DataDictionaryConstant.LOADING_BILL_STATUS_ZX_FINISH);
					tmsLoadingBillHeaderMapper.updateMapById(loadingBillDetailModel.getLoadingBillId(), mapHeaderUpdate, TmsLoadingBillHeaderModel.class);
				}
			}
		}

		MessageUtil.addMessage(new SendMessageDTO(MessageOrderTypeEnum.APPOINTMENT_NO.getCode(), MessageTypeEnum.LOADING.getCode(), vo.getAppointmentIds()));
	}

	/**
	 * 父级运单开始装卸流程
	 *
	 * @param shipbillId
	 * @param date
	 * @param user
	 * @return
	 */
	public String fatherStartedWork(String shipbillId, Date date, UserEntity user, int status) {
		// 查询运单
		TmsShipbillHeaderModel tmsShipbillHeaderModel = tmsShipbillHeaderMapper.findById(shipbillId, TmsShipbillHeaderModel.class);

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

				// 判断父级单号的状态是否为开始装卸
				if (fatherShipbillHeaderModel.getStatus() != status) {
					// 修改父级运单状态
					fatherShipbillHeaderModel.setStatus(status);
					fatherShipbillHeaderModel.setUpdatetime(date);
					fatherShipbillHeaderModel.setUpdateperson(user.getNickname());
					tmsShipbillHeaderMapper.update(fatherShipbillHeaderModel);

					// 更新装车单明细
					Map<String, Object> mapUpdate = Maps.newHashMap();
					mapUpdate.put("updateperson", user.getNickname());
					mapUpdate.put("updatetime", date);
					mapUpdate.put("status", status);
					Criteria criteriaFatherLoadingBillDetail = Criteria.forClass(TmsLoadingBillDetailModel.class);
					Restriction r5 = Restrictions.eq("shipbillId", tmsShipbillHeaderModel.getFatherShipbillId());
					Restriction r6 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
					criteriaFatherLoadingBillDetail.setRestriction(Restrictions.and(r5, r6));
					tmsLoadingBillDetailMapper.updateMapByCriteria(mapUpdate, criteriaFatherLoadingBillDetail);

					// 运单节点保存
					ShipbillNodeTrackingSaveNewVO shipbillNodeTrackingSaveNewVO = new ShipbillNodeTrackingSaveNewVO();
					shipbillNodeTrackingSaveNewVO.setNodeDate(date);
					shipbillNodeTrackingSaveNewVO.setShipbillId(fatherShipbillHeaderModel.getShipbillId());
					shipbillNodeTrackingSaveNewVO.setShipbillNo(fatherShipbillHeaderModel.getShipbillId());
					shipbillNodeTrackingSaveNewVO.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_ZX_START);
					shipbillNodeTrackingSaveNewVO.setNodeEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_ZX_START);
					shipbillNodeTrackingSaveNewVO.setUserId(user.getUserid());
					shipbillNodeTrackingSaveNewVO.setUserName(user.getNickname());
					shipbillNodeTrackingSaveNewVO.setEnterpriseId(user.getEnterpriseId());
					shipbillNodeTrackingSaveNewVO.setEnterpriseName(user.getEnterpriseName());
					shipbillNodeTrackingService.addShipbillNodeTrackingNewData(shipbillNodeTrackingSaveNewVO);

					// 运单日志保存
					ShipbillOperateLogSaveNewVO shipbillOperateLogSaveNewVO = new ShipbillOperateLogSaveNewVO();
					shipbillOperateLogSaveNewVO.setShipbillId(fatherShipbillHeaderModel.getShipbillId());
					shipbillOperateLogSaveNewVO.setShipbillNo(fatherShipbillHeaderModel.getShipbillId());
					shipbillOperateLogSaveNewVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_ZX_START);
					shipbillOperateLogSaveNewVO.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_LH_FINISH);
					shipbillOperateLogSaveNewVO.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_ZX_START);
					shipbillOperateLogSaveNewVO.setOperateDate(date);
					shipbillOperateLogSaveNewVO.setEnterpriseId(user.getEnterpriseId());
					shipbillOperateLogSaveNewVO.setEnterpriseName(user.getEnterpriseName());
					shipbillOperateLogSaveNewVO.setUserId(user.getUserid());
					shipbillOperateLogSaveNewVO.setUserName(user.getNickname());
					shipbillOperateLogService.addShipbillOperateLogNewData(shipbillOperateLogSaveNewVO);

					// 更新订单运输记录表
					Criteria criteriaTransport = Criteria.forClass(TmsShipbillTransLogModel.class);
					criteriaTransport.setRestriction(r5);
					// 订单运输记录表
					Map<String, Object> mapTransportLogUpdate = Maps.newHashMap();
					mapTransportLogUpdate.put("updateperson", user.getNickname());
					mapTransportLogUpdate.put("updatetime", date);
					// 开始装卸时间
					mapTransportLogUpdate.put("loadAndUnloadStartTime", new Date());
					tmsShipbillTransportLogMapper.updateMapByCriteria(mapTransportLogUpdate, criteriaTransport);

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

	/**
	 * 父级运单装卸完成流程
	 *
	 * @param shipbillId
	 * @param date
	 * @param user
	 * @return
	 */
	public String fatherCompleteWork(String shipbillId, Date date, UserEntity user, int status) {
		// 查询运单
		TmsShipbillHeaderModel tmsShipbillHeaderModel = tmsShipbillHeaderMapper.findById(shipbillId, TmsShipbillHeaderModel.class);
		// 查询预约单明细
		Criteria criteriaAppointment = Criteria.forClass(TmsAppointmentDetailModel.class);
		Restriction appointment = Restrictions.eq(TmsAppointmentDetailModel::getShipbillId, shipbillId);
		criteriaAppointment.setRestriction(appointment);
		List<TmsAppointmentDetailModel> tmsAppointmentDetailModels = tmsAppointmentDetailMapper.findByCriteria(criteriaAppointment);
		if (ToolKits.isNotEmpty(tmsAppointmentDetailModels)) {
			/*
			 * if (tmsAppointmentDetailModels.size() > 1) { throw new RuntimeException("运单["
			 * + shipbillId + "]被重复预约!"); }
			 */

			// 获取剩余预约运单信息
			appointment = Restrictions.ne(TmsAppointmentDetailModel::getShipbillId, shipbillId);
			Restriction appointment2 = Restrictions.eq(TmsAppointmentDetailModel::getAppointmentId, tmsAppointmentDetailModels.get(0).getAppointmentId());
			criteriaAppointment.setRestriction(Restrictions.and(appointment, appointment2));
			List<TmsAppointmentDetailModel> tmsAppointmentDetailModelList = tmsAppointmentDetailMapper.findByCriteria(criteriaAppointment);

			if (ToolKits.isNotEmpty(tmsAppointmentDetailModelList)) {
				// 获取是否还有未理货完成的单子
				List<TmsAppointmentDetailModel> tmsAppointmentDetails = tmsAppointmentDetailModelList.stream().filter(o -> DataDictionaryConstant.SHIPBILL_STATUS_ZX_FINISH >= o.getStatus()).collect(Collectors.toList());
				if (ToolKits.isEmpty(tmsAppointmentDetails)) {
					// 修改预约单主表
					Map<String, Object> map = Maps.newHashMap();
					map.put("status", DataDictionaryConstant.APPOINTMENT_STATUS_ZXWC);
					tmsAppointmentHeaderMapper.updateMapById(tmsAppointmentDetailModels.get(0).getAppointmentId(), map, TmsAppointmentHeaderModel.class);
				}

				// 修改预约单明细表
				criteriaAppointment.setRestriction(appointment2);
				Map<String, Object> updateDetail = Maps.newHashMap();
				updateDetail.put("status", status);
				tmsAppointmentDetailMapper.updateMapByCriteria(updateDetail, criteriaAppointment);
			}

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

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

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

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

				// 运单节点保存
				ShipbillNodeTrackingSaveNewVO shipbillNodeTrackingSaveNewVO = new ShipbillNodeTrackingSaveNewVO();
				shipbillNodeTrackingSaveNewVO.setNodeDate(date);
				shipbillNodeTrackingSaveNewVO.setShipbillId(fatherShipbillHeaderModel.getShipbillId());
				shipbillNodeTrackingSaveNewVO.setShipbillNo(fatherShipbillHeaderModel.getShipbillId());
				shipbillNodeTrackingSaveNewVO.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_ZX_FINISH);
				shipbillNodeTrackingSaveNewVO.setNodeEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_ZX_FINISH);
				shipbillNodeTrackingSaveNewVO.setUserId(user.getUserid());
				shipbillNodeTrackingSaveNewVO.setUserName(user.getNickname());
				shipbillNodeTrackingSaveNewVO.setEnterpriseId(user.getEnterpriseId());
				shipbillNodeTrackingSaveNewVO.setEnterpriseName(user.getEnterpriseName());
				shipbillNodeTrackingService.addShipbillNodeTrackingNewData(shipbillNodeTrackingSaveNewVO);

				// 运单日志保存
				ShipbillOperateLogSaveNewVO shipbillOperateLogSaveNewVO = new ShipbillOperateLogSaveNewVO();
				shipbillOperateLogSaveNewVO.setShipbillId(fatherShipbillHeaderModel.getShipbillId());
				shipbillOperateLogSaveNewVO.setShipbillNo(fatherShipbillHeaderModel.getShipbillId());
				shipbillOperateLogSaveNewVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_ZX_FINISH);
				shipbillOperateLogSaveNewVO.setOldStatus(DataDictionaryConstant.SHIPBILL_STATUS_ZX_START);
				shipbillOperateLogSaveNewVO.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_ZX_FINISH);
				shipbillOperateLogSaveNewVO.setOperateDate(date);
				shipbillOperateLogSaveNewVO.setEnterpriseId(user.getEnterpriseId());
				shipbillOperateLogSaveNewVO.setEnterpriseName(user.getEnterpriseName());
				shipbillOperateLogSaveNewVO.setUserId(user.getUserid());
				shipbillOperateLogSaveNewVO.setUserName(user.getNickname());
				shipbillOperateLogService.addShipbillOperateLogNewData(shipbillOperateLogSaveNewVO);

				// 更新订单运输记录表
				Criteria criteriaTransport = Criteria.forClass(TmsShipbillTransLogModel.class);
				r1 = Restrictions.eq("shipbillId", tmsShipbillHeaderModel.getFatherShipbillId());
				criteriaTransport.setRestriction(r1);
				Map<String, Object> mapTransportLogUpdate = Maps.newHashMap();
				mapTransportLogUpdate.put("updateperson", user.getNickname());
				mapTransportLogUpdate.put("updatetime", date);
				// 理货完成时间
				mapTransportLogUpdate.put("loadAndUnloadEndTime", date);
				tmsShipbillTransportLogMapper.updateMapByCriteria(mapTransportLogUpdate, criteriaTransport);

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

	}

	/**
	 * 开始装卸操作成功后刷新预约单数据
	 * 
	 * @param
	 * @return
	 */
	@Override
	public AppointmentHeaderDTO refreshAppoint(Long appointmentId) throws Exception {
		TmsAppointmentHeaderModel model = tmsAppointmentHeaderMapper.findById(appointmentId, TmsAppointmentHeaderModel.class);
		if (ObjectUtil.isNull(model)) {
			throw new BizException("预约单不存在，appointmentId=" + appointmentId);
		}
		AppointmentHeaderDTO appointmentHeaderDTO = BeanUtil.toBean(model, AppointmentHeaderDTO.class);
		Criteria criteria = Criteria.forClass(TmsAppointmentDetailModel.class);
		Restriction r1 = Restrictions.eq(TmsAppointmentDetailModel::getAppointmentId, appointmentId);
		criteria.setRestriction(r1);
		List<TmsAppointmentDetailModel> tmsAppointmentDetailModels = tmsAppointmentDetailMapper.findByCriteria(criteria);
		appointmentHeaderDTO.setLoadingBillIds(DataUtils.getLoadingBillIds(tmsAppointmentDetailModels));
		return appointmentHeaderDTO;
	}

}
