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.util.ObjectUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.prolog.common.util.ToolKits;
import com.prolog.framework.common.message.RestMessage;
import com.prolog.framework.core.exception.PrologException;
import com.prolog.framework.core.pojo.Page;
import com.prolog.framework.core.restriction.Criteria;
import com.prolog.framework.core.restriction.Order;
import com.prolog.framework.core.restriction.Restriction;
import com.prolog.framework.core.restriction.Restrictions;
import com.prolog.framework.dao.util.PageUtils;
import com.prolog.product.core.framework.entity.UserEntity;
import com.prolog.product.core.framework.util.PlgFxUsrUtils;
import com.prolog.rdc.tms.app.constant.BussinessConstant;
import com.prolog.rdc.tms.app.constant.DataDictionaryConstant;
import com.prolog.rdc.tms.app.dao.mapper.*;
import com.prolog.rdc.tms.app.model.dto.business.WaitForArrangeGoodsDTO;
import com.prolog.rdc.tms.app.model.dto.business.WaitForArrangeGoodsItemDTO;
import com.prolog.rdc.tms.app.model.dto.business.WaitForArrangeGoodsPackageDTO;
import com.prolog.rdc.tms.app.model.dto.business.WaitForArrangeGoodsQueryDTO;
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.LoadingBillService;
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.WaitForArrangeGoodsService;
import com.prolog.rdc.tms.app.util.*;
import com.prolog.rdc.tms.model.dto.message.SendMessageDTO;
import com.prolog.rdc.tms.model.entity.SysRefdatadModel;
import com.prolog.rdc.tms.model.enums.MessageOrderTypeEnum;
import com.prolog.rdc.tms.model.enums.MessageTypeEnum;
import com.prolog.rdc.tms.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;

/**
 * Company: 湖北普罗格科技股份有限公司
 *
 * @author zhangsj
 * @since 2022/7/22 11:02
 */
@Service
public class WaitForArrangeGoodsServiceImpl implements WaitForArrangeGoodsService {

	@Autowired
	private TmsAppointmentHeaderMapper tmsAppointmentHeaderMapper;

	@Autowired
	private TmsAppointmentDetailMapper tmsAppointmentDetailMapper;

	@Autowired
	private TmsShipbillDetailMapper tmsShipbillDetailMapper;

	@Autowired
	private MaindataFeign maindataTmsResource;

	@Autowired
	private TmsShipbillHeaderMapper tmsShipbillHeaderMapper;

	@Autowired
	private TmsLoadingBillDetailMapper tmsLoadingBillDetailMapper;

	@Autowired
	private TmsLoadingBillHeaderMapper tmsLoadingBillHeaderMapper;

	@Autowired
	private ShipbillOperateLogService shipbillOperateLogService;

	@Autowired
	private ShipbillNodeTrackingService shipbillNodeTrackingService;

	@Autowired
	private TmsShipbillTransportLogMapper tmsShipbillTransportLogMapper;

	@Autowired
	private BusinessFlowUtil businessFlowUtil;

	@Autowired
	private TmsShipbillPackageMapper tmsShipbillPackageMapper;

	@Autowired
	private LoadingBillService loadingBillService;

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

	@Autowired
	private ConvertorUtil convertorUtil;
	/**
	 * 主页查询
	 *
	 * @param waitForArrangeGoodsVO
	 * @return
	 */
	@Override
	public Page<WaitForArrangeGoodsDTO> queryData(WaitForArrangeGoodsVO waitForArrangeGoodsVO) throws Exception {
		ToolKits.isParamNull(waitForArrangeGoodsVO.getBranchId(), "仓库ID不可为空");

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

		List<WaitForArrangeGoodsDTO> dtos = Lists.newArrayList();

		List<SysRefdatadModel> dicData = convertorUtil.getDictionary(new String[] { DataDictionaryConstant.APPOINTMENT_STATUS, // 预约单状态
				DataDictionaryConstant.TALLY_STATUS
		});

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

		// 查询理货工已经做了开始理货的预约单
		Criteria tallyCriteria = Criteria.forClass(TmsAppointmentHeaderModel.class);
		Restriction r11 = Restrictions.eq(TmsAppointmentHeaderModel::getTallyWorkerId, user.getUserid());
		Restriction r22 = Restrictions.eq(TmsAppointmentHeaderModel::getBranchId, waitForArrangeGoodsVO.getBranchId());
		Restriction r44 = Restrictions.eq(TmsAppointmentHeaderModel::getTallyStatus, DataDictionaryConstant.TALLY_STATUS_KSLH);
		Restriction r45 = Restrictions.gt(TmsAppointmentHeaderModel::getStatus, DataDictionaryConstant.APPOINTMENT_STATUS_QX);
		tallyCriteria.setRestriction(Restrictions.and(r11, r22, r44,r45));
		tallyCriteria.setOrder(Order.newInstance().asc(TmsAppointmentHeaderModel::getCallNumber));

		PageUtils.startPage(waitForArrangeGoodsVO.getPageNum(), waitForArrangeGoodsVO.getPageSize());
		List<TmsAppointmentHeaderModel> tallyTmsAppointmentHeaderModels = tmsAppointmentHeaderMapper.findByCriteria(tallyCriteria);

		if (ToolKits.isNotEmpty(tallyTmsAppointmentHeaderModels)) {
			for(TmsAppointmentHeaderModel tallyTmsAppointmentHeaderModel :tallyTmsAppointmentHeaderModels) {
				WaitForArrangeGoodsDTO waitForArrangeGoodsDTO = BeanUtil.copyProperties(tallyTmsAppointmentHeaderModel, WaitForArrangeGoodsDTO.class);
				waitForArrangeGoodsDTO.setStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.TALLY_STATUS, String.valueOf(tallyTmsAppointmentHeaderModel.getTallyStatus())));
				waitForArrangeGoodsDTO.setStatus(0);
				waitForArrangeGoodsDTO.setHasTakeNumAndCallNum(false);

				Criteria appointmentDetailCriteria = Criteria.forClass(TmsAppointmentDetailModel.class);
				r11 = Restrictions.eq(TmsAppointmentDetailModel::getAppointmentId, tallyTmsAppointmentHeaderModel.getAppointmentId());
				appointmentDetailCriteria.setRestriction(r11);
				List<TmsAppointmentDetailModel> tmsAppointmentDetailModels = tmsAppointmentDetailMapper.findByCriteria(appointmentDetailCriteria);
				//设置预约单的派车单
				waitForArrangeGoodsDTO.setLoadingBillIds(DataUtils.getLoadingBillIds(tmsAppointmentDetailModels));
				if (ToolKits.isNotEmpty(tmsAppointmentDetailModels)) {
					if (tmsAppointmentDetailModels.get(0).getFlowConfig().contains(DataDictionaryConstant.FLOW_CONFIG_APPOINTMENT_TN_CN)) {
						waitForArrangeGoodsDTO.setHasTakeNumAndCallNum(true);
					}
					waitForArrangeGoodsDTO.setShipbillIds(tmsAppointmentDetailModels.stream().map(TmsAppointmentDetailModel::getShipbillId).distinct().collect(Collectors.toList()));
					Criteria itemCriteria = Criteria.forClass(TmsShipbillDetailModel.class);
					r11 = Restrictions.in(TmsShipbillDetailModel::getShipbillId, tmsAppointmentDetailModels.stream().map(TmsAppointmentDetailModel::getShipbillId).distinct().collect(Collectors.toList()).toArray());
					itemCriteria.setRestriction(r11);
					List<TmsShipbillDetailModel> tmsShipbillDetailModels = tmsShipbillDetailMapper.findByCriteria(itemCriteria);

					for (TmsShipbillDetailModel tmsShipbillDetailModel : tmsShipbillDetailModels) {
						WaitForArrangeGoodsItemDTO waitForArrangeGoodsItemDTO = new WaitForArrangeGoodsItemDTO();
						BeanUtils.copyProperties(tmsShipbillDetailModel, waitForArrangeGoodsItemDTO);
						waitForArrangeGoodsItemDTOS.add(waitForArrangeGoodsItemDTO);
					}
				}
				waitForArrangeGoodsDTO.setWaitForArrangeGoodsItemDTOS(waitForArrangeGoodsItemDTOS);
				dtos.add(waitForArrangeGoodsDTO);
			}
			Page<WaitForArrangeGoodsDTO> page = PageUtils.getPage(dtos);
			if (tallyTmsAppointmentHeaderModels instanceof com.github.pagehelper.Page) {
				com.github.pagehelper.Page<TmsAppointmentHeaderModel> p0 = (com.github.pagehelper.Page<TmsAppointmentHeaderModel>) tallyTmsAppointmentHeaderModels;
				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<WaitForArrangeGoodsDTO> pageNoTakeNumAndCallNum = queryNoTakeNumAndCallNum(waitForArrangeGoodsVO,dicData);
		if (ToolKits.isNotEmpty(pageNoTakeNumAndCallNum)) {
			return pageNoTakeNumAndCallNum;
		}
		WaitForArrangeGoodsDTO waitForArrangeGoodsDTO = new WaitForArrangeGoodsDTO();
		waitForArrangeGoodsDTO.setHasTakeNumAndCallNum(true);
		// 查询已取号预约单
		Criteria criteria = Criteria.forClass(TmsAppointmentHeaderModel.class);
		Restriction r1 = Restrictions.in(TmsAppointmentHeaderModel::getStatus, new Integer[] { DataDictionaryConstant.APPOINTMENT_STATUS_YQH, DataDictionaryConstant.APPOINTMENT_STATUS_DDZ });
		Restriction r2 = Restrictions.eq(TmsAppointmentHeaderModel::getBranchId, waitForArrangeGoodsVO.getBranchId());
		Restriction r4 = Restrictions.lt(TmsAppointmentHeaderModel::getTallyStatus, DataDictionaryConstant.TALLY_STATUS_LHWC);
		criteria.setRestriction(Restrictions.and(r1, r2, r4));
		criteria.setOrder(Order.newInstance().asc(TmsAppointmentHeaderModel::getCallNumber));
		List<TmsAppointmentHeaderModel> tmsAppointmentHeaderModels = tmsAppointmentHeaderMapper.findByCriteria(criteria);

		if (ToolKits.isNotEmpty(tmsAppointmentHeaderModels)) {
			TmsAppointmentHeaderModel tmsAppointmentHeaderModel = tmsAppointmentHeaderModels.get(0);
			BeanUtils.copyProperties(tmsAppointmentHeaderModel, waitForArrangeGoodsDTO);
			if (DataDictionaryConstant.TALLY_STATUS_KSLH.equals(tmsAppointmentHeaderModel.getTallyStatus())) {
				waitForArrangeGoodsDTO.setStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.TALLY_STATUS, String.valueOf(tmsAppointmentHeaderModel.getTallyStatus())));
				waitForArrangeGoodsDTO.setStatus(0);
			} else {
				waitForArrangeGoodsDTO.setStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.APPOINTMENT_STATUS, String.valueOf(tmsAppointmentHeaderModel.getStatus())));
			}

			Criteria appointmentDetailCriteria = Criteria.forClass(TmsAppointmentDetailModel.class);
			r1 = Restrictions.eq(TmsAppointmentDetailModel::getAppointmentId, tmsAppointmentHeaderModel.getAppointmentId());
			appointmentDetailCriteria.setRestriction(r1);
			List<TmsAppointmentDetailModel> tmsAppointmentDetailModels = tmsAppointmentDetailMapper.findByCriteria(appointmentDetailCriteria);
			//设置预约单的派车单
			waitForArrangeGoodsDTO.setLoadingBillIds(DataUtils.getLoadingBillIds(tmsAppointmentDetailModels));
			if (ToolKits.isNotEmpty(tmsAppointmentDetailModels)) {
				waitForArrangeGoodsDTO.setShipbillIds(tmsAppointmentDetailModels.stream().map(TmsAppointmentDetailModel::getShipbillId).distinct().collect(Collectors.toList()));
				Criteria itemCriteria = Criteria.forClass(TmsShipbillDetailModel.class);
				r1 = Restrictions.in(TmsShipbillDetailModel::getShipbillId, tmsAppointmentDetailModels.stream().map(TmsAppointmentDetailModel::getShipbillId).distinct().collect(Collectors.toList()).toArray());
				itemCriteria.setRestriction(r1);
				List<TmsShipbillDetailModel> tmsShipbillDetailModels = tmsShipbillDetailMapper.findByCriteria(itemCriteria);

				for (TmsShipbillDetailModel tmsShipbillDetailModel : tmsShipbillDetailModels) {
					WaitForArrangeGoodsItemDTO waitForArrangeGoodsItemDTO = new WaitForArrangeGoodsItemDTO();
					BeanUtils.copyProperties(tmsShipbillDetailModel, waitForArrangeGoodsItemDTO);
					waitForArrangeGoodsItemDTOS.add(waitForArrangeGoodsItemDTO);
				}
			}
			waitForArrangeGoodsDTO.setWaitForArrangeGoodsItemDTOS(waitForArrangeGoodsItemDTOS);
		} else {
			// 查询已审核为急的预约单
			r1 = Restrictions.eq(TmsAppointmentHeaderModel::getStatus, DataDictionaryConstant.APPOINTMENT_STATUS_YSH);
			Restriction r3 = Restrictions.like(TmsAppointmentHeaderModel::getReserveNumber, "%急%");
			criteria.setRestriction(Restrictions.and(r1, r2, r3, r4));
			criteria.setOrder(Order.newInstance().asc(TmsAppointmentHeaderModel::getReserveNumber));
			List<TmsAppointmentHeaderModel> tmsAppointmentHeaderModelLike = tmsAppointmentHeaderMapper.findByCriteria(criteria);
			if (ToolKits.isNotEmpty(tmsAppointmentHeaderModelLike)) {
				TmsAppointmentHeaderModel tmsAppointmentHeaderModel = tmsAppointmentHeaderModelLike.get(0);
				BeanUtils.copyProperties(tmsAppointmentHeaderModel, waitForArrangeGoodsDTO);
				if (DataDictionaryConstant.TALLY_STATUS_KSLH.equals(tmsAppointmentHeaderModel.getTallyStatus())) {
					waitForArrangeGoodsDTO.setStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.TALLY_STATUS, String.valueOf(tmsAppointmentHeaderModel.getTallyStatus())));
					waitForArrangeGoodsDTO.setStatus(0);
				} else {
					waitForArrangeGoodsDTO.setStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.APPOINTMENT_STATUS, String.valueOf(tmsAppointmentHeaderModel.getStatus())));
				}

				Criteria appointmentDetailCriteria = Criteria.forClass(TmsAppointmentDetailModel.class);
				r1 = Restrictions.eq(TmsAppointmentDetailModel::getAppointmentId, tmsAppointmentHeaderModel.getAppointmentId());
				appointmentDetailCriteria.setRestriction(r1);
				List<TmsAppointmentDetailModel> tmsAppointmentDetailModels = tmsAppointmentDetailMapper.findByCriteria(appointmentDetailCriteria);
				//设置预约单的派车单
				waitForArrangeGoodsDTO.setLoadingBillIds(DataUtils.getLoadingBillIds(tmsAppointmentDetailModels));
				if (ToolKits.isNotEmpty(tmsAppointmentDetailModels)) {
					waitForArrangeGoodsDTO.setShipbillIds(tmsAppointmentDetailModels.stream().map(TmsAppointmentDetailModel::getShipbillId).distinct().collect(Collectors.toList()));
					Criteria itemCriteria = Criteria.forClass(TmsShipbillDetailModel.class);
					r1 = Restrictions.in(TmsShipbillDetailModel::getShipbillId, tmsAppointmentDetailModels.stream().map(TmsAppointmentDetailModel::getShipbillId).distinct().collect(Collectors.toList()).toArray());
					itemCriteria.setRestriction(r1);
					List<TmsShipbillDetailModel> tmsShipbillDetailModels = tmsShipbillDetailMapper.findByCriteria(itemCriteria);

					for (TmsShipbillDetailModel tmsShipbillDetailModel : tmsShipbillDetailModels) {
						WaitForArrangeGoodsItemDTO waitForArrangeGoodsItemDTO = new WaitForArrangeGoodsItemDTO();
						BeanUtils.copyProperties(tmsShipbillDetailModel, waitForArrangeGoodsItemDTO);
						waitForArrangeGoodsItemDTOS.add(waitForArrangeGoodsItemDTO);
					}
				}
				waitForArrangeGoodsDTO.setWaitForArrangeGoodsItemDTOS(waitForArrangeGoodsItemDTOS);
			} else {
				// 查询已审核不为急的预约单
				r1 = Restrictions.eq(TmsAppointmentHeaderModel::getStatus, DataDictionaryConstant.APPOINTMENT_STATUS_YSH);
				r3 = Restrictions.notLike(TmsAppointmentHeaderModel::getReserveNumber, "%急%");
				criteria.setRestriction(Restrictions.and(r1, r2, r3, r4));
				criteria.setOrder(Order.newInstance().asc(TmsAppointmentHeaderModel::getReserveNumber));
				List<TmsAppointmentHeaderModel> tmsAppointmentHeaderModelNotLike = tmsAppointmentHeaderMapper.findByCriteria(criteria);
				if (ToolKits.isNotEmpty(tmsAppointmentHeaderModelNotLike)) {
					TmsAppointmentHeaderModel tmsAppointmentHeaderModel = tmsAppointmentHeaderModelNotLike.get(0);
					BeanUtils.copyProperties(tmsAppointmentHeaderModel, waitForArrangeGoodsDTO);
					if (DataDictionaryConstant.TALLY_STATUS_KSLH.equals(tmsAppointmentHeaderModel.getTallyStatus())) {
						waitForArrangeGoodsDTO.setStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.TALLY_STATUS, String.valueOf(tmsAppointmentHeaderModel.getTallyStatus())));
						waitForArrangeGoodsDTO.setStatus(0);
					} else {
						waitForArrangeGoodsDTO.setStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.APPOINTMENT_STATUS, String.valueOf(tmsAppointmentHeaderModel.getStatus())));
					}

					Criteria appointmentDetailCriteria = Criteria.forClass(TmsAppointmentDetailModel.class);
					r1 = Restrictions.eq(TmsAppointmentDetailModel::getAppointmentId, tmsAppointmentHeaderModel.getAppointmentId());
					appointmentDetailCriteria.setRestriction(r1);
					List<TmsAppointmentDetailModel> tmsAppointmentDetailModels = tmsAppointmentDetailMapper.findByCriteria(appointmentDetailCriteria);
					//设置预约单的派车单
					waitForArrangeGoodsDTO.setLoadingBillIds(DataUtils.getLoadingBillIds(tmsAppointmentDetailModels));
					if (ToolKits.isNotEmpty(tmsAppointmentDetailModels)) {
						waitForArrangeGoodsDTO.setShipbillIds(tmsAppointmentDetailModels.stream().map(TmsAppointmentDetailModel::getShipbillId).distinct().collect(Collectors.toList()));
						Criteria itemCriteria = Criteria.forClass(TmsShipbillDetailModel.class);
						r1 = Restrictions.in(TmsShipbillDetailModel::getShipbillId, tmsAppointmentDetailModels.stream().map(TmsAppointmentDetailModel::getShipbillId).distinct().collect(Collectors.toList()).toArray());
						itemCriteria.setRestriction(r1);
						List<TmsShipbillDetailModel> tmsShipbillDetailModels = tmsShipbillDetailMapper.findByCriteria(itemCriteria);

						for (TmsShipbillDetailModel tmsShipbillDetailModel : tmsShipbillDetailModels) {
							WaitForArrangeGoodsItemDTO waitForArrangeGoodsItemDTO = new WaitForArrangeGoodsItemDTO();
							BeanUtils.copyProperties(tmsShipbillDetailModel, waitForArrangeGoodsItemDTO);
							waitForArrangeGoodsItemDTOS.add(waitForArrangeGoodsItemDTO);
						}
					}
					waitForArrangeGoodsDTO.setWaitForArrangeGoodsItemDTOS(waitForArrangeGoodsItemDTOS);
				}
			}
		}
		dtos.add(waitForArrangeGoodsDTO);
		Page<WaitForArrangeGoodsDTO> page = PageUtils.getPage(dtos);
		page.setPageCount(1);
		page.setPageNum(10);
		page.setPageSize(10);
		page.setTotalCount(1);
		page.setStartRow(1);
		page.setEndRow(1);
		return page;
	}

	Page<WaitForArrangeGoodsDTO> queryNoTakeNumAndCallNum (WaitForArrangeGoodsVO waitForArrangeGoodsVO,List<SysRefdatadModel> dicData) {
		List<WaitForArrangeGoodsDTO> dtos = Lists.newArrayList();
		Criteria criteriaAppointmentHeader = Criteria.forClass(TmsAppointmentHeaderModel.class);
		Restriction r1 = Restrictions.eq(TmsAppointmentHeaderModel::getStatus, DataDictionaryConstant.APPOINTMENT_STATUS_DLH);
		Restriction r2 = Restrictions.eq(TmsAppointmentHeaderModel::getBranchId, waitForArrangeGoodsVO.getBranchId());
		Restriction r3 = Restrictions.lt(TmsAppointmentHeaderModel::getTallyStatus, DataDictionaryConstant.TALLY_STATUS_LHWC);
		criteriaAppointmentHeader.setRestriction(Restrictions.and(r1, r2, r3));
		criteriaAppointmentHeader.setOrder(Order.newInstance().desc(TmsAppointmentHeaderModel::getUpdatetime));

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

		for (TmsAppointmentHeaderModel headerModel:tmsAppointmentHeaderModels ) {
			List<WaitForArrangeGoodsItemDTO> waitForArrangeGoodsItemDTOS = Lists.newArrayList();
			WaitForArrangeGoodsDTO waitForArrangeGoodsDTO = BeanUtil.copyProperties(headerModel, WaitForArrangeGoodsDTO.class);
			waitForArrangeGoodsDTO.setHasTakeNumAndCallNum(false);

			if (DataDictionaryConstant.TALLY_STATUS_KSLH.equals(headerModel.getTallyStatus())) {
				waitForArrangeGoodsDTO.setStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.TALLY_STATUS, String.valueOf(headerModel.getTallyStatus())));
				waitForArrangeGoodsDTO.setStatus(0);
			} else {
				waitForArrangeGoodsDTO.setStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.APPOINTMENT_STATUS, String.valueOf(headerModel.getStatus())));
			}

			Criteria appointmentDetailCriteria = Criteria.forClass(TmsAppointmentDetailModel.class);
			r1 = Restrictions.eq(TmsAppointmentDetailModel::getAppointmentId, headerModel.getAppointmentId());
			appointmentDetailCriteria.setRestriction(r1);
			List<TmsAppointmentDetailModel> tmsAppointmentDetailModels = tmsAppointmentDetailMapper.findByCriteria(appointmentDetailCriteria);
			if (ToolKits.isEmpty(tmsAppointmentDetailModels)) {
				throw new PrologException("预约明细不存在");
			}
			//设置预约单的派车单
			waitForArrangeGoodsDTO.setLoadingBillIds(DataUtils.getLoadingBillIds(tmsAppointmentDetailModels));

			waitForArrangeGoodsDTO.setShipbillIds(tmsAppointmentDetailModels.stream().map(TmsAppointmentDetailModel::getShipbillId).distinct().collect(Collectors.toList()));
			Criteria itemCriteria = Criteria.forClass(TmsShipbillDetailModel.class);
			r1 = Restrictions.in(TmsShipbillDetailModel::getShipbillId, tmsAppointmentDetailModels.stream().map(TmsAppointmentDetailModel::getShipbillId).distinct().collect(Collectors.toList()).toArray());
			itemCriteria.setRestriction(r1);
			List<TmsShipbillDetailModel> tmsShipbillDetailModels = tmsShipbillDetailMapper.findByCriteria(itemCriteria);

			for (TmsShipbillDetailModel tmsShipbillDetailModel : tmsShipbillDetailModels) {
				WaitForArrangeGoodsItemDTO waitForArrangeGoodsItemDTO = new WaitForArrangeGoodsItemDTO();
				BeanUtils.copyProperties(tmsShipbillDetailModel, waitForArrangeGoodsItemDTO);
				waitForArrangeGoodsItemDTOS.add(waitForArrangeGoodsItemDTO);
			}
			waitForArrangeGoodsDTO.setWaitForArrangeGoodsItemDTOS(waitForArrangeGoodsItemDTOS);
			dtos.add(waitForArrangeGoodsDTO);
		}
		Page<WaitForArrangeGoodsDTO> 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 ids
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void startArrangeGoods(List<String> ids) {
		ToolKits.isParamNull(ids, "请选中要操作的数据");
		UserEntity user = PlgFxUsrUtils.getUserEntity();
		ToolKits.isParamNull(user, "当前人员没有操作权限");
		Date date = DateUtil.date();

		Map<String, Object> mapTransportLogUpdate = Maps.newHashMap();
		mapTransportLogUpdate.put("updateperson", user.getNickname());
		mapTransportLogUpdate.put("updatetime", new Date());
		// 开始理货时间
		mapTransportLogUpdate.put("arrangeGoodsStartTime", new Date());
		Criteria criteriaLoadingBillDetail = Criteria.forClass(TmsLoadingBillDetailModel.class);
		Criteria criteriaLoadingHeader = Criteria.forClass(TmsLoadingBillHeaderModel.class);
		for (String id : ids) {
			TmsShipbillHeaderModel tmsShipbillHeader = tmsShipbillHeaderMapper.findById(id, TmsShipbillHeaderModel.class);
			if (ToolKits.isEmpty(tmsShipbillHeader)) {
				throw new PrologException("运单不存在");
			}
			// 调度单明细状态更新
			Restriction r1 = Restrictions.eq("shipbillId", id);
			Restriction r2 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
			criteriaLoadingBillDetail.setRestriction(Restrictions.and(r1, r2));
			criteriaLoadingBillDetail.setOrder(Order.newInstance().desc(TmsLoadingBillDetailModel::getCreatetime));
			List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteriaLoadingBillDetail);
			ToolKits.isParamNull(tmsLoadingBillDetailModels, "调度单明细不存在");
			TmsLoadingBillDetailModel loadingBillDetailModel = tmsLoadingBillDetailModels.get(0);
			if (loadingBillDetailModel.getStatus().intValue() > DataDictionaryConstant.SHIPBILL_STATUS_LH_START.intValue()) {
				throw new PrologException("运单【" + id + "】已开始理货");
			}
			Map<String, Object> mapFatherUpdate = Maps.newHashMap();
			mapFatherUpdate.put("updateperson", user.getNickname());
			mapFatherUpdate.put("updatetime", date);
			mapFatherUpdate.put("status", DataDictionaryConstant.SHIPBILL_STATUS_LH_FINISH);
			tmsLoadingBillDetailMapper.updateMapById(loadingBillDetailModel.getId(), mapFatherUpdate, TmsLoadingBillDetailModel.class);

			tmsShipbillHeader.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_LH_FINISH);
			tmsShipbillHeader.setUpdateperson(user.getNickname());
			tmsShipbillHeader.setUpdatetime(new Date());
			tmsShipbillHeaderMapper.update(tmsShipbillHeader);

			// 判断预约单是否存在
			Criteria criteriaAppointment = Criteria.forClass(TmsAppointmentDetailModel.class);
			Restriction appointment = Restrictions.eq(TmsAppointmentDetailModel::getShipbillId, tmsShipbillHeader.getShipbillId());
			criteriaAppointment.setRestriction(appointment);
			criteriaAppointment.setOrder(Order.newInstance().desc(new String[] { "createtime" }));
			List<TmsAppointmentDetailModel> tmsAppointmentDetailModels = tmsAppointmentDetailMapper.findByCriteria(criteriaAppointment);
			if (ToolKits.isNotEmpty(tmsAppointmentDetailModels)) {
				TmsAppointmentDetailModel tmsAppointmentDetailModel = tmsAppointmentDetailModels.get(0);
				if (user.getUserType().equals(BussinessConstant.USER_TYPE_ZY)) {
					if (ToolKits.isEmpty(tmsAppointmentDetailModel.getFlowConfig()) || !tmsAppointmentDetailModel.getFlowConfig().contains(DataDictionaryConstant.FLOW_CONFIG_ARRANGE_GOODS)) {
						throw new PrologException("运单【" + tmsAppointmentDetailModel.getShipbillId() + "】没有待理货流程，不能做理货");
					}
				} else {
					if (ToolKits.isEmpty(tmsAppointmentDetailModel.getCarrierFlowConfig()) || !tmsAppointmentDetailModel.getCarrierFlowConfig().contains(DataDictionaryConstant.FLOW_CONFIG_ARRANGE_GOODS)) {
						throw new PrologException("运单【" + tmsAppointmentDetailModel.getShipbillId() + "】没有待理货流程，不能做理货");
					}
				}
				// 预约明细
				tmsAppointmentDetailModel.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_LH_FINISH);
				tmsAppointmentDetailModel.setUpdateperson(user.getNickname());
				tmsAppointmentDetailModel.setUpdatetime(date);
				tmsAppointmentDetailMapper.update(tmsAppointmentDetailModel);

				Criteria criteriaAppointmentAll = Criteria.forClass(TmsAppointmentDetailModel.class);
				Restriction appointmentId = Restrictions.eq(TmsAppointmentDetailModel::getAppointmentId, tmsAppointmentDetailModel.getAppointmentId());
				criteriaAppointmentAll.setRestriction(appointmentId);
				List<TmsAppointmentDetailModel> allAppointmentDetailModels = tmsAppointmentDetailMapper.findByCriteria(criteriaAppointmentAll);
				List<TmsAppointmentDetailModel> tmsAppointmentDetails = allAppointmentDetailModels.stream().filter(o -> o.getStatus().intValue() < DataDictionaryConstant.SHIPBILL_STATUS_LH_FINISH.intValue()).collect(Collectors.toList());

				TmsAppointmentHeaderModel tmsAppointmentHeaderModel = tmsAppointmentHeaderMapper.findById(tmsAppointmentDetailModel.getAppointmentId(), TmsAppointmentHeaderModel.class);
				if (ToolKits.isEmpty(tmsAppointmentDetails)) {
					// 预约明细全部开始理货完成时，更新预约主表为开始理货
					// 预约主表 开始理货
					tmsAppointmentHeaderModel.setTallyStatus(DataDictionaryConstant.TALLY_STATUS_KSLH);
					tmsAppointmentHeaderModel.setUpdateperson(user.getNickname());
					tmsAppointmentHeaderModel.setUpdatetime(date);
				}
				tmsAppointmentHeaderModel.setTallyWorkerId(user.getUserid());
				tmsAppointmentHeaderModel.setTallyWorkerCode(String.valueOf(user.getUserid()));
				tmsAppointmentHeaderModel.setTallyWorkerName(user.getNickname());
				tmsAppointmentHeaderMapper.update(tmsAppointmentHeaderModel);
			}
			// 维护运单节点数据
			ShipbillNodeTrackingSaveNewVO shipbillNodeTrackingSaveVO = new ShipbillNodeTrackingSaveNewVO();
			shipbillNodeTrackingSaveVO.setShipbillId(tmsShipbillHeader.getShipbillId());
			shipbillNodeTrackingSaveVO.setShipbillNo(tmsShipbillHeader.getShipbillNo());
			shipbillNodeTrackingSaveVO.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_LH_FINISH);
			shipbillNodeTrackingSaveVO.setNodeEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_LH_START);
			shipbillNodeTrackingSaveVO.setNodeDate(date);
			shipbillNodeTrackingService.addShipbillNodeTrackingNewData(shipbillNodeTrackingSaveVO);

			// 维护运单日志保存
			ShipbillOperateLogSaveNewVO shipbillOperateLogSaveVO = new ShipbillOperateLogSaveNewVO();
			shipbillOperateLogSaveVO.setShipbillId(tmsShipbillHeader.getShipbillId());
			shipbillOperateLogSaveVO.setShipbillNo(tmsShipbillHeader.getShipbillNo());
			shipbillOperateLogSaveVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_LH_START);
			shipbillOperateLogSaveVO.setOperateDate(date);
			shipbillOperateLogSaveVO.setOldStatus(tmsShipbillHeader.getStatus());
			shipbillOperateLogSaveVO.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_LH_FINISH);
			shipbillOperateLogService.addShipbillOperateLogNewData(shipbillOperateLogSaveVO);

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

			// 更新调度单状态
			Restriction r3 = Restrictions.eq("loadingBillId", loadingBillDetailModel.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() != DataDictionaryConstant.SHIPBILL_STATUS_LH_FINISH) {
				// 更新调度单
				Map<String, Object> mapHeaderUpdate = Maps.newHashMap();
				mapHeaderUpdate.put("updateperson", user.getNickname());
				mapHeaderUpdate.put("updatetime", date);
				mapHeaderUpdate.put("status", DataDictionaryConstant.LOADING_BILL_STATUS_LH_START);
				tmsLoadingBillHeaderMapper.updateMapByCriteria(mapHeaderUpdate, criteriaLoadingHeader);
			}

			// 依次递归更新上级运单状态为开始理货
			String fatherShipbillId = tmsShipbillHeader.getShipbillId();
			while (ToolKits.isNotEmpty(fatherShipbillId)) {
				fatherShipbillId = startArrangeGoodsFather(fatherShipbillId, user, shipbillNodeTrackingSaveVO, shipbillOperateLogSaveVO);
			}
		}
	}

	/**
	 * 理货完成
	 *
	 * @param ids
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void completeArrangeGoods(List<String> ids) {
		UserEntity user = PlgFxUsrUtils.getUserEntity();
		ToolKits.isParamNull(user, "当前人员没有操作权限");
		ToolKits.isParamNull(ids, "请选中要操作的数据");
		Date date = DateUtil.date();
		Map<String, Object> mapTransportLogUpdate = Maps.newHashMap();
		mapTransportLogUpdate.put("updateperson", user.getNickname());
		mapTransportLogUpdate.put("updatetime", date);
		// 理货完成时间
		mapTransportLogUpdate.put("arrangeGoodsEndTime", date);

		Criteria criteriaLoadingBillDetail = Criteria.forClass(TmsLoadingBillDetailModel.class);
		Criteria criteriaLoadingHeader = Criteria.forClass(TmsLoadingBillHeaderModel.class);

		for (String id : ids) {
			Restriction r1 = Restrictions.eq(TmsLoadingBillDetailModel::getShipbillId, id);
			Restriction r2 = Restrictions.eq(TmsLoadingBillDetailModel::getEnterpriseId, user.getEnterpriseId());
			criteriaLoadingBillDetail.setRestriction(Restrictions.and(r1, r2));
			criteriaLoadingBillDetail.setOrder(Order.newInstance().desc(new String[] { "createtime" }));
			List<TmsLoadingBillDetailModel> tmsLoadingBillDetails = tmsLoadingBillDetailMapper.findByCriteria(criteriaLoadingBillDetail);

			if (ToolKits.isEmpty(tmsLoadingBillDetails)) {
				throw new PrologException("运单【" + id + "】查询失败");
			}
			TmsLoadingBillDetailModel tmsLoadingBillDetail = tmsLoadingBillDetails.get(0);

			if (tmsLoadingBillDetail.getStatus().intValue() > DataDictionaryConstant.SHIPBILL_STATUS_LH_FINISH.intValue()) {
				throw new PrologException("运单【" + id + "】已理货完成");
			}
			if (ToolKits.isNotEmpty(tmsLoadingBillDetail.getAppTallyStatus()) &&
					tmsLoadingBillDetail.getAppTallyStatus().intValue() > DataDictionaryConstant.TALLY_STATUS_KSLH.intValue()) {
				throw new PrologException("运单【" + id + "】已理货完成");
			}

			TmsShipbillHeaderModel tmsShipbillHeader = tmsShipbillHeaderMapper.findById(id, TmsShipbillHeaderModel.class);
			if (ToolKits.isNotEmpty(tmsShipbillHeader)) {
				// 判定下一步流程,取下一步流程的状态
				String flowConfig = "";
				if (user.getUserType().equals(BussinessConstant.USER_TYPE_ZY)) {
					flowConfig = tmsShipbillHeader.getFlowConfig();
				} else if (user.getUserType().equals(BussinessConstant.USER_TYPE_CYS)) {
					flowConfig = tmsShipbillHeader.getCarrierFlowConfig();
				}
				int status = businessFlowUtil.judgmentNextFlowSts(flowConfig, DataDictionaryConstant.FLOW_CONFIG_ARRANGE_GOODS);

				// 判断预约单是否存在
				Criteria criteriaAppointment = Criteria.forClass(TmsAppointmentDetailModel.class);
				Restriction appointment = Restrictions.eq(TmsAppointmentDetailModel::getShipbillId, tmsShipbillHeader.getShipbillId());
				criteriaAppointment.setRestriction(appointment);
				criteriaAppointment.setOrder(Order.newInstance().desc(new String[] { "createtime" }));
				List<TmsAppointmentDetailModel> tmsAppointmentDetailModels = tmsAppointmentDetailMapper.findByCriteria(criteriaAppointment);
				Boolean upStatus = true;
				Boolean hasTakeNumAndCallNum = false;
				Boolean hasLoading = false;
				if (ToolKits.isNotEmpty(tmsAppointmentDetailModels)) {
					TmsAppointmentDetailModel tmsAppointmentDetailModel = tmsAppointmentDetailModels.get(0);
					if (user.getUserType().equals(BussinessConstant.USER_TYPE_ZY)) {
						if (ToolKits.isEmpty(tmsAppointmentDetailModel.getFlowConfig()) || !tmsAppointmentDetailModel.getFlowConfig().contains(DataDictionaryConstant.FLOW_CONFIG_ARRANGE_GOODS)) {
							throw new PrologException("运单【" + tmsAppointmentDetailModel.getShipbillId() + "】没有待理货流程，不能做理货");
						}
						if (tmsAppointmentDetailModel.getFlowConfig().contains(DataDictionaryConstant.FLOW_CONFIG_APPOINTMENT_TN_CN)) {
							hasTakeNumAndCallNum = true;
						}
						if (tmsAppointmentDetailModel.getFlowConfig().contains(DataDictionaryConstant.FLOW_CONFIG_LOAD_UNLOAD)) {
							hasLoading = true;
						}
					} else {
						if (ToolKits.isEmpty(tmsAppointmentDetailModel.getCarrierFlowConfig()) || !tmsAppointmentDetailModel.getCarrierFlowConfig().contains(DataDictionaryConstant.FLOW_CONFIG_ARRANGE_GOODS)) {
							throw new PrologException("运单【" + tmsAppointmentDetailModel.getShipbillId() + "】没有待理货流程，不能做理货");
						}
						if (tmsAppointmentDetailModel.getCarrierFlowConfig().contains(DataDictionaryConstant.FLOW_CONFIG_APPOINTMENT_TN_CN)) {
							hasTakeNumAndCallNum = true;
						}
						if (tmsAppointmentDetailModel.getCarrierFlowConfig().contains(DataDictionaryConstant.FLOW_CONFIG_LOAD_UNLOAD)) {
							hasLoading = true;
						}
					}
					// 更新运单的预约理货状态为理货完成
					tmsShipbillHeader.setAppTallyStatus(DataDictionaryConstant.TALLY_STATUS_LHWC);
					tmsShipbillHeaderMapper.update(tmsShipbillHeader);
					// 更新预约明细的预约理货状态为理货完成
					tmsAppointmentDetailModel.setAppTallyStatus(DataDictionaryConstant.TALLY_STATUS_LHWC);
					tmsAppointmentDetailMapper.update(tmsAppointmentDetailModel);
					// 更新装车明细的预约理货状态为理货完成
					tmsLoadingBillDetail.setAppTallyStatus(DataDictionaryConstant.TALLY_STATUS_LHWC);
					tmsLoadingBillDetailMapper.update(tmsLoadingBillDetail);

					Criteria criteriaAppointmentAll = Criteria.forClass(TmsAppointmentDetailModel.class);
					Restriction appointmentId = Restrictions.eq(TmsAppointmentDetailModel::getAppointmentId, tmsAppointmentDetailModel.getAppointmentId());
					criteriaAppointmentAll.setRestriction(appointmentId);
					List<TmsAppointmentDetailModel> allAppointmentDetailModels = tmsAppointmentDetailMapper.findByCriteria(criteriaAppointmentAll);

					List<TmsAppointmentDetailModel> tmsAppointmentDetails = allAppointmentDetailModels.stream().filter(o -> ToolKits.isEmpty(o.getAppTallyStatus()) || !o.getAppTallyStatus().equals(DataDictionaryConstant.TALLY_STATUS_LHWC)).collect(Collectors.toList());

					if (ToolKits.isEmpty(tmsAppointmentDetails)) {
						// 预约明细全部理货完成时，更新预约主表为理货完成
						TmsAppointmentHeaderModel tmsAppointmentHeaderModel = tmsAppointmentHeaderMapper.findById(tmsAppointmentDetailModel.getAppointmentId(), TmsAppointmentHeaderModel.class);
						// 预约主表 开始理货
						tmsAppointmentHeaderModel.setTallyStatus(DataDictionaryConstant.TALLY_STATUS_LHWC);
						tmsAppointmentHeaderModel.setUpdateperson(user.getNickname());
						tmsAppointmentHeaderModel.setUpdatetime(date);
						if (!hasTakeNumAndCallNum) {
							if (hasLoading) {
								tmsAppointmentHeaderModel.setStatus(DataDictionaryConstant.APPOINTMENT_STATUS_DZX);
							} else {
								tmsAppointmentHeaderModel.setStatus(DataDictionaryConstant.APPOINTMENT_STATUS_ZXWC);
							}
						} else {
							if (!hasLoading) {
								tmsAppointmentHeaderModel.setStatus(DataDictionaryConstant.APPOINTMENT_STATUS_ZXWC);
							}
						}
						tmsAppointmentHeaderMapper.update(tmsAppointmentHeaderModel);
					}
					if (hasTakeNumAndCallNum && hasLoading) {
						upStatus = false;
					}
				}

				// 调度单明细状态更新
				if (upStatus) {
					Map<String, Object> mapFatherUpdate = Maps.newHashMap();
					mapFatherUpdate.put("updateperson", user.getNickname());
					mapFatherUpdate.put("updatetime", date);
					mapFatherUpdate.put("status", status);
					tmsLoadingBillDetailMapper.updateMapById(tmsLoadingBillDetail.getId(), mapFatherUpdate, TmsLoadingBillDetailModel.class);
					// 运单更新
					tmsShipbillHeader.setStatus(status);
					tmsShipbillHeader.setUpdateperson(user.getNickname());
					tmsShipbillHeader.setUpdatetime(new Date());
					tmsShipbillHeaderMapper.update(tmsShipbillHeader);
				}

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

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

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

				// 依次递归更新上级运单状态为理货完成
				String fatherShipbillId = tmsShipbillHeader.getShipbillId();
				while (ToolKits.isNotEmpty(fatherShipbillId)) {
					fatherShipbillId = updateFatherShipBillEndArrange(fatherShipbillId, status, date);
				}

				// 更新调度单状态
				Restriction r3 = Restrictions.eq("loadingBillId", tmsLoadingBillDetail.getLoadingBillId());
				Restriction r4 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
				criteriaLoadingBillDetail.setRestriction(Restrictions.and(r3, r4));
				tmsLoadingBillDetails = tmsLoadingBillDetailMapper.findByCriteria(criteriaLoadingBillDetail);
				if (ToolKits.isNotEmpty(tmsLoadingBillDetails)) {
					List<TmsLoadingBillDetailModel> filterTmsLoadingBillDetailModels = tmsLoadingBillDetails.stream().filter(dto -> dto.getStatus().intValue() < DataDictionaryConstant.SHIPBILL_STATUS_ZX_START.intValue()).collect(Collectors.toList());
					if (ToolKits.isEmpty(filterTmsLoadingBillDetailModels)) {
						// 更新状态为理货完成
						criteriaLoadingHeader.setRestriction(Restrictions.and(r3, r4));
						// 更新调度单
						Map<String, Object> mapHeaderUpdate = Maps.newHashMap();
						mapHeaderUpdate.put("updateperson", user.getNickname());
						mapHeaderUpdate.put("updatetime", date);
						mapHeaderUpdate.put("status", status);
						tmsLoadingBillHeaderMapper.updateMapByCriteria(mapHeaderUpdate, criteriaLoadingHeader);
					}
				}

			} else {
				throw new PrologException("运单查询失败");
			}
			MessageUtil.addMessage(new SendMessageDTO(MessageOrderTypeEnum.SHIP_NO.getCode(), MessageTypeEnum.TALLY.getCode(), Lists.newArrayList(id)));
		}
	}

	/**
	 * 开始理货递归父运单
	 *
	 * @param
	 * @param
	 * @param
	 * @return
	 */
	private String startArrangeGoodsFather(String shipbillId, UserEntity user, ShipbillNodeTrackingSaveNewVO shipbillNodeTrackingSaveNewVO, ShipbillOperateLogSaveNewVO shipbillOperateLogSaveNewVO) {
		TmsShipbillHeaderModel tmsShipbillHeaderModel = tmsShipbillHeaderMapper.findById(shipbillId, TmsShipbillHeaderModel.class);

		// 判断是否为原始单号
		if (ToolKits.isNotEmpty(tmsShipbillHeaderModel.getFatherShipbillId()) && !tmsShipbillHeaderModel.getFatherShipbillId().equals(shipbillId)) {
			// 查找父级单号
			TmsShipbillHeaderModel fatherShipbillHeaderModel = tmsShipbillHeaderMapper.findById(tmsShipbillHeaderModel.getFatherShipbillId(), TmsShipbillHeaderModel.class);
			// 判断父级单号的状态是否为【开始理货】
			if (ObjectUtil.notEqual(fatherShipbillHeaderModel.getStatus(), DataDictionaryConstant.SHIPBILL_STATUS_LH_FINISH)) {
				// 修改父运单状态
				fatherShipbillHeaderModel.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_LH_FINISH);
				fatherShipbillHeaderModel.setUpdatetime(DateUtil.date());
				fatherShipbillHeaderModel.setUpdateperson(user.getNickname());
				tmsShipbillHeaderMapper.update(fatherShipbillHeaderModel);

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

				// 运单日志保存
				shipbillOperateLogSaveNewVO.setOperateDate(DateUtil.date());
				shipbillOperateLogSaveNewVO.setShipbillId(fatherShipbillHeaderModel.getShipbillId());
				shipbillOperateLogSaveNewVO.setShipbillNo(fatherShipbillHeaderModel.getShipbillId());
				shipbillOperateLogService.addShipbillOperateLogNewData(shipbillOperateLogSaveNewVO);
				return fatherShipbillHeaderModel.getShipbillId();
			}
		}
		return null;
	}

	/**
	 * 递归更新父运单理货完成状态
	 *
	 * @param
	 * @return
	 */
	private 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() < DataDictionaryConstant.SHIPBILL_STATUS_ZX_START.intValue()).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 waitForArrangeGoodsQueryVO
	 * @return
	 */
	@SuppressWarnings("resource")
	@Override
	public Page<WaitForArrangeGoodsQueryDTO> queryShipbillData(WaitForArrangeGoodsQueryVO waitForArrangeGoodsQueryVO) {
		UserEntity user = PlgFxUsrUtils.getUserEntity();
		ToolKits.isParamNull(user, "当前人员没有操作权限");
		ToolKits.isParamNull(waitForArrangeGoodsQueryVO.getPageNum(), "当前页码不为空");
		ToolKits.isParamNull(waitForArrangeGoodsQueryVO.getPageSize(), "每页条数不为空");
		ToolKits.isParamNull(waitForArrangeGoodsQueryVO.getShipbillIds(), "运单ID不为空");

		// 数据字典翻译数据集合

		List<Map<String, Object>> data6 = Lists.newArrayList();
		List<Map<String, Object>> data7 = Lists.newArrayList();
		List<Map<String, Object>> data8 = Lists.newArrayList();

		// 发货方类型
		RestMessage<List<Map<String, Object>>> restMessage6 = maindataTmsResource.getDropDownById(DataDictionaryConstant.SHIPPER_TYPE, null, null, null);
		if (!restMessage6.isSuccess()) {
			throw new RuntimeException("发货方类型翻译失败!");
		} else {
			data6 = restMessage6.getData();
		}
		// 收货方类型
		RestMessage<List<Map<String, Object>>> restMessage7 = maindataTmsResource.getDropDownById(DataDictionaryConstant.CONSIGNEE_TYPE, null, null, null);
		if (!restMessage7.isSuccess()) {
			throw new RuntimeException("收货方类型翻译失败!");
		} else {
			data7 = restMessage7.getData();
		}

		// 运单状态
		RestMessage<List<Map<String, Object>>> restMessage8 = maindataTmsResource.getDropDownById(DataDictionaryConstant.SHIPBILL_STATUS, null, null, null);
		if (!restMessage8.isSuccess()) {
			throw new RuntimeException("运单状态翻译失败!");
		} else {
			data8 = restMessage8.getData();
		}

		// 添加查询条件
		Criteria criteria = Criteria.forClass(TmsShipbillHeaderModel.class);

		Restriction r1 = Restrictions.eq(TmsShipbillHeaderModel::getEnterpriseId, user.getEnterpriseId());

		Restriction r2 = Restrictions.in(TmsShipbillHeaderModel::getShipbillId, waitForArrangeGoodsQueryVO.getShipbillIds().toArray());

		criteria.setRestriction(Restrictions.and(r1, r2));
		criteria.setOrder(Order.newInstance().desc(new String[] { "updatetime" }));

		PageUtils.startPage(waitForArrangeGoodsQueryVO.getPageNum(), waitForArrangeGoodsQueryVO.getPageSize());
		List<TmsShipbillHeaderModel> tmsShipbillHeaderModels = tmsShipbillHeaderMapper.findByCriteria(criteria);

		List<WaitForArrangeGoodsQueryDTO> list = Lists.newArrayList();
		for (TmsShipbillHeaderModel model : tmsShipbillHeaderModels) {
			WaitForArrangeGoodsQueryDTO dto = new WaitForArrangeGoodsQueryDTO();
			BeanUtils.copyProperties(model, dto);
			dto.setLoadingBillId(loadingBillService.getLoadingBillIdByShipBillId(dto.getShipbillId()));

			// 类型翻译
			dto.setShipperTypeName(PublicMethods.change(data6, String.valueOf(dto.getShipperType())));
			dto.setConsigneeTypeName(PublicMethods.change(data7, String.valueOf(dto.getConsigneeType())));
			if (user.getUserType().equals(BussinessConstant.USER_TYPE_CYS)) {
				dto.setStatus(model.getCarrierShipbillStatus());
				dto.setStatusName(PublicMethods.change(data8, String.valueOf(model.getCarrierShipbillStatus())));
			} else {
				dto.setStatusName(PublicMethods.change(data8, String.valueOf(dto.getStatus())));
			}

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

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

			if (ToolKits.isNotEmpty(tmsShipbillPackageModels)) {
				List<WaitForArrangeGoodsPackageDTO> packageDTOList = Lists.newArrayList();
				for (TmsShipbillPackageModel packageModel : tmsShipbillPackageModels) {
					WaitForArrangeGoodsPackageDTO packageDTO = new WaitForArrangeGoodsPackageDTO();
					BeanUtils.copyProperties(packageModel, packageDTO);
					packageDTOList.add(packageDTO);
				}
				dto.setWaitForArrangeGoodsPackageDTOS(packageDTOList);
				list.add(dto);
				continue;
			}

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

			List<WaitForArrangeGoodsItemDTO> itemDTOList = Lists.newArrayList();
			for (TmsShipbillDetailModel detailModel : tmsShipbillDetailModels) {
				WaitForArrangeGoodsItemDTO itemDTO = new WaitForArrangeGoodsItemDTO();
				BeanUtils.copyProperties(detailModel, itemDTO);
				itemDTOList.add(itemDTO);
			}
			// 商品信息
			dto.setWaitForArrangeGoodsItemDTOS(itemDTOList);

			list.add(dto);
		}

		// 分页重组
		Page<WaitForArrangeGoodsQueryDTO> page = PageUtils.getPage(list);
		if (tmsShipbillHeaderModels instanceof com.github.pagehelper.Page) {
			com.github.pagehelper.Page<TmsShipbillHeaderModel> p0 = (com.github.pagehelper.Page<TmsShipbillHeaderModel>) tmsShipbillHeaderModels;
			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;
	}
}
