package com.sckw.transport.dubbo;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
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.AddressTypeEnum;
import com.sckw.core.model.enums.CarWaybillEnum;
import com.sckw.core.model.enums.CarWaybillV1Enum;
import com.sckw.core.model.enums.LogisticsOrderEnum;
import com.sckw.core.utils.CollectionUtils;
import com.sckw.core.utils.DateUtils;
import com.sckw.core.utils.IdWorker;
import com.sckw.core.utils.StringUtils;
import com.sckw.core.web.constant.HttpStatus;
import com.sckw.core.web.context.LoginUserHolder;
import com.sckw.core.web.response.HttpResult;
import com.sckw.fleet.api.RemoteFleetService;
import com.sckw.fleet.api.model.vo.RTruckVo;
import com.sckw.manage.api.RemoteManageService;
import com.sckw.manage.api.model.dto.res.LineFreightAddressRes;
import com.sckw.mongo.enums.BusinessTypeEnum;
import com.sckw.mongo.model.SckwLogisticsOrder;
import com.sckw.order.api.dubbo.TradeOrderInfoService;
import com.sckw.order.api.model.OrderDetailRes;
import com.sckw.order.api.model.UnitInfoDetailRes;
import com.sckw.redis.constant.RedisConstant;
import com.sckw.redis.utils.RedissonUtils;
import com.sckw.stream.model.SckwBusSum;
import com.sckw.system.api.RemoteSystemService;
import com.sckw.system.api.model.dto.res.SysDictResDto;
import com.sckw.transport.api.dubbo.TransportRemoteService;
import com.sckw.transport.api.model.dto.AcceptCarriageLogisticsOrderDto;
import com.sckw.transport.api.model.dto.RawOreOrderExecutionDto;
import com.sckw.transport.api.model.dto.TradeOrderWaybillAggDto;
import com.sckw.transport.api.model.dto.AccountCheckingBindDTO;
import com.sckw.transport.api.model.dto.RWaybillOrderDto;
import com.sckw.transport.api.model.param.*;
import com.sckw.transport.api.model.vo.*;
import com.sckw.transport.dao.*;
import com.sckw.transport.model.*;
import com.sckw.transport.model.dto.AddLogisticOrderDTO;
import com.sckw.transport.model.dto.LogisticData;
import com.sckw.transport.model.dto.WaybillOrderRequest;
import com.sckw.transport.model.param.QueryLogisticsOrderReq;
import com.sckw.transport.model.param.WaybillOrderReq;
import com.sckw.transport.model.vo.OrderFinishReq;
import com.sckw.transport.model.vo.OrderStatusStatisticsResp;
import com.sckw.transport.model.vo.StatisticsWaybillResp;
import com.sckw.transport.model.vo.WaybillOrderDetailResp;
import com.sckw.transport.repository.*;
import com.sckw.transport.service.KwtAcceptCarriageOrderService;
import com.sckw.transport.service.KwtCommonService;
import com.sckw.transport.service.KwtLogisticsConsignmentService;
import com.sckw.transport.service.KwtWaybillOrderV1Service;
import jakarta.annotation.Resource;
import jodd.util.StringUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.stream.function.StreamBridge;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author lfdc
 * @description 运输服务dubbo接口
 * @date 2023-07-11 14:07:28
 */
@Slf4j
@Service
@DubboService(group = "design", version = "1.0.0", timeout = 50000)
@RequiredArgsConstructor
public class TransportServiceImpl implements TransportRemoteService {

    @Autowired
    public KwtCommonService commonService;

    @Resource
    private StreamBridge streamBridge;

    @DubboReference(version = "1.0.0", group = "design", check = false)
    RemoteSystemService remoteSystemService;

    @DubboReference(version = "1.0.0", group = "design", check = false)
    RemoteManageService manageService;

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

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

    @Autowired
    private KwtLogisticsOrderMapper logisticsOrderMapper;

    @Autowired
    private KwtLogisticsOrderUnitMapper logisticsOrderUnitMapper;

    @Autowired
    private KwtLogisticsOrderContractMapper logisticsOrderContractMapper;

    @Autowired
    private KwtLogisticsOrderTrackMapper logisticsOrderTrackMapper;

    @Autowired
    private KwtLogisticsOrderGoodsMapper logisticsOrderGoodsMapper;

    @Autowired
    private KwtWaybillOrderV1Mapper waybillOrderV1Mapper;
    @Autowired
    private KwtWaybillOrderMapper kwtWaybillOrderMapper;
    private final RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private KwtWaybillOrderSubtaskMapper waybillOrderSubtaskMapper;

    @Autowired
    private KwtLogisticsOrderLineFreightRateMapper lineFreightRateMapper;

    @Autowired
    private KwtWaybillOrderTrackMapper waybillOrderTrackDao;
    @Resource
    private KwtWaybillOrderRepository waybillOrderRepository;

    private final KwtWaybillOrderSubtaskRepository waybillOrderSubtaskRepository;
    private final KwtLogisticsOrderRepository logisticsOrderRepository;
    private final KwtLogisticsOrderUnitRepository logisticsOrderUnitRepository;
    private final KwtLogisticsOrderContractRepository logisticsOrderContractRepository;
    private final KwtLogisticsOrderCirculateRepository logisticsOrderCirculateRepository;
    private final KwtAcceptCarriageOrderService kwtAcceptCarriageOrderService;
    private final KwtLogisticsConsignmentService logisticsConsignmentService;
    private final KwtLogisticsOrderGoodsRepository logisticsOrderGoodsRepository;
    private final KwtLogisticsOrderAddressRepository logisticsOrderAddressRepository;
    private final KwtWaybillOrderV1Service waybillOrderV1Service;

    // 定义禁止关联车辆删除的状态集合
    private static final List<Integer> FORBIDDEN_STATUSES = Arrays.asList(
            CarWaybillV1Enum.PENDING_VEHICLE.getCode(),
            CarWaybillV1Enum.REFUSE_TRAFFIC.getCode(),
            CarWaybillV1Enum.EXIT_COMPLETED.getCode(),
            CarWaybillV1Enum.EMPTY_WAIT_LEAVE.getCode(),
            CarWaybillV1Enum.WAIT_LEAVE.getCode(),
            CarWaybillV1Enum.UNLOADING.getCode(),
            CarWaybillV1Enum.WAIT_RELEASE.getCode(),
            CarWaybillV1Enum.REPLENISHING.getCode(),
            CarWaybillV1Enum.REPLENISH_FINISH.getCode(),
            CarWaybillV1Enum.RELEASED_NOT_EXITED.getCode(),
            CarWaybillV1Enum.WAIT_LOADING.getCode(),

            CarWaybillV1Enum.UNLOADING_POINT.getCode(),
            CarWaybillV1Enum.UNLOADING_WAIT_LEAVE.getCode(),
            CarWaybillV1Enum.UNLOADING_WAIT_RELEASE.getCode(),
//            CarWaybillV1Enum.UNLOADING_RELEASED_WAIT_LEAVE.getCode(),

            CarWaybillV1Enum.REVIEW_REJECTION.getCode()
    );

    /**
     * 对账管理-ids查询
     *
     * @param ids
     * @return
     */
    @Override
    public List<KwtLogisticsOrderVO> getAcceptCarriageOrderDetail(List<String> ids) {
        List<KwtLogisticsOrderVO> list = new ArrayList<>();
        List<KwtLogisticsOrder> kwtLogisticsOrders = logisticsOrderMapper.selectList(new LambdaQueryWrapper<KwtLogisticsOrder>().in(KwtLogisticsOrder::getId, ids));
        if (CollectionUtils.isNotEmpty(kwtLogisticsOrders)) {
            for (KwtLogisticsOrder kwtLogisticsOrder : kwtLogisticsOrders) {
                KwtLogisticsOrderVO vo = new KwtLogisticsOrderVO();
                BeanUtils.copyProperties(kwtLogisticsOrder, vo);
                list.add(vo);
            }
        }
        return list;
    }

    /**
     * 对账页面数据接口
     *
     * @param ids
     * @return
     */
    @Override
    public List<AcceptCarriageLogisticsOrderDto> getAcceptCarriageOrderList(List<String> ids) {
        List<AcceptCarriageLogisticsOrderDto> list = logisticsOrderMapper.selectLogisticOrderList(ids, LogisticsOrderEnum.HAVE_FINISHED.getCode());
        /**计量单位*/
        Map<String, String> unitTypeDictData = getDictData(DictTypeEnum.UNIT_TYPE.getType());
        /**运价方式*/
        Map<String, String> priceDictData = getDictData(DictTypeEnum.PRICE_TYPE.getType());
        /**计费方式*/
        Map<String, String> chargingDictData = getDictData(DictTypeEnum.CHARGING_TYPE.getType());
        /**结算周期*/
        Map<String, String> settlementDictData = getDictData(DictTypeEnum.SETTLEMENT_CYCLE.getType());
        /**合理损耗*/
        Map<String, String> taxRateTypeDictData = getDictData(DictTypeEnum.TAX_RATE_TYPE.getType());
        if (CollectionUtils.isNotEmpty(list)) {

            List<AcceptCarriageLogisticsOrderDto> collect = list.stream().filter(item -> item.getBillingMode().equals(DictEnum.CHARGING_TYPE_4.getValue())).collect(Collectors.toList());
            Map<Long, List<KwtLogisticsOrderLineFreightRate>> collect1 = new HashMap<>();
            if (CollectionUtils.isNotEmpty(collect)) {
                List<KwtLogisticsOrderLineFreightRate> kwtLogisticsOrderLineFreightRates = lineFreightRateMapper.selectListByOrderIdList(collect.stream().map(AcceptCarriageLogisticsOrderDto::getLOrderId).map(Long::parseLong).toList());
                if (CollectionUtils.isNotEmpty(kwtLogisticsOrderLineFreightRates)) {
                    collect1 = kwtLogisticsOrderLineFreightRates.stream().collect(Collectors.groupingBy(KwtLogisticsOrderLineFreightRate::getLOrderId));
                }
            }

            for (AcceptCarriageLogisticsOrderDto logisticsOrderDTO : list) {

                List<KwtLogisticsOrderLineFreightRate> kwtLogisticsOrderLineFreightRates = collect1.get(Long.parseLong(logisticsOrderDTO.getLOrderId()));
                if (CollectionUtils.isNotEmpty(kwtLogisticsOrderLineFreightRates)) {
                    logisticsOrderDTO.setPrices(kwtLogisticsOrderLineFreightRates.stream().map(item -> item.getName() + " " + item.getTransportPrice()).toList());
                }

                String tOrderId = logisticsOrderDTO.getTOrderId();
                if (StringUtils.isNotBlank(tOrderId)) {
                    try {
                        OrderDetailRes orderDetailById = tradeOrderInfoService.getOrderDetailById(Long.parseLong(tOrderId));
                        if (orderDetailById != null) {
                            List<UnitInfoDetailRes> unitInfo = orderDetailById.getUnitInfo();
                            if (CollectionUtils.isNotEmpty(unitInfo)) {
                                for (UnitInfoDetailRes detailRes : unitInfo) {
                                    if ("1".equals(detailRes.getUnitType())) {
                                        logisticsOrderDTO.setConsignee(detailRes.getFirmName());
                                    }
                                    if ("2".equals(detailRes.getUnitType())) {
                                        logisticsOrderDTO.setForwardingUnit(detailRes.getFirmName());
                                    }
                                }
                            }
                        }
                    } catch (NumberFormatException e) {
                        System.out.println("查询不到贸易订单数据,id" + tOrderId);
                    }
                }

                KwtLogisticsOrderUnit consignOrderUnit = logisticsOrderUnitMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrderUnit>()
                        .eq(KwtLogisticsOrderUnit::getLOrderId, logisticsOrderDTO.getLOrderId())
                        .eq(KwtLogisticsOrderUnit::getUnitType, NumberConstant.ONE));
                KwtLogisticsOrderUnit carrierOrderUnit = logisticsOrderUnitMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrderUnit>()
                        .eq(KwtLogisticsOrderUnit::getLOrderId, logisticsOrderDTO.getLOrderId())
                        .eq(KwtLogisticsOrderUnit::getUnitType, NumberConstant.TWO));
//                KwtLogisticsOrderAddress loadOrderAddress = logisticsOrderAddressMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrderAddress>()
//                        .eq(KwtLogisticsOrderAddress::getLOrderId, logisticsOrderDTO.getLOrderId())
//                        .eq(KwtLogisticsOrderAddress::getAddressType, NumberConstant.ONE)
//                );
//                KwtLogisticsOrderAddress unloadOrderAddress = logisticsOrderAddressMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrderAddress>()
//                        .eq(KwtLogisticsOrderAddress::getLOrderId, logisticsOrderDTO.getLOrderId())
//                        .eq(KwtLogisticsOrderAddress::getAddressType, NumberConstant.TWO)
//                );
                KwtLogisticsOrderContract contract = logisticsOrderContractMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrderContract>()
                        .eq(KwtLogisticsOrderContract::getLOrderId, logisticsOrderDTO.getLOrderId())
                );

                KwtLogisticsOrderGoods orderGoods = logisticsOrderGoodsMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrderGoods>()
                        .eq(KwtLogisticsOrderGoods::getLOrderId, logisticsOrderDTO.getLOrderId())
                );
                logisticsOrderDTO.setGoodsName(orderGoods == null ? null : orderGoods.getGoodsName());
                String billingMode = logisticsOrderDTO.getBillingMode();

                /**
                 * 一、罚款值计算：
                 * 1、合理损耗值=实装量*合理损耗（‰）
                 *  1.1 亏吨量= 实装量-实卸量
                 * 2、扣亏量=亏吨量-合理损耗值【要求大于0，如果小于0则扣亏货量取0】
                 * 3、罚款值=扣亏量 * 扣亏货值
                 *
                 * 二、运价计算：
                 * 1、按装货量：总运价=实装量*运价-罚款值
                 * 2、按卸货量：总运价=实卸量*运价-罚款值
                 * 3、按趟次：总运价=运价*趟次【后期加】
                 */
                //运价
                BigDecimal price = logisticsOrderDTO.getPrice() == null ? NumberConstant.ZERO_TWO : logisticsOrderDTO.getPrice();


                /**亏吨量/吨->装货量-卸货量
                 扣亏量/吨->亏吨量-合理损耗值
                 扣亏量/吨->亏吨量-合理损耗值(装货量*合理损耗)*/
                BigDecimal loadAmount = logisticsOrderDTO.getTotalLoadAmount() == null ? NumberConstant.ZERO_TWO : logisticsOrderDTO.getTotalLoadAmount();
                BigDecimal unloadAmount = logisticsOrderDTO.getTotalUnloadAmount() == null ? NumberConstant.ZERO_TWO : logisticsOrderDTO.getTotalUnloadAmount();

                BigDecimal loss = logisticsOrderDTO.getLoss() == null ? NumberConstant.ZERO_TWO : logisticsOrderDTO.getLoss();
                //亏吨量
                BigDecimal defectiveWeighNumber = loadAmount.subtract(unloadAmount);
                //合理损耗值
                BigDecimal lossAmount = loadAmount.multiply(logisticsOrderDTO.getLoss() == null ? NumberConstant.ZERO_TWO : logisticsOrderDTO.getLoss());
                //扣亏量
//                BigDecimal deductWeighNumber = defectiveWeighNumber.subtract(lossAmount);
                BigDecimal deductWeighNumber = commonService.deficitLossAmount(loadAmount, defectiveWeighNumber, loss, logisticsOrderDTO.getLossUnit());
                if (deductWeighNumber.compareTo(new BigDecimal("0")) < 0) {
                    deductWeighNumber = NumberConstant.ZERO_TWO;
                }
                //罚款值
                BigDecimal fineValue = (logisticsOrderDTO.getGoodsPrice() == null ? NumberConstant.ZERO_TWO : logisticsOrderDTO.getGoodsPrice()).multiply(deductWeighNumber);
                /**
                 *
                 * 二、运价计算：
                 * 1、按装货量：总运价=实装量*运价-罚款值
                 * 2、按卸货量：总运价=实卸量*运价-罚款值
                 * 3、按趟次：总运价=运价*趟次【后期加】
                 */
                //todo 2023-10-10 含税金额不减去罚款值 另指定罚款值进行返回数据
                BigDecimal actualAmount = NumberConstant.ZERO_TWO;
                actualAmount = computeAmount(actualAmount, logisticsOrderDTO, billingMode, price);
                logisticsOrderDTO.setDeductPrice(fineValue);
                logisticsOrderDTO.setTaxMoney(actualAmount);
                logisticsOrderDTO.setContractName(contract.getContractName());
                logisticsOrderDTO.setContractNo(contract.getContractNo());
                logisticsOrderDTO.setGoodsPriceLabel(priceDictData.get(logisticsOrderDTO.getPriceType()));
                logisticsOrderDTO.setCreateByName(remoteSystemService.queryUserCacheById(logisticsOrderDTO.getCreateBy()) == null ? null : remoteSystemService.queryUserCacheById(logisticsOrderDTO.getCreateBy()).getName());
//                logisticsOrderDTO.setLoadAddress(loadOrderAddress.getDetailAddress());
//                logisticsOrderDTO.setLoadName(loadOrderAddress.getName());
//                logisticsOrderDTO.setLoadContacts(loadOrderAddress.getContacts());
//                logisticsOrderDTO.setLoadPhone(loadOrderAddress.getPhone());
//                logisticsOrderDTO.setUnloadAddress(unloadOrderAddress.getDetailAddress());
//                logisticsOrderDTO.setUnloadName(unloadOrderAddress.getName());
//                logisticsOrderDTO.setUnloadContacts(unloadOrderAddress.getContacts());
//                logisticsOrderDTO.setUnloadPhone(unloadOrderAddress.getPhone());
                logisticsOrderDTO.setCarrierCompany(carrierOrderUnit == null ? null : carrierOrderUnit.getFirmName());
                logisticsOrderDTO.setCarrierPhone(carrierOrderUnit == null ? null : carrierOrderUnit.getPhone());
                logisticsOrderDTO.setCarrierContacts(carrierOrderUnit == null ? null : carrierOrderUnit.getContacts());
                logisticsOrderDTO.setConsignCompany(consignOrderUnit == null ? null : consignOrderUnit.getFirmName());
                logisticsOrderDTO.setConsignPhone(consignOrderUnit == null ? null : consignOrderUnit.getPhone());
                logisticsOrderDTO.setConsignContacts(consignOrderUnit == null ? null : consignOrderUnit.getContacts());
                logisticsOrderDTO.setSettlementCycleLabel(logisticsOrderDTO.getSettlementCycle() == null ? null : settlementDictData.get(logisticsOrderDTO.getSettlementCycle().toString()));
                logisticsOrderDTO.setBillingModeLabel(chargingDictData.get(logisticsOrderDTO.getBillingMode()));
                logisticsOrderDTO.setPriceLabel(priceDictData.get(logisticsOrderDTO.getPriceType()));
                logisticsOrderDTO.setLossUnitLabel(taxRateTypeDictData.get(logisticsOrderDTO.getLossUnit()));
                logisticsOrderDTO.setAmountLabel(unitTypeDictData.get(logisticsOrderDTO.getUnit()));
                logisticsOrderDTO.setIgnoreAmountLabel(unitTypeDictData.get(logisticsOrderDTO.getUnit()));
                logisticsOrderDTO.setLoadAmount(logisticsOrderDTO.getTotalLoadAmount());
                logisticsOrderDTO.setUnloadAmount(logisticsOrderDTO.getTotalUnloadAmount());
//                logisticsOrderDTO.setCount(waybillOrderMapper.selectCount(new LambdaQueryWrapper<KwtWaybillOrder>().eq(KwtWaybillOrder::getLOrderId, logisticsOrderDTO.getLOrderId())));
            }
        }
        return list;
    }

    /**
     * 含税金额计算
     *
     * @param actualAmount      初始化值
     * @param logisticsOrderDTO 物流订单
     * @param billingMode       计算方式
     * @param price             运价
     * @return 计算后的值
     */
    private BigDecimal computeAmount(BigDecimal actualAmount, AcceptCarriageLogisticsOrderDto logisticsOrderDTO, String billingMode, BigDecimal price) {
        if (DictEnum.CHARGING_TYPE_1.getValue().equals(billingMode)) {
            actualAmount = (logisticsOrderDTO.getTotalLoadAmount() == null ? NumberConstant.ZERO_TWO : logisticsOrderDTO.getTotalLoadAmount()).multiply(price);
//                    actualAmount = (logisticsOrderDTO.getTotalLoadAmount() == null ? NumberConstant.ZERO_TWO : logisticsOrderDTO.getTotalLoadAmount()).multiply(price).subtract(fineValue);
        } else if (DictEnum.CHARGING_TYPE_2.getValue().equals(billingMode)) {
            actualAmount = (logisticsOrderDTO.getTotalUnloadAmount() == null ? NumberConstant.ZERO_TWO : logisticsOrderDTO.getTotalUnloadAmount()).multiply(price);
//                    actualAmount = (logisticsOrderDTO.getTotalUnloadAmount() == null ? NumberConstant.ZERO_TWO : logisticsOrderDTO.getTotalUnloadAmount()).multiply(price).subtract(fineValue);
        } else if (DictEnum.CHARGING_TYPE_3.getValue().equals(billingMode)) {
            // 物流订单运单趟次数量
            /*WaybillCountVo waybillOrderCount = waybillOrderV1Mapper.findCountByLOrderId(Long.parseLong(logisticsOrderDTO.getLOrderId()));
            BigDecimal totalComplete = waybillOrderCount == null ? NumberConstant.ZERO_TWO : new BigDecimal(waybillOrderCount.getTotalComplete());*/

            BigDecimal totalComplete = BigDecimal.valueOf(logisticsOrderDTO.getTotalTake());
            actualAmount = totalComplete.multiply(price);
        } else if (DictEnum.CHARGING_TYPE_4.getValue().equals(billingMode)) {
            String lOrderId = logisticsOrderDTO.getLOrderId();
            List<KwtLogisticsOrderLineFreightRate> lineFreightRates = lineFreightRateMapper.selectList(new LambdaQueryWrapper<KwtLogisticsOrderLineFreightRate>()
                    .eq(KwtLogisticsOrderLineFreightRate::getLOrderId, lOrderId)
                    .eq(KwtLogisticsOrderLineFreightRate::getDelFlag, 0)
            );
            if (CollectionUtils.isNotEmpty(lineFreightRates)) {
                Map<Long, BigDecimal> amountMap = lineFreightRates.stream().collect(Collectors.toMap(KwtLogisticsOrderLineFreightRate::getLineFreightRateId, KwtLogisticsOrderLineFreightRate::getSettlementAmount));
                List<Long> lineFreightRateIds = lineFreightRates.stream().map(KwtLogisticsOrderLineFreightRate::getLineFreightRateId).collect(Collectors.toList());
                Map<Long, LineFreightAddressRes> lineFreightAddress = manageService.findLineFreightAddress(lineFreightRateIds);
                if (lineFreightAddress != null) {
                    for (LineFreightAddressRes address : lineFreightAddress.values()) {
//                        BigDecimal decimal = amountMap.get(address.getId());
//                        if (decimal != null) {
//                            BigDecimal sum = address.getTransportPrice().multiply(decimal).setScale(2, RoundingMode.HALF_UP);
//                            actualAmount = actualAmount.add(sum);
//                        }
                        actualAmount = actualAmount.add(address.getTransportAmount());
                    }
                }
            }
        }
        return actualAmount;
    }

    public Map<String, String> getDictData(String type) {
        Map<String, String> maps = new HashMap<>(NumberConstant.SIXTEEN);
        List<SysDictResDto> list = remoteSystemService.queryDictByType(type);
        if (CollectionUtils.isNotEmpty(list)) {
            maps = list.stream().collect(Collectors.toMap(SysDictResDto::getValue, SysDictResDto::getLabel, (key1, key2) -> key2));
        }
        return maps;
    }

    /**
     * 获取当前企业下物流订单地址信息
     *
     * @return
     */
    @Override
    public List<Integer> getLogisticsOrderAddressList() {
        return logisticsOrderMapper.getAddressList(LoginUserHolder.getEntId());
    }


    /**
     * 贸易订单验证物流订单是否已完成
     *
     * @param tOrderId 贸易订单id
     * @return false 无操作中的物流订单  ture 存在操作中的物流订单
     */
    @Override
    public boolean checkLogisticsOrderByTradeOrderId(Long tOrderId) {
        boolean flag = false;
        List<Integer> statusList = new ArrayList<>();
        statusList.add(LogisticsOrderEnum.TO_BE_PLANNED.getCode());
        statusList.add(LogisticsOrderEnum.PENDING_ORDER.getCode());
        statusList.add(LogisticsOrderEnum.WAIT_DELIVERY.getCode());
        statusList.add(LogisticsOrderEnum.IN_TRANSIT.getCode());
        List<KwtLogisticsOrder> logisticsOrders = logisticsOrderMapper.selectList(
                new LambdaQueryWrapper<KwtLogisticsOrder>()
                        .eq(KwtLogisticsOrder::getTOrderId, tOrderId)
                        .eq(KwtLogisticsOrder::getDelFlag, NumberConstant.ZERO)
                        .in(KwtLogisticsOrder::getStatus, statusList)
        );
        if (!org.springframework.util.CollectionUtils.isEmpty(logisticsOrders)) {
            flag = true;
        }
        return flag;
    }

    /**
     * 对账修改物流订单信息
     *
     * @param logisticsOrderParam 请求物流订单数据
     * @return
     */
    @Override
    public HttpResult checkLogisticsOrderStatusById(LogisticsOrderParam logisticsOrderParam) {
        HttpResult httpResult = new HttpResult();
        log.info("对账修改物流订单参数:{}", JSONObject.toJSONString(logisticsOrderParam));
        Long lOrderId = logisticsOrderParam.getLOrderId();
        String status = logisticsOrderParam.getStatus();
        if (lOrderId == null) {
            httpResult.setMsg("物流订单不能为空!");
            httpResult.setCode(HttpStatus.GLOBAL_EXCEPTION_CODE);
            return httpResult;
        }

        LambdaQueryWrapper<KwtLogisticsOrder> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(KwtLogisticsOrder::getId, lOrderId);
        wrapper.eq(KwtLogisticsOrder::getDelFlag, NumberConstant.ZERO);
        KwtLogisticsOrder kwtLogisticsOrder = logisticsOrderMapper.selectOne(wrapper);
        if (kwtLogisticsOrder == null) {
            httpResult.setMsg("物流订单不存在!");
            httpResult.setCode(HttpStatus.GLOBAL_EXCEPTION_CODE);
            return httpResult;
        }

        if (LogisticsOrderEnum.HAVE_RECONCILED.getStatus().equals(status)) {
            if (!LogisticsOrderEnum.HAVE_FINISHED.getStatus().equals(String.valueOf(kwtLogisticsOrder.getStatus()))) {
                httpResult.setMsg("物流单据状态有误,不能修改");
                httpResult.setCode(HttpStatus.GLOBAL_EXCEPTION_CODE);
                return httpResult;
            }
        } else if (LogisticsOrderEnum.HAVE_ALREADY_SETTLED.getStatus().equals(status)) {
            if (!LogisticsOrderEnum.HAVE_RECONCILED.getStatus().equals(String.valueOf(kwtLogisticsOrder.getStatus()))) {
                httpResult.setMsg("物流单据状态有误,不能修改");
                httpResult.setCode(HttpStatus.GLOBAL_EXCEPTION_CODE);
                return httpResult;
            }
        } else {
            httpResult.setMsg("物流单据状态有误");
            httpResult.setCode(HttpStatus.GLOBAL_EXCEPTION_CODE);
            return httpResult;
        }
        //修改单据状态
        kwtLogisticsOrder.setStatus(Integer.valueOf(status));
        kwtLogisticsOrder.setUpdateTime(new Date());
        kwtLogisticsOrder.setUpdateBy(LoginUserHolder.getUserId());
        logisticsOrderMapper.updateById(kwtLogisticsOrder);
        //修改mongodb状态
        SckwLogisticsOrder order = new SckwLogisticsOrder();
        order.set_id(kwtLogisticsOrder.getId());
        order.setLOrderId(kwtLogisticsOrder.getId());
        order.setStatus(status);
        order.setUpdateTime(new Date());
        order.setUpdateByName(LoginUserHolder.getUserName());
        SckwBusSum busSum = new SckwBusSum();
        busSum.setBusSumType(BusinessTypeEnum.LOGISTICS_ORDER_TYPE.getName());
        busSum.setMethod(NumberConstant.TWO);
        busSum.setObject(order);
        streamBridge.send("sckw-busSum", JSON.toJSONString(busSum));
        return HttpResult.ok();
    }

//    /**
//     * 根据企业id 获取物流订单相关地址信息
//     *
//     * @param entIds 企业id集合
//     * @return
//     */
//    @Override
//    public Map<Long, List<AddressResDTO>> getLogisticsOrderAddressListByEntId(List<Long> entIds) {
//        Map<Long, List<AddressResDTO>> map = new HashMap<>(entIds.size());
//        for (Long entId : entIds) {
//            List<AddressResDTO> list = logisticsOrderMapper.getAddressDetailListByEntId(entId);
//            if (Objects.nonNull(list)) {
//                map.put(entId, list);
//            }
//        }
//        return map;
//    }

    /**
     * 运费对账是否进行对账绑定数据
     * accountCheckingBindDTO
     *
     * @return
     */
    @Override
//    @GlobalLock
    @Transactional
    public HttpResult logisticsOrderAccountCheckingBind(AccountCheckingBindDTO accountCheckingBindDTO) {
        log.info("物流订单对账,推送是否绑定,请求数据:{}", JSONObject.toJSONString(accountCheckingBindDTO));
        if (org.springframework.util.CollectionUtils.isEmpty(accountCheckingBindDTO.getLOrderList())) {
            return HttpResult.error(HttpStatus.GLOBAL_EXCEPTION_CODE, "物流订单不能为空!");
        }
        if (StringUtils.isBlank(accountCheckingBindDTO.getStatus())) {
            return HttpResult.error(HttpStatus.GLOBAL_EXCEPTION_CODE, "绑定状态不能为空");
        }
        if (!String.valueOf(NumberConstant.ZERO).equals(accountCheckingBindDTO.getStatus()) &&
                !String.valueOf(NumberConstant.ONE).equals(accountCheckingBindDTO.getStatus())) {
            return HttpResult.error(HttpStatus.GLOBAL_EXCEPTION_CODE, "绑定状态类型错误!");
        }
        accountCheckingBindDTO.getLOrderList().forEach(id -> {
            logisticsOrderMapper.update(null,
                    new LambdaUpdateWrapper<KwtLogisticsOrder>()
                            .eq(KwtLogisticsOrder::getId, id)
                            .set(KwtLogisticsOrder::getBindStatus, accountCheckingBindDTO.getStatus())
                            .set(KwtLogisticsOrder::getUpdateBy, accountCheckingBindDTO.getUpdateBy())
                            .set(KwtLogisticsOrder::getUpdateTime, new Date()));
            //修改mongodb数据
            SckwLogisticsOrder order = new SckwLogisticsOrder();
            order.set_id(id);
            order.setLOrderId(id);
            order.setBindStatus(accountCheckingBindDTO.getStatus());
            order.setUpdateTime(new Date());
            order.setUpdateByName(accountCheckingBindDTO.getUpdateName());
            SckwBusSum busSum = new SckwBusSum();
            busSum.setBusSumType(BusinessTypeEnum.LOGISTICS_ORDER_TYPE.getName());
            busSum.setMethod(NumberConstant.TWO);
            busSum.setObject(order);
            streamBridge.send("sckw-busSum", JSON.toJSONString(busSum));
        });
        return HttpResult.ok();
    }

    /**
     * 根据企业id查询是否存在有未完结的物流订单
     *
     * @param entId 企业id
     * @return ture 代表还有未完结的  false代表没有未完结的
     */
    @Override
    public boolean checkLogisticsOrderFinishByEntId(Long entId) {
        List<KwtLogisticsOrderUnit> logisticsOrderUnits = logisticsOrderUnitMapper.selectList(new LambdaQueryWrapper<KwtLogisticsOrderUnit>()
                .eq(KwtLogisticsOrderUnit::getTopEntId, entId)
        );
        if (CollectionUtils.isEmpty(logisticsOrderUnits)) {
            return false;
        }
        List<Integer> orderStatus = new ArrayList<>();
        orderStatus.add(LogisticsOrderEnum.TO_BE_PLANNED.getCode());
        orderStatus.add(LogisticsOrderEnum.PENDING_ORDER.getCode());
        orderStatus.add(LogisticsOrderEnum.WAIT_DELIVERY.getCode());
        orderStatus.add(LogisticsOrderEnum.IN_TRANSIT.getCode());
        orderStatus.add(LogisticsOrderEnum.HAVE_FINISHED.getCode());
        orderStatus.add(LogisticsOrderEnum.HAVE_RECONCILED.getCode());
        List<Long> collect = logisticsOrderUnits.stream().map(KwtLogisticsOrderUnit::getLOrderId).distinct().collect(Collectors.toList());
        Long count = logisticsOrderMapper.selectCount(new LambdaQueryWrapper<KwtLogisticsOrder>()
                .in(KwtLogisticsOrder::getId, collect)
                .in(KwtLogisticsOrder::getStatus, orderStatus)
                .eq(KwtLogisticsOrder::getDelFlag, NumberConstant.ZERO)
        );
        if (count > 0) {
            return true;
        }
        return false;
    }

    /**
     * @param consignEntId        托运企业id
     * @param acceptCarriageEntId 承运企业id
     * @return
     */
    @Override
    public HttpResult checkLogisticsOrderIsFinishByEntId(Long consignEntId, Long acceptCarriageEntId) {
        if (Objects.isNull(consignEntId) || Objects.isNull(acceptCarriageEntId)) {
            throw new BusinessException("企业id不能为空");
        }
        List<Integer> orderStatus = new ArrayList<>();
        orderStatus.add(LogisticsOrderEnum.TO_BE_PLANNED.getCode());
        orderStatus.add(LogisticsOrderEnum.PENDING_ORDER.getCode());
        orderStatus.add(LogisticsOrderEnum.WAIT_DELIVERY.getCode());
        orderStatus.add(LogisticsOrderEnum.IN_TRANSIT.getCode());
        orderStatus.add(LogisticsOrderEnum.HAVE_FINISHED.getCode());
        orderStatus.add(LogisticsOrderEnum.HAVE_RECONCILED.getCode());
//        orderStatus.add(LogisticsOrderEnum.HAVE_ALREADY_SETTLED.getCode());
        List<String> logisticsNo = logisticsOrderMapper.checkLogisticsOrderIsFinishByEntId(consignEntId, acceptCarriageEntId, orderStatus);
        if (CollectionUtils.isNotEmpty(logisticsNo)) {
            return HttpResult.error("", logisticsNo);
        } else {
            return HttpResult.ok();
        }
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public void contractSignLogisticsCompleted(ContractSignLogisticsParam param) {
        if (Objects.isNull(param.getUpdateBy()) || StringUtils.isBlank(param.getUpdateByName())) {
            throw new BusinessException("操作人信息不能为空!");
        }
        Long contractId = param.getContractId();
        Long updateBy = param.getUpdateBy();

        String lockKey = String.format(RedisConstant.LOGISTICS_ORDER_CONTRACT_UPDATE_KEY, param.getContractId());
        if (Boolean.FALSE.equals(RedissonUtils.tryLock(lockKey, 5L, 10L))) {
            throw new BusinessException("业务繁忙，请稍后再试!");
        }
        try {
            List<KwtLogisticsOrderContract> contracts = logisticsOrderContractMapper.selectList(new LambdaQueryWrapper<KwtLogisticsOrderContract>()
                    .eq(KwtLogisticsOrderContract::getContractId, contractId)
                    .eq(KwtLogisticsOrderContract::getDelFlag, NumberConstant.ZERO)
            );
            if (CollectionUtils.isEmpty(contracts)) {
                log.info("合同：{}无相关联待签约的物流订单", contractId);
                return;
            }
            List<Long> orderIds = contracts.stream().map(KwtLogisticsOrderContract::getLOrderId).distinct().collect(Collectors.toList());
            List<KwtLogisticsOrder> orders = logisticsOrderMapper.selectList(new LambdaQueryWrapper<KwtLogisticsOrder>()
                    .in(KwtLogisticsOrder::getId, orderIds)
                    .eq(KwtLogisticsOrder::getStatus, LogisticsOrderEnum.TO_BE_PLANNED.getCode())
            );
            if (CollectionUtils.isEmpty(orders)) {
                log.info("合同：{}无相关联待签约的物流订单", contractId);
                return;
            }
            List<SckwLogisticsOrder> logisticsOrders = Lists.newArrayList();
            List<Long> ids = orders.stream().map(KwtLogisticsOrder::getId).toList();
            /**改变物流订单状态*/
            for (Long id : ids) {
                logisticsOrderMapper.update(null, new LambdaUpdateWrapper<KwtLogisticsOrder>()
                        .set(KwtLogisticsOrder::getUpdateBy, updateBy)
                        .set(KwtLogisticsOrder::getUpdateTime, new Date())
                        .set(KwtLogisticsOrder::getStatus, LogisticsOrderEnum.PENDING_ORDER.getCode())
                        .eq(KwtLogisticsOrder::getId, id)
                );
                SckwLogisticsOrder logisticsOrder = new SckwLogisticsOrder();
                logisticsOrder.set_id(id);
                logisticsOrder.setLOrderId(id);
                logisticsOrder.setStatus(LogisticsOrderEnum.PENDING_ORDER.getStatus());
                logisticsOrder.setUpdateBy(updateBy);
                logisticsOrder.setUpdateByName(param.getUpdateByName());
                logisticsOrders.add(logisticsOrder);
            }
            /**增加状态表数据*/
            orders.forEach(e -> {
                KwtLogisticsOrderTrack orderTrack = logisticsOrderTrackMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrderTrack>()
                        .eq(KwtLogisticsOrderTrack::getLOrderId, e.getId())
                        .eq(KwtLogisticsOrderTrack::getStatus, LogisticsOrderEnum.PENDING_ORDER.getCode())
                );
                if (orderTrack == null) {
                    KwtLogisticsOrderTrack track = new KwtLogisticsOrderTrack();
                    track.setId(new IdWorker(NumberConstant.ONE).nextId());
                    track.setLOrderId(e.getId());
                    track.setStatus(LogisticsOrderEnum.PENDING_ORDER.getCode());
                    track.setCreateBy(updateBy);
                    track.setCreateTime(new Date());
                    track.setUpdateBy(updateBy);
                    track.setUpdateTime(new Date());
                    track.setDelFlag(NumberConstant.ZERO);
                    logisticsOrderTrackMapper.insert(track);
                } else {
                    orderTrack.setUpdateBy(updateBy);
                    orderTrack.setUpdateTime(new Date());
                    logisticsOrderTrackMapper.updateById(orderTrack);
                }
            });
            /** mongodb保存*/
            for (SckwLogisticsOrder logisticsOrder : logisticsOrders) {
                SckwBusSum busSum = new SckwBusSum();
                busSum.setBusSumType(BusinessTypeEnum.LOGISTICS_ORDER_TYPE.getName());
                busSum.setMethod(NumberConstant.TWO);
                busSum.setObject(logisticsOrder);
                streamBridge.send("sckw-busSum", JSON.toJSONString(busSum));
            }
        } finally {
            RedissonUtils.unlock(lockKey);
        }
    }

    /**
     * @param params 参数
     * @desc 查询车辆运单
     * @author zk
     * @date 2023/9/6
     **/
    @Override
    public List<RWaybillOrderVo> findWaybillOrder(RWaybillOrderDto params) {
        List<RWaybillOrderVo> waybillOrderVos = new ArrayList<>();
        Map<String, Object> queryParams = new HashMap<>(Global.NUMERICAL_SIXTEEN) {{
            put("truckNo", params.getTruckNo());
            put("busStatus", params.getBusStatus());
        }};
        List<KwtWaybillOrderV1> waybillOrders = waybillOrderV1Mapper.findWaybillOrder(queryParams);
        if (CollectionUtils.isEmpty(waybillOrders)) {
            return waybillOrderVos;
        }

        for (KwtWaybillOrderV1 waybillOrder : waybillOrders) {
            RWaybillOrderVo order = new RWaybillOrderVo();
            BeanUtils.copyProperties(waybillOrder, order);

            //子运单
            List<KwtWaybillOrderSubtask> subtasks = waybillOrderSubtaskMapper.findByWOrderId(waybillOrder.getId());
            //装货时间
            Optional<KwtWaybillOrderSubtask> unloadDate = subtasks.stream().max(Comparator.comparing(KwtWaybillOrderSubtask::getUnloadTime));
            //卸货时间
            Optional<KwtWaybillOrderSubtask> loadDate = subtasks.stream().min(Comparator.comparing(KwtWaybillOrderSubtask::getLoadTime));
            KwtWaybillOrderTrack track = waybillOrderTrackDao.findWaybillOrderTrack(waybillOrder.getId(), null, null, CarWaybillEnum.EXIT_COMPLETED.getCode());
            order.setDepartureTime(track != null ? track.getOperateTime() : null);
            order.setStartTime(loadDate.get().getLoadTime());
            order.setEndTime(unloadDate.get().getUnloadTime());
            waybillOrderVos.add(order);
        }

        return waybillOrderVos;
    }

    /**
     * @param checkEntId 托运企业ID
     * @desc 查询托运方关联任务中的车辆
     * @author zk
     * @date 2023/10/8
     **/
    @Override
    public List<RTruckMonitorVo> truckInTask(Long checkEntId) {
        //查询物流订单
        List<Long> orderIds = new ArrayList<>();
        Map<String, Object> params = new HashMap<>(Global.NUMERICAL_SIXTEEN) {{
            put("status", LogisticsOrderEnum.IN_TRANSIT.getCode());
            put("checkEntId", checkEntId);
        }};
        List<KwtLogisticsOrder> orders = logisticsOrderMapper.findLogisticsOrder(params);
        if (!CollectionUtils.isEmpty(orders)) {
            List<Long> idList = new ArrayList<>();
            orders.forEach(order -> idList.add(order.getId()));
            orderIds.addAll(idList);
            findLogisticsOrderChild(orderIds, StringUtil.join(idList, Global.COMMA));
        }

        //查询运单
        List<RTruckMonitorVo> trucks = new ArrayList<>();
        params = new HashMap<>(Global.NUMERICAL_SIXTEEN) {{
            put("busStatus", Global.NUMERICAL_THREE);
            put("lOrderIds", orderIds);
        }};
        List<KwtWaybillOrderV1> waybillOrders = waybillOrderV1Mapper.findWaybillOrder(params);
        waybillOrders.forEach(order -> trucks.add(new RTruckMonitorVo(order.getEntId(), order.getTruckNo(), Global.NUMERICAL_ONE)));
        return trucks;
    }

    /**
     * @param orderIds 物流订单ID集合
     * @param ids      当前物流订单ID
     * @desc 查询下级分包 物流订单
     * @author zk
     * @date 2023/10/8
     **/
    public void findLogisticsOrderChild(List<Long> orderIds, String ids) {
        Map<String, Object> params = new HashMap<>(Global.NUMERICAL_SIXTEEN) {{
            put("status", LogisticsOrderEnum.IN_TRANSIT.getCode());
            put("pid", ids);
        }};
        //查询物流订单
        List<KwtLogisticsOrder> orders = logisticsOrderMapper.findLogisticsOrder(params);
        if (!CollectionUtils.isEmpty(orders)) {
            List<Long> idList = new ArrayList<>();
            orders.forEach(order -> idList.add(order.getId()));
            orderIds.addAll(idList);
            findLogisticsOrderChild(orderIds, StringUtil.join(idList, Global.COMMA));
        }
    }

    /**
     * 物流订单发起对账状态变更
     *
     * @param params 请求参数
     */
    @Transactional
    public HttpResult logisticsOrderInitiateReconciliationUpdateStatus(UpdateOrderStatusDto params) {
        List<Long> orderIds = params.getOrderIds();
        for (Long orderId : orderIds) {
            KwtLogisticsOrder kwtLogisticsOrder = logisticsOrderMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrder>()
                    .eq(KwtLogisticsOrder::getId, orderId));
            Integer code = params.getLogisticsOrderStatus().getCode();
            if (LogisticsOrderEnum.HAVE_ALREADY_SETTLED.getCode() == kwtLogisticsOrder.getStatus()) {
                return HttpResult.error(HttpStatus.GLOBAL_EXCEPTION_CODE, "已结算,不能进行对账");
            }
            if (LogisticsOrderEnum.HAVE_FINISHED.getCode() != kwtLogisticsOrder.getStatus()) {
                return HttpResult.error(HttpStatus.GLOBAL_EXCEPTION_CODE, "订单并未完成，不能进行对账");
            }
            if (LogisticsOrderEnum.HAVE_RECONCILED.getCode() != code) {
                return HttpResult.error(HttpStatus.GLOBAL_EXCEPTION_CODE, "订单状态错误");
            }
            logisticsOrderMapper.update(null, new LambdaUpdateWrapper<KwtLogisticsOrder>()
                    .eq(KwtLogisticsOrder::getId, orderId)
                    .set(KwtLogisticsOrder::getStatus, code)
            );
            KwtLogisticsOrderTrack orderTrack = logisticsOrderTrackMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrderTrack>()
                    .eq(KwtLogisticsOrderTrack::getLOrderId, orderId)
                    .eq(KwtLogisticsOrderTrack::getStatus, code)
                    .eq(KwtLogisticsOrderTrack::getDelFlag, 0)
            );
            if (orderTrack != null) {
                orderTrack.setStatus(code);
                orderTrack.setUpdateBy(params.getUpdateBy());
                orderTrack.setUpdateTime(DateUtils.formatDate(params.getUpdateTime()));
            } else {
                KwtLogisticsOrderTrack track = new KwtLogisticsOrderTrack();
                track.setId(new IdWorker(NumberConstant.ONE).nextId());
                track.setLOrderId(orderId);
                track.setStatus(code);
                track.setCreateBy(params.getUpdateBy());
                track.setCreateTime(DateUtils.formatDate(params.getUpdateTime()));
                track.setUpdateBy(params.getUpdateBy());
                track.setUpdateTime(DateUtils.formatDate(params.getUpdateTime()));
                track.setDelFlag(0);
                logisticsOrderTrackMapper.insert(track);
            }
        }
        return HttpResult.ok();
    }

    @Override
    public List<RWaybillOrderVo> queryWaybillOrderByEntId(Long entId) {
        List<KwtWaybillOrder> waybillOrders = waybillOrderRepository.queryWaybillOrderByEntId(entId);
        if (CollectionUtils.isEmpty(waybillOrders)) {
            return Collections.emptyList();
        }
        return waybillOrders.stream()
                .map(TransportServiceImpl::getWaybillOrderVo)
                .collect(Collectors.toList());
    }

    @Override
    public List<RTransportEntVo> queryTransportEnt(Set<Long> tradeOrderIds) {
        List<KwtLogisticsOrder> logisticsOrders = logisticsOrderRepository.queryByTradeOrderIds(tradeOrderIds);
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(logisticsOrders)) {
            return Collections.emptyList();
        }
        List<Long> logIds = logisticsOrders.stream()
                .map(KwtLogisticsOrder::getId)
                .collect(Collectors.toList());
        List<KwtLogisticsOrderUnit> units = logisticsOrderUnitRepository.queryByLogOrderIds(logIds);
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(units)) {
            return Collections.emptyList();
        }
        return units.stream().map(unit -> {
            RTransportEntVo rTransportEntVo = new RTransportEntVo();
            rTransportEntVo.setTransportEntType(unit.getUnitType());
            rTransportEntVo.setTransportEntId(unit.getEntId());
            rTransportEntVo.setTransportEntName(unit.getFirmName());
            return rTransportEntVo;
        }).collect(Collectors.toList());
    }

    @Override
    public List<RWaybillSubOrderVo> queryWaybillOrderByTradeOrderIds(Set<Long> tradeOrderIds) {
        List<KwtLogisticsOrder> logisticsOrders = logisticsOrderRepository.queryByTradeOrderIds(tradeOrderIds);
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(logisticsOrders)) {
            return Collections.emptyList();
        }
        List<Long> logIds = logisticsOrders.stream()
                .map(KwtLogisticsOrder::getId)
                .collect(Collectors.toList());
        List<KwtWaybillOrderSubtask> subtasks = waybillOrderSubtaskRepository.queryByLogIds(logIds);
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(subtasks)) {
            return Collections.emptyList();
        }
        //查询物流订单和的商品关系
        List<KwtLogisticsOrderGoods> logOrderGoods = logisticsOrderGoodsRepository.queryByLogIds(logIds);
        Map<Long, KwtLogisticsOrderGoods> logisticsOrderGoodsMap = Maps.newHashMap();
        if (CollectionUtils.isNotEmpty(logOrderGoods)) {
            logisticsOrderGoodsMap = logOrderGoods.stream()
                    .collect(Collectors.toMap(KwtLogisticsOrderGoods::getLOrderId, Function.identity(), (x, y) -> x));
        }
        //物理订单id映射运单
        Map<Long, List<KwtWaybillOrderSubtask>> logIdAndSubtasksMap =
                subtasks.stream().collect(Collectors.groupingBy(KwtWaybillOrderSubtask::getLOrderId));
        Map<Long, List<KwtLogisticsOrder>> tradeIdAndLogisticsOrdersMap = logisticsOrders.stream().collect(Collectors.groupingBy(KwtLogisticsOrder::getTOrderId));

        List<RWaybillSubOrderVo> result = Lists.newArrayList();
        Map<Long, KwtLogisticsOrderGoods> finalLogisticsOrderGoodsMap = logisticsOrderGoodsMap;
        tradeIdAndLogisticsOrdersMap.forEach((tradeId, logisticsOrderList) -> {
            RWaybillSubOrderVo rWaybillOrderVo = new RWaybillSubOrderVo();
            rWaybillOrderVo.setTradeId(tradeId);
            List<RWaybillSubOrderVo.BillSubOrder> subOrdersList = Lists.newArrayList();
            List<RWaybillSubOrderVo.LogisticGoodsInfo> goodsInfos = Lists.newArrayList();
            logisticsOrderList.forEach(l -> {
                KwtLogisticsOrderGoods goods = finalLogisticsOrderGoodsMap.getOrDefault(l.getId(), new KwtLogisticsOrderGoods());
                RWaybillSubOrderVo.LogisticGoodsInfo logisticGoodsInfo = new RWaybillSubOrderVo.LogisticGoodsInfo();
                logisticGoodsInfo.setLOrderId(l.getId());
                logisticGoodsInfo.setGoodsId(goods.getGoodsId());
                goodsInfos.add(logisticGoodsInfo);
                List<KwtWaybillOrderSubtask> waybillOrderSubtasks = logIdAndSubtasksMap.get(l.getId());
                if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(waybillOrderSubtasks)) {
                    List<RWaybillSubOrderVo.BillSubOrder> collect = waybillOrderSubtasks.stream()
                            .map(x -> getRWaybillSubOrderVo(x, goods.getGoodsId(), null))
                            .collect(Collectors.toList());
                    subOrdersList.addAll(collect);
                }
            });
            rWaybillOrderVo.setSubOrders(subOrdersList);
            result.add(rWaybillOrderVo);
        });
        return result;


    }

    @Override
    public List<LogisticContractVo> queryLogisticContractByTradeId(Long tradeId) {
        //查询物流id
        List<KwtLogisticsOrder> kwtLogisticsOrders = logisticsOrderRepository.queryByTradeOrderId(tradeId);
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(kwtLogisticsOrders)) {
            return Collections.emptyList();
        }
        //获取物流订单
        Set<Long> logOrderIds = kwtLogisticsOrders.stream()
                .map(KwtLogisticsOrder::getId)
                .collect(Collectors.toSet());
        //根据物流订单id获取物流合同
        List<KwtLogisticsOrderContract> contracts = logisticsOrderContractRepository.queryByLogOrderIds(logOrderIds);
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(contracts)) {
            return Collections.emptyList();
        }
        //获取物流合同id
        return contracts.stream().map(c -> {
            LogisticContractVo logisticContractVo = new LogisticContractVo();
            logisticContractVo.setLogContractId(c.getContractId());
            return logisticContractVo;
        }).collect(Collectors.toList());
    }

    @Override
    public List<RTransportEntVo> queryTransportEntByTradeOrderId(Long tradeId) {
        List<KwtLogisticsOrder> logisticsOrders = logisticsOrderRepository.queryByTradeOrderId(tradeId);
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(logisticsOrders)) {
            return Collections.emptyList();
        }
        List<Long> logIds = logisticsOrders.stream()
                .map(KwtLogisticsOrder::getId)
                .collect(Collectors.toList());
        //物流订单映射物流信息
        Map<Long, KwtLogisticsOrder> logIdAndLogisticsOrderMap =
                logisticsOrders.stream().collect(Collectors.toMap(KwtLogisticsOrder::getId,
                        Function.identity(),
                        (e1, e2) -> e1));
        List<KwtLogisticsOrderUnit> units = logisticsOrderUnitRepository.queryByLogOrderIds(logIds);
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(units)) {
            return Collections.emptyList();
        }

        return units.stream().map(unit -> {
            KwtLogisticsOrder logOrder = logIdAndLogisticsOrderMap.get(unit.getLOrderId());
            RTransportEntVo rTransportEntVo = new RTransportEntVo();
            rTransportEntVo.setTransportPrice(logOrder.getPrice());
            rTransportEntVo.setTransportEntType(unit.getUnitType());
            rTransportEntVo.setTransportEntId(unit.getEntId());
            rTransportEntVo.setTransportEntName(unit.getFirmName());
            rTransportEntVo.setTransportContacts(unit.getContacts());
            rTransportEntVo.setTransportContactsPhone(unit.getPhone());
            return rTransportEntVo;
        }).collect(Collectors.toList());
    }

    @Override
    public List<KwtLogisticsOrderVO> queryLogisticOrderByTradeId(Long tradeId) {
        List<KwtLogisticsOrder> kwtLogisticsOrders = logisticsOrderRepository.queryByTradeOrderId(tradeId);
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(kwtLogisticsOrders)) {
            return Collections.emptyList();
        }
        return kwtLogisticsOrders.stream()
                .map(TransportServiceImpl::getLogisticsOrderVo)
                .collect(Collectors.toList());

    }

    @Override
    public List<KwtLogisticsOrderVO> queryTransportEntByEntId(Long entId) {
        //通过承运单位查询物流订单
        List<KwtLogisticsOrderUnit> unitList = logisticsOrderUnitRepository.queryByEntId(entId);
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(unitList)) {
            return Collections.emptyList();
        }
        // 物流订单号
        Set<Long> logOrderIds = unitList.stream()
                .map(KwtLogisticsOrderUnit::getLOrderId)
                .collect(Collectors.toSet());
        //通过物流订单号查询物流订单
        List<KwtLogisticsOrder> logOrders = logisticsOrderRepository.queryByLogOrderIds(logOrderIds);
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(logOrders)) {
            return Collections.emptyList();
        }
        return logOrders.stream()
                .map(TransportServiceImpl::getLogisticsOrderVo)
                .collect(Collectors.toList());

    }

    private static KwtLogisticsOrderVO getLogisticsOrderVo(KwtLogisticsOrder logOrder) {
        KwtLogisticsOrderVO kwtLogisticsOrderVO = new KwtLogisticsOrderVO();
        kwtLogisticsOrderVO.setId(logOrder.getId());
        kwtLogisticsOrderVO.setEntId(logOrder.getEntId());
        kwtLogisticsOrderVO.setTOrderId(logOrder.getTOrderId());
        kwtLogisticsOrderVO.setTOrderNo(logOrder.getTOrderNo());
        kwtLogisticsOrderVO.setLOrderNo(logOrder.getLOrderNo());
        kwtLogisticsOrderVO.setPid(logOrder.getPid());
        kwtLogisticsOrderVO.setSettlementCycle(logOrder.getSettlementCycle());
        kwtLogisticsOrderVO.setBillingMode(logOrder.getBillingMode());
        kwtLogisticsOrderVO.setPrice(logOrder.getPrice());
        kwtLogisticsOrderVO.setPriceType(logOrder.getPriceType());
        kwtLogisticsOrderVO.setAmount(logOrder.getAmount());
        kwtLogisticsOrderVO.setUnit(logOrder.getUnit());
        kwtLogisticsOrderVO.setLoss(logOrder.getLoss());
        kwtLogisticsOrderVO.setLossUnit(logOrder.getLossUnit());
        kwtLogisticsOrderVO.setGoodsPrice(logOrder.getGoodsPrice());
        kwtLogisticsOrderVO.setGoodsPriceUnit(logOrder.getGoodsPriceUnit());
        if (logOrder.getStartTime() != null) {
            kwtLogisticsOrderVO.setStartTime(Date.from(logOrder.getStartTime().atZone(ZoneId.systemDefault()).toInstant()));
        }
        if (logOrder.getEndTime() != null) {
            kwtLogisticsOrderVO.setEntTime(Date.from(logOrder.getEndTime().atZone(ZoneId.systemDefault()).toInstant()));
        }
        kwtLogisticsOrderVO.setSubcontractAmount(logOrder.getSubcontractAmount());
        kwtLogisticsOrderVO.setEntrustAmount(logOrder.getEntrustAmount());
        kwtLogisticsOrderVO.setUnloadAmount(logOrder.getUnloadAmount());
        kwtLogisticsOrderVO.setLoadAmount(logOrder.getLoadAmount());
        kwtLogisticsOrderVO.setIgnoreAmount(logOrder.getIgnoreAmount());
        kwtLogisticsOrderVO.setDeficitAmount(logOrder.getDeficitAmount());
        kwtLogisticsOrderVO.setDeficitPrice(logOrder.getDeficitPrice());
        kwtLogisticsOrderVO.setPayment(logOrder.getPayment());
        kwtLogisticsOrderVO.setTaxRate(logOrder.getTaxRate());
        kwtLogisticsOrderVO.setRemark(logOrder.getRemark());
        kwtLogisticsOrderVO.setStatus(logOrder.getStatus());
        kwtLogisticsOrderVO.setCreateBy(logOrder.getCreateBy());
        kwtLogisticsOrderVO.setCreateTime(logOrder.getCreateTime());
        kwtLogisticsOrderVO.setUpdateBy(logOrder.getUpdateBy());
        kwtLogisticsOrderVO.setUpdateTime(logOrder.getUpdateTime());
        kwtLogisticsOrderVO.setDelFlag(logOrder.getDelFlag());
        return kwtLogisticsOrderVO;
    }

    @NotNull
    private static RWaybillSubOrderVo.BillSubOrder getRWaybillSubOrderVo(KwtWaybillOrderSubtask subtask, Long goodsId, KwtLogisticsOrder logisticsOrder) {
        RWaybillSubOrderVo.BillSubOrder billSubOrder = new RWaybillSubOrderVo.BillSubOrder();
        billSubOrder.setEntId(subtask.getEntId());
        billSubOrder.setLOrderId(subtask.getLOrderId());
        billSubOrder.setWOrderId(subtask.getWOrderId());
        billSubOrder.setWOrderNo(subtask.getWOrderNo());
        billSubOrder.setUnit(subtask.getUnit());
        billSubOrder.setEntrustAmount(subtask.getEntrustAmount());
        billSubOrder.setUnloadAmount(subtask.getUnloadAmount());
        billSubOrder.setUnloadTime(subtask.getUnloadTime());
        billSubOrder.setLoadAmount(subtask.getLoadAmount());
        billSubOrder.setLoadTime(subtask.getLoadTime());
        billSubOrder.setDeficitAmount(subtask.getDeficitAmount());
        billSubOrder.setDeficitPrice(subtask.getDeficitPrice());
        billSubOrder.setGoodId(goodsId);
        billSubOrder.setStatus(subtask.getStatus());
        if (Objects.nonNull(logisticsOrder)) {
            billSubOrder.setBillMode(logisticsOrder.getBillingMode());
        }
        return billSubOrder;
    }

    @NotNull
    private static RWaybillOrderVo getWaybillOrderVo(KwtWaybillOrder waybillOrder) {
        RWaybillOrderVo vo = new RWaybillOrderVo();
        vo.setId(waybillOrder.getId());
        vo.setEntId(waybillOrder.getEntId());
        vo.setLOrderId(waybillOrder.getLOrderId());
        vo.setWOrderNo(waybillOrder.getWOrderNo());
        vo.setType(waybillOrder.getType());
        vo.setTruckId(waybillOrder.getTruckId());
        vo.setTruckNo(waybillOrder.getTruckNo());
        vo.setDriverId(waybillOrder.getDriverId());
        vo.setDriverName(waybillOrder.getDriverName());
        vo.setDriverPhone(waybillOrder.getDriverPhone());
        vo.setDriverIdcard(waybillOrder.getDriverIdcard());
        vo.setStartTime(waybillOrder.getStartTime());
        vo.setEndTime(waybillOrder.getEndTime());
        vo.setStatus(waybillOrder.getStatus());
        vo.setDepartureTime(waybillOrder.getEndTime());
        return vo;
    }

    /**
     * 查询物流订单已派运力车辆
     *
     * @param param
     * @return
     */
    public List<CapacityTruckVO> queryCapacityTruck(CapacityTruckParam param) {
        log.info("查询物流订单已派运力车辆：{}", com.alibaba.fastjson.JSON.toJSONString(param));
        LambdaQueryWrapper<KwtLogisticsOrderCirculate> queryWrapper = Wrappers.<KwtLogisticsOrderCirculate>lambdaQuery()
                .in(KwtLogisticsOrderCirculate::getEntId, param.getEntId())
                .eq(KwtLogisticsOrderCirculate::getDelFlag, 0)
                .eq(KwtLogisticsOrderCirculate::getTruckNo, param.getTruckNo())
                .orderByDesc(KwtLogisticsOrderCirculate::getCreateTime)
                .orderByAsc(KwtLogisticsOrderCirculate::getId);
        //TODO 是否考虑订单状态
        List<KwtLogisticsOrderCirculate> orderCirculateList = logisticsOrderCirculateRepository.list(queryWrapper);
        if (CollectionUtils.isEmpty(orderCirculateList)) {
            return new ArrayList<>();
        }
        //获取车牌号
        List<Long> truckId = orderCirculateList.stream().map(KwtLogisticsOrderCirculate::getTruckId)
                .distinct().collect(Collectors.toList());
        //查询车辆信息
        List<RTruckVo> truckByTruckIds = remoteFleetService.findTruckByTruckIds(truckId);
        List<CapacityTruckVO> truckVOList = truckByTruckIds.stream().map(truck -> {
            CapacityTruckVO truckVO = new CapacityTruckVO();
            truckVO.setTruckId(truck.getId());
            truckVO.setTruckNo(truck.getTruckNo());
            return truckVO;
        }).collect(Collectors.toList());
        log.info("查询物流订单已派运力车辆成功，结果：{}", com.alibaba.fastjson.JSON.toJSONString(param));
        return truckVOList;
    }


    /**
     * 查询物流订单已派运力车辆
     *
     * @param param
     * @return
     */
    public List<RWaybillOrderVo> queryWaybillOrder(CapacityTruckParam param) {
        log.info("查询物流运单已派运力车辆：{}", com.alibaba.fastjson.JSON.toJSONString(param));
        LambdaQueryWrapper<KwtWaybillOrder> queryWrapper = Wrappers.<KwtWaybillOrder>lambdaQuery()
                .eq(KwtWaybillOrder::getDelFlag, 0)
                .eq(KwtWaybillOrder::getTruckNo, param.getTruckNo())
                .in(KwtWaybillOrder::getStatus, FORBIDDEN_STATUSES)
                .orderByDesc(KwtWaybillOrder::getCreateTime)
                .orderByAsc(KwtWaybillOrder::getId);

        List<KwtWaybillOrder> waybillOrderList = waybillOrderRepository.list(queryWrapper);
        if (CollectionUtils.isEmpty(waybillOrderList)) {
            return new ArrayList<>();
        }
        return waybillOrderList.stream()
                .map(TransportServiceImpl::getWaybillOrderVo)
                .collect(Collectors.toList());
    }

    @Override
    public Integer addLogisticOrder(AddLogisticOrderParam param) {
        log.info("新增物流订单：{}", JSON.toJSONString(param));
        AddLogisticOrderDTO addLogisticOrderDTO = getAddLogisticOrderDTO(param);
        return kwtAcceptCarriageOrderService.addLogisticOrder(addLogisticOrderDTO);
    }

    @Override
    public Boolean logisticOrderFinish(OrderFinishParam req) {
        log.info("流程完结物流订单：{}", JSON.toJSONString(req));
        if (Objects.isNull(req.getTradeOrderId())) {
            throw new BusinessException("贸易订单id不能为空");
        }

        OrderFinishReq orderFinishReq = new OrderFinishReq();
        orderFinishReq.setTradeOrderId(req.getTradeOrderId());
        return logisticsConsignmentService.logisticOrderFinish(orderFinishReq);

    }

    @Override
    public List<KwtLogisticsOrderVO> getLogisticOrderList(OrderFinishParam param) {
        if (Objects.isNull(param.getTradeOrderId())) {
            throw new BusinessException("贸易订单id不能为空");
        }
        List<KwtLogisticsOrder> kwtLogisticsOrders = logisticsOrderRepository.queryByTradeOrderId(param.getTradeOrderId());
        if (CollectionUtils.isEmpty(kwtLogisticsOrders)) {
            return List.of();
        }
        return kwtLogisticsOrders.stream()
                .map(TransportServiceImpl::getLogisticsOrderVo)
                .collect(Collectors.toList());

    }

    @Override
    public List<RWaybillSubOrderVo> queryWaybillOrderByLogContractIds(Set<Long> logContractIds) {
        if (CollectionUtils.isEmpty(logContractIds)) {
            return List.of();
        }
        //根据物流合同查询物流id
        List<KwtLogisticsOrderContract> logisticsOrderContracts = logisticsOrderContractRepository.queryByLogContractIds(logContractIds);
        if (CollectionUtils.isEmpty(logisticsOrderContracts)) {
            return List.of();
        }
        List<Long> logIds = logisticsOrderContracts.stream()
                .map(KwtLogisticsOrderContract::getLOrderId)
                .distinct()
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(logIds)) {
            return List.of();
        }
        //查询物流运单
        List<KwtWaybillOrderSubtask> waybillOrderSubtasks = waybillOrderSubtaskRepository.queryByLogIds(logIds);
        if (CollectionUtils.isEmpty(waybillOrderSubtasks)) {
            return List.of();
        }
        Map<Long, List<KwtWaybillOrderSubtask>> logIdAndWaybillOrderSubtasksMap = waybillOrderSubtasks.stream()
                .collect(Collectors.groupingBy(KwtWaybillOrderSubtask::getLOrderId));
        //查询物流 订单
        List<KwtLogisticsOrder> logOrders = logisticsOrderRepository.queryByLogisticsOrderIds(logIds);
        if (CollectionUtils.isEmpty(logOrders)) {
            return List.of();
        }
        Map<Long, KwtLogisticsOrder> logIdAndLogOrderMap = logOrders.stream()
                .collect(Collectors.toMap(KwtLogisticsOrder::getId, Function.identity(), (x, y) -> x));
        //查询物流订单和的商品关系
        List<KwtLogisticsOrderGoods> logOrderGoods = logisticsOrderGoodsRepository.queryByLogIds(logIds);
        Map<Long, KwtLogisticsOrderGoods> logisticsOrderGoodsMap = Maps.newHashMap();
        if (CollectionUtils.isNotEmpty(logOrderGoods)) {
            logisticsOrderGoodsMap = logOrderGoods.stream()
                    .collect(Collectors.toMap(KwtLogisticsOrderGoods::getLOrderId, Function.identity(), (x, y) -> x));
        }
        Map<Long, KwtLogisticsOrderGoods> finalLogisticsOrderGoodsMap = logisticsOrderGoodsMap;
        return logisticsOrderContracts.stream().map(x -> {
            RWaybillSubOrderVo rWaybillSubOrderVo = new RWaybillSubOrderVo();
            rWaybillSubOrderVo.setLogContractId(x.getContractId());
            KwtLogisticsOrder logisticsOrder = logIdAndLogOrderMap.getOrDefault(x.getLOrderId(), new KwtLogisticsOrder());
            KwtLogisticsOrderGoods goods = finalLogisticsOrderGoodsMap.getOrDefault(x.getLOrderId(), new KwtLogisticsOrderGoods());
            List<KwtWaybillOrderSubtask> subtasks = logIdAndWaybillOrderSubtasksMap.getOrDefault(x.getLOrderId(), new ArrayList<>());
            List<RWaybillSubOrderVo.BillSubOrder> subOrders = subtasks.stream()
                    .map(s -> getRWaybillSubOrderVo(s, goods.getGoodsId(), logisticsOrder))
                    .collect(Collectors.toList());
            rWaybillSubOrderVo.setSubOrders(subOrders);
            return rWaybillSubOrderVo;
        }).collect(Collectors.toList());

    }

    @NotNull
    private static AddLogisticOrderDTO getAddLogisticOrderDTO(AddLogisticOrderParam param) {
        AddLogisticOrderDTO addLogisticOrderDTO = new AddLogisticOrderDTO();
        List<LogisticInfo> logisticInfo = param.getLogisticInfo();
        if (CollectionUtils.isEmpty(logisticInfo)) {
            throw new BusinessException("物流信息不能为空");
        }
        List<LogisticData> infos = logisticInfo.stream()
                .map(TransportServiceImpl::getLogisticInfo)
                .collect(Collectors.toList());
        addLogisticOrderDTO.setLogisticInfo(infos);
        addLogisticOrderDTO.setEntId(param.getEntId());
        addLogisticOrderDTO.setUserId(param.getUserId());
        addLogisticOrderDTO.setTradeOrderId(param.getTradeOrderId());
        addLogisticOrderDTO.setTradeOrderNo(param.getTradeOrderNo());
        addLogisticOrderDTO.setNonConsignCompany(param.getNonConsignCompany());
        addLogisticOrderDTO.setNonConsignCompanyId(param.getNonConsignCompanyId());
        addLogisticOrderDTO.setNonConsignContactPhone(param.getNonConsignContactPhone());
        addLogisticOrderDTO.setNonConsignContacts(param.getNonConsignContacts());
        addLogisticOrderDTO.setNonConsignContactsId(param.getNonConsignContactsId());

        addLogisticOrderDTO.setConsignCompany(param.getConsignCompany());
        addLogisticOrderDTO.setConsignCompanyId(param.getConsignCompanyId());
        addLogisticOrderDTO.setConsignContactPhone(param.getConsignContactPhone());
        addLogisticOrderDTO.setConsignContacts(param.getConsignContacts());
        addLogisticOrderDTO.setConsignContactsId(param.getConsignContactsId());
        addLogisticOrderDTO.setGoodsId(param.getGoodsId());
        addLogisticOrderDTO.setGoodsName(param.getGoodsName());
        addLogisticOrderDTO.setGoodsType(param.getGoodsType());
        addLogisticOrderDTO.setGoodsPrice(param.getGoodsPrice());
        addLogisticOrderDTO.setGoodsPriceUnit(param.getGoodsPriceUnit());
        addLogisticOrderDTO.setLoadName(param.getLoadName());
        addLogisticOrderDTO.setLoadCityCode(param.getLoadCityCode());
        addLogisticOrderDTO.setLoadCityName(param.getLoadCityName());
        addLogisticOrderDTO.setLoadContacts(param.getLoadContacts());
        addLogisticOrderDTO.setLoadPhone(param.getLoadPhone());
        addLogisticOrderDTO.setLoadDetailAddress(param.getLoadDetailAddress());
        addLogisticOrderDTO.setUnloadId(param.getUnloadId());
        addLogisticOrderDTO.setUnloadName(param.getUnloadName());
        addLogisticOrderDTO.setUnloadCityCode(param.getUnloadCityCode());
        addLogisticOrderDTO.setUnloadCityName(param.getUnloadCityName());
        addLogisticOrderDTO.setUnLoadDetailAddress(param.getUnLoadDetailAddress());
        addLogisticOrderDTO.setUnloadContacts(param.getUnloadContacts());
        addLogisticOrderDTO.setUnloadPhone(param.getUnloadPhone());
        addLogisticOrderDTO.setLoadLat(param.getLoadLat());
        addLogisticOrderDTO.setLoadLng(param.getLoadLng());
        addLogisticOrderDTO.setUnloadLat(param.getUnloadLat());
        addLogisticOrderDTO.setUnloadLng(param.getUnloadLng());
        addLogisticOrderDTO.setBillingMode(param.getBillingMode());
        addLogisticOrderDTO.setStartTime(param.getStartTime());
        addLogisticOrderDTO.setEndTime(param.getEndTime());
        addLogisticOrderDTO.setDispatchWay(param.getDispatchWay());
        addLogisticOrderDTO.setActualDisPatch(param.getActualDisPatch());
        addLogisticOrderDTO.setGoodsUnit(param.getGoodsUnit());
        addLogisticOrderDTO.setMeasurementWay(param.getMeasurementWay());
        return addLogisticOrderDTO;
    }

    private static LogisticData getLogisticInfo(LogisticInfo logistic) {
        LogisticData info = new LogisticData();
        info.setContractId(logistic.getContractId());
        info.setContractNo(logistic.getContractNo());
        info.setContractName(logistic.getContractName());
        info.setAcceptCompanyId(logistic.getAcceptCompanyId());
        info.setAcceptContactPhone(logistic.getAcceptContactPhone());
        info.setAcceptContacts(logistic.getAcceptContacts());
        info.setAcceptContactsId(logistic.getAcceptContactsId());
        info.setAcceptCompany(logistic.getAcceptCompany());
        info.setPrice(logistic.getPrice());
        info.setPriceType(logistic.getPriceType());
//        info.setUnloadId(logistic.getUnloadId());
//        info.setUnloadName(logistic.getUnloadName());
//        info.setUnloadCityCode(logistic.getUnloadCityCode());
//        info.setUnloadCityName(logistic.getUnloadCityName());
        info.setAmount(logistic.getAmount());
        info.setAmountUnit(logistic.getAmountUnit());
        info.setLoss(logistic.getLoss());
        info.setPayment(logistic.getPayment());
        info.setSigningWay(logistic.getSigningWay());
        info.setLossUnit(logistic.getLossUnit());
        info.setRemark(logistic.getRemark());
        info.setType(logistic.getType());
        return info;
    }

    /**
     * 查询司机的当天完成量、7天完成量、30天完成量
     *
     * @param entId    企业id
     * @param driverId
     * @return
     */
    public WaybillOrderTaskVO queryWaybillOrderTaskByDriverId(Long entId, Long driverId) {
        log.info("查询司机的完成量：企业id：{}，司机id：{}", entId, driverId);
        WaybillOrderTaskVO taskVO = new WaybillOrderTaskVO();
        // 1. 查询司机近30天的所有运单
        List<KwtWaybillOrder> waybillOrders = waybillOrderRepository.queryByEntIdAndDriverId(entId, driverId);
        if (CollectionUtils.isEmpty(waybillOrders)) {
            return taskVO;
        }
        // 2. 查询关联的物流订单（获取结算方式）
        List<Long> logOrderIds = waybillOrders.stream().map(KwtWaybillOrder::getLOrderId).distinct().toList();
        List<KwtLogisticsOrder> logisticsOrders = logisticsOrderRepository.queryByLogisticsOrderIds(logOrderIds);
        if (CollectionUtils.isEmpty(logisticsOrders)) {
            return taskVO;
        }
        Map<Long, KwtLogisticsOrder> logOrderMap = logisticsOrders.stream().collect(Collectors.toMap(KwtLogisticsOrder::getId, Function.identity(), (x, y) -> x));

        // 3. 定义时间范围
        Date todayStart = DateUtil.beginOfDay(new Date()); // 当天00:00:00
        Date todayEnd = DateUtil.endOfDay(new Date());  // 当天23:59:59
        Date sevenDaysStart = DateUtil.beginOfDay(DateUtil.offsetDay(new Date(), -7)); // 7天前的00:00:00
        Date thirtyDaysStart = DateUtil.beginOfDay(DateUtil.offsetDay(new Date(), -30)); // 30天前的00:00:00
        //4. 初始化计数器
        int todayCount = 0;
        int weeklyCount = 0;
        int monthlyCount = 0;

        // 5. 按物流订单ID分组
        Map<Long, List<KwtWaybillOrder>> waybillOrderMaps = waybillOrders.stream().collect(Collectors
                .groupingBy(KwtWaybillOrder::getLOrderId));

        // 6. 统计各时间维度有效运单量
        for (Map.Entry<Long, List<KwtWaybillOrder>> orderEntry : waybillOrderMaps.entrySet()) {
            Long key = orderEntry.getKey();
            List<KwtWaybillOrder> waybillOrderList = orderEntry.getValue();
            KwtLogisticsOrder orDefault = logOrderMap.getOrDefault(key, new KwtLogisticsOrder());
            //结算方式
            String billingMode = orDefault.getBillingMode();

            for (KwtWaybillOrder order : waybillOrderList) {
                // 检查运单完成时间
                Date updateTime = order.getUpdateTime();
                if (updateTime == null) {
                    continue;
                }

                boolean statusValid;
                //按照装货量结算(统计“已卸货” “已完成”运单)

                if (Objects.equals(billingMode, String.valueOf(1))) {
                    statusValid = CarWaybillV1Enum.COMPLETION_LOADING.getCode().equals(order.getStatus())
                            || CarWaybillV1Enum.COMPLETED.getCode().equals(order.getStatus());
                } else {
                    //按照卸货量结算(统计“已完成”运单)
                    statusValid = order.getStatus().equals(CarWaybillV1Enum.COMPLETED.getCode());
                }

                if (!statusValid) {
                    continue;
                }
                // 按时间范围统计
                if (updateTime.after(todayStart) && updateTime.before(todayEnd)) {
                    todayCount++;
                }
                if (updateTime.after(sevenDaysStart) && updateTime.before(todayEnd)) {
                    weeklyCount++;
                }
                if (updateTime.after(thirtyDaysStart) && updateTime.before(todayEnd)) {
                    monthlyCount++;
                }
            }
        }
        // 7. 设置返回值
        taskVO.setTodayTaskAmount(todayCount);
        taskVO.setWeeklyTaskAmount(weeklyCount);
        taskVO.setMonthlyTaskAmount(monthlyCount);
        return taskVO;
    }

    @Override
    public RWaybillOrderVo queryWaybillOrderByWayBillOrderId(Long wayBillOrderId) {
        KwtWaybillOrder waybillOrder = waybillOrderRepository.queryByBillOrderId(wayBillOrderId);
        if (Objects.isNull(waybillOrder)) {
            return new RWaybillOrderVo();
        }
        //查询子运单
        KwtWaybillOrderSubtask subtasks = waybillOrderSubtaskRepository.queryByWOrderId(waybillOrder.getId());
        List<KwtLogisticsOrderAddress> addressList = null;
        if (Objects.nonNull(subtasks) && Objects.nonNull(subtasks.getLOrderId())) {
            addressList = logisticsOrderAddressRepository.queryByLogOrderId(subtasks.getLOrderId());
        }
        RWaybillOrderVo rWaybillOrderVo = new RWaybillOrderVo();
        rWaybillOrderVo.setId(waybillOrder.getId());
        rWaybillOrderVo.setEntId(waybillOrder.getEntId());
        rWaybillOrderVo.setLOrderId(waybillOrder.getLOrderId());
        rWaybillOrderVo.setWOrderNo(waybillOrder.getWOrderNo());
        rWaybillOrderVo.setType(waybillOrder.getType());
        rWaybillOrderVo.setTruckId(waybillOrder.getTruckId());
        rWaybillOrderVo.setTruckNo(waybillOrder.getTruckNo());
        rWaybillOrderVo.setDriverId(waybillOrder.getDriverId());
        rWaybillOrderVo.setDriverName(waybillOrder.getDriverName());
        rWaybillOrderVo.setDriverPhone(waybillOrder.getDriverPhone());
        rWaybillOrderVo.setDriverIdcard(waybillOrder.getDriverIdcard());
        rWaybillOrderVo.setStartTime(waybillOrder.getStartTime());
        rWaybillOrderVo.setEndTime(waybillOrder.getEndTime());
        rWaybillOrderVo.setStatus(waybillOrder.getStatus());
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(addressList)) {
            addressList.forEach(address -> {
                if (Objects.equals(address.getAddressType(), AddressTypeEnum.SHIPMENT.getCode())) {
                    rWaybillOrderVo.setStartLng(address.getLng());
                    rWaybillOrderVo.setStartLat(address.getLat());
                } else if (Objects.equals(address.getAddressType(), AddressTypeEnum.TAKE.getCode())) {
                    rWaybillOrderVo.setEndLng(address.getLng());
                    rWaybillOrderVo.setEndLat(address.getLat());
                }
            });
        }

        return rWaybillOrderVo;
    }

    @Override
    public WaybillOrderSubtaskVo queryWaybillOrderId(Long wayBillOrderId) {
        KwtWaybillOrderSubtask kwtWaybillOrder = waybillOrderSubtaskRepository.queryByBillOrderId(wayBillOrderId);
        if (Objects.isNull(kwtWaybillOrder)) {
            return new WaybillOrderSubtaskVo();
        }
        WaybillOrderSubtaskVo rWaybillOrderVo = new WaybillOrderSubtaskVo();
        rWaybillOrderVo.setId(kwtWaybillOrder.getId());
        rWaybillOrderVo.setEntId(kwtWaybillOrder.getEntId());
        rWaybillOrderVo.setLOrderId(kwtWaybillOrder.getLOrderId());
        return rWaybillOrderVo;
    }

    @Override
    public List<KwtLogisticsOrderAddressVo> queryByWOrderId(Long wayBillOrderId) {
        List<KwtLogisticsOrderAddress> addressList = logisticsOrderAddressRepository.queryByLogOrderId(wayBillOrderId);
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(addressList)) {
            return List.of();
        }
        return addressList.stream().map(address -> {
            KwtLogisticsOrderAddressVo vo = new KwtLogisticsOrderAddressVo();
            vo.setId(address.getId());
            vo.setAddressType(address.getAddressType());
            vo.setDetailAddress(address.getDetailAddress());
            vo.setLng(address.getLng());
            vo.setLat(address.getLat());
            return vo;
        }).collect(Collectors.toList());

    }

    @Override
    public List<WayContaractbillOrderVo> queryLogisticContractByContTradeIds(Set<Long> contractIds) {
        if (CollectionUtils.isEmpty(contractIds)) {
            return List.of();
        }
        //根据物流合同查询物流id
        List<KwtLogisticsOrderContract> logisticsOrderContracts = logisticsOrderContractRepository.queryByLogContractIds(contractIds);
        if (CollectionUtils.isEmpty(logisticsOrderContracts)) {
            return List.of();
        }

        Map<Long, List<Long>> logContractIdAndContractsMap = logisticsOrderContracts.stream()
                .collect(Collectors.groupingBy(KwtLogisticsOrderContract::getContractId, Collectors.mapping(KwtLogisticsOrderContract::getLOrderId, Collectors.toList())));
        List<Long> logIds = logisticsOrderContracts.stream()
                .map(KwtLogisticsOrderContract::getLOrderId)
                .distinct()
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(logIds)) {
            return List.of();
        }
        //查询物流订单
        List<KwtLogisticsOrder> kwtLogisticsOrders = logisticsOrderRepository.queryByLogisticsOrderIds(logIds);
        if (CollectionUtils.isEmpty(kwtLogisticsOrders)) {
            return List.of();
        }
        List<WayContaractbillOrderVo> result = Lists.newArrayList();
        logContractIdAndContractsMap.forEach((contractId, contracts) -> {
            WayContaractbillOrderVo wayContaractbillOrderVo = new WayContaractbillOrderVo();
            wayContaractbillOrderVo.setContractId(contractId);
            List<KwtLogisticsOrder> logisticsOrders = kwtLogisticsOrders.stream()
                    .filter(log -> contracts.contains(log.getId()))
                    .collect(Collectors.toList());
            List<KwtLogisticsOrderVO> kwtLogisticsOrderVOS = Optional.ofNullable(logisticsOrders).orElse(List.of()).stream().map(x -> {
                KwtLogisticsOrderVO rWaybillOrderVo = new KwtLogisticsOrderVO();
                rWaybillOrderVo.setId(x.getId());
                rWaybillOrderVo.setEntId(x.getEntId());
                rWaybillOrderVo.setTOrderId(x.getTOrderId());
                rWaybillOrderVo.setTOrderNo(x.getTOrderNo());
                rWaybillOrderVo.setLOrderNo(x.getLOrderNo());
                rWaybillOrderVo.setPid(x.getPid());
                rWaybillOrderVo.setSettlementCycle(x.getSettlementCycle());
                rWaybillOrderVo.setBillingMode(x.getBillingMode());
                rWaybillOrderVo.setPrice(x.getPrice());
                rWaybillOrderVo.setPriceType(x.getPriceType());
                rWaybillOrderVo.setAmount(x.getAmount());
                rWaybillOrderVo.setUnit(x.getUnit());
                rWaybillOrderVo.setLoss(x.getLoss());
                rWaybillOrderVo.setLossUnit(x.getLossUnit());
                rWaybillOrderVo.setGoodsPrice(x.getGoodsPrice());
                rWaybillOrderVo.setGoodsPriceUnit(x.getGoodsPriceUnit());
                rWaybillOrderVo.setSubcontractAmount(x.getSubcontractAmount());
                rWaybillOrderVo.setEntrustAmount(x.getEntrustAmount());
                rWaybillOrderVo.setUnloadAmount(x.getUnloadAmount());
                rWaybillOrderVo.setLoadAmount(x.getLoadAmount());
                rWaybillOrderVo.setIgnoreAmount(x.getIgnoreAmount());
                rWaybillOrderVo.setDeficitAmount(x.getDeficitAmount());
                rWaybillOrderVo.setDeficitPrice(x.getDeficitPrice());
                rWaybillOrderVo.setPayment(x.getPayment());
                rWaybillOrderVo.setTaxRate(x.getTaxRate());
                rWaybillOrderVo.setTotalLoadAmount(x.getTotalLoadAmount());
                rWaybillOrderVo.setTotalUnloadAmount(x.getTotalUnloadAmount());
                rWaybillOrderVo.setRemark(x.getRemark());
                rWaybillOrderVo.setStatus(x.getStatus());
                rWaybillOrderVo.setCreateBy(x.getCreateBy());
                rWaybillOrderVo.setCreateTime(x.getCreateTime());
                rWaybillOrderVo.setUpdateBy(x.getUpdateBy());
                rWaybillOrderVo.setUpdateTime(x.getUpdateTime());
                rWaybillOrderVo.setDelFlag(x.getDelFlag());
                return rWaybillOrderVo;
            }).collect(Collectors.toList());
            wayContaractbillOrderVo.setOrderVos(kwtLogisticsOrderVOS);
            result.add(wayContaractbillOrderVo);
        });
        return result;
    }

    @Override
    public Long queryLogisticsCount(Long entId,Integer type) {
        QueryLogisticsOrderReq queryLogisticsOrderReq = new QueryLogisticsOrderReq();
        if(Objects.equals(type,3)){
            queryLogisticsOrderReq.setCarriageCompanyId(String.valueOf(entId));
        }else {
            queryLogisticsOrderReq.setConsignCompanyId(String.valueOf(entId));
        }
        OrderStatusStatisticsResp orderStatusStatisticsResp = logisticsConsignmentService.orderStatusStatistics(queryLogisticsOrderReq);
        List<OrderStatusStatisticsResp.OrderStatusStatistics> orderStatusStatistics = orderStatusStatisticsResp.getOrderStatusStatistics();

        if (CollUtil.isEmpty(orderStatusStatistics)) {
            return 0L;
        }
        Optional<OrderStatusStatisticsResp.OrderStatusStatistics> first = orderStatusStatistics.stream().filter(d -> StrUtil.equals(d.getOrderStatus(), "5")).findFirst();
        return first.map(contractStatusCount -> Long.parseLong(contractStatusCount.getOrderNum())).orElse(0L);

    }

    @Override
    public Long queryWaybillCount() {
        StatisticsWaybillResp statisticsWaybillResp = waybillOrderV1Service.statisticsWaybillOrder(new WaybillOrderReq());
        List<StatisticsWaybillResp.OrderBillStatusStatistics> orderStatusStatistics = statisticsWaybillResp.getOrderStatusStatistics();
        if (CollUtil.isEmpty(orderStatusStatistics)) {
            return 0L;
        }
        Optional<StatisticsWaybillResp.OrderBillStatusStatistics> first = orderStatusStatistics.stream().filter(d -> StrUtil.equals(d.getOrderStatus(), "20")).findFirst();
        return first.map(contractStatusCount -> Long.parseLong(contractStatusCount.getOrderNum())).orElse(0L);

    }

    @Override
    public Long queryCount() {
        List<Long> ids = new ArrayList<>();
        if (!LoginUserHolder.isManager()) {
            ids = LoginUserHolder.getChildEntList();
        }
        return logisticsOrderMapper.queryCount(ids);
    }

    @Override
    public List<LogisticsVo> logisticsList() {
        List<Long> ids = new ArrayList<>();
        if (!LoginUserHolder.isManager()) {
            ids = LoginUserHolder.getChildEntList();
        }
        return kwtWaybillOrderMapper.queryList(ids, false);
    }

    @Override
    public LogisticsDto logisticsRank(TimePara timePara) {
        List<Long> ids = new ArrayList<>();
        if (!LoginUserHolder.isManager()) {
            ids = LoginUserHolder.getChildEntList();
        }

        List<WaybillRankVo> waybillRankVos = kwtWaybillOrderMapper.logisticsRank(ids, timePara);
        if (CollUtil.isEmpty(waybillRankVos)) {
            waybillRankVos = new ArrayList<>();
        }
        LogisticsDto logisticsDto = new LogisticsDto();
        List<String> strings = new ArrayList<>();
        List<BigDecimal> strings1 = new ArrayList<>();
        for (WaybillRankVo waybillRankVo : waybillRankVos) {
            strings.add(waybillRankVo.getFirmName());
            strings1.add(Objects.nonNull(waybillRankVo.getAmount()) ? waybillRankVo.getAmount() : new BigDecimal("0"));
        }
        logisticsDto.setFirmName(strings);
        logisticsDto.setAmount(strings1);

        return logisticsDto;
    }

    private List<Long> separateAndRotate(List<Long> list, long pivot) {
        if (list == null || list.isEmpty()) {
            return new ArrayList<>();
        }

        // 查找分隔元素的索引
        int pivotIndex = list.indexOf(pivot);
        if (pivotIndex == -1) {
            // 如果元素不存在，返回原列表的副本
            return new ArrayList<>(list);
        }

        List<Long> result = new ArrayList<>();

        // 添加右边的元素（分隔元素之后的部分）
        for (int i = pivotIndex + 1; i < list.size(); i++) {
            result.add(list.get(i));
        }

        // 添加左边的元素（分隔元素之前的部分）
        for (int i = 0; i < pivotIndex; i++) {
            result.add(list.get(i));
        }
        return result;
    }

    @Override
    public WaybillOrderDetailVo auditLogisticsTask(LogisticsOrderAuditPara para) {
        Long orderId = para.getOrderId();
        List<Long> ids = new ArrayList<>();
        if (!LoginUserHolder.isManager()) {
            ids = LoginUserHolder.getChildEntList();
        }
        String key = String.format(RedisConstant.AUDIT_LOGISTICS_TASK, LoginUserHolder.getEntId());

        if (para.getStart()) {//首次加载，合同id为第一个合同
            if (Boolean.TRUE.equals(redisTemplate.hasKey(key))) {
                redisTemplate.delete(key);
            }
            //写入缓存
            List<LogisticsVo> tradeVos = kwtWaybillOrderMapper.queryList(ids, true);
            if (CollUtil.isNotEmpty(tradeVos)) {
                List<Long> list = tradeVos.stream().map(LogisticsVo::getId).toList();
                List<Long> longs = separateAndRotate(list, orderId);
                redisTemplate.opsForList().rightPushAll(key, longs);
                redisTemplate.expire(key, 24, TimeUnit.HOURS);
            }

        } else {
            //继续审核合同，合同id为上一次的合同id。
            orderId = (Long) redisTemplate.opsForList().leftPop(key);
            if (Objects.isNull(orderId)) {
                throw new BusinessException("已审核完成");
            }
        }
        WaybillOrderRequest waybillOrderRequest = new WaybillOrderRequest();
        waybillOrderRequest.setOrderId(orderId);
        WaybillOrderDetailResp waybillOrderDetailResp = waybillOrderV1Service.queryBillOrderDetail(waybillOrderRequest);

        WaybillOrderDetailVo order = BeanUtil.copyProperties(waybillOrderDetailResp, WaybillOrderDetailVo.class);

        if (Objects.nonNull(order)) {
            return order;
        }
        throw new BusinessException("未找到贸易订单");
    }

    @Override
    public Object countLogistics(CountPara2 countPara) {
        List<Long> ids = new ArrayList<>();
        if (!LoginUserHolder.isManager()) {
            ids = LoginUserHolder.getChildEntList();
        }
        List<WaybillVo> waybillVos = kwtWaybillOrderMapper.countLogistics(countPara, ids);
        if (CollUtil.isEmpty(waybillVos)) {
            waybillVos = new ArrayList<>();
        }

        com.alibaba.fastjson2.JSONObject jsonObject = new com.alibaba.fastjson2.JSONObject();
        List<String> two = new ArrayList<>();
        List<BigDecimal> three = new ArrayList<>();
        for (WaybillVo saleVo : waybillVos) {
            two.add(saleVo.getFirmName());
            three.add(Objects.nonNull(saleVo.getMoney()) ? saleVo.getMoney().divide(new BigDecimal("10000"), RoundingMode.HALF_UP) : new BigDecimal("0"));
        }

        jsonObject.put("firm", two);
        jsonObject.put("amount", three);

        return jsonObject;
    }

    @Override
    public List<LogisticContractVo> queryLogOrderCirculateByLogOrderId(Long tradeOrderId) {
        //根据贸易订单查询物流订单
        List<KwtLogisticsOrder> logisticsOrders = logisticsOrderRepository.queryByTradeOrderId(tradeOrderId);
        if (CollectionUtils.isEmpty(logisticsOrders)) {
            return new ArrayList<>();
        }
        Set<Long> logOrderIds = logisticsOrders.stream().map(KwtLogisticsOrder::getId).collect(Collectors.toSet());
        //查询物流订单合同信息
        List<KwtLogisticsOrderContract> logisticsOrderContracts = logisticsOrderContractRepository.queryByLogOrderIds(logOrderIds);
        return logisticsOrderContracts.stream().map(con -> {
            LogisticContractVo logisticContractVo = new LogisticContractVo();
            logisticContractVo.setLogContractId(con.getContractId());
            return logisticContractVo;
        }).collect(Collectors.toList());
    }

    @Override
    /**
     * 根据贸易订单ID列表，聚合统计已完成的运单数据（趟次和净重）
     *
     * @param tOrderIds 贸易订单ID列表
     * @return 贸易订单运单聚合统计DTO列表
     */
    public List<TradeOrderWaybillAggDto> aggregateCompletedWaybillStatsByTradeOrderIds(List<Long> tOrderIds) {
        log.info("开始聚合统计已完成运单数据，贸易订单ID数量: {}", tOrderIds == null ? 0 : tOrderIds.size());
        
        // 1. 参数校验与预处理
        if (CollectionUtils.isEmpty(tOrderIds)) {
            log.debug("贸易订单ID列表为空，返回空列表");
            return Collections.emptyList();
        }
        // 过滤空值并去重，保持原始顺序
        List<Long> orderedIds = tOrderIds.stream().filter(Objects::nonNull).distinct().toList();
        log.debug("处理后的贸易订单ID列表: {}", orderedIds);

        // 2. 初始化结果容器，确保每个输入的贸易订单ID都有对应的返回对象，即使没有关联的运单
        Map<Long, TradeOrderWaybillAggDto> acc = new LinkedHashMap<>(orderedIds.size());
        for (Long id : orderedIds) {
            TradeOrderWaybillAggDto dto = new TradeOrderWaybillAggDto();
            dto.setTOrderId(id);
            dto.setTripCount(0);
            dto.setNetWeightSum(BigDecimal.ZERO);
            acc.put(id, dto);
        }

        // 3. 查询关联的物流订单 (KwtLogisticsOrder)
        List<KwtLogisticsOrder> logisticsOrders = logisticsOrderRepository.list(
                Wrappers.<KwtLogisticsOrder>lambdaQuery()
                        .in(KwtLogisticsOrder::getTOrderId, orderedIds)
                        .eq(KwtLogisticsOrder::getDelFlag, Global.NO));
        
        if (CollectionUtils.isEmpty(logisticsOrders)) {
            log.info("未找到关联的物流订单，贸易订单IDs: {}", orderedIds);
            return new ArrayList<>(acc.values());
        }
        log.debug("找到关联的物流订单数量: {}", logisticsOrders.size());

        // 4. 构建物流订单ID到贸易订单ID的映射关系
        Map<Long, Long> lOrderIdToTOrderId = logisticsOrders.stream()
                .filter(lo -> lo.getTOrderId() != null && lo.getId() != null)
                .collect(Collectors.toMap(KwtLogisticsOrder::getId, KwtLogisticsOrder::getTOrderId, (a, b) -> a));
        Set<Long> lOrderIds = lOrderIdToTOrderId.keySet();

        // 5. 查询状态为“已完成”的运单 (KwtWaybillOrder)
        List<KwtWaybillOrder> waybills = waybillOrderRepository.list(
                Wrappers.<KwtWaybillOrder>lambdaQuery()
                        .in(KwtWaybillOrder::getLOrderId, lOrderIds)
                        .eq(KwtWaybillOrder::getStatus, CarWaybillV1Enum.COMPLETED.getCode())
                        .eq(KwtWaybillOrder::getDelFlag, Global.NO));
        
        if (CollectionUtils.isEmpty(waybills)) {
            log.info("未找到状态为已完成的运单，物流订单IDs: {}", lOrderIds);
            return new ArrayList<>(acc.values());
        }
        log.debug("找到已完成的运单数量: {}", waybills.size());

        // 6. 查询运单子任务 (KwtWaybillOrderSubtask) 用于计算净重
        Set<Long> wOrderIds = waybills.stream().map(KwtWaybillOrder::getId).filter(Objects::nonNull).collect(Collectors.toSet());
        List<KwtWaybillOrderSubtask> subtasks = waybillOrderSubtaskRepository.list(
                Wrappers.<KwtWaybillOrderSubtask>lambdaQuery()
                        .in(KwtWaybillOrderSubtask::getWOrderId, wOrderIds)
                        .eq(KwtWaybillOrderSubtask::getDelFlag, Global.NO));
        
        // 7. 按运单ID分组子任务，并计算每个运单的总净重
        Map<Long, BigDecimal> netByWaybill = new HashMap<>(wOrderIds.size());
        Map<Long, List<KwtWaybillOrderSubtask>> subByWaybill = subtasks.stream()
                .collect(Collectors.groupingBy(KwtWaybillOrderSubtask::getWOrderId));
        
        netByWaybill = wOrderIds.stream()
                .collect(Collectors.toMap(
                        Function.identity(),
                        wid -> subByWaybill.getOrDefault(wid, Collections.emptyList()).stream()
                                .map(TransportServiceImpl::waybillSubtaskNetWeightTon)
                                .reduce(BigDecimal.ZERO, BigDecimal::add)
                ));
        log.debug("完成运单净重计算，运单数量: {}", netByWaybill.size());

        // 8. 聚合统计数据：遍历运单，累加趟次和净重到对应的贸易订单
        for (KwtWaybillOrder wo : waybills) {
            Long tOrderId = lOrderIdToTOrderId.get(wo.getLOrderId());
            if (tOrderId == null || !acc.containsKey(tOrderId)) {
                // 理论上不应发生，因为运单是通过物流订单关联查出的
                log.warn("运单 {} 无法关联到有效的贸易订单，物流订单ID: {}", wo.getId(), wo.getLOrderId());
                continue;
            }
            TradeOrderWaybillAggDto dto = acc.get(tOrderId);
            // 增加趟次计数
            dto.setTripCount(dto.getTripCount() + 1);
            // 累加净重
            BigDecimal currentNetWeight = netByWaybill.getOrDefault(wo.getId(), BigDecimal.ZERO);
            dto.setNetWeightSum(dto.getNetWeightSum().add(currentNetWeight));
        }

        List<TradeOrderWaybillAggDto> result = new ArrayList<>(acc.values());
        log.info("完成聚合统计，返回结果数量: {}", result.size());
        return result;
    }

    /**
     * 查询原矿物流订单执行展示列表
     * <p>
     * 根据上报企业ID集合，查询关联的物流订单及其已完成的运单执行情况（趟次、净重等）。
     * 主要用于监控原矿运输任务的实时执行进度。
     * </p>
     *
     * @param entIds 上报企业ID集合
     * @param limit  查询数量限制
     * @return 原矿订单执行展示DTO列表
     */
    @Override
    public List<RawOreOrderExecutionDto> listRawOreOrderExecutionDisplay(List<Long> entIds, int limit) {
        log.info("开始查询原矿物流订单执行展示数据, entIds={}, limit={}", entIds, limit);

        // 1. 参数校验
        if (CollectionUtils.isEmpty(entIds) || limit <= 0) {
            log.warn("查询原矿订单执行展示参数无效, entIds为空或limit<=0");
            return Collections.emptyList();
        }

        // 2. 根据上报企业ID查询关联的物流订单单元信息
        List<KwtLogisticsOrderUnit> units = logisticsOrderUnitRepository.queryByReportEntIds(entIds);
        if (CollectionUtils.isEmpty(units)) {
            log.debug("未找到上报企业关联的物流订单单元, entIds={}", entIds);
            return Collections.emptyList();
        }

        // 3. 提取并去重物流订单ID
        List<Long> logisticsOrderIds = units.stream()
                .filter(Objects::nonNull)
                .map(KwtLogisticsOrderUnit::getLOrderId)
                .filter(Objects::nonNull)
                .distinct()
                .toList();

        if (CollectionUtils.isEmpty(logisticsOrderIds)) {
            log.debug("从物流订单单元中未提取到有效的物流订单ID");
            return Collections.emptyList();
        }
        log.debug("提取到待查询的物流订单ID数量: {}", logisticsOrderIds.size());

        // 4. 查询物流订单主表信息
        // 筛选条件：未删除、订单类型为原矿(1)、排除已结算/退回/拒绝/取消的状态、按更新时间倒序、限制条数
        List<KwtLogisticsOrder> logisticsOrders = logisticsOrderRepository.list(
                Wrappers.<KwtLogisticsOrder>lambdaQuery()
                        .select(KwtLogisticsOrder::getId, KwtLogisticsOrder::getLOrderNo,
                                KwtLogisticsOrder::getAmount, KwtLogisticsOrder::getUpdateTime)
                        .eq(KwtLogisticsOrder::getDelFlag, Global.NO)
                        .eq(KwtLogisticsOrder::getOrderType, 1) // 1代表原矿订单
                        .in(KwtLogisticsOrder::getId, logisticsOrderIds)
                        .notIn(KwtLogisticsOrder::getStatus, Arrays.asList(
                                LogisticsOrderEnum.HAVE_ALREADY_SETTLED.getCode(), // 已结算
                                LogisticsOrderEnum.SEND_BACK.getCode(),            // 退回
                                LogisticsOrderEnum.REJECT_ORDER.getCode(),         // 拒绝
                                LogisticsOrderEnum.CANCEL_ORDER.getCode()))        // 取消
                        .orderByDesc(KwtLogisticsOrder::getUpdateTime)
                        .last("LIMIT " + limit));

        if (CollectionUtils.isEmpty(logisticsOrders)) {
            log.info("未查询到符合条件的原矿物流订单, logisticsOrderIds={}", logisticsOrderIds);
            return Collections.emptyList();
        }
        log.info("查询到符合条件的原矿物流订单数量: {}", logisticsOrders.size());

        // 5. 提取物流订单ID，用于查询关联的已完成运单
        List<Long> rawOreLogisticsOrderIds = logisticsOrders.stream()
                .map(KwtLogisticsOrder::getId)
                .filter(Objects::nonNull)
                .toList();

        // 6. 查询这些物流订单下状态为“已完成”的运单
        List<KwtWaybillOrder> waybills = waybillOrderRepository.queryCompletedWaybillOrdersByLogisticsOrderIds(
                CarWaybillV1Enum.COMPLETED.getCode(), rawOreLogisticsOrderIds);
        
        // 7. 将运单按物流订单ID分组，方便后续统计每个订单下的运单列表
        Map<Long, List<KwtWaybillOrder>> waybillsByLogisticsOrder = waybills.stream()
                .filter(wo -> wo.getLOrderId() != null && wo.getId() != null)
                .collect(Collectors.groupingBy(KwtWaybillOrder::getLOrderId));
        log.debug("查询到已完成运单数量: {}, 涉及物流订单数: {}", waybills.size(), waybillsByLogisticsOrder.size());

        // 8. 提取所有相关运单ID，批量查询子任务以计算净重
        Set<Long> waybillIds = waybills.stream()
                .map(KwtWaybillOrder::getId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());
        
        // 构建运单ID到净重总和的映射关系
        Map<Long, BigDecimal> netByWaybill = buildNetWeightByWaybill(waybillIds);

        // 9. 组装返回结果DTO
        List<RawOreOrderExecutionDto> result = logisticsOrders.stream()
                .map(order -> buildRawOreOrderExecutionDto(order, waybillsByLogisticsOrder, netByWaybill))
                .toList();
        
        log.info("原矿物流订单执行展示数据组装完成, 返回数量: {}", result.size());
        return result;
    }

    /**
     * 构建运单ID到净重总和的映射关系
     * <p>
     * 根据运单ID集合，查询对应的运单子任务，计算每个运单的总净重。
     * 净重计算逻辑优先取卸货量，若无卸货量则取装货量。
     * </p>
     *
     * @param waybillIds 运单ID集合
     * @return Map<运单ID, 净重总和(吨)>
     */
    private Map<Long, BigDecimal> buildNetWeightByWaybill(Set<Long> waybillIds) {
        // 1. 参数校验：如果运单ID集合为空，直接返回空Map，避免不必要的数据库查询
        if (CollectionUtils.isEmpty(waybillIds)) {
            log.debug("构建运单净重映射：运单ID集合为空");
            return Collections.emptyMap();
        }
        
        log.debug("开始构建运单净重映射，运单数量: {}", waybillIds.size());

        // 2. 批量查询运单子任务
        // 查询条件：运单ID在指定集合中，且未删除
        List<KwtWaybillOrderSubtask> subtasks = waybillOrderSubtaskRepository.list(
                Wrappers.<KwtWaybillOrderSubtask>lambdaQuery()
                        .in(KwtWaybillOrderSubtask::getWOrderId, waybillIds)
                        .eq(KwtWaybillOrderSubtask::getDelFlag, Global.NO));
        
        if (CollectionUtils.isEmpty(subtasks)) {
            log.debug("未查询到任何运单子任务，运单IDs: {}", waybillIds);
        } else {
            log.debug("查询到运单子任务数量: {}", subtasks.size());
        }

        // 3. 将子任务按运单ID分组
        // 过滤掉运单ID为空的异常数据，防止分组Key为null导致错误
        Map<Long, List<KwtWaybillOrderSubtask>> subByWaybill = subtasks.stream()
                .filter(st -> st.getWOrderId() != null)
                .collect(Collectors.groupingBy(KwtWaybillOrderSubtask::getWOrderId));

        // 4. 计算每个运单的总净重并构建结果Map
        // 遍历原始运单ID集合，确保所有输入的ID都在结果Map中有对应项（即使净重为0）
        Map<Long, BigDecimal> result = waybillIds.stream()
                .collect(Collectors.toMap(
                        Function.identity(), // Key: 运单ID
                        wid -> {
                            // 获取该运单下的所有子任务列表，若不存在则为空列表
                            List<KwtWaybillOrderSubtask> waybillSubtasks = subByWaybill.getOrDefault(wid, Collections.emptyList());
                            
                            // 累加子任务的净重
                            BigDecimal totalNetWeight = waybillSubtasks.stream()
                                    .map(TransportServiceImpl::waybillSubtaskNetWeightTon) // 计算单个子任务净重
                                    .reduce(BigDecimal.ZERO, BigDecimal::add); // 求和
                            
                            return totalNetWeight;
                        }
                ));
        
        log.debug("运单净重映射构建完成，结果大小: {}", result.size());
        return result;
    }

    /**
     * 构建原矿订单执行展示DTO对象
     * <p>
     * 根据物流订单主表信息、关联的已完成运单列表以及运单净重映射，
     * 组装原矿订单的执行进度数据，包括计划量、实际趟次、累计净重等。
     * </p>
     *
     * @param order                 物流订单主表对象
     * @param waybillsByLogisticsOrder 物流订单ID到已完成运单列表的映射
     * @param netByWaybill          运单ID到净重总和的映射
     * @return 原矿订单执行展示DTO
     */
    private RawOreOrderExecutionDto buildRawOreOrderExecutionDto(KwtLogisticsOrder order,
                                                                 Map<Long, List<KwtWaybillOrder>> waybillsByLogisticsOrder,
                                                                 Map<Long, BigDecimal> netByWaybill) {
        // 1. 获取当前物流订单关联的所有已完成运单
        Long logisticsOrderId = order.getId();
        List<KwtWaybillOrder> orderWaybills = waybillsByLogisticsOrder.getOrDefault(logisticsOrderId, Collections.emptyList());
        
        // 2. 计算该物流订单下所有已完成运单的累计净重
        // 遍历运单ID，从预计算的净重映射中获取每个运单的净重并求和
        BigDecimal netWeightSum = orderWaybills.stream()
                .map(KwtWaybillOrder::getId)
                .map(waybillId -> {
                    BigDecimal weight = netByWaybill.getOrDefault(waybillId, BigDecimal.ZERO);
                    log.debug("运单ID: {}, 净重: {}", waybillId, weight);
                    return weight;
                })
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        log.debug("物流订单ID: {}, 关联运单数: {}, 累计净重: {}", logisticsOrderId, orderWaybills.size(), netWeightSum);

        // 3. 组装返回DTO
        RawOreOrderExecutionDto dto = new RawOreOrderExecutionDto();
        dto.setLogisticsOrderId(logisticsOrderId);
        dto.setLogisticsOrderNo(order.getLOrderNo());
        // 计划运输量
        dto.setPlannedAmount(order.getAmount());
        // 实际完成趟次（即已完成运单的数量）
        dto.setTripCount(orderWaybills.size());
        // 累计完成净重
        dto.setNetWeightSum(netWeightSum);
        // 订单最后更新时间
        dto.setUpdateTime(order.getUpdateTime());
        
        return dto;
    }

    private static BigDecimal waybillSubtaskNetWeightTon(KwtWaybillOrderSubtask st) {
        if (st == null) {
            return BigDecimal.ZERO;
        }
        if (st.getUnloadAmount() != null && st.getUnloadAmount().compareTo(BigDecimal.ZERO) > 0) {
            return st.getUnloadAmount();
        }
        if (st.getLoadAmount() != null && st.getLoadAmount().compareTo(BigDecimal.ZERO) > 0) {
            return st.getLoadAmount();
        }
        return BigDecimal.ZERO;
    }

}
