package com.sckw.transport.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.sckw.contract.api.RemoteContractService;
import com.sckw.contract.api.model.dto.res.ContractCommonInfoResDto;
import com.sckw.contract.api.model.vo.KwcContractLogisticsDto;
import com.sckw.contract.api.model.vo.TradeContractUnitDto;
import com.sckw.core.common.enums.enums.DictEnum;
import com.sckw.core.common.enums.enums.DictTypeEnum;
import com.sckw.core.exception.BusinessException;
import com.sckw.core.model.constant.Global;
import com.sckw.core.model.constant.NumberConstant;
import com.sckw.core.model.enums.*;
import com.sckw.core.model.page.PageHelperUtil;
import com.sckw.core.model.page.PageRes;
import com.sckw.core.model.page.PageResult;
import com.sckw.core.utils.*;
import com.sckw.core.web.constant.HttpStatus;
import com.sckw.core.web.context.LoginUserHolder;
import com.sckw.core.web.response.BaseResult;
import com.sckw.core.web.response.HttpResult;
import com.sckw.core.web.response.result.PageDataResult;
import com.sckw.excel.utils.DateUtil;
import com.sckw.excel.utils.ValidUtil;
import com.sckw.fleet.api.RemoteFleetService;
import com.sckw.fleet.api.model.vo.RTruckVo;
import com.sckw.mongo.enums.BusinessTypeEnum;
import com.sckw.mongo.model.SckwLogisticsOrder;
import com.sckw.order.api.dubbo.RemoteTradeOrderAmountService;
import com.sckw.order.api.dubbo.TradeOrderInfoService;
import com.sckw.order.api.model.*;
import com.sckw.payment.api.feign.PaymentFeignService;
import com.sckw.payment.api.model.feign.WalletPayableDto;
import com.sckw.product.api.dubbo.GoodsInfoService;
import com.sckw.product.api.model.GoodsDetails;
import com.sckw.product.api.model.KwpGoods;
import com.sckw.redis.config.RedisLockUtil;
import com.sckw.redis.constant.RedisConstant;
import com.sckw.stream.enums.MessageEnum;
import com.sckw.stream.model.SckwBusSum;
import com.sckw.system.api.RemoteSystemService;
import com.sckw.system.api.RemoteUserService;
import com.sckw.system.api.feign.DataPermissionFeignService;
import com.sckw.system.api.model.dto.req.DataPermissionFilterReqDto;
import com.sckw.system.api.model.dto.res.DataPermissionDTO;
import com.sckw.system.api.model.dto.res.EntCacheResDto;
import com.sckw.system.api.model.dto.res.UserResDto;
import com.sckw.transport.api.model.LogisticsBaseOrderVo;
import com.sckw.transport.api.model.dto.McpLogisticsOrderVo;
import com.sckw.transport.api.model.dto.OrderUrl;
import com.sckw.transport.common.config.MessageUrlConfig;
import com.sckw.transport.dao.*;
import com.sckw.transport.model.*;
import com.sckw.transport.model.dto.*;
import com.sckw.transport.model.param.*;
import com.sckw.transport.model.vo.*;
import com.sckw.transport.repository.*;
import io.seata.spring.annotation.GlobalTransactional;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.stream.function.StreamBridge;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author lfdc
 * @description 物流托运/分包托运Service
 * @date 2023-06-28 11:06:07
 */
@Slf4j
@Service
@RequiredArgsConstructor
@SuppressWarnings("all")
public class KwtLogisticsConsignmentService {

    @Resource
    private StreamBridge streamBridge;

    @Autowired
    RedisLockUtil redisLockUtil;

    @Autowired
    public KwtTransportCommonService transportCommonService;

    @Autowired
    KwtWaybillOrderService waybillOrderService;

    @Autowired
    KwtLogisticsOrderGoodsService logisticsOrderGoodsService;

    @Autowired
    MessageUrlConfig messageUrlConfig;

    @Autowired
    public KwtCommonService commonService;

    @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 6000)
    RemoteSystemService remoteSystemService;
    @DubboReference(version = "1.0.0", group = "design", check = false)
    private RemoteUserService remoteUserService;

    @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 6000)
    GoodsInfoService goodsInfoService;

    @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 80000)
    TradeOrderInfoService tradeOrderInfoService;

    @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 80000)
    RemoteTradeOrderAmountService tradeOrderAmountService;

    @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 6000)
    RemoteFleetService remoteFleetService;

    @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 6000)
    RemoteContractService contractService;

    @Autowired
    private KwtLogisticsOrderUnitRepository kwtLogisticsOrderUnitRepository;

    @Autowired(required = false)
    private PaymentFeignService paymentFeignService;

    @Autowired(required = false)
    DataPermissionFeignService dataPermissionFeignService;

    @Autowired
    public KwtLogisticsOrderConsignmentService logisticsOrderConsignmentService;

    @Autowired
    public KwtLogisticsOrderGoodsMapper kwtLogisticsOrderGoodsMapper;

    @Autowired
    public KwtLogisticsOrderContractMapper kwtLogisticsOrderContractMapper;

    @Autowired
    public KwtLogisticsOrderAmountMapper logisticsOrderAmountMapper;

    @Autowired
    public KwtLogisticsOrderMapper kwtLogisticsOrderMapper;

    @Autowired
    public KwtLogisticsOrderAddressMapper kwtLogisticsOrderAddressMapper;

    @Autowired
    public KwtLogisticsOrderTrackMapper kwtLogisticsOrderTrackMapper;

    @Autowired
    public KwtLogisticsOrderUnitMapper kwtLogisticsOrderUnitMapper;

    @Autowired
    public KwtWaybillOrderMapper waybillOrderMapper;

    @Autowired
    public KwtWaybillOrderV1Mapper waybillOrderV1Mapper;
    private final KwtAcceptCarriageOrderService kwtAcceptCarriageOrderService;

    private final KwtLogisticsOrderRepository logisticsOrderRepository;
    private final KwtLogisticsOrderGoodsRepository logisticsOrderGoodsRepository;
    private final KwtLogisticsOrderUnitRepository logisticsOrderUnitRepository;
    private final KwtLogisticsOrderAddressRepository logisticsOrderAddressRepository;
    private final KwtLogisticsOrderContractRepository logisticsOrderContractRepository;
    private final KwtWaybillOrderSubtaskRepository waybillOrderSubtaskRepository;
    private final KwtWaybillOrderRepository waybillOrderRepository;
    private final KwtLogisticsOrderCirculateRepository logisticsOrderCirculateRepository;
    private final KwtWaybillOrderAddressRepository waybillOrderAddressRepository;
    private final KwtWaybillOrderTicketRepository waybillOrderTicketRepository;
    private final KwtWaybillOrderNodeRepository waybillOrderNodeRepository;

    /**
     * 采购订单-物流托运生成托运订单
     *
     * @param bo 请求参数
     * @return 响应数据
     */
    @Transactional(rollbackFor = Exception.class)
    public HttpResult logisticsConsignment(LogisticsConsignmentParam bo, int orderType) {
        HttpResult httpResult = ValidUtil.serviceValid(bo);
        if (HttpStatus.SUCCESS_CODE != httpResult.getCode()) {
            return HttpResult.error(httpResult.getMsg());
        }
        HttpResult checked = checkParamData(bo);
        if (checked.getCode() != HttpStatus.SUCCESS_CODE) {
            return HttpResult.error(checked.getMsg());
        }
        String key = String.format(RedisConstant.TRADE_TO_LOGISTICS_NO_GENERATE_KEY, bo.getTOrderId());
        if (redisLockUtil.tryLock(key)) {
            try {
                logisticsConsignmentInsert(bo, orderType);
            } finally {
                redisLockUtil.unlock(key);
            }
        } else {
            return HttpResult.error("请求不可重复操作,请稍后重试");
        }
        return HttpResult.ok();
    }

    /**
     * 参数校验
     *
     * @param bo 订单参数
     * @return 校验结果
     */
    private HttpResult checkParamData(LogisticsConsignmentParam bo) {
        if (!ObjectUtils.isEmpty(bo.getLoss())) {
            if (bo.getLoss().compareTo(NumberConstant.ZERO_TWO) < 0) {
                return HttpResult.error("合理损耗填写时,必须大于0");
            }
        }
        if (!ObjectUtils.isEmpty(bo.getGoodsPrice())) {
            if (bo.getGoodsPrice().compareTo(NumberConstant.ZERO_TWO) < 0) {
                return HttpResult.error("扣亏货值填写时,必须大于0");
            }
        }
        return HttpResult.ok();
    }

    /**
     * 参数校验
     *
     * @param bo 订单参数
     * @return 校验结果
     */
    private HttpResult checkParamData(LogisticsConsignmentDto bo) {
        if (!ObjectUtils.isEmpty(bo.getLoss())) {
            if (bo.getLoss().compareTo(NumberConstant.ZERO_TWO) < 0) {
                return HttpResult.error("合理损耗填写时,必须大于0");
            }
        }
        if (!ObjectUtils.isEmpty(bo.getGoodsPrice())) {
            if (bo.getGoodsPrice().compareTo(NumberConstant.ZERO_TWO) < 0) {
                return HttpResult.error("扣亏货值填写时,必须大于0");
            }
        }
        return HttpResult.ok();
    }

    /**
     * 创建物流订单
     *
     * @param bo        订单参数
     * @param orderType 类型
     */
    void logisticsConsignmentInsert(LogisticsConsignmentParam bo, int orderType) {
        commonService.getRedisGenerateOrderNo();
        Long count = kwtLogisticsOrderMapper.selectCount(new LambdaQueryWrapper<KwtLogisticsOrder>().eq(KwtLogisticsOrder::getTOrderId, bo.getTOrderId()));
        String lOrderNo = OrderGenerateSeqNoUtils.getSeqNo(RedisOrderGenerateEnum.LOGISTICS_ORDER, OrderRuleEnum.LOGISTICS_ORDER, "1", "0", String.valueOf(count + 1));
        OrderDetailRes tradeOrder = tradeOrderInfoService.getOrderDetailById(Long.parseLong(bo.getTOrderId()));
        if (tradeOrder == null) {
            log.error("订单id查找失败:{}", bo.getTOrderId());
            throw new BusinessException("贸易订单数据不存在");
        }
        KwtLogisticsOrder order = new KwtLogisticsOrder();
        if (!bo.getIsFullDose()) {
            //BigDecimal amount = tradeOrder.getAmount().subtract(tradeOrder.getEntrustAmount());
            BigDecimal carryingCapacity = bo.getCarryingCapacity();
            if (bo.getCarryingCapacity().compareTo(NumberConstant.ZERO_TWO) == 0) {
                log.error("可分配量分配错误:{}", bo.getTOrderId());
                throw new BusinessException("可分配量分配必须填写大于0");
            }
            //可运量校验
            boolean bool = logisticsOrderGoodsService.chenkAmount(bo, tradeOrder);
            if (!bool) {
                log.error("可分配量分配错误:{}", bo.getTOrderId());
                throw new BusinessException("可分配量分配错误");
            }
            if (ArrayUtil.isEmpty(bo.getCarryingCapacity())) {
                throw new BusinessException("不是全量分配时,分配量不能为空!");
            }
            order.setAmount(bo.getCarryingCapacity());
        } else {
            order.setAmount(NumberConstant.ZERO_TWO);
            order.setSubcontractAmount(NumberConstant.ZERO_TWO);
        }

        Long orderId = new IdWorker(NumberConstant.ONE).nextId();
        order.setId(orderId);
        long contractId = Long.parseLong(bo.getContractId());
        List<Long> contractList = new ArrayList<>();
        contractList.add(contractId);
        Map<Long, ContractCommonInfoResDto> longContractCommonInfoResDtoMap = contractService.queryContractBaseInfo(contractList);
        if (CollectionUtils.isEmpty(longContractCommonInfoResDtoMap)) {
            throw new BusinessException("托运订单新建订单-并未有对应合同,应先签约合同");
        }
        if (longContractCommonInfoResDtoMap.get(contractId) == null) {
            throw new BusinessException("托运订单新建订单-并未有对应合同,应先签约合同");
        }
        ContractCommonInfoResDto infoResDto = longContractCommonInfoResDtoMap.get(contractId);
        /**状态判断
         * 是否是已签约合同
         * */
        // 0 已签约 1待签约
        Integer status = infoResDto.getStatus();
        Integer orderStatus = LogisticsOrderEnum.PENDING_ORDER.getCode();
        if (NumberConstant.ONE == status) {
            orderStatus = LogisticsOrderEnum.TO_BE_PLANNED.getCode();
        } else if (NumberConstant.ZERO == status) {
            orderStatus = LogisticsOrderEnum.PENDING_ORDER.getCode();
        } else {
            log.info("物流托运创建订单异常");
            throw new BusinessException("物流托运创建订单异常");
        }
        logisticsOrderGoodsService.insertLogisticsGoods(bo, lOrderNo, orderId);
        insertLogisticsOrder(bo, lOrderNo, order, tradeOrder, orderId, orderStatus);
        insertLogisticsOrderContract(bo, orderId);
        insertLogisticsOrderUnit(bo, orderId);
        insertLogisticsOrderAddress(bo, orderId);
        insertLogisticsOrderTrack(bo, orderId, orderStatus);
        sendMongoDB(lOrderNo, orderId, bo, tradeOrder, orderStatus);

        /**将生成的分配量->贸易订单*/
        /*CreateOrCancelLogisticsOrderParam param = new CreateOrCancelLogisticsOrderParam();
        param.setTOrderId(Long.valueOf(bo.getTOrderId()));
        param.setEntrustAmount(bo.getCarryingCapacity());
        param.setUpdateBy(LoginUserHolder.getUserId());
        param.setUpdateByName(LoginUserHolder.getUserName());
        //HttpResult httpResult = tradeOrderInfoService.createOrCancelLogisticsOrder(param);*/
        List<GoodsLoadingParam> goodsLoading = logisticsOrderGoodsService.goodsLoadingParams(order, false);
//        HttpResult httpResult = tradeOrderInfoService.createOrCancelLogisticsOrderV1(order.getTOrderId(), goodsLoading);
        HttpResult httpResult = tradeOrderInfoService.createOrCancelLogisticsOrderV1(LoginUserHolder.getUserId(), LoginUserHolder.getUserName(), order.getTOrderId(), goodsLoading);
        if (httpResult.getCode() != HttpStatus.SUCCESS_CODE) {
            log.info("{}生成物流托运失败!,返回信息:{}", tradeOrder.getTOrderNo(), JSONObject.toJSONString(httpResult));
            throw new BusinessException("{" + tradeOrder.getTOrderNo() + "}生成物流托运失败!" + httpResult.getMsg());
        }

        /**消息列表
         * 1 采购 2 销售
         * */
        String pcConsignUrl = "", appConsignUrl = "", pcCarriageUrl = "", appCarriageUrl = "", type = "";
        MessageEnum consignMessageEnum = null, carriageMessageEnum = null;
        //托运单位
        KwtLogisticsOrderUnit checkUnit = new KwtLogisticsOrderUnit();
        //承运单位
        KwtLogisticsOrderUnit carriageUnit = new KwtLogisticsOrderUnit();
        if (orderType == NumberConstant.ONE) {
            EntCacheResDto consignentMap = remoteSystemService.queryEntTreeById(Long.parseLong(bo.getConsignCompanyId()));
            EntCacheResDto checkentMap = remoteSystemService.queryEntTreeById(Long.parseLong(bo.getCheckCompanyId()));
            //发起方
            checkUnit.setUnitType(NumberConstant.ONE);
            checkUnit.setFirmName(bo.getCheckCompany());
            checkUnit.setEntId(Long.parseLong(bo.getConsignCompanyId()));
            checkUnit.setTopEntId(consignentMap == null ? null : consignentMap.getId());
            checkUnit.setContactsId(Long.parseLong(bo.getCheckContactsId()));
            //接收方
            carriageUnit.setUnitType(NumberConstant.TWO);
            carriageUnit.setFirmName(bo.getConsignCompany());
            carriageUnit.setEntId(Long.parseLong(bo.getCheckCompanyId()));
            carriageUnit.setTopEntId(checkentMap == null ? null : checkentMap.getId());
            carriageUnit.setContactsId(Long.parseLong(bo.getConsignContactsId()));
            pcConsignUrl = messageUrlConfig.getPc().getCarriageLogisticsAddOrderUrl();
            appConsignUrl = messageUrlConfig.getApp().getCarriageLogisticsAddOrderUrl();
            pcCarriageUrl = messageUrlConfig.getPc().getConsignLogisticsAddOrderUrl();
            appCarriageUrl = messageUrlConfig.getApp().getConsignLogisticsAddOrderUrl();
            consignMessageEnum = MessageEnum.NEW_CARRIAGE_ORDER;
            carriageMessageEnum = MessageEnum.INITIATING_LOGISTICS_CONSIGNMENT;
            type = "2";
        } else if (orderType == NumberConstant.TWO) {
            EntCacheResDto consignentMap = remoteSystemService.queryEntTreeById(Long.parseLong(bo.getConsignCompanyId()));
            EntCacheResDto checkentMap = remoteSystemService.queryEntTreeById(Long.parseLong(bo.getCheckCompanyId()));
            //发起方
            checkUnit.setUnitType(NumberConstant.ONE);
            checkUnit.setFirmName(bo.getCheckCompany());
            checkUnit.setEntId(Long.parseLong(bo.getCheckCompanyId()));
            checkUnit.setTopEntId(consignentMap == null ? null : consignentMap.getId());
            checkUnit.setContactsId(Long.parseLong(bo.getConsignContactsId()));
            //接收方
            carriageUnit.setUnitType(NumberConstant.TWO);
            carriageUnit.setFirmName(bo.getConsignCompany());
            carriageUnit.setEntId(Long.parseLong(bo.getConsignCompanyId()));
            carriageUnit.setTopEntId(checkentMap == null ? null : checkentMap.getId());
            carriageUnit.setContactsId(Long.parseLong(bo.getCheckContactsId()));
            pcConsignUrl = messageUrlConfig.getPc().getConsignLogisticsAddOrderUrl();
            appConsignUrl = messageUrlConfig.getApp().getConsignLogisticsAddOrderUrl();
            pcCarriageUrl = messageUrlConfig.getPc().getCarriageLogisticsAddOrderUrl();
            appCarriageUrl = messageUrlConfig.getApp().getCarriageLogisticsAddOrderUrl();
            consignMessageEnum = MessageEnum.NEW_CARRIAGE_ORDER;
            carriageMessageEnum = MessageEnum.INITIATING_LOGISTICS_CONSIGNMENT;
            type = "1";
        }
        //发送消息
        commonService.newSendLogisticsOrderToMessage(checkUnit, carriageUnit, lOrderNo, LoginUserHolder.getUserId(),
                LoginUserHolder.getEntId(), pcConsignUrl, appConsignUrl, pcCarriageUrl, appCarriageUrl,
                consignMessageEnum, carriageMessageEnum, type);
    }

    /**
     * 组装数据发送至mongoDb
     *
     * @param lOrderNo    物流订单编号
     * @param orderId     物流订单id
     * @param bo          页面请求数据
     * @param tradeOrder  贸易单据
     * @param orderStatus 物流订单状态
     */
    private void sendMongoDB(String lOrderNo, Long orderId, LogisticsConsignmentParam bo, OrderDetailRes tradeOrder, Integer orderStatus) {
        SckwLogisticsOrder logisticsOrder = new SckwLogisticsOrder();
        logisticsOrder.setStatus(String.valueOf(orderStatus));
        logisticsOrder.setLOrderId(orderId);
        logisticsOrder.setLOrderNo(lOrderNo);
        logisticsOrder.setLOrderPid(null);
        logisticsOrder.setTOrderId(tradeOrder.getId());
        logisticsOrder.setTOrderNo("D" + com.sckw.transport.utils.StringUtils.getWaybillNoUtil());
        logisticsOrder.setSettlementCycle(bo.getSettlementCycle());
        logisticsOrder.setPrice(bo.getPrice());
        logisticsOrder.setPriceType(remoteSystemService.queryDictByTypeAndValue(DictTypeEnum.PRICE_TYPE.getType(), bo.getPriceType()) == null ?
                null : Long.parseLong(remoteSystemService.queryDictByTypeAndValue(DictTypeEnum.PRICE_TYPE.getType(), bo.getPriceType()).getValue()));

        if (!bo.getIsFullDose()) {
            if (ArrayUtil.isEmpty(bo.getCarryingCapacity())) {
                throw new RuntimeException("不是全量分配时,分配量不能为空!");
            }
            logisticsOrder.setAmount(bo.getCarryingCapacity());
            logisticsOrder.setUnit(bo.getCarryingCapacityUnit());
            logisticsOrder.setCarryingCapacity(bo.getCarryingCapacity());
        } else {
            logisticsOrder.setAmount(NumberConstant.ZERO_TWO);
            logisticsOrder.setSubcontractAmount(NumberConstant.ZERO_TWO);
            logisticsOrder.setCarryingCapacity(NumberConstant.ZERO_TWO);
        }
        logisticsOrder.setLoss(bo.getLoss() == null ? null : bo.getLoss());
        logisticsOrder.setLossUnit(bo.getLossUnit());
        logisticsOrder.setGoodsPrice(bo.getGoodsPrice() == null ? null : bo.getGoodsPrice());
        BigDecimal decimal = new BigDecimal(NumberConstant.ZERO);
        logisticsOrder.setSubcontractAmount(decimal);
        logisticsOrder.setEntrustAmount(decimal);
        logisticsOrder.setUnloadAmount(decimal);
        logisticsOrder.setLoadAmount(decimal);
        logisticsOrder.setIgnoreAmount(decimal);
        logisticsOrder.setDeficitPrice(decimal);
        logisticsOrder.setPayment(Long.parseLong(bo.getPayment()));
        logisticsOrder.setTaxRate(bo.getTaxRate() == null ? null : new BigDecimal(bo.getTaxRate()));
        logisticsOrder.setRemark(bo.getRemark());
        logisticsOrder.setEntId(LoginUserHolder.getEntId());
        logisticsOrder.setFirmName(remoteSystemService.queryEntCacheById(LoginUserHolder.getEntId()).getFirmName());
        logisticsOrder.setGoodsId(Long.parseLong(bo.getGoodsId()));
        KwpGoods goods = goodsInfoService.getGoodsById(Long.parseLong(bo.getGoodsId()));
        logisticsOrder.setGoodsType(goods == null ? null : goods.getGoodsType());
        logisticsOrder.setGoodsSpec(goods == null ? null : goods.getSpec());
        logisticsOrder.setContractId(bo.getContractId());
        logisticsOrder.setContractNo(bo.getContractNo());
        logisticsOrder.setContractName(bo.getContractName());
        logisticsOrder.setContractSigningWay(bo.getPayment());
        logisticsOrder.setCheckEntId(Long.parseLong(bo.getCheckCompanyId()));
        logisticsOrder.setCheckFirmName(bo.getCheckCompany());
        logisticsOrder.setCheckContacts(bo.getCheckContacts());
        logisticsOrder.setCheckPhone(bo.getCheckContactPhone());
        logisticsOrder.setCarrierEntId(Long.parseLong(bo.getConsignCompanyId()));
        logisticsOrder.setCarrierFirmName(bo.getConsignCompany());
        logisticsOrder.setCarrierContacts(bo.getConsignContacts());
        OrderDetailRes orderDetailRes = tradeOrderInfoService.getOrderDetailById(Long.valueOf(bo.getTOrderId()));
        // 收货单位+发货单位
        if (orderDetailRes != null) {
            List<UnitInfoDetailRes> unitInfo = orderDetailRes.getUnitInfo();
            if (CollectionUtils.isNotEmpty(unitInfo)) {
                for (UnitInfoDetailRes unitInfoDetailRes : unitInfo) {
                    if (String.valueOf(NumberConstant.ONE).equals(unitInfoDetailRes.getUnitType())) {
                        logisticsOrder.setShipmentsUnitEntId(String.valueOf(unitInfoDetailRes.getEntId()));
                        logisticsOrder.setShipmentsUnit(unitInfoDetailRes.getFirmName());
                    } else if (String.valueOf(NumberConstant.TWO).equals(unitInfoDetailRes.getUnitType())) {
                        logisticsOrder.setReceiveGoodsUnitEntId(String.valueOf(unitInfoDetailRes.getEntId()));
                        logisticsOrder.setReceiveGoodsUnit(unitInfoDetailRes.getFirmName());
                    }
                }
            }
        }
        List<AddressInfoDetail> addressInfo = tradeOrder.getAddressInfo();
        for (AddressInfoDetail detail : addressInfo) {
            if (String.valueOf(NumberConstant.ONE).equals(detail.getAddressType())) {
                logisticsOrder.setLoadType(Long.parseLong(detail.getType()));
                logisticsOrder.setLoadCityCode(detail.getCityCode());
                logisticsOrder.setLoadCityName(detail.getCityName());
                logisticsOrder.setLoadDetailAddress(detail.getDetailAddress());
                logisticsOrder.setLoadLat(detail.getLat());
                logisticsOrder.setLoadPhone(detail.getPhone());
                logisticsOrder.setLoadLng(detail.getLng());
                logisticsOrder.setLoadContacts(detail.getContacts());
            }
            if (String.valueOf(NumberConstant.TWO).equals(detail.getAddressType())) {
                logisticsOrder.setUnloadType(Long.parseLong(detail.getType()));
                logisticsOrder.setUnloadPhone(detail.getPhone());
                logisticsOrder.setUnloadCityCode(detail.getCityCode());
                logisticsOrder.setUnloadCityName(detail.getCityName());
                logisticsOrder.setUnloadDetailAddress(detail.getDetailAddress());
                logisticsOrder.setUnloadLat(detail.getLat());
                logisticsOrder.setUnloadLng(detail.getLng());
                logisticsOrder.setUnloadContacts(detail.getContacts());
            }
        }
        //TODO 生成时并无时间
//        logisticsOrder.setLoadTime();
//        logisticsOrder.setunLoadTime();
        logisticsOrder.setCreateBy(LoginUserHolder.getUserId());
        logisticsOrder.setCreateByName(LoginUserHolder.getUserName());
        logisticsOrder.setCreateTime(new Date());
        logisticsOrder.setUpdateBy(LoginUserHolder.getUserId());
        logisticsOrder.setUpdateByName(LoginUserHolder.getUserName());
        logisticsOrder.setUpdateTime(new Date());
        logisticsOrder.setGoodsPriceUnit(bo.getGoodsPriceUnit());
        logisticsOrder.setContractName(bo.getContractName());
        logisticsOrder.setBillingMode(bo.getBillingMode());
        logisticsOrder.setStartTime(bo.getShipmentsDateTime() == null ? null : DateUtil.localDateToLocalDateTimeStart(bo.getShipmentsDateTime()));
        logisticsOrder.setEndTime(bo.getReceiveGoodsDateTime() == null ? null : DateUtil.localDateToLocalDateTimeEnd(bo.getReceiveGoodsDateTime()));
        //rabbitMq业务汇总数据发送/消费对象
        SckwBusSum busSum = new SckwBusSum();
        //业务汇总类型
        busSum.setBusSumType(BusinessTypeEnum.LOGISTICS_ORDER_TYPE.getName());
        //操作对象（1新增/2修改）
        busSum.setMethod(1);
        //业务汇总数据对象
        busSum.setObject(logisticsOrder);
        streamBridge.send("sckw-busSum", JSON.toJSONString(busSum));
    }

    /**
     * 物流订单-企业信息
     *
     * @param bo      请求参数
     * @param orderId 订单id
     */
    private void insertLogisticsOrderUnit(LogisticsConsignmentParam bo, Long orderId) {
        EntCacheResDto consignentMap = remoteSystemService.queryEntTreeById(Long.parseLong(bo.getConsignCompanyId()));
        EntCacheResDto checkentMap = remoteSystemService.queryEntTreeById(Long.parseLong(bo.getCheckCompanyId()));
        if (consignentMap == null || checkentMap == null) {
            throw new BusinessException("企业对应一级企业不存在");
        }
        KwtLogisticsOrderUnit checkUnit = new KwtLogisticsOrderUnit()
                .setLOrderId(orderId)
                .setId(new IdWorker(NumberConstant.ONE).nextId())
                .setUnitType(NumberConstant.ONE)
                .setFirmName(bo.getCheckCompany())
                .setRemark(bo.getRemark())
                .setEntId(Long.parseLong(bo.getCheckCompanyId()))
                .setTopEntId(checkentMap.getId())
                .setContacts(bo.getCheckContacts())
                .setPhone(bo.getCheckContactPhone())
                .setCreateBy(LoginUserHolder.getUserId())
                .setCreateTime(new Date())
                .setUpdateBy(LoginUserHolder.getUserId())
                .setUpdateTime(new Date())
                .setContactsId(Long.parseLong(bo.getCheckContactsId()));
        kwtLogisticsOrderUnitMapper.insert(checkUnit);

        KwtLogisticsOrderUnit consignUnit = new KwtLogisticsOrderUnit()
                .setLOrderId(orderId)
                .setId(new IdWorker(NumberConstant.ONE).nextId())
                .setUnitType(NumberConstant.TWO)
                .setFirmName(bo.getConsignCompany())
                .setRemark(bo.getRemark())
                .setEntId(Long.parseLong(bo.getConsignCompanyId()))
                .setTopEntId(consignentMap.getId())
                .setContacts(bo.getConsignContacts())
                .setPhone(bo.getConsignContactPhone())
                .setCreateBy(LoginUserHolder.getUserId())
                .setCreateTime(new Date())
                .setUpdateBy(LoginUserHolder.getUserId())
                .setUpdateTime(new Date())
                .setContactsId(Long.parseLong(bo.getConsignContactsId()));
        kwtLogisticsOrderUnitMapper.insert(consignUnit);
    }

    /**
     * 物流订单-状态
     *
     * @param bo      请求数据
     * @param orderId 订单状态
     */
    private void insertLogisticsOrderTrack(LogisticsConsignmentParam bo, Long orderId, Integer orderStatus) {
        KwtLogisticsOrderTrack entity = new KwtLogisticsOrderTrack();
        entity.setId(new IdWorker(NumberConstant.ONE).nextId());
        entity.setLOrderId(orderId);
        entity.setStatus(LogisticsOrderEnum.PENDING_ORDER.getCode());
        entity.setCreateTime(new Date());
        entity.setUpdateTime(new Date());
        entity.setCreateBy(LoginUserHolder.getUserId());
        entity.setUpdateBy(LoginUserHolder.getUserId());
        entity.setRemark(bo.getRemark());
        kwtLogisticsOrderTrackMapper.insert(entity);
    }

    /**
     * 物流订单-主体
     *
     * @param bo          页面请求参数
     * @param lOrderNo    物流订单编号
     * @param order       物流订单数据
     * @param tradeOrder  贸易订单数据
     * @param orderId     物流订单id
     * @param orderStatus 物流订单状态
     */
    private void insertLogisticsOrder(LogisticsConsignmentParam bo, String lOrderNo, KwtLogisticsOrder order, OrderDetailRes tradeOrder, Long orderId, Integer orderStatus) {
        order.setId(orderId);
        order.setEntId(LoginUserHolder.getEntId());
        order.setType(String.valueOf(NumberConstant.ONE));
        order.setTOrderId(Long.parseLong(bo.getTOrderId()));
        order.setTOrderNo(bo.getTOrderNo());
        order.setLOrderNo(lOrderNo);
        order.setPid(null);
//        order.setPids(orderId + StringConstant.COMMA);
        order.setPids(String.valueOf(orderId));
        order.setSettlementCycle(bo.getSettlementCycle());
        order.setPrice(bo.getPrice());
        order.setPriceType(remoteSystemService.queryDictByTypeAndValue(DictTypeEnum.PRICE_TYPE.getType(), bo.getPriceType()) == null ?
                null : Long.parseLong(remoteSystemService.queryDictByTypeAndValue(DictTypeEnum.PRICE_TYPE.getType(), bo.getPriceType()).getValue()));
//        order.setAmount(tradeOrder.getAmount());
        order.setBillingMode(bo.getBillingMode());
        order.setUnit(bo.getCarryingCapacityUnit());
        order.setLoss(bo.getLoss() == null ? null : bo.getLoss());
//        order.setLossUnit(bo.getLossUnit());
        order.setLossUnit(remoteSystemService.queryDictByTypeAndValue(DictTypeEnum.UNIT_TYPE.getType(), bo.getLossUnit()) == null ?
                null : remoteSystemService.queryDictByTypeAndValue(DictTypeEnum.UNIT_TYPE.getType(), bo.getLossUnit()).getValue());
        order.setGoodsPrice(bo.getGoodsPrice() == null ? null : bo.getGoodsPrice());
        order.setGoodsPriceUnit(remoteSystemService.queryDictByTypeAndValue(DictTypeEnum.PRICE_TYPE.getType(), bo.getGoodsPriceUnit()) == null ?
                null : remoteSystemService.queryDictByTypeAndValue(DictTypeEnum.PRICE_TYPE.getType(), bo.getGoodsPriceUnit()).getValue());
        order.setGoodsPriceUnit(bo.getGoodsPriceUnit());
        order.setStartTime(bo.getShipmentsDateTime() == null ? null : DateUtil.localDateToLocalDateTimeStart(bo.getShipmentsDateTime()));
        order.setEndTime(bo.getReceiveGoodsDateTime() == null ? null : DateUtil.localDateToLocalDateTimeEnd(bo.getReceiveGoodsDateTime()));
        order.setRemark(bo.getRemark());
        order.setPayment(Long.parseLong(bo.getPayment()));
        order.setTaxRate(new BigDecimal(bo.getTaxRate()));
        order.setCreateBy(LoginUserHolder.getUserId());
        order.setCreateTime(new Date());
        order.setUpdateBy(LoginUserHolder.getUserId());
        order.setUpdateTime(new Date());
        order.setStatus(orderStatus);
        BigDecimal decimal = new BigDecimal(NumberConstant.ZERO);
        /**补充默认值*/
        order.setEntrustAmount(decimal);
        order.setSubcontractAmount(decimal);
        order.setLoadAmount(decimal);
        order.setUnloadAmount(decimal);
        order.setIgnoreAmount(decimal);
        order.setDeficitPrice(decimal);
        order.setDeficitAmount(decimal);
        order.setTotalUnloadAmount(decimal);
        order.setTotalLoadAmount(decimal);
        order.setBindStatus(String.valueOf(NumberConstant.ZERO));
        kwtLogisticsOrderMapper.insert(order);
    }

    /**
     * 物流订单-合同
     *
     * @param bo 请求数据
     */
    private void insertLogisticsOrderContract(LogisticsConsignmentParam bo, Long orderId) {
        KwtLogisticsOrderContract kwtLogisticsOrderContract = new KwtLogisticsOrderContract();
        kwtLogisticsOrderContract.setId(new IdWorker(NumberConstant.ONE).nextId());
        kwtLogisticsOrderContract.setLOrderId(orderId);
        kwtLogisticsOrderContract.setContractId(Long.parseLong(bo.getContractId()));
        kwtLogisticsOrderContract.setContractNo(bo.getContractNo());
        kwtLogisticsOrderContract.setContractName(bo.getContractName());
        kwtLogisticsOrderContract.setSigningWay(bo.getSigningWay());
        kwtLogisticsOrderContract.setRemark(bo.getRemark());
        kwtLogisticsOrderContract.setCreateBy(LoginUserHolder.getUserId());
        kwtLogisticsOrderContract.setUpdateBy(LoginUserHolder.getUserId());
        kwtLogisticsOrderContract.setCreateTime(new Date());
        kwtLogisticsOrderContract.setUpdateTime(new Date());
        kwtLogisticsOrderContractMapper.insert(kwtLogisticsOrderContract);
    }

    /**
     * 物流订单-装卸货地址
     *
     * @param bo      请求数据
     * @param orderId 订单id
     */
    private void insertLogisticsOrderAddress(LogisticsConsignmentParam bo, Long orderId) {
        KwtLogisticsOrderAddress loadOrderAddress = new KwtLogisticsOrderAddress();
        KwtLogisticsOrderAddress unloadOrderAddress = new KwtLogisticsOrderAddress();
        //todo 装卸货地址 通过dubbo查询
        OrderDetailRes orderDetailRes = tradeOrderInfoService.getOrderDetailById(Long.parseLong(bo.getTOrderId()));
        if (ObjectUtils.isEmpty(orderDetailRes)) {
            log.info("dubbp 查询数据 error :orderId:{}", bo.getTOrderId());
            throw new RuntimeException("dubbp 查询销售订单数据查找失败!");
        }
        List<AddressInfoDetail> addressInfo = orderDetailRes.getAddressInfo();
        if (CollectionUtils.isEmpty(addressInfo)) {
            throw new BusinessException("生成物流托运时,地址信息不存在!");
        }
        if (CollectionUtils.isNotEmpty(addressInfo)) {
            for (AddressInfoDetail detail : addressInfo) {
                if (String.valueOf(NumberConstant.ONE).equals(detail.getAddressType())) {
                    loadOrderAddress.setId(new IdWorker(NumberConstant.ONE).nextId());
                    loadOrderAddress.setAddressType(NumberConstant.ONE);
                    loadOrderAddress.setDetailAddress(detail.getDetailAddress());
                    loadOrderAddress.setContacts(detail.getContacts());
                    loadOrderAddress.setLOrderId(orderId);
                    loadOrderAddress.setLat(detail.getLat());
                    loadOrderAddress.setFence(detail.getFence());
                    loadOrderAddress.setCityName(detail.getCityName());
                    loadOrderAddress.setEntryType(NumberConstant.FOUR);
                    loadOrderAddress.setCreateTime(new Date());
                    loadOrderAddress.setPhone(detail.getPhone());
                    loadOrderAddress.setCreateBy(LoginUserHolder.getUserId());
                    loadOrderAddress.setUpdateBy(LoginUserHolder.getUserId());
                    loadOrderAddress.setUpdateTime(new Date());
                    loadOrderAddress.setName(detail.getName());
                    loadOrderAddress.setType(Long.parseLong(detail.getType()));
                    loadOrderAddress.setCityCode(detail.getCityCode());
                    loadOrderAddress.setLng(detail.getLng());
//                    loadOrderAddress.setRemark(detail.getRemark());
//                    loadOrderAddress.setStatus(detail.getStatus());
                }
                if (String.valueOf(NumberConstant.TWO).equals(detail.getAddressType())) {
                    unloadOrderAddress.setId(new IdWorker(NumberConstant.TWO).nextId());
                    unloadOrderAddress.setAddressType(NumberConstant.TWO);
                    unloadOrderAddress.setContacts(detail.getContacts());
                    unloadOrderAddress.setLOrderId(orderId);
                    unloadOrderAddress.setLat(detail.getLat());
                    unloadOrderAddress.setFence(detail.getFence());
                    unloadOrderAddress.setCityName(detail.getCityName());
                    unloadOrderAddress.setEntryType(NumberConstant.FOUR);
                    unloadOrderAddress.setPhone(detail.getPhone());
                    unloadOrderAddress.setDetailAddress(detail.getDetailAddress());
                    unloadOrderAddress.setCreateTime(new Date());
                    unloadOrderAddress.setCreateBy(LoginUserHolder.getUserId());
                    unloadOrderAddress.setUpdateBy(LoginUserHolder.getUserId());
                    unloadOrderAddress.setUpdateTime(new Date());
                    unloadOrderAddress.setName(detail.getName());
                    unloadOrderAddress.setType(Long.valueOf(detail.getType()));
                    unloadOrderAddress.setCityCode(detail.getCityCode());
                    unloadOrderAddress.setLng(detail.getLng());
//                    unloadOrderAddress.setRemark(detail.getRemark());
//                    unloadOrderAddress.setStatus(detail.getStatus());
                }
            }
        }

        kwtLogisticsOrderAddressMapper.insert(loadOrderAddress);
        kwtLogisticsOrderAddressMapper.insert(unloadOrderAddress);
    }

    /**
     * @param id
     * @param page
     * @param pageSize
     * @return
     */
    public HttpResult purchaseLogisticsOrder(String id, Integer page, Integer pageSize, String type) {
        Long count = getLogisticsOrderCount(id, type);
        Integer newPage = (page - 1) * pageSize;
        List<LogisticsOrderDto> list = getLogisticsOrderData(id, newPage, pageSize, type);
        PageResult build = PageResult.build(page, pageSize, count, list);
        return HttpResult.ok(build);
    }

    private Long getLogisticsOrderCount(String id, String type) {
        return kwtLogisticsOrderMapper.selectOrderCount(id, type);
    }

    /**
     * 采购订单-获取托运订单数据
     *
     * @param ids      销售订单ids
     * @param page     当前页
     * @param pageSize 每页条数
     * @param type     属于采购（1）还是销售（2）
     * @return
     */
    public HttpResult logisticsOrder(String ids, Integer page, Integer pageSize, String type) {
        HttpResult httpResult = new HttpResult();
        if (String.valueOf(NumberConstant.ONE).equals(type)) {
            //采购
            httpResult = logisticsOrderList(ids, page, pageSize, type);
        } else if (String.valueOf(NumberConstant.TWO).equals(type)) {
            //销售
            httpResult = logisticsSellOrderList(ids, page, pageSize, type);
        } else {
            return HttpResult.error("单据类型错误");
        }
        return httpResult;
    }

    /**
     * 销售订单-获取托运订单数据
     *
     * @param ids
     * @param page
     * @param pageSize
     * @param type
     * @return
     */
    private HttpResult logisticsSellOrderList(String ids, Integer page, Integer pageSize, String type) {
        List<String> stringList = StringUtils.splitStrToList(ids, String.class);
        if (CollectionUtils.isEmpty(stringList)) {
            return HttpResult.ok();
        }
        List<LogisticsOrderDto> returnList = new ArrayList<>();
        stringList = stringList.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
        /**后期分页优化，可以使用此方法*/
//        PageRes<LogisticsOrderDTO> logisticsOrderListByTradeOrderIds = getLogisticsOrderListByTradeOrderIds(stringList, page, pageSize, type);
        for (String id : stringList) {
            OrderDetailRes orderDetailRes = tradeOrderInfoService.getOrderDetailById(Long.parseLong(id));
            if (orderDetailRes == null) {
                continue;
            }
            /**
             * 0销售展示是供应配送  1采购展示是采购自提
             * 根据提货方式（0供应配送/1采购自提）
             * 决定托运数据是否展示
             *
             */
            /**销售订单-供应配送的才能看*/
            /**采购订单-采方自提的才能看*/
            boolean flag = false;
            if (String.valueOf(NumberConstant.ZERO).equals(orderDetailRes.getPickupType())) {
                flag = true;
            }
            List<LogisticsOrderDto> list = new ArrayList<>();
            if (flag) {
                /**数据展示*/
                list = kwtLogisticsOrderMapper.selectOrderListNotPage(id, type);
                /**计量单位*/
                Map<String, String> unitTypeDictData = commonService.getDictData(DictTypeEnum.UNIT_TYPE.getType());
                /**运价方式*/
                Map<String, String> priceDictData = commonService.getDictData(DictTypeEnum.PRICE_TYPE.getType());
                /**合理损耗*/
                Map<String, String> taxRateTypeDictData = commonService.getDictData(DictTypeEnum.TAX_RATE_TYPE.getType());
                if (CollectionUtils.isNotEmpty(list)) {
                    for (LogisticsOrderDto logisticsOrderDTO : list) {
                        logisticsOrderDTO.setStatusLabel(LogisticsOrderEnum.getDestination(logisticsOrderDTO.getStatus()));
                        String createName = StringUtils.isBlank(logisticsOrderDTO.getCreateBy()) ? null :
                                (remoteSystemService.queryUserCacheById(Long.parseLong(logisticsOrderDTO.getCreateBy())) == null ? null :
                                        remoteSystemService.queryUserCacheById(Long.parseLong(logisticsOrderDTO.getCreateBy())).getName());
                        logisticsOrderDTO.setCreateName(createName);
                        logisticsOrderDTO.setPriceLabel(priceDictData.get(logisticsOrderDTO.getPriceType()));
                        logisticsOrderDTO.setLossUnitLabel(taxRateTypeDictData.get(logisticsOrderDTO.getLossUnit()));
                        logisticsOrderDTO.setGoodsPriceUnitLabel(priceDictData.get(logisticsOrderDTO.getGoodsPriceUnit()));
                        logisticsOrderDTO.setUnitLabel(unitTypeDictData.get(logisticsOrderDTO.getUnit()));
                    }
                    returnList.addAll(list);
                }
            }
        }
        /**基于多个传递数据查询->手动分页*/
        List<LogisticsOrderDto> subList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(returnList)) {
            subList = returnList.stream().skip((page - 1) * pageSize).limit(pageSize).collect(Collectors.toList());
        }

        PageResult build = PageResult.build(page, pageSize, returnList.stream().count(), subList);
        return HttpResult.ok(build);
    }

    /**
     * 贸易订单或者物流订单分页优化代码
     *
     * @param stringList 贸易订单id集合
     * @param page       分页数据
     * @param pageSize   分页条数
     * @param type       数据类型 1 采购2销售
     * @return
     */
    public PageRes<LogisticsOrderDto> getLogisticsOrderListByTradeOrderIds(List<String> stringList, Integer page, Integer pageSize, String type) {
        PageHelper.startPage(page, pageSize);
        List<Long> returnIds = new ArrayList<>();
        for (String id : stringList) {
            OrderDetailRes orderDetailRes = tradeOrderInfoService.getOrderDetailById(Long.parseLong(id));
            if (orderDetailRes == null) {
                continue;
            }
            /**
             * 0销售展示是供应配送  1采购展示是采购自提
             * 根据提货方式（0供应配送/1采购自提）
             * 决定托运数据是否展示
             *
             */
            /**销售订单-供应配送的才能看*/
            /**采购订单-采方自提的才能看*/
            boolean flag = false;
            if (String.valueOf(NumberConstant.ZERO).equals(orderDetailRes.getPickupType())) {
                flag = true;
                returnIds.add(Long.parseLong(id));
            }
        }
        List<LogisticsOrderDto> orderDTOList = kwtLogisticsOrderMapper.selectOrderListNotPageByIds(returnIds, type);
        PageInfo<LogisticsOrderDto> info = new PageInfo<>(orderDTOList);
        if (CollectionUtils.isEmpty(orderDTOList)) {
            PageRes<LogisticsOrderDto> pageRes = new PageRes<>();
            pageRes.setPage(page);
            pageRes.setPageSize(pageSize);
            return pageRes;
        }
        /**计量单位*/
        Map<String, String> unitTypeDictData = commonService.getDictData(DictTypeEnum.UNIT_TYPE.getType());
        /**运价方式*/
        Map<String, String> priceDictData = commonService.getDictData(DictTypeEnum.PRICE_TYPE.getType());
        /**合理损耗*/
        Map<String, String> taxRateTypeDictData = commonService.getDictData(DictTypeEnum.TAX_RATE_TYPE.getType());
        for (LogisticsOrderDto logisticsOrderDTO : orderDTOList) {
            logisticsOrderDTO.setStatusLabel(LogisticsOrderEnum.getDestination(logisticsOrderDTO.getStatus()));
            String createName = StringUtils.isBlank(logisticsOrderDTO.getCreateBy()) ? null :
                    (remoteSystemService.queryUserCacheById(Long.parseLong(logisticsOrderDTO.getCreateBy())) == null ? null :
                            remoteSystemService.queryUserCacheById(Long.parseLong(logisticsOrderDTO.getCreateBy())).getName());
            logisticsOrderDTO.setCreateName(createName);
            logisticsOrderDTO.setPriceLabel(priceDictData.get(logisticsOrderDTO.getPriceType()));
            logisticsOrderDTO.setLossUnitLabel(taxRateTypeDictData.get(logisticsOrderDTO.getLossUnit()));
            logisticsOrderDTO.setGoodsPriceUnitLabel(priceDictData.get(logisticsOrderDTO.getGoodsPriceUnit()));
            logisticsOrderDTO.setUnitLabel(unitTypeDictData.get(logisticsOrderDTO.getUnit()));
        }
        return PageRes.build(info, orderDTOList);
    }

    /**
     * 采购订单/销售订单-托运订单列表-下方数据统计
     *
     * @param id   贸易订单id
     * @param type 采购1 销售2
     * @return
     */
    public HttpResult logisticsOrderCount(String id, String type) {
        OrderDetailRes orderDetailRes = tradeOrderInfoService.getOrderDetailById(Long.parseLong(id));
        if (orderDetailRes == null) {
            return HttpResult.ok();
        }
        /**根据下单方式（代客下单/自主下单）决定托运数据是否展示*/
        boolean flag = false;
        if (String.valueOf(NumberConstant.ONE).equals(orderDetailRes.getSource())) {
            flag = true;
        } else if (String.valueOf(NumberConstant.TWO).equals(orderDetailRes.getSource())) {
            flag = true;
        } else {
            throw new RuntimeException("获取贸易订单下单方式异常!");
        }
        BigDecimal resAmount = orderDetailRes.getAmount();
        List<LogisticsOrderDto> list = new ArrayList<>();
        JSONObject jsonObject = new JSONObject();
        //总数
        Long count = 0L;
        //计划量
        BigDecimal amount = NumberConstant.ZERO_TWO;
        //剩余调度量
        BigDecimal residue = NumberConstant.ZERO_TWO;
        if (flag) {
            count = getLogisticsOrderCount(id, type);
            list = kwtLogisticsOrderMapper.selectOrderCountByOrderId(id, type);
            /**数据统计*/
            for (LogisticsOrderDto logisticsOrderDTO : list) {
                amount = amount.add(logisticsOrderDTO.getAmount() == null ? NumberConstant.ZERO_TWO : logisticsOrderDTO.getAmount());
            }
            residue = resAmount.subtract(amount);
        }
        jsonObject.put("count", count);
        jsonObject.put("residue", residue);
        jsonObject.put("amount", amount);
        return HttpResult.ok(jsonObject);
    }

    /**
     * 采购订单-获取托运订单数据
     *
     * @param ids      销售订单id
     * @param page     当前页
     * @param pageSize 每页条数
     * @param type     属于采购（1）还是销售（2）
     * @return
     */
    private HttpResult logisticsOrderList(String ids, Integer page, Integer pageSize, String type) {
        List<String> stringList = StringUtils.splitStrToList(ids, String.class);
        if (CollectionUtils.isEmpty(stringList)) {
            return HttpResult.ok();
        }
        stringList = stringList.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
        List<LogisticsOrderDto> returnList = new ArrayList<>();
        for (String id : stringList) {
            OrderDetailRes orderDetailRes = tradeOrderInfoService.getOrderDetailById(Long.parseLong(id));
            if (orderDetailRes == null) {
                continue;
            }
            log.info("贸易订单数据:{}", JSONObject.toJSONString(orderDetailRes));
            log.info("贸易订单数据类型:{}", orderDetailRes.getPickupType());
            /**
             * 0销售展示是供应配送  1采购展示是采购自提
             * 根据提货方式（0供应配送/1采购自提）
             * 决定托运数据是否展示
             *
             */
            /**销售订单-供应配送的才能看*/
            /**采购订单-采方自提的才能看*/
            boolean flag = false;
            if (String.valueOf(NumberConstant.ONE).equals(orderDetailRes.getPickupType())) {
                flag = true;
            }
            List<LogisticsOrderDto> list = new ArrayList<>();
            if (flag) {
                /**数据展示*/
                list = kwtLogisticsOrderMapper.selectOrderListNotPage(id, "2");
                /**计量单位*/
                Map<String, String> unitTypeDictData = commonService.getDictData(DictTypeEnum.UNIT_TYPE.getType());
                /**运价方式*/
                Map<String, String> priceDictData = commonService.getDictData(DictTypeEnum.PRICE_TYPE.getType());
                /**合理损耗*/
                Map<String, String> taxRateTypeDictData = commonService.getDictData(DictTypeEnum.TAX_RATE_TYPE.getType());
                if (CollectionUtils.isNotEmpty(list)) {
                    for (LogisticsOrderDto logisticsOrderDTO : list) {
                        logisticsOrderDTO.setStatusLabel(LogisticsOrderEnum.getDestination(logisticsOrderDTO.getStatus()));
                        String createName = StringUtils.isBlank(logisticsOrderDTO.getCreateBy()) ? null :
                                (remoteSystemService.queryUserCacheById(Long.parseLong(logisticsOrderDTO.getCreateBy())) == null ? null :
                                        remoteSystemService.queryUserCacheById(Long.parseLong(logisticsOrderDTO.getCreateBy())).getName());
                        logisticsOrderDTO.setCreateName(createName);
                        logisticsOrderDTO.setPriceLabel(priceDictData.get(logisticsOrderDTO.getPriceType()));
                        logisticsOrderDTO.setLossUnitLabel(taxRateTypeDictData.get(logisticsOrderDTO.getLossUnit()));
                        logisticsOrderDTO.setGoodsPriceUnitLabel(priceDictData.get(logisticsOrderDTO.getGoodsPriceUnit()));
                        logisticsOrderDTO.setUnitLabel(unitTypeDictData.get(logisticsOrderDTO.getUnit()));
                    }
                    returnList.addAll(list);
                }
            }
        }
        List<LogisticsOrderDto> subList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(returnList)) {
            subList = returnList.stream().skip((page - 1) * pageSize).limit(pageSize).collect(Collectors.toList());
        }
        PageResult build = PageResult.build(page, pageSize, returnList.stream().count(), subList);
        return HttpResult.ok(build);
    }

    /**
     * @param id       贸易订单id
     * @param page     当前页
     * @param pageSize 每页条数
     * @param type     采购订单1/销售订单2
     * @return 物流订单实体
     */
    private List<LogisticsOrderDto> getLogisticsOrderData(String id, Integer page, Integer pageSize, String type) {
        List<LogisticsOrderDto> list = kwtLogisticsOrderMapper.selectOrderList(id, page, pageSize, type);
        return list;
    }

    /**
     * 销售订单-车辆列表-销售订单id
     *
     * @param ids
     * @param page
     * @param pageSize
     * @return
     */
    public HttpResult sellLogisticsCar(String ids, Integer page, Integer pageSize) {
        List<Long> stringList = StringUtils.splitStrToList(ids, Long.class);
        if (CollectionUtils.isEmpty(stringList)) {
            return HttpResult.ok();
        }

        Map<String, Object> params = new HashMap<>();
        params.put("tOrderIds", stringList);
        params.put("page", page);
        params.put("pageSize", pageSize);
        PageHelper.startPage(PageResult.getPage(params), PageResult.getPageSize(params));
        List<OrderCarDTO> list = waybillOrderV1Mapper.selectWaybillOrderCarPage(params);
        if (CollectionUtils.isNotEmpty(list)) {
            List<String> collect = list.stream().map(OrderCarDTO::getTruckNo).collect(Collectors.toList());
            Map<String, RTruckVo> truck = remoteFleetService.findTruck(collect);
            for (OrderCarDTO orderCarDTO : list) {
                orderCarDTO.setStatusLabel(CarWaybillEnum.getName(orderCarDTO.getStatus()));
                orderCarDTO.setLoadAmount(truck.get(orderCarDTO.getTruckNo()) == null ?
                        null : (truck.get(orderCarDTO.getTruckNo()).getActualWeight() == null ?
                        null : (String.valueOf(truck.get(orderCarDTO.getTruckNo()).getActualWeight()))));
            }
        }
        PageResult pageResult = PageHelperUtil.getPageResult(new PageInfo<>(list));
        return HttpResult.ok(pageResult);
    }

    private Long getLogisticsCarDataCount(String id) {
        return waybillOrderMapper.selectWaybillOrderCarCount(id);
    }

    private List<OrderCarDTO> getLogisticsCarData(String id, Integer page, Integer pageSize) {
        List<OrderCarDTO> list = waybillOrderMapper.selectWaybillOrderCarList(id, page, pageSize);
        List<String> stringList = list.stream().map(OrderCarDTO::getTruckNo).collect(Collectors.toList());
        Map<String, RTruckVo> truck = remoteFleetService.findTruck(stringList);
        for (OrderCarDTO orderCarDTO : list) {
            orderCarDTO.setLoadAmount(truck.get(orderCarDTO.getTruckNo()) == null ?
                    null : (truck.get(orderCarDTO.getTruckNo()).getActualWeight() == null ?
                    null : (String.valueOf(truck.get(orderCarDTO.getTruckNo()).getActualWeight()))));
        }
        return list;
    }

    /**
     * 采购订单/销售订单-托运订单列表-撤销托运
     *
     * @param ids    物流订单id
     * @param remark 备注
     * @param type   单据操作类型
     * @return
     */
//    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional
    public HttpResult cancelConsign(List<String> ids, String remark, String type) {
        if (CollectionUtils.isEmpty(ids) || ids.size() < NumberConstant.ONE) {
            throw new BusinessException("单据id不能为空");
        }
        HttpResult result = new HttpResult();
        String key = String.format(RedisConstant.LOGISTICS_ORDER_CANCEL_KEY, ids.toString());
        if (redisLockUtil.tryLock(key)) {
            try {
                //1采购 2销售
                if (String.valueOf(NumberConstant.ONE).equals(type)) {
                    result = cancelConsignByOrder(ids, remark);
                } else if (String.valueOf(NumberConstant.TWO).equals(type)) {
                    result = cancelConsignBySellOrder(ids, remark);
                } else {
                    throw new BusinessException("类型错误!");
                }
            } finally {
                redisLockUtil.unlock(key);
            }
        } else {
            return HttpResult.error("当前数据不可重复操作,稍后请重试");
        }
        return result;
    }

    /**
     * 销售订单撤销托运
     *
     * @param ids
     */
    public HttpResult cancelConsignBySellOrder(List<String> ids, String remark) {
        HttpResult result = new HttpResult();
        String s = ids.get(0);
        /**当前单据作废
         * 托运数量回归溯
         */
        KwtLogisticsOrder kwtLogisticsOrder = kwtLogisticsOrderMapper.selectOne(new LambdaUpdateWrapper<KwtLogisticsOrder>()
                .eq(KwtLogisticsOrder::getId, s));
        if (kwtLogisticsOrder == null || (!LogisticsOrderEnum.PENDING_ORDER.getStatus().equals(String.valueOf(kwtLogisticsOrder.getStatus())))) {
            log.info("物流订单单据id:{}", s);
            result.setMsg("单据状态异常或单据不存在");
            result.setCode(HttpStatus.GLOBAL_EXCEPTION_CODE);
            return result;
        } else {
            /**撤退推送接口数据溯源修改贸易订单已委托量*/
            /*CreateOrCancelLogisticsOrderParam param = new CreateOrCancelLogisticsOrderParam();
            param.setTOrderId(kwtLogisticsOrder.getTOrderId());
            param.setEntrustAmount(kwtLogisticsOrder.getAmount().negate());
            param.setUpdateBy(LoginUserHolder.getUserId());
            param.setUpdateByName(LoginUserHolder.getUserName());
            HttpResult httpResult = tradeOrderInfoService.createOrCancelLogisticsOrder(param);*/
            List<GoodsLoadingParam> goodsLoading = logisticsOrderGoodsService.goodsLoadingParams(kwtLogisticsOrder, false);
//            HttpResult httpResult = tradeOrderInfoService.createOrCancelLogisticsOrderV1(kwtLogisticsOrder.getTOrderId(), goodsLoading);
            HttpResult httpResult = tradeOrderInfoService.createOrCancelLogisticsOrderV1(LoginUserHolder.getUserId(), LoginUserHolder.getUserName(), kwtLogisticsOrder.getTOrderId(), goodsLoading);
            log.info("销售订单撤销托运-溯源贸易订单请求数据:{}[],返回数据:{}", kwtLogisticsOrder.getTOrderId(), JSONObject.toJSONString(goodsLoading), JSONObject.toJSONString(httpResult));
            if (HttpStatus.SUCCESS_CODE == httpResult.getCode()) {

                Long logisticsOrderId = Long.parseLong(s);
                List<LogisticsOrderCancelAmountVo> logisticsOrderCancelAmountVos = logisticsOrderAmountMapper.cancelOrderToAmountByOrderId(logisticsOrderId, NumberConstant.ONE);
                if (CollectionUtils.isNotEmpty(logisticsOrderCancelAmountVos)) {
                    logisticsOrderCancelAmountVos.forEach(cancelAmountVos -> {
                        Long tOrderId = cancelAmountVos.getTOrderId();
                        Long tOrderAddressId = cancelAmountVos.getTOrderAddressId();
                        UpdateAddressEntrustAmountParam param = new UpdateAddressEntrustAmountParam();
                        param.setTOrderId(tOrderId);
                        param.setTAddressId(tOrderAddressId);
                        param.setEntrustAmount(cancelAmountVos.getAmount().negate());
                        param.setUpdateBy(LoginUserHolder.getUserId());
                        param.setUpdateByName(LoginUserHolder.getUserName());
                        HttpResult httpResult1 = tradeOrderAmountService.updateAddressEntrustAmount(param);
                        if (HttpStatus.SUCCESS_CODE != httpResult1.getCode()) {
                            log.info("销售订单-撤销托运还原地址的分配量错误:,请求参数:{},{},响应信息:{}",
                                    kwtLogisticsOrder.getTOrderId(), JSONObject.toJSONString(param), JSONObject.toJSONString(httpResult1));
                            throw new BusinessException("销售订单-撤销托运还原地址的分配量错误:" + httpResult1.getMsg());
                        }
                    });
                }

//                    kwtLogisticsOrder.setDelFlag(NumberConstant.ONE);
                kwtLogisticsOrder.setUpdateTime(new Date());
                kwtLogisticsOrder.setUpdateBy(LoginUserHolder.getUserId());
                kwtLogisticsOrderMapper.update(null, new LambdaUpdateWrapper<KwtLogisticsOrder>()
                        .eq(KwtLogisticsOrder::getId, kwtLogisticsOrder.getId())
                        .set(KwtLogisticsOrder::getStatus, LogisticsOrderEnum.CANCEL_ORDER.getCode())
                        .set(KwtLogisticsOrder::getUpdateBy, LoginUserHolder.getUserId())
                        .set(KwtLogisticsOrder::getUpdateTime, new Date()));
                KwtLogisticsOrderTrack orderTrack = kwtLogisticsOrderTrackMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrderTrack>()
                        .eq(KwtLogisticsOrderTrack::getLOrderId, s)
                        .eq(KwtLogisticsOrderTrack::getStatus, LogisticsOrderEnum.CANCEL_ORDER.getCode())
                );
                if (orderTrack == null) {
                    KwtLogisticsOrderTrack track = new KwtLogisticsOrderTrack();
                    track.setId(new IdWorker(NumberConstant.ONE).nextId());
                    track.setLOrderId(Long.valueOf(s));
                    track.setRemark(remark);
                    track.setStatus(LogisticsOrderEnum.CANCEL_ORDER.getCode());
                    track.setCreateBy(LoginUserHolder.getUserId());
                    track.setCreateTime(new Date());
                    track.setUpdateBy(LoginUserHolder.getUserId());
                    track.setUpdateTime(new Date());
                    kwtLogisticsOrderTrackMapper.insert(track);
                } else {
                    orderTrack.setRemark(remark);
                    orderTrack.setStatus(LogisticsOrderEnum.CANCEL_ORDER.getCode());
                    orderTrack.setUpdateBy(LoginUserHolder.getUserId());
                    orderTrack.setUpdateTime(new Date());
                    kwtLogisticsOrderTrackMapper.updateById(orderTrack);
                }
                //mongoDb数据
                SckwLogisticsOrder logisticsOrder = new SckwLogisticsOrder();
                logisticsOrder.set_id(Long.valueOf(s));
                logisticsOrder.setLOrderId(Long.valueOf(s));
                logisticsOrder.setStatus(LogisticsOrderEnum.CANCEL_ORDER.getStatus());
                logisticsOrder.setUpdateByName(LoginUserHolder.getUserName());
                logisticsOrder.setUpdateBy(LoginUserHolder.getUserId());
                logisticsOrder.setUpdateTime(new Date());
                SckwBusSum sckwBusSum = new SckwBusSum();
                sckwBusSum.setBusSumType(BusinessTypeEnum.LOGISTICS_ORDER_TYPE.getName());
                sckwBusSum.setMethod(NumberConstant.TWO);
                sckwBusSum.setObject(logisticsOrder);
                streamBridge.send("sckw-busSum", JSON.toJSONString(sckwBusSum));
                result.setMsg("操作成功");
                result.setCode(HttpStatus.SUCCESS_CODE);

                /**消息列表发送*/
                //托运
                KwtLogisticsOrderUnit consignUnit = kwtLogisticsOrderUnitMapper.selectOne(
                        new LambdaQueryWrapper<KwtLogisticsOrderUnit>()
                                .eq(KwtLogisticsOrderUnit::getLOrderId, kwtLogisticsOrder.getId())
                                .eq(KwtLogisticsOrderUnit::getUnitType, NumberConstant.ONE));
                //承运
                KwtLogisticsOrderUnit carriageUnit = kwtLogisticsOrderUnitMapper.selectOne(
                        new LambdaQueryWrapper<KwtLogisticsOrderUnit>()
                                .eq(KwtLogisticsOrderUnit::getLOrderId, kwtLogisticsOrder.getId())
                                .eq(KwtLogisticsOrderUnit::getUnitType, NumberConstant.TWO));
//                commonService.cancelLogisticsConsignment(consignUnit, carriageUnit, kwtLogisticsOrder.getLOrderNo(), kwtLogisticsOrder.getCreateBy(),
//                        kwtLogisticsOrder.getEntId(), MessageEnum.CANCELLATION_LOGISTICS, MessageEnum.CARRIAGE_CANCELLATION_LOGISTICS);
                commonService.newSendLogisticsOrderToMessage(consignUnit, carriageUnit, kwtLogisticsOrder.getLOrderNo(), kwtLogisticsOrder.getCreateBy(),
                        kwtLogisticsOrder.getEntId(),
                        messageUrlConfig.getPc().getConsignLogisticsAddOrderUrl(), messageUrlConfig.getApp().getConsignLogisticsAddOrderUrl(),
                        messageUrlConfig.getPc().getCarriageLogisticsAddOrderUrl(), messageUrlConfig.getApp().getCarriageLogisticsAddOrderUrl(),
                        MessageEnum.CANCELLATION_LOGISTICS, MessageEnum.CARRIAGE_CANCELLATION_LOGISTICS,
                        "1");
            } else {
                result.setMsg("操作失败:" + httpResult.getMsg());
                result.setCode(HttpStatus.GLOBAL_EXCEPTION_CODE);
            }
        }
        return result;
    }

    /**
     * 采购订单撤销托运
     *
     * @param ids
     */
    public HttpResult cancelConsignByOrder(List<String> ids, String remark) {
        HttpResult result = new HttpResult();
        String id = ids.get(0);
        /**当前单据作废
         * 托运数量回归溯
         */
        KwtLogisticsOrder kwtLogisticsOrder = kwtLogisticsOrderMapper.selectOne(new LambdaUpdateWrapper<KwtLogisticsOrder>()
                .eq(KwtLogisticsOrder::getId, Long.parseLong(id)));
        if (kwtLogisticsOrder == null || (!LogisticsOrderEnum.PENDING_ORDER.getStatus().equals(String.valueOf(kwtLogisticsOrder.getStatus())))) {
            log.info("物流订单单据id:{}", id);
            result.setCode(HttpStatus.GLOBAL_EXCEPTION_CODE);
            result.setMsg("单据状态异常或单据不存在");
            return result;
        } else {
            /**撤退推送接口数据溯源修改贸易订单已委托量*/
            /*CreateOrCancelLogisticsOrderParam param = new CreateOrCancelLogisticsOrderParam();
            param.setTOrderId(kwtLogisticsOrder.getTOrderId());
            param.setEntrustAmount(kwtLogisticsOrder.getAmount().negate());
            param.setUpdateBy(LoginUserHolder.getUserId());
            param.setUpdateByName(LoginUserHolder.getUserName());
            HttpResult httpResult = tradeOrderInfoService.createOrCancelLogisticsOrder(param);*/
            List<GoodsLoadingParam> goodsLoading = logisticsOrderGoodsService.goodsLoadingParams(kwtLogisticsOrder, false);
//            HttpResult httpResult = tradeOrderInfoService.createOrCancelLogisticsOrderV1(kwtLogisticsOrder.getTOrderId(), goodsLoading);
            HttpResult httpResult = tradeOrderInfoService.createOrCancelLogisticsOrderV1(LoginUserHolder.getUserId(), LoginUserHolder.getUserName(), kwtLogisticsOrder.getTOrderId(), goodsLoading);
            log.info("采购订单撤销托运-溯源贸易订单请求数据:{}[],返回数据:{}", kwtLogisticsOrder.getTOrderId(), JSONObject.toJSONString(goodsLoading), JSONObject.toJSONString(httpResult));
            if (HttpStatus.SUCCESS_CODE == httpResult.getCode()) {

                Long logisticsOrderId = Long.parseLong(id);
                List<LogisticsOrderCancelAmountVo> logisticsOrderCancelAmountVos = logisticsOrderAmountMapper.cancelOrderToAmountByOrderId(logisticsOrderId, NumberConstant.ONE);
                if (CollectionUtils.isNotEmpty(logisticsOrderCancelAmountVos)) {
                    logisticsOrderCancelAmountVos.forEach(cancelAmountVos -> {
                        Long tOrderId = cancelAmountVos.getTOrderId();
                        Long tOrderAddressId = cancelAmountVos.getTOrderAddressId();
                        UpdateAddressEntrustAmountParam param = new UpdateAddressEntrustAmountParam();
                        param.setTOrderId(tOrderId);
                        param.setTAddressId(tOrderAddressId);
                        param.setEntrustAmount(cancelAmountVos.getAmount().negate());
                        param.setUpdateBy(LoginUserHolder.getUserId());
                        param.setUpdateByName(LoginUserHolder.getUserName());
                        HttpResult httpResult1 = tradeOrderAmountService.updateAddressEntrustAmount(param);
                        if (HttpStatus.SUCCESS_CODE != httpResult1.getCode()) {
                            log.info("贸易订单-撤销托运还原地址的分配量错误:,请求参数:{},{},响应信息:{}",
                                    kwtLogisticsOrder.getTOrderId(), JSONObject.toJSONString(param), JSONObject.toJSONString(httpResult1));
                            throw new BusinessException("贸易订单-撤销托运还原地址的分配量错误:" + httpResult1.getMsg());
                        }
                    });
                }
//                    kwtLogisticsOrder.setDelFlag(NumberConstant.ONE);
//                    kwtLogisticsOrder.setUpdateTime(new Date());
//                    kwtLogisticsOrder.setUpdateBy(LoginUserHolder.getUserId());
                kwtLogisticsOrderMapper.update(null, new LambdaUpdateWrapper<KwtLogisticsOrder>()
                        .eq(KwtLogisticsOrder::getId, kwtLogisticsOrder.getId())
                        .set(KwtLogisticsOrder::getStatus, LogisticsOrderEnum.CANCEL_ORDER.getCode())
                        .set(KwtLogisticsOrder::getUpdateBy, LoginUserHolder.getUserId())
                        .set(KwtLogisticsOrder::getUpdateTime, new Date()));
                KwtLogisticsOrderTrack orderTrack = kwtLogisticsOrderTrackMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrderTrack>()
                        .eq(KwtLogisticsOrderTrack::getLOrderId, id)
                        .eq(KwtLogisticsOrderTrack::getStatus, LogisticsOrderEnum.CANCEL_ORDER.getCode())
                );
                if (orderTrack == null) {
                    KwtLogisticsOrderTrack track = new KwtLogisticsOrderTrack();
                    track.setId(new IdWorker(NumberConstant.ONE).nextId());
                    track.setLOrderId(Long.valueOf(id));
                    track.setRemark(remark);
                    track.setStatus(LogisticsOrderEnum.CANCEL_ORDER.getCode());
                    track.setCreateBy(LoginUserHolder.getUserId());
                    track.setCreateTime(new Date());
                    track.setUpdateBy(LoginUserHolder.getUserId());
                    track.setUpdateTime(new Date());
                    kwtLogisticsOrderTrackMapper.insert(track);
                } else {
                    orderTrack.setRemark(remark);
                    orderTrack.setStatus(LogisticsOrderEnum.CANCEL_ORDER.getCode());
                    orderTrack.setUpdateBy(LoginUserHolder.getUserId());
                    orderTrack.setUpdateTime(new Date());
                    kwtLogisticsOrderTrackMapper.updateById(orderTrack);
                }
                //mongoDb数据
                SckwLogisticsOrder logisticsOrder = new SckwLogisticsOrder();
                logisticsOrder.set_id(Long.valueOf(id));
                logisticsOrder.setLOrderId(Long.valueOf(id));
                logisticsOrder.setStatus(LogisticsOrderEnum.CANCEL_ORDER.getStatus());
                logisticsOrder.setUpdateByName(LoginUserHolder.getUserName());
                logisticsOrder.setUpdateBy(LoginUserHolder.getUserId());
                logisticsOrder.setUpdateTime(new Date());
                SckwBusSum sckwBusSum = new SckwBusSum();
                sckwBusSum.setBusSumType(BusinessTypeEnum.LOGISTICS_ORDER_TYPE.getName());
                sckwBusSum.setMethod(NumberConstant.TWO);
                sckwBusSum.setObject(logisticsOrder);
                streamBridge.send("sckw-busSum", JSON.toJSONString(sckwBusSum));
                result.setCode(HttpStatus.SUCCESS_CODE);

                /**消息列表发送*/
                //托运
                KwtLogisticsOrderUnit consignUnit = kwtLogisticsOrderUnitMapper.selectOne(
                        new LambdaQueryWrapper<KwtLogisticsOrderUnit>()
                                .eq(KwtLogisticsOrderUnit::getLOrderId, id)
                                .eq(KwtLogisticsOrderUnit::getUnitType, NumberConstant.ONE));
                //承运
                KwtLogisticsOrderUnit carriageUnit = kwtLogisticsOrderUnitMapper.selectOne(
                        new LambdaQueryWrapper<KwtLogisticsOrderUnit>()
                                .eq(KwtLogisticsOrderUnit::getLOrderId, id)
                                .eq(KwtLogisticsOrderUnit::getUnitType, NumberConstant.TWO));
//                commonService.cancelLogisticsConsignment(consignUnit, carriageUnit, kwtLogisticsOrder.getLOrderNo(), kwtLogisticsOrder.getCreateBy(),
//                        kwtLogisticsOrder.getEntId(), MessageEnum.CANCELLATION_LOGISTICS, MessageEnum.CARRIAGE_CANCELLATION_LOGISTICS);
                commonService.newSendLogisticsOrderToMessage(consignUnit, carriageUnit, kwtLogisticsOrder.getLOrderNo(), kwtLogisticsOrder.getCreateBy(),
                        kwtLogisticsOrder.getEntId(),
                        messageUrlConfig.getPc().getConsignLogisticsAddOrderUrl(), messageUrlConfig.getApp().getConsignLogisticsAddOrderUrl(),
                        messageUrlConfig.getPc().getCarriageLogisticsAddOrderUrl(), messageUrlConfig.getApp().getCarriageLogisticsAddOrderUrl(),
                        MessageEnum.CANCELLATION_LOGISTICS, MessageEnum.CARRIAGE_CANCELLATION_LOGISTICS, "1");
            } else {
                result.setCode(HttpStatus.GLOBAL_EXCEPTION_CODE);
                result.setMsg("操作失败:" + httpResult.getMsg());
            }
        }
        return result;
    }

    /**
     * 采购订单/销售订单-完结订单
     *
     * @param orderFinishDTO 数据dto
     * @param type           类型
     * @return
     */
//    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional()
    public HttpResult orderFinish(OrderFinishDTO orderFinishDTO, String type) {
        HttpResult httpResult = ValidUtil.serviceValid(orderFinishDTO);
        if (!String.valueOf(httpResult.getCode()).equals(String.valueOf(HttpStatus.SUCCESS_CODE))) {
            return HttpResult.error(httpResult.getMsg());
        }
        String key = String.format(RedisConstant.LOGISTICS_ORDER_FINISH_KEY, orderFinishDTO.getId());
        if (redisLockUtil.tryLock(key)) {
            try {
                //1采购 2销售
                if (String.valueOf(NumberConstant.ONE).equals(type)) {
                    purchaseOrderFinish(orderFinishDTO);
                } else if (String.valueOf(NumberConstant.TWO).equals(type)) {
                    sellOrderFinish(orderFinishDTO);
                } else {
                    throw new RuntimeException("完结订单-单据类型异常!");
                }
            } finally {
                redisLockUtil.unlock(key);
            }
        } else {
            return HttpResult.error("当前数据不可重复操作");
        }
        return HttpResult.ok("完结订单-成功");
    }

    /**
     * 销售订单-完结订单
     *
     * @param orderFinishDTO
     */
    private void sellOrderFinish(OrderFinishDTO orderFinishDTO) {
        purchaseOrderFinish(orderFinishDTO);
    }

    /**
     * 采购订单-完结订单
     *
     * @param orderFinishDTO
     */
    public void purchaseOrderFinish(OrderFinishDTO orderFinishDTO) {
        /** 订单完结 物流运单状态为【待派车】、【运输中】可操作*/
        /**完结拦截 必须车辆运单无正在运输中的单据才能完结 状态有 待接单之后已核弹之前的状态 都不能完结*/
        /**完结订单-对应物流订单下子订单都要进行完结*/
        /**完结订单 不做页面填写数量与数据库数量进行计算验证-直接获取页面填写数据进行保存处理*/
        //物流订单id
        String id = orderFinishDTO.getId();
        KwtLogisticsOrder logisticsOrder = kwtLogisticsOrderMapper.selectById(id);
        if (logisticsOrder == null) {
            throw new BusinessException("采购订单-完结订单-物流单据不存在!");
        }
        //todo 2023-09-01 根据要求去除校验 物流订单手动完结，实装量可大于分配量，实卸量目前暂定不可大于实装量；根据计费方式，当对应实装或实卸大于分配量时自然完结
//        BigDecimal amount = logisticsOrder.getAmount() == null ? NumberConstant.ZERO_TWO : logisticsOrder.getAmount();
//        if (amount.compareTo(orderFinishDTO.getLoadAmount()) < 0) {
//            throw new BusinessException("完结订单,装货量不能大于运输总量");
//        }
//        if (orderFinishDTO.getUnloadAmount().compareTo(orderFinishDTO.getLoadAmount()) > 0) {
//            throw new BusinessException("完结订单,填写卸货量不能大于装货量");
//        }
        /**订单状态验证*/
        if (!LogisticsOrderEnum.WAIT_DELIVERY.getStatus().equals(String.valueOf(logisticsOrder.getStatus()))
                && !LogisticsOrderEnum.IN_TRANSIT.getStatus().equals(String.valueOf(logisticsOrder.getStatus()))) {
            throw new BusinessException("当前订单并不属于【待派车】,【运输中】状态");
        }

        //验证当前物流订单是否还存在进行的车辆运单
        boolean flag = commonService.judgmentWaybillOrderIsFinish(id);
        if (flag) {
            throw new BusinessException("检测您现在有运单正在执行中，该订单目前不可完结，请先将运单执行完毕！");
        }
        //修改单据本身数据
        logisticsOrder.setTotalLoadAmount(orderFinishDTO.getLoadAmount());
        logisticsOrder.setTotalUnloadAmount(orderFinishDTO.getUnloadAmount());
        logisticsOrder.setIgnoreAmount(logisticsOrder.getAmount());
        logisticsOrder.setStatus(LogisticsOrderEnum.HAVE_FINISHED.getCode());
        logisticsOrder.setUpdateTime(new Date());
        logisticsOrder.setUpdateBy(LoginUserHolder.getUserId());
        kwtLogisticsOrderMapper.updateById(logisticsOrder);
        //修改mongodb的数据
        updateMongoDbByLogisticsOrder(logisticsOrder, orderFinishDTO);

        //获取物流订单下的子单
        /**完结订单-对应物流订单下子订单都要进行完结*/
        List<KwtLogisticsOrder> kwtLogisticsOrders = kwtLogisticsOrderMapper.selectList(new LambdaQueryWrapper<KwtLogisticsOrder>()
                .eq(KwtLogisticsOrder::getDelFlag, NumberConstant.ZERO)
                .apply(id != null, "FIND_IN_SET ('" + id + "', pids)").ne(KwtLogisticsOrder::getId, id));
        //找到该订单下所有的物流订单
        if (!org.springframework.util.CollectionUtils.isEmpty(kwtLogisticsOrders)) {
            //修改单据状态
//            List<Long> ids = kwtLogisticsOrders.stream().map(KwtLogisticsOrder::getId).collect(Collectors.toList());
            //修改单据剩余运输量
            kwtLogisticsOrders.forEach(kwtLogisticsOrder -> {
                BigDecimal subtract = kwtLogisticsOrder.getAmount().subtract(kwtLogisticsOrder.getTotalLoadAmount());
                updateLogisticOrderAndTrack(kwtLogisticsOrder.getId(), orderFinishDTO, subtract);
                //修改mongodb的数据
                updateMongoDbByLogisticsOrder(kwtLogisticsOrder, orderFinishDTO);
            });
        }

        //修改合同履约量
        commonService.updatePerformed(logisticsOrder, orderFinishDTO.getLoadAmount(), orderFinishDTO.getUnloadAmount());

        /**数据推送至贸易订单*/
        CompleteLogisticsOrderParam tradeOrder = new CompleteLogisticsOrderParam();
        tradeOrder.setTOrderId(logisticsOrder.getTOrderId());
        tradeOrder.setActualLoadAmount(orderFinishDTO.getLoadAmount());
        tradeOrder.setActualUnloadAmount(orderFinishDTO.getUnloadAmount());
        tradeOrder.setUpdateBy(LoginUserHolder.getUserId());
        tradeOrder.setUpdateByName(LoginUserHolder.getUserName());
        log.info("采购订单手动完结订单请求参数:{}", JSONObject.toJSONString(tradeOrder));
        HttpResult httpResult = tradeOrderInfoService.completeLogisticsOrder(tradeOrder);
        if (httpResult.getCode() != HttpStatus.SUCCESS_CODE) {
            log.info("贸易订单-采购订单/销售订单-手动完结订单异常,传递信息:{},返回信息:{}", JSONObject.toJSONString(tradeOrder), JSONObject.toJSONString(httpResult));
            throw new BusinessException("单据完结出现错误！" + httpResult.getMsg());
        }

        CreateOrCancelLogisticsOrderParam param = new CreateOrCancelLogisticsOrderParam();
        param.setTOrderId(logisticsOrder.getTOrderId());
        param.setEntrustAmount(orderFinishDTO.getLoadAmount().subtract(logisticsOrder.getAmount()));
        param.setUpdateBy(LoginUserHolder.getUserId());
        param.setUpdateByName(LoginUserHolder.getUserName());
        HttpResult result1 = null;//tradeOrderInfoService.createOrCancelLogisticsOrder(param);
        if (result1.getCode() != HttpStatus.SUCCESS_CODE) {
            log.info("采购订单/销售订单完结订单,返回信息:{}", "id:" + logisticsOrder.getTOrderId() + "orderNo" + logisticsOrder.getTOrderNo(), JSONObject.toJSONString(result1));
            throw new BusinessException("{" + logisticsOrder.getTOrderNo() + "} 采购订单/销售订单完结订单失败!" + result1.getMsg());
        }

        transportCommonService.closeHandle(logisticsOrder.getId());
        waybillOrderService.cancelSendCar(logisticsOrder.getId());
        //todo 直接订单完结-不递归操作
//
//        //存在子集
//        if (CollectionUtils.isNotEmpty(kwtLogisticsOrders)) {
//            if (kwtLogisticsOrders.size() == 1 && !(kwtLogisticsOrders.get(0).getPids().contains(StringConstant.COMMA))) {
//                //不存在子集
//                /**
//                 * 验证是否存在进行中的车辆运单
//                 * 统计当前物流订单的 分配量/实装量/实卸量
//                 * 验证当前贸易订单是否存在进行中的物流运单
//                 * */
//                judgmentLogisticsOrderIsFinish(logisticsOrder);
//                //直接修改数据以及状态
//            } else {
//                //分组排序
//                Map<String, List<KwtLogisticsOrder>> collect1 = kwtLogisticsOrders.stream().collect(Collectors.groupingBy(KwtLogisticsOrder::getLevel,
//                        Collectors.collectingAndThen(Collectors.toList(),
//                                logisticsOrders -> logisticsOrders.stream().sorted(Comparator.comparing(KwtLogisticsOrder::getLevel).reversed())
//                                        .collect(Collectors.toList()))
//                ));
//                //查出来最原始的数据
//                List<KwtLogisticsOrder> orderLists = new ArrayList<>();
//                for (List<KwtLogisticsOrder> value : collect1.values()) {
//                    orderLists.addAll(value);
//                }
//                //当前订单下的最大分包等级
//                int maxLevel = kwtLogisticsOrderMapper.selectMaxLevel(id);
//                List<Map<String, Object>> list = new ArrayList<>();
//                for (int level = maxLevel; level > 0; level--) {
//                    if (maxLevel == level) {
//                        List<KwtLogisticsOrder> logisticsOrderList = collect1.get(String.valueOf(level));
//                        //操作最底层数据，溯源父级
//                        for (KwtLogisticsOrder kwtLogisticsOrder : logisticsOrderList) {
//                            BigDecimal entrustAmount = kwtLogisticsOrder.getEntrustAmount();
//                            BigDecimal subcontractAmount = kwtLogisticsOrder.getSubcontractAmount();
//                            BigDecimal amount = kwtLogisticsOrder.getAmount();
//                            BigDecimal loadAmount = kwtLogisticsOrder.getLoadAmount();
//                            BigDecimal unloadAmount = kwtLogisticsOrder.getUnloadAmount();
//                            //已完成的量
//                            BigDecimal subtract = subcontractAmount.add(loadAmount);
//                            //本身数据修改(剩余量=上游给的委托量-（分包量+实际装货）)
//                            //剩余量
//                            BigDecimal ignoreAmount = amount.subtract((subcontractAmount.add(loadAmount)));
//                            kwtLogisticsOrderMapper.update(null, new LambdaUpdateWrapper<KwtLogisticsOrder>()
//                                    .eq(KwtLogisticsOrder::getId, kwtLogisticsOrder.getId())
//                                    .set(KwtLogisticsOrder::getIgnoreAmount, ignoreAmount)
//                            );
//                            //最底下根节点-获取父级
//                            KwtLogisticsOrder selectOne = kwtLogisticsOrderMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrder>()
//                                    .eq(KwtLogisticsOrder::getId, kwtLogisticsOrder.getPid())
//                            );
//                            BigDecimal amount1 = selectOne.getAmount();
//                            BigDecimal loadAmount1 = selectOne.getLoadAmount();
//                            BigDecimal subcontractAmount1 = selectOne.getSubcontractAmount();
//                            BigDecimal ignoreAmount1 = selectOne.getIgnoreAmount();
//                            subcontractAmount1 = subcontractAmount1.subtract(subtract);
//                            ignoreAmount1 = amount1.subtract((subcontractAmount1.add(loadAmount1)));
//                            kwtLogisticsOrderMapper.update(null, new LambdaUpdateWrapper<KwtLogisticsOrder>()
//                                    .eq(KwtLogisticsOrder::getId, selectOne.getId())
//                                    .set(KwtLogisticsOrder::getSubcontractAmount, subcontractAmount1)
//                                    .set(KwtLogisticsOrder::getIgnoreAmount, ignoreAmount1)
//                            );
//                        }
////                    List<KwtLogisticsOrder> collect = logisticsOrderList.stream().filter(item -> StringUtils.isNotBlank(item.getPid())).collect(Collectors.toList());
//                    } else {
//                        //不是一级,也不是最后一级
//                        List<KwtLogisticsOrder> logisticsOrderList = collect1.get(String.valueOf(level));
//                        if (CollectionUtils.isNotEmpty(logisticsOrderList)) {
//                            for (KwtLogisticsOrder kwtLogisticsOrder : logisticsOrderList) {
//                                Map<String, Object> map = new HashMap<>(NumberConstant.SIXTEEN);
//                                List<Object> collect = list.stream().map(item -> item.get("level")).collect(Collectors.toList());
//                                if (!collect.contains(kwtLogisticsOrder.getId())) {
//                                    map.put("level", level);
//                                    map.put("id", kwtLogisticsOrder.getId());
//                                    list.add(map);
//                                }
//
//                            }
//                        }
//                    }
//                }
//                recursionLogisticsOrder(list);
//            }
////
////            List<Long> collect = kwtLogisticsOrders.stream().map(KwtLogisticsOrder::getId).collect(Collectors.toList());
////            //验证 是否存在进行中车辆运单
////            List<KwtLogisticsOrder> kwtLogisticsOrderList = kwtLogisticsOrderMapper.selectList(new LambdaQueryWrapper<KwtLogisticsOrder>().in(KwtLogisticsOrder::getId, collect));
////            if (CollectionUtils.isNotEmpty(kwtLogisticsOrderList)) {
////                judgmentLogisticsOrderIsFinish(logisticsOrder);
////            }
////            // 按照父级ID分组
////            //判断是不是一级(一级的情况下，pid为null 方便处理，赋值为OL)
////            List<KwtLogisticsOrder> list = kwtLogisticsOrders.stream()
////                    .map(object -> {
////                        KwtLogisticsOrder LogisticsOrder = new KwtLogisticsOrder();
////                        BeanUtils.copyProperties(object, LogisticsOrder);
////                        if (LogisticsOrder.getPid() == null) {
////                            LogisticsOrder.setPid(0L);
////                        }
////                        return LogisticsOrder;
////                    })
////                    .collect(Collectors.toList());
////            Map<Long, List<KwtLogisticsOrder>> groupByParentIdMap = list.stream().collect(Collectors.groupingBy(KwtLogisticsOrder::getPid));
////            //存放:对应的当前节点ID数据
////            Set<Long> topToLowerChildIdSet = new HashSet<>();
////            // 取出顶级数据(也就是父级ID为0的数据  父级ID也可以自定义 当前赋值0L)
////            List<KwtLogisticsOrder> topTreeNodes = groupByParentIdMap.get(0L);
////            if (CollectionUtils.isEmpty(topTreeNodes)) {
////                /**当前传输的代表不是一级 可能是二级或者三级
////                 topTreeNodes = groupByParentIdMap.get(Long.parseLong(id));*/
////                getMinimumChildIdArray(groupByParentIdMap, Long.parseLong(id), topToLowerChildIdSet);
////                System.out.println("当前节点【" + id + "】节点下所有的根节点数据集合:" + topToLowerChildIdSet.toString());
////                //根据等级分组倒序排序
////                List<KwtLogisticsOrder> orderList = kwtLogisticsOrderMapper.selectList(new LambdaQueryWrapper<KwtLogisticsOrder>()
////                        .in(KwtLogisticsOrder::getId, topToLowerChildIdSet)
////                );
////
////            } else {
////                for (KwtLogisticsOrder node : topTreeNodes) {
////                    getMinimumChildIdArray(groupByParentIdMap, node.getId(), topToLowerChildIdSet);
////                }
////                System.out.println("0节点(传输为一级)下所有的根节点数据集合:" + topToLowerChildIdSet.toString());
////            }
////            //处理当前传递的id下  全部完结需要改的量
////            BigDecimal decimals = NumberConstant.ZERO_TWO;
////            BigDecimal decimal = judgmentOrderFinish(id, topToLowerChildIdSet, decimals, logisticsOrder);
////            //返回给贸易订单实际装卸货量
////            Map map = countOrderNumber(logisticsOrder.getTOrderId());
////            //修改单据状态
//////            updateLogisticOrderStatus(id,orderFinishDTO);
//        } else {
//            throw new BusinessException("不存在物流订单,不可操作！");
//        }
    }

    /**
     * 根据物流订单修改mongodb数据
     *
     * @param logisticsOrder 物流订单
     * @param orderFinishDTO 完结信息
     */
    private void updateMongoDbByLogisticsOrder(KwtLogisticsOrder logisticsOrder, OrderFinishDTO orderFinishDTO) {
        //更新mongodb
        SckwLogisticsOrder lOrder = new SckwLogisticsOrder();
        lOrder.set_id(logisticsOrder.getId());
        lOrder.setLOrderId(logisticsOrder.getId());
        lOrder.setStatus(LogisticsOrderEnum.HAVE_FINISHED.getStatus());
        lOrder.setUpdateTime(new Date());
        lOrder.setUpdateBy(LoginUserHolder.getUserId());
        lOrder.setUpdateByName(LoginUserHolder.getUserName());
        lOrder.setTotalLoadAmount(orderFinishDTO.getLoadAmount());
        lOrder.setTotalUnloadAmount(orderFinishDTO.getUnloadAmount());
        //rabbitMq业务汇总数据发送/消费对象
        SckwBusSum busSum = new SckwBusSum();
        //业务汇总类型
        busSum.setBusSumType(BusinessTypeEnum.LOGISTICS_ORDER_TYPE.getName());
        //操作对象（1新增/2修改/3替换数据）
        busSum.setMethod(2);
        //业务汇总数据对象
        busSum.setObject(lOrder);
        busSum.setBusSumType(BusinessTypeEnum.LOGISTICS_ORDER_TYPE.getName());
        busSum.setMethod(NumberConstant.TWO);
        streamBridge.send("sckw-busSum", JSON.toJSONString(busSum));
    }

    private void recursionLogisticsOrder(List<Map<String, Object>> list) {
        if (!org.springframework.util.CollectionUtils.isEmpty(list) && list.size() > 0) {
            //倒序排序
//                List<Map<String, Object>> maps = ListUtils.sortMapListByFeild(list, "level", "desc");
            int level = list.stream().mapToInt(m -> (Integer) m.getOrDefault("level", Long.MAX_VALUE)).max().getAsInt();
            List<Long> ids = new ArrayList<>();
            for (int i = level; i > 0; i--) {
                for (Map<String, Object> map : list) {
                    if (CollectionUtils.isEmpty(list)) {
                        continue;
                    }
                    if (String.valueOf(i).equals(String.valueOf(map.get("level")))) {
                        List<KwtLogisticsOrder> orderList = kwtLogisticsOrderMapper.selectList(new LambdaQueryWrapper<KwtLogisticsOrder>()
                                .eq(KwtLogisticsOrder::getId, map.get("id"))
                        );
                        if (CollectionUtils.isNotEmpty(orderList)) {
                            //操作最底层数据，溯源父级
                            for (KwtLogisticsOrder kwtLogisticsOrder : orderList) {
                                BigDecimal entrustAmount = kwtLogisticsOrder.getEntrustAmount();
                                BigDecimal subcontractAmount = kwtLogisticsOrder.getSubcontractAmount();
                                BigDecimal amount = kwtLogisticsOrder.getAmount();
                                BigDecimal loadAmount = kwtLogisticsOrder.getLoadAmount();
                                BigDecimal unloadAmount = kwtLogisticsOrder.getUnloadAmount();
                                //剩余未完成的量
                                BigDecimal subtract = amount.subtract(loadAmount);
                                //最底下根节点-获取父级
                                if (kwtLogisticsOrder.getPid() == null && kwtLogisticsOrder.getPids().equals(String.valueOf(kwtLogisticsOrder.getId()))) {
                                    //代表是一级
                                    //todo 当前不做操作
                                } else {
                                    KwtLogisticsOrder selectOne = kwtLogisticsOrderMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrder>()
                                            .eq(KwtLogisticsOrder::getId, kwtLogisticsOrder.getPid())
                                    );
                                    kwtLogisticsOrderMapper.update(null, new LambdaUpdateWrapper<KwtLogisticsOrder>()
                                            .eq(KwtLogisticsOrder::getId, selectOne.getId())
                                            .set(KwtLogisticsOrder::getEntrustAmount, selectOne.getEntrustAmount().add(subtract))
                                            .set(KwtLogisticsOrder::getSubcontractAmount, selectOne.getSubcontractAmount().subtract(subtract))
                                    );
                                }
                                ids.add(kwtLogisticsOrder.getId());
                            }
                        }
                    } else {
                        if (!ObjectUtils.isEmpty(map.get(String.valueOf(i)))) {
                            List<KwtLogisticsOrder> orderList = kwtLogisticsOrderMapper.selectList(new LambdaQueryWrapper<KwtLogisticsOrder>()
                                    .eq(KwtLogisticsOrder::getId, Long.parseLong((String) map.get("id")))
                            );
                            if (CollectionUtils.isNotEmpty(orderList)) {
                                for (KwtLogisticsOrder kwtLogisticsOrder : orderList) {
                                    Map<String, Object> maps = new HashMap<>(NumberConstant.SIXTEEN);
                                    List<Object> collect = list.stream().map(item -> item.get("level")).collect(Collectors.toList());
                                    if (!collect.contains(kwtLogisticsOrder.getId())) {
                                        maps.put("level", level);
                                        maps.put("id", kwtLogisticsOrder.getId());
                                        list.add(maps);
                                    }
                                }
                            }
                        }
                    }
                }
                Iterator<Map<String, Object>> iterator = list.iterator();
                while (iterator.hasNext()) {
                    Map<String, Object> next = iterator.next();
                    String key = String.valueOf(next.get(("id")));
                    for (Long id : ids) {
                        if (key.equals(String.valueOf(id))) {
                            iterator.remove();
                        }
                    }
                }
            }
            recursionLogisticsOrder(list);
        }
    }


    private Map countOrderNumber(Long tOrderId) {
        Map<String, BigDecimal> map = new HashMap<>(Global.NUMERICAL_SIXTEEN);
        BigDecimal loadAmountTotal = NumberConstant.ZERO_TWO;
        BigDecimal unloadAmountTotal = NumberConstant.ZERO_TWO;
        List<KwtLogisticsOrder> kwtLogisticsOrderList = kwtLogisticsOrderMapper.selectList(new LambdaQueryWrapper<KwtLogisticsOrder>().eq(KwtLogisticsOrder::getTOrderId, tOrderId));
        for (KwtLogisticsOrder kwtLogisticsOrder : kwtLogisticsOrderList) {
            BigDecimal loadAmount = kwtLogisticsOrder.getLoadAmount();
            BigDecimal unloadAmount = kwtLogisticsOrder.getUnloadAmount();
            loadAmountTotal = loadAmountTotal.add(loadAmount);
            unloadAmountTotal = unloadAmountTotal.add(unloadAmount);
        }
        return map;
    }

    /**
     * 处理当前传递的id下  全部完结
     *
     * @param id                   当前完结物流订单传递id
     * @param topToLowerChildIdSet 当前传递的下的最末一级的物流订单主键id
     * @param logisticsOrder       本身物流订单
     */
    private BigDecimal judgmentOrderFinish(String id, Set<Long> topToLowerChildIdSet, BigDecimal amount, KwtLogisticsOrder logisticsOrder) {
        if (CollectionUtils.isNotEmpty(topToLowerChildIdSet)) {
            List<KwtLogisticsOrder> kwtLogisticsOrderList = kwtLogisticsOrderMapper.selectList(new LambdaQueryWrapper<KwtLogisticsOrder>()
                    .in(KwtLogisticsOrder::getId, topToLowerChildIdSet)
            );
            List<KwtLogisticsOrder> logisticsOrders = new ArrayList<>();
            if (CollectionUtils.isNotEmpty(kwtLogisticsOrderList)) {
                for (KwtLogisticsOrder kwtLogisticsOrder : kwtLogisticsOrderList) {
                    BigDecimal entrustAmount = kwtLogisticsOrder.getEntrustAmount();
                    BigDecimal subcontractAmount = kwtLogisticsOrder.getSubcontractAmount();
                    if (subcontractAmount.compareTo(NumberConstant.ZERO_TWO) == 0) {
                        //最底下根节点-获取父级
                        KwtLogisticsOrder selectOne = kwtLogisticsOrderMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrder>()
                                .eq(KwtLogisticsOrder::getId, kwtLogisticsOrder.getPid())
                        );
                        BigDecimal amount1 = kwtLogisticsOrder.getAmount().subtract(entrustAmount.add(subcontractAmount));
                        amount = amount.add(amount1);
                        kwtLogisticsOrderMapper.update(null, new LambdaUpdateWrapper<KwtLogisticsOrder>()
                                .eq(KwtLogisticsOrder::getId, selectOne.getId())
                                .set(KwtLogisticsOrder::getEntrustAmount, selectOne.getEntrustAmount().subtract(kwtLogisticsOrder.getEntrustAmount()))
                                .set(KwtLogisticsOrder::getSubcontractAmount, selectOne.getSubcontractAmount().subtract(kwtLogisticsOrder.getSubcontractAmount()))
                        );
                    } else {
                        logisticsOrders.add(kwtLogisticsOrder);
                    }
                }
            }

        }
        return amount;
    }


    /**
     * 修改物流订单状态，以及状态表新增记录
     *
     * @param lOrderId       物流订单id
     * @param orderFinishDTO 页面请求参数
     * @param ignoreAmount   剩余量
     */
    private void updateLogisticOrderAndTrack(Long lOrderId, OrderFinishDTO orderFinishDTO, BigDecimal ignoreAmount) {
        Integer code = LogisticsOrderEnum.HAVE_FINISHED.getCode();
        kwtLogisticsOrderMapper.update(null, new LambdaUpdateWrapper<KwtLogisticsOrder>()
                .set(KwtLogisticsOrder::getStatus, code)
                .set(KwtLogisticsOrder::getUpdateBy, LoginUserHolder.getUserId())
                .set(KwtLogisticsOrder::getIgnoreAmount, ignoreAmount)
                .set(KwtLogisticsOrder::getUpdateTime, new Date())
                .eq(KwtLogisticsOrder::getId, lOrderId)
        );
        KwtLogisticsOrderTrack track = kwtLogisticsOrderTrackMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrderTrack>()
                .eq(KwtLogisticsOrderTrack::getLOrderId, lOrderId).eq(KwtLogisticsOrderTrack::getStatus, code)
        );
        if (track != null) {
            kwtLogisticsOrderTrackMapper.update(null, new LambdaUpdateWrapper<KwtLogisticsOrderTrack>()
                    .set(KwtLogisticsOrderTrack::getUpdateBy, LoginUserHolder.getUserId())
                    .set(KwtLogisticsOrderTrack::getUpdateTime, new Date())
                    .set(KwtLogisticsOrderTrack::getRemark, orderFinishDTO.getRemark())
                    .eq(KwtLogisticsOrderTrack::getId, track.getId())
            );
        } else {
            KwtLogisticsOrderTrack orderTrack = new KwtLogisticsOrderTrack();
            orderTrack.setId(new IdWorker(NumberConstant.ONE).nextId());
            orderTrack.setLOrderId(lOrderId);
            orderTrack.setRemark(orderFinishDTO.getRemark());
            orderTrack.setStatus(code);
            orderTrack.setCreateBy(LoginUserHolder.getUserId());
            orderTrack.setCreateTime(new Date());
            orderTrack.setUpdateBy(LoginUserHolder.getUserId());
            orderTrack.setUpdateTime(new Date());
            orderTrack.setDelFlag(NumberConstant.ZERO);
            kwtLogisticsOrderTrackMapper.insert(orderTrack);
        }
    }

    /**
     * 根据父级节点获取最低层次 那一级的节点数据
     * 1
     * /   \
     * 2     3
     * / \   / \
     * 4  5  6  7
     * 上面的树形结构调用此方法  根据1 可以获取到  [4 5 6 7]
     * 根据3 可以获得到  [6 7]
     *
     * @param groupByParentIdMap   所有的元素集合(根据父级ID进行了分组) 分组方法可以使用lambda 如下:
     *                             Map<String, List<Person>> peopleByCity = personStream.collect(Collectors.groupingBy(Person::getCity));
     * @param pid                  父级ID
     * @param topToLowerChildIdSet 存储最深根节点的数据集合
     */
    public static Set<Long> getMinimumChildIdArray(Map<Long, List<KwtLogisticsOrder>> groupByParentIdMap,
                                                   Long pid, Set<Long> topToLowerChildIdSet) {
        // 存放当前pid对应的所有根节点ID数据
        Set<Long> currentPidLowerChildIdSet = new HashSet<>();
        // 获取当前pid下所有的子节点
        List<KwtLogisticsOrder> childTreeNodes = groupByParentIdMap.get(pid);
        if (CollUtil.isEmpty(childTreeNodes)) {
            return null;
        }
        for (KwtLogisticsOrder treeNode : childTreeNodes) {
            Set<Long> lowerChildIdSet = getMinimumChildIdArray(groupByParentIdMap, treeNode.getId(), currentPidLowerChildIdSet);
            if (CollUtil.isEmpty(lowerChildIdSet)) {
                // 如果返回null  表示当前遍历的treeNode节点为最底层的节点
                currentPidLowerChildIdSet.add(treeNode.getId());
            }
        }
        System.out.println("当前父级ID：" + pid + "下所有的根节点数据:" + currentPidLowerChildIdSet.toString());
        // 把当前获取到的根节点数据 一并保存到上一个节点父级ID集合中
        topToLowerChildIdSet.addAll(currentPidLowerChildIdSet);
        return currentPidLowerChildIdSet;
    }

    /**
     * 验证当前物流订单是否存在未完结的车辆运单
     *
     * @param id 对应物流订单id
     */
    private boolean judgmentWaybillOrderIsFinish(String id) {
        boolean flag = false;
        List<Integer> statusList = new ArrayList<>();
//        statusList.add(CarWaybillEnum.PENDING_ORDER.getCode());
        statusList.add(CarWaybillEnum.PENDING_VEHICLE.getCode());
        statusList.add(CarWaybillEnum.EXIT_COMPLETED.getCode());
        statusList.add(CarWaybillEnum.WAIT_LOADING.getCode());
        statusList.add(CarWaybillEnum.COMPLETION_LOADING.getCode());
        statusList.add(CarWaybillEnum.WAIT_UNLOADING.getCode());
        statusList.add(CarWaybillEnum.COMPLETION_UNLOADING.getCode());
//        statusList.add(CarWaybillEnum.APPROVAL_PASS.getCode());
        statusList.add(CarWaybillEnum.APPROVAL_IN.getCode());
        statusList.add(CarWaybillEnum.APPROVAL_NO_PASS.getCode());
        int count = waybillOrderMapper.selectDataByLorderId(id, statusList);
        if (count > NumberConstant.ZERO) {
            flag = true;
        }
        return flag;
    }

    /**
     * 验证是否存在进行中的车辆运单
     * 统计当前物流订单的 分配量/实装量/实卸量
     * 验证当前贸易订单是否存在进行中的物流运单
     *
     * @param logisticsOrder 物流订单数据
     */
    public void judgmentLogisticsOrderIsFinish(KwtLogisticsOrder logisticsOrder) {
        //查询是否存在进行中的车辆运单 取至 CarWaybillEnum 枚举类
        long[] waybillStatus = {1, 2, 3, 4, 5, 6, 7, 13};
        List<KwtWaybillOrder> waybillOrders = waybillOrderMapper.selectList(new LambdaQueryWrapper<KwtWaybillOrder>()
                .eq(KwtWaybillOrder::getLOrderId, logisticsOrder.getId())
                .in(KwtWaybillOrder::getStatus, waybillStatus));
        if (CollectionUtils.isNotEmpty(waybillOrders)) {
            log.info("完结订单时存在进行中的车辆运单,物流订单id:{},物流订单编号:{},车辆运单:{}",
                    logisticsOrder.getId(), logisticsOrder.getLOrderNo(), JSONObject.toJSONString(waybillOrders));
            throw new BusinessException("不能进行订单完结,存在进行中的车辆运单");
        }
        //获取贸易订单下物流运单是否存在进行中的单据(贸易订单统计物流订单) 取至 LogisticsOrderEnum枚举类
        long[] logisticsStatus = {0, 1, 2, 3};
        List<KwtLogisticsOrder> orderList = kwtLogisticsOrderMapper.selectList(new LambdaQueryWrapper<KwtLogisticsOrder>()
                .eq(KwtLogisticsOrder::getTOrderId, logisticsOrder.getTOrderId())
                .in(KwtLogisticsOrder::getStatus, logisticsStatus));
        boolean flag = true;
        if (CollectionUtils.isNotEmpty(orderList)) {
            log.info("完结订单时存在当前进行中的贸易订单下的物流运单,物流订单id:{},物流订单编号:{},贸易订单id:{},贸易订单编号:{},当前贸易订单其他物流订单:{}",
                    logisticsOrder.getId(), logisticsOrder.getLOrderNo(), logisticsOrder.getTOrderId(), JSONObject.toJSONString(waybillOrders), JSONObject.toJSONString(orderList));
            throw new BusinessException("完结订单时存在当前进行中的贸易订单下的物流运单");
        }
        //防止事务脏读,幻读.重新查询 物流订单数据
//        KwtLogisticsOrder kwtLogisticsOrder = kwtLogisticsOrderMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrder>().eq(KwtLogisticsOrder::getId, logisticsOrder.getId()));
//        CompleteLogisticsOrderParam param = new CompleteLogisticsOrderParam();
//        param.setTOrderId(logisticsOrder.getTOrderId());
//        param.setEntrustAmount(kwtLogisticsOrder.getAmount().negate());
//        param.setActualLoadAmount(kwtLogisticsOrder.getLoadAmount());
//        param.setActualUnloadAmount(kwtLogisticsOrder.getUnloadAmount());
//        param.setIsAllComplete(flag);
//        param.setUpdateBy(LoginUserHolder.getUserId());
//        param.setUpdateByName(LoginUserHolder.getUserName());
//        tradeOrderInfoService.completeLogisticsOrder(param);
    }

    public void updateDataBySubset(OrderFinishDTO orderFinishDTO, String orderId) {
        KwtLogisticsOrder kwtLogisticsOrder = kwtLogisticsOrderMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrder>()
                .eq(KwtLogisticsOrder::getId, Long.parseLong(orderId)));
        if (kwtLogisticsOrder != null) {
            kwtLogisticsOrder.setStatus(LogisticsOrderEnum.HAVE_FINISHED.getCode());
            kwtLogisticsOrder.setUpdateBy(LoginUserHolder.getUserId());
            kwtLogisticsOrder.setUpdateTime(new Date());
            kwtLogisticsOrder.setRemark(orderFinishDTO.getRemark());
            kwtLogisticsOrderMapper.updateById(kwtLogisticsOrder);
            KwtLogisticsOrderTrack logisticsOrderTrack = kwtLogisticsOrderTrackMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrderTrack>()
                    .eq(KwtLogisticsOrderTrack::getLOrderId, orderId)
                    .eq(KwtLogisticsOrderTrack::getStatus, LogisticsOrderEnum.HAVE_FINISHED.getCode()));
            if (logisticsOrderTrack == null) {
                KwtLogisticsOrderTrack track = new KwtLogisticsOrderTrack();
                track.setId(new IdWorker(NumberConstant.ONE).nextId());
                track.setLOrderId(kwtLogisticsOrder.getId());
                track.setStatus(LogisticsOrderEnum.HAVE_FINISHED.getCode());
                track.setCreateTime(new Date());
                track.setRemark(orderFinishDTO.getRemark());
                track.setCreateBy(LoginUserHolder.getUserId());
                track.setUpdateBy(LoginUserHolder.getUserId());
                track.setUpdateTime(new Date());
                kwtLogisticsOrderTrackMapper.insert(track);
            } else {
                kwtLogisticsOrderTrackMapper.update(null, new LambdaUpdateWrapper<KwtLogisticsOrderTrack>()
                        .eq(KwtLogisticsOrderTrack::getLOrderId, orderId)
                        .set(KwtLogisticsOrderTrack::getRemark, orderFinishDTO.getRemark())
                        .set(KwtLogisticsOrderTrack::getUpdateTime, new Date())
                        .set(KwtLogisticsOrderTrack::getUpdateBy, LoginUserHolder.getUserId()));
            }
            /**单据完结修改Mongodb*/
            SckwLogisticsOrder updateParam = new SckwLogisticsOrder();
            updateParam.setLOrderId(kwtLogisticsOrder.getId())
                    .setStatus(LogisticsOrderEnum.HAVE_FINISHED.getStatus())
                    .setUpdateBy(LoginUserHolder.getUserId())
                    .setUpdateByName(LoginUserHolder.getUserName())
                    .setUpdateTime(new Date())
            ;
            SckwBusSum busSum = new SckwBusSum();
            busSum.setBusSumType(BusinessTypeEnum.LOGISTICS_ORDER_TYPE.getName());
            busSum.setMethod(2);
            busSum.setObject(updateParam);
            streamBridge.send("sckw-busSum", com.alibaba.fastjson2.JSON.toJSONString(busSum));
        }
    }

    /**
     * 完结订单-修改本身数据
     */
    private void updateDataByItself(KwtLogisticsOrder logisticsOrder, OrderFinishDTO orderFinishDTO) {
        logisticsOrder.setStatus(LogisticsOrderEnum.HAVE_FINISHED.getCode());
        logisticsOrder.setLoadAmount(orderFinishDTO.getLoadAmount());
        logisticsOrder.setUnloadAmount(orderFinishDTO.getUnloadAmount());
        logisticsOrder.setUpdateBy(LoginUserHolder.getUserId());
        logisticsOrder.setUpdateTime(new Date());
        logisticsOrder.setRemark(orderFinishDTO.getRemark());
        kwtLogisticsOrderMapper.updateById(logisticsOrder);
        KwtLogisticsOrderTrack logisticsOrderTrack = kwtLogisticsOrderTrackMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrderTrack>()
                .eq(KwtLogisticsOrderTrack::getLOrderId, logisticsOrder.getId())
                .eq(KwtLogisticsOrderTrack::getStatus, LogisticsOrderEnum.HAVE_FINISHED.getCode()));
        if (logisticsOrderTrack == null) {
            KwtLogisticsOrderTrack track = new KwtLogisticsOrderTrack();
            track.setId(new IdWorker(NumberConstant.ONE).nextId());
            track.setLOrderId(logisticsOrder.getId());
            track.setStatus(LogisticsOrderEnum.HAVE_FINISHED.getCode());
            track.setCreateTime(new Date());
            track.setRemark(orderFinishDTO.getRemark());
            track.setCreateBy(LoginUserHolder.getUserId());
            track.setUpdateBy(LoginUserHolder.getUserId());
            track.setUpdateTime(new Date());
            kwtLogisticsOrderTrackMapper.insert(track);
        } else {
            kwtLogisticsOrderTrackMapper.update(null, new LambdaUpdateWrapper<KwtLogisticsOrderTrack>()
                    .eq(KwtLogisticsOrderTrack::getLOrderId, logisticsOrder.getId())
                    .set(KwtLogisticsOrderTrack::getRemark, orderFinishDTO.getRemark())
                    .set(KwtLogisticsOrderTrack::getUpdateTime, new Date())
                    .set(KwtLogisticsOrderTrack::getUpdateBy, LoginUserHolder.getUserId()));
        }
        /**单据完结修改Mongodb*/
        SckwLogisticsOrder updateParam = new SckwLogisticsOrder();
        updateParam.setLOrderId(Long.parseLong(orderFinishDTO.getId()))
                .setStatus(LogisticsOrderEnum.HAVE_FINISHED.getStatus())
                .setUpdateBy(LoginUserHolder.getUserId())
                .setUpdateByName(LoginUserHolder.getUserName())
                .setUpdateTime(new Date())
                .setLoadAmount(orderFinishDTO.getLoadAmount())
                .setUnloadAmount(orderFinishDTO.getUnloadAmount())
        ;
        SckwBusSum busSum = new SckwBusSum();
        busSum.setBusSumType(BusinessTypeEnum.LOGISTICS_ORDER_TYPE.getName());
        busSum.setMethod(2);
        busSum.setObject(updateParam);
        streamBridge.send("sckw-busSum", com.alibaba.fastjson2.JSON.toJSONString(busSum));
    }

    /**
     * 采购订单/销售订单-托运订单列表-订单完结-数据查询
     *
     * @param orderId 物流订单id
     * @param type    1采购订单2销售订单
     * @return
     */
    public HttpResult selectOrderFinishVo(String orderId, String type) {
        HttpResult httpResult = new HttpResult();
        httpResult.setCode(HttpStatus.SUCCESS_CODE);
        if (String.valueOf(NumberConstant.ONE).equals(type)) {
            httpResult = selectOrderFinishData(orderId);
        } else if (String.valueOf(NumberConstant.TWO).equals(type)) {
            httpResult = selectOrderFinishData(orderId);
        } else {
            httpResult.setCode(HttpStatus.SUCCESS_CODE);
            httpResult.setMsg("订单完结查询,类型错误！");
        }
        return httpResult;
    }

    /**
     * 采购订单/销售订单-托运订单列表-订单完结-数据查询
     *
     * @param orderId 物流订单id
     * @return
     */
    private HttpResult selectOrderFinishData(String orderId) {
        HttpResult httpResult = new HttpResult();
//        OrderFinishVO orderFinishVO = kwtLogisticsOrderMapper.selectOrderFinishData(orderId);
        Map<String, Object> map = new HashMap(NumberConstant.SIXTEEN);
        map.put("upperlOrderId", orderId);
        //随意给个值 主要是传递不为null
        map.put("passStatus", 1);
        WaybillCountVo waybillOrderCount = waybillOrderMapper.findWaybillOrderCount(map);
        OrderFinishVO orderFinishVO = new OrderFinishVO();
        orderFinishVO.setLoadAmount(waybillOrderCount == null ? NumberConstant.ZERO_TWO : waybillOrderCount.getLoadAmount());
        orderFinishVO.setUnloadAmount(waybillOrderCount == null ? NumberConstant.ZERO_TWO : waybillOrderCount.getUnloadAmount());
        orderFinishVO.setNumber(waybillOrderCount == null ? NumberConstant.ZERO : waybillOrderCount.getTotalComplete());
        httpResult.setData(orderFinishVO);
        return httpResult;
    }

    /**
     * 导出采购订单-对应的运单列表
     *
     * @param ids 销售/采购订单IDs
     * @return
     */
    public List<PurchaseLogisticOrderExcelVo> logisticOrderByPurchaseOrderIdExport(String ids) {
        List<String> idList = StringUtils.splitStrToList(ids, String.class);
        List<PurchaseLogisticOrderExcelVo> logisticOrderExcelVos = new ArrayList<>();
        List<LogisticsOrderDto> orders = kwtLogisticsOrderMapper.selectOrderListByIdsAndUnitType(idList, "1");
        AtomicInteger i = new AtomicInteger(1);
        orders.forEach(e -> {
            PurchaseLogisticOrderExcelVo vo = new PurchaseLogisticOrderExcelVo();
            vo.setSerialNumber(String.valueOf(i.getAndIncrement()));
            vo.setLOrderNo(e.getLOrderNo());
            vo.setTOrderNo(e.getTOrderNo());
            vo.setStatus(LogisticsOrderEnum.getDestination(e.getStatus()));
            vo.setCompanyName(e.getCompanyName());
            vo.setAmount(String.valueOf(e.getAmount()));
            vo.setPrice(e.getPrice());
            vo.setLoss(e.getLoss());
            vo.setGoodsPrice(e.getGoodsPrice());
            vo.setContacts(e.getContacts());
            vo.setPhone(e.getPhone());
            vo.setCreateTime(e.getCreateTime());
            vo.setCreateBy(e.getCreateBy());
            logisticOrderExcelVos.add(vo);
        });
        return logisticOrderExcelVos;
    }

    /**
     * 导出销售/采购订单对应的运单列表
     *
     * @param ids 销售/采购订单IDs
     * @return
     */
    public List<SellLogisticOrderExcelVo> logisticOrderBySellOrderIdExport(String ids) {
        List<String> idList = StringUtils.splitStrToList(ids, String.class);
        List<SellLogisticOrderExcelVo> logisticOrderExcelVos = new ArrayList<>();
        List<LogisticsOrderDto> orders = kwtLogisticsOrderMapper.selectOrderListByIdsAndUnitType(idList, "2");
        AtomicInteger i = new AtomicInteger(1);
        orders.forEach(e -> {
            SellLogisticOrderExcelVo vo = new SellLogisticOrderExcelVo();
            vo.setSerialNumber(String.valueOf(i.getAndIncrement()));
            vo.setLOrderNo(e.getLOrderNo());
            vo.setTOrderNo(e.getTOrderNo());
            vo.setStatus(LogisticsOrderEnum.getDestination(e.getStatus()));
            vo.setCompanyName(e.getCompanyName());
            vo.setAmount(String.valueOf(e.getAmount()));
            vo.setPrice(e.getPrice());
            vo.setLoss(e.getLoss());
            vo.setGoodsPrice(e.getGoodsPrice());
            vo.setContacts(e.getContacts());
            vo.setPhone(e.getPhone());
            vo.setCreateTime(e.getCreateTime());
            vo.setCreateBy(e.getCreateBy());
            logisticOrderExcelVos.add(vo);
        });
        return logisticOrderExcelVos;
    }

    public static void getLogisticsLOrderNo(String t, String number, String number1, String number2) {
        StringBuilder str = new StringBuilder();
        String date = DateUtils.formatDate(new Date());
        str.append(t).append(date).append(number).append(number1).append(number2);
    }

    /**
     * 采购/销售订单-完成车次统计
     *
     * @param tradeOrderId 贸易订单id
     * @return
     */
    public Integer statisticsWaybillCount(String tradeOrderId) {
        int count = 0;
        List<KwtLogisticsOrder> orderList = kwtLogisticsOrderMapper.selectList(new LambdaQueryWrapper<KwtLogisticsOrder>()
                .eq(KwtLogisticsOrder::getTOrderId, tradeOrderId).eq(KwtLogisticsOrder::getDelFlag, NumberConstant.ZERO));
        if (org.springframework.util.CollectionUtils.isEmpty(orderList)) {
            return count;
        }
        List<Long> longList = orderList.stream().map(KwtLogisticsOrder::getId).collect(Collectors.toList());
        if (org.springframework.util.CollectionUtils.isEmpty(longList)) {
            return count;
        }

        return waybillOrderV1Mapper.selectDataByLorderIds(longList, CarWaybillEnum.APPROVAL_PASS.getCode());
    }

    /**
     * 采购订单/销售订单-物流托运-v4.2
     *
     * @param logisticsConsignmentDto
     * @return
     */
    @GlobalTransactional
    public HttpResult logisticsOrderConsignment(LogisticsConsignmentDto dto) {
        HttpResult httpResult = ValidUtil.serviceValid(dto);
        if (HttpStatus.SUCCESS_CODE != httpResult.getCode()) {
            return HttpResult.error(httpResult.getMsg());
        }
        HttpResult checked = checkParamData(dto);
        if (checked.getCode() != HttpStatus.SUCCESS_CODE) {
            return HttpResult.error(checked.getMsg());
        }
        String key = String.format(RedisConstant.TRADE_TO_LOGISTICS_NO_GENERATE_KEY, dto.getTOrderId());
        if (redisLockUtil.tryLock(key)) {
            try {
                logisticsConsignmentSave(dto);
            } finally {
                redisLockUtil.unlock(key);
            }
        } else {
            return HttpResult.error("请求不可重复操作,请稍后重试");
        }
        return HttpResult.ok();
    }

    /**
     * 采购订单/销售订单-物流托运-v4.2
     *
     * @param dto
     */
    private void logisticsConsignmentSave(LogisticsConsignmentDto dto) {
        logisticsOrderConsignmentService.logisticsConsignmentSave(dto);
    }

    /**
     * 物流订单-自建订单-v4.2
     *
     * @param addLogisticsOrderParam
     * @return
     */
    public HttpResult addLogisticsOrder(AddLogisticsOrderParam addLogisticsOrderParam) {
        return logisticsOrderConsignmentService.addLogisticsOrder(addLogisticsOrderParam);
    }

    /**
     * 物流订单-分包托运-v4.2
     *
     * @param logisticsOrderSubcontractDto
     * @return
     */
    public HttpResult logisticsOrderSubcontract(LogisticsOrderSubcontractDto logisticsOrderSubcontractDto) {
        return logisticsOrderConsignmentService.logisticsOrderSubcontract(logisticsOrderSubcontractDto);
    }

    // 自定义线程池
    private static final ExecutorService QUERY_EXECUTOR = Executors.newFixedThreadPool(10);


    public PageDataResult<LogisticsOrderResp> queryLogisticsOrderByPage(QueryLogisticsOrderReq req) {
        log.info("分页查询物流订单传递参数信息:{}", JSONObject.toJSONString(req));

        // 1. 并行获取基础数据
        log.debug("开始并行获取基础数据");
        Long allEnt = getAllEnt(req.getEntId());

        BaseQueryData baseQueryData = fetchBaseQueryData(req);

        // 2. 处理企业信息
        log.debug("处理企业信息");
        Set<Long> entList = processEnterpriseData(baseQueryData);

        // 3. 获取物流订单ID集合
        log.debug("获取物流订单ID集合");
        Set<Long> logOrderIds = getLogOrderIds(req, entList, allEnt);
        // 应用数据权限过滤
        logOrderIds = applyDataPermissionFilterToLogOrderIds(logOrderIds);

        // 4. 检查是否需要返回空结果
        log.debug("检查是否需要返回空结果，logOrderIds大小: {}, entList大小: {}", logOrderIds.size(), entList.size());
        if (shouldReturnEmptyResult(logOrderIds, entList, req)) {
            log.info("满足返回空结果条件，直接返回空分页数据");
            return PageDataResult.empty(req.getPageNum(), req.getPageSize());
        }

        // 5. 分页查询物流订单
        log.debug("开始分页查询物流订单，订单ID数量: {}", logOrderIds.size());
        IPage<KwtLogisticsOrder> page = queryLogisticsOrdersPage(logOrderIds, req);
        List<KwtLogisticsOrder> records = page.getRecords();

        if (CollectionUtils.isEmpty(records)) {
            log.info("查询结果为空，返回空分页数据");
            return PageDataResult.empty(req.getPageNum(), req.getPageSize());
        }

        log.info("分页查询结果，总记录数: {}，当前页记录数: {}", page.getTotal(), records.size());

        // 6. 提取物流订单ID列表
        log.debug("提取物流订单ID列表");
        List<Long> logOrderIdList = extractLogisticsOrderIds(records);

        // 7. 并行获取相关数据
        log.debug("并行获取相关数据");
        RelatedOrderData relatedData = fetchRelatedOrderData(logOrderIdList, records);

        // 8. 获取字典数据
        log.debug("获取字典数据");
        Map<String, Map<String, String>> dictMap = getCachedDictData(baseQueryData.getDictFuture());

        // 9. 转换为响应对象
        log.debug("转换为响应对象");
        List<LogisticsOrderResp> resps = convertToResponseList(
                records, relatedData, dictMap);

        log.info("物流订单分页查询完成，返回结果数量: {}", resps.size());
        return PageDataResult.of(page, resps);
    }

    /**
     * 获取基础查询数据
     */
    private BaseQueryData fetchBaseQueryData(QueryLogisticsOrderReq req) {
        CompletableFuture<Set<Long>> entListFuture = CompletableFuture.supplyAsync(
                () -> getEntList(req), QUERY_EXECUTOR);
        CompletableFuture<Map<String, Map<String, String>>> dictFuture = CompletableFuture.supplyAsync(
                () -> getCachedDictData(), QUERY_EXECUTOR);

        return new BaseQueryData(entListFuture, dictFuture);
    }

    /**
     * 处理企业数据
     */
    private Set<Long> processEnterpriseData(BaseQueryData baseQueryData) {
        Set<Long> entList = baseQueryData.getEntListFuture().join();
        return entList;
    }

    /**
     * 检查是否需要返回空结果
     */
    private boolean shouldReturnEmptyResult(Set<Long> logOrderIds, Set<Long> entList, QueryLogisticsOrderReq req) {
        return CollectionUtils.isEmpty(logOrderIds) &&
                (!org.apache.commons.lang3.StringUtils.isAllBlank(req.getContractId(), req.getGoodsName(), req.getConsignCompanyId(), req.getCarriageCompanyId())
                        || org.apache.commons.collections4.CollectionUtils.isNotEmpty(entList));
    }

    /**
     * 分页查询物流订单
     */
    private IPage<KwtLogisticsOrder> queryLogisticsOrdersPage(Set<Long> logOrderIds, QueryLogisticsOrderReq req) {
        QueryLogisticsOrderReq optimizedReq = optimizeRequestWithFilters(req);
        Date startDate = null;
        Date endDate = null;
        if (org.apache.commons.lang3.StringUtils.isNoneBlank(optimizedReq.getStartTime(), optimizedReq.getEndTime())) {
            startDate = DateUtils.getStartDate(optimizedReq.getStartTime());
            endDate = DateUtils.getEndDate(optimizedReq.getEndTime());
        }
        return logisticsOrderRepository.queryByPage(
                logOrderIds, optimizedReq.getTradeOrderId(), optimizedReq.getOrderNo(), optimizedReq.getTradeOrderNo(),
                optimizedReq.getOrderStatus(), startDate,
                endDate, optimizedReq.getPageNum(), optimizedReq.getPageSize());
    }

    /**
     * 提取物流订单ID列表
     */
    private List<Long> extractLogisticsOrderIds(List<KwtLogisticsOrder> records) {
        return records.stream()
                .map(KwtLogisticsOrder::getId)
                .distinct()
                .collect(Collectors.toList());
    }

    /**
     * 获取相关订单数据
     */

    /**
     * 并行获取相关订单数据
     * 包括：订单单位信息、订单商品信息、订单地址信息、订单合同信息、子运单信息和贸易订单信息
     *
     * @param logOrderIdList 物流订单ID列表
     * @param records        物流订单记录列表
     * @return RelatedOrderData 包含所有相关订单数据的对象
     */

    private RelatedOrderData fetchRelatedOrderData(List<Long> logOrderIdList, List<KwtLogisticsOrder> records) {
        log.debug("开始并行获取相关订单数据，物流订单数量: {}", logOrderIdList.size());

        // 并行执行多个不相互依赖的查询
        CompletableFuture<List<KwtLogisticsOrderUnit>> unitListFuture = CompletableFuture.supplyAsync(
                () -> {
                    log.debug("开始查询物流订单单位信息");
                    List<KwtLogisticsOrderUnit> result = logisticsOrderUnitRepository.queryByLogOrderIds(logOrderIdList);
                    log.debug("物流订单单位信息查询完成，结果数量: {}", result.size());
                    return result;
                }, QUERY_EXECUTOR);

        CompletableFuture<List<KwtLogisticsOrderGoods>> goodsListFuture = CompletableFuture.supplyAsync(
                () -> {
                    log.debug("开始查询物流订单商品信息");
                    List<KwtLogisticsOrderGoods> result = logisticsOrderGoodsRepository.queryByLogOrderIds(logOrderIdList);
                    log.debug("物流订单商品信息查询完成，结果数量: {}", result.size());
                    return result;
                }, QUERY_EXECUTOR);

        CompletableFuture<Map<String, KwtLogisticsOrderAddress>> addressMapFuture = CompletableFuture.supplyAsync(
                () -> {
                    log.debug("开始查询物流订单地址信息");
                    Map<String, KwtLogisticsOrderAddress> result = getStringKwtLogisticsOrderAddressMap(logOrderIdList);
                    log.debug("物流订单地址信息查询完成，结果数量: {}", result.size());
                    return result;
                }, QUERY_EXECUTOR);

        CompletableFuture<Map<Long, KwtLogisticsOrderContract>> contractMapFuture = CompletableFuture.supplyAsync(
                () -> {
                    log.debug("开始查询物流订单合同信息");
                    Map<Long, KwtLogisticsOrderContract> result = getLongKwtLogisticsOrderContractMap(logOrderIdList);
                    log.debug("物流订单合同信息查询完成，结果数量: {}", result.size());
                    return result;
                }, QUERY_EXECUTOR);

        CompletableFuture<List<KwtWaybillOrderSubtask>> subtaskListFuture = CompletableFuture.supplyAsync(
                () -> {
                    log.debug("开始查询物流订单子运单信息");
                    List<KwtWaybillOrderSubtask> result = waybillOrderSubtaskRepository.queryByLogIds(logOrderIdList);
                    log.debug("物流订单子运单信息查询完成，结果数量: {}", result.size());
                    return result;
                }, QUERY_EXECUTOR);

        // 并行处理贸易订单信息
        CompletableFuture<Map<Long, OrderDetailVo>> tradeMapFuture = CompletableFuture.supplyAsync(
                () -> {
                    log.debug("开始查询贸易订单信息");
                    Map<Long, OrderDetailVo> result = fetchTradeOrderData(records);
                    log.debug("贸易订单信息查询完成，结果数量: {}", result.size());
                    return result;
                }, QUERY_EXECUTOR);

        // 等待所有并行查询完成
        log.debug("等待所有并行查询完成");
        CompletableFuture.allOf(unitListFuture, goodsListFuture, addressMapFuture,
                contractMapFuture, subtaskListFuture, tradeMapFuture).join();
        log.debug("所有并行查询已完成");

        // 处理查询结果
        log.debug("开始处理查询结果");
        Map<String, KwtLogisticsOrderUnit> unitMap = processUnitData(unitListFuture.join());
        GoodsData goodsData = processGoodsData(goodsListFuture.join());
        Map<String, KwtLogisticsOrderAddress> addressMap = addressMapFuture.join();
        Map<Long, KwtLogisticsOrderContract> contractMap = contractMapFuture.join();
        Map<Long, List<KwtWaybillOrderSubtask>> subtaskMap = processSubtaskData(subtaskListFuture.join());
        Map<Long, List<KwtWaybillOrderTicket>> ticketMap = processTicketData(subtaskListFuture.join());
        Map<Long, OrderDetailVo> tradeMap = tradeMapFuture.join();
        Map<Long, List<KwtLogisticsOrder>> tradeLogOrderMap = groupByTradeOrder(records);
        log.debug("查询结果处理完成");

        log.debug("相关订单数据获取完成");
        return new RelatedOrderData(unitMap, goodsData, addressMap, contractMap,
                subtaskMap, ticketMap, tradeMap, tradeLogOrderMap);
    }

    /**
     * 获取贸易订单数据
     */
    private Map<Long, OrderDetailVo> fetchTradeOrderData(List<KwtLogisticsOrder> records) {
        Set<Long> tradeIds = records.stream()
                .map(KwtLogisticsOrder::getTOrderId)
                .collect(Collectors.toSet());

        if (CollectionUtils.isEmpty(tradeIds)) {
            return Maps.newHashMap();
        }

        List<OrderDetailVo> orderDetailVos = tradeOrderInfoService.queryByTradeOrderIds(tradeIds);
        return orderDetailVos.stream()
                .collect(Collectors.toMap(OrderDetailVo::getId, Function.identity(), (x, y) -> x));
    }

    /**
     * 处理单位数据
     */
    private Map<String, KwtLogisticsOrderUnit> processUnitData(List<KwtLogisticsOrderUnit> unitList) {
        if (CollectionUtils.isEmpty(unitList)) {
            return Maps.newHashMap();
        }

        return unitList.stream()
                .collect(Collectors.toMap(x -> x.getLOrderId() + "-" + x.getUnitType(),
                        Function.identity(), (x, y) -> x));
    }

    /**
     * 处理商品数据
     */
    private GoodsData processGoodsData(List<KwtLogisticsOrderGoods> logOrderGoodsList) {
        Map<Long, KwtLogisticsOrderGoods> logGoodsMap = Maps.newHashMap();
        Map<Long, KwpGoods> goodsMap = Maps.newHashMap();

        if (CollectionUtils.isNotEmpty(logOrderGoodsList)) {
            List<Long> goodsIds = logOrderGoodsList.stream()
                    .map(KwtLogisticsOrderGoods::getGoodsId)
                    .distinct()
                    .collect(Collectors.toList());

            logGoodsMap = logOrderGoodsList.stream()
                    .collect(Collectors.toMap(KwtLogisticsOrderGoods::getLOrderId,
                            Function.identity(), (x, y) -> x));

            if (CollectionUtils.isNotEmpty(goodsIds)) {
                goodsMap = goodsInfoService.getGoodsByIds(goodsIds);
            }
        }

        return new GoodsData(logGoodsMap, goodsMap);
    }

    /**
     * 处理子运单数据
     */
    private Map<Long, List<KwtWaybillOrderSubtask>> processSubtaskData(List<KwtWaybillOrderSubtask> subtaskList) {
        if (CollectionUtils.isEmpty(subtaskList)) {
            return Maps.newHashMap();
        }

        return subtaskList.stream()
                .collect(Collectors.groupingBy(KwtWaybillOrderSubtask::getLOrderId));
    }

    /**
     * 处理磅单数据，构建运单ID与磅单列表映射
     */
    private Map<Long, List<KwtWaybillOrderTicket>> processTicketData(List<KwtWaybillOrderSubtask> subtaskList) {
        if (CollectionUtils.isEmpty(subtaskList)) {
            return Maps.newHashMap();
        }
        List<Long> wOrderIds = subtaskList.stream()
                .filter(Objects::nonNull)
                .map(KwtWaybillOrderSubtask::getWOrderId)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(wOrderIds)) {
            return Maps.newHashMap();
        }
        List<KwtWaybillOrderTicket> tickets = waybillOrderTicketRepository.queryByWOrderIds(wOrderIds);
        if (CollectionUtils.isEmpty(tickets)) {
            return Maps.newHashMap();
        }
        return tickets.stream()
                .filter(Objects::nonNull)
                .collect(Collectors.groupingBy(KwtWaybillOrderTicket::getWOrderId));
    }

    /**
     * 按贸易订单分组
     */
    private Map<Long, List<KwtLogisticsOrder>> groupByTradeOrder(List<KwtLogisticsOrder> records) {
        return records.stream()
                .collect(Collectors.groupingBy(KwtLogisticsOrder::getTOrderId));
    }

    /**
     * 获取缓存的字典数据
     */
    private Map<String, Map<String, String>> getCachedDictData() {
        // 这里可以使用Redis或本地缓存如Caffeine
        // 如果缓存中没有，则查询远程系统并更新缓存
        return remoteSystemService.queryDictByType(Arrays.asList(DictTypeEnum.PRODUCT_NAME_TYPE.getType(), DictTypeEnum.GOODS_SPEC.getType()));
    }

    /**
     * 获取缓存的字典数据
     */
    private Map<String, Map<String, String>> getCachedDictData(CompletableFuture<Map<String, Map<String, String>>> dictFuture) {
        return dictFuture.join();
    }

    /**
     * 优化请求对象，添加过滤条件
     */
    private QueryLogisticsOrderReq optimizeRequestWithFilters(QueryLogisticsOrderReq req) {
        QueryLogisticsOrderReq optimizedReq = new QueryLogisticsOrderReq();
        BeanUtils.copyProperties(req, optimizedReq);

        // 如果有承运单位或托运单位过滤条件，可以在这里添加到请求中
        // 这样可以在数据库层面完成过滤，减少内存中的过滤操作

        return optimizedReq;
    }

    /**
     * 转换为响应对象列表
     */
    private List<LogisticsOrderResp> convertToResponseList(
            List<KwtLogisticsOrder> records,
            RelatedOrderData relatedData,
            Map<String, Map<String, String>> dictMap) {

        return records.stream()
                .map(order -> getLogisticsOrderResp(
                        order,
                        relatedData.getUnitMap(),
                        relatedData.getGoodsData().getLogGoodsMap(),
                        relatedData.getGoodsData().getGoodsMap(),
                        relatedData.getAddressMap(),
                        relatedData.getContractMap(),
                        dictMap,
                        relatedData.getTradeMap(),
                        relatedData.getTradeLogOrderMap(),
                        relatedData.getSubtaskMap(),
                        relatedData.getTicketMap()))
                .collect(Collectors.toList());
    }

    public List<LogisticsBaseOrderVo> queryBaseList(LogisticsOrderPara orderPara) {
        UserResDto userResDto = remoteSystemService.queryUserById(orderPara.getUserId());
        if (Objects.nonNull(userResDto)) {
            orderPara.setType(userResDto.getType());
            Integer systemType = userResDto.getSystemType();
            if (!Objects.equals(systemType, SystemTypeEnum.MANAGE.getCode())) {
                orderPara.setEntId(remoteUserService.findChildEntList(userResDto.getEntId()));
            }
        }

        List<LogisticsBaseOrderVo> logisticsBaseOrderVos = kwtLogisticsOrderMapper.selectBase(orderPara);
        if (CollUtil.isNotEmpty(logisticsBaseOrderVos)) {
            logisticsBaseOrderVos.forEach(d -> d.setMoreUrl("/#/operatManagement/logisticsOrder/list"));
        }
        return logisticsBaseOrderVos;
    }

    public HttpResult createLogisticsOrder(CreateLogisticsOrderParam addLogisticsOrderParam) {
        AddLogisticOrderDTO addLogisticOrderDTO = new AddLogisticOrderDTO();
        addLogisticOrderDTO.setOrderType(1);
        List<LogisticsEntDto> logisticsContractList = addLogisticsOrderParam.getLogisticsContractList();
        Long goodsId = addLogisticsOrderParam.getGoodsId();
        Long contractId = logisticsContractList.get(0).getContractId();

        List<TradeContractUnitDto> tradeContractUnitDtos = contractService.queryLogContractUnitByContractId(contractId);


        addLogisticOrderDTO.setEntId(LoginUserHolder.getEntId());
        addLogisticOrderDTO.setUserId(LoginUserHolder.getUserId());
        //todo 获取不到的参数
        addLogisticOrderDTO.setTradeOrderId(0L);
        addLogisticOrderDTO.setTradeOrderNo("");

        for (TradeContractUnitDto tradeContractUnitDto : tradeContractUnitDtos) {
            if(StrUtil.equals(tradeContractUnitDto.getUnitType(),"3")){
                addLogisticOrderDTO.setConsignCompany(tradeContractUnitDto.getFirmName());
                addLogisticOrderDTO.setConsignCompanyId(tradeContractUnitDto.getEntId());
                addLogisticOrderDTO.setConsignContactPhone(tradeContractUnitDto.getPhone());
                addLogisticOrderDTO.setConsignContacts(tradeContractUnitDto.getContacts());
                addLogisticOrderDTO.setConsignContactsId(tradeContractUnitDto.getContactsId());
            }else  if(StrUtil.equals(tradeContractUnitDto.getUnitType(),"4")){
                List<LogisticData> collect = logisticsContractList.stream().map(d -> {
                    LogisticData logisticInfo = new LogisticData();
                    logisticInfo.setContractId(d.getContractId());
                    logisticInfo.setContractNo(d.getContractNo());
                    logisticInfo.setContractName("");
                    logisticInfo.setAcceptCompanyId(tradeContractUnitDto.getEntId());
                    logisticInfo.setAcceptContactPhone(tradeContractUnitDto.getPhone());
                    logisticInfo.setAcceptContacts(tradeContractUnitDto.getContacts());
                    logisticInfo.setAcceptContactsId(tradeContractUnitDto.getContactsId());
                    logisticInfo.setAcceptCompany("");
                    logisticInfo.setPrice(d.getTransportPrice());
                    logisticInfo.setPriceType(0L);
                    logisticInfo.setAmount(addLogisticsOrderParam.getAmount());
                    logisticInfo.setAmountUnit("");//默认是吨 todo
                    logisticInfo.setLoss(new BigDecimal("0"));
                    logisticInfo.setPayment(0L);
                    logisticInfo.setSigningWay(0);
                    logisticInfo.setLossUnit("");
                    logisticInfo.setRemark("");
                    logisticInfo.setType(0);

                    return logisticInfo;
                }).collect(Collectors.toList());
                addLogisticOrderDTO.setLogisticInfo(collect);
                addLogisticOrderDTO.setNonConsignCompany(tradeContractUnitDto.getFirmName());
                addLogisticOrderDTO.setNonConsignCompanyId(tradeContractUnitDto.getEntId());
                addLogisticOrderDTO.setNonConsignContactPhone(tradeContractUnitDto.getPhone());
                addLogisticOrderDTO.setNonConsignContacts(tradeContractUnitDto.getContacts());
                addLogisticOrderDTO.setNonConsignContactsId(tradeContractUnitDto.getContactsId());
            }
        }


        KwpGoods kwpGoods = null;
        if (Objects.nonNull(goodsId)) {
            kwpGoods = goodsInfoService.getGoodsById(goodsId);
        }
        addLogisticOrderDTO.setGoodsId(goodsId);
        addLogisticOrderDTO.setGoodsName(kwpGoods.getName());
        addLogisticOrderDTO.setGoodsType(kwpGoods.getGoodsType());
        addLogisticOrderDTO.setGoodsPrice(new BigDecimal("0"));
        addLogisticOrderDTO.setGoodsPriceUnit(kwpGoods.getPriceUnit());
        addLogisticOrderDTO.setGoodsUnit(kwpGoods.getUnit());

        CreateLogisticsAddressParam loadAddress = addLogisticsOrderParam.getLoadAddress();


        addLogisticOrderDTO.setLoadName(loadAddress.getName());
        addLogisticOrderDTO.setLoadCityCode(loadAddress.getCityCode());
        addLogisticOrderDTO.setLoadCityName(loadAddress.getCityName());
        addLogisticOrderDTO.setLoadContacts(loadAddress.getContacts());
        addLogisticOrderDTO.setLoadPhone(loadAddress.getPhone());
        addLogisticOrderDTO.setLoadDetailAddress(loadAddress.getDetailAddress());

        CreateLogisticsAddressParam unloadAddress = addLogisticsOrderParam.getUnloadAddress();
        addLogisticOrderDTO.setUnloadId(unloadAddress.getId());
        addLogisticOrderDTO.setUnloadName(unloadAddress.getName());
        addLogisticOrderDTO.setUnloadCityCode(unloadAddress.getCityCode());
        addLogisticOrderDTO.setUnloadCityName(unloadAddress.getCityName());
        addLogisticOrderDTO.setUnLoadDetailAddress(unloadAddress.getDetailAddress());
        addLogisticOrderDTO.setUnloadContacts(unloadAddress.getContacts());
        addLogisticOrderDTO.setUnloadPhone(unloadAddress.getPhone());

        addLogisticOrderDTO.setLoadLat(null);
        addLogisticOrderDTO.setLoadLng(null);
        addLogisticOrderDTO.setUnloadLat(null);
        addLogisticOrderDTO.setUnloadLng(null);
        addLogisticOrderDTO.setBillingMode("");
        addLogisticOrderDTO.setStartTime(addLogisticsOrderParam.getStartTime());
        addLogisticOrderDTO.setEndTime(addLogisticsOrderParam.getEndTime());
        addLogisticOrderDTO.setDispatchWay(DispatchWayEnums.MANUAL_DISPATCH.getCode());
        addLogisticOrderDTO.setActualDisPatch(0);
        addLogisticOrderDTO.setMeasurementWay(0);
        kwtAcceptCarriageOrderService.addLogisticOrder(addLogisticOrderDTO);
        return HttpResult.ok();
    }

    /**
     * 基础查询数据
     */
    private static class BaseQueryData {
        private final CompletableFuture<Set<Long>> entListFuture;
        private final CompletableFuture<Map<String, Map<String, String>>> dictFuture;

        public BaseQueryData(CompletableFuture<Set<Long>> entListFuture,
                             CompletableFuture<Map<String, Map<String, String>>> dictFuture) {
            this.entListFuture = entListFuture;
            this.dictFuture = dictFuture;
        }


        public CompletableFuture<Set<Long>> getEntListFuture() {
            return entListFuture;
        }

        public CompletableFuture<Map<String, Map<String, String>>> getDictFuture() {
            return dictFuture;
        }


        public Set<Long> getEntList() {
            return entListFuture.join();
        }
    }

    /**
     * 商品数据
     */
    private static class GoodsData {
        private final Map<Long, KwtLogisticsOrderGoods> logGoodsMap;
        private final Map<Long, KwpGoods> goodsMap;

        public GoodsData(Map<Long, KwtLogisticsOrderGoods> logGoodsMap,
                         Map<Long, KwpGoods> goodsMap) {
            this.logGoodsMap = logGoodsMap;
            this.goodsMap = goodsMap;
        }

        public Map<Long, KwtLogisticsOrderGoods> getLogGoodsMap() {
            return logGoodsMap;
        }

        public Map<Long, KwpGoods> getGoodsMap() {
            return goodsMap;
        }
    }

    /**
     * 相关订单数据
     */
    private static class RelatedOrderData {
        private final Map<String, KwtLogisticsOrderUnit> unitMap;
        private final GoodsData goodsData;
        private final Map<String, KwtLogisticsOrderAddress> addressMap;
        private final Map<Long, KwtLogisticsOrderContract> contractMap;
        private final Map<Long, List<KwtWaybillOrderSubtask>> subtaskMap;
        private final Map<Long, List<KwtWaybillOrderTicket>> ticketMap;
        private final Map<Long, OrderDetailVo> tradeMap;
        private final Map<Long, List<KwtLogisticsOrder>> tradeLogOrderMap;

        public RelatedOrderData(Map<String, KwtLogisticsOrderUnit> unitMap,
                                GoodsData goodsData,
                                Map<String, KwtLogisticsOrderAddress> addressMap,
                                Map<Long, KwtLogisticsOrderContract> contractMap,
                                Map<Long, List<KwtWaybillOrderSubtask>> subtaskMap,
                                Map<Long, List<KwtWaybillOrderTicket>> ticketMap,
                                Map<Long, OrderDetailVo> tradeMap,
                                Map<Long, List<KwtLogisticsOrder>> tradeLogOrderMap) {
            this.unitMap = unitMap;
            this.goodsData = goodsData;
            this.addressMap = addressMap;
            this.contractMap = contractMap;
            this.subtaskMap = subtaskMap;
            this.ticketMap = ticketMap;
            this.tradeMap = tradeMap;
            this.tradeLogOrderMap = tradeLogOrderMap;
        }

        public Map<String, KwtLogisticsOrderUnit> getUnitMap() {
            return unitMap;
        }

        public GoodsData getGoodsData() {
            return goodsData;
        }

        public Map<String, KwtLogisticsOrderAddress> getAddressMap() {
            return addressMap;
        }

        public Map<Long, KwtLogisticsOrderContract> getContractMap() {
            return contractMap;
        }

        public Map<Long, List<KwtWaybillOrderSubtask>> getSubtaskMap() {
            return subtaskMap;
        }

        public Map<Long, List<KwtWaybillOrderTicket>> getTicketMap() {
            return ticketMap;
        }

        public Map<Long, OrderDetailVo> getTradeMap() {
            return tradeMap;
        }

        public Map<Long, List<KwtLogisticsOrder>> getTradeLogOrderMap() {
            return tradeLogOrderMap;
        }
    }

    /**
     * 优化请求对象，添加过滤条件
     */
    /**
     * 获取缓存的字典数据
     */


    /**
     * 应用数据权限过滤到物流订单ID集合
     * <p>
     * 根据当前登录用户的数据权限配置，对传入的物流订单ID集合进行过滤。
     * 支持企业维度权限（可见企业范围）和个人维度权限（销售员匹配）。
     * </p>
     *
     * @param logOrderIds 待过滤的物流订单ID集合
     * @return 过滤后的物流订单ID集合
     */
    private Set<Long> applyDataPermissionFilterToLogOrderIds(Set<Long> logOrderIds) {
        // 1. 获取当前用户的数据权限配置
        DataPermissionDTO perm = fetchDataPermissionForCurrentUser();

        // 如果未获取到权限配置或不需要进行数据过滤，直接返回原始ID集合da
        if (perm == null || !perm.needFilter()) {
            log.debug("数据权限过滤：无需过滤或权限配置为空，返回原始订单ID集合，大小: {}",
                    CollectionUtils.isEmpty(logOrderIds) ? 0 : logOrderIds.size());
            return logOrderIds;
        }

        // 如果输入的订单ID集合为空，直接返回
        if (CollectionUtils.isEmpty(logOrderIds)) {
            log.debug("数据权限过滤：输入订单ID集合为空");
            return logOrderIds;
        }

        log.info("开始应用数据权限过滤，初始订单ID数量: {}, 用户ID: {}", logOrderIds.size(), LoginUserHolder.getUserId());
        Set<Long> result = new HashSet<>(logOrderIds);

        // 2. 处理企业维度数据权限
        // 如果不是所有数据可见，则需要根据可见企业ID进行过滤
        if (!perm.isAllVisible()) {
            // 如果可见企业ID列表为空，说明该用户无权查看任何企业数据，返回空集合
            if (CollectionUtils.isEmpty(perm.getVisibleEntIds())) {
                log.warn("数据权限过滤：用户无可见企业权限，返回空集合");
                return Sets.newHashSet();
            }

            log.debug("数据权限过滤：根据可见企业ID过滤，可见企业数量: {}", perm.getVisibleEntIds().size());
            // 查询这些企业关联的所有物流订单单位信息
            List<KwtLogisticsOrderUnit> units =
                    logisticsOrderUnitRepository.queryByEntIds(new HashSet<>(perm.getVisibleEntIds()));

            // 提取出这些单位对应的物流订单ID
            Set<Long> entScopeLogOrderIds = units.stream()
                    .map(KwtLogisticsOrderUnit::getLOrderId)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toSet());

            log.debug("数据权限过滤：企业维度关联的订单ID数量: {}", entScopeLogOrderIds.size());

            // 取交集：只保留在当前用户可见企业范围内的订单ID
            result.retainAll(entScopeLogOrderIds);
            log.debug("数据权限过滤：企业维度过滤后剩余订单ID数量: {}", result.size());
        }

        // 如果经过企业维度过滤后结果为空，直接返回
        if (CollectionUtils.isEmpty(result)) {
            log.info("数据权限过滤：企业维度过滤后无剩余订单，提前返回");
            return result;
        }

        // 3. 处理个人维度数据权限
        // 如果未启用个人数据权限控制，则直接返回当前结果
        if (!perm.isPersonalDataEnabled()) {
            log.info("数据权限过滤：未启用个人数据权限，最终订单ID数量: {}", result.size());
            return result;
        }

        // 启用个人数据权限时，进一步过滤：仅保留关联贸易合同中销售员为当前用户的物流订单
        log.debug("数据权限过滤：启用个人数据权限，开始按销售员过滤");
        Set<Long> finalResult = filterLogOrderIdsByTradeContractSalesman(result, perm);
        log.info("数据权限过滤完成，最终订单ID数量: {}", finalResult.size());

        return finalResult;
    }

    /**
     * 个人数据权限过滤：仅保留关联贸易合同中销售员为当前用户的物流订单
     * <p>
     * 逻辑链路：物流订单 -> 贸易订单ID -> 贸易合同ID -> 合同销售员ID == 当前用户ID
     * </p>
     *
     * @param logOrderIds 待过滤的物流订单ID集合
     * @param perm        当前用户的数据权限DTO
     * @return 过滤后的物流订单ID集合
     */
    private Set<Long> filterLogOrderIdsByTradeContractSalesman(Set<Long> logOrderIds, DataPermissionDTO perm) {
        // 校验用户ID，若为空则无法进行个人权限匹配，返回空集合
        if (perm.getUserId() == null) {
            log.warn("个人数据权限过滤：用户ID为空，返回空集合");
            return Sets.newHashSet();
        }

        Long currentUserId = perm.getUserId();
        log.debug("个人数据权限过滤：开始处理，待过滤订单数: {}, 当前用户ID: {}", logOrderIds.size(), currentUserId);

        // 1. 查询物流订单详情，获取关联的贸易订单ID
        List<KwtLogisticsOrder> orders = logisticsOrderRepository.queryByLogOrderIds(logOrderIds);
        if (CollectionUtils.isEmpty(orders)) {
            log.debug("个人数据权限过滤：未查询到物流订单详情，返回空集合");
            return Sets.newHashSet();
        }

        // 提取所有非空的贸易订单ID
        Set<Long> tradeIds = orders.stream()
                .map(KwtLogisticsOrder::getTOrderId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());

        if (CollectionUtils.isEmpty(tradeIds)) {
            log.warn("个人数据权限过滤：物流订单中未找到关联的贸易订单ID，返回空集合");
            return Sets.newHashSet();
        }
        log.debug("个人数据权限过滤：提取到贸易订单ID数量: {}", tradeIds.size());

        // 2. 查询贸易订单与合同的关联关系
        List<TradeOrderContractVo> contractLinks = tradeOrderInfoService.queryTradeOrderIds(tradeIds);
        Map<Long, Long> tradeIdToContractId = new HashMap<>();
        if (CollectionUtils.isNotEmpty(contractLinks)) {
            for (TradeOrderContractVo link : contractLinks) {
                // 确保贸易订单ID和合同ID均不为空
                if (link.getTOrderId() == null || link.getContractId() == null) {
                    continue;
                }
                // 使用 putIfAbsent 避免覆盖，通常一个贸易订单对应一个主合同
                tradeIdToContractId.putIfAbsent(link.getTOrderId(), link.getContractId());
            }
        }
        log.debug("个人数据权限过滤：贸易订单-合同映射关系数量: {}", tradeIdToContractId.size());

        // 3. 批量查询合同基础信息，获取销售员ID
        List<Long> contractIdList = tradeIdToContractId.values().stream().distinct().collect(Collectors.toList());
        Map<Long, ContractCommonInfoResDto> contractMap = Maps.newHashMap();
        if (CollectionUtils.isNotEmpty(contractIdList)) {
            contractMap = contractService.queryContractBaseInfo(contractIdList);
            log.debug("个人数据权限过滤：查询到合同信息数量: {}", contractMap.size());
        } else {
            log.warn("个人数据权限过滤：未找到关联的合同ID列表");
        }

        // 4. 筛选出销售员为当前用户的贸易订单ID
        Set<Long> allowedTradeIds = new HashSet<>();
        for (Long tid : tradeIds) {
            Long cid = tradeIdToContractId.get(tid);
            if (cid == null) {
                // 该贸易订单未关联合同，根据个人权限策略，通常视为不可见或需特殊处理，此处跳过
                continue;
            }
            ContractCommonInfoResDto contractInfo = contractMap.get(cid);
            if (contractInfo == null) {
                // 合同信息缺失，跳过
                continue;
            }
            // 判断合同销售员是否等于当前用户
            if (currentUserId.equals(contractInfo.getSalesmanId())) {
                allowedTradeIds.add(tid);
            }
        }
        log.debug("个人数据权限过滤：匹配到当前用户作为销售员的贸易订单数量: {}", allowedTradeIds.size());

        // 5. 根据允许的贸易订单ID，反向过滤出最终的物流订单ID
        Set<Long> finalLogOrderIds = orders.stream()
                .filter(order -> order.getTOrderId() != null && allowedTradeIds.contains(order.getTOrderId()))
                .map(KwtLogisticsOrder::getId)
                .collect(Collectors.toSet());

        log.debug("个人数据权限过滤：最终保留的物流订单数量: {}", finalLogOrderIds.size());
        return finalLogOrderIds;
    }

    private DataPermissionDTO fetchDataPermissionForCurrentUser() {
        try {
            DataPermissionFilterReqDto reqDto = new DataPermissionFilterReqDto();
            reqDto.setUserId(LoginUserHolder.getUserId());
            reqDto.setRoleId(LoginUserHolder.getCurrentRoleId());
            reqDto.setManager(LoginUserHolder.isManager());
            return dataPermissionFeignService.getDataPermissionFilter(reqDto);
        } catch (Exception e) {
            log.warn("获取数据权限失败，跳过本接口数据权限过滤: {}", e.getMessage());
            return null;
        }
    }

    @NotNull
    private static Set<Long> getEntList(QueryLogisticsOrderReq req) {
        Set<Long> entList = Sets.newHashSet();
        if (StringUtils.isNotBlank(req.getConsignCompanyId())) {
            entList.add(Long.parseLong(req.getConsignCompanyId()));
        }
        if (StringUtils.isNotBlank(req.getCarriageCompanyId())) {
            entList.add(Long.parseLong(req.getCarriageCompanyId()));
        }
        return entList;
    }

    @NotNull
    private Map<Long, KwtLogisticsOrderContract> getLongKwtLogisticsOrderContractMap(List<Long> logOrderIdList) {
        List<KwtLogisticsOrderContract> logOrderContractList = logisticsOrderContractRepository.queryByLogOrderIds(new HashSet<>(logOrderIdList));
        Map<Long, KwtLogisticsOrderContract> logOrderIdAndContractMap = Maps.newHashMap();
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(logOrderContractList)) {
            logOrderIdAndContractMap =
                    logOrderContractList.stream().collect(Collectors.toMap(KwtLogisticsOrderContract::getLOrderId,
                            Function.identity(), (x, y) -> x));
        }
        return logOrderIdAndContractMap;
    }

    @NotNull
    private Map<String, KwtLogisticsOrderAddress> getStringKwtLogisticsOrderAddressMap(List<Long> logOrderIdList) {
        List<KwtLogisticsOrderAddress> logOrderAddressList = logisticsOrderAddressRepository.queryByLogOrderIds(logOrderIdList);
        Map<String, KwtLogisticsOrderAddress> logisticsOrderIdAndUnitTypeKeyAndAddressMap = Maps.newHashMap();
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(logOrderAddressList)) {
            logisticsOrderIdAndUnitTypeKeyAndAddressMap =
                    logOrderAddressList.stream()
                            .collect(Collectors.toMap(x -> x.getLOrderId() + "-" + x.getAddressType(),
                                    Function.identity(), (x, y) -> x));
        }
        return logisticsOrderIdAndUnitTypeKeyAndAddressMap;
    }

    @NotNull
    private Set<Long> getLogOrderIds(QueryLogisticsOrderReq req, Set<Long> entList, Long allEnt) {
        Set<Long> logOrderIds = Sets.newHashSet();
        if (Objects.nonNull(allEnt)) {
            entList.add(allEnt);
        }
        List<KwtLogisticsOrderUnit> logOrderUnits = logisticsOrderUnitRepository.queryByEntIds(entList);
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(logOrderUnits)) {
            Long entId = LoginUserHolder.getEntId();
            // 获取物流订单ID集合
            Set<Long> logOrderIdList = logOrderUnits.stream()
                    .filter(x -> Objects.equals(x.getEntId(), entId))
                    .map(KwtLogisticsOrderUnit::getLOrderId)
                    .collect(Collectors.toSet());

            // 根据托运单位和承运单位进行过滤
            if (StringUtils.isNotBlank(req.getConsignCompanyId())) {
                Set<Long> consignCompanyLogOrderIds = logOrderUnits.stream()
                        .filter(x -> Objects.equals(x.getEntId(), Long.valueOf(req.getConsignCompanyId())))
                        .map(KwtLogisticsOrderUnit::getLOrderId)
                        .collect(Collectors.toSet());
                // 只有当托运单位过滤条件存在时，才进行交集操作
                logOrderIdList.retainAll(consignCompanyLogOrderIds);
            }

            if (StringUtils.isNotBlank(req.getCarriageCompanyId())) {
                Set<Long> carriageCompanyLogOrderIds = logOrderUnits.stream()
                        .filter(x -> Objects.equals(x.getEntId(), Long.valueOf(req.getCarriageCompanyId())))
                        .map(KwtLogisticsOrderUnit::getLOrderId)
                        .collect(Collectors.toSet());
                // 只有当承运单位过滤条件存在时，才进行交集操作
                logOrderIdList.retainAll(carriageCompanyLogOrderIds);
            }

            logOrderIds.addAll(logOrderIdList);
        }
        if (StringUtils.isNotBlank(req.getContractId())) {
            List<KwtLogisticsOrderContract> kwtLogisticsOrderContracts = logisticsOrderContractRepository.queryByContractId(Long.parseLong(req.getContractId()));
            if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(kwtLogisticsOrderContracts)) {
                Set<Long> logOrderIdList = kwtLogisticsOrderContracts.stream()
                        .map(KwtLogisticsOrderContract::getLOrderId)
                        .collect(Collectors.toSet());
                logOrderIds.addAll(logOrderIdList);
                logOrderIds = logOrderIds.stream()
                        .filter(x -> logOrderIdList.contains(x))
                        .collect(Collectors.toSet());
            } else {
                logOrderIds = Sets.newHashSet();
            }
        }

        if (StringUtils.isNotBlank(req.getGoodsName())) {
            List<KwtLogisticsOrderGoods> logisticsOrderGoodsList =
                    logisticsOrderGoodsRepository.queryByGoodsName(req.getGoodsName());
            if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(logisticsOrderGoodsList)) {
                //获取物流订单
                Set<Long> logOrderFormGoodsIds =
                        logisticsOrderGoodsList.stream().map(KwtLogisticsOrderGoods::getLOrderId).collect(Collectors.toSet());
                logOrderIds.retainAll(logOrderFormGoodsIds);
//                logOrderIds  = logOrderIds.stream()
//                        .filter(x->logOrderFormGoodsIds.contains(x))
//                        .collect(Collectors.toSet());
            } else {
                logOrderIds = Sets.newHashSet();
            }
        }

        return logOrderIds;
    }

    private Long getAllEnt(String entId) {
        //根据企业类型查询企业
        Long enterId = null;
        if (org.apache.commons.lang3.StringUtils.isBlank(entId)) {
            enterId = LoginUserHolder.getEntId();
        } else {
            enterId = Long.parseLong(entId);
        }

        return enterId;
    }

    private static LogisticsOrderResp getLogisticsOrderResp(KwtLogisticsOrder kwtLogisticsOrder,
                                                            Map<String, KwtLogisticsOrderUnit> finalLogOrderIdAndUnitTypeKeyAndUnitMap,
                                                            Map<Long, KwtLogisticsOrderGoods> finalLogIdAndGoodsMap,
                                                            Map<Long, KwpGoods> finalGoodsIdAndGoodsMap,
                                                            Map<String, KwtLogisticsOrderAddress> finalLogisticsOrderIdAndUnitTypeKeyAndAddressMap,
                                                            Map<Long, KwtLogisticsOrderContract> finalLogOrderIdAndContractMap,
                                                            Map<String, Map<String, String>> dictValueAndDictResDtoMap,
                                                            Map<Long, OrderDetailVo> tradeIdAndOrderDetailVoMap,
                                                            Map<Long, List<KwtLogisticsOrder>> tradeIdAndLogOrderList,
                                                            Map<Long, List<KwtWaybillOrderSubtask>> logisticsOrderIdAndSubtaskList,
                                                            Map<Long, List<KwtWaybillOrderTicket>> waybillOrderIdAndTicketList) {
        LogisticsOrderResp logisticsOrderResp = new LogisticsOrderResp();
        logisticsOrderResp.setLogisticsOrderId(String.valueOf(kwtLogisticsOrder.getId()));
        logisticsOrderResp.setLogisticsOrderNo(kwtLogisticsOrder.getLOrderNo());
        KwtLogisticsOrderUnit consignCompany = finalLogOrderIdAndUnitTypeKeyAndUnitMap.getOrDefault(kwtLogisticsOrder.getId() + "-" + NumberConstant.ONE,
                new KwtLogisticsOrderUnit());
        logisticsOrderResp.setConsignCompanyId(String.valueOf(consignCompany.getId()));
        logisticsOrderResp.setConsignCompanyName(consignCompany.getFirmName());
        KwtLogisticsOrderUnit carriageCompany = finalLogOrderIdAndUnitTypeKeyAndUnitMap.getOrDefault(kwtLogisticsOrder.getId() +
                        "-" + NumberConstant.TWO,
                new KwtLogisticsOrderUnit());
        logisticsOrderResp.setCarriageCompanyId(String.valueOf(carriageCompany.getId()));
        logisticsOrderResp.setCarriageCompanyName(carriageCompany.getFirmName());
        logisticsOrderResp.setTradeOrderNo(kwtLogisticsOrder.getTOrderNo());

        KwtLogisticsOrderGoods goods = finalLogIdAndGoodsMap.getOrDefault(kwtLogisticsOrder.getId(), new KwtLogisticsOrderGoods());
        KwpGoods kwpGoods = finalGoodsIdAndGoodsMap.get(goods.getGoodsId());
        String priceUnit = "";
        if (Objects.nonNull(kwpGoods)) {
            priceUnit = kwpGoods.getPriceUnit();
            logisticsOrderResp.setGoodsId(String.valueOf(goods.getGoodsId()));
            Map<String, String> goodsTypeMap = dictValueAndDictResDtoMap.getOrDefault(DictTypeEnum.PRODUCT_NAME_TYPE.getType(), new HashMap<>());
            Map<String, String> goodsSpecMap = dictValueAndDictResDtoMap.getOrDefault(DictTypeEnum.GOODS_SPEC.getType(), new HashMap<>());
            logisticsOrderResp.setGoodsName(kwpGoods.getName() + "/" + goodsTypeMap.getOrDefault(kwpGoods.getGoodsType(), "") + "/" + goodsSpecMap.getOrDefault(kwpGoods.getSpec(), ""));
        }
        logisticsOrderResp.setTransportPrice((Objects.nonNull(kwtLogisticsOrder.getPrice()) ? kwtLogisticsOrder.getPrice().setScale(2,
                RoundingMode.HALF_UP).toPlainString() : "0.00") + priceUnit);
        logisticsOrderResp.setChargeType(kwtLogisticsOrder.getBillingMode());
        logisticsOrderResp.setChargeTypeDesc(DictEnum.getLabel(DictTypeEnum.CHARGING_TYPE.getType(),
                String.valueOf(kwtLogisticsOrder.getBillingMode())));
        OrderDetailVo orderDetailVo = tradeIdAndOrderDetailVoMap.getOrDefault(kwtLogisticsOrder.getTOrderId(), new OrderDetailVo());
        logisticsOrderResp.setAmount((Objects.nonNull(orderDetailVo.getAmount()) ?
                orderDetailVo.getAmount().setScale(2, RoundingMode.HALF_UP).toPlainString() : "0.00") + kwtLogisticsOrder.getUnit());
        if (Objects.equals(kwtLogisticsOrder.getOrderType(),1)){
            logisticsOrderResp.setAmount((Objects.nonNull(kwtLogisticsOrder.getAmount()) ?
                    kwtLogisticsOrder.getAmount().setScale(2, RoundingMode.HALF_UP).toPlainString() : "0.00") + kwtLogisticsOrder.getUnit());
        }
        BigDecimal expectedTransportPrice =
                Objects.nonNull(kwtLogisticsOrder.getPrice()) && Objects.nonNull(orderDetailVo.getAmount()) ?
                        kwtLogisticsOrder.getPrice().multiply(orderDetailVo.getAmount()) : BigDecimal.ZERO;
//        BigDecimal actualTransportPrice = Objects.nonNull(kwtLogisticsOrder.getPrice()) && Objects.nonNull(kwtLogisticsOrder.getUnloadAmount()) ?
//                kwtLogisticsOrder.getPrice().multiply(kwtLogisticsOrder.getUnloadAmount()) : BigDecimal.ZERO;

        logisticsOrderResp.setExpectedTransportPrice(expectedTransportPrice.setScale(2, RoundingMode.HALF_UP).toPlainString() + priceUnit);

        List<KwtWaybillOrderSubtask> subtasks = logisticsOrderIdAndSubtaskList.getOrDefault(kwtLogisticsOrder.getId(), new ArrayList<>());
        BigDecimal transportPrice = BigDecimal.ZERO;
        BigDecimal loadAmount= BigDecimal.ZERO;
        BigDecimal unloadAmount = BigDecimal.ZERO;
        //用于计算
        BigDecimal totalAmount = BigDecimal.ZERO;
        if (Objects.equals(kwtLogisticsOrder.getOrderType(),1)){
            log.info("订单类型为1,原矿转运");
            loadAmount = subtasks.stream().filter(x->Objects.nonNull(x.getLoadAmount()))
                    .map(KwtWaybillOrderSubtask::getLoadAmount)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            unloadAmount = subtasks.stream().filter(x->Objects.nonNull(x.getUnloadAmount()))
                    .map(KwtWaybillOrderSubtask::getUnloadAmount)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            transportPrice = Objects.nonNull(kwtLogisticsOrder.getPrice()) ? unloadAmount.multiply(kwtLogisticsOrder.getPrice()) :
                    BigDecimal.ZERO;

            // logisticsOrderResp.setLoadAmount(loadAmount.setScale(2, RoundingMode.HALF_UP).toPlainString() + kwtLogisticsOrder.getUnit());
            logisticsOrderResp.setUnloadAmount(unloadAmount.setScale(2, RoundingMode.HALF_UP).toPlainString() +"吨");
            logisticsOrderResp.setLoadAmount(loadAmount.setScale(2, RoundingMode.HALF_UP).toPlainString() +"吨");

            //设置余量
            BigDecimal orderSurplus = getRaworeSupAmount(kwtLogisticsOrder, tradeIdAndOrderDetailVoMap, tradeIdAndLogOrderList,
                    logisticsOrderIdAndSubtaskList, waybillOrderIdAndTicketList);
            logisticsOrderResp.setOrderSurplus(orderSurplus.toPlainString() + "吨");
            logisticsOrderResp.setRemainingAmount(orderSurplus);
        }else {
            log.info("订单类型不为1,普通订单");
            if (org.apache.commons.lang3.StringUtils.equals(kwtLogisticsOrder.getBillingMode(),
                    DictEnum.CHARGING_TYPE_1.getValue())) {
                loadAmount = subtasks.stream().filter(x->Objects.nonNull(x.getLoadAmount()))
                        .map(KwtWaybillOrderSubtask::getLoadAmount)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                transportPrice = Objects.nonNull(kwtLogisticsOrder.getPrice()) ? loadAmount.multiply(kwtLogisticsOrder.getPrice()) :
                        BigDecimal.ZERO;
                // logisticsOrderResp.setLoadAmount(loadAmount.setScale(2, RoundingMode.HALF_UP).toPlainString() + kwtLogisticsOrder.getUnit());
                logisticsOrderResp.setUnloadAmount("-");
                // logisticsOrderResp.setActualTransportPrice(transportPrice.setScale(2, RoundingMode.HALF_UP).toPlainString() + priceUnit);

            } else if (org.apache.commons.lang3.StringUtils.equals(kwtLogisticsOrder.getBillingMode(),
                    DictEnum.CHARGING_TYPE_2.getValue())) {
                loadAmount = subtasks.stream().filter(x->Objects.nonNull(x.getLoadAmount()))
                        .map(KwtWaybillOrderSubtask::getLoadAmount)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                unloadAmount = subtasks.stream().filter(x->Objects.nonNull(x.getUnloadAmount()))
                        .map(KwtWaybillOrderSubtask::getUnloadAmount)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                transportPrice = Objects.nonNull(kwtLogisticsOrder.getPrice()) ? unloadAmount.multiply(kwtLogisticsOrder.getPrice()) :
                        BigDecimal.ZERO;

                // logisticsOrderResp.setLoadAmount(loadAmount.setScale(2, RoundingMode.HALF_UP).toPlainString() + kwtLogisticsOrder.getUnit());
                logisticsOrderResp.setUnloadAmount(unloadAmount.setScale(2, RoundingMode.HALF_UP).toPlainString() + kwtLogisticsOrder.getUnit());
                //logisticsOrderResp.setActualTransportPrice(transportPrice.setScale(2, RoundingMode.HALF_UP).toPlainString() + priceUnit);
            }
            logisticsOrderResp.setLoadAmount(loadAmount.setScale(2, RoundingMode.HALF_UP).toPlainString() + kwtLogisticsOrder.getUnit());
            //设置余量
            BigDecimal orderSurplus = getSupAmount(kwtLogisticsOrder.getTOrderId(), tradeIdAndOrderDetailVoMap, tradeIdAndLogOrderList,
                    logisticsOrderIdAndSubtaskList, waybillOrderIdAndTicketList);
            logisticsOrderResp.setOrderSurplus(orderSurplus.toPlainString() + kwtLogisticsOrder.getUnit());
            logisticsOrderResp.setRemainingAmount(orderSurplus);
        }
        logisticsOrderResp.setActualTransportPrice(transportPrice.setScale(2, RoundingMode.HALF_UP).toPlainString() + priceUnit);
//        logisticsOrderResp.setActualTransportPrice(actualTransportPrice.setScale(2, RoundingMode.HALF_UP).toPlainString() + priceUnit);
//        logisticsOrderResp.setLoadAmount((Objects.nonNull(kwtLogisticsOrder.getLoadAmount()) ?
//                kwtLogisticsOrder.getLoadAmount().setScale(2, RoundingMode.HALF_UP).toPlainString() : "0.00") + kwtLogisticsOrder.getUnit());
//        logisticsOrderResp.setUnloadAmount((Objects.nonNull(kwtLogisticsOrder.getUnloadAmount()) ?
//                kwtLogisticsOrder.getUnloadAmount().setScale(2, RoundingMode.HALF_UP).toPlainString() : "0.00") + kwtLogisticsOrder.getUnit());

        KwtLogisticsOrderAddress loadAdd = finalLogisticsOrderIdAndUnitTypeKeyAndAddressMap.getOrDefault(kwtLogisticsOrder.getId() + "-" + AddressTypeEnum.SHIPMENT.getCode(), new KwtLogisticsOrderAddress());
        logisticsOrderResp.setLoadAddress(loadAdd.getCityName() + loadAdd.getDetailAddress());
        KwtLogisticsOrderAddress unloadAdd =
                finalLogisticsOrderIdAndUnitTypeKeyAndAddressMap.getOrDefault(kwtLogisticsOrder.getId() + "-" + AddressTypeEnum.TAKE.getCode(), new KwtLogisticsOrderAddress());
        logisticsOrderResp.setUnloadAddress(unloadAdd.getCityName() + unloadAdd.getDetailAddress());
        logisticsOrderResp.setUnloadContacts(unloadAdd.getContacts());
        logisticsOrderResp.setUnloadPhone(unloadAdd.getPhone());
        logisticsOrderResp.setStartTime(DateUtils.format(kwtLogisticsOrder.getStartTime(), DateUtils.DATE_PATTERN));
        logisticsOrderResp.setEndTime(DateUtils.format(kwtLogisticsOrder.getEndTime(), DateUtils.DATE_PATTERN));
        logisticsOrderResp.setDistanceKm(kwtLogisticsOrder.getDistance());
        KwtLogisticsOrderContract orderContract = finalLogOrderIdAndContractMap.getOrDefault(kwtLogisticsOrder.getId(),
                new KwtLogisticsOrderContract());
        logisticsOrderResp.setContractNo(orderContract.getContractNo());
        logisticsOrderResp.setCreateTime(DateUtils.format(kwtLogisticsOrder.getCreateTime(), DateUtils.DATE_TIME_PATTERN));
        logisticsOrderResp.setStatus(String.valueOf(kwtLogisticsOrder.getStatus()));
        logisticsOrderResp.setStatusDesc(LogisticsOrderV1Enum.getDesc(kwtLogisticsOrder.getStatus()));

        return logisticsOrderResp;
    }

    /**
     * 计算贸易订单的剩余可分配量（余量）
     * <p>
     * 计算逻辑：订单余量 = 贸易订单总货物量 - 已使用的量
     * 其中“已使用的量”包括：
     * 1. 子运单的委托量（EntrustAmount）
     * 2. 磅单的实际装/卸货量（根据计费模式决定取装货还是卸货）
     * </p>
     *
     * @param tradeOrderId                贸易订单ID
     * @param tradeIdAndOrderDetailVoMap  贸易订单ID与详情对象的映射
     * @param tradeIdAndLogOrderList      贸易订单ID与关联物流订单列表的映射
     * @param logisticsOrderIdAndSubtaskList 物流订单ID与子运单列表的映射
     * @param waybillOrderIdAndTicketList    主运单ID与磅单列表的映射
     * @return 剩余可分配量，保留两位小数，最小为0
     */
    private static BigDecimal getSupAmount(Long tradeOrderId,
                                           Map<Long, OrderDetailVo> tradeIdAndOrderDetailVoMap,
                                           Map<Long, List<KwtLogisticsOrder>> tradeIdAndLogOrderList,
                                           Map<Long, List<KwtWaybillOrderSubtask>> logisticsOrderIdAndSubtaskList,
                                           Map<Long, List<KwtWaybillOrderTicket>> waybillOrderIdAndTicketList) {
        log.debug("开始计算贸易订单余量，tradeOrderId: {}", tradeOrderId);

        // 1. 获取贸易订单基础信息及总货物量
        OrderDetailVo detailVo = tradeIdAndOrderDetailVoMap.getOrDefault(tradeOrderId, new OrderDetailVo());
        BigDecimal tradeAmount = Optional.ofNullable(detailVo).map(OrderDetailVo::getAmount).orElse(BigDecimal.ZERO);
        log.debug("贸易订单总货物量: {}", tradeAmount);

        // 2. 获取该贸易订单关联的所有物流订单
        List<KwtLogisticsOrder> kwtLogisticsOrders = tradeIdAndLogOrderList.get(tradeOrderId);
        BigDecimal usedAmount = BigDecimal.ZERO;

        if (CollectionUtils.isNotEmpty(kwtLogisticsOrders)) {
            log.debug("关联物流订单数量: {}", kwtLogisticsOrders.size());
            for (KwtLogisticsOrder kwtLogisticsOrder : kwtLogisticsOrders) {
                Long logOrderId = kwtLogisticsOrder.getId();
                // 获取当前物流订单下的所有子运单
                List<KwtWaybillOrderSubtask> waybillOrderSubtasks = logisticsOrderIdAndSubtaskList.getOrDefault(logOrderId, Collections.emptyList());

                if (CollectionUtils.isEmpty(waybillOrderSubtasks)) {
                    log.debug("物流订单 {} 下无子运单，跳过", logOrderId);
                    continue;
                }

                // 3. 根据计费模式确定磅单类型（装货或卸货）
                // CHARGING_TYPE_1: 按装货量计费 -> 对应装货磅单 (SHIPMENT)
                // CHARGING_TYPE_2: 按卸货量计费 -> 对应卸货磅单 (TAKE)
                Integer ticketType;
                String billingMode = kwtLogisticsOrder.getBillingMode();
                if (org.apache.commons.lang3.StringUtils.equals(billingMode, DictEnum.CHARGING_TYPE_1.getValue())) {
                    ticketType = AddressTypeEnum.SHIPMENT.getCode();
                } else if (org.apache.commons.lang3.StringUtils.equals(billingMode, DictEnum.CHARGING_TYPE_2.getValue())) {
                    ticketType = AddressTypeEnum.TAKE.getCode();
                } else {
                    // 未知计费模式，记录警告并跳过该物流订单的计算，避免数据错误
                    log.warn("余量计算跳过未知计费模式，tradeOrderId:{}, logOrderId:{}, billingMode:{}",
                            tradeOrderId, logOrderId, billingMode);
                    continue;
                }

                // 4. 计算子运单委托量总和
                // 过滤条件：对象非空、状态非取消、委托量非空
                List<Integer> statusList = Arrays.asList(CarWaybillV1Enum.COMPLETED.getCode(), CarWaybillV1Enum.CANCELLED.getCode());
                BigDecimal entrustAmount = waybillOrderSubtasks.stream()
                        .filter(Objects::nonNull)
                        .filter(subtask -> !statusList.contains(subtask.getStatus()))
                        .map(KwtWaybillOrderSubtask::getEntrustAmount)
                        .filter(Objects::nonNull)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);

                // 5. 计算磅单实际量总和
                // 逻辑：子运单 -> 主运单ID -> 磅单列表 -> 过滤特定类型 -> 累加金额/数量
                BigDecimal ticketAmount = waybillOrderSubtasks.stream()
                        .filter(Objects::nonNull)
                        .filter(subtask -> !Objects.equals(subtask.getStatus(), CarWaybillV1Enum.CANCELLED.getCode()))
                        .map(KwtWaybillOrderSubtask::getWOrderId)
                        .filter(Objects::nonNull)
                        .flatMap(wOrderId -> waybillOrderIdAndTicketList.getOrDefault(wOrderId, Collections.emptyList()).stream())
                        .filter(Objects::nonNull)
                        // 只统计与计费模式匹配的磅单类型（装或卸）
                        .filter(ticket -> Objects.equals(ticket.getType(), ticketType))
                        .map(KwtWaybillOrderTicket::getAmount)
                        .filter(Objects::nonNull)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);

                // 累加当前物流订单的已使用量
                BigDecimal currentUsed = entrustAmount.add(ticketAmount);
                usedAmount = usedAmount.add(currentUsed);

                log.debug("物流订单 {} 计算详情: 委托量={}, 磅单量={}, 计费类型={}",
                        logOrderId, entrustAmount, ticketAmount, ticketType);
            }
        }

        // 6. 计算最终余量：总量 - 已用量，若结果小于0则置为0
        BigDecimal surplus = tradeAmount.subtract(usedAmount);
        if (surplus.compareTo(BigDecimal.ZERO) <= 0) {
            log.info("贸易订单 {} 余量计算结果为负或零，重置为0。总量: {}, 已用: {}", tradeOrderId, tradeAmount, usedAmount);
            surplus = BigDecimal.ZERO;
        } else {
            log.debug("贸易订单 {} 余量计算正常。总量: {}, 已用: {}, 余量: {}", tradeOrderId, tradeAmount, usedAmount, surplus);
        }

        // 保留两位小数，四舍五入
        return surplus.setScale(2, RoundingMode.HALF_UP);
    }

    private static BigDecimal getRaworeSupAmount(KwtLogisticsOrder kwtLogisticsOrder,
                                           Map<Long, OrderDetailVo> tradeIdAndOrderDetailVoMap,
                                           Map<Long, List<KwtLogisticsOrder>> tradeIdAndLogOrderList,
                                           Map<Long, List<KwtWaybillOrderSubtask>> logisticsOrderIdAndSubtaskList,
                                           Map<Long, List<KwtWaybillOrderTicket>> waybillOrderIdAndTicketList) {
        log.debug("开始计算原矿订单余量，物流订单号: {}", kwtLogisticsOrder.getLOrderNo());

        // 1. 获取贸易订单基础信息及总货物量
        BigDecimal tradeAmount = Optional.ofNullable(kwtLogisticsOrder).map(KwtLogisticsOrder::getAmount).orElse(BigDecimal.ZERO);
        log.debug("贸易订单总货物量: {}", tradeAmount);

        // 2. 获取该贸易订单关联的所有物流订单
        BigDecimal usedAmount = BigDecimal.ZERO;

        if (Objects.nonNull(kwtLogisticsOrder)) {
            log.debug("开始获取该贸易订单关联的所有物流订单");
            Long logOrderId = kwtLogisticsOrder.getId();
            // 获取当前物流订单下的所有子运单
            List<KwtWaybillOrderSubtask> waybillOrderSubtasks = logisticsOrderIdAndSubtaskList.getOrDefault(logOrderId, Collections.emptyList());

            if (CollectionUtils.isEmpty(waybillOrderSubtasks)) {
                log.debug("物流订单 {} 下无子运单，跳过", logOrderId);
                return BigDecimal.ZERO;
            }

            // 3. 根据计费模式确定磅单类型（装货或卸货）
            // CHARGING_TYPE_1: 按装货量计费 -> 对应装货磅单 (SHIPMENT)
            // CHARGING_TYPE_2: 按卸货量计费 -> 对应卸货磅单 (TAKE)
            Integer ticketType;
            String billingMode = kwtLogisticsOrder.getBillingMode();
            if (org.apache.commons.lang3.StringUtils.equals(billingMode, DictEnum.CHARGING_TYPE_1.getValue())) {
                ticketType = AddressTypeEnum.SHIPMENT.getCode();
            } else if (org.apache.commons.lang3.StringUtils.equals(billingMode, DictEnum.CHARGING_TYPE_2.getValue())) {
                ticketType = AddressTypeEnum.TAKE.getCode();
            } else {
                // 未知计费模式，记录警告并跳过该物流订单的计算，避免数据错误
                log.warn("余量计算跳过未知计费模式， logOrderId:{}, billingMode:{}",
                                 logOrderId, billingMode);
                return BigDecimal.ZERO;
            }

            // 4. 计算子运单委托量总和
            // 过滤条件：对象非空、状态非取消、委托量非空
            List<Integer> statusList = Arrays.asList(CarWaybillV1Enum.COMPLETED.getCode(), CarWaybillV1Enum.CANCELLED.getCode());
            BigDecimal entrustAmount = waybillOrderSubtasks.stream()
                    .filter(Objects::nonNull)
                    .filter(subtask -> !statusList.contains(subtask.getStatus()))
                    .map(KwtWaybillOrderSubtask::getEntrustAmount)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            // 5. 计算磅单实际量总和
            // 逻辑：子运单 -> 主运单ID -> 磅单列表 -> 过滤特定类型 -> 累加金额/数量
            BigDecimal ticketAmount = waybillOrderSubtasks.stream()
                    .filter(Objects::nonNull)
                    .filter(subtask -> !Objects.equals(subtask.getStatus(), CarWaybillV1Enum.CANCELLED.getCode()))
                    .map(KwtWaybillOrderSubtask::getWOrderId)
                    .filter(Objects::nonNull)
                    .flatMap(wOrderId -> waybillOrderIdAndTicketList.getOrDefault(wOrderId, Collections.emptyList()).stream())
                    .filter(Objects::nonNull)
                    // 只统计与计费模式匹配的磅单类型（装或卸）
                    .filter(ticket -> Objects.equals(ticket.getType(), ticketType))
                    .map(KwtWaybillOrderTicket::getAmount)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            // 累加当前物流订单的已使用量
            BigDecimal currentUsed = entrustAmount.add(ticketAmount);
            usedAmount = usedAmount.add(currentUsed);

            log.debug("物流订单 {} 计算详情: 委托量={}, 磅单量={}, 计费类型={}",
                    logOrderId, entrustAmount, ticketAmount, ticketType);
        }

        // 6. 计算最终余量：总量 - 已用量，若结果小于0则置为0
        BigDecimal surplus = tradeAmount.subtract(usedAmount);
        if (surplus.compareTo(BigDecimal.ZERO) <= 0) {
            log.info("物流订单 {} 余量计算结果为负或零，重置为0。总量: {}, 已用: {}", kwtLogisticsOrder.getId(), tradeAmount, usedAmount);
            surplus = BigDecimal.ZERO;
        } else {
            log.debug("物流订单 {} 余量计算正常。总量: {}, 已用: {}, 余量: {}",  kwtLogisticsOrder.getId(), tradeAmount, usedAmount, surplus);
        }

        // 保留两位小数，四舍五入
        return surplus.setScale(2, RoundingMode.HALF_UP);
    }

    public LogisticsOrderDetailResp getLogisticsOrderDetail(@Valid LogisticsOrderReq req) {
        KwtLogisticsOrder logisticsOrder =
                logisticsOrderRepository.queryByLogisticsOrderId(Long.valueOf(req.getLogisticsOrderId()));
        if (Objects.isNull(logisticsOrder)) {
            throw new BusinessException("物流订单不存在");
        }
        //根据物流订单号查询物流合同
        KwtLogisticsOrderContract orderContract = logisticsOrderContractRepository.queryByLogOrderId(logisticsOrder.getId());
        if (Objects.isNull(orderContract)) {
            log.info("物流合同不存在,物流订单号:{}", logisticsOrder.getId());
            throw new BusinessException("物流合同不存在");
        }
        KwcContractLogisticsDto tradeContractResDto = contractService.queryContractByContractId(orderContract.getContractId());
        //根据订单号查询物流公司信息
        List<KwtLogisticsOrderUnit> unitList = logisticsOrderUnitRepository.queryByLOrderId(logisticsOrder.getId());
        Map<String, KwtLogisticsOrderUnit> logOrderIdUnitTypeKeyAndUnitMap = Maps.newHashMap();
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(unitList)) {
            logOrderIdUnitTypeKeyAndUnitMap = unitList.stream()
                    .collect(Collectors.toMap(x -> x.getLOrderId() + "-" + x.getUnitType(), Function.identity(), (v1, v2) -> v1));

        }

        //根据物流订单号查询商品信息
        KwtLogisticsOrderGoods goods = logisticsOrderGoodsRepository.queryByLogOrderId(logisticsOrder.getId());
        KwpGoods kwpGoods = null;
        if (Objects.nonNull(goods)) {
            kwpGoods = goodsInfoService.getGoodsById(goods.getGoodsId());
        }

        //根据订单号查询装卸货地址
        List<KwtLogisticsOrderAddress> addressList = logisticsOrderAddressRepository.queryByLogOrderId(logisticsOrder.getId());
        Map<String, KwtLogisticsOrderAddress> logOrderIdAndUnitTypeKeyAndAddressMap = Maps.newHashMap();
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(addressList)) {
            logOrderIdAndUnitTypeKeyAndAddressMap = addressList.stream()
                    .collect(Collectors.toMap(x -> x.getLOrderId() + "-" + x.getAddressType(), Function.identity(), (v1, v2) -> v1));
        }

        //根据物流订单号查询运单信息
        List<KwtWaybillOrderSubtask> waybillOrderSubtasks = waybillOrderSubtaskRepository.queryByLogId(logisticsOrder.getId());

        //根据贸易订单号查询物流订单
        List<KwtLogisticsOrder> logOrderList = logisticsOrderRepository.queryByTradeOrderId(logisticsOrder.getTOrderId());
        //查询贸易订单
        OrderDetailVo orderDetailVo = tradeOrderInfoService.queryByTradeOrderId(logisticsOrder.getTOrderId());
        //查询字典
        Map<String, Map<String, String>> dictValueAndDictResDtoMap = remoteSystemService.queryDictByType(Arrays.asList(DictTypeEnum.PRODUCT_NAME_TYPE.getType(), DictTypeEnum.GOODS_SPEC.getType()));


        //获取返回信息
        return getLogisticsOrderDetailResp(orderContract, tradeContractResDto, logOrderIdUnitTypeKeyAndUnitMap, logisticsOrder, kwpGoods,
                logOrderIdAndUnitTypeKeyAndAddressMap, waybillOrderSubtasks, logOrderList, orderDetailVo, dictValueAndDictResDtoMap);

    }

    @NotNull
    private LogisticsOrderDetailResp getLogisticsOrderDetailResp(KwtLogisticsOrderContract orderContract,
                                                                 KwcContractLogisticsDto tradeContractResDto,
                                                                 Map<String, KwtLogisticsOrderUnit> logOrderIdUnitTypeKeyAndUnitMap,
                                                                 KwtLogisticsOrder logisticsOrder,
                                                                 KwpGoods kwpGoods,
                                                                 Map<String, KwtLogisticsOrderAddress> logOrderIdAndUnitTypeKeyAndAddressMap,
                                                                 List<KwtWaybillOrderSubtask> waybillOrderSubtasks,
                                                                 List<KwtLogisticsOrder> logOrderList,
                                                                 OrderDetailVo orderDetailVo,
                                                                 Map<String, Map<String, String>> dictValueAndDictResDtoMap) {
        LogisticsOrderDetailResp logisticsOrderDetailResp = new LogisticsOrderDetailResp();
        //设置合同信息
        setContractInfo(orderContract, tradeContractResDto, logisticsOrderDetailResp);
        //设置单位信息
        setUnitInfo(logOrderIdUnitTypeKeyAndUnitMap, logisticsOrder, logisticsOrderDetailResp);

        //设置贸易信息
        setGoodsInfo(kwpGoods, logisticsOrder, logisticsOrderDetailResp, orderDetailVo, dictValueAndDictResDtoMap);

        //设置装卸货地址信息
        setAddressInfo(logOrderIdAndUnitTypeKeyAndAddressMap, logisticsOrder, logisticsOrderDetailResp);

        //设置履约信息
        setPerformInfo(logisticsOrder, waybillOrderSubtasks, logisticsOrderDetailResp, logOrderList, orderDetailVo, kwpGoods);

        //设置物流信息
        setLogisticInfo(logisticsOrder, logisticsOrderDetailResp);

        return logisticsOrderDetailResp;
    }

    private static void setLogisticInfo(KwtLogisticsOrder logisticsOrder, LogisticsOrderDetailResp logisticsOrderDetailResp) {
        LogisticsOrderDetailResp.LogisticOrderInfo logisticOrderInfo = new LogisticsOrderDetailResp.LogisticOrderInfo();
        logisticOrderInfo.setLogisticsOrderStatus(String.valueOf(logisticsOrder.getStatus()));
        logisticOrderInfo.setLogisticsOrderStatusDesc(LogisticsOrderV1Enum.getDesc(logisticsOrder.getStatus()));
        logisticOrderInfo.setStartTime(DateUtils.format(logisticsOrder.getStartTime(), DateUtils.FORMAT9));
        logisticOrderInfo.setEndTime(DateUtils.format(logisticsOrder.getEndTime(), DateUtils.FORMAT9));
        logisticsOrderDetailResp.setLogisticOrderInfo(logisticOrderInfo);
    }

    private void setPerformInfo(KwtLogisticsOrder logisticsOrder,
                                List<KwtWaybillOrderSubtask> waybillOrderSubtasks,
                                LogisticsOrderDetailResp logisticsOrderDetailResp,
                                List<KwtLogisticsOrder> logOrderList,
                                OrderDetailVo orderDetailVo, KwpGoods kwpGoods) {
        LogisticsOrderDetailResp.PerformanceInfoVO performanceInfoVO = new LogisticsOrderDetailResp.PerformanceInfoVO();
        performanceInfoVO.setBillingMode(logisticsOrder.getBillingMode());
        performanceInfoVO.setBillingModeDesc(DictEnum.getLabel(DictTypeEnum.CHARGING_TYPE.getType(),
                logisticsOrder.getBillingMode()));
        long completedCarNum = waybillOrderSubtasks.stream()
                .filter(x -> Objects.equals(x.getStatus(), CarWaybillV1Enum.COMPLETED.getCode())).count();
        performanceInfoVO.setCompletedCarNum(String.valueOf(completedCarNum));
        BigDecimal orderAmount = waybillOrderSubtasks.stream().filter(x -> !Arrays.asList(CarWaybillV1Enum.COMPLETED.getCode(),
                        CarWaybillV1Enum.CANCELLED.getCode()).contains(x.getStatus()))
                .map(KwtWaybillOrderSubtask::getEntrustAmount)
                .filter(x -> Objects.nonNull(x))
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        performanceInfoVO.setOrderAmount(orderAmount.setScale(2, RoundingMode.HALF_UP).toPlainString() + logisticsOrder.getUnit());
        BigDecimal loadAmount = BigDecimal.ZERO;
        BigDecimal unloadAmount = BigDecimal.ZERO;
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(waybillOrderSubtasks)) {
            loadAmount = waybillOrderSubtasks.stream()
                    .filter(x -> Objects.nonNull(x.getLoadAmount()))
                    .map(KwtWaybillOrderSubtask::getLoadAmount)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            unloadAmount = waybillOrderSubtasks.stream()
                    .filter(x -> !Objects.equals(x.getStatus(), CarWaybillV1Enum.CANCELLED.getCode()))
                    .filter(x -> Objects.nonNull(x.getUnloadAmount()))
                    .map(KwtWaybillOrderSubtask::getUnloadAmount)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
        }
        BigDecimal tradeAmount = Optional.ofNullable(orderDetailVo).map(OrderDetailVo::getAmount).orElse(BigDecimal.ZERO);
        BigDecimal totalCarriageCost = BigDecimal.ZERO;
        //用于计算
        BigDecimal totalAmount = BigDecimal.ZERO;
        if (Objects.equals(logisticsOrder.getOrderType(), 1)){
            log.info("物流单类型为1,原矿转运");
            BigDecimal orderAmount1 = Objects.nonNull(logisticsOrder.getAmount()) ? logisticsOrder.getAmount() : BigDecimal.ZERO;
            performanceInfoVO.setOrderAmount(orderAmount1.setScale(2, RoundingMode.HALF_UP).toPlainString() + "吨");
            totalCarriageCost = Objects.nonNull(logisticsOrder.getPrice()) ? unloadAmount.multiply(logisticsOrder.getPrice()) :
                    BigDecimal.ZERO;
            performanceInfoVO.setLoadAmount(loadAmount.setScale(2, RoundingMode.HALF_UP).toPlainString() + "吨");
            performanceInfoVO.setUnloadAmount(unloadAmount.setScale(2, RoundingMode.HALF_UP).toPlainString() + "吨");
            BigDecimal surplusAmount = orderAmount1.subtract(orderAmount.add(unloadAmount)).compareTo(BigDecimal.ZERO) <= 0 ? BigDecimal.ZERO : orderAmount1.subtract(orderAmount.add(unloadAmount));
            performanceInfoVO.setSurplusAmount(surplusAmount.setScale(2, RoundingMode.HALF_UP).toPlainString() + "吨");
        }else {
            log.info("物流单类型不为1,普通物流");
            if (org.apache.commons.lang3.StringUtils.equals(logisticsOrder.getBillingMode(),
                    DictEnum.CHARGING_TYPE_1.getValue())) {
                totalCarriageCost = Objects.nonNull(logisticsOrder.getPrice()) ? loadAmount.multiply(logisticsOrder.getPrice()) :
                        BigDecimal.ZERO;
                performanceInfoVO.setLoadAmount(loadAmount.setScale(2, RoundingMode.HALF_UP).toPlainString() + logisticsOrder.getUnit());
                performanceInfoVO.setUnloadAmount("-");
                BigDecimal surplusAmount = tradeAmount.subtract(orderAmount.add(loadAmount)).compareTo(BigDecimal.ZERO) <= 0 ? BigDecimal.ZERO : tradeAmount.subtract(orderAmount.add(loadAmount));
                performanceInfoVO.setSurplusAmount(surplusAmount.setScale(2, RoundingMode.HALF_UP).toPlainString() + logisticsOrder.getUnit());

            } else if (org.apache.commons.lang3.StringUtils.equals(logisticsOrder.getBillingMode(),
                    DictEnum.CHARGING_TYPE_2.getValue())) {
                totalCarriageCost = Objects.nonNull(logisticsOrder.getPrice()) ? unloadAmount.multiply(logisticsOrder.getPrice()) :
                        BigDecimal.ZERO;
                performanceInfoVO.setLoadAmount(loadAmount.setScale(2, RoundingMode.HALF_UP).toPlainString() + logisticsOrder.getUnit());
                performanceInfoVO.setUnloadAmount(unloadAmount.setScale(2, RoundingMode.HALF_UP).toPlainString() + logisticsOrder.getUnit());
                BigDecimal surplusAmount = tradeAmount.subtract(orderAmount.add(unloadAmount)).compareTo(BigDecimal.ZERO) <= 0 ? BigDecimal.ZERO : tradeAmount.subtract(orderAmount.add(unloadAmount));
                performanceInfoVO.setSurplusAmount(surplusAmount.setScale(2, RoundingMode.HALF_UP).toPlainString() + logisticsOrder.getUnit());

            }
        }
        String priceUnit = Optional.ofNullable(kwpGoods).map(KwpGoods::getPriceUnit).orElse("");
        performanceInfoVO.setTotalCarriageCost(totalCarriageCost.setScale(2, RoundingMode.HALF_UP).toPlainString() + priceUnit);

        // BigDecimal totalAmount = getTotalAmount(logOrderList);

        logisticsOrderDetailResp.setPerformanceInfoVO(performanceInfoVO);
    }

    @NotNull
    private BigDecimal getTotalAmount(List<KwtLogisticsOrder> logOrderList) {
        BigDecimal totalAmount = BigDecimal.ZERO;
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(logOrderList)) {
            return totalAmount;
        }
        // 计费方式
        String billingMode = logOrderList.get(0).getBillingMode();
        // 物流订单ID列表
        List<Long> logOrderIds = logOrderList.stream()
                .map(KwtLogisticsOrder::getId)
                .collect(Collectors.toList());

        // 根据物流订单查询子运单
        List<KwtWaybillOrderSubtask> waybillOrderSubtasks = waybillOrderSubtaskRepository.queryByLogIds(logOrderIds);
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(waybillOrderSubtasks)) {
            return totalAmount;
        }
        // 筛选出状态为已完成的子运单
        List<KwtWaybillOrderSubtask> pendingUnloadSubtasks = waybillOrderSubtasks.stream()
                .filter(subtask -> !Objects.equals(subtask.getStatus(), CarWaybillV1Enum.CANCELLED.getCode()))
                .collect(Collectors.toList());

        if (org.apache.commons.collections4.CollectionUtils.isEmpty(pendingUnloadSubtasks)) {
            return totalAmount;
        }
        // 已接单量
        BigDecimal entrustAmount = pendingUnloadSubtasks.stream()
                .map(KwtWaybillOrderSubtask::getEntrustAmount)
                .filter(x -> Objects.nonNull(x))
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        // 累计卸货量
        BigDecimal unloadAmount = pendingUnloadSubtasks.stream()
                .map(KwtWaybillOrderSubtask::getUnloadAmount)
                .filter(x -> Objects.nonNull(x))
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        return entrustAmount.add(unloadAmount);
    }

    private static void setAddressInfo(Map<String, KwtLogisticsOrderAddress> logOrderIdAndUnitTypeKeyAndAddressMap, KwtLogisticsOrder logisticsOrder, LogisticsOrderDetailResp logisticsOrderDetailResp) {
        LogisticsOrderDetailResp.LoadingInfoVO loadingInfoVO = new LogisticsOrderDetailResp.LoadingInfoVO();
        KwtLogisticsOrderAddress loadAdd = logOrderIdAndUnitTypeKeyAndAddressMap.getOrDefault(logisticsOrder.getId() + "-" + AddressTypeEnum.SHIPMENT.getCode(),
                new KwtLogisticsOrderAddress());
        loadingInfoVO.setLoadAddress("(" + loadAdd.getName() + ")" + loadAdd.getCityName() + loadAdd.getDetailAddress());
        KwtLogisticsOrderAddress unloadAdd =
                logOrderIdAndUnitTypeKeyAndAddressMap.getOrDefault(logisticsOrder.getId() + "-" + AddressTypeEnum.TAKE.getCode(),
                        new KwtLogisticsOrderAddress());
        loadingInfoVO.setUnloadAddress("(" + unloadAdd.getName() + ")" + unloadAdd.getCityName() + unloadAdd.getDetailAddress());
        loadingInfoVO.setUnloadContacts(unloadAdd.getContacts());
        loadingInfoVO.setUnloadPhone(unloadAdd.getPhone());
        loadingInfoVO.setReferenceDistance(logisticsOrder.getDistance());
        logisticsOrderDetailResp.setLoadingInfoVO(loadingInfoVO);
    }

    private static void setGoodsInfo(KwpGoods kwpGoods, KwtLogisticsOrder logisticsOrder,
                                     LogisticsOrderDetailResp logisticsOrderDetailResp,
                                     OrderDetailVo orderDetailVo,
                                     Map<String, Map<String, String>> dictValueAndDictResDtoMap) {
        LogisticsOrderDetailResp.GoodsInfoVO goodsInfoVO = new LogisticsOrderDetailResp.GoodsInfoVO();
        String priceUnit = "";
        if (Objects.nonNull(kwpGoods)) {
            Map<String, String> goodsTypeMap = dictValueAndDictResDtoMap.getOrDefault(DictTypeEnum.PRODUCT_NAME_TYPE.getType(), new HashMap<>());
            Map<String, String> goodsSpecMap = dictValueAndDictResDtoMap.getOrDefault(DictTypeEnum.GOODS_SPEC.getType(), new HashMap<>());
            goodsInfoVO.setGoodsName(kwpGoods.getName() + "/" + goodsTypeMap.getOrDefault(kwpGoods.getGoodsType(), "") + "/" + goodsSpecMap.getOrDefault(kwpGoods.getSpec(), ""));
            priceUnit = kwpGoods.getPriceUnit();
        }
        goodsInfoVO.setUnitPrice((Objects.nonNull(logisticsOrder.getPrice()) ? logisticsOrder.getPrice().setScale(2, RoundingMode.HALF_UP).toPlainString() : "0.00") + "元");
        if (Objects.equals(logisticsOrder.getOrderType(), 1)){
            log.info("物流单类型为1,原矿转运，设置订单总量");
            goodsInfoVO.setOrderAmount((Objects.nonNull(logisticsOrder.getAmount()) ? logisticsOrder.getAmount().setScale(2, RoundingMode.HALF_UP).toPlainString() : "0.00") + "吨");
        }else {
            log.info("物流单类型不为1,普通物流，设置订单总量");
            goodsInfoVO.setOrderAmount((Objects.nonNull(orderDetailVo.getAmount()) ? orderDetailVo.getAmount().setScale(2, RoundingMode.HALF_UP).toPlainString() : "0.00") + logisticsOrder.getUnit());
        }

        BigDecimal carriageCost = Objects.nonNull(orderDetailVo.getAmount()) && Objects.nonNull(logisticsOrder.getPrice()) ?
                orderDetailVo.getAmount().multiply(logisticsOrder.getPrice()) : BigDecimal.ZERO;
        goodsInfoVO.setCarriageCost(carriageCost.setScale(2, RoundingMode.HALF_UP).toPlainString() + priceUnit);
        logisticsOrderDetailResp.setGoodsInfoVO(goodsInfoVO);
    }

    private static void setUnitInfo(Map<String, KwtLogisticsOrderUnit> logOrderIdUnitTypeKeyAndUnitMap, KwtLogisticsOrder logisticsOrder, LogisticsOrderDetailResp logisticsOrderDetailResp) {
        LogisticsOrderDetailResp.UnitInfoVO unitInfoVO = new LogisticsOrderDetailResp.UnitInfoVO();
        KwtLogisticsOrderUnit consignUnit =
                logOrderIdUnitTypeKeyAndUnitMap.getOrDefault(logisticsOrder.getId() + "-" + NumberConstant.ONE,
                        new KwtLogisticsOrderUnit());
        unitInfoVO.setConsignUnitId(String.valueOf(consignUnit.getEntId()));
        unitInfoVO.setConsignUnitName(consignUnit.getFirmName());
        unitInfoVO.setConsignUnitPhone(consignUnit.getPhone());
        KwtLogisticsOrderUnit carriageUnit =
                logOrderIdUnitTypeKeyAndUnitMap.getOrDefault(logisticsOrder.getId() + "-" + NumberConstant.TWO,
                        new KwtLogisticsOrderUnit());
        unitInfoVO.setCarriageUnitId(String.valueOf(carriageUnit.getEntId()));
        unitInfoVO.setCarriageUnitName(carriageUnit.getFirmName());
        unitInfoVO.setCarriageUnitPhone(carriageUnit.getPhone());
        logisticsOrderDetailResp.setUnitInfoVO(unitInfoVO);
    }

    private static void setContractInfo(KwtLogisticsOrderContract orderContract, KwcContractLogisticsDto tradeContractResDto, LogisticsOrderDetailResp logisticsOrderDetailResp) {
        LogisticsOrderDetailResp.ContractInfoVO contractInfoVO = new LogisticsOrderDetailResp.ContractInfoVO();
        if (Objects.nonNull(tradeContractResDto)) {
            contractInfoVO.setContractId(tradeContractResDto.getId());
            contractInfoVO.setContractNo(tradeContractResDto.getContractNo());
            contractInfoVO.setContractName(tradeContractResDto.getName());
        }
        logisticsOrderDetailResp.setContractInfoVO(contractInfoVO);
    }

    public PageDataResult<LogisticsOrderDispatchResp> getLogisticsOrderDispatch(@Valid LogisticsOrderReq req) {
        KwtLogisticsOrder kwtLogisticsOrder = logisticsOrderRepository.queryByLogisticsOrderId(Long.parseLong(req.getLogisticsOrderId()));
        if (Objects.nonNull(kwtLogisticsOrder)) {
            throw new BusinessException("物流订单不存在");
        }
        //通过物流订单号查询运单

        List<KwtWaybillOrderSubtask> waybillOrderSubtasks = waybillOrderSubtaskRepository.queryByLogId(kwtLogisticsOrder.getId());
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(waybillOrderSubtasks)) {
            return PageDataResult.empty(req.getPageNum(), req.getPageSize());
        }
        //物流订单id列表
        Set<Long> billOrderIds =
                waybillOrderSubtasks.stream().map(KwtWaybillOrderSubtask::getWOrderId).collect(Collectors.toSet());
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(billOrderIds)) {
            return PageDataResult.empty(req.getPageNum(), req.getPageSize());
        }
        //根据运单id查询物流运单
        IPage<KwtWaybillOrder> page = waybillOrderRepository.queryPageByBillOrderIds(billOrderIds, req.getPageNum(), req.getPageSize());

        List<KwtWaybillOrder> records = page.getRecords();
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(records)) {
            return PageDataResult.empty(req.getPageNum(), req.getPageSize());
        }
        //获取车辆id
        List<Long> truckIds = records.stream()
                .map(KwtWaybillOrder::getTruckId)
                .distinct()
                .collect(Collectors.toList());
        Map<Long, RTruckVo> truckIdAndTruckMap = Maps.newHashMap();
        List<RTruckVo> truckByTruckIds = Lists.newArrayList();
        //查询车辆信息
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(truckIds)) {
            truckByTruckIds = remoteFleetService.findTruckByTruckIds(truckIds);
        }
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(truckByTruckIds)) {
            truckIdAndTruckMap =
                    truckByTruckIds.stream()
                            .collect(Collectors.toMap(RTruckVo::getId, Function.identity(), (k1, k2) -> k1));
        }
        //组装返回信息
        Map<Long, RTruckVo> finalTruckIdAndTruckMap = truckIdAndTruckMap;
        List<LogisticsOrderDispatchResp> resps = records.stream()
                .map(record -> getLogisticsOrderDispatchResp(record, finalTruckIdAndTruckMap, kwtLogisticsOrder))
                .collect(Collectors.toList());
        return PageDataResult.of(page, resps);
    }

    @NotNull
    private static LogisticsOrderDispatchResp getLogisticsOrderDispatchResp(KwtWaybillOrder record, Map<Long, RTruckVo> finalTruckIdAndTruckMap, KwtLogisticsOrder kwtLogisticsOrder) {
        LogisticsOrderDispatchResp logisticsOrderDispatchResp = new LogisticsOrderDispatchResp();
        logisticsOrderDispatchResp.setWayBillId(String.valueOf(record.getId()));
        RTruckVo truckVo = finalTruckIdAndTruckMap.getOrDefault(record.getTruckId(), new RTruckVo());
        logisticsOrderDispatchResp.setTruckNo(truckVo.getTruckNo());
        logisticsOrderDispatchResp.setCarAxis(truckVo.getCarAxis());
        logisticsOrderDispatchResp.setFinishWaybillCount(String.valueOf(kwtLogisticsOrder.getTotalTake()));
        logisticsOrderDispatchResp.setLoadAmount(Objects.nonNull(record.getLoadAmount()) ?
                record.getLoadAmount().setScale(2, RoundingMode.HALF_UP).toPlainString() : "0.00");
        logisticsOrderDispatchResp.setUnloadAmount(Objects.nonNull(record.getUnloadAmount()) ? record.getUnloadAmount().setScale(2, RoundingMode.HALF_UP).toPlainString() : "0.00");
        logisticsOrderDispatchResp.setStatus(String.valueOf(record.getStatus()));
        logisticsOrderDispatchResp.setStatusDesc(CarWaybillEnum.getName(record.getStatus()));

        logisticsOrderDispatchResp.setCloseOrder(String.valueOf(truckVo.getStatus()));
        logisticsOrderDispatchResp.setCloseOrderDesc(CarStatusEnum.getName(truckVo.getStatus()));
        return logisticsOrderDispatchResp;
    }

    public PageDataResult<CapacityVo> pageCapacity(CapacityReq req) {
        log.info("查询车辆列表请求：{}", JSON.toJSONString(req));
        Long logOrderId = Long.parseLong(req.getLogOrderId());
        //Set<Long> allEnt = getAllEnt(req.getEntId());
        IPage<KwtLogisticsOrderCirculate> page = logisticsOrderCirculateRepository.queryByPage(req.getPageNum(),
                req.getPageSize(), req.getTruckNo(), logOrderId);
        List<KwtLogisticsOrderCirculate> records = page.getRecords();

        if (org.apache.commons.collections4.CollectionUtils.isEmpty(records)) {
            return PageDataResult.empty(req.getPageNum(), req.getPageSize());
        }

        List<Long> truckIds = records.stream()
                .map(KwtLogisticsOrderCirculate::getTruckId)
                .distinct()
                .collect(Collectors.toList());
        List<Long> logisticsOrderIds = records.stream()
                .map(KwtLogisticsOrderCirculate::getLOrderId)
                .distinct()
                .collect(Collectors.toList());
        List<KwtLogisticsOrder> logisticsOrders = Lists.newArrayList();
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(logisticsOrderIds)) {
            logisticsOrders = logisticsOrderRepository.queryByLogisticsOrderIds(logisticsOrderIds);
        }
        List<RTruckVo> truckByTruckIds = remoteFleetService.findTruckByTruckIds(truckIds);
        Map<Long, RTruckVo> truckIdAndTruckMap = Maps.newHashMap();
        if (CollectionUtils.isNotEmpty(truckByTruckIds)) {
            truckIdAndTruckMap = truckByTruckIds.stream()
                    .collect(Collectors.toMap(RTruckVo::getId, Function.identity(), (k1, k2) -> k1));
        }
        //查询子运单信息
        List<KwtWaybillOrderSubtask> waybillOrderSubtasks = waybillOrderSubtaskRepository.queryByLogId(logOrderId);
        Set<Long> billOrderIds = Sets.newHashSet();
        if (CollectionUtils.isNotEmpty(waybillOrderSubtasks)) {
            //获取主运单id
            billOrderIds = waybillOrderSubtasks.stream()
                    .map(KwtWaybillOrderSubtask::getWOrderId)
                    .collect(Collectors.toSet());
        }
        //查询运单信息
        Map<Long, List<KwtWaybillOrder>> billOrderIdAndWaybillOrderMap = Maps.newHashMap();
        if (CollectionUtils.isNotEmpty(billOrderIds)) {
            List<KwtWaybillOrder> waybillOrders = waybillOrderRepository.queryByBillOrderIds(billOrderIds);
            if (CollectionUtils.isNotEmpty(waybillOrders)) {
                billOrderIdAndWaybillOrderMap = waybillOrders.stream()
                        .collect(Collectors.groupingBy(KwtWaybillOrder::getTruckId));
            }
        }


        Map<Long, RTruckVo> finalTruckIdAndTruckMap = truckIdAndTruckMap;
        Map<Long, List<KwtWaybillOrder>> finalBillOrderIdAndWaybillOrderMap = billOrderIdAndWaybillOrderMap;
        List<KwtLogisticsOrder> finalLogisticsOrders = logisticsOrders;
        List<CapacityVo> capacityVos = records.stream()
                .map(t -> getCapacityVo(t, finalTruckIdAndTruckMap, finalBillOrderIdAndWaybillOrderMap, waybillOrderSubtasks, finalLogisticsOrders))
                .collect(Collectors.toList());
        return PageDataResult.of(page, capacityVos);

    }

    @NotNull
    private static CapacityVo getCapacityVo(KwtLogisticsOrderCirculate t, Map<Long, RTruckVo> finalTruckIdAndTruckMap,
                                            Map<Long, List<KwtWaybillOrder>> finalBillOrderIdAndWaybillOrderMap,
                                            List<KwtWaybillOrderSubtask> waybillOrderSubtasks,
                                            List<KwtLogisticsOrder> logisticsOrders) {
        CapacityVo capacityVo = new CapacityVo();
        capacityVo.setTruckId(String.valueOf(t.getTruckId()));
        capacityVo.setTruckNo(t.getTruckNo());
        RTruckVo truckVo = finalTruckIdAndTruckMap.getOrDefault(t.getTruckId(), new RTruckVo());
        capacityVo.setCarAxis(truckVo.getCarAxis());
        List<KwtWaybillOrder> waybillOrders = finalBillOrderIdAndWaybillOrderMap.get(t.getTruckId());
        capacityVo.setFinishWaybillCount("0");
        BigDecimal loadAmount = BigDecimal.ZERO;
        BigDecimal unloadAmount = BigDecimal.ZERO;
        String unit = Optional.ofNullable(logisticsOrders).map(x -> x.get(0))
                .map(KwtLogisticsOrder::getUnit).orElse("");
        capacityVo.setStatus("0");
        capacityVo.setStatusDesc("待接单");
        KwtLogisticsOrder kwtLogisticsOrder = Optional.ofNullable(logisticsOrders).map(x -> x.get(0)).orElse(new KwtLogisticsOrder());
        if (Objects.equals(kwtLogisticsOrder.getOrderType(), 1)){
            log.info("物流单类型为1,原矿转运");
            unit = "吨";
        }
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(waybillOrders)) {
            List<KwtWaybillOrder> waybillOrderList = Optional.ofNullable(waybillOrders).orElse(List.of())
                    .stream()
                    .filter(x -> Objects.equals(x.getStatus(), CarWaybillV1Enum.COMPLETED.getCode()))
                    .collect(Collectors.toList());
            capacityVo.setFinishWaybillCount(String.valueOf(waybillOrderList.size()));
            capacityVo.setStatus(String.valueOf(waybillOrders.get(0).getStatus()));
            capacityVo.setStatusDesc(CarWaybillV1Enum.geDesc(waybillOrders.get(0).getStatus()));
            List<Long> waybillOrderIds = waybillOrderList.stream()
                    .map(KwtWaybillOrder::getId)
                    .collect(Collectors.toList());

            List<KwtWaybillOrderSubtask> subtasks = Optional.ofNullable(waybillOrderSubtasks)
                    .orElse(List.of())
                    .stream()
                    .filter(x -> waybillOrderIds.contains(x.getWOrderId()))
                    .collect(Collectors.toList());
            loadAmount = subtasks.stream()
                    .filter(x -> Objects.nonNull(x.getLoadAmount()))
                    .map(KwtWaybillOrderSubtask::getLoadAmount)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            unloadAmount = subtasks.stream()
                    .filter(x -> Objects.nonNull(x.getUnloadAmount()))
                    .map(KwtWaybillOrderSubtask::getUnloadAmount)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
        }
        capacityVo.setLoadAmount(loadAmount.setScale(2, RoundingMode.HALF_UP).toPlainString() + unit);
        capacityVo.setUnloadAmount(unloadAmount.setScale(2, RoundingMode.HALF_UP).toPlainString() + unit);
        capacityVo.setDispatchStatus(String.valueOf(t.getStatus()));
        capacityVo.setDispatchStatusDesc(Objects.equals(t.getStatus(), 0) ? "启用" : "关闭");
        return capacityVo;
    }


    @Transactional(rollbackFor = Exception.class)
    public Boolean closeCapacity(@Valid DeleteCapacityReq req) {
        log.info("关闭启用已派运力请求参数：{}", JSON.toJSONString(req));
        Long truckId = StringUtils.isNotBlank(req.getTruckId()) ? Long.parseLong(req.getTruckId()) : null;
        List<Long> logisticsOrderIds = req.getLogisticsOrderIds()
                .stream().map(x -> Long.parseLong(x)).collect(Collectors.toList());
        List<KwtLogisticsOrderCirculate> logisticsOrderCirculate =
                logisticsOrderCirculateRepository.findOneByLogOrderIdsAndTruckId(logisticsOrderIds, truckId);
        if (Objects.isNull(logisticsOrderCirculate)) {
            throw new BusinessException("未找到该运力信息");
        }
        List<KwtLogisticsOrderCirculate> orderCirculates = logisticsOrderCirculate.stream()
                .map(x -> {
                    KwtLogisticsOrderCirculate updateCirCulate = new KwtLogisticsOrderCirculate();
                    updateCirCulate.setId(x.getId());
                    updateCirCulate.setStatus(Integer.parseInt(req.getStatus()));
                    updateCirCulate.setUpdateTime(new Date());
                    updateCirCulate.setUpdateBy(LoginUserHolder.getUserId());
                    return updateCirCulate;
                }).collect(Collectors.toList());

        return logisticsOrderCirculateRepository.updateCirculates(orderCirculates);
    }

    @Transactional(rollbackFor = Exception.class)
    public DispatchCarResp dispatchCar(@Valid DispatchCarReq req) {
        log.info("派车请求参数：{}", JSON.toJSONString(req));
        //查询物流订单
        Long logOrderId = Long.parseLong(req.getLogisticOrderId());
        KwtLogisticsOrder logisticsOrder =
                logisticsOrderRepository.queryByLogisticsOrderId(logOrderId);
        if (Objects.isNull(logisticsOrder)) {
            throw new BusinessException("未找到该物流订单信息");
        }
        List<Integer> status = Arrays.asList(LogisticsOrderV1Enum.WAIT_DELIVERY.getCode(), LogisticsOrderV1Enum.IN_TRANSIT.getCode());
        if (!status.contains(logisticsOrder.getStatus())) {
            throw new BusinessException("该物流订单状态不能进行派车");
        }
        //查询承运企业
        KwtLogisticsOrderUnit kwtLogisticsOrderUnit = logisticsOrderUnitRepository.queryByLOrderIdAndUnitType(logOrderId, 2);
        if (Objects.isNull(kwtLogisticsOrderUnit)) {
            throw new BusinessException("未找到承运企业信息");
        }
        //过滤停用车辆
        List<DispatchCarReq.CarInfo> carInfos = req.getCarInfos();
        List<Long> reqTruckIds = carInfos.stream()
                .map(DispatchCarReq.CarInfo::getTruckId)
                .filter(org.apache.commons.lang3.StringUtils::isNotBlank)
                .map(Long::valueOf)
                .toList();
        if (CollectionUtils.isEmpty(reqTruckIds)) {
            throw new BusinessException("车辆id不能为空");
        }
        Map<Long, RTruckVo> truckMap = remoteFleetService.findTruckByTruckIds(reqTruckIds).stream()
                .collect(Collectors.toMap(RTruckVo::getId, Function.identity(), (k1, k2) -> k1));
        final int disabledTruckStatus = 1;
        carInfos = carInfos.stream()
                .filter(carInfo -> {
                    RTruckVo truckVo = truckMap.get(Long.valueOf(carInfo.getTruckId()));
                    return truckVo == null || !Objects.equals(truckVo.getStatus(), disabledTruckStatus);
                })
                .toList();

        //车牌id去重
        Set<String> truckIds = carInfos.stream()
                .map(DispatchCarReq.CarInfo::getTruckId)
                .collect(Collectors.toSet());

        //查询派车信息
        List<KwtLogisticsOrderCirculate> logisticsOrderCirculates =
                logisticsOrderCirculateRepository.findOneByLogOrderIdsAndTruckIds(logisticsOrder.getId(), truckIds);

        List<KwtLogisticsOrderCirculate> insertOrderCirculates = Lists.newArrayList();
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(logisticsOrderCirculates)) {
            //直接新增
            List<KwtLogisticsOrderCirculate> saveOrderCirculates = carInfos.stream()
                    .map(t -> getKwtLogisticsOrderCirculate(req, t, logOrderId, logisticsOrder, kwtLogisticsOrderUnit))
                    .collect(Collectors.toList());
            insertOrderCirculates.addAll(saveOrderCirculates);
        } else {
            //过滤掉已有的车
            List<Long> truckIdList = logisticsOrderCirculates.stream()
                    .map(KwtLogisticsOrderCirculate::getTruckId)
                    .collect(Collectors.toList());
            List<KwtLogisticsOrderCirculate> saveOrderCirculates = carInfos.stream().filter(t -> !truckIdList.contains(Long.valueOf(t.getTruckId())))
                    .map(t -> getKwtLogisticsOrderCirculate(req, t, logOrderId, logisticsOrder, kwtLogisticsOrderUnit))
                    .collect(Collectors.toList());
            insertOrderCirculates.addAll(saveOrderCirculates);
        }
        DispatchCarResp dispatchCarResp = new DispatchCarResp();
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(insertOrderCirculates)) {
            //批量新增
            dispatchCarResp.setSuccessCount("0");
            return new DispatchCarResp();
        }
        Boolean b = logisticsOrderCirculateRepository.insertCirculates(insertOrderCirculates);
        //修改物流订单状态
        if (!b) {
            throw new BusinessException("派车失败");
        }
        KwtLogisticsOrder updateLogisticsOrder = new KwtLogisticsOrder();
        updateLogisticsOrder.setId(logOrderId);
        updateLogisticsOrder.setStatus(LogisticsOrderV1Enum.IN_TRANSIT.getCode());
        Boolean updateFlag = logisticsOrderRepository.updateLogisticsOrder(updateLogisticsOrder);
        if (!updateFlag) {
            throw new BusinessException("修改物流订单状态失败");
        }
        dispatchCarResp.setSuccessCount(String.valueOf(insertOrderCirculates.size()));
        return dispatchCarResp;
    }

    @NotNull
    private static KwtLogisticsOrderCirculate getKwtLogisticsOrderCirculate(DispatchCarReq req,
                                                                            DispatchCarReq.CarInfo carInfo,
                                                                            Long logOrderId,
                                                                            KwtLogisticsOrder logisticsOrder,
                                                                            KwtLogisticsOrderUnit kwtLogisticsOrderUnit) {
        KwtLogisticsOrderCirculate logisticsOrderCirculate = new KwtLogisticsOrderCirculate();
        logisticsOrderCirculate.setEntId(Long.valueOf(kwtLogisticsOrderUnit.getEntId()));
        logisticsOrderCirculate.setLOrderId(logOrderId);
        logisticsOrderCirculate.setTruckId(Long.valueOf(carInfo.getTruckId()));
        logisticsOrderCirculate.setTruckNo(carInfo.getTruckNo());
        logisticsOrderCirculate.setDriverId(-9L);
        Date startDate = Objects.nonNull(logisticsOrder.getStartTime()) ?
                Date.from(logisticsOrder.getStartTime().atZone(ZoneId.systemDefault()).toInstant()) : null;
        logisticsOrderCirculate.setStartTime(startDate);
        Date endDate = Objects.nonNull(logisticsOrder.getEndTime()) ?
                Date.from(logisticsOrder.getEndTime().atZone(ZoneId.systemDefault()).toInstant()) : null;
        logisticsOrderCirculate.setEndTime(endDate);
        logisticsOrderCirculate.setUnit(logisticsOrder.getUnit());
        logisticsOrderCirculate.setEntrustAmount(logisticsOrder.getEntrustAmount());
        Date date = new Date();
        logisticsOrderCirculate.setCreateBy(LoginUserHolder.getUserId());
        logisticsOrderCirculate.setCreateTime(date);
        logisticsOrderCirculate.setUpdateBy(LoginUserHolder.getUserId());
        logisticsOrderCirculate.setUpdateTime(date);
        return logisticsOrderCirculate;
    }

    public Boolean logisticOrderFinish(OrderFinishReq req) {
        log.info("物流订单-完结订单传递参数信息:{}", JSONObject.toJSONString(req));
        List<KwtLogisticsOrder> logisticsOrder = Lists.newArrayList();
        //根据运单号查询物流运单
        if (Objects.nonNull(req.getTradeOrderId())) {
            logisticsOrder = logisticsOrderRepository.queryByTradeOrderId(req.getTradeOrderId());
        } else {
            //查询物流订单
            logisticsOrder =
                    logisticsOrderRepository.queryByLogisticsOrderIds(req.getLogisticOrderId());
        }
        if (CollectionUtils.isEmpty(logisticsOrder)) {
            throw new BusinessException("未找到该物流订单信息");
        }
        List<KwtLogisticsOrder> logisticsOrders = Lists.newArrayList();
        List<KwtLogisticsOrder> completedLogisticsOrders = Lists.newArrayList();
        Set<Long> tradeIds = Sets.newHashSet();
        logisticsOrder.forEach(x -> {
            KwtLogisticsOrder updateLogisticsOrder = new KwtLogisticsOrder();
            updateLogisticsOrder.setId(x.getId());

            if (!Arrays.asList(LogisticsOrderV1Enum.WAIT_DELIVERY.getCode(), LogisticsOrderV1Enum.IN_TRANSIT.getCode()).contains(x.getStatus())) {
                throw new BusinessException("该物流订单状态不能进行完结，订单编号，{}，订单id：{}", x.getLOrderNo(), x.getId());
            }
            if (Objects.equals(x.getStatus(), LogisticsOrderV1Enum.WAIT_DELIVERY.getCode())) {
                updateLogisticsOrder.setStatus(LogisticsOrderV1Enum.COMPLETED.getCode());
                completedLogisticsOrders.add(x);
                logisticsOrders.add(updateLogisticsOrder);
                tradeIds.add(x.getTOrderId());
                return;
                // return logisticsOrderRepository.updateLogisticsOrder(updateLogisticsOrder);
            }

            //查询物流订单下的所有运单
            List<KwtWaybillOrderSubtask> waybillOrderSubtasks = waybillOrderSubtaskRepository.queryByLogId(x.getId());
            if (org.apache.commons.collections4.CollectionUtils.isEmpty(waybillOrderSubtasks)) {
                updateLogisticsOrder.setStatus(LogisticsOrderV1Enum.COMPLETED.getCode());
                completedLogisticsOrders.add(x);
                logisticsOrders.add(updateLogisticsOrder);
                tradeIds.add(x.getTOrderId());
            }
            if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(waybillOrderSubtasks) && Objects.equals(x.getStatus(), LogisticsOrderV1Enum.IN_TRANSIT.getCode())) {
                boolean b = waybillOrderSubtasks.stream()
                        .anyMatch(y -> !Arrays.asList(CarWaybillV1Enum.COMPLETED.getCode(), CarWaybillV1Enum.CANCELLED.getCode()).contains(y.getStatus()));

                if (b) {
                    updateLogisticsOrder.setStatus(LogisticsOrderV1Enum.NEARING_COMPLETION.getCode());
                    logisticsOrders.add(updateLogisticsOrder);
                } else {
                    updateLogisticsOrder.setStatus(LogisticsOrderV1Enum.COMPLETED.getCode());
                    completedLogisticsOrders.add(x);
                    logisticsOrders.add(updateLogisticsOrder);
                    tradeIds.add(x.getTOrderId());
                }
            }
        });
        //更新物流订单
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(logisticsOrders)) {
            log.info("没有需要更新的物流订单");
            return false;
        }
        logisticsOrderRepository.updateBatchById(logisticsOrders);

        calculateFreight(completedLogisticsOrders);

        //更新贸易订单数据
        // updateTradeOrder(tradeIds);
        return Boolean.TRUE;
    }

    private void calculateFreight(List<KwtLogisticsOrder> completedLogisticsOrders) {
        for (KwtLogisticsOrder logisticsOrder : completedLogisticsOrders) {
            //物流订单已完结，计算待付运费
            if (Objects.equals(logisticsOrder.getSettlement(), 1)) {
                //todo 普通结算

            } else if (Objects.equals(logisticsOrder.getSettlement(), 2)) {
                //记账模式
                //1解冻运费
                List<KwtLogisticsOrderUnit> orderUnits = kwtLogisticsOrderUnitRepository.queryByLOrderId(logisticsOrder.getId());
                Map<Integer, Long> map = orderUnits.stream().collect(Collectors.toMap(KwtLogisticsOrderUnit::getUnitType, KwtLogisticsOrderUnit::getEntId, (v1, v2) -> v1));
                WalletPayableDto unFreezePayableDto = new WalletPayableDto();
                unFreezePayableDto.setConsignEntId(map.get(1));
                unFreezePayableDto.setCarriageEntId(map.get(2));
                unFreezePayableDto.setOrderNo(logisticsOrder.getLOrderNo());
                unFreezePayableDto.setOrderType(5);
                unFreezePayableDto.setTradeType(5);
                unFreezePayableDto.setRemark("物流订单号：" + unFreezePayableDto.getOrderNo() + "，订单完结解冻");
                log.info("物流订单号：{}，订单完结解冻进行中运费，参数：{}", unFreezePayableDto.getOrderNo(),JSON.toJSONString(unFreezePayableDto));
                BaseResult<Object> unFreezeResult = paymentFeignService.updatePayable(unFreezePayableDto);
                if (unFreezeResult.getCode() != HttpStatus.SUCCESS_CODE) {
                    log.error("物流订单号：{}，订单完结解冻失败,异常信息为：{}", unFreezePayableDto.getOrderNo(), unFreezeResult.getMessage());
                    throw new BusinessException("物流订单号：" + unFreezePayableDto.getOrderNo() + "，订单完结解冻失败");
                }
                //2计算待付运费
                WalletPayableDto consumePayableDto = new WalletPayableDto();
                consumePayableDto.setConsignEntId(map.get(1));
                consumePayableDto.setCarriageEntId(map.get(2));
                consumePayableDto.setOrderNo(logisticsOrder.getLOrderNo());
                consumePayableDto.setOrderType(5);
                consumePayableDto.setTradeType(6);
                if (org.apache.commons.lang3.StringUtils.equals(logisticsOrder.getBillingMode(), DictEnum.CHARGING_TYPE_1.getValue())) {
                    BigDecimal actualPrice = Objects.nonNull(logisticsOrder.getPrice()) && Objects.nonNull(logisticsOrder.getTotalLoadAmount()) ?
                            logisticsOrder.getPrice().multiply(logisticsOrder.getTotalLoadAmount()) : BigDecimal.ZERO;
                    consumePayableDto.setTradeAmount(actualPrice);
                } else if (org.apache.commons.lang3.StringUtils.equals(logisticsOrder.getBillingMode(), DictEnum.CHARGING_TYPE_2.getValue())) {
                    BigDecimal actualPrice = Objects.nonNull(logisticsOrder.getPrice()) && Objects.nonNull(logisticsOrder.getTotalUnloadAmount()) ?
                            logisticsOrder.getPrice().multiply(logisticsOrder.getTotalUnloadAmount()) : BigDecimal.ZERO;
                    consumePayableDto.setTradeAmount(actualPrice);
                }
                consumePayableDto.setRemark("物流订单号：" + consumePayableDto.getOrderNo() + "，订单完结消费");
                log.info("物流订单号：{}，订单完结消费，参数：{}", consumePayableDto.getOrderNo(),JSON.toJSONString(consumePayableDto));
                BaseResult<Object> consumeResult = paymentFeignService.updatePayable(consumePayableDto);
                if (consumeResult.getCode() != HttpStatus.SUCCESS_CODE) {
                    log.error("物流订单号：{}，订单完结消费失败,异常信息为：{}", unFreezePayableDto.getOrderNo(), consumeResult.getMessage());
                    throw new BusinessException("物流订单号：" + unFreezePayableDto.getOrderNo() + "，订单完结消费失败");
                }
            }
        }
    }

    private void updateTradeOrder(Set<Long> tradeIds) {
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(tradeIds)) {
            return;
        }
        List<KwtLogisticsOrder> tradeOrderInfos = logisticsOrderRepository.queryByTradeOrderIds(tradeIds);
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(tradeOrderInfos)) {
            return;
        }
        Map<Long, List<KwtLogisticsOrder>> tradeOrderIdAndLogisticsOrdersMap = tradeOrderInfos.stream()
                .collect(Collectors.groupingBy(KwtLogisticsOrder::getTOrderId));
        //通知订贸易订单完结订单
        if (MapUtils.isNotEmpty(tradeOrderIdAndLogisticsOrdersMap)) {

            tradeOrderIdAndLogisticsOrdersMap
                    .forEach((tradeOrderId, orders) -> noticeTrader(tradeOrderId, orders));
        }
    }

    private void noticeTrader(Long tradeOrderId, List<KwtLogisticsOrder> orders) {
        boolean b = orders.stream()
                .allMatch(x -> Arrays.asList(LogisticsOrderV1Enum.COMPLETED.getCode())
                        .contains(x.getStatus()));
        if (!b) {
            return;
        }
        TradeOrderSettlePara tradeOrderSettlePara = new TradeOrderSettlePara();

        tradeOrderSettlePara.setTOrderId(tradeOrderId);
        BigDecimal loadAmount = orders.stream()
                .filter(x -> Objects.nonNull(x.getTotalLoadAmount()))
                .map(KwtLogisticsOrder::getLoadAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal unloadAmount = orders.stream()
                .filter(x -> Objects.nonNull(x.getTotalUnloadAmount()))
                .map(KwtLogisticsOrder::getUnloadAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        tradeOrderSettlePara.setLoadAmount(loadAmount);
        tradeOrderSettlePara.setUnloadAmount(unloadAmount);
        log.info("物流订单-完结修改贸易订单参数信息:{}", JSONObject.toJSONString(tradeOrderSettlePara));
        tradeOrderInfoService.orderSettle(tradeOrderSettlePara);
    }


    public OrderStatusStatisticsResp orderStatusStatistics(QueryLogisticsOrderReq req) {
        log.info("物流订单状态统计");
        OrderStatusStatisticsResp orderStatusStatisticsResp = new OrderStatusStatisticsResp();
        orderStatusStatisticsResp.setTotalNum("0");

        List<LogisticsOrderV1Enum> orderV1Enums = Arrays.stream(LogisticsOrderV1Enum.values())
                .sorted(Comparator.comparingInt(LogisticsOrderV1Enum::getCode))
                .collect(Collectors.toList());
        Long allEnt = getAllEnt(req.getEntId());
        //根据托运单位或者承运单位查询企业
        Set<Long> entList = getEntList(req);
        if (Objects.nonNull(allEnt)) {
            entList.add(allEnt);
        }

        if (!org.apache.commons.lang3.StringUtils.isAllBlank(req.getConsignCompanyId(), req.getCarriageCompanyId())
                && org.apache.commons.collections4.CollectionUtils.isEmpty(entList)) {
            Map<Integer, List<KwtLogisticsOrder>> statusAndLogOrdersMap = Maps.newHashMap();
            List<OrderStatusStatisticsResp.OrderStatusStatistics> statistics = orderV1Enums.stream()
                    .map(o -> getOrderStatusStatistics(o, statusAndLogOrdersMap))
                    .collect(Collectors.toList());
            orderStatusStatisticsResp.setOrderStatusStatistics(statistics);
            return orderStatusStatisticsResp;
        }

        //根据商品名称查询物流订单
        Set<Long> logOrderIds = getLogOrderIds(req, entList, allEnt);
        logOrderIds = applyDataPermissionFilterToLogOrderIds(logOrderIds);
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(logOrderIds) && org.apache.commons.collections4.CollectionUtils.isNotEmpty(entList)) {
            Map<Integer, List<KwtLogisticsOrder>> statusAndLogOrdersMap = Maps.newHashMap();
            List<OrderStatusStatisticsResp.OrderStatusStatistics> statistics = orderV1Enums.stream()
                    .map(o -> getOrderStatusStatistics(o, statusAndLogOrdersMap))
                    .collect(Collectors.toList());
            orderStatusStatisticsResp.setOrderStatusStatistics(statistics);
            return orderStatusStatisticsResp;
        }
        List<KwtLogisticsOrder> logisticsOrders = logisticsOrderRepository.queryList(logOrderIds, req.getTradeOrderId(), req.getOrderNo(), req.getOrderStatus(),
                req.getStartTime(), req.getEndTime());

        if (Objects.isNull(logisticsOrders)) {
            Map<Integer, List<KwtLogisticsOrder>> statusAndLogOrdersMap = Maps.newHashMap();
            List<OrderStatusStatisticsResp.OrderStatusStatistics> statistics = orderV1Enums.stream()
                    .map(o -> getOrderStatusStatistics(o, statusAndLogOrdersMap))
                    .collect(Collectors.toList());
            orderStatusStatisticsResp.setOrderStatusStatistics(statistics);
            return orderStatusStatisticsResp;
        }
        Map<Integer, List<KwtLogisticsOrder>> statusAndLogOrdersMap = logisticsOrders.stream().collect(Collectors.groupingBy(KwtLogisticsOrder::getStatus));
        List<OrderStatusStatisticsResp.OrderStatusStatistics> statusStatistics = orderV1Enums.stream()
                .map(o -> getOrderStatusStatistics(o, statusAndLogOrdersMap))
                .collect(Collectors.toList());
        orderStatusStatisticsResp.setOrderStatusStatistics(statusStatistics);
        orderStatusStatisticsResp.setTotalNum(String.valueOf(logisticsOrders.size()));
        return orderStatusStatisticsResp;
    }

    private static OrderStatusStatisticsResp.OrderStatusStatistics getOrderStatusStatistics(LogisticsOrderV1Enum o, Map<Integer, List<KwtLogisticsOrder>> finalStatusAndLogOrdersMap1) {
        OrderStatusStatisticsResp.OrderStatusStatistics orderStatusStatistics = new OrderStatusStatisticsResp.OrderStatusStatistics();
        orderStatusStatistics.setOrderStatus(String.valueOf(o.getCode()));
        orderStatusStatistics.setOrderStatusDesc(o.getDestination());
        orderStatusStatistics.setOrderNum(String.valueOf(finalStatusAndLogOrdersMap1.getOrDefault(o.getCode(), new ArrayList<>()).size()));
        return orderStatusStatistics;
    }


    public List<McpLogisticsOrderVo> queryMcpList(LogisticsOrderPara orderPara) {
        UserResDto userResDto = remoteSystemService.queryUserById(orderPara.getUserId());
        if (Objects.nonNull(userResDto)) {
            orderPara.setType(userResDto.getType());
            Integer systemType = userResDto.getSystemType();
            if (!Objects.equals(systemType, SystemTypeEnum.MANAGE.getCode())) {
                orderPara.setEntId(remoteUserService.findChildEntList(userResDto.getEntId()));
            }
        }

        List<McpLogisticsOrderVo> list = kwtLogisticsOrderMapper.selectData(orderPara);
        if (CollUtil.isNotEmpty(list)) {
            list.forEach(d -> {
                GoodsDetails detailById = goodsInfoService.getDetail(d.getGoodsId());
                if (Objects.nonNull(detailById)) {
                    d.setGoodsName(d.getGoodsName() + detailById.getSpecLabel());
                }
                d.setMoreUrl("/#/operatManagement/logisticsOrder/list");
                d.setLOrderNoUrl(new OrderUrl(d.getLOrderNo(), "/#/operatManagement/logisticsOrder/detail/" + d.getLOrderId()));
                d.setTOrderNoUrl(new OrderUrl(d.getTOrderNo(), "/#/orderManagement/tradeOrder/detail/" + d.getTOrderId()));
                d.setStatusLabel(LogisticsOrderV1Enum.getDesc(d.getStatus()));
            });
            return list;
        }
        return new ArrayList<>();
    }

    public List<LogisticOrderSelectOptionVo> getLogisticOrderSelectList(LogisticOrderSelectReq req) {
        Long entId = LoginUserHolder.getEntId();
        //根据企业查询物流订单
        List<KwtLogisticsOrderUnit> kwtLogisticsOrderUnits = logisticsOrderUnitRepository.queryByEntId(entId);
        if (CollUtil.isEmpty(kwtLogisticsOrderUnits)) {
            log.info("该企业未查询到物流订单数据，企业id:{}", entId);
            return List.of();
        }
        //获取物流订单号
        Set<Long> logOrderIds = kwtLogisticsOrderUnits.stream()
                .map(KwtLogisticsOrderUnit::getLOrderId)
                .collect(Collectors.toSet());
        if (CollUtil.isEmpty(logOrderIds)) {
            log.info("该企业下物流订单数据，企业id:{}", entId);
            return List.of();
        }
        List<KwtLogisticsOrder> logisticOrders = logisticsOrderRepository.selectWaybillOrderOptions(logOrderIds, req.getLogisticOrderNo());

        if (org.apache.commons.collections4.CollectionUtils.isEmpty(logisticOrders)) {
            return List.of();
        }
        return logisticOrders.stream().map(d -> {
            LogisticOrderSelectOptionVo logisticOrderSelectOptionVo = new LogisticOrderSelectOptionVo();
            logisticOrderSelectOptionVo.setId(d.getId());
            logisticOrderSelectOptionVo.setLogisticOrderNo(d.getLOrderNo());
            logisticOrderSelectOptionVo.setStatus(d.getStatus());
            return logisticOrderSelectOptionVo;
        }).collect(Collectors.toList());
    }
}
