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

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import com.prolog.rdc.tms.app.service.business.PendingReceiptService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
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.constant.SeriaNnumberConstant;
import com.prolog.rdc.tms.app.dao.mapper.TmsAppointmentDetailMapper;
import com.prolog.rdc.tms.app.dao.mapper.TmsAppointmentHeaderMapper;
import com.prolog.rdc.tms.app.dao.mapper.TmsLoadingBillDetailMapper;
import com.prolog.rdc.tms.app.dao.mapper.TmsLoadingBillHeaderMapper;
import com.prolog.rdc.tms.app.dao.mapper.TmsShipbillDetailMapper;
import com.prolog.rdc.tms.app.dao.mapper.TmsShipbillHeaderMapper;
import com.prolog.rdc.tms.app.dao.mapper.TmsShipbillNodeTrackingMapper;
import com.prolog.rdc.tms.app.dao.mapper.TmsShipbillPackageMapper;
import com.prolog.rdc.tms.app.model.dto.ShipbillManageDTO;
import com.prolog.rdc.tms.app.model.dto.ShipbillNodeTrackingDTO;
import com.prolog.rdc.tms.app.model.dto.business.ShipbillManageItemDTO;
import com.prolog.rdc.tms.app.model.dto.business.ShipbillManagePackDTO;
import com.prolog.rdc.tms.app.model.entity.ShipbillNodeTracking;
import com.prolog.rdc.tms.app.model.entity.TmsAppointmentDetailModel;
import com.prolog.rdc.tms.app.model.entity.TmsAppointmentHeaderModel;
import com.prolog.rdc.tms.app.model.entity.TmsLoadingBillDetailModel;
import com.prolog.rdc.tms.app.model.entity.TmsLoadingBillHeaderModel;
import com.prolog.rdc.tms.app.model.entity.TmsShipbillDetailModel;
import com.prolog.rdc.tms.app.model.entity.TmsShipbillHeaderModel;
import com.prolog.rdc.tms.app.model.entity.TmsShipbillPackageModel;
import com.prolog.rdc.tms.app.model.vo.ShipbillAdjustVO;
import com.prolog.rdc.tms.app.model.vo.ShipbillDetailModifyVO;
import com.prolog.rdc.tms.app.model.vo.ShipbillManageQueryVO;
import com.prolog.rdc.tms.app.model.vo.business.ShipbillOperateLogSaveVO;
import com.prolog.rdc.tms.app.service.business.ShipbillManageService;
import com.prolog.rdc.tms.app.service.business.ShipbillOperateLogService;
import com.prolog.rdc.tms.app.util.ConvertorUtil;
import com.prolog.rdc.tms.model.dto.basicData.ItemCheckDTO;
import com.prolog.rdc.tms.model.entity.SysRefdatadModel;
import com.prolog.rdc.tms.model.vo.basicData.ItemCheckVO;
import com.prolog.rdc.tms.rmi.feign.MaindataFeign;

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

/**
 * 运单管理实现层
 *
 * @author xiaoyf
 * @since 2022-04-13 14:32:31
 */
@Service
public class ShipbillManageServiceImpl implements ShipbillManageService {

	@Autowired
	private ConvertorUtil convertorUtil;

	@Autowired
	private TmsShipbillHeaderMapper tmsShipbillHeaderMapper;

	@Autowired
	private TmsShipbillPackageMapper tmsShipbillPackageMapper;

	@Autowired
	private TmsShipbillDetailMapper tmsShipbillDetailMapper;

	@Autowired
	private TmsShipbillNodeTrackingMapper tmsShipbillNodeTrackingMapper;

	@Autowired
	private MaindataFeign maindataTmsResource;

	@Autowired
	private ShipbillOperateLogService shipbillOperateLogService;

	@Autowired
	private TmsLoadingBillDetailMapper tmsLoadingBillDetailMapper;

	@Autowired
	private TmsLoadingBillHeaderMapper tmsLoadingBillHeaderMapper;

	@Autowired
	private TmsAppointmentDetailMapper tmsAppointmentDetailMapper;

	@Autowired
	private TmsAppointmentHeaderMapper tmsAppointmentHeaderMapper;

	@Autowired
	private PendingReceiptService pendingReceiptService;

	/**
	 * 分页查询
	 *
	 * @param
	 * @return
	 */
	@Override
	public Page<ShipbillManageDTO> queryPage(ShipbillManageQueryVO 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) && ObjectUtil.notEqual(user.getUserType(), BussinessConstant.USER_TYPE_HZ) && ObjectUtil.notEqual(user.getUserType(), BussinessConstant.USER_TYPE_KH) && ObjectUtil.notEqual(user.getUserType(), BussinessConstant.USER_TYPE_GYS)) {
			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));
			}
		} else if (ObjectUtil.equal(user.getUserType(), BussinessConstant.USER_TYPE_CYS)) {// 承运商账号
			vo.setCarrierId(Long.valueOf(user.getLoginUserCompanyInfo().getId()));
		} else if (ObjectUtil.equal(user.getUserType(), BussinessConstant.USER_TYPE_HZ)) {// 货主账号
			vo.setCargoOwnerUserId(Long.valueOf(user.getLoginUserCompanyInfo().getId()));
		} else if (ObjectUtil.equal(user.getUserType(), BussinessConstant.USER_TYPE_GYS)) {// 供应商账号
			vo.setSupplierUserId(Long.valueOf(user.getLoginUserCompanyInfo().getId()));
		} else if (ObjectUtil.equal(user.getUserType(), BussinessConstant.USER_TYPE_KH)) {// 客户账号
			vo.setCustomerUserId(Long.valueOf(user.getLoginUserCompanyInfo().getId()));
		}

		PageUtils.startPage(vo.getPageNum(), vo.getPageSize());
		List<ShipbillManageDTO> list = tmsShipbillHeaderMapper.shipbillManageQuery(vo);

		for (ShipbillManageDTO dto : list) {
			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())));

			// 获取商品信息
			Criteria criteriaDetail = Criteria.forClass(TmsShipbillDetailModel.class);
			Restriction r27 = Restrictions.eq(TmsShipbillPackageModel::getShipbillId, dto.getShipbillId());
			Restriction r28 = Restrictions.eq(TmsShipbillPackageModel::getEnterpriseId, user.getEnterpriseId());
			criteriaDetail.setRestriction(Restrictions.and(r27, r28));
			criteriaDetail.setOrder(Order.newInstance().desc(new String[] { "updatetime" }));
			List<TmsShipbillDetailModel> tmsShipbillDetailModels = tmsShipbillDetailMapper.findByCriteria(criteriaDetail);

			List<ShipbillManageItemDTO> detailDTOList = Lists.newArrayList();
			for (TmsShipbillDetailModel detailModel : tmsShipbillDetailModels) {
				ShipbillManageItemDTO detailDTO = new ShipbillManageItemDTO();
				BeanUtils.copyProperties(detailModel, detailDTO);
				detailDTOList.add(detailDTO);
			}
			// 商品信息
			dto.setItemDTOList(detailDTOList);
		}
		return PageUtils.getPage(list);
	}

	// STD-DEVELOP20220823 lhb 计算件重体 20220913 start
	/**
	 * 运单管理调整分页查询
	 *
	 * @param
	 * @return
	 */
	public Page<ShipbillManageDTO> adjustQuery(ShipbillManageQueryVO 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) && ObjectUtil.notEqual(user.getUserType(), BussinessConstant.USER_TYPE_HZ) && ObjectUtil.notEqual(user.getUserType(), BussinessConstant.USER_TYPE_KH) && ObjectUtil.notEqual(user.getUserType(), BussinessConstant.USER_TYPE_GYS)) {
			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));
			}
		} else if (ObjectUtil.equal(user.getUserType(), BussinessConstant.USER_TYPE_CYS)) {// 承运商账号
			vo.setCarrierId(Long.valueOf(user.getLoginUserCompanyInfo().getId()));
		} else if (ObjectUtil.equal(user.getUserType(), BussinessConstant.USER_TYPE_HZ)) {// 货主账号
			vo.setCargoOwnerUserId(Long.valueOf(user.getLoginUserCompanyInfo().getId()));
		} else if (ObjectUtil.equal(user.getUserType(), BussinessConstant.USER_TYPE_GYS)) {// 供应商账号
			vo.setSupplierUserId(Long.valueOf(user.getLoginUserCompanyInfo().getId()));
		} else if (ObjectUtil.equal(user.getUserType(), BussinessConstant.USER_TYPE_KH)) {// 客户账号
			vo.setCustomerUserId(Long.valueOf(user.getLoginUserCompanyInfo().getId()));
		}

		PageUtils.startPage(vo.getPageNum(), vo.getPageSize());
		List<ShipbillManageDTO> list = tmsShipbillHeaderMapper.shipbillManageAdjustQuery(vo);

		for (ShipbillManageDTO dto : list) {
			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())));

			// 获取商品信息
			Criteria criteriaDetail = Criteria.forClass(TmsShipbillDetailModel.class);
			Restriction r27 = Restrictions.eq(TmsShipbillPackageModel::getShipbillId, dto.getShipbillId());
			Restriction r28 = Restrictions.eq(TmsShipbillPackageModel::getEnterpriseId, user.getEnterpriseId());
			criteriaDetail.setRestriction(Restrictions.and(r27, r28));
			criteriaDetail.setOrder(Order.newInstance().desc(new String[] { "updatetime" }));
			List<TmsShipbillDetailModel> tmsShipbillDetailModels = tmsShipbillDetailMapper.findByCriteria(criteriaDetail);

			List<ShipbillManageItemDTO> detailDTOList = Lists.newArrayList();
			for (TmsShipbillDetailModel detailModel : tmsShipbillDetailModels) {
				ShipbillManageItemDTO detailDTO = new ShipbillManageItemDTO();
				BeanUtils.copyProperties(detailModel, detailDTO);
				detailDTOList.add(detailDTO);
			}
			// 商品信息
			dto.setItemDTOList(detailDTOList);
			dto.setPackageDetailDTOList(pendingReceiptService.getPackageDetailDTO(dto.getShipbillId()));
		}
		return PageUtils.getPage(list);
	}

// STD-DEVELOP20220823 lhb 计算件重体 20220913 end
	/**
	 * 运单详情查询
	 *
	 * @param
	 * @return
	 */
	@Override
	public ShipbillManageDTO queryDetail(ShipbillManageQueryVO vo) throws Exception {
		UserEntity user = PlgFxUsrUtils.getUserEntity();
		ToolKits.isParamNull(user, "当前人员没有操作权限");

		if (ToolKits.isEmpty(vo.getShipbillId())) {
			throw new PrologException("运单ID不能为空");
		}

		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// 温度要求
		});

		TmsShipbillHeaderModel model = tmsShipbillHeaderMapper.findById(vo.getShipbillId(), TmsShipbillHeaderModel.class);
		if (ToolKits.isNotEmpty(model)) {
			ShipbillManageDTO dto = new ShipbillManageDTO();
			BeanUtils.copyProperties(model, dto);
			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 dto;
		} else {
			return null;
		}
	}

	/**
	 * 运单商品查询
	 *
	 * @param
	 * @return
	 */
	@SuppressWarnings("resource")
	@Override
	public Page<ShipbillManageItemDTO> queryItem(ShipbillManageQueryVO vo) throws Exception {
		UserEntity user = PlgFxUsrUtils.getUserEntity();
		ToolKits.isParamNull(user, "当前人员没有操作权限");

		List<SysRefdatadModel> dicData = convertorUtil.getDictionary(new String[] { DataDictionaryConstant.PACK_TYPE, // 包装类型
				DataDictionaryConstant.CARGO_THERMOSPHERE// 货物温存
		});

		Criteria criteria = Criteria.forClass(TmsShipbillDetailModel.class);
		Restriction r1 = Restrictions.eq("shipbillId", vo.getShipbillId());
		Restriction r2 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
		criteria.setRestriction(Restrictions.and(r1, r2));
		criteria.setOrder(Order.newInstance().desc(new String[] { "updatetime" }));
		PageUtils.startPage(vo.getPageNum(), vo.getPageSize());
		List<TmsShipbillDetailModel> list = tmsShipbillDetailMapper.findByCriteria(criteria);

		List<ShipbillManageItemDTO> dtos = Lists.newArrayList();
		for (TmsShipbillDetailModel model : list) {
			ShipbillManageItemDTO dto = new ShipbillManageItemDTO();
			BeanUtils.copyProperties(model, dto);
			dto.setPackTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.PACK_TYPE, String.valueOf(dto.getPackType())));
			dto.setCargoThermosphereName(ConvertorUtil.getName(dicData, DataDictionaryConstant.CARGO_THERMOSPHERE, String.valueOf(dto.getCargoThermosphere())));
			dtos.add(dto);
		}

		Page<ShipbillManageItemDTO> page = PageUtils.getPage(dtos);
		if (list instanceof com.github.pagehelper.Page) {
			com.github.pagehelper.Page<TmsShipbillDetailModel> p0 = (com.github.pagehelper.Page<TmsShipbillDetailModel>) list;
			page.setPageCount(p0.getPages());
			page.setPageNum(p0.getPageNum());
			page.setPageSize(p0.getPageSize());
			page.setTotalCount(p0.getTotal());
			page.setStartRow(p0.getStartRow());
			page.setEndRow(p0.getEndRow());
		}
		return page;
	}

	/**
	 * 运单包裹查询
	 *
	 * @param
	 * @return
	 */
	@SuppressWarnings("resource")
	@Override
	public Page<ShipbillManagePackDTO> queryPack(ShipbillManageQueryVO vo) throws Exception {
		UserEntity user = PlgFxUsrUtils.getUserEntity();
		ToolKits.isParamNull(user, "当前人员没有操作权限");

		List<SysRefdatadModel> dicData = convertorUtil.getDictionary(new String[] { DataDictionaryConstant.PACKAGE_TYPE, // 包裹类型
				DataDictionaryConstant.DEVICE_COMPANY// 设备生产厂商
		});

		Criteria criteria = Criteria.forClass(TmsShipbillPackageModel.class);
		Restriction r1 = Restrictions.eq("shipbillId", vo.getShipbillId());
		Restriction r2 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
		criteria.setRestriction(Restrictions.and(r1, r2));
		criteria.setOrder(Order.newInstance().desc(new String[] { "updatetime" }));
		PageUtils.startPage(vo.getPageNum(), vo.getPageSize());
		List<TmsShipbillPackageModel> list = tmsShipbillPackageMapper.findByCriteria(criteria);
		List<ShipbillManagePackDTO> dtos = Lists.newArrayList();

		for (TmsShipbillPackageModel model : list) {
			ShipbillManagePackDTO dto = new ShipbillManagePackDTO();
			BeanUtils.copyProperties(model, dto);
			dto.setPackageTypeName(ConvertorUtil.getName(dicData, DataDictionaryConstant.PACKAGE_TYPE, String.valueOf(dto.getPackageType())));
			dto.setDeviceCompanyName(ConvertorUtil.getName(dicData, DataDictionaryConstant.DEVICE_COMPANY, String.valueOf(dto.getDeviceCompany())));
			dtos.add(dto);
		}

		Page<ShipbillManagePackDTO> page = PageUtils.getPage(dtos);
		if (list instanceof com.github.pagehelper.Page) {
			com.github.pagehelper.Page<TmsShipbillPackageModel> p0 = (com.github.pagehelper.Page<TmsShipbillPackageModel>) list;
			page.setPageCount(p0.getPages());
			page.setPageNum(p0.getPageNum());
			page.setPageSize(p0.getPageSize());
			page.setTotalCount(p0.getTotal());
			page.setStartRow(p0.getStartRow());
			page.setEndRow(p0.getEndRow());
		}
		return page;
	}

	/**
	 * 运单节点查询
	 *
	 * @param
	 * @return
	 */
	@Override
	public List<ShipbillNodeTrackingDTO> queryShipbillNode(ShipbillManageQueryVO vo) throws Exception {
		UserEntity user = PlgFxUsrUtils.getUserEntity();
		ToolKits.isParamNull(user, "当前人员没有操作权限");

		Criteria criteria = Criteria.forClass(ShipbillNodeTracking.class);
		Restriction r1 = Restrictions.eq("shipbillId", vo.getShipbillId());
		Restriction r2 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
		criteria.setRestriction(Restrictions.and(r1, r2));
		criteria.setOrder(Order.newInstance().asc(new String[] { "updatetime" }));
		List<ShipbillNodeTracking> list = tmsShipbillNodeTrackingMapper.findByCriteria(criteria);

		List<ShipbillNodeTrackingDTO> dtos = Lists.newArrayList();
		for (ShipbillNodeTracking model : list) {
			ShipbillNodeTrackingDTO dto = new ShipbillNodeTrackingDTO();
			BeanUtils.copyProperties(model, dto);
			dtos.add(dto);
		}
		return dtos;
	}

	/**
	 * 运单修改保存
	 */
	@Transactional(rollbackFor = Exception.class)
	@Override
	public void shipbillUpdate(List<ShipbillAdjustVO> adjustVOs) {
		ToolKits.isParamNull(adjustVOs, "运单修改保存请求不为空！");

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

		for (ShipbillAdjustVO adjustVO : adjustVOs) {
			ToolKits.isParamNull(adjustVO.getShipbillId(), "订单ID不为空");
			ToolKits.isParamNull(adjustVO.getDetails(), "商品信息不为空");

			TmsShipbillHeaderModel model = tmsShipbillHeaderMapper.findById(adjustVO.getShipbillId(), TmsShipbillHeaderModel.class);

			if (ToolKits.isEmpty(model)) {
				throw new PrologException("运单【" + adjustVO.getShipbillId() + "】不存在！");
			}
			if (ToolKits.isNotEmpty(model.getTransportStatus()) && !model.getTransportStatus().equals(DataDictionaryConstant.TRANSPORT_STATUS_PENDING_SHIP)) {
				throw new PrologException("运单【" + model.getShipbillNo() + "】已发货，不支持修改！");
			}
			if (model.getSplitOrderStatus().equals(DataDictionaryConstant.SPLIT_ORDER_STATUS_ED) || model.getCarrierSplitOrderStatus().equals(DataDictionaryConstant.CARRIER_SPLIT_ORDER_STATUS_ED)) {
				throw new PrologException("不支持拆单主单修改！");
			}
			if (model.getSplitOrderType().equals(DataDictionaryConstant.CARRIER_SPLIT_ORDER_TYPE_TRANSIT_SUB) || model.getCarrierSplitOrderType().equals(DataDictionaryConstant.CARRIER_SPLIT_ORDER_TYPE_TRANSIT_SUB)) {
				throw new PrologException("不支持拆段子单修改！");
			}

			if (ToolKits.isNotEmpty(adjustVO.getDetails())) {
				updateShipbillDetail(adjustVO.getShipbillId(), adjustVO.getDetails(), user, date, "");
			}
		}
	}

	private void updateShipbillDetail(String shipbillId, List<ShipbillDetailModifyVO> details, UserEntity user, Date date, String isClose) {

		TmsShipbillHeaderModel model = tmsShipbillHeaderMapper.findById(shipbillId, TmsShipbillHeaderModel.class);
		List<TmsShipbillHeaderModel> notTransportShipbills = Lists.newArrayList();
		if (ToolKits.isNotEmpty(model.getFatherShipbillId())) {
			Criteria criteriaHeader = Criteria.forClass(TmsShipbillHeaderModel.class);
			Restriction r1 = Restrictions.eq(TmsShipbillHeaderModel::getFatherShipbillId, model.getFatherShipbillId());
			Restriction r2 = Restrictions.eq(TmsShipbillHeaderModel::getEnterpriseId, user.getEnterpriseId());
			Restriction r3 = Restrictions.ne(TmsShipbillHeaderModel::getShipbillId, model.getShipbillId());

			criteriaHeader.setRestriction(Restrictions.and(r1, r2, r3));
			List<TmsShipbillHeaderModel> headerModelList = tmsShipbillHeaderMapper.findByCriteria(criteriaHeader);
			if (ToolKits.isNotEmpty(headerModelList)) {
				if (model.getStatus().equals(DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH_CHECK) && ToolKits.isNotEmpty(model.getCarrierShipbillStatus())) {
					// 承运商未调度
					notTransportShipbills = headerModelList.stream().filter(o -> o.getCarrierShipbillStatus().intValue() < DataDictionaryConstant.CARRIER_SHIPBILL_STATUS_DISPATCHED).collect(Collectors.toList());
				} else {
					// 自主账号未调度
					notTransportShipbills = headerModelList.stream().filter(o -> o.getStatus().intValue() < DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH.intValue()).collect(Collectors.toList());
				}
				if (ToolKits.isEmpty(notTransportShipbills)) {
					throw new PrologException("同级子运单都已调度，不支持修改！");
				}
				if (model.getStatus().equals(DataDictionaryConstant.SHIPBILL_STATUS_DISPATCH_CHECK) && ToolKits.isNotEmpty(model.getCarrierShipbillStatus())) {
					// 承运商未调度
					notTransportShipbills = notTransportShipbills.stream().filter(o -> o.getCarrierSplitOrderStatus().equals(DataDictionaryConstant.CARRIER_SPLIT_ORDER_STATUS_UN)).collect(Collectors.toList());
				} else {
					// 自主账号未调度
					notTransportShipbills = notTransportShipbills.stream().filter(o -> o.getSplitOrderStatus().equals(DataDictionaryConstant.SPLIT_ORDER_STATUS_UN)).collect(Collectors.toList());
				}
				if (ToolKits.isEmpty(notTransportShipbills)) {
					throw new PrologException("同级子运单都已拆分或者中转了，不支持修改！");
				}
			} else {
				throw new PrologException("运单【" + shipbillId + "】没有同级子运单，不支持修改！");
			}
		}

		// 设置明细行号
		Integer seqno = 1;
		// 商品总件数
		BigDecimal goodsTotalPcs = new BigDecimal(0);
		// 商品总体积
		BigDecimal goodsTotalVolume = new BigDecimal(0);
		// 商品总重量
		BigDecimal goodsTotalWeight = new BigDecimal(0);

		for (ShipbillDetailModifyVO shipbillDetailModifyVO : details) {
			ToolKits.isParamNull(shipbillDetailModifyVO.getItemId(), "商品ID不为空");
			ToolKits.isParamNull(shipbillDetailModifyVO.getPcs(), "商品件数不为空");

			TmsShipbillDetailModel origShipbillDetal = tmsShipbillDetailMapper.findById(shipbillDetailModifyVO.getId(), TmsShipbillDetailModel.class);
			if (ToolKits.isEmpty(origShipbillDetal)) {
				throw new PrologException("运单【" + shipbillId + "】的商品明细" + shipbillDetailModifyVO.getItemId() + "不存在");
			}
			BigDecimal origPcs = origShipbillDetal.getPcs();
			BigDecimal adjustPcs = origPcs.subtract(shipbillDetailModifyVO.getPcs());
			BigDecimal cmpPcs = shipbillDetailModifyVO.getPcs().subtract(origPcs);
			if (cmpPcs.intValue() == 0) {
				continue;
			}
			// 调整的件重体，反应到同级子单对应的相同商品上
			if (ToolKits.isNotEmpty(notTransportShipbills)) {
				String[] shipbills = notTransportShipbills.stream().map(s -> s.getShipbillId()).collect(Collectors.joining(",")).split(",");
				Criteria criteriaShipbillDetail = Criteria.forClass(TmsShipbillDetailModel.class);
				Restriction r1 = Restrictions.in(TmsShipbillDetailModel::getShipbillId, shipbills);
				Restriction r2 = Restrictions.eq(TmsShipbillDetailModel::getEnterpriseId, user.getEnterpriseId());
				Restriction r3 = Restrictions.eq(TmsShipbillDetailModel::getItemId, shipbillDetailModifyVO.getItemId());
				criteriaShipbillDetail.setRestriction(Restrictions.and(r1, r2, r3));
				List<TmsShipbillDetailModel> shipbillDetailModels = tmsShipbillDetailMapper.findByCriteria(criteriaShipbillDetail);

				if (ToolKits.isEmpty(shipbillDetailModels)) {
					throw new PrologException("同级子运单没有相同的商品，不支持修改！");
				}
				BigDecimal tjSumPcs = shipbillDetailModels.stream().map(TmsShipbillDetailModel::getPcs).reduce(BigDecimal.ZERO, BigDecimal::add);
				if (NumberUtil.isGreater(cmpPcs, tjSumPcs)) {
					throw new PrologException("运单【】" + origShipbillDetal.getShipbillId() + "的明细商品【" + origShipbillDetal.getItemName() + "】调整后的总件数超过原来的总件数");
				}
				// 需要调整到同级子单的件数
				TmsShipbillDetailModel adjustTmsShipbillDetail = shipbillDetailModels.get(0);

				ItemCheckVO itemCheckVO = new ItemCheckVO();
				itemCheckVO.setItemId(adjustTmsShipbillDetail.getItemId());
				RestMessage<ItemCheckDTO> restMessage3 = maindataTmsResource.getItem(itemCheckVO);
				if (!restMessage3.isSuccess()) {
					throw new RuntimeException("取商品资料信息失败:" + restMessage3.getMessage());
				}
				ItemCheckDTO rsItemInfo = restMessage3.getData();

				BigDecimal adjustVolume = adjustPcs.multiply(rsItemInfo.getVolume());
				BigDecimal adjustWeight = adjustPcs.multiply(rsItemInfo.getWeight());

				adjustTmsShipbillDetail.setPcs(adjustTmsShipbillDetail.getPcs().add(adjustPcs));
				adjustTmsShipbillDetail.setVolume(adjustTmsShipbillDetail.getVolume().add(adjustVolume));
				adjustTmsShipbillDetail.setWeight(adjustTmsShipbillDetail.getWeight().add(adjustWeight));
				tmsShipbillDetailMapper.update(adjustTmsShipbillDetail);

				// 调整的运单商品对应的运单，调度单，预约单件重体重新计算
				TmsShipbillHeaderModel shipbillHeaderModel = tmsShipbillHeaderMapper.findById(adjustTmsShipbillDetail.getShipbillId(), TmsShipbillHeaderModel.class);
				// 总件数
				shipbillHeaderModel.setTotalPcs(shipbillHeaderModel.getTotalPcs().add(adjustPcs));
				// 总体积
				shipbillHeaderModel.setTotalVolume(shipbillHeaderModel.getTotalVolume().add(adjustVolume));
				// 总重量
				shipbillHeaderModel.setTotalWeight(shipbillHeaderModel.getTotalWeight().add(adjustWeight));
				// 实际总件数
				shipbillHeaderModel.setActualTotalPcs(shipbillHeaderModel.getActualTotalPcs().add(adjustPcs));
				// 实际总体积
				shipbillHeaderModel.setActualTotalVolume(shipbillHeaderModel.getActualTotalVolume().add(adjustVolume));
				// 实际总重量
				shipbillHeaderModel.setActualTotalWeight(shipbillHeaderModel.getActualTotalWeight().add(adjustWeight));
				tmsShipbillHeaderMapper.update(shipbillHeaderModel);

				// 运单操作日志保存
				ShipbillOperateLogSaveVO shipbillOperateLogSaveVO = new ShipbillOperateLogSaveVO();
				shipbillOperateLogSaveVO.setShipbillId(shipbillHeaderModel.getShipbillId());
				shipbillOperateLogSaveVO.setShipbillNo(shipbillHeaderModel.getShipbillNo());
				shipbillOperateLogSaveVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_OPERATENAME_TZ);
				shipbillOperateLogSaveVO.setOldStatus(model.getStatus());
				shipbillOperateLogSaveVO.setNewStatus(model.getStatus());
				shipbillOperateLogService.addShipbillOperateLogData(shipbillOperateLogSaveVO);
			}

			// 获取运单明细ID
			RestMessage<String> restMessage2 = maindataTmsResource.getCodeNumberByCode(SeriaNnumberConstant.TMS_SHIPBILL_DETAIL_ID, "L");
			if (!restMessage2.isSuccess()) {
				throw new RuntimeException("生成运单明细ID失败");
			}
			String tmsShipbillDetailId = restMessage2.getData();

			// 删除原有商品
			tmsShipbillDetailMapper.deleteById(shipbillDetailModifyVO.getId(), TmsShipbillDetailModel.class);

			TmsShipbillDetailModel tmsShipbillDetailModel = new TmsShipbillDetailModel();
			BeanUtils.copyProperties(shipbillDetailModifyVO, tmsShipbillDetailModel);

			// 明细赋值
			tmsShipbillDetailModel.setId(tmsShipbillDetailId);
			tmsShipbillDetailModel.setSeqno(seqno);
			tmsShipbillDetailModel.setShipbillId(model.getShipbillId());
			tmsShipbillDetailModel.setShipbillNo(model.getShipbillNo());
			tmsShipbillDetailModel.setCargoOwnerId(model.getCargoOwnerId());
			tmsShipbillDetailModel.setCargoOwnerCode(model.getCargoOwnerCode());
			tmsShipbillDetailModel.setCargoOwnerName(model.getCargoOwnerName());
			tmsShipbillDetailModel.setEnterpriseId(user.getEnterpriseId());
			tmsShipbillDetailModel.setEnterpriseName(user.getEnterpriseName());
			tmsShipbillDetailModel.setCreateperson(model.getCreateperson());
			tmsShipbillDetailModel.setCreatetime(model.getCreatetime());
			tmsShipbillDetailModel.setUpdateperson(user.getNickname());
			tmsShipbillDetailModel.setUpdatetime(date);
			if (ToolKits.isNotEmpty(isClose) && isClose.equals("close")) {
				tmsShipbillDetailModel.setClosingPcs(tmsShipbillDetailModel.getPcs());
			}

			tmsShipbillDetailModel.setOrigPcs(tmsShipbillDetailModel.getPcs());
			tmsShipbillDetailModel.setClosingPcs(BigDecimal.valueOf(0));
			tmsShipbillDetailModel.setDeliveryPcs(BigDecimal.valueOf(0));
			tmsShipbillDetailModel.setScanStatus(DataDictionaryConstant.SCAN_STATUS_INIT);
			tmsShipbillDetailMapper.save(tmsShipbillDetailModel);

			// 行号自增长
			seqno++;

			// STD-DEVELOP20220823 lhb 计算件重体 20220909 start
			goodsTotalPcs = goodsTotalPcs.add(tmsShipbillDetailModel.getPcs());
			goodsTotalVolume = goodsTotalVolume.add(ToolKits.isEmpty(tmsShipbillDetailModel.getVolume()) ? BigDecimal.ZERO : tmsShipbillDetailModel.getVolume());
			goodsTotalWeight = goodsTotalWeight.add(ToolKits.isEmpty(tmsShipbillDetailModel.getWeight()) ? BigDecimal.ZERO : tmsShipbillDetailModel.getWeight());
			// STD-DEVELOP20220823 lhb 计算件重体 20220909 end
		}
		// 修正运单的件重体
		// 总件数
		model.setTotalPcs(goodsTotalPcs);
		// 总体积
		model.setTotalVolume(goodsTotalVolume);
		// 总重量
		model.setTotalWeight(goodsTotalWeight);
		// 实际总件数
		model.setActualTotalPcs(goodsTotalPcs);
		// 实际总体积
		model.setActualTotalVolume(goodsTotalVolume);
		// 实际总重量
		model.setActualTotalWeight(goodsTotalWeight);
		tmsShipbillHeaderMapper.update(model);

		// 运单操作日志保存
		ShipbillOperateLogSaveVO shipbillOperateLogSaveVO = new ShipbillOperateLogSaveVO();
		shipbillOperateLogSaveVO.setShipbillId(model.getShipbillId());
		shipbillOperateLogSaveVO.setShipbillNo(model.getShipbillNo());
		shipbillOperateLogSaveVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_OPERATENAME_TZ);
		shipbillOperateLogSaveVO.setOldStatus(model.getStatus());
		shipbillOperateLogSaveVO.setNewStatus(model.getStatus());
		shipbillOperateLogService.addShipbillOperateLogData(shipbillOperateLogSaveVO);

		// 修改调度单的件重体
		Criteria criteriaLoadingBillDetail = Criteria.forClass(TmsLoadingBillDetailModel.class);
		Restriction r3 = Restrictions.eq(TmsLoadingBillDetailModel::getShipbillId, model.getShipbillId());
		Restriction r4 = Restrictions.eq(TmsLoadingBillDetailModel::getEnterpriseId, user.getEnterpriseId());
		criteriaLoadingBillDetail.setRestriction(Restrictions.and(r3, r4));
		List<TmsLoadingBillDetailModel> loadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteriaLoadingBillDetail);
		if (ToolKits.isNotEmpty(loadingBillDetailModels)) {
			Set<String> loadingIdSet = Sets.newHashSet();
			for (TmsLoadingBillDetailModel detailModel : loadingBillDetailModels) {
				// 修正运单的件重体
				// 总件数
				detailModel.setTotalPcs(goodsTotalPcs);
				// 总体积
				detailModel.setTotalVolume(goodsTotalVolume);
				// 总重量
				detailModel.setTotalWeight(goodsTotalWeight);
				// 实际总件数
				detailModel.setActualTotalPcs(goodsTotalPcs);
				// 实际总体积
				detailModel.setActualTotalVolume(goodsTotalVolume);
				// 实际总重量
				detailModel.setActualTotalWeight(goodsTotalWeight);
				tmsLoadingBillDetailMapper.update(detailModel);

				loadingIdSet.add(detailModel.getLoadingBillId());
			}
			for (String loadingId : loadingIdSet) {
				r3 = Restrictions.eq(TmsLoadingBillDetailModel::getLoadingBillId, loadingId);
				criteriaLoadingBillDetail.setRestriction(Restrictions.and(r3, r4));
				List<TmsLoadingBillDetailModel> loadingBillDetailModelList = tmsLoadingBillDetailMapper.findByCriteria(criteriaLoadingBillDetail);
				if (ToolKits.isNotEmpty(loadingBillDetailModelList)) {
					BigDecimal hTotalPcs = loadingBillDetailModelList.stream().map(TmsLoadingBillDetailModel::getTotalPcs).reduce(BigDecimal.ZERO, BigDecimal::add);
					BigDecimal hTotalWeigth = loadingBillDetailModelList.stream().map(TmsLoadingBillDetailModel::getTotalWeight).reduce(BigDecimal.ZERO, BigDecimal::add);
					BigDecimal hTotalVolume = loadingBillDetailModelList.stream().map(TmsLoadingBillDetailModel::getTotalVolume).reduce(BigDecimal.ZERO, BigDecimal::add);

					TmsLoadingBillHeaderModel loadingBillHeaderModel = tmsLoadingBillHeaderMapper.findById(loadingId, TmsLoadingBillHeaderModel.class);
					if (ToolKits.isNotEmpty(loadingBillHeaderModel)) {
						loadingBillHeaderModel.setTotalPcs(hTotalPcs);
						loadingBillHeaderModel.setTotalVolume(hTotalVolume);
						loadingBillHeaderModel.setTotalWeight(hTotalWeigth);
						loadingBillHeaderModel.setActualTotalPcs(loadingBillHeaderModel.getTotalPcs());
						loadingBillHeaderModel.setActualTotalVolume(loadingBillHeaderModel.getTotalVolume());
						loadingBillHeaderModel.setActualTotalWeight(loadingBillHeaderModel.getTotalWeight());
						tmsLoadingBillHeaderMapper.update(loadingBillHeaderModel);
					}
				}
			}
		}

		// 修改预约单的件重体
		Criteria criteriaAppointmentDetail = Criteria.forClass(TmsAppointmentDetailModel.class);
		Restriction r5 = Restrictions.eq(TmsAppointmentDetailModel::getShipbillId, model.getShipbillId());
		Restriction r6 = Restrictions.eq(TmsAppointmentDetailModel::getEnterpriseId, user.getEnterpriseId());
		criteriaAppointmentDetail.setRestriction(Restrictions.and(r5, r6));
		List<TmsAppointmentDetailModel> appointmentDetailModels = tmsAppointmentDetailMapper.findByCriteria(criteriaAppointmentDetail);
		if (ToolKits.isNotEmpty(appointmentDetailModels)) {
			Set<String> appointmentIdSet = Sets.newHashSet();
			for (TmsAppointmentDetailModel appointmentDetailModel : appointmentDetailModels) {
				// 修正运单的件重体
				// 总件数
				appointmentDetailModel.setTotalPcs(goodsTotalPcs);
				// 总体积
				appointmentDetailModel.setTotalVolume(goodsTotalVolume);
				// 总重量
				appointmentDetailModel.setTotalWeight(goodsTotalWeight);
				// 实际总件数
				appointmentDetailModel.setActualTotalPcs(goodsTotalPcs);
				// 实际总体积
				appointmentDetailModel.setActualTotalVolume(goodsTotalVolume);
				// 实际总重量
				appointmentDetailModel.setActualTotalWeight(goodsTotalWeight);
				tmsAppointmentDetailMapper.update(appointmentDetailModel);
				appointmentIdSet.add(appointmentDetailModel.getAppointmentId());
			}
			for (String appointmentId : appointmentIdSet) {
				r5 = Restrictions.eq(TmsAppointmentDetailModel::getAppointmentId, appointmentId);
				criteriaAppointmentDetail.setRestriction(Restrictions.and(r5, r6));
				List<TmsAppointmentDetailModel> appointmentDetailModelList = tmsAppointmentDetailMapper.findByCriteria(criteriaAppointmentDetail);
				if (ToolKits.isNotEmpty(appointmentDetailModelList)) {
					BigDecimal hTotalPcs = appointmentDetailModelList.stream().map(TmsAppointmentDetailModel::getTotalPcs).reduce(BigDecimal.ZERO, BigDecimal::add);
					BigDecimal hTotalWeigth = appointmentDetailModelList.stream().map(TmsAppointmentDetailModel::getTotalWeight).reduce(BigDecimal.ZERO, BigDecimal::add);
					BigDecimal hTotalVolume = appointmentDetailModelList.stream().map(TmsAppointmentDetailModel::getTotalVolume).reduce(BigDecimal.ZERO, BigDecimal::add);

					TmsAppointmentHeaderModel appointmentHeaderModel = tmsAppointmentHeaderMapper.findById(appointmentId, TmsAppointmentHeaderModel.class);
					if (ToolKits.isNotEmpty(appointmentHeaderModel)) {
						appointmentHeaderModel.setTotalPcs(hTotalPcs);
						appointmentHeaderModel.setTotalVolume(hTotalVolume);
						appointmentHeaderModel.setTotalWeight(hTotalWeigth);
						tmsAppointmentHeaderMapper.update(appointmentHeaderModel);
					}
				}
			}
		}
	}
}
