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

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

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.util.DataUtils;
import com.prolog.rdc.tms.util.MessageUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.prolog.common.util.ToolKits;
import com.prolog.cs.platform.power.model.Organization;
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.constant.BussinessConstant;
import com.prolog.rdc.tms.constant.DataDictionaryConstant;
import com.prolog.rdc.tms.constant.StatusConstant;
import com.prolog.rdc.tms.dao.mapper.TmsAppointmentDetailMapper;
import com.prolog.rdc.tms.dao.mapper.TmsAppointmentHeaderMapper;
import com.prolog.rdc.tms.dao.mapper.TmsLoadingBillDetailMapper;
import com.prolog.rdc.tms.dao.mapper.TmsLoadingBillHeaderMapper;
import com.prolog.rdc.tms.dao.mapper.TmsShipbillDetailMapper;
import com.prolog.rdc.tms.dao.mapper.TmsShipbillHeaderMapper;
import com.prolog.rdc.tms.dao.mapper.TmsShipbillPackageMapper;
import com.prolog.rdc.tms.dao.mapper.TmsShipbillTransportLogMapper;
import com.prolog.rdc.tms.model.dto.WaitForArrangeGoodsAppointmentDTO;
import com.prolog.rdc.tms.model.dto.WaitForArrangeGoodsExportDTO;
import com.prolog.rdc.tms.model.dto.WaitForArrangeGoodsItemDTO;
import com.prolog.rdc.tms.model.dto.WaitForArrangeGoodsPackageDTO;
import com.prolog.rdc.tms.model.dto.WaitForArrangeGoodsReceiverPageDTO;
import com.prolog.rdc.tms.model.dto.WaitForArrangeGoodsShipbillDTO;
import com.prolog.rdc.tms.model.dto.WaitForArrangeGoodsShipbillPageDTO;
import com.prolog.rdc.tms.model.entity.SysRefdatadModel;
import com.prolog.rdc.tms.model.entity.TmsAppointmentDetailModel;
import com.prolog.rdc.tms.model.entity.TmsAppointmentHeaderModel;
import com.prolog.rdc.tms.model.entity.TmsLoadingBillDetailModel;
import com.prolog.rdc.tms.model.entity.TmsLoadingBillHeaderModel;
import com.prolog.rdc.tms.model.entity.TmsShipbillDetailModel;
import com.prolog.rdc.tms.model.entity.TmsShipbillHeaderModel;
import com.prolog.rdc.tms.model.entity.TmsShipbillPackageModel;
import com.prolog.rdc.tms.model.entity.TmsShipbillTransLogModel;
import com.prolog.rdc.tms.model.vo.ReceiverTypeQueryVO;
import com.prolog.rdc.tms.model.vo.ShipbillNodeTrackingSaveNewVO;
import com.prolog.rdc.tms.model.vo.ShipbillNodeTrackingSaveVO;
import com.prolog.rdc.tms.model.vo.ShipbillOperateLogSaveNewVO;
import com.prolog.rdc.tms.model.vo.ShipbillOperateLogSaveVO;
import com.prolog.rdc.tms.model.vo.ShipbillTypeAdvancedQueryVO;
import com.prolog.rdc.tms.model.vo.ShipbillTypeQueryVO;
import com.prolog.rdc.tms.model.vo.WaitForArrangeGoodsAppointmentVO;
import com.prolog.rdc.tms.rmi.feign.MaindataFeign;
import com.prolog.rdc.tms.rmi.feign.UserFeign;
import com.prolog.rdc.tms.service.ShipbillNodeTrackingService;
import com.prolog.rdc.tms.service.ShipbillOperateLogService;
import com.prolog.rdc.tms.service.WaitForArrangeGoodsService;
import com.prolog.rdc.tms.util.BusinessFlowUtil;
import com.prolog.rdc.tms.util.ConvertorUtil;
import com.prolog.rdc.tms.util.PublicMethods;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;

/**
 * 待理货实现层
 *
 * @author xyf
 * @since 2022/4/18 12:43
 */
@Service
public class WaitForArrangeGoodsServiceImpl implements WaitForArrangeGoodsService {

	@Autowired
	private TmsLoadingBillDetailMapper tmsLoadingBillDetailMapper;

	@Autowired
	private UserFeign userTmsResource;

	@Autowired
	private MaindataFeign maindataTmsResource;

	@Autowired
	private TmsShipbillPackageMapper tmsShipbillPackageMapper;

	@Autowired
	private TmsShipbillDetailMapper tmsShipbillDetailMapper;

	@Autowired
	private TmsShipbillHeaderMapper tmsShipbillHeaderMapper;

	@Autowired
	private ShipbillNodeTrackingService shipbillNodeTrackingService;

	@Autowired
	private ShipbillOperateLogService shipbillOperateLogService;

	@Autowired
	private TmsLoadingBillHeaderMapper tmsLoadingBillHeaderMapper;

	@Autowired
	private TmsShipbillTransportLogMapper tmsShipbillTransportLogMapper;

	@Autowired
	private ConvertorUtil convertorUtil;

	@Autowired
	private BusinessFlowUtil businessFlowUtil;

	@Autowired
	private TmsAppointmentHeaderMapper tmsAppointmentHeaderMapper;

	@Autowired
	private TmsAppointmentDetailMapper tmsAppointmentDetailMapper;

	/**
	 * 待理货——运单模式分页查询
	 *
	 */
	@Override
	public Page<WaitForArrangeGoodsShipbillPageDTO> queryShipbillTypePage(ShipbillTypeQueryVO vo) throws Exception {
		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, "当前人员没有操作权限");
		}
		List<SysRefdatadModel> dicData = convertorUtil.getDictionary(new String[] { DataDictionaryConstant.SHIPBILL_STATUS, // 运单状态
				DataDictionaryConstant.TRANSPORT_STATUS, // 运输状态
				DataDictionaryConstant.LINE_CARRIER_TYPE, // 承运方类型
				DataDictionaryConstant.ABNORMAL_STATUS, // 异常状态
				DataDictionaryConstant.SCAN_STATUS, // 扫描状态
				DataDictionaryConstant.ORDER_TYPE, // 订单类型
				DataDictionaryConstant.ORDER_BUSINESS_TYPE, // 订单业务类型
				DataDictionaryConstant.DELIVERY_METHOD_TYPE, // 配送方式
				DataDictionaryConstant.TRANSPORT_TYPE, // 运输类型(运输模式)
				DataDictionaryConstant.TEMPERATURE_REQUIREMENT// 温度要求
		});

		vo.setUserType(user.getUserType());
		vo.setEnterpriseId(user.getEnterpriseId());

		if (ObjectUtil.equal(user.getUserType(), BussinessConstant.USER_TYPE_ZY)) {// 自有账号
			vo.setDepts(ToolKits.isEmpty(user.getDepts()) ? null : user.getDepts().stream().toArray(String[]::new));
			if (BussinessConstant.USER_DEPARTMENT_AUTH_Y.equals(user.getOwnedAllDataAuthFlag())) {// 部门权限
				vo.setIsDept("YES");
			} else {// 业务员权限
				vo.setIsDept("NO");
				// 货主
				vo.setConsignors(ToolKits.isEmpty(user.getConsignors()) ? null : user.getConsignors().stream().toArray(Long[]::new));
				// 客户
				vo.setCustomers(ToolKits.isEmpty(user.getCustomers()) ? null : user.getCustomers().stream().toArray(Long[]::new));
				// 供应商
				vo.setSuppliers(ToolKits.isEmpty(user.getSuppliers()) ? null : user.getSuppliers().stream().toArray(Long[]::new));
				// 仓库
				vo.setWsarehouses(ToolKits.isEmpty(user.getWarehouses()) ? null : user.getWarehouses().stream().toArray(Long[]::new));
			}
		}
		if (ObjectUtil.equal(user.getUserType(), BussinessConstant.USER_TYPE_CYS)) {// 承运商账号
			vo.setCarrierId(Long.valueOf(user.getLoginUserCompanyInfo().getId()));
		}

		PageUtils.startPage(vo.getPageNum(), vo.getPageSize());
		List<WaitForArrangeGoodsShipbillPageDTO> list = tmsLoadingBillDetailMapper.queryShipbillTypePage(vo);

		for (WaitForArrangeGoodsShipbillPageDTO dto : list) {
			dto.setStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.SHIPBILL_STATUS, String.valueOf(dto.getStatus())));
			dto.setTransportStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.TRANSPORT_STATUS, String.valueOf(dto.getTransportStatus())));
			dto.setCarrierTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.LINE_CARRIER_TYPE, String.valueOf(dto.getCarrierType())));
			dto.setAbnormalStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.ABNORMAL_STATUS, String.valueOf(dto.getAbnormalStatus())));
			dto.setScanStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.SCAN_STATUS, String.valueOf(dto.getScanStatus())));
			dto.setOrderTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.ORDER_TYPE, String.valueOf(dto.getOrderType())));
			dto.setOrderBusinessTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.ORDER_BUSINESS_TYPE, String.valueOf(dto.getOrderType())));
			dto.setDeliveryMethodTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.DELIVERY_METHOD_TYPE, String.valueOf(dto.getDeliveryMethodType())));
			dto.setTransportTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.TRANSPORT_TYPE, String.valueOf(dto.getTransportType())));
			dto.setTemperatureRequirementName(ConvertorUtil.getName(dicData, DataDictionaryConstant.TEMPERATURE_REQUIREMENT, String.valueOf(dto.getTemperatureRequirement())));

			// 目的地
			StringBuffer consigneeProvinceCityDistrict = new StringBuffer();
			consigneeProvinceCityDistrict.append(dto.getConsigneeProvinceName());
			consigneeProvinceCityDistrict.append(dto.getConsigneeCityName());
			consigneeProvinceCityDistrict.append(dto.getConsigneeDistrictName());
			dto.setConsigneeProvinceCity(consigneeProvinceCityDistrict.toString());

			// 始发地
			StringBuffer shipperProvinceCityDistrict = new StringBuffer();
			shipperProvinceCityDistrict.append(dto.getShipperProvinceName());
			shipperProvinceCityDistrict.append(dto.getShipperCityName());
			shipperProvinceCityDistrict.append(dto.getShipperDistrictName());
			dto.setShipperProvinceCity(shipperProvinceCityDistrict.toString());

			// 收货方位置(经纬度判断)
			if (ToolKits.isNotEmpty(dto.getConsigneeLongitude()) && ToolKits.isNotEmpty(dto.getConsigneeLatitude())) {
				dto.setConsigneePositioning(StatusConstant.POSITIONING_YDW);
			} else {
				dto.setConsigneePositioning(StatusConstant.POSITIONING_WDW);
			}

			if (ObjectUtil.equal(DataDictionaryConstant.LINE_CARRIER_TYPE_SJ, dto.getCarrierType())) {// 承运方类型为司机时展示司机姓名
				dto.setCarrierName(dto.getDriverName());
				dto.setCarrierPhoneNumber(dto.getDriverPhoneNumber());
			}

			// 发货方位置(经纬度判断)
			if (ToolKits.isNotEmpty(dto.getShipperLongitude()) && ToolKits.isNotEmpty(dto.getShipperLatitude())) {
				dto.setShipperPositioning(StatusConstant.POSITIONING_YDW);
			} else {
				dto.setShipperPositioning(StatusConstant.POSITIONING_WDW);
			}
		}
		return PageUtils.getPage(list);
	}

	/**
	 * 运单模式高级查询
	 *
	 * @param vo
	 * @return
	 */
	@Override
	public Page<WaitForArrangeGoodsShipbillPageDTO> advancedQueryShipbillTypePage(ShipbillTypeAdvancedQueryVO vo) {
		UserEntity user = PlgFxUsrUtils.getUserEntity();
		ToolKits.isParamNull(user, "当前人员没有操作权限");
		// 权限控制
		if (!ObjectUtil.equal(user.getUserType(), BussinessConstant.USER_TYPE_ZY) && !ObjectUtil.equal(user.getUserType(), BussinessConstant.USER_TYPE_CYS)) {
			throw new PrologException("当前人员没有操作权限");
		}

		// 获取当前账号的顶级部门
		RestMessage<List<Organization>> restMessage = userTmsResource.search("0", null, null, String.valueOf(user.getEnterpriseId()));
		if (!restMessage.isSuccess()) {
			throw new PrologException("获取部门信息API错误!");
		}
		List<Organization> organizations = restMessage.getData();
		ToolKits.isParamNull(organizations, "顶级部门不存在,请先维护部门!");

		List<SysRefdatadModel> dicData = convertorUtil.getDictionary(new String[] { DataDictionaryConstant.SHIPBILL_STATUS, // 运单状态
				DataDictionaryConstant.TRANSPORT_STATUS, // 运输状态
				DataDictionaryConstant.LINE_CARRIER_TYPE, // 承运方类型
				DataDictionaryConstant.ABNORMAL_STATUS, // 异常状态
				DataDictionaryConstant.SCAN_STATUS, // 扫描状态
				DataDictionaryConstant.ORDER_TYPE, // 订单类型
				DataDictionaryConstant.ORDER_BUSINESS_TYPE, // 订单业务类型
				DataDictionaryConstant.DELIVERY_METHOD_TYPE, // 配送方式
				DataDictionaryConstant.TRANSPORT_TYPE, // 运输类型(运输模式)
				DataDictionaryConstant.TEMPERATURE_REQUIREMENT// 温度要求
		});

		// 权限控制
		if (user.getUserType().equals(BussinessConstant.USER_TYPE_ZY)) {
			// 判断是否是部门权限
			if (user.getOwnedAllDataAuthFlag().equals(BussinessConstant.USER_DEPARTMENT_AUTH_Y)) {
				vo.setIsDept(StatusConstant.IS_DEPT_YES);
				vo.setDepts(user.getDepts().toArray(new String[] {}));
			} else {
				vo.setIsDept(StatusConstant.IS_DEPT_NO);
				// 设置部门权限
				vo.setDepts(user.getDepts().toArray(new String[] {}));
				// 设置数据权限
				vo.setConsignors(user.getConsignors().toArray(new Long[] {}));
				vo.setWsarehouses(user.getWarehouses().toArray(new Long[] {}));
				vo.setCustomers(user.getCustomers().toArray(new Long[] {}));
				vo.setSuppliers(user.getSuppliers().toArray(new Long[] {}));
			}
		} else if (user.getUserType().equals(BussinessConstant.USER_TYPE_CYS)) {
			vo.setUnitId(Long.valueOf(user.getLoginUserCompanyInfo().getId()));
		} else {
			throw new PrologException("当前人员没有操作权限");
		}
		vo.setUserType(user.getUserType());
		vo.setEnterpriseId(user.getEnterpriseId());

		// 获取高级查询配置
		String conditions = null;
		RestMessage<String> restMessageAdvancedCfg = maindataTmsResource.getQueryConfiguration(DataDictionaryConstant.BIZ_TYPE_WAITFORARRANGEGOODS);
		if (!restMessageAdvancedCfg.isSuccess()) {
			throw new RuntimeException("获取高级查询配置失败!");
		} else {
			conditions = restMessageAdvancedCfg.getData();
		}
		vo.setSql(conditions);

		PageUtils.startPage(vo.getPageNum(), vo.getPageSize());
		List<WaitForArrangeGoodsShipbillPageDTO> list = tmsLoadingBillDetailMapper.advancedQueryShipbillTypePage(vo);

		for (WaitForArrangeGoodsShipbillPageDTO dto : list) {
			dto.setStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.SHIPBILL_STATUS, String.valueOf(dto.getStatus())));
			dto.setTransportStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.TRANSPORT_STATUS, String.valueOf(dto.getTransportStatus())));
			dto.setCarrierTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.LINE_CARRIER_TYPE, String.valueOf(dto.getCarrierType())));
			dto.setAbnormalStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.ABNORMAL_STATUS, String.valueOf(dto.getAbnormalStatus())));
			dto.setScanStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.SCAN_STATUS, String.valueOf(dto.getScanStatus())));
			dto.setOrderTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.ORDER_TYPE, String.valueOf(dto.getOrderType())));
			dto.setOrderBusinessTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.ORDER_BUSINESS_TYPE, String.valueOf(dto.getOrderType())));
			dto.setDeliveryMethodTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.DELIVERY_METHOD_TYPE, String.valueOf(dto.getDeliveryMethodType())));
			dto.setTransportTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.TRANSPORT_TYPE, String.valueOf(dto.getTransportType())));
			dto.setTemperatureRequirementName(ConvertorUtil.getName(dicData, DataDictionaryConstant.TEMPERATURE_REQUIREMENT, String.valueOf(dto.getTemperatureRequirement())));
		}
		return PageUtils.getPage(list);
	}

	/**
	 * 待理货——收货方模式分页查询
	 *
	 */
	@Override
	public Page<WaitForArrangeGoodsReceiverPageDTO> queryReceiverTypePage(ReceiverTypeQueryVO vo) throws Exception {
		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, "当前人员没有操作权限");
		}

		vo.setEnterpriseId(user.getEnterpriseId());
		vo.setUserType(user.getUserType());

		if (ObjectUtil.equal(user.getUserType(), BussinessConstant.USER_TYPE_ZY)) {// 自有账号
			vo.setDepts(ToolKits.isEmpty(user.getDepts()) ? null : user.getDepts().stream().toArray(String[]::new));
			if (BussinessConstant.USER_DEPARTMENT_AUTH_Y.equals(user.getOwnedAllDataAuthFlag())) {// 部门权限
				vo.setIsDept("YES");
			} else {// 业务员权限
				vo.setIsDept("NO");
				// 货主
				vo.setConsignors(ToolKits.isEmpty(user.getConsignors()) ? null : user.getConsignors().stream().toArray(Long[]::new));
				// 客户
				vo.setCustomers(ToolKits.isEmpty(user.getCustomers()) ? null : user.getCustomers().stream().toArray(Long[]::new));
				// 供应商
				vo.setSuppliers(ToolKits.isEmpty(user.getSuppliers()) ? null : user.getSuppliers().stream().toArray(Long[]::new));
				// 仓库
				vo.setWsarehouses(ToolKits.isEmpty(user.getWarehouses()) ? null : user.getWarehouses().stream().toArray(Long[]::new));
			}
		}
		if (ObjectUtil.equal(user.getUserType(), BussinessConstant.USER_TYPE_CYS)) {// 承运商账号
			vo.setCarrierId(Long.valueOf(user.getLoginUserCompanyInfo().getId()));
		}

		PageUtils.startPage(vo.getPageNum(), vo.getPageSize());
		List<WaitForArrangeGoodsReceiverPageDTO> list = tmsLoadingBillDetailMapper.queryReceiverTypeSql(vo);

		int i = 1;
		for (WaitForArrangeGoodsReceiverPageDTO dto : list) {
			dto.setId(i);

			dto.setConsigneeProvinceCityDistrict(dto.getConsigneePCD());
			dto.setEstimatedDeliveryTime(dto.getEstimatedDeliveryStartTime());

			i++;
		}
		return PageUtils.getPage(list);
	}

	/**
	 * 预约单模式分页查询
	 *
	 * @param vo
	 * @return
	 */
	@SuppressWarnings("resource")
	@Override
	public Page<WaitForArrangeGoodsAppointmentDTO> queryAppointmentTypePage(WaitForArrangeGoodsAppointmentVO vo) {
		UserEntity user = PlgFxUsrUtils.getUserEntity();
		ToolKits.isParamNull(user, "当前人员没有操作权限");
		// 权限控制 仅支持自有账号操作
		if (!user.getUserType().equals(BussinessConstant.USER_TYPE_ZY)) {
			throw new PrologException("当前人员没有操作权限");
		}

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

		Criteria criteria = Criteria.forClass(TmsAppointmentHeaderModel.class);
		Restriction r1 = ToolKits.isEmpty(vo.getAppointmentNo()) ? null : Restrictions.like("appointmentNo", "%" + vo.getAppointmentNo() + "%");
		Restriction r2 = ToolKits.isEmpty(vo.getBranchAddress()) ? null : Restrictions.like("branchAddress", "%" + vo.getBranchAddress() + "%");
		Restriction r3 = ToolKits.isEmpty(vo.getDriverName()) ? null : Restrictions.like("driverName", "%" + vo.getDriverName() + "%");
		Restriction r4 = ToolKits.isEmpty(vo.getDriverPhoneNumber()) ? null : Restrictions.like("driverPhoneNumber", "%" + vo.getDriverPhoneNumber() + "%");
		Restriction r5 = ToolKits.isEmpty(vo.getVehiclePlateNumber()) ? null : Restrictions.like("vehiclePlateNumber", "%" + vo.getVehiclePlateNumber() + "%");
		Restriction r6 = ToolKits.isEmpty(vo.getAppointmentType()) ? null : Restrictions.eq("appointmentType", vo.getAppointmentType());
		Restriction r7 = Restrictions.in("branchId", vo.getBranchId().split(","));
		Restriction r8 = Restrictions.in("status", new Integer[] { DataDictionaryConstant.APPOINTMENT_STATUS_YSH,
				DataDictionaryConstant.APPOINTMENT_STATUS_YQH,
				DataDictionaryConstant.APPOINTMENT_STATUS_DLH,
				DataDictionaryConstant.APPOINTMENT_STATUS_DDZ });
		Restriction r9 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
		Restriction r10 = Restrictions.lt(TmsAppointmentHeaderModel::getTallyStatus, DataDictionaryConstant.TALLY_STATUS_LHWC);
		Restriction r11 = ToolKits.isEmpty(vo.getReserveNumber()) ? null : Restrictions.like(TmsAppointmentHeaderModel::getReserveNumber, "%" + vo.getReserveNumber() + "%");

		PageUtils.startPage(vo.getPageNum(), vo.getPageSize());
		criteria.setRestriction(Restrictions.and(r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11));
		criteria.setOrder(Order.newInstance().asc(new String[] { "updatetime" }));

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

		List<TmsAppointmentHeaderModel> tmsAppointmentHeaderModels = tmsAppointmentHeaderMapper.findByCriteria(criteria);

		for (TmsAppointmentHeaderModel tmsAppointmentHeaderModel : tmsAppointmentHeaderModels) {
			WaitForArrangeGoodsAppointmentDTO dto = new WaitForArrangeGoodsAppointmentDTO();
			BeanUtils.copyProperties(tmsAppointmentHeaderModel, dto);

			// 数据翻译
			dto.setStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.APPOINTMENT_STATUS, String.valueOf(dto.getStatus())));
			dto.setAppointmentTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.APPOINTMENT_TYPE, String.valueOf(dto.getAppointmentType())));
			dto.setTallyStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.TALLY_STATUS, String.valueOf(dto.getTallyStatus())));

			criteria = Criteria.forClass(TmsAppointmentDetailModel.class);
			r1 = Restrictions.eq(TmsAppointmentDetailModel::getAppointmentId, tmsAppointmentHeaderModel.getAppointmentId());
			criteria.setRestriction(r1);
			List<TmsAppointmentDetailModel> tmsAppointmentDetailModels = tmsAppointmentDetailMapper.findByCriteria(criteria);

			// 获取预约单下的运单
			String shipbillIds = tmsAppointmentDetailModels.stream().map(TmsAppointmentDetailModel::getShipbillId).distinct().collect(Collectors.joining(","));
			dto.setShipbillIds(shipbillIds);

			//设置预约单的派车单
			dto.setLoadingBillIds(DataUtils.getLoadingBillIds(tmsAppointmentDetailModels));
			dto.setLoadingBillNo(dto.getLoadingBillIds());

			// 是否包含紧急订单
			if (ToolKits.isNotEmpty(tmsAppointmentHeaderModel.getUrgentQuantity()) && tmsAppointmentHeaderModel.getUrgentQuantity().intValue() > 0) {
				dto.setUrgentShipbill("是");
			} else {
				dto.setUrgentShipbill("否");
			}
			// 封装数据集
			waitForArrangeGoodsAppointmentDTOS.add(dto);
		}

		// 分页重组
		Page<WaitForArrangeGoodsAppointmentDTO> page = PageUtils.getPage(waitForArrangeGoodsAppointmentDTOS);
		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 shipbillId
	 * @return
	 */
	@Override
	public Page<WaitForArrangeGoodsItemDTO> queryItemDetail(int pageNum, int pageSize, String shipbillId) {
		UserEntity user = PlgFxUsrUtils.getUserEntity();
		ToolKits.isParamNull(user, "当前人员没有操作权限");
		ToolKits.isParamNull(shipbillId, "运单ID不为空");

		List<Map<String, Object>> data1 = Lists.newArrayList();
		List<Map<String, Object>> data2 = Lists.newArrayList();
		// 包装类型
		RestMessage<List<Map<String, Object>>> restMessage1 = maindataTmsResource.getDropDownById(DataDictionaryConstant.PACK_TYPE, null, null, null);
		if (!restMessage1.isSuccess()) {
			throw new RuntimeException("包装类型翻译失败!");
		} else {
			data1 = restMessage1.getData();
		}
		// 货物温层
		RestMessage<List<Map<String, Object>>> restMessage2 = maindataTmsResource.getDropDownById(DataDictionaryConstant.CARGO_THERMOSPHERE, null, null, null);
		if (!restMessage2.isSuccess()) {
			throw new RuntimeException("货物温层翻译失败!");
		} else {
			data2 = restMessage2.getData();
		}
		// 获取商品信息
		Criteria criteria = Criteria.forClass(TmsShipbillDetailModel.class);
		Restriction r1 = Restrictions.in("shipbillId", shipbillId.split(","));
		Restriction r2 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
		criteria.setRestriction(Restrictions.and(r1, r2));
		criteria.setOrder(Order.newInstance().desc(new String[] { "updatetime" }));
		List<TmsShipbillDetailModel> models = tmsShipbillDetailMapper.findByCriteria(criteria);
		List<WaitForArrangeGoodsItemDTO> dtos = new ArrayList<WaitForArrangeGoodsItemDTO>();
		if (ToolKits.isNotEmpty(models)) {
			for (TmsShipbillDetailModel model : models) {
				WaitForArrangeGoodsItemDTO dto = new WaitForArrangeGoodsItemDTO();
				BeanUtils.copyProperties(model, dto);
				dto.setPackTypeName(PublicMethods.change(data1, String.valueOf(dto.getPackType())));
				dto.setCargoThermosphereName(PublicMethods.change(data2, String.valueOf(dto.getCargoThermosphere())));
				dtos.add(dto);
			}
		}
		return PageUtils.getPage(dtos);
	}

	/**
	 * 配载包裹信息查询
	 *
	 * @param shipbillId
	 * @return
	 */
	@Override
	public Page<WaitForArrangeGoodsPackageDTO> queryPackageDetail(int pageNum, int pageSize, String shipbillId) {
		UserEntity user = PlgFxUsrUtils.getUserEntity();
		ToolKits.isParamNull(user, "当前人员没有操作权限");
		ToolKits.isParamNull(shipbillId, "运单ID不为空");

		List<Map<String, Object>> data1 = Lists.newArrayList();
		List<Map<String, Object>> data2 = Lists.newArrayList();
		// 包裹类型
		RestMessage<List<Map<String, Object>>> restMessage1 = maindataTmsResource.getDropDownById(DataDictionaryConstant.PACKAGE_TYPE, null, null, null);
		if (!restMessage1.isSuccess()) {
			throw new RuntimeException("包裹类型翻译失败!");
		} else {
			data1 = restMessage1.getData();
		}
		// 设备类型
		RestMessage<List<Map<String, Object>>> restMessage2 = maindataTmsResource.getDropDownById(DataDictionaryConstant.DEVICE_COMPANY, null, null, null);
		if (!restMessage2.isSuccess()) {
			throw new RuntimeException("设备类型翻译失败!");
		} else {
			data2 = restMessage2.getData();
		}
		Criteria criteria = Criteria.forClass(TmsShipbillPackageModel.class);
		Restriction r1 = Restrictions.in("shipbillId", shipbillId.split(","));
		Restriction r2 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
		criteria.setRestriction(Restrictions.and(r1, r2));
		criteria.setOrder(Order.newInstance().desc(new String[] { "updatetime" }));
		List<TmsShipbillPackageModel> models = tmsShipbillPackageMapper.findByCriteria(criteria);
		List<WaitForArrangeGoodsPackageDTO> dtos = Lists.newArrayList();
		if (ToolKits.isNotEmpty(models)) {
			for (TmsShipbillPackageModel model : models) {
				WaitForArrangeGoodsPackageDTO dto = new WaitForArrangeGoodsPackageDTO();
				BeanUtils.copyProperties(model, dto);
				dto.setPackageTypeName(PublicMethods.change(data1, String.valueOf(dto.getPackageType())));
				dto.setDeviceCompanyName(PublicMethods.change(data2, String.valueOf(dto.getDeviceCompany())));
				dtos.add(dto);
			}
		}
		return PageUtils.getPage(dtos);
	}

	/**
	 * 开始理货
	 *
	 * @param
	 * @return
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void startArrangeGoods(List<String> ids) throws Exception {
		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", date);
		// 开始理货时间
		mapTransportLogUpdate.put("arrangeGoodsStartTime", 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 loadingBillDetailModel = tmsLoadingBillDetails.get(0);
			if (loadingBillDetailModel.getStatus().intValue() > DataDictionaryConstant.SHIPBILL_STATUS_LH_START.intValue()) {
				throw new PrologException("运单【" + id + "】已开始理货");
			}
			TmsShipbillHeaderModel tmsShipbillHeader = tmsShipbillHeaderMapper.findById(loadingBillDetailModel.getShipbillId(), TmsShipbillHeaderModel.class);
			if (ToolKits.isNotEmpty(tmsShipbillHeader)) {
				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(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.setNodeDate(DateUtil.date());
				shipbillNodeTrackingSaveVO.setUserId(user.getUserid());
				shipbillNodeTrackingSaveVO.setUserName(user.getUsername());
				shipbillNodeTrackingSaveVO.setEnterpriseId(user.getEnterpriseId());
				shipbillNodeTrackingSaveVO.setEnterpriseName(user.getEnterpriseName());
				shipbillNodeTrackingSaveVO.setStatus(DataDictionaryConstant.SHIPBILL_STATUS_LH_FINISH);
				shipbillNodeTrackingSaveVO.setNodeEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_LH_START);
				shipbillNodeTrackingService.addShipbillNodeTrackingNewData(shipbillNodeTrackingSaveVO);

				// 维护运单日志保存
				ShipbillOperateLogSaveNewVO shipbillOperateLogSaveVO = new ShipbillOperateLogSaveNewVO();
				shipbillOperateLogSaveVO.setShipbillId(tmsShipbillHeader.getShipbillId());
				shipbillOperateLogSaveVO.setShipbillNo(tmsShipbillHeader.getShipbillNo());
				shipbillOperateLogSaveVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_LH_START);
				shipbillOperateLogSaveVO.setOldStatus(tmsShipbillHeader.getStatus());
				shipbillOperateLogSaveVO.setNewStatus(DataDictionaryConstant.SHIPBILL_STATUS_LH_FINISH);
				shipbillOperateLogSaveVO.setOperateDate(DateUtil.date());
				shipbillOperateLogSaveVO.setUserId(user.getUserid());
				shipbillOperateLogSaveVO.setUserName(user.getUsername());
				shipbillOperateLogSaveVO.setEnterpriseId(user.getEnterpriseId());
				shipbillOperateLogSaveVO.setEnterpriseName(user.getEnterpriseName());
				shipbillOperateLogService.addShipbillOperateLogNewData(shipbillOperateLogSaveVO);

				// 维护运输日志
				Criteria criteriaTransport = Criteria.forClass(TmsShipbillTransLogModel.class);
				Restriction r5 = Restrictions.eq(TmsShipbillTransLogModel::getShipbillId, id);
				criteriaTransport.setRestriction(r5);
				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);
				}
			} else {
				throw new PrologException("运单查询失败");
			}
		}
	}

	/**
	 * 开始理货递归父运单
	 *
	 * @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 (ToolKits.isNotEmpty(fatherShipbillHeaderModel)) {
				// 判断父级单号的状态是否为【开始理货】
				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());
					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
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void completeArrangeGoods(List<String> ids) throws Exception {
		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(tmsLoadingBillDetail.getShipbillId(), 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);

				// 调度单明细状态更新
				Assert.isTrue(tmsLoadingBillDetail.getStatus() != status, "运单【" + id + "】已开始理货");

				// 判断预约单是否存在
				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);
				}

				// 维护运单节点数据
				ShipbillNodeTrackingSaveNewVO shipbillNodeTrackingSaveVO = new ShipbillNodeTrackingSaveNewVO();
				shipbillNodeTrackingSaveVO.setShipbillId(tmsShipbillHeader.getShipbillId());
				shipbillNodeTrackingSaveVO.setShipbillNo(tmsShipbillHeader.getShipbillNo());
				shipbillNodeTrackingSaveVO.setNodeDate(DateUtil.date());
				shipbillNodeTrackingSaveVO.setUserId(user.getUserid());
				shipbillNodeTrackingSaveVO.setUserName(user.getUsername());
				shipbillNodeTrackingSaveVO.setEnterpriseId(user.getEnterpriseId());
				shipbillNodeTrackingSaveVO.setEnterpriseName(user.getEnterpriseName());
				shipbillNodeTrackingSaveVO.setStatus(status);
				shipbillNodeTrackingSaveVO.setNodeEvent(DataDictionaryConstant.SHIPBILL_STATUSNAME_LH_END);
				shipbillNodeTrackingService.addShipbillNodeTrackingNewData(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);
				Restriction r5 = Restrictions.eq(TmsShipbillTransLogModel::getShipbillId, id);
				criteriaTransport.setRestriction(r5);
				tmsShipbillTransportLogMapper.updateMapByCriteria(mapTransportLogUpdate, criteriaTransport);

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

				// 更新调度单状态
				if (null != tmsLoadingBillDetail) {
					Restriction r3 = Restrictions.eq("loadingBillId", tmsLoadingBillDetail.getLoadingBillId());
					Restriction r4 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
					criteriaLoadingBillDetail.setRestriction(Restrictions.and(r3, r4));
					List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteriaLoadingBillDetail);
					if (ToolKits.isNotEmpty(tmsLoadingBillDetailModels)) {
						List<TmsLoadingBillDetailModel> filterTmsLoadingBillDetailModels = tmsLoadingBillDetailModels.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", DataDictionaryConstant.LOADING_BILL_STATUS_LH_FINISH);
							tmsLoadingBillHeaderMapper.updateMapByCriteria(mapHeaderUpdate, criteriaLoadingHeader);
						}
					}
				}
			} else {
				throw new PrologException("运单查询失败");
			}
			MessageUtil.addMessage(new SendMessageDTO(MessageOrderTypeEnum.SHIP_NO.getCode(), MessageTypeEnum.TALLY.getCode(), Lists.newArrayList(id)));
		}
	}

	/**
	 * 递归更新父运单理货完成状态
	 *
	 * @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;
	}

	/**
	 * 查询配载运单
	 */
	@SuppressWarnings("resource")
	@Override
	public Page<WaitForArrangeGoodsShipbillDTO> queryShipbill(Integer pageNum, Integer pageSize, String shipbillId) throws Exception {
		UserEntity user = PlgFxUsrUtils.getUserEntity();
		ToolKits.isParamNull(user, "当前人员没有操作权限");

		List<SysRefdatadModel> dicData = convertorUtil.getDictionary(new String[] { DataDictionaryConstant.SHIPBILL_STATUS, // 运单状态
				DataDictionaryConstant.TRANSPORT_STATUS, // 运输状态
				DataDictionaryConstant.ABNORMAL_STATUS, // 异常状态
				DataDictionaryConstant.SCAN_STATUS, // 扫描状态
				DataDictionaryConstant.LINE_CARRIER_TYPE, // 承运方类型
				DataDictionaryConstant.DELIVERY_METHOD_TYPE, // 配送方式
				DataDictionaryConstant.TRANSPORT_TYPE, // 运输类型(运输模式)
				DataDictionaryConstant.TEMPERATURE_REQUIREMENT, // 温度要求
				DataDictionaryConstant.SHIPPER_TYPE, // 发货方类型
				DataDictionaryConstant.CONSIGNEE_TYPE, // 收货方类型
				DataDictionaryConstant.ORDER_TYPE, // 订单类型
				DataDictionaryConstant.ORDER_BUSINESS_TYPE// 订单业务类型
		});

		Criteria criteria = Criteria.forClass(TmsShipbillHeaderModel.class);
		Restriction r1 = Restrictions.in("shipbillId", shipbillId.split(","));
		Restriction r2 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
		criteria.setRestriction(Restrictions.and(r1, r2));
		criteria.setRestriction(r1);
		PageUtils.startPage(pageNum, pageSize);
		List<TmsShipbillHeaderModel> list = tmsShipbillHeaderMapper.findByCriteria(criteria);

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

		for (TmsShipbillHeaderModel model : list) {
			WaitForArrangeGoodsShipbillDTO dto = new WaitForArrangeGoodsShipbillDTO();
			BeanUtils.copyProperties(model, dto);
			// 收货方位置(经纬度判断)
			if (ToolKits.isNotEmpty(model.getConsigneeLongitude()) && ToolKits.isNotEmpty(model.getConsigneeLatitude())) {
				dto.setConsigneePositioning(StatusConstant.POSITIONING_YDW);
			} else {
				dto.setConsigneePositioning(StatusConstant.POSITIONING_WDW);
			}
			// 发货方位置(经纬度判断)
			if (ToolKits.isNotEmpty(model.getShipperLongitude()) && ToolKits.isNotEmpty(model.getShipperLatitude())) {
				dto.setShipperPositioning(StatusConstant.POSITIONING_YDW);
			} else {
				dto.setShipperPositioning(StatusConstant.POSITIONING_WDW);
			}

			StringBuffer consigneeProvinceCityDistrict = new StringBuffer();
			// 目的地
			consigneeProvinceCityDistrict.append(dto.getConsigneeProvinceName());
			consigneeProvinceCityDistrict.append(dto.getConsigneeCityName());
			consigneeProvinceCityDistrict.append(dto.getConsigneeDistrictName());
			dto.setConsigneeProvinceCityDistrict(consigneeProvinceCityDistrict.toString());

			// 始发地
			StringBuffer shipperProvinceCityDistrict = new StringBuffer();
			shipperProvinceCityDistrict.append(dto.getShipperProvinceName());
			shipperProvinceCityDistrict.append(dto.getShipperCityName());
			shipperProvinceCityDistrict.append(dto.getShipperDistrictName());
			dto.setShipperProvinceCityDistrict(shipperProvinceCityDistrict.toString());

			// 字典翻译
			dto.setOrderTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.ORDER_TYPE, String.valueOf(dto.getOrderType())));
			dto.setOrderBusinessTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.ORDER_BUSINESS_TYPE, String.valueOf(dto.getOrderBusinessType())));
			dto.setDeliveryMethodTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.DELIVERY_METHOD_TYPE, String.valueOf(dto.getDeliveryMethodType())));
			dto.setTransportTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.TRANSPORT_TYPE, String.valueOf(dto.getTransportType())));
			dto.setTemperatureRequirementName(ConvertorUtil.getName(dicData, DataDictionaryConstant.TEMPERATURE_REQUIREMENT, String.valueOf(dto.getTemperatureRequirement())));
			dto.setShipperTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.SHIPPER_TYPE, String.valueOf(dto.getShipperType())));
			dto.setConsigneeTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.CONSIGNEE_TYPE, String.valueOf(dto.getConsigneeType())));
			dtos.add(dto);
		}

		Page<WaitForArrangeGoodsShipbillDTO> page = PageUtils.getPage(dtos);
		if (list instanceof com.github.pagehelper.Page) {
			com.github.pagehelper.Page<TmsShipbillHeaderModel> p0 = (com.github.pagehelper.Page<TmsShipbillHeaderModel>) 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;
	}

	/**
	 * 待理货导出
	 */
	@Override
	public List<WaitForArrangeGoodsExportDTO> export(ShipbillTypeQueryVO vo) throws Exception {
		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, "当前人员没有操作权限");
		}

		List<SysRefdatadModel> dicData = convertorUtil.getDictionary(new String[] { DataDictionaryConstant.SHIPBILL_STATUS, // 运单状态
				DataDictionaryConstant.TRANSPORT_STATUS, // 运输状态
				DataDictionaryConstant.LINE_CARRIER_TYPE, // 承运方类型
				DataDictionaryConstant.ABNORMAL_STATUS, // 异常状态
				DataDictionaryConstant.SCAN_STATUS, // 扫描状态
				DataDictionaryConstant.ORDER_TYPE, // 订单类型
				DataDictionaryConstant.ORDER_BUSINESS_TYPE, // 订单业务类型
				DataDictionaryConstant.DELIVERY_METHOD_TYPE, // 配送方式
				DataDictionaryConstant.TRANSPORT_TYPE, // 运输类型(运输模式)
				DataDictionaryConstant.TEMPERATURE_REQUIREMENT, // 温度要求
				DataDictionaryConstant.SHIPPER_TYPE, // 发货方类型
				DataDictionaryConstant.CONSIGNEE_TYPE, // 收货方类型
		});

		vo.setUserType(user.getUserType());
		vo.setEnterpriseId(user.getEnterpriseId());

		if (ObjectUtil.equal(user.getUserType(), BussinessConstant.USER_TYPE_ZY)) {// 自有账号
			vo.setDepts(ToolKits.isEmpty(user.getDepts()) ? null : user.getDepts().stream().toArray(String[]::new));
			if (BussinessConstant.USER_DEPARTMENT_AUTH_Y.equals(user.getOwnedAllDataAuthFlag())) {// 部门权限
				vo.setIsDept("YES");
			} else {// 业务员权限
				vo.setIsDept("NO");
				// 货主
				vo.setConsignors(ToolKits.isEmpty(user.getConsignors()) ? null : user.getConsignors().stream().toArray(Long[]::new));
				// 客户
				vo.setCustomers(ToolKits.isEmpty(user.getCustomers()) ? null : user.getCustomers().stream().toArray(Long[]::new));
				// 供应商
				vo.setSuppliers(ToolKits.isEmpty(user.getSuppliers()) ? null : user.getSuppliers().stream().toArray(Long[]::new));
				// 仓库
				vo.setWsarehouses(ToolKits.isEmpty(user.getWarehouses()) ? null : user.getWarehouses().stream().toArray(Long[]::new));
			}
		}
		if (ObjectUtil.equal(user.getUserType(), BussinessConstant.USER_TYPE_CYS)) {// 承运商账号
			vo.setCarrierId(Long.valueOf(user.getLoginUserCompanyInfo().getId()));
		}

		List<WaitForArrangeGoodsShipbillPageDTO> dtos = tmsLoadingBillDetailMapper.queryShipbillTypePage(vo);
		List<WaitForArrangeGoodsExportDTO> exportDTOs = Lists.newArrayList();
		for (WaitForArrangeGoodsShipbillPageDTO dto : dtos) {
			StringBuffer consigneeProvinceCityDistrict = new StringBuffer();
			// 目的地
			consigneeProvinceCityDistrict.append(dto.getConsigneeProvinceName());
			consigneeProvinceCityDistrict.append(dto.getConsigneeCityName());
			consigneeProvinceCityDistrict.append(dto.getConsigneeDistrictName());
			dto.setConsigneeProvinceCity(consigneeProvinceCityDistrict.toString());

			// 始发地
			StringBuffer shipperProvinceCityDistrict = new StringBuffer();
			shipperProvinceCityDistrict.append(dto.getShipperProvinceName());
			shipperProvinceCityDistrict.append(dto.getShipperCityName());
			shipperProvinceCityDistrict.append(dto.getShipperDistrictName());
			dto.setShipperProvinceCity(shipperProvinceCityDistrict.toString());

			// 收货方位置(经纬度判断)
			if (ToolKits.isNotEmpty(dto.getConsigneeLongitude()) && ToolKits.isNotEmpty(dto.getConsigneeLatitude())) {
				dto.setConsigneePositioning(StatusConstant.POSITIONING_YDW);
			} else {
				dto.setConsigneePositioning(StatusConstant.POSITIONING_WDW);
			}

			// 发货方位置(经纬度判断)
			if (ToolKits.isNotEmpty(dto.getShipperLongitude()) && ToolKits.isNotEmpty(dto.getShipperLatitude())) {
				dto.setShipperPositioning(StatusConstant.POSITIONING_YDW);
			} else {
				dto.setShipperPositioning(StatusConstant.POSITIONING_WDW);
			}

			if (ObjectUtil.equal(DataDictionaryConstant.LINE_CARRIER_TYPE_SJ, dto.getCarrierType())) {// 承运方类型为司机时展示司机姓名
				dto.setCarrierName(dto.getDriverName());
				dto.setCarrierPhoneNumber(dto.getDriverPhoneNumber());
			}

			// 字典翻译
			dto.setStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.SHIPBILL_STATUS, String.valueOf(dto.getStatus())));
			dto.setTransportStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.TRANSPORT_STATUS, String.valueOf(dto.getTransportStatus())));
			dto.setAbnormalStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.ABNORMAL_STATUS, String.valueOf(dto.getAbnormalStatus())));
			dto.setScanStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.SCAN_STATUS, String.valueOf(dto.getScanStatus())));
			dto.setCarrierTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.LINE_CARRIER_TYPE, String.valueOf(dto.getCarrierType())));
			dto.setOrderTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.ORDER_TYPE, String.valueOf(dto.getOrderType())));
			dto.setOrderBusinessTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.ORDER_BUSINESS_TYPE, String.valueOf(dto.getOrderBusinessType())));
			dto.setDeliveryMethodTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.DELIVERY_METHOD_TYPE, String.valueOf(dto.getDeliveryMethodType())));
			dto.setTransportTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.TRANSPORT_TYPE, String.valueOf(dto.getTransportType())));
			dto.setTemperatureRequirementName(ConvertorUtil.getName(dicData, DataDictionaryConstant.TEMPERATURE_REQUIREMENT, String.valueOf(dto.getTemperatureRequirement())));
			dto.setShipperTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.SHIPPER_TYPE, String.valueOf(dto.getShipperType())));
			dto.setConsigneeTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.CONSIGNEE_TYPE, String.valueOf(dto.getConsigneeType())));

			WaitForArrangeGoodsExportDTO exportDTO = new WaitForArrangeGoodsExportDTO();
			BeanUtils.copyProperties(dto, exportDTO);
			exportDTOs.add(exportDTO);
		}
		return exportDTOs;
	}

	/**
	 * 待理货分页导出
	 */
	@SuppressWarnings("resource")
	@Override
	public List<WaitForArrangeGoodsExportDTO> exportPage(ShipbillTypeQueryVO vo) throws Exception {
		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, "当前人员没有操作权限");
		}

		List<SysRefdatadModel> dicData = convertorUtil.getDictionary(new String[] { DataDictionaryConstant.SHIPBILL_STATUS, // 运单状态
				DataDictionaryConstant.TRANSPORT_STATUS, // 运输状态
				DataDictionaryConstant.LINE_CARRIER_TYPE, // 承运方类型
				DataDictionaryConstant.ABNORMAL_STATUS, // 异常状态
				DataDictionaryConstant.SCAN_STATUS, // 扫描状态
				DataDictionaryConstant.ORDER_TYPE, // 订单类型
				DataDictionaryConstant.ORDER_BUSINESS_TYPE, // 订单业务类型
				DataDictionaryConstant.DELIVERY_METHOD_TYPE, // 配送方式
				DataDictionaryConstant.TRANSPORT_TYPE, // 运输类型(运输模式)
				DataDictionaryConstant.TEMPERATURE_REQUIREMENT, // 温度要求
				DataDictionaryConstant.SHIPPER_TYPE, // 发货方类型
				DataDictionaryConstant.CONSIGNEE_TYPE, // 收货方类型
		});

		vo.setUserType(user.getUserType());
		vo.setEnterpriseId(user.getEnterpriseId());

		if (ObjectUtil.equal(user.getUserType(), BussinessConstant.USER_TYPE_ZY)) {// 自有账号
			vo.setDepts(ToolKits.isEmpty(user.getDepts()) ? null : user.getDepts().stream().toArray(String[]::new));
			if (BussinessConstant.USER_DEPARTMENT_AUTH_Y.equals(user.getOwnedAllDataAuthFlag())) {// 部门权限
				vo.setIsDept("YES");
			} else {// 业务员权限
				vo.setIsDept("NO");
				// 货主
				vo.setConsignors(ToolKits.isEmpty(user.getConsignors()) ? null : user.getConsignors().stream().toArray(Long[]::new));
				// 客户
				vo.setCustomers(ToolKits.isEmpty(user.getCustomers()) ? null : user.getCustomers().stream().toArray(Long[]::new));
				// 供应商
				vo.setSuppliers(ToolKits.isEmpty(user.getSuppliers()) ? null : user.getSuppliers().stream().toArray(Long[]::new));
				// 仓库
				vo.setWsarehouses(ToolKits.isEmpty(user.getWarehouses()) ? null : user.getWarehouses().stream().toArray(Long[]::new));
			}
		}
		if (ObjectUtil.equal(user.getUserType(), BussinessConstant.USER_TYPE_CYS)) {// 承运商账号
			vo.setCarrierId(Long.valueOf(user.getLoginUserCompanyInfo().getId()));
		}

		PageUtils.startPage(vo.getPageNum(), vo.getPageSize());
		List<WaitForArrangeGoodsShipbillPageDTO> dtos = tmsLoadingBillDetailMapper.queryShipbillTypePage(vo);
		List<WaitForArrangeGoodsExportDTO> exportDTOs = Lists.newArrayList();
		for (WaitForArrangeGoodsShipbillPageDTO dto : dtos) {
			StringBuffer consigneeProvinceCityDistrict = new StringBuffer();
			// 目的地
			consigneeProvinceCityDistrict.append(dto.getConsigneeProvinceName());
			consigneeProvinceCityDistrict.append(dto.getConsigneeCityName());
			consigneeProvinceCityDistrict.append(dto.getConsigneeDistrictName());
			dto.setConsigneeProvinceCity(consigneeProvinceCityDistrict.toString());

			// 始发地
			StringBuffer shipperProvinceCityDistrict = new StringBuffer();
			shipperProvinceCityDistrict.append(dto.getShipperProvinceName());
			shipperProvinceCityDistrict.append(dto.getShipperCityName());
			shipperProvinceCityDistrict.append(dto.getShipperDistrictName());
			dto.setShipperProvinceCity(shipperProvinceCityDistrict.toString());

			// 收货方位置(经纬度判断)
			if (ToolKits.isNotEmpty(dto.getConsigneeLongitude()) && ToolKits.isNotEmpty(dto.getConsigneeLatitude())) {
				dto.setConsigneePositioning(StatusConstant.POSITIONING_YDW);
			} else {
				dto.setConsigneePositioning(StatusConstant.POSITIONING_WDW);
			}

			// 发货方位置(经纬度判断)
			if (ToolKits.isNotEmpty(dto.getShipperLongitude()) && ToolKits.isNotEmpty(dto.getShipperLatitude())) {
				dto.setShipperPositioning(StatusConstant.POSITIONING_YDW);
			} else {
				dto.setShipperPositioning(StatusConstant.POSITIONING_WDW);
			}

			if (ObjectUtil.equal(DataDictionaryConstant.LINE_CARRIER_TYPE_SJ, dto.getCarrierType())) {// 承运方类型为司机时展示司机姓名
				dto.setCarrierName(dto.getDriverName());
			}

			if (ObjectUtil.equal(DataDictionaryConstant.LINE_CARRIER_TYPE_SJ, dto.getCarrierType())) {// 承运方类型为司机时展示司机姓名
				dto.setCarrierName(dto.getDriverName());
				dto.setCarrierPhoneNumber(dto.getDriverPhoneNumber());
			}

			// 字典翻译
			dto.setStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.SHIPBILL_STATUS, String.valueOf(dto.getStatus())));
			dto.setTransportStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.TRANSPORT_STATUS, String.valueOf(dto.getTransportStatus())));
			dto.setAbnormalStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.ABNORMAL_STATUS, String.valueOf(dto.getAbnormalStatus())));
			dto.setScanStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.SCAN_STATUS, String.valueOf(dto.getScanStatus())));
			dto.setCarrierTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.LINE_CARRIER_TYPE, String.valueOf(dto.getCarrierType())));
			dto.setOrderTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.ORDER_TYPE, String.valueOf(dto.getOrderType())));
			dto.setOrderBusinessTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.ORDER_BUSINESS_TYPE, String.valueOf(dto.getOrderBusinessType())));
			dto.setDeliveryMethodTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.DELIVERY_METHOD_TYPE, String.valueOf(dto.getDeliveryMethodType())));
			dto.setTransportTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.TRANSPORT_TYPE, String.valueOf(dto.getTransportType())));
			dto.setTemperatureRequirementName(ConvertorUtil.getName(dicData, DataDictionaryConstant.TEMPERATURE_REQUIREMENT, String.valueOf(dto.getTemperatureRequirement())));
			dto.setShipperTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.SHIPPER_TYPE, String.valueOf(dto.getShipperType())));
			dto.setConsigneeTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.CONSIGNEE_TYPE, String.valueOf(dto.getConsigneeType())));

			WaitForArrangeGoodsExportDTO exportDTO = new WaitForArrangeGoodsExportDTO();
			BeanUtils.copyProperties(dto, exportDTO);
			exportDTOs.add(exportDTO);
		}

		Page<WaitForArrangeGoodsExportDTO> page = PageUtils.getPage(exportDTOs);
		if (dtos instanceof com.github.pagehelper.Page) {
			com.github.pagehelper.Page<WaitForArrangeGoodsShipbillPageDTO> p0 = (com.github.pagehelper.Page<WaitForArrangeGoodsShipbillPageDTO>) dtos;
			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.getList();
	}

	/**
	 * 待理货选择行导出
	 */
	@Override
	public List<WaitForArrangeGoodsExportDTO> exportSelected(List<String> ids) throws Exception {
		UserEntity user = PlgFxUsrUtils.getUserEntity();
		ToolKits.isParamNull(user, "当前人员没有操作权限");

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

		List<SysRefdatadModel> dicData = convertorUtil.getDictionary(new String[] { DataDictionaryConstant.SHIPBILL_STATUS, // 运单状态
				DataDictionaryConstant.TRANSPORT_STATUS, // 运输状态
				DataDictionaryConstant.LINE_CARRIER_TYPE, // 承运方类型
				DataDictionaryConstant.ABNORMAL_STATUS, // 异常状态
				DataDictionaryConstant.SCAN_STATUS, // 扫描状态
				DataDictionaryConstant.ORDER_TYPE, // 订单类型
				DataDictionaryConstant.ORDER_BUSINESS_TYPE, // 订单业务类型
				DataDictionaryConstant.DELIVERY_METHOD_TYPE, // 配送方式
				DataDictionaryConstant.TRANSPORT_TYPE, // 运输类型(运输模式)
				DataDictionaryConstant.TEMPERATURE_REQUIREMENT, // 温度要求
				DataDictionaryConstant.SHIPPER_TYPE, // 发货方类型
				DataDictionaryConstant.CONSIGNEE_TYPE, // 收货方类型
		});

		vo.setUserType(user.getUserType());
		vo.setEnterpriseId(user.getEnterpriseId());

		if (ObjectUtil.equal(user.getUserType(), BussinessConstant.USER_TYPE_ZY)) {// 自有账号
			vo.setDepts(ToolKits.isEmpty(user.getDepts()) ? null : user.getDepts().stream().toArray(String[]::new));
			if (BussinessConstant.USER_DEPARTMENT_AUTH_Y.equals(user.getOwnedAllDataAuthFlag())) {// 部门权限
				vo.setIsDept("YES");
			} else {// 业务员权限
				vo.setIsDept("NO");
				// 货主
				vo.setConsignors(ToolKits.isEmpty(user.getConsignors()) ? null : user.getConsignors().stream().toArray(Long[]::new));
				// 客户
				vo.setCustomers(ToolKits.isEmpty(user.getCustomers()) ? null : user.getCustomers().stream().toArray(Long[]::new));
				// 供应商
				vo.setSuppliers(ToolKits.isEmpty(user.getSuppliers()) ? null : user.getSuppliers().stream().toArray(Long[]::new));
				// 仓库
				vo.setWsarehouses(ToolKits.isEmpty(user.getWarehouses()) ? null : user.getWarehouses().stream().toArray(Long[]::new));
			}
		}
		if (ObjectUtil.equal(user.getUserType(), BussinessConstant.USER_TYPE_CYS)) {// 承运商账号
			vo.setCarrierId(Long.valueOf(user.getLoginUserCompanyInfo().getId()));
		}

		vo.setIds(ids.stream().toArray(String[]::new));
		List<WaitForArrangeGoodsShipbillPageDTO> dtos = tmsLoadingBillDetailMapper.queryShipbillTypePage(vo);
		List<WaitForArrangeGoodsExportDTO> exportDTOs = Lists.newArrayList();
		for (WaitForArrangeGoodsShipbillPageDTO dto : dtos) {
			StringBuffer consigneeProvinceCityDistrict = new StringBuffer();
			// 目的地
			consigneeProvinceCityDistrict.append(dto.getConsigneeProvinceName());
			consigneeProvinceCityDistrict.append(dto.getConsigneeCityName());
			consigneeProvinceCityDistrict.append(dto.getConsigneeDistrictName());
			dto.setConsigneeProvinceCity(consigneeProvinceCityDistrict.toString());

			// 始发地
			StringBuffer shipperProvinceCityDistrict = new StringBuffer();
			shipperProvinceCityDistrict.append(dto.getShipperProvinceName());
			shipperProvinceCityDistrict.append(dto.getShipperCityName());
			shipperProvinceCityDistrict.append(dto.getShipperDistrictName());
			dto.setShipperProvinceCity(shipperProvinceCityDistrict.toString());

			// 收货方位置(经纬度判断)
			if (ToolKits.isNotEmpty(dto.getConsigneeLongitude()) && ToolKits.isNotEmpty(dto.getConsigneeLatitude())) {
				dto.setConsigneePositioning(StatusConstant.POSITIONING_YDW);
			} else {
				dto.setConsigneePositioning(StatusConstant.POSITIONING_WDW);
			}

			// 发货方位置(经纬度判断)
			if (ToolKits.isNotEmpty(dto.getShipperLongitude()) && ToolKits.isNotEmpty(dto.getShipperLatitude())) {
				dto.setShipperPositioning(StatusConstant.POSITIONING_YDW);
			} else {
				dto.setShipperPositioning(StatusConstant.POSITIONING_WDW);
			}

			if (ObjectUtil.equal(DataDictionaryConstant.LINE_CARRIER_TYPE_SJ, dto.getCarrierType())) {// 承运方类型为司机时展示司机姓名
				dto.setCarrierName(dto.getDriverName());
			}

			if (ObjectUtil.equal(DataDictionaryConstant.LINE_CARRIER_TYPE_SJ, dto.getCarrierType())) {// 承运方类型为司机时展示司机姓名
				dto.setCarrierName(dto.getDriverName());
				dto.setCarrierPhoneNumber(dto.getDriverPhoneNumber());
			}

			// 字典翻译
			dto.setStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.SHIPBILL_STATUS, String.valueOf(dto.getStatus())));
			dto.setTransportStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.TRANSPORT_STATUS, String.valueOf(dto.getTransportStatus())));
			dto.setAbnormalStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.ABNORMAL_STATUS, String.valueOf(dto.getAbnormalStatus())));
			dto.setScanStatusName(ConvertorUtil.getName(dicData, DataDictionaryConstant.SCAN_STATUS, String.valueOf(dto.getScanStatus())));
			dto.setCarrierTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.LINE_CARRIER_TYPE, String.valueOf(dto.getCarrierType())));
			dto.setOrderTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.ORDER_TYPE, String.valueOf(dto.getOrderType())));
			dto.setOrderBusinessTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.ORDER_BUSINESS_TYPE, String.valueOf(dto.getOrderBusinessType())));
			dto.setDeliveryMethodTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.DELIVERY_METHOD_TYPE, String.valueOf(dto.getDeliveryMethodType())));
			dto.setTransportTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.TRANSPORT_TYPE, String.valueOf(dto.getTransportType())));
			dto.setTemperatureRequirementName(ConvertorUtil.getName(dicData, DataDictionaryConstant.TEMPERATURE_REQUIREMENT, String.valueOf(dto.getTemperatureRequirement())));
			dto.setShipperTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.SHIPPER_TYPE, String.valueOf(dto.getShipperType())));
			dto.setConsigneeTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.CONSIGNEE_TYPE, String.valueOf(dto.getConsigneeType())));

			WaitForArrangeGoodsExportDTO exportDTO = new WaitForArrangeGoodsExportDTO();
			BeanUtils.copyProperties(dto, exportDTO);
			exportDTOs.add(exportDTO);
		}
		return exportDTOs;
	}

}
