package com.sckw.transport.service;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.sckw.core.common.enums.enums.DictEnum;
import com.sckw.core.common.enums.enums.DictTypeEnum;
import com.sckw.core.common.enums.enums.ErrorCodeEnum;
import com.sckw.core.exception.BusinessException;
import com.sckw.core.exception.BusinessPlatfromException;
import com.sckw.core.model.constant.Global;
import com.sckw.core.model.constant.NumberConstant;
import com.sckw.core.model.constant.UrlConstants;
import com.sckw.core.model.enums.*;
import com.sckw.core.model.page.PageHelperUtil;
import com.sckw.core.model.page.PageResult;
import com.sckw.core.model.vo.TableTop;
import com.sckw.core.utils.*;
import com.sckw.core.web.constant.CommonConstants;
import com.sckw.core.web.constant.HttpStatus;
import com.sckw.core.web.context.LoginUserHolder;
import com.sckw.core.web.response.HttpResult;
import com.sckw.core.web.response.result.PageDataResult;
import com.sckw.excel.utils.DateUtil;
import com.sckw.fleet.api.RemoteFleetService;
import com.sckw.fleet.api.model.vo.*;
import com.sckw.mongo.model.SckwWaybillOrder;
import com.sckw.order.api.dubbo.TradeOrderInfoService;
import com.sckw.order.api.model.TradeOrderSettlePara;
import com.sckw.product.api.dubbo.GoodsInfoService;
import com.sckw.product.api.model.KwpGoods;
import com.sckw.stream.enums.MessageEnum;
import com.sckw.stream.model.SckwMessage;
import com.sckw.stream.model.UserInfo;
import com.sckw.system.api.RemoteSystemService;
import com.sckw.system.api.RemoteUserService;
import com.sckw.system.api.model.dto.res.*;
import com.sckw.transport.common.config.UrlConfigProperties;
import com.sckw.transport.dao.*;
import com.sckw.transport.model.*;
import com.sckw.transport.model.dto.*;
import com.sckw.transport.model.enuma.ApproveStatusEnum;
import com.sckw.transport.model.enuma.CarWaybillDetailEnum;
import com.sckw.transport.model.enuma.CarWaybillNdexTopEnum;
import com.sckw.transport.model.enuma.CarWaybillTableTopEnum;
import com.sckw.transport.model.param.WaybillOrderNodeReq;
import com.sckw.transport.model.param.WaybillOrderReq;
import com.sckw.transport.model.param.WaybillOrderResp;
import com.sckw.transport.model.vo.*;
import com.sckw.transport.repository.*;
import com.sckw.transport.utils.DistanceUtils;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.stream.function.StreamBridge;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author zk
 * @desc 车辆运单
 * @date 2023/7/19 0019
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class KwtWaybillOrderV1Service {
    @Autowired
    KwtWaybillOrderV1Mapper waybillOrderV1Dao;
    @Autowired
    KwtLogisticsOrderMapper logisticsOrderDao;
    @Autowired
    KwtLogisticsOrderTrackMapper logisticsOrderTrackDao;
    @Autowired
    KwtLogisticsOrderAddressMapper logisticsOrderAddressDao;
    @Autowired
    KwtWaybillOrderAddressMapper waybillOrderAddressDao;
    @Autowired
    KwtWaybillOrderTrackMapper waybillOrderTrackDao;
    @Autowired
    KwtWaybillOrderTicketMapper waybillOrderTicketDao;
    @Autowired
    KwtWaybillOrderSubtaskMapper waybillOrderSubtaskDao;
    @Autowired
    KwtLogisticsOrderAmountMapper logisticsOrderAmountDao;
    @Autowired
    KwtLogisticsOrderGoodsMapper logisticsOrderGoodsDao;
    @Autowired
    KwtLogisticsOrderUnitMapper logisticsOrderUnitDao;
    @Autowired
    KwtWaybillOrderTicketService waybillOrderTicketService;
    @Autowired
    KwtLogisticsOrderGoodsService kwtLogisticsOrderGoodsService;
    @Autowired
    KwtWaybillOrderSubtaskService waybillOrderSubtaskService;
    @Autowired
    KwtCommonService commonService;
    @Resource
    private UrlConfigProperties urlConfigProperties;
    private final KwtWaybillOrderAddressRepository waybillOrderAddressRepository;
    private final KwtWaybillOrderTrackRepository kwtWaybillOrderTrackRepository;
    private final KwtWaybillOrderSubtaskRepository waybillOrderSubtaskRepository;
    private final KwtLogisticsOrderRepository logisticsOrderRepository;
    private final KwtWaybillOrderRepository kwtWaybillOrderRepository;
    private final KwtLogisticsOrderUnitRepository kwtLogisticsOrderUnitRepository;
    private final KwtLogisticsOrderGoodsRepository kwtLogisticsOrderGoodsRepository;
    private final KwtWaybillOrderSubtaskRepository kwtWaybillOrderSubtaskRepository;
    private final KwtLogisticsOrderRepository kwtLogisticsOrderRepository;
    private final KwtWaybillOrderTicketRepository  kwtWaybillOrderTicketRepository;
    private final KwtWaybillOrderNodeRepository kwtWaybillOrderNodeRepository;
    @Resource
    private StreamBridge streamBridge;
    @DubboReference(version = "1.0.0", group = "design", check = false)
    private RemoteSystemService remoteSystemService;
    @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 6000)
    private RemoteUserService remoteUserService;
    @DubboReference(version = "1.0.0", group = "design", check = false)
    private RemoteFleetService remoteFleetService;
    @DubboReference(version = "1.0.0", group = "design", check = false)
    private TradeOrderInfoService tradeOrderInfoService;
    @Value("${message.waybill.refuseSendCar.app}")
    private String refuseSendCarAppUrl;
    @Value("${message.waybill.refuseSendCar.pc}")
    private String refuseSendCarPcUrl;

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


    /**
     * @param params 请求参数
     * @desc 统计
     * @author zk
     * @date 2024/3/8
     **/
    public List<TableTop> statistics(WaybillOrderQueryDto params) {
        //统计信息
        List<TableTop> tableTops = waybillOrderV1Dao.statistics(params);

        //数据处理
        List<TableTop> topList = new ArrayList<>();
        TableTop top1 = new TableTop();
        top1.setName("全部");
        top1.setTotal(tableTops.stream().mapToInt(TableTop::getTotal).sum());
        topList.add(top1);

        for (CarWaybillTableTopEnum entity : CarWaybillTableTopEnum.values()) {
            TableTop top = new TableTop();
            top.setName(entity.getName());
            top.setValue(entity.getCode());
            top.setTotal(Global.NUMERICAL_ZERO);
            if (entity.getValue() == null) {
                //全部数据
                int totalCount = tableTops.stream().mapToInt(TableTop::getTotal).sum();
                top.setTotal(totalCount);
            } else {
                tableTops.stream().filter(table -> entity.getValue().contains(String.valueOf(table.getValue()))).findAny().ifPresent(tableTop -> top.setTotal(tableTop.getTotal()));
            }
            topList.add(top);
        }
        return topList;
    }

    /**
     * @param params {page：页数、pageSize：每页条数、。。。}
     * @desc 分页查询
     * @author zk
     * @date 2024/3/8
     **/
    public List<WaybillOrderSelectVo> findListPage(WaybillOrderQueryDto params) {
        params.setQueryWstatus(CarWaybillTableTopEnum.getValue(params.getStatus()));
        List<WaybillOrderSelectVo> list = waybillOrderV1Dao.findListPage(params);
        if (CollectionUtils.isEmpty(list)) {
            return list;
        }

        //单位
        Map<String, Map<String, String>> dict = remoteSystemService.queryDictByType(List.of(DictTypeEnum.UNIT_TYPE.getType()));
        Map<String, String> unitMap = CollectionUtils.isNotEmpty(dict) ? dict.get(DictTypeEnum.UNIT_TYPE.getType()) : new HashMap<>(NumberConstant.SIXTEEN);

        //数据处理
        for (WaybillOrderSelectVo waybillOrder : list) {
            findListPageHandle(waybillOrder, unitMap);
            waybillOrder.setStatusLabel(CarWaybillEnum.getName(waybillOrder.getStatus()));
        }
        return list;
    }

    /**
     * @param params {page：页数、pageSize：每页条数、。。。}
     * @desc 分页查询
     * @author zk
     * @date 2024/3/8
     **/
    public PageResult findNdexPage(WaybillOrderQueryDto params) {
        params.setQueryWstatus(CarWaybillTableTopEnum.getValue(params.getStatus()));
        // 设置分页参数
        PageHelper.startPage(params.getPage(), params.getPageSize());
        List<WaybillOrderSelectVo> list = waybillOrderV1Dao.findListPage(params);
        PageResult pageResult = PageHelperUtil.getPageResult(new PageInfo<>(list));

        //用户ID
        List<Long> userIds = list.stream().map(WaybillOrderSelectVo::getCreateBy).toList();
        List<UserCacheResDto> users = remoteSystemService.queryUserCacheByIds(userIds);
        Map<Long, UserCacheResDto> usersMap = new HashMap<>(Global.NUMERICAL_SIXTEEN);
        users.forEach(e -> usersMap.put(e.getId(), e));
        //企业ID
        List<Long> entIds = list.stream().map(WaybillOrderSelectVo::getEntId).toList();
        Map<Long, EntCacheResDto> ents = remoteSystemService.queryEntCacheMapByIds(entIds);

        //数据处理
        List<WaybillOrderNdexVo> data = BeanUtil.copyToList(list, WaybillOrderNdexVo.class);
        for (WaybillOrderNdexVo waybillOrder : data) {
            waybillOrder.setStatusLabel(CarWaybillEnum.getName(waybillOrder.getStatus()));
            waybillOrder.setCreateByName(usersMap.get(waybillOrder.getCreateBy()) != null ? usersMap.get(waybillOrder.getCreateBy()).getName() : null);
            waybillOrder.setFirmName(ents.get(waybillOrder.getEntId()) != null ? ents.get(waybillOrder.getEntId()).getFirmName() : null);
            //数据处理
            findNdexPageHandle(waybillOrder);
        }
        pageResult.setList(data);
        return pageResult;
    }

    /**
     * @param params {page：页数、pageSize：每页条数、。。。}
     * @desc 分页查询-运营端
     * @author zk
     * @date 2024/3/8
     **/
    public List<WaybillOrderSelectVo> findListPageManagement(WaybillOrderQueryDto params) {
        //客户经理权限过滤
        List<Long> authEntIdList = LoginUserHolder.getAuthEntIdList();
        if (CollectionUtils.isEmpty(authEntIdList)) {
            List<Long> ids = remoteUserService.findEnterpriseIdsByUserIdIsMain(LoginUserHolder.getUserId());
            if (CollectionUtils.isEmpty(ids)) {
                return new ArrayList<>();
            }
            authEntIdList.addAll(ids);
        }
        params.setEntIds(authEntIdList);
        params.setQueryWstatus(CarWaybillTableTopEnum.getValue(params.getStatus()));
        List<WaybillOrderSelectVo> list = waybillOrderV1Dao.findListPage(params);
        if (CollectionUtils.isEmpty(list)) {
            return list;
        }

        //单位
        Map<String, Map<String, String>> dict = remoteSystemService.queryDictByType(List.of(DictTypeEnum.UNIT_TYPE.getType()));
        Map<String, String> unitMap = CollectionUtils.isNotEmpty(dict) ? dict.get(DictTypeEnum.UNIT_TYPE.getType()) : new HashMap<>(NumberConstant.SIXTEEN);

        //数据处理
        for (WaybillOrderSelectVo waybillOrder : list) {
            findListPageHandle(waybillOrder, unitMap);
            waybillOrder.setStatusLabel(CarWaybillEnum.getName(waybillOrder.getStatus()));
        }
        return list;
    }

    /**
     * @param wOrderId 运单ID
     * @desc 运单详情
     * @author zk
     * @date 2024/3/13
     **/
    public HttpResult waybillDetail(Long wOrderId) {
        //运单信息
        KwtWaybillOrderV1 waybillOrder = waybillOrderV1Dao.selectById(wOrderId);
        if (waybillOrder == null) {
            return HttpResult.error("运单" + wOrderId + "不存在，请确认！");
        }

        //子单
        List<KwtWaybillOrderSubtask> subtasks = waybillOrderSubtaskDao.findByWOrderId(wOrderId);
        //运单状态记录
        List<KwtWaybillOrderTrack> tracks = waybillOrderTrackDao.findTrack(wOrderId, null, null, null);
        //用户信息
        List<Long> userIds = tracks.stream().map(KwtWaybillOrderTrack::getCreateBy).toList();
        List<Long> userIdList = new ArrayList<>(NumberConstant.SIXTEEN) {{
            add(waybillOrder.getCreateBy());
        }};
        userIdList.addAll(userIds);
        List<UserCacheResDto> users = remoteSystemService.queryUserCacheByIds(userIdList);
        Map<Long, UserCacheResDto> usersMap = new HashMap<>(Global.NUMERICAL_SIXTEEN);
        users.forEach(e -> usersMap.put(e.getId(), e));
        //企业ID
        List<Long> entIds = new ArrayList<>() {{
            add(waybillOrder.getEntId());
        }};
        Map<Long, EntCacheResDto> ents = remoteSystemService.queryEntCacheMapByIds(entIds);
        //单位
        Map<String, Map<String, String>> dict = remoteSystemService.queryDictByType(List.of(DictTypeEnum.UNIT_TYPE.getType()));
        Map<String, String> unitMap = CollectionUtils.isNotEmpty(dict) ? dict.get(DictTypeEnum.UNIT_TYPE.getType()) : new HashMap<>(NumberConstant.SIXTEEN);
        //车辆信息
        RTruckVo truck = remoteFleetService.findTruck(waybillOrder.getTruckId());

        //返回信息
        WaybillDetailVo waybillDetail = new WaybillDetailVo();
        //地址信息
        List<KwtWaybillOrderAddress> addresses = waybillOrderAddressDao.findByAddresses(wOrderId, null);
        //地址数据处理
        List<Map<String, Object>> addressList = new ArrayList<>(NumberConstant.SIXTEEN);
        for (KwtWaybillOrderAddress address : addresses) {
            //运单子单
            KwtWaybillOrderSubtask subtask = waybillOrderSubtaskDao.selectById(address.getWSubtaskId());
            //物流订单商品信息
            KwtLogisticsOrderGoods goods = logisticsOrderGoodsDao.findByGoods(subtask != null ? subtask.getLOrderId() : null);
            //榜单信息
            KwtWaybillOrderTicket ticket = waybillOrderTicketDao.findWaybillOrderTicketV2(address.getId(), subtask.getUnit());
            Map<String, Object> addressData = new HashMap<>(NumberConstant.SIXTEEN);
            addressData.put("addressType", address.getAddressType());
            addressData.put("addressName", address.getName());
            addressData.put("addressCityName", address.getCityName());
            addressData.put("addressDetail", address.getDetailAddress());
            addressData.put("planTime", DateUtils.format(address.getPlanTime(), DateUtils.FORMAT12));
            addressData.put("entrustAmount", address.getEntrustAmount());
            addressData.put("goodsName", goods != null ? goods.getGoodsName() : null);
            addressData.put("unit", subtask.getUnit());
            addressData.put("unitName", unitMap.get(subtask.getUnit()));
            addressData.put("amount", ticket != null ? ticket.getAmount() : null);
            addressData.put("urls", ticket != null ? FileUtils.spliceBatch(ticket.getUrls()) : null);
            addressData.put("operateStatus", ticket != null);
            addressData.put("operateTime", ticket != null ? DateUtils.format(address.getPlanTime(), DateUtils.FORMAT11) : null);
            addressData.put("status", ticket != null ? ticket.getStatus() : null);
            addressData.put("statusName", ticket != null ? ApproveStatusEnum.getName(ticket.getStatus()) : null);
            addressList.add(addressData);
        }

        //状态数据处理
        List<Map<String, Object>> trackList = new ArrayList<>(NumberConstant.SIXTEEN);
        for (KwtWaybillOrderTrack track : tracks) {
            Map<String, Object> trackData = new HashMap<>(NumberConstant.SIXTEEN);
            trackData.put("status", track.getStatus());
            trackData.put("statusName", CarWaybillEnum.getAlias(track.getStatus()));
            trackData.put("remark", track.getRemark());
            trackData.put("operateTime", DateUtils.format(track.getOperateTime(), DateUtils.DATE_TIME_PATTERN));
            trackData.put("createTime", DateUtils.format(track.getCreateTime(), DateUtils.DATE_TIME_PATTERN));
            trackData.put("createByName", usersMap.get(waybillOrder.getCreateBy()) != null ? usersMap.get(waybillOrder.getCreateBy()).getName() : null);
            trackData.put("createByPhone", usersMap.get(waybillOrder.getCreateBy()) != null ? usersMap.get(waybillOrder.getCreateBy()).getPhone() : null);
            trackList.add(trackData);
        }

        //物流订单编号
        for (KwtWaybillOrderSubtask subtask : subtasks) {
            KwtLogisticsOrder logisticsOrder = logisticsOrderDao.selectById(subtask.getLOrderId());
            waybillDetail.setLOrderNo((StringUtils.isBlank(waybillDetail.getLOrderNo()) ? Global.EMPTY_STRING : Global.COMMA) + logisticsOrder.getLOrderNo());
        }

        //状态轨迹
        List<Map<String, Object>> trajectory = waybillDetailHandle(wOrderId);

        BeanUtils.copyProperties(waybillOrder, waybillDetail);
        waybillDetail.setWOrderId(waybillOrder.getId());
        waybillDetail.setStatusName(CarWaybillEnum.getName(waybillOrder.getStatus()));
        waybillDetail.setCreateByName(usersMap.get(waybillOrder.getCreateBy()) != null ? usersMap.get(waybillOrder.getCreateBy()).getName() : null);
        waybillDetail.setCreateByPhone(usersMap.get(waybillOrder.getCreateBy()) != null ? usersMap.get(waybillOrder.getCreateBy()).getPhone() : null);
        waybillDetail.setTrailerNo(truck != null ? truck.getTrailerNo() : null);
        waybillDetail.setTruckType(truck != null ? truck.getTruckType() : null);
        waybillDetail.setFirmName(ents.get(waybillOrder.getEntId()) != null ? ents.get(waybillOrder.getEntId()).getFirmName() : null);
        waybillDetail.setTracks(trackList);
        waybillDetail.setAddresses(addressList);
        waybillDetail.setTrajectory(trajectory);
        waybillDetail.setTypeName(waybillDetail.getType() == NumberConstant.ONE ? "趟次运单" : "循环运单");
        return HttpResult.ok(waybillDetail);
    }

    /**
     * @param params {page：页数、pageSize：每页条数、。。。}
     * @desc 分页查询
     * @author zk
     * @date 2024/3/8
     **/
    public PageResult subtaskSelect(WaybillSubtaskOrderQueryDto params) {
        // 设置分页参数
        PageHelper.startPage(params.getPage(), params.getPageSize());
        List<WaybillSubtaskSelectVo> list = waybillOrderSubtaskDao.findListPage(params);

        //单位
        Map<String, Map<String, String>> dict = remoteSystemService.queryDictByType(List.of(DictTypeEnum.UNIT_TYPE.getType()));
        Map<String, String> unitMap = CollectionUtils.isNotEmpty(dict) ? dict.get(DictTypeEnum.UNIT_TYPE.getType()) : new HashMap<>(NumberConstant.SIXTEEN);
        //企业ID
        List<Long> entIds = list.stream().map(WaybillSubtaskSelectVo::getEntId).toList();
        Map<Long, EntCacheResDto> ents = remoteSystemService.queryEntCacheMapByIds(entIds);
        //用户ID
        List<Long> userIds = list.stream().map(WaybillSubtaskSelectVo::getCreateBy).toList();
        List<UserCacheResDto> users = remoteSystemService.queryUserCacheByIds(userIds);
        Map<Long, UserCacheResDto> usersMap = new HashMap<>(Global.NUMERICAL_SIXTEEN);
        users.forEach(e -> usersMap.put(e.getId(), e));

        //数据处理
        for (WaybillSubtaskSelectVo waybillOrder : list) {
            waybillOrder.setStatusLabel(CarWaybillEnum.getName(waybillOrder.getStatus()));
            waybillOrder.setUnitLabel(unitMap.get(waybillOrder.getUnit()));
            waybillOrder.setFirmName(ents.get(waybillOrder.getEntId()) != null ? ents.get(waybillOrder.getEntId()).getFirmName() : null);
            waybillOrder.setCreateByName(usersMap.get(waybillOrder.getCreateBy()) != null ? usersMap.get(waybillOrder.getCreateBy()).getName() : null);
            waybillOrder.setCreateByPhone(usersMap.get(waybillOrder.getCreateBy()) != null ? usersMap.get(waybillOrder.getCreateBy()).getPhone() : null);
            waybillOrder.setSendCarWeigh(NumberUtils.parseBigDecimal(waybillOrder.getEntrustAmount()));
            waybillOrder.setDefectiveWeigh(NumberUtils.parseBigDecimal(waybillOrder.getDeficitAmount()));
            waybillOrder.setDeduct(deficitPrice(NumberUtils.parseBigDecimal(waybillOrder.getLoadAmount(), null),
                                                NumberUtils.parseBigDecimal(waybillOrder.getDeficitAmount(), null),
                                                waybillOrder.getLoss(),
                                                waybillOrder.getLossLabel(),
                                                waybillOrder.getGoodsPrice()));
        }
        return PageHelperUtil.getPageResult(new PageInfo<>(list));
    }

    /**
     * @param params {page：页数、pageSize：每页条数、。。。}
     * @desc 分页查询
     * @author zk
     * @date 2024/3/8
     **/
    public PageResult transportationCapacitySelect(WaybillSubtaskOrderQueryDto params) {
        // 设置分页参数
        PageHelper.startPage(params.getPage(), params.getPageSize());
        List<WaybillOrderSelectVo> list = waybillOrderV1Dao.findCapacityListPage(params);

        //删除空数据
        if (list.size() == 1 && list.get(NumberConstant.ZERO).getTruckId() == null) {
            list.remove(NumberConstant.ZERO);
        }

        //数据处理
        for (WaybillOrderSelectVo waybillOrder : list) {
            RTruckVo truck = remoteFleetService.findTruck(waybillOrder.getTruckId());
            if (truck != null) {
                Double actualWeight = Optional.ofNullable(truck.getActualWeight()).map(BigDecimal::doubleValue).orElse(0.0);
                waybillOrder.setActualWeight(actualWeight);
            }
        }
        return PageHelperUtil.getPageResult(new PageInfo<>(list));
    }

    /**
     * @param wSubtaskId 运单子单ID
     * @desc 运单详情(物流订单)
     * @author zk
     * @date 2024/3/18
     **/
    public HttpResult waybillSubtaskDetail(Long wSubtaskId) {
        //子单
        KwtWaybillOrderSubtask subtask = waybillOrderSubtaskDao.selectById(wSubtaskId);
        if (subtask == null) {
            return HttpResult.error("运单" + wSubtaskId + "不存在，请确认！");
        }

        //运单信息
        KwtWaybillOrderV1 waybillOrder = waybillOrderV1Dao.selectById(subtask.getWOrderId());
        //用户信息
        List<Long> userIdList = new ArrayList<>(NumberConstant.SIXTEEN) {{
            add(waybillOrder.getCreateBy());
        }};
        List<UserCacheResDto> users = remoteSystemService.queryUserCacheByIds(userIdList);
        Map<Long, UserCacheResDto> usersMap = new HashMap<>(Global.NUMERICAL_SIXTEEN);
        users.forEach(e -> usersMap.put(e.getId(), e));
        //企业ID
        List<Long> entIds = new ArrayList<>() {{
            add(waybillOrder.getEntId());
        }};
        Map<Long, EntCacheResDto> ents = remoteSystemService.queryEntCacheMapByIds(entIds);
        //单位
        Map<String, Map<String, String>> dict = remoteSystemService.queryDictByType(List.of(DictTypeEnum.UNIT_TYPE.getType()));
        Map<String, String> unitMap = CollectionUtils.isNotEmpty(dict) ? dict.get(DictTypeEnum.UNIT_TYPE.getType()) : new HashMap<>(NumberConstant.SIXTEEN);
        //合理损耗单位
        Map<String, Map<String, String>> dictLoss = remoteSystemService.queryDictByType(List.of(DictTypeEnum.TAX_RATE_TYPE.getType()));
        Map<String, String> lossMap = CollectionUtils.isNotEmpty(dictLoss) ? dictLoss.get(DictTypeEnum.TAX_RATE_TYPE.getType()) : new HashMap<>(NumberConstant.SIXTEEN);

        //物流订单
        KwtLogisticsOrder logisticsOrder = logisticsOrderDao.selectById(subtask.getLOrderId());
        //物流订单地址信息
        List<KwtLogisticsOrderAddress> lAddressList = logisticsOrderAddressDao.findByAddresses(subtask.getLOrderId(), null);
        List<Long> addressIds = lAddressList.stream().map(KwtLogisticsOrderAddress::getId).toList();
        //地址信息
        List<KwtWaybillOrderAddress> addresses = waybillOrderAddressDao.findByLAddressIds(subtask.getWOrderId(), addressIds);
        //榜单信息
        List<WaybillTicketVO> tickets = waybillOrderTicketService.agreement(subtask);

        //地址数据处理
        List<Map<String, Object>> addressList = new ArrayList<>(NumberConstant.SIXTEEN);
        for (KwtWaybillOrderAddress address : addresses) {
            //物流订单商品信息
            KwtLogisticsOrderGoods goods = logisticsOrderGoodsDao.findByGoods(subtask != null ? subtask.getLOrderId() : null);
            //榜单信息
            KwtWaybillOrderTicket ticket = waybillOrderTicketDao.findWaybillOrderTicketV2(address.getId(), subtask.getUnit());
            Map<String, Object> addressData = new HashMap<>(NumberConstant.SIXTEEN);
            addressData.put("addressType", address.getAddressType());
            addressData.put("addressName", address.getName());
            addressData.put("addressCityName", address.getCityName());
            addressData.put("addressDetail", address.getDetailAddress());
            addressData.put("planTime", DateUtils.format(address.getPlanTime(), DateUtils.FORMAT12));
            addressData.put("entrustAmount", address.getEntrustAmount());
            addressData.put("goodsName", goods != null ? goods.getGoodsName() : null);
            addressData.put("unit", subtask.getUnit());
            addressData.put("unitName", unitMap.get(subtask.getUnit()));
            addressData.put("amount", ticket != null ? ticket.getAmount() : null);
            addressData.put("urls", ticket != null ? ticket.getUrls() : null);
            addressData.put("operateTime", ticket != null ? DateUtils.format(address.getPlanTime(), DateUtils.FORMAT11) : null);
            addressData.put("operateStatus", ticket != null);
            addressList.add(addressData);
        }

        //返回信息
        WaybillSubtaskDetailVo waybillDetail = new WaybillSubtaskDetailVo();
        BeanUtils.copyPropertiesValue(waybillOrder, waybillDetail);
        BeanUtils.copyPropertiesValue(subtask, waybillDetail);
        waybillDetail.setWOrderId(waybillOrder.getId());
        waybillDetail.setLOrderNo(logisticsOrder.getLOrderNo());
        waybillDetail.setLoss(logisticsOrder.getLoss());
        waybillDetail.setLossUnitLabe(lossMap.get(waybillDetail.getUnit()));
        waybillDetail.setWSubtaskId(subtask.getId());
        waybillDetail.setStatusLabel(CarWaybillEnum.getName(waybillOrder.getStatus()));
        waybillDetail.setUnitLabel(unitMap.get(waybillDetail.getUnit()));
        waybillDetail.setFirmName(ents.get(waybillOrder.getEntId()) != null ? ents.get(waybillOrder.getEntId()).getFirmName() : null);
        waybillDetail.setCreateByName(usersMap.get(waybillOrder.getCreateBy()) != null ? usersMap.get(waybillOrder.getCreateBy()).getName() : null);
        waybillDetail.setCreateByPhone(usersMap.get(waybillOrder.getCreateBy()) != null ? usersMap.get(waybillOrder.getCreateBy()).getPhone() : null);
        waybillDetail.setAddresses(addressList);
        waybillDetail.setTickets(tickets);
        return HttpResult.ok(waybillDetail);
    }

    /**
     * @param waybillOrder 运单信息
     * @param unitMap      字段
     * @desc 分页列表查询
     * @author zk
     * @date 2024/3/13
     **/
    public void findListPageHandle(WaybillOrderSelectVo waybillOrder, Map<String, String> unitMap) {
        //子运单
        List<KwtWaybillOrderSubtask> subtasks = waybillOrderSubtaskDao.findByWOrderId(waybillOrder.getWOrderId());
        //子运单
        List<KwtWaybillOrderAddress> loadAddresses = waybillOrderAddressDao.findByAddresses(waybillOrder.getWOrderId(), AddressTypeEnum.SHIPMENT.getCode());
        //子运单
        List<KwtWaybillOrderAddress> unloadAddresses = waybillOrderAddressDao.findByAddresses(waybillOrder.getWOrderId(), AddressTypeEnum.TAKE.getCode());
        //榜单信息
        List<KwtWaybillOrderTicket> tickets = waybillOrderTicketDao.findWaybillOrderTicket(waybillOrder.getWOrderId(), null, null);
        List<KwtWaybillOrderTicket> loadTickets = tickets.stream().filter(item -> item.getType().equals(NumberConstant.ONE)).toList();
        List<KwtWaybillOrderTicket> unloadTickets = tickets.stream().filter(item -> item.getType().equals(NumberConstant.TWO)).toList();
        //装货时间
        Optional<KwtWaybillOrderSubtask> startDate = subtasks.stream().min(Comparator.comparing(KwtWaybillOrderSubtask::getLoadTime));
        //卸货时间
        Optional<KwtWaybillOrderSubtask> endDate = subtasks.stream().max(Comparator.comparing(KwtWaybillOrderSubtask::getUnloadTime));
        //实际装货时间
        Optional<KwtWaybillOrderTicket> loadDate = loadTickets.stream().min(Comparator.comparing(KwtWaybillOrderTicket::getOperateTime));
        //实际卸货时间
        Optional<KwtWaybillOrderTicket> unloadDate = unloadTickets.stream().max(Comparator.comparing(KwtWaybillOrderTicket::getOperateTime));
        //装货地点名称
        List<String> loadName = loadAddresses.stream().map(KwtWaybillOrderAddress::getCityName).toList();
        //装货地点
        List<String> loadAddress = loadAddresses.stream().map(KwtWaybillOrderAddress::getDetailAddress).toList();
        //卸货地点点名称
        List<String> unloadName = unloadAddresses.stream().map(KwtWaybillOrderAddress::getCityName).toList();
        //卸货地点
        List<String> unloadAddress = unloadAddresses.stream().map(KwtWaybillOrderAddress::getDetailAddress).toList();

        //数据处理
        for (KwtWaybillOrderSubtask subtask : subtasks) {
            //物流订单
            KwtLogisticsOrder logisticsOrder = logisticsOrderDao.selectById(subtask.getLOrderId());
            //托运企业
            KwtLogisticsOrderUnit procure = logisticsOrderUnitDao.findByUnit(subtask.getLOrderId(), NumberConstant.ONE);
            //承运企业
            KwtLogisticsOrderUnit supply = logisticsOrderUnitDao.findByUnit(subtask.getLOrderId(), NumberConstant.TWO);
            //派单量
            String entrustAmount = subtask.getEntrustAmount() + unitMap.get(subtask.getUnit());
            //实装量
            String loadAmount = subtask.getLoadAmount() != null ? subtask.getLoadAmount() + unitMap.get(subtask.getUnit()) : Global.NUMERICAL_ZERO + unitMap.get(subtask.getUnit());
            //实卸量
            String unloadAmount = subtask.getUnloadAmount() != null ? subtask.getUnloadAmount() + unitMap.get(subtask.getUnit()) : Global.NUMERICAL_ZERO + unitMap.get(subtask.getUnit());
            //实卸量
            String deficitAmount = subtask.getDeficitAmount() != null ? subtask.getDeficitAmount() + unitMap.get(subtask.getUnit()) : Global.NUMERICAL_ZERO + unitMap.get(subtask.getUnit());
            //亏吨重量
            String deficitRealAmount = deficitPrice(BigDecimal.valueOf(NumberUtils.parseDouble(subtask.getLoadAmount())),
                    BigDecimal.valueOf(NumberUtils.parseDouble(subtask.getDeficitAmount())), logisticsOrder.getLoss(),
                    logisticsOrder.getLossUnit(), logisticsOrder.getGoodsPrice()) + unitMap.get(subtask.getUnit());
            waybillOrder.setEntrustAmount((StringUtils.isBlank(waybillOrder.getEntrustAmount()) ? Global.EMPTY_STRING : Global.COMMA) + entrustAmount);
            waybillOrder.setLoadAmount((StringUtils.isBlank(waybillOrder.getLoadAmount()) ? Global.EMPTY_STRING : Global.COMMA) + loadAmount);
            waybillOrder.setUnloadAmount((StringUtils.isBlank(waybillOrder.getUnloadAmount()) ? Global.EMPTY_STRING : Global.COMMA) + unloadAmount);
            waybillOrder.setDeficitAmount((StringUtils.isBlank(waybillOrder.getDeficitAmount()) ? Global.EMPTY_STRING : Global.COMMA) + deficitAmount);
            waybillOrder.setDeficitRealAmount((StringUtils.isBlank(waybillOrder.getDeficitRealAmount()) ? Global.EMPTY_STRING : Global.COMMA) + deficitRealAmount);
            waybillOrder.setLOrderNo((StringUtils.isBlank(waybillOrder.getLOrderNo()) ? Global.EMPTY_STRING : Global.COMMA) + logisticsOrder.getLOrderNo());
            waybillOrder.setProcureFirmName(procure.getFirmName());
            waybillOrder.setSupplyFirmName(supply.getFirmName());
        }
        waybillOrder.setStartTime(startDate.map(KwtWaybillOrderSubtask::getLoadTime).orElse(null));
        waybillOrder.setEndTime(endDate.map(KwtWaybillOrderSubtask::getUnloadTime).orElse(null));
        waybillOrder.setLoadTime(loadDate.map(KwtWaybillOrderTicket::getOperateTime).orElse(null));
        waybillOrder.setUnloadTime(unloadDate.map(KwtWaybillOrderTicket::getOperateTime).orElse(null));
        waybillOrder.setLoadName(loadName);
        waybillOrder.setLoadAddress(loadAddress);
        waybillOrder.setUnloadName(unloadName);
        waybillOrder.setUnloadAddress(unloadAddress);
    }

    /**
     * @param waybillOrder 运单信息
     * @desc 分页看板查询处理
     * @author zk
     * @date 2024/3/13
     **/
    public void findNdexPageHandle(WaybillOrderNdexVo waybillOrder) {
        /*数据处理*/
        List<Map<String, Object>> trackList = new ArrayList<>();
        for (CarWaybillNdexTopEnum entity : CarWaybillNdexTopEnum.values()) {
            //审核状态
            KwtWaybillOrderTrack track = waybillOrderTrackDao.findWaybillOrderTrackV1(waybillOrder.getWOrderId(), entity.getValue());
            Map<String, Object> trackData = new HashMap<>(NumberConstant.SIXTEEN);
            trackData.put("statusName", entity.getName());
            trackData.put("operateStatus", track != null);
            trackData.put("operateTime", track != null ? DateUtils.format(track.getOperateTime(), DateUtils.FORMAT11) : null);
            trackList.add(trackData);
        }
        waybillOrder.setTracks(trackList);

        //榜单信息
        List<KwtWaybillOrderTicket> tickets = waybillOrderTicketDao.findWaybillOrderTicket(waybillOrder.getWOrderId(), null, null);
        //数据处理
        List<String> loadUrl = new ArrayList<>(), unloadUrl = new ArrayList<>();
        for (KwtWaybillOrderTicket ticket : tickets) {
            if (ticket.getType().equals(AddressTypeEnum.SHIPMENT.getCode())) {
                loadUrl.add(FileUtils.spliceBatch(ticket.getUrls()));
            } else {
                unloadUrl.add(FileUtils.spliceBatch(ticket.getUrls()));
            }
        }
        waybillOrder.setLoadUrl(loadUrl);
        waybillOrder.setUnloadUrl(unloadUrl);

        //运单-子单
        List<KwtWaybillOrderSubtask> subtasks = waybillOrderSubtaskDao.findByWOrderId(waybillOrder.getWOrderId());
        //装货时间
        Optional<KwtWaybillOrderSubtask> unloadDate = subtasks.stream().max(Comparator.comparing(KwtWaybillOrderSubtask::getUnloadTime));
        //卸货时间
        Optional<KwtWaybillOrderSubtask> loadDate = subtasks.stream().min(Comparator.comparing(KwtWaybillOrderSubtask::getLoadTime));
        waybillOrder.setStartTime(loadDate.get().getLoadTime());
        waybillOrder.setEndTime(unloadDate.get().getUnloadTime());
    }

    /**
     * @param wOrderId 运单ID
     * @desc 运单详情状态轴
     * @author zk
     * @date 2024/3/14
     **/
    public List<Map<String, Object>> waybillDetailHandle(Long wOrderId) {
        /*数据处理*/
        List<Map<String, Object>> trackList = new ArrayList<>();
        List<Integer> statusList = CarWaybillDetailEnum.initWaybillStatus();
        //使用for-each循环来遍历Color枚举类的所有值
        for (Integer value : statusList) {
            List<String> asList = Arrays.asList(CarWaybillDetailEnum.getValue(value).split(Global.COMMA));
            for (String status : asList) {
                KwtWaybillOrderTrack track = waybillOrderTrackDao.findWaybillOrderTrack(wOrderId, null, null, Integer.valueOf(status));
                Map<String, Object> trackData = new HashMap<>(NumberConstant.SIXTEEN);
                trackData.put("operateTime", track != null ? DateUtils.format(track.getOperateTime(), DateUtils.FORMAT11) : null);
                trackData.put("operateStatus", track != null);
                trackData.put("createTime", track != null ? DateUtils.format(track.getCreateTime(), DateUtils.DATE_TIME_PATTERN) : null);
                trackData.put("status", status);
                trackData.put("statusName", CarWaybillDetailEnum.getName1(Integer.valueOf(status)));
                trackList.add(trackData);
            }
        }

        //运单地址状态处理(到达装货点、已装货、到达卸货点、已卸货)
        List<KwtWaybillOrderAddress> addresses = waybillOrderAddressDao.findByAddresses(wOrderId, null);
        for (KwtWaybillOrderAddress address : addresses) {
            if (address.getAddressType().equals(AddressTypeEnum.SHIPMENT.getCode())) {
                statusList = new ArrayList<>() {{
                    add(CarWaybillEnum.WAIT_LOADING.getCode());
                    add(CarWaybillEnum.COMPLETION_LOADING.getCode());
                }};
            } else {
                statusList = new ArrayList<>() {{
                    add(CarWaybillEnum.WAIT_UNLOADING.getCode());
                    add(CarWaybillEnum.COMPLETION_UNLOADING.getCode());
                }};
            }

            //子单信息
            KwtWaybillOrderSubtask subtask = waybillOrderSubtaskDao.selectById(address.getWSubtaskId());
            for (Integer status : statusList) {
                //状态记录
                KwtWaybillOrderTrack track = waybillOrderTrackDao.findWaybillOrderTrack(wOrderId, null, null, status);
                Map<String, Object> trackData = new HashMap<>(NumberConstant.SIXTEEN);
                trackData.put("id", track != null ? track.getId() : null);
                trackData.put("operateTime", track != null ? DateUtils.format(track.getOperateTime(), DateUtils.FORMAT11) : null);
                trackData.put("operateStatus", track != null);
                trackData.put("createTime", track != null ? DateUtils.format(track.getCreateTime(), DateUtils.DATE_TIME_PATTERN) : null);
                trackData.put("status", status);
                trackData.put("statusName", CarWaybillEnum.getName(status));
                trackData.put("planTime", track != null ? DateUtils.format(address.getPlanTime(), DateUtils.DATE_TIME_PATTERN) : null);
                trackData.put("addressName", address.getName());
                trackData.put("addressCityName", address.getCityName());
                trackData.put("addressDetail", address.getDetailAddress());
                trackData.put("lat", address.getLat());
                trackData.put("lng", address.getLng());
                trackList.add(trackData);
            }
        }

        //审核状态
        KwtWaybillOrderTrack track = waybillOrderTrackDao.findWaybillOrderTrackV1(wOrderId, CarWaybillDetailEnum.WAIT_APPROVAL.getValue());
        Map<String, Object> trackData = new HashMap<>(NumberConstant.SIXTEEN);
        trackData.put("operateTime", track != null ? DateUtils.format(track.getOperateTime(), DateUtils.FORMAT11) : null);
        trackData.put("operateStatus", track != null);
        trackData.put("createTime", track != null ? track.getCreateTime() : null);
        trackData.put("status", CarWaybillDetailEnum.WAIT_APPROVAL.getCode());
        trackData.put("statusName", CarWaybillDetailEnum.WAIT_APPROVAL.getName());
        trackList.add(trackData);
        return trackList;
    }

    /**
     * @param driverId 司机ID
     * @desc 统计司机任务数(待接单 / 出车 / 执行 / 完结)
     * @author zk
     * @date 2024/3/12
     **/
    public Map<String, Object> findStatisticsCountByDriver(Long driverId, HttpServletRequest request) {
        //专场逻辑
        String accessSpecial = request.getHeader("Access-Special");
        List<Long> specialEntIds = remoteSystemService.queryEntIdsByCode(accessSpecial, EntTypeEnum.carrier());
        return waybillOrderV1Dao.findStatisticsCountByDriver(driverId, specialEntIds);
    }

    /**
     * @param params {driverId 司机ID, busStatus  1待接单/2出车/3执行/4完结, month月份, startTime 开始实际, endTime 结束时间}
     * @desc 任务查询
     * @author zk
     * @date 2024/3/12
     **/
    public List<JSONObject> findWaybillOrderByDriver(Map<String, Object> params, HttpServletRequest request) {
        /*参数处理*/
        params.put("driverId", StringUtils.isBlank(params.get("driverId")) ? LoginUserHolder.getUserId() : params.get("driverId"));
        //专场逻辑
        String accessSpecial = request.getHeader("Access-Special");
        List<Long> specialEntIds = remoteSystemService.queryEntIdsByCode(accessSpecial, EntTypeEnum.carrier());
        params.put("specialEntIds", specialEntIds);
        // 设置分页参数
        PageHelper.startPage(PageResult.getPage(params), PageResult.getPageSize(params));

        /*数据查询**/
        List<WaybillOrderSubtaskVo> waybillOrders = waybillOrderV1Dao.findWaybillOrderSubtask(params);
        //企业ID
        List<Long> entIds = waybillOrders.stream().map(WaybillOrderSubtaskVo::getEntId).toList();
        Map<Long, EntCacheResDto> ents = remoteSystemService.queryEntCacheMapByIds(entIds);
        //单位
        Map<String, Map<String, String>> dict = remoteSystemService.queryDictByType(List.of(DictTypeEnum.UNIT_TYPE.getType()));
        Map<String, String> unitMap = CollectionUtils.isNotEmpty(dict) ? dict.get(DictTypeEnum.UNIT_TYPE.getType()) : new HashMap<>(NumberConstant.SIXTEEN);

        //数据处理
        List<JSONObject> list = new ArrayList<>();
        for (WaybillOrderSubtaskVo waybillOrder : waybillOrders) {
            //运单地址信息
            List<KwtWaybillOrderAddress> addresses = waybillOrderAddressDao.findByAddresses(waybillOrder.getId(), null);
            List<JSONObject> addressList = new ArrayList<>();
            for (KwtWaybillOrderAddress address : addresses) {
                //运单子单
                KwtWaybillOrderSubtask subtask = waybillOrderSubtaskDao.selectById(address.getWSubtaskId());
                //物流订单商品信息
                KwtLogisticsOrderGoods goods = logisticsOrderGoodsDao.findByGoods(subtask != null ? subtask.getLOrderId() : null);
                //榜单信息
                KwtWaybillOrderTicket ticket = waybillOrderTicketDao.findWaybillOrderTicketV2(address.getId(), subtask.getUnit());
                //数据组装
                JSONObject addressJson = new JSONObject();
                addressJson.put("wAddressId", address.getId());
                addressJson.put("addressType", address.getAddressType());
                addressJson.put("addressName", address.getName());
                addressJson.put("addressCityName", address.getCityName());
                addressJson.put("addressDetail", address.getDetailAddress());
                addressJson.put("planTime", DateUtils.format(address.getPlanTime(), DateUtils.FORMAT12));
                addressJson.put("entrustAmount", address.getEntrustAmount());
                addressJson.put("goodsName", goods != null ? goods.getGoodsName() : null);
                addressJson.put("unit", subtask.getUnit());
                addressJson.put("unitName", unitMap.get(subtask.getUnit()));
                addressJson.put("amount", ticket != null ? ticket.getAmount() : null);
                addressJson.put("urls", ticket != null ? ticket.getUrls() : null);
                addressJson.put("operateTime", ticket != null ? DateUtils.format(address.getPlanTime(), DateUtils.FORMAT11) : null);
                addressJson.put("approvalStatus", ticket != null ? ticket.getStatus() : null);
                addressList.add(addressJson);
            }

            JSONObject order = JSON.parseObject(JSON.toJSONString(waybillOrder));
            order.put("createTime", DateUtils.format(waybillOrder.getCreateTime(), DateUtils.FORMAT11));
            order.put("typeName", waybillOrder.getType() == NumberConstant.ONE ? "趟次" : "循环");
            order.put("statusName", CarWaybillEnum.getName(waybillOrder.getStatus()));
            order.put("carrierFirmName", ents.get(waybillOrder.getEntId()) != null ? ents.get(waybillOrder.getEntId()).getFirmName() : null);
            order.put("addresses", addressList);
            list.add(order);
        }
        return list;
    }

    /**
     * @desc 获取企业地址信息
     * @author zk
     * @date 2023/9/1
     **/
    public AddressDropListDTO findAddressList() {
        AddressDropListDTO res = new AddressDropListDTO();
        //装货地址树
        List<Integer> loadAddressList = waybillOrderAddressDao.findAddressCodeList(LoginUserHolder.getEntId(), Global.NUMERICAL_ONE);
        //卸货地址树
        List<Integer> unloadAddressList = waybillOrderAddressDao.findAddressCodeList(LoginUserHolder.getEntId(), Global.NUMERICAL_TWO);

        //装货地址下拉列表树
        List<AreaTreeFrontResDto> loadTree = remoteSystemService.queryAreaTreeFrontByCodeList(loadAddressList);
        res.setLoadAddressList(loadTree);
        //卸货地址下拉列表树
        List<AreaTreeFrontResDto> unloadTree = remoteSystemService.queryAreaTreeFrontByCodeList(unloadAddressList);
        res.setUnloadAddressList(unloadTree);
        return res;
    }

    /**
     * @param params 派车参数
     * @desc 派车-多装多卸
     * @author zk
     * @date 2023/7/19
     **/
    @Transactional(rollbackFor = Exception.class)
    public HttpResult sendCarV1(SendCarDto2 params) {
        /*1、校验*/
        HttpResult result = checkWaybillOrderV1(params);
        if (result.getCode() != HttpStatus.SUCCESS_CODE) {
            return result;
        }

        /*2、新增运单相关信息*/
        List<SendCarEntrustDto> sendCarEntrustAll = ranksSave(params);

        /*3、更新承运订单委派信息*/
        List<Long> lOrderIds = editLogisticsOrder(sendCarEntrustAll, params.getType());

        /*4、更新承运订单状态（包括上级承运订单）*/
        editLogisticsOrderStatus(lOrderIds);
        return HttpResult.ok();
    }

    /**
     * @param params 派车请求参数
     * @desc 派车校验
     * @author zk
     * @date 2024/3/4
     **/
    public HttpResult checkWaybillOrderV1(SendCarDto2 params) {
        /*控制校验*/
        if (CollectionUtils.isEmpty(params.getSends())) {
            return HttpResult.error("请选择委派信息！");
        } else {
            for (SendCarInfoDto sendCar : params.getSends()) {
                if (CollectionUtils.isEmpty(sendCar.getEntrusts())) {
                    return HttpResult.error("请选择委派信息！");
                }
            }
        }

        //车辆司机信息
        List<SendCarInfoDto> sends = params.getSends();
        //物流订单ID
        List<Long> lOrderIds = new ArrayList<>();
        //物流订单装卸货地址委派量统计
        Map<Long, BigDecimal> truckTotalEntrustAmount = new HashMap<>(NumberConstant.SIXTEEN);
        for (SendCarInfoDto sendCar : sends) {
            //循环单校验所派车辆是否存在未完结运单
            if (params.getType() == Global.NUMERICAL_TWO) {
                WaybillCountVo countVo = waybillOrderV1Dao.findUnfinishedByTruck(Global.NUMERICAL_TWO, sendCar.getTruckId());
                if (countVo.getTotalExecute() > 0) {
                    //车辆信息
                    RTruckVo truck = remoteFleetService.findTruck(sendCar.getTruckId());
                    String msg = truck != null ? truck.getTruckNo() : Global.EMPTY_STRING;
                    return HttpResult.error("车辆" + msg + "存在未完结的循环运单！");
                }
            }

            //趟次单(循环单默认趟次为1)
            int count = params.getType() == Global.NUMERICAL_ONE ? sendCar.getCount() : Global.NUMERICAL_ONE;
            //运输委托信息
            List<SendCarEntrustDto> entrusts = sendCar.getEntrusts();
            /*数据组装*/
            for (SendCarEntrustDto sendCarEntrust : entrusts) {
                lOrderIds.add(sendCarEntrust.getLOrderId());
                //承运订单该车辆计划运输总量：核定载量 * 趟次
                BigDecimal entrustAmount = BigDecimal.valueOf(sendCarEntrust.getEntrustAmount() * count);
                BigDecimal totalEntrustAmount = truckTotalEntrustAmount.get(sendCarEntrust.getAddressId()) != null
                        ? truckTotalEntrustAmount.get(sendCarEntrust.getAddressId()) : NumberConstant.ZERO_TWO;
                truckTotalEntrustAmount.put(sendCarEntrust.getAddressId(), totalEntrustAmount.add(entrustAmount));
            }
        }
        List<Long> lOrderIdsList = lOrderIds.stream().distinct().toList();

        /*校验物流运单是否可以派车*/
        for (Long lOrderId : lOrderIdsList) {
            KwtLogisticsOrder logisticsOrder = logisticsOrderDao.selectById(lOrderId);
            if (logisticsOrder == null) {
                return HttpResult.error("订单" + lOrderId + "已不存在！");
            }

            //状态校验
            if (!logisticsOrder.getStatus().equals(LogisticsOrderEnum.WAIT_DELIVERY.getCode())
                    && !logisticsOrder.getStatus().equals(LogisticsOrderEnum.IN_TRANSIT.getCode())) {
                return HttpResult.error("订单" + logisticsOrder.getLOrderNo() + LogisticsOrderEnum.getName(logisticsOrder.getStatus()) + "不能派车！");
            }

            //剩余可运量校验
            BigDecimal entrustAmount = logisticsOrder.getEntrustAmount() == null ? new BigDecimal(Global.AMOUNT) : logisticsOrder.getEntrustAmount();
            BigDecimal subcontractAmount = logisticsOrder.getSubcontractAmount() == null ? new BigDecimal(Global.AMOUNT) : logisticsOrder.getSubcontractAmount();
            //历史下游司机委派量 + 分包量
            BigDecimal entrustAmountTotal = entrustAmount.add(subcontractAmount);
            if (entrustAmountTotal.compareTo(logisticsOrder.getAmount()) > 0) {
                return HttpResult.error("订单" + logisticsOrder.getLOrderNo() + "剩余可运量已不能派车！");
            }

            /*校验是车辆委托量否超过物流订单剩余量-趟次*/
            //物流订单地址委托量信息-装货信息
            KwtLogisticsOrderAddress queryAmount = new KwtLogisticsOrderAddress();
            queryAmount.setLOrderId(lOrderId);
            queryAmount.setAddressType(AddressTypeEnum.SHIPMENT.getCode());
            List<KwtLogisticsOrderAmount> logisticsOrderAmounts = logisticsOrderAmountDao.findByAddress(queryAmount);
            for (KwtLogisticsOrderAmount orderAmount : logisticsOrderAmounts) {
                BigDecimal truckEntrustAmount = truckTotalEntrustAmount.get(orderAmount.getLAddressId());
                if (Objects.isNull(truckEntrustAmount)) {
                    continue;
                }
                //剩余可运量 = 当前上游委派量 - 历史下游司机委派量 - 分包量
                BigDecimal surplusAmount = orderAmount.getAmount().subtract(orderAmount.getEntrustAmount()).subtract(orderAmount.getSubcontractAmount());
                if (surplusAmount.doubleValue() < truckEntrustAmount.doubleValue()) {
                    KwtLogisticsOrderAddress address = logisticsOrderAddressDao.selectById(orderAmount.getLAddressId());
                    return HttpResult.error(address.getName() + "剩余量为" + surplusAmount.doubleValue()
                            + "，当前累计派车量为" + truckEntrustAmount.doubleValue() +"，可运量小于累计派车量则不能派车！");
                }
            }
        }
        return HttpResult.ok(truckTotalEntrustAmount);
    }

    /**
     * @param params 派车请求参数
     * @desc 新增运单相关信息
     * @author zk
     * @date 2024/3/5
     **/
    public List<SendCarEntrustDto> ranksSave(SendCarDto2 params) {
        //车辆司机信息
        List<SendCarInfoDto> sends = params.getSends();
        //物流订单对应地址信息(所有)
        List<SendCarEntrustDto> sendCarEntrustAll = new ArrayList<>();
        for (SendCarInfoDto sendCar : sends) {
            //趟次单(循环单默认趟次为1)
            int count = params.getType() == Global.NUMERICAL_ONE ? sendCar.getCount() : Global.NUMERICAL_ONE;
            for (int i = 0; i < count; i++) {
                //新增运单信息
                KwtWaybillOrderV1 waybillOrder = sendCarDriver(sendCar, params.getType());
                //运输委托信息
                List<SendCarEntrustDto> entrusts = sendCar.getEntrusts();
                //物流订单对应地址信息
                Map<Long, List<SendCarEntrustDto>> sendCarEntrusts = new HashMap<>(NumberConstant.SIXTEEN);
                //数据组装-物流订单归类（合并派车）
                for (SendCarEntrustDto sendCarEntrust : entrusts) {
                    //物流订单ID
                    Long lOrderId = sendCarEntrust.getLOrderId();
                    //委派信息
                    List<SendCarEntrustDto> entrustDtos = new ArrayList<>() {{
                        add(sendCarEntrust);
                    }};
                    if (sendCarEntrusts.get(lOrderId) == null) {
                        sendCarEntrusts.put(lOrderId, entrustDtos);
                    } else {
                        entrustDtos.addAll(sendCarEntrusts.get(lOrderId));
                        sendCarEntrusts.put(lOrderId, entrustDtos);
                    }
                    sendCarEntrustAll.add(sendCarEntrust);
                }

                //数据存储
                for (Long lOrderId : sendCarEntrusts.keySet()) {
                    //物流订单关联委派地址信息
                    List<SendCarEntrustDto> sendCars = sendCarEntrusts.get(lOrderId);
                    //物流订单委派量统计
                    BigDecimal entrustAmount = NumberConstant.ZERO_TWO;
                    //物流订单委派装货时间
                    List<Date> loadTime = new ArrayList<>();
                    //物流订单委派卸货时间
                    List<Date> unloadTime = new ArrayList<>();
                    //数据组装-数据统计
                    for (SendCarEntrustDto sendCarEntrust : sendCars) {
                        //委派量
                        BigDecimal amount = BigDecimal.valueOf(sendCarEntrust.getEntrustAmount());
                        //计划装卸货时间
                        Date planTime = sendCarEntrust.getPlanTime();
                        //装货+卸货
                        if (sendCarEntrust.getAddressType() == AddressTypeEnum.SHIPMENT.getCode()) {
                            entrustAmount = entrustAmount.add(amount);
                            loadTime.add(planTime);
                        } else {
                            unloadTime.add(planTime);
                        }
                    }

                    //新增运单子单信息
                    KwtWaybillOrderSubtask subtasks = waybillOrderSubtaskService.sendCarSubtask(waybillOrder, lOrderId, entrustAmount, loadTime, unloadTime);
                    for (SendCarEntrustDto sendCarEntrust : sendCars) {
                        //新增地址信息
                        sendCarAddress(subtasks.getId(), sendCarEntrust, waybillOrder);
                    }
                }

                /*车辆运单状态记录*/
                this.setWaybillOrderTrack(waybillOrder.getId(), null, null, waybillOrder.getUpdateTime(), waybillOrder.getStatus(), null);
            }
        }
        return sendCarEntrustAll;
    }

    /**
     * @param sendCarEntrusts 委派参数
     * @param type            运单类型
     * @desc 更新承运订单委派信息
     * @author zk
     * @date 2024/3/5
     **/
    public List<Long> editLogisticsOrder(List<SendCarEntrustDto> sendCarEntrusts, int type) {
        //物流订单ID
        List<Long> lOrderIds = new ArrayList<>();
        //物流订单对应委派量(所有)
        Map<Long, BigDecimal> lEntrustAmount = new HashMap<>(NumberConstant.SIXTEEN);
        //物流订单地址对应委派量(所有)
        Map<Long, BigDecimal> aEntrustAmount = new HashMap<>(NumberConstant.SIXTEEN);
        //数据组装-数据统计
        for (SendCarEntrustDto sendCarEntrust : sendCarEntrusts) {
            //委派量
            BigDecimal amount = BigDecimal.valueOf(sendCarEntrust.getEntrustAmount());
            //装货+卸货
            if (sendCarEntrust.getAddressType() == AddressTypeEnum.SHIPMENT.getCode()) {
                if (lEntrustAmount.get(sendCarEntrust.getLOrderId()) == null) {
                    lEntrustAmount.put(sendCarEntrust.getLOrderId(), amount);
                } else {
                    BigDecimal entrustAmount = lEntrustAmount.get(sendCarEntrust.getLOrderId()).add(amount);
                    lEntrustAmount.put(sendCarEntrust.getLOrderId(), entrustAmount);
                }
                if (aEntrustAmount.get(sendCarEntrust.getAddressId()) == null) {
                    aEntrustAmount.put(sendCarEntrust.getAddressId(), amount);
                } else {
                    BigDecimal entrustAmount = aEntrustAmount.get(sendCarEntrust.getAddressId()).add(amount);
                    aEntrustAmount.put(sendCarEntrust.getAddressId(), entrustAmount);
                }
            }
            lOrderIds.add(sendCarEntrust.getLOrderId());
        }

        //循环单不更新物流订单委派量
        if (type == Global.NUMERICAL_TWO) {
            return lOrderIds.stream().distinct().toList();
        }

        //更新承运订单运量kwt_logistics_order_amount委派量
        for (Long lOrderId : lEntrustAmount.keySet()) {
            KwtLogisticsOrder logisticsOrder = logisticsOrderDao.selectById(lOrderId);
            BigDecimal entrustAmount = logisticsOrder.getEntrustAmount() == null ? new BigDecimal(Global.AMOUNT) : logisticsOrder.getEntrustAmount();
            logisticsOrder.setEntrustAmount(entrustAmount.add(lEntrustAmount.get(lOrderId)));
            logisticsOrderDao.updateById(logisticsOrder);
        }

        //更新承运订单kwt_logistics_order委派量
        for (Long lAddressId : aEntrustAmount.keySet()) {
            KwtLogisticsOrderAmount logisticsOrderAmount = logisticsOrderAmountDao.findByLAddressId(lAddressId);
            BigDecimal entrustAmount = logisticsOrderAmount.getEntrustAmount() == null ? new BigDecimal(Global.AMOUNT) : logisticsOrderAmount.getEntrustAmount();
            logisticsOrderAmount.setEntrustAmount(entrustAmount.add(aEntrustAmount.get(lAddressId)));
            logisticsOrderAmountDao.updateById(logisticsOrderAmount);
        }
        return lOrderIds.stream().distinct().toList();
    }

    /**
     * @param lOrderIds 物流订单集
     * @desc 更新承运订单状态信息（包括分包上级物流订单）
     * @author zk
     * @date 2024/3/5
     **/
    public void editLogisticsOrderStatus(List<Long> lOrderIds) {
        for (Long lOrderId : lOrderIds) {
            //物流订单信息
            KwtLogisticsOrder logisticsOrder = logisticsOrderDao.selectById(lOrderId);
            //当前承运订单所属分包层级
            String pids = logisticsOrder.getPids();
            if (StringUtils.isNotBlank(pids)) {
                String[] idArray = pids.split(Global.COMMA);
                for (String id : idArray) {
                    KwtLogisticsOrder order = logisticsOrderDao.selectById(id);
                    //承运订单-待派车
                    if (order.getStatus().equals(LogisticsOrderEnum.WAIT_DELIVERY.getCode())) {
                        //更新当前承运订单状态(待派车->运输中)
                        order.setStatus(LogisticsOrderEnum.IN_TRANSIT.getCode());
                        logisticsOrderDao.updateById(order);

                        //承运订单状态记录
                        KwtLogisticsOrderTrack orderTrack = new KwtLogisticsOrderTrack();
                        orderTrack.setLOrderId(order.getId());
                        orderTrack.setStatus(order.getStatus());
                        orderTrack.setRemark(LogisticsOrderEnum.getName(order.getStatus()));
                        logisticsOrderTrackDao.insert(orderTrack);
                    }
                }
            }
        }
    }

    /**
     * @param sendCar 车辆司机信息
     * @param type    派车类型(1 趟次、2 循环)
     * @desc 运单信息
     * @author zk
     * @date 2024/3/4
     **/
    public KwtWaybillOrderV1 sendCarDriver(SendCarInfoDto sendCar, int type) {
        //车辆运单编号存储
        //String wOrderNo = getRedisGenerateWaybillOrderNo(RedisOrderGenerateEnum.WAYBILL_ORDER, OrderRuleEnum.WAYBILL_ORDER, logisticsOrder.getLOrderNo());
        //车辆信息
        RTruckVo truck = remoteFleetService.findTruck(sendCar.getTruckId());
        //司机信息
        RDriverVo driver = remoteFleetService.findDriver(sendCar.getDriverId());
        //运单信息
        KwtWaybillOrderV1 waybillOrder = new KwtWaybillOrderV1();
        waybillOrder.setEntId(LoginUserHolder.getEntId());
        waybillOrder.setWOrderNo("W" + System.currentTimeMillis());
        waybillOrder.setType(type);
        waybillOrder.setTruckId(sendCar.getTruckId());
        waybillOrder.setTruckNo(truck != null ? truck.getTruckNo() : null);
        waybillOrder.setDriverId(sendCar.getDriverId());
        waybillOrder.setDriverName(driver != null ? driver.getName() : null);
        waybillOrder.setDriverPhone(driver != null ? driver.getPhone() : null);
        waybillOrder.setDriverIdcard(driver != null ? driver.getIdcard() : null);
        waybillOrder.setStatus(CarWaybillEnum.PENDING_ORDER.getCode());
        waybillOrderV1Dao.insert(waybillOrder);
        return waybillOrder;
    }

    /**
     * @param wSubtaskId     运单-子订单ID
     * @param sendCarEntrust 运输委托信息
     * @param waybillOrder   运单信息
     * @desc 运单地址信息
     * @author zk
     * @date 2024/3/4
     **/
    public KwtWaybillOrderAddress sendCarAddress(Long wSubtaskId, SendCarEntrustDto sendCarEntrust, KwtWaybillOrderV1 waybillOrder) {
        KwtLogisticsOrderAddress logisticsOrderAddress = logisticsOrderAddressDao.selectById(sendCarEntrust.getAddressId());
        KwtWaybillOrderAddress orderAddress = new KwtWaybillOrderAddress();
        BeanUtils.copyProperties(logisticsOrderAddress, orderAddress);
        orderAddress.setId(null);
        orderAddress.setWOrderId(waybillOrder.getId());
        orderAddress.setWSubtaskId(wSubtaskId);
        orderAddress.setLAddressId(sendCarEntrust.getAddressId());
        orderAddress.setPlanTime(sendCarEntrust.getPlanTime());
        orderAddress.setEntrustAmount(BigDecimal.valueOf(sendCarEntrust.getEntrustAmount()));
        orderAddress.setSort(sendCarEntrust.getSort());
        orderAddress.setCreateBy(null);
        orderAddress.setCreateTime(null);
        orderAddress.setUpdateBy(null);
        orderAddress.setUpdateTime(null);
        waybillOrderAddressDao.insert(orderAddress);
        return orderAddress;
    }

    /**
     * @param wOrderId   车辆订单ID
     * @param wSubtaskId 车辆运单子单ID
     * @param wAddressId 车辆订单地址id
     * @param status     车辆运单状态
     * @param remark     备注
     * @desc 新增运单状态记录
     * @author zk
     * @date 2023/7/20
     **/
    public void setWaybillOrderTrack(Long wOrderId, Long wSubtaskId, Long wAddressId, Date operateTime, int status, String remark) {
        KwtWaybillOrderTrack orderTrack = new KwtWaybillOrderTrack();
        orderTrack.setWOrderId(wOrderId);
        orderTrack.setWSubtaskId(wSubtaskId);
        orderTrack.setWAddressId(wAddressId);
        orderTrack.setOperateTime(operateTime == null ? new Date() : operateTime);
        orderTrack.setStatus(status);
        orderTrack.setRemark(remark);
        waybillOrderTrackDao.insert(orderTrack);
    }

    /**
     * @param ids 车辆运单主键ID，多个已逗号隔开
     * @desc 取消派车(趟次派车)
     * @author zk
     * @date 2024/3/7
     **/
    @Transactional(rollbackFor = Exception.class)
    public HttpResult cancelSendCarV1(List<Long> ids) {
        /*1、校验*/
        if (CollectionUtils.isEmpty(ids)) {
            return HttpResult.error("请选择需要撤回的运单！");
        }
        for (Long wOrderId : ids) {
            KwtWaybillOrderV1 waybillOrder = waybillOrderV1Dao.selectById(wOrderId);
            if (waybillOrder == null) {
                return HttpResult.error("运单" + wOrderId + "不存在，请确认！");
            }
            //趟次运单才能撤回
            if (waybillOrder.getType() != Global.NUMERICAL_ONE) {
                return HttpResult.error("运单" + waybillOrder.getWOrderNo() + "为循环运单不能撤回！");
            }
            //待接单的车辆运单才能撤回
            if (!waybillOrder.getStatus().equals(CarWaybillEnum.PENDING_ORDER.getCode())) {
                return HttpResult.error("运单" + waybillOrder.getWOrderNo() + "当前状态已不能撤回！");
            }

            /*2、更新运单状态*/
            waybillOrder.setStatus(CarWaybillEnum.REVOKED.getCode());
            waybillOrderV1Dao.updateById(waybillOrder);

            /*3、新增运单状态记录*/
            setWaybillOrderTrack(waybillOrder.getId(), null, null, waybillOrder.getUpdateTime(), waybillOrder.getStatus(), null);

            /*4、回退物流订单委托量*/
            /*4.1、装货址委派量entrustAmount回退*/
            //运单装货地址
            List<KwtWaybillOrderAddress> orderAddresses = waybillOrderAddressDao.findByAddresses(wOrderId, AddressTypeEnum.SHIPMENT.getCode());
            for (KwtWaybillOrderAddress address : orderAddresses) {
                //物流订单-装卸货地址运量信息
                KwtLogisticsOrderAmount logisticsOrderAmount = logisticsOrderAmountDao.findByLAddressId(address.getLAddressId());
                //承运订单地址已委派量=承运订单地址原委派量-当前车辆运单地址委派量
                BigDecimal entrustAmount = logisticsOrderAmount.getEntrustAmount() == null ? NumberConstant.ZERO_TWO : logisticsOrderAmount.getEntrustAmount();
                logisticsOrderAmount.setEntrustAmount(entrustAmount.subtract(address.getEntrustAmount()));
                logisticsOrderAmountDao.updateById(logisticsOrderAmount);
            }

            /*4.2、物流订单委派量entrustAmount回退*/
            //运单子订单
            List<KwtWaybillOrderSubtask> orderSubtasks = waybillOrderSubtaskDao.findByWOrderId(wOrderId);
            for (KwtWaybillOrderSubtask subtask : orderSubtasks) {
                //更新运单子单状态
                subtask.setStatus(waybillOrder.getStatus());
                waybillOrderSubtaskDao.updateById(subtask);

                //物流订单
                KwtLogisticsOrder logisticsOrder = logisticsOrderDao.selectById(subtask.getLOrderId());
                //承运订单已委派量=承运订单原委派量-当前车辆运单委派量
                BigDecimal entrustAmount = logisticsOrder.getEntrustAmount() == null ? NumberConstant.ZERO_TWO : logisticsOrder.getEntrustAmount();
                logisticsOrder.setEntrustAmount(entrustAmount.subtract(subtask.getEntrustAmount()));
                logisticsOrderDao.updateById(logisticsOrder);
            }
        }
        return HttpResult.ok();
    }

    /**
     * @param params {}
     * @desc 确认接单
     * @author zk
     * @date 2024/3/7
     **/
    @Transactional(rollbackFor = Exception.class)
    public HttpResult confirmSendCarV1(OperateWaybillDto params) {
        /*1、校验*/
        Long wOrderId = params.getWOrderId();
        //运单信息
        KwtWaybillOrderV1 waybillOrder = waybillOrderV1Dao.selectById(wOrderId);
        if (waybillOrder == null) {
            return HttpResult.error("运单" + wOrderId + "不存在，请确认！");
        }
        //待接单的车辆运单才能确认接单
        if (!waybillOrder.getStatus().equals(CarWaybillEnum.PENDING_ORDER.getCode())) {
            return HttpResult.error("运单" + waybillOrder.getWOrderNo() + "当前状态已不能接单！");
        }

        /*2、更新运单状态*/
        waybillOrder.setStatus(CarWaybillEnum.PENDING_VEHICLE.getCode());
        waybillOrderV1Dao.updateById(waybillOrder);

        //3、运单子单更新状态
        List<KwtWaybillOrderSubtask> orderSubtasks = waybillOrderSubtaskDao.findByWOrderId(wOrderId);
        for (KwtWaybillOrderSubtask subtask : orderSubtasks) {
            //更新运单子单状态
            subtask.setStatus(waybillOrder.getStatus());
            waybillOrderSubtaskDao.updateById(subtask);
        }

        /*4、新增运单状态记录*/
        setWaybillOrderTrack(waybillOrder.getId(), null, null, params.getOperateTime(), waybillOrder.getStatus(), params.getRemark());

        /*5、更新司机/车辆数据*/
        //更新司机信息
        editDriver(waybillOrder.getDriverId());
        //更新车辆信息
        editTruck(waybillOrder.getTruckId());
        //趟次运单不对物流订单委托量变更
        if (waybillOrder.getType() == Global.NUMERICAL_ONE) {
            return HttpResult.ok();
        }

        /*6、累加物流订单委托量(循环运单)*/
        /*6.1、装货址委派量entrustAmount累加*/
        //运单装货地址
        List<KwtWaybillOrderAddress> orderAddresses = waybillOrderAddressDao.findByAddresses(wOrderId, AddressTypeEnum.SHIPMENT.getCode());
        for (KwtWaybillOrderAddress address : orderAddresses) {
            //物流订单-装卸货地址运量信息
            KwtLogisticsOrderAmount logisticsOrderAmount = logisticsOrderAmountDao.findByLAddressId(address.getLAddressId());
            //承运订单地址已委派量=承运订单地址原委派量+当前车辆运单地址委派量
            BigDecimal entrustAmount = logisticsOrderAmount.getEntrustAmount() == null ? NumberConstant.ZERO_TWO : logisticsOrderAmount.getEntrustAmount();
            logisticsOrderAmount.setEntrustAmount(entrustAmount.add(address.getEntrustAmount()));
            logisticsOrderAmountDao.updateById(logisticsOrderAmount);
        }

        /*6.2、物流订单委派量entrustAmount累加*/
        for (KwtWaybillOrderSubtask subtask : orderSubtasks) {
            //物流订单
            KwtLogisticsOrder logisticsOrder = logisticsOrderDao.selectById(subtask.getLOrderId());
            //承运订单已委派量=承运订单原委派量+当前车辆运单委派量
            BigDecimal entrustAmount = logisticsOrder.getEntrustAmount() == null ? NumberConstant.ZERO_TWO : logisticsOrder.getEntrustAmount();
            logisticsOrder.setEntrustAmount(entrustAmount.add(subtask.getEntrustAmount()));
            logisticsOrderDao.updateById(logisticsOrder);
        }
        return HttpResult.ok();
    }

    /**
     * @param params {}
     * @desc 拒绝接单
     * @author zk
     * @date 2024/3/7
     **/
    @Transactional(rollbackFor = Exception.class)
    public HttpResult refuseSendCarV1(OperateWaybillDto params) {
        /*1、校验*/
        Long wOrderId = params.getWOrderId();
        //运单信息
        KwtWaybillOrderV1 waybillOrder = waybillOrderV1Dao.selectById(wOrderId);
        if (waybillOrder == null) {
            return HttpResult.error("运单" + wOrderId + "不存在，请确认！");
        }
        //待接单的车辆运单才能拒绝接单
        if (!waybillOrder.getStatus().equals(CarWaybillEnum.PENDING_ORDER.getCode())) {
            return HttpResult.error("运单" + waybillOrder.getWOrderNo() + "当前状态已不能拒绝接单！");
        }

        /*2、更新运单状态*/
        waybillOrder.setStatus(CarWaybillEnum.REJECT_ORDER.getCode());
        waybillOrderV1Dao.updateById(waybillOrder);

        /*3、新增运单状态记录*/
        setWaybillOrderTrack(waybillOrder.getId(), null, null, params.getOperateTime(), waybillOrder.getStatus(), params.getRemark());

        //4、运单子单更新状态
        List<KwtWaybillOrderSubtask> orderSubtasks = waybillOrderSubtaskDao.findByWOrderId(wOrderId);
        for (KwtWaybillOrderSubtask subtask : orderSubtasks) {
            //更新运单子单状态
            subtask.setStatus(waybillOrder.getStatus());
            waybillOrderSubtaskDao.updateById(subtask);
        }

        //循环运单不对物流订单委托量变更
        if (waybillOrder.getType() == Global.NUMERICAL_TWO) {
            return HttpResult.ok();
        }

        /*5、回退物流订单委托量(循环运单)*/
        /*5.1、装货址委派量entrustAmount回退*/
        //运单装货地址
        List<KwtWaybillOrderAddress> orderAddresses = waybillOrderAddressDao.findByAddresses(wOrderId, AddressTypeEnum.SHIPMENT.getCode());
        for (KwtWaybillOrderAddress address : orderAddresses) {
            //物流订单-装卸货地址运量信息
            KwtLogisticsOrderAmount logisticsOrderAmount = logisticsOrderAmountDao.findByLAddressId(address.getLAddressId());
            //承运订单地址已委派量=承运订单地址原委派量-+当前车辆运单地址委派量
            BigDecimal entrustAmount = logisticsOrderAmount.getEntrustAmount() == null ? NumberConstant.ZERO_TWO : logisticsOrderAmount.getEntrustAmount();
            logisticsOrderAmount.setEntrustAmount(entrustAmount.subtract(address.getEntrustAmount()));
            logisticsOrderAmountDao.updateById(logisticsOrderAmount);
        }

        /*5.2、物流订单委派量entrustAmount回退*/
        for (KwtWaybillOrderSubtask subtask : orderSubtasks) {
            //物流订单
            KwtLogisticsOrder logisticsOrder = logisticsOrderDao.selectById(subtask.getLOrderId());
            //承运订单已委派量=承运订单原委派量-当前车辆运单委派量
            BigDecimal entrustAmount = logisticsOrder.getEntrustAmount() == null ? NumberConstant.ZERO_TWO : logisticsOrder.getEntrustAmount();
            logisticsOrder.setEntrustAmount(entrustAmount.subtract(subtask.getEntrustAmount()));
            logisticsOrderDao.updateById(logisticsOrder);
        }

        /*6发送消息**/
        List<UserInfo> users = new ArrayList<>() {{
            add(new UserInfo(waybillOrder.getCreateBy(), waybillOrder.getEntId()));
        }};
        Map<String, Object> msgParams = new HashMap<>() {{
            put("orderNo", waybillOrder.getWOrderNo());
            put("driverName", waybillOrder.getDriverName());
        }};
        SckwMessage msg = new SckwMessage();
        msg.setRequestId(UUIDUtils.get32UUID());
        msg.setMessageEnum(MessageEnum.WAYBILL_REFUSE_SENDCAR_TRIP);
        msg.setParams(msgParams);
        msg.setMsgUrls(new HashMap<>(Global.NUMERICAL_SIXTEEN) {{
            put("app", refuseSendCarAppUrl);
            put("pc", refuseSendCarPcUrl);
        }});
        msg.setUserInfos(users);
        msg.setCreateBy(LoginUserHolder.getUserId());
        streamBridge.send("sckw-message", JSON.toJSONString(msg));
        return HttpResult.ok();
    }

    /**
     * @param params {}
     * @desc 确认出车
     * @author zk
     * @date 2024/3/7
     **/
    @Transactional(rollbackFor = Exception.class)
    public HttpResult confirmDepartureV1(OperateWaybillDto params) {
        /*1、校验*/
        Long wOrderId = params.getWOrderId();
        //运单信息
        KwtWaybillOrderV1 waybillOrder = waybillOrderV1Dao.selectById(wOrderId);
        if (waybillOrder == null) {
            return HttpResult.error("运单" + wOrderId + "不存在，请确认！");
        }
        //待出车的车辆运单才能出车
        if (!waybillOrder.getStatus().equals(CarWaybillEnum.PENDING_VEHICLE.getCode())) {
            return HttpResult.error("运单" + waybillOrder.getWOrderNo() + "当前状态不能出车！");
        }
        //车辆任务中校验
        WaybillCountVo countVo = waybillOrderV1Dao.findCountByDriverOrTruck(null, waybillOrder.getTruckId());
        if (countVo.getTotalExecute() > 0) {
            return HttpResult.error("车辆" + waybillOrder.getTruckNo() + "正在任务中，暂不能出车！");
        }

        /*2、更新运单状态*/
        waybillOrder.setStatus(CarWaybillEnum.EXIT_COMPLETED.getCode());
        waybillOrderV1Dao.updateById(waybillOrder);

        //3、运单子单更新状态
        List<KwtWaybillOrderSubtask> orderSubtasks = waybillOrderSubtaskDao.findByWOrderId(wOrderId);
        for (KwtWaybillOrderSubtask subtask : orderSubtasks) {
            //更新运单子单状态
            subtask.setStatus(waybillOrder.getStatus());
            waybillOrderSubtaskDao.updateById(subtask);
        }

        /*4、新增运单状态记录*/
        setWaybillOrderTrack(waybillOrder.getId(), null, null, params.getOperateTime(), waybillOrder.getStatus(), params.getRemark());

        /*5、更新司机/车辆数据*/
        //更新司机信息
        editDriver(waybillOrder.getDriverId());
        //更新车辆信息
        editTruck(waybillOrder.getTruckId());
        return HttpResult.ok();
    }

    /**
     * @param params {}
     * @desc 拒绝出车
     * @author zk
     * @date 2024/3/7
     **/
    @Transactional(rollbackFor = Exception.class)
    public HttpResult refuseDepartureV1(OperateWaybillDto params) {
        /*1、校验*/
        Long wOrderId = params.getWOrderId();
        //运单信息
        KwtWaybillOrderV1 waybillOrder = waybillOrderV1Dao.selectById(wOrderId);
        if (waybillOrder == null) {
            return HttpResult.error("运单" + wOrderId + "不存在，请确认！");
        }
        //待出车的车辆运单才能拒绝出车
        if (!waybillOrder.getStatus().equals(CarWaybillEnum.PENDING_VEHICLE.getCode())) {
            return HttpResult.error("运单" + waybillOrder.getWOrderNo() + "当前状态不能拒绝出车！");
        }

        /*2、更新运单状态*/
        waybillOrder.setStatus(CarWaybillEnum.REFUSE_TRAFFIC.getCode());
        waybillOrderV1Dao.updateById(waybillOrder);

        //3、运单子单更新状态
        List<KwtWaybillOrderSubtask> orderSubtasks = waybillOrderSubtaskDao.findByWOrderId(wOrderId);
        for (KwtWaybillOrderSubtask subtask : orderSubtasks) {
            //更新运单子单状态
            subtask.setStatus(waybillOrder.getStatus());
            waybillOrderSubtaskDao.updateById(subtask);
        }

        /*4、新增运单状态记录*/
        setWaybillOrderTrack(waybillOrder.getId(), null, null, params.getOperateTime(), waybillOrder.getStatus(), params.getRemark());

        /*5、回退物流订单委托量*/
        /*5.1、装货址委派量entrustAmount回退*/
        //运单装货地址
        List<KwtWaybillOrderAddress> orderAddresses = waybillOrderAddressDao.findByAddresses(wOrderId, AddressTypeEnum.SHIPMENT.getCode());
        for (KwtWaybillOrderAddress address : orderAddresses) {
            //物流订单-装卸货地址运量信息
            KwtLogisticsOrderAmount logisticsOrderAmount = logisticsOrderAmountDao.findByLAddressId(address.getLAddressId());
            //承运订单地址已委派量=承运订单地址原委派量-当前车辆运单地址委派量
            BigDecimal entrustAmount = logisticsOrderAmount.getEntrustAmount() == null ? NumberConstant.ZERO_TWO : logisticsOrderAmount.getEntrustAmount();
            logisticsOrderAmount.setEntrustAmount(entrustAmount.subtract(address.getEntrustAmount()));
            logisticsOrderAmountDao.updateById(logisticsOrderAmount);
        }

        /*5.2、物流订单委派量entrustAmount回退*/
        for (KwtWaybillOrderSubtask subtask : orderSubtasks) {
            //物流订单
            KwtLogisticsOrder logisticsOrder = logisticsOrderDao.selectById(subtask.getLOrderId());
            //承运订单已委派量=承运订单原委派量-当前车辆运单委派量
            BigDecimal entrustAmount = logisticsOrder.getEntrustAmount() == null ? NumberConstant.ZERO_TWO : logisticsOrder.getEntrustAmount();
            logisticsOrder.setEntrustAmount(entrustAmount.subtract(subtask.getEntrustAmount()));
            logisticsOrderDao.updateById(logisticsOrder);
        }

        /*6、发送消息**/
        List<UserInfo> users = new ArrayList<>() {{
            add(new UserInfo(waybillOrder.getCreateBy(), waybillOrder.getEntId()));
        }};
        Map<String, Object> msgParams = new HashMap<>() {{
            put("orderNo", waybillOrder.getWOrderNo());
            put("driverName", waybillOrder.getDriverName());
        }};
        SckwMessage msg = new SckwMessage();
        msg.setRequestId(UUIDUtils.get32UUID());
        msg.setMessageEnum(MessageEnum.WAYBIL_CONFIRM_DEPARTURE);
        msg.setParams(msgParams);
        msg.setMsgUrls(new HashMap<>(Global.NUMERICAL_SIXTEEN) {{
            put("app", refuseSendCarAppUrl);
            put("pc", refuseSendCarPcUrl);
        }});
        msg.setUserInfos(users);
        msg.setCreateBy(LoginUserHolder.getUserId());
        streamBridge.send("sckw-message", JSON.toJSONString(msg));
        return HttpResult.ok();
    }

    /**
     * @param params {}
     * @desc 到达装货地点
     * @author zk
     * @date 2024/3/7
     **/
    @Transactional(rollbackFor = Exception.class)
    public HttpResult arriveLoadLocationV1(OperateWaybillDto params) {
        /*1、校验*/
        Long wOrderId = params.getWOrderId();
        //运单信息
        KwtWaybillOrderV1 waybillOrder = waybillOrderV1Dao.selectById(wOrderId);
        if (waybillOrder == null) {
            return HttpResult.error("运单" + wOrderId + "不存在，请确认！");
        }
        //已出车、到达装货地、已装货、到达卸货地、已卸货的车辆运单才能到达装货地点
        if (!CarWaybillEnum.arriveLocation(waybillOrder.getStatus())) {
            return HttpResult.error("运单" + waybillOrder.getWOrderNo() + "当前状态已不能到达装货地点！");
        }

        /*2、更新运单状态*/
        waybillOrder.setStatus(CarWaybillEnum.WAIT_LOADING.getCode());
        waybillOrderV1Dao.updateById(waybillOrder);

        /*3、更新车辆运单-子单*/
        //运单子单信息
        KwtWaybillOrderSubtask orderSubtask = waybillOrderSubtaskDao.selectById(params.getWSubtaskId());
        orderSubtask.setStatus(waybillOrder.getStatus());
        waybillOrderSubtaskDao.updateById(orderSubtask);

        /*4、新增运单状态记录*/
        setWaybillOrderTrack(waybillOrder.getId(), params.getWSubtaskId(), params.getWAddressId(), params.getOperateTime(), waybillOrder.getStatus(), params.getRemark());
        return HttpResult.ok();
    }

    /**
     * @param params {}
     * @desc 装货-多单位+多地址
     * @author zk
     * @date 2024/3/7
     **/
    @Transactional(rollbackFor = Exception.class)
    public HttpResult loadingV1(WaybillOrderTicketV4Dto params) {
        /*1、校验*/
        Long wOrderId = params.getWOrderId();
        //运单信息
        KwtWaybillOrderV1 waybillOrder = waybillOrderV1Dao.selectById(wOrderId);
        if (waybillOrder == null) {
            return HttpResult.error("运单" + wOrderId + "不存在，请确认！");
        }
        //到达装货地的车辆运单才能装货
        if (!waybillOrder.getStatus().equals(CarWaybillEnum.WAIT_LOADING.getCode())) {
            return HttpResult.error("运单" + waybillOrder.getWOrderNo() + "当前状态已不能装货！");
        }

        /*2、更新车辆运单*/
        /*2.1、更新车辆运单-状态*/
        waybillOrder.setStatus(CarWaybillEnum.COMPLETION_LOADING.getCode());
        waybillOrderV1Dao.updateById(waybillOrder);

        /*2.2、更新车辆运单-子单*/
        //运单子单信息
        KwtWaybillOrderSubtask orderSubtask = waybillOrderSubtaskDao.selectById(params.getWSubtaskId());
        //榜单信息
        List<WaybillOrderTicketLoadingDto> loading = params.getLoading();
        BigDecimal loadAmout = waybillOrderTicketService.countAmount(loading, orderSubtask.getUnit(), orderSubtask.getLoadAmount());
        orderSubtask.setLoadAmount(orderSubtask.getLoadAmount().add(loadAmout));
        orderSubtask.setStatus(waybillOrder.getStatus());
        waybillOrderSubtaskDao.updateById(orderSubtask);

        /*3、新增运单状态记录*/
        setWaybillOrderTrack(waybillOrder.getId(), params.getWSubtaskId(), params.getWAddressId(), params.getOperateTime(), waybillOrder.getStatus(), params.getRemark());

        /*4、新增装卸货榜单信息*/
        waybillOrderTicketService.addTicketV1(loading, waybillOrder.getId(), params.getWSubtaskId(), params.getWAddressId(), params.getUrls(), params.getOperateTime(), Global.NUMERICAL_ONE);
        return HttpResult.ok();
    }

    /**
     * @param params {}
     * @desc 到达卸货地点
     * @author zk
     * @date 2024/3/7
     **/
    @Transactional(rollbackFor = Exception.class)
    public HttpResult arriveUnloadLocationV1(OperateWaybillDto params) {
        /*1、校验*/
        Long wOrderId = params.getWOrderId();
        //运单信息
        KwtWaybillOrderV1 waybillOrder = waybillOrderV1Dao.selectById(wOrderId);
        if (waybillOrder == null) {
            return HttpResult.error("运单" + wOrderId + "不存在，请确认！");
        }
        //已出车、到达装货地、已装货、到达卸货地、已卸货的车辆运单才能到达卸货地点
        if (!CarWaybillEnum.arriveLocation(waybillOrder.getStatus())) {
            return HttpResult.error("运单" + waybillOrder.getWOrderNo() + "当前状态已不能到达卸货地点！");
        }

        /*2、更新运单状态*/
        waybillOrder.setStatus(CarWaybillEnum.WAIT_UNLOADING.getCode());
        waybillOrderV1Dao.updateById(waybillOrder);

        /*3、更新车辆运单-子单*/
        //运单子单信息
        KwtWaybillOrderSubtask orderSubtask = waybillOrderSubtaskDao.selectById(params.getWSubtaskId());
        orderSubtask.setStatus(waybillOrder.getStatus());
        waybillOrderSubtaskDao.updateById(orderSubtask);

        /*4、新增运单状态记录*/
        setWaybillOrderTrack(waybillOrder.getId(), params.getWSubtaskId(), params.getWAddressId(), params.getOperateTime(), waybillOrder.getStatus(), params.getRemark());
        return HttpResult.ok();
    }

    /**
     * @param params {}
     * @desc 卸货-多单位
     * @author zk
     * @date 2024/3/7
     **/
    @Transactional(rollbackFor = Exception.class)
    public HttpResult unloadingV1(WaybillOrderTicketV4Dto params) {
        /*1、校验*/
        Long wOrderId = params.getWOrderId();
        //运单信息
        KwtWaybillOrderV1 waybillOrder = waybillOrderV1Dao.selectById(wOrderId);
        if (waybillOrder == null) {
            return HttpResult.error("运单" + wOrderId + "不存在，请确认！");
        }
        //到达卸货地的车辆运单才能卸货
        if (!waybillOrder.getStatus().equals(CarWaybillEnum.WAIT_UNLOADING.getCode())) {
            return HttpResult.error("运单" + waybillOrder.getWOrderNo() + "当前状态已不能卸货！");
        }

        /*2、更新车辆运单*/
        /*2.1、更新车辆运单-状态*/
        waybillOrder.setStatus(CarWaybillEnum.COMPLETION_UNLOADING.getCode());
        waybillOrderV1Dao.updateById(waybillOrder);

        /*2.2、更新车辆运单-子单*/
        //运单子单信息
        KwtWaybillOrderSubtask orderSubtask = waybillOrderSubtaskDao.selectById(params.getWSubtaskId());
        //物流运单信息
        KwtLogisticsOrder logisticsOrder = logisticsOrderDao.selectById(orderSubtask.getLOrderId());
        //榜单信息
        List<WaybillOrderTicketLoadingDto> loading = params.getLoading();
        BigDecimal unloadAmout = waybillOrderTicketService.countAmount(loading, orderSubtask.getUnit(), orderSubtask.getLoadAmount());
        orderSubtask.setUnloadAmount(orderSubtask.getUnloadAmount().add(unloadAmout));
        orderSubtask.setDeficitAmount(orderSubtask.getLoadAmount().subtract(orderSubtask.getUnloadAmount()));
        BigDecimal deficitPrice = deficitPrice(orderSubtask.getLoadAmount(), orderSubtask.getDeficitAmount(),
                logisticsOrder.getLoss(), logisticsOrder.getLossUnit(), logisticsOrder.getGoodsPrice());
        orderSubtask.setDeficitPrice(deficitPrice);
        orderSubtask.setStatus(waybillOrder.getStatus());
        waybillOrderSubtaskDao.updateById(orderSubtask);

        /*3、新增运单状态记录*/
        setWaybillOrderTrack(waybillOrder.getId(), params.getWSubtaskId(), params.getWAddressId(), params.getOperateTime(), waybillOrder.getStatus(), params.getRemark());

        /*4、新增装卸货榜单信息*/
        waybillOrderTicketService.addTicketV1(loading, waybillOrder.getId(), params.getWSubtaskId(), params.getWAddressId(), params.getUrls(), params.getOperateTime(), Global.NUMERICAL_TWO);

        /*5、校验运单-子单是否全部运输完毕*/
        //运单地址信息
        List<KwtWaybillOrderAddress> addresses = waybillOrderAddressDao.findBySubtaskId(params.getWSubtaskId(), null);
        //运单地址榜单信息
        List<KwtWaybillOrderTicket> tickets = waybillOrderTicketDao.findWaybillOrderTicketV1(wOrderId, params.getWSubtaskId(), null, orderSubtask.getUnit());
        ;
        //运单子单是否已经运输完成
        if (addresses.size() != tickets.size()) {
            return HttpResult.ok();
        }

        //更新运单-子单状态
        orderSubtask.setStatus(CarWaybillEnum.APPROVAL_TREAT.getCode());
        waybillOrderSubtaskDao.updateById(orderSubtask);

        /*6、校验运单是否全部运输完毕*/
        //校验子单是否全部为待审批
        List<KwtWaybillOrderSubtask> subtasks = waybillOrderSubtaskDao.findByWOrderId(wOrderId);
        for (KwtWaybillOrderSubtask subtask : subtasks) {
            if (!subtask.getStatus().equals(CarWaybillEnum.APPROVAL_TREAT.getCode())) {
                return HttpResult.ok();
            }
        }

        /*6.1、更新运单状态*/
        waybillOrder.setStatus(CarWaybillEnum.APPROVAL_TREAT.getCode());
        waybillOrderV1Dao.updateById(waybillOrder);

        /*6.2、新增运单状态记录*/
        setWaybillOrderTrack(waybillOrder.getId(), null, null, params.getOperateTime(), waybillOrder.getStatus(), params.getRemark());

        /*7、更新司机/车辆数据*/
        //更新司机信息
        editDriver(waybillOrder.getDriverId());
        //更新车辆信息
        editTruck(waybillOrder.getTruckId());

        /*8、循环单全部装卸货完重新生成运单*/
        if (waybillOrder.getType() == Global.NUMERICAL_TWO) {
            recreateWaybillOrder(waybillOrder);
        }
        return HttpResult.ok();
    }

    /**
     * @param waybillOrder {}
     * @desc 重新生成运单
     * @author zk
     * @date 2024/3/7
     **/
    public void recreateWaybillOrder(KwtWaybillOrderV1 waybillOrder) {
        //运单信息kwt_waybill_order
        KwtWaybillOrderV1 waybillOrderNew = new KwtWaybillOrderV1();
        BeanUtils.copyProperties(waybillOrder, waybillOrderNew);
        waybillOrderNew.setId(null);
        waybillOrderNew.setWOrderNo("W" + System.currentTimeMillis());
        waybillOrderNew.setStatus(CarWaybillEnum.PENDING_ORDER.getCode());
        waybillOrderNew.setCreateTime(null);
        waybillOrderNew.setUpdateTime(null);
        waybillOrderV1Dao.insert(waybillOrderNew);

        //运单子单信息kwt_waybill_order_subtask
        List<KwtWaybillOrderSubtask> subtasks = waybillOrderSubtaskDao.findByWOrderId(waybillOrder.getId());
        for (KwtWaybillOrderSubtask subtask : subtasks) {
            KwtWaybillOrderSubtask subtaskNew = new KwtWaybillOrderSubtask();
            BeanUtils.copyProperties(subtask, subtaskNew);
            subtaskNew.setId(null);
            subtaskNew.setWOrderId(waybillOrderNew.getId());
            subtaskNew.setWOrderNo(waybillOrderNew.getWOrderNo());
            subtaskNew.setLoadAmount(NumberConstant.ZERO_TWO);
            subtaskNew.setUnloadAmount(NumberConstant.ZERO_TWO);
            subtaskNew.setDeficitAmount(NumberConstant.ZERO_TWO);
            subtaskNew.setDeficitPrice(NumberConstant.ZERO_TWO);
            subtaskNew.setStatus(waybillOrderNew.getStatus());
            subtaskNew.setCreateTime(null);
            subtaskNew.setUpdateTime(null);
            waybillOrderSubtaskDao.insert(subtaskNew);

            //运单地址信息kwt_waybill_order_address
            List<KwtWaybillOrderAddress> addresses = waybillOrderAddressDao.findBySubtaskId(subtask.getId(), null);
            for (KwtWaybillOrderAddress address : addresses) {
                KwtWaybillOrderAddress addressNew = new KwtWaybillOrderAddress();
                BeanUtils.copyProperties(address, addressNew);
                addressNew.setId(null);
                addressNew.setWOrderId(waybillOrderNew.getId());
                addressNew.setWSubtaskId(subtaskNew.getId());
                addressNew.setCreateTime(null);
                addressNew.setUpdateTime(null);
                waybillOrderAddressDao.insert(addressNew);
            }
        }

        //新增运单状态记录kwt_waybill_order_track
        setWaybillOrderTrack(waybillOrderNew.getId(), null, null, waybillOrderNew.getCreateTime(), waybillOrderNew.getStatus(), null);
    }

    /**
     * @param params {}
     * @desc 修改单证
     * @author zk
     * @date 2024/3/7
     **/
    @Transactional(rollbackFor = Exception.class)
    public HttpResult editTicketV1(WaybillOrderEditTicketDto params) {
        /*1、校验*/
        Long wTicketId = params.getWTicketId();
        KwtWaybillOrderTicket ticket = waybillOrderTicketDao.selectById(wTicketId);
        //榜单信息
        if (ticket == null) {
            return HttpResult.error("榜单信息不存在，请确认！");
        }
        Long wOrderId = ticket.getWOrderId();
        //运单信息
        KwtWaybillOrderV1 waybillOrder = waybillOrderV1Dao.selectById(wOrderId);
        if (waybillOrder == null) {
            return HttpResult.error("运单" + wOrderId + "不存在，请确认！");
        }
        //已出车、到达装货地、已装货、到达卸货地、已卸货的车辆运单才能卸货
        if (!CarWaybillEnum.arriveLoading(waybillOrder.getStatus())) {
            return HttpResult.error("运单" + waybillOrder.getWOrderNo() + "当前状态已不能修改榜单！");
        }
        //地址信息
        KwtWaybillOrderAddress address = waybillOrderAddressDao.selectById(ticket.getWAddressId());
        if (address == null) {
            return HttpResult.error("运单该地址已不存在！");
        }

        /*2、更新装卸货榜单信息*/
        //榜单信息
        List<WaybillOrderTicketLoadingDto> loading = params.getLoading();
        waybillOrderTicketService.editTicketV1(loading, ticket.getWAddressId(), params.getUrls(), params.getOperateTime());

        /*3、更新车辆运单-子单*/
        //运单子单信息
        KwtWaybillOrderSubtask orderSubtask = waybillOrderSubtaskDao.selectById(ticket.getWSubtaskId());
        //物流运单信息
        KwtLogisticsOrder logisticsOrder = logisticsOrderDao.selectById(orderSubtask.getLOrderId());
        //运单-子单装货榜单信息
        List<KwtWaybillOrderTicket> loadTickets = waybillOrderTicketDao.findWaybillOrderTicketV1(wOrderId, ticket.getWSubtaskId(), AddressTypeEnum.SHIPMENT.getCode(), orderSubtask.getUnit());
        //运单-子单卸货榜单信息
        List<KwtWaybillOrderTicket> unloadTickets = waybillOrderTicketDao.findWaybillOrderTicketV1(wOrderId, ticket.getWSubtaskId(), AddressTypeEnum.TAKE.getCode(), orderSubtask.getUnit());
        //装货-总量
        BigDecimal loadAmount = loadTickets.stream().map(KwtWaybillOrderTicket::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        //卸货-总量
        BigDecimal unloadAmount = unloadTickets.stream().map(KwtWaybillOrderTicket::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        orderSubtask.setLoadAmount(loadAmount);
        orderSubtask.setUnloadAmount(unloadAmount);
        orderSubtask.setDeficitAmount(orderSubtask.getLoadAmount().subtract(orderSubtask.getUnloadAmount()));
        BigDecimal deficitPrice = deficitPrice(orderSubtask.getLoadAmount(), orderSubtask.getDeficitAmount(),
                logisticsOrder.getLoss(), logisticsOrder.getLossUnit(), logisticsOrder.getGoodsPrice());
        orderSubtask.setDeficitPrice(deficitPrice);
        waybillOrderSubtaskDao.updateById(orderSubtask);

        /*4、更新车辆运单子单状态*/
        //运单子单信息
        List<KwtWaybillOrderSubtask> subtasks = waybillOrderSubtaskDao.findByWOrderId(orderSubtask.getWOrderId());
        for (KwtWaybillOrderSubtask subtask : subtasks) {
            //运单子单状态不为驳回状态则不更新运单状态
            if (!subtask.getStatus().equals(CarWaybillEnum.APPROVAL_NO_PASS.getCode())) {
                return HttpResult.ok();
            }
            //榜单存在审核失败状态则不更新运单状态
            List<KwtWaybillOrderTicket> tickets = waybillOrderTicketDao.findWaybillOrderTicket(null, subtask.getId(), null);
            for (KwtWaybillOrderTicket ticket1 : tickets) {
                if (ticket1.getStatus() == Global.NUMERICAL_ONE) {
                    return HttpResult.ok();
                }
            }
            //运单-子弹当前为驳回则状态更新为单证更新审核中
            int status = orderSubtask.getStatus().equals(CarWaybillEnum.APPROVAL_NO_PASS.getCode()) ? CarWaybillEnum.APPROVAL_IN.getCode() : orderSubtask.getStatus();
            subtask.setStatus(status);
            waybillOrderSubtaskDao.updateById(subtask);
        }

        /*5、更新车辆运单-状态*/
        //运单状态不为驳回状态则不更新运单状态
        if (!waybillOrder.getStatus().equals(CarWaybillEnum.APPROVAL_NO_PASS.getCode())) {
            return HttpResult.ok();
        }
        //运单子单存在非待审核和审核中则不更新
        subtasks = waybillOrderSubtaskDao.findByWOrderId(orderSubtask.getWOrderId());
        for (KwtWaybillOrderSubtask subtask : subtasks) {
            if (!subtask.getStatus().equals(CarWaybillEnum.APPROVAL_IN.getCode())
                    && !subtask.getStatus().equals(CarWaybillEnum.APPROVAL_TREAT.getCode())) {
                return HttpResult.ok();
            }
        }
        waybillOrder.setStatus(CarWaybillEnum.APPROVAL_IN.getCode());
        waybillOrderV1Dao.updateById(waybillOrder);

        /*4.2、新增运单状态记录*/
        setWaybillOrderTrack(waybillOrder.getId(), null, null, null, waybillOrder.getStatus(), null);
        return HttpResult.ok();
    }

    /**
     * @param params {}
     * @desc 修改单证-多个修改
     * @author zk
     * @date 2024/3/7
     **/
    @Transactional(rollbackFor = Exception.class)
    public HttpResult editTicketV2(List<WaybillOrderEditTicketDto> params) {
        /*1、校验*/
        for (WaybillOrderEditTicketDto ticketDto : params) {
            Long wTicketId = ticketDto.getWTicketId();
            KwtWaybillOrderTicket ticket = waybillOrderTicketDao.selectById(wTicketId);
            //榜单信息
            if (ticket == null) {
                return HttpResult.error("榜单信息不存在，请确认！");
            }
        }

        //数据处理-榜单
        Long wOrderId = null;
        //运单信息
        KwtWaybillOrderV1 waybillOrder = null;
        for (WaybillOrderEditTicketDto ticketDto : params) {
            Long wTicketId = ticketDto.getWTicketId();
            KwtWaybillOrderTicket ticket = waybillOrderTicketDao.selectById(wTicketId);
            wOrderId = ticket.getWOrderId();
            //运单信息
            waybillOrder = waybillOrderV1Dao.selectById(wOrderId);
            if (waybillOrder == null) {
                return HttpResult.error("运单" + wOrderId + "不存在，请确认！");
            }
            //已出车、到达装货地、已装货、到达卸货地、已卸货的车辆运单才能卸货
            if (!CarWaybillEnum.editTicket(waybillOrder.getStatus())) {
                return HttpResult.error("运单" + waybillOrder.getWOrderNo() + "当前状态已不能修改榜单！");
            }
            //地址信息
            KwtWaybillOrderAddress address = waybillOrderAddressDao.selectById(ticket.getWAddressId());
            if (address == null) {
                return HttpResult.error("运单该地址已不存在！");
            }

            /*2、更新装卸货榜单信息*/
            //榜单信息
            List<WaybillOrderTicketLoadingDto> loading = ticketDto.getLoading();
            waybillOrderTicketService.editTicketV1(loading, ticket.getWAddressId(), ticketDto.getUrls(), ticketDto.getOperateTime());

            /*3、更新车辆运单-子单*/
            //运单子单信息
            KwtWaybillOrderSubtask orderSubtask = waybillOrderSubtaskDao.selectById(ticket.getWSubtaskId());

            //物流运单信息
            KwtLogisticsOrder logisticsOrder = logisticsOrderDao.selectById(orderSubtask.getLOrderId());
            //运单-子单装货榜单信息
            List<KwtWaybillOrderTicket> loadTickets = waybillOrderTicketDao.findWaybillOrderTicketV1(wOrderId, ticket.getWSubtaskId(), AddressTypeEnum.SHIPMENT.getCode(), orderSubtask.getUnit());
            //运单-子单卸货榜单信息
            List<KwtWaybillOrderTicket> unloadTickets = waybillOrderTicketDao.findWaybillOrderTicketV1(wOrderId, ticket.getWSubtaskId(), AddressTypeEnum.TAKE.getCode(), orderSubtask.getUnit());
            //装货-总量
            BigDecimal loadAmount = loadTickets.stream().map(KwtWaybillOrderTicket::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            //卸货-总量
            BigDecimal unloadAmount = unloadTickets.stream().map(KwtWaybillOrderTicket::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            orderSubtask.setLoadAmount(loadAmount);
            orderSubtask.setUnloadAmount(unloadAmount);
            orderSubtask.setDeficitAmount(orderSubtask.getLoadAmount().subtract(orderSubtask.getUnloadAmount()));
            BigDecimal deficitPrice = deficitPrice(orderSubtask.getLoadAmount(), orderSubtask.getDeficitAmount(),
                    logisticsOrder.getLoss(), logisticsOrder.getLossUnit(), logisticsOrder.getGoodsPrice());
            orderSubtask.setDeficitPrice(deficitPrice);
            waybillOrderSubtaskDao.updateById(orderSubtask);
        }

        /*4、更新车辆运单子单状态*/
        //运单子单信息
        List<KwtWaybillOrderSubtask> subtasks = waybillOrderSubtaskDao.findByWOrderId(wOrderId);
        for (KwtWaybillOrderSubtask subtask : subtasks) {
            //运单子单状态不为驳回状态则不更新运单状态
            if (!subtask.getStatus().equals(CarWaybillEnum.APPROVAL_NO_PASS.getCode())) {
                return HttpResult.ok();
            }
            //榜单存在审核失败状态则不更新运单状态
            List<KwtWaybillOrderTicket> tickets = waybillOrderTicketDao.findWaybillOrderTicket(null, subtask.getId(), null);
            for (KwtWaybillOrderTicket ticket1 : tickets) {
                if (ticket1.getStatus() == Global.NUMERICAL_ONE) {
                    return HttpResult.ok();
                }
            }
            //运单-子单当前为驳回则状态更新为单证更新审核中
            int status = subtask.getStatus().equals(CarWaybillEnum.APPROVAL_NO_PASS.getCode()) ? CarWaybillEnum.APPROVAL_IN.getCode() : subtask.getStatus();
            subtask.setStatus(status);
            waybillOrderSubtaskDao.updateById(subtask);
        }

        /*5、更新车辆运单-状态*/
        //运单状态不为驳回状态则不更新运单状态
        if (!waybillOrder.getStatus().equals(CarWaybillEnum.APPROVAL_NO_PASS.getCode())) {
            return HttpResult.ok();
        }
        //运单子单存在非待审核和审核中则不更新
        subtasks = waybillOrderSubtaskDao.findByWOrderId(wOrderId);
        for (KwtWaybillOrderSubtask subtask : subtasks) {
            if (!subtask.getStatus().equals(CarWaybillEnum.APPROVAL_IN.getCode())
                    && !subtask.getStatus().equals(CarWaybillEnum.APPROVAL_TREAT.getCode())) {
                return HttpResult.ok();
            }
        }
        waybillOrder.setStatus(CarWaybillEnum.APPROVAL_IN.getCode());
        waybillOrderV1Dao.updateById(waybillOrder);

        /*4.2、新增运单状态记录*/
        setWaybillOrderTrack(waybillOrder.getId(), null, null, null, waybillOrder.getStatus(), null);
        return HttpResult.ok();
    }

    /**
     * @param params {}
     * @desc 单证审核-驳回
     * @author zk
     * @date 2024/3/7
     **/
    @Transactional(rollbackFor = Exception.class)
    public HttpResult approvalReject(List<WaybillOrderTicketApprovalRejectDto> params) {
        /*1、验证*/
        if (CollectionUtils.isEmpty(params)) {
            return HttpResult.error("请选择需要驳回的榜单！");
        }
        //运单ID集
        List<Long> wOrderIds = new ArrayList<>();
        //运单-子单ID集
        List<Long> wSubtaskIds = new ArrayList<>();
        for (WaybillOrderTicketApprovalRejectDto approval : params) {
            KwtWaybillOrderTicket ticket = waybillOrderTicketDao.selectById(approval.getWTicketId());
            if (ticket == null) {
                return HttpResult.error("榜单不存在请确认！");
            }
            wOrderIds.add(ticket.getWOrderId());
            wSubtaskIds.add(ticket.getWSubtaskId());
        }

        /*2、数据处理*/
        /*2.1、修改榜单状态*/
        for (WaybillOrderTicketApprovalRejectDto approval : params) {
            KwtWaybillOrderTicket ticket = waybillOrderTicketDao.selectById(approval.getWTicketId());
            ticket.setStatus(Global.NUMERICAL_ONE);
            ticket.setRemark(approval.getRemark());
            waybillOrderTicketDao.updateById(ticket);
        }
        /*2.2、修改运单状态*/
        for (Long wOrderId : wOrderIds) {
            KwtWaybillOrderV1 waybillOrder = waybillOrderV1Dao.selectById(wOrderId);
            if (waybillOrder.getStatus().equals(CarWaybillEnum.APPROVAL_NO_PASS.getCode())) {
                continue;
            }
            waybillOrder.setStatus(CarWaybillEnum.APPROVAL_NO_PASS.getCode());
            waybillOrderV1Dao.updateById(waybillOrder);

            /*2.3、新增运单状态记录*/
            setWaybillOrderTrack(waybillOrder.getId(), null, null, null, waybillOrder.getStatus(), null);
        }

        /*2.4、修改运单-子单状态*/
        for (Long wSubtaskId : wSubtaskIds) {
            KwtWaybillOrderSubtask orderSubtask = waybillOrderSubtaskDao.selectById(wSubtaskId);
            if (orderSubtask.getStatus().equals(CarWaybillEnum.APPROVAL_NO_PASS.getCode())) {
                continue;
            }
            orderSubtask.setStatus(CarWaybillEnum.APPROVAL_NO_PASS.getCode());
            waybillOrderSubtaskDao.updateById(orderSubtask);
        }
        return HttpResult.ok();
    }

    /**
     * @param params {}
     * @desc 单证审核（编辑单证）
     * @author zk
     * @date 2024/3/7
     **/
    @Transactional(rollbackFor = Exception.class)
    public HttpResult approvalEditTicketV1(WaybillOrderTicketApprovalV2Dto params) {
        /*1、校验*/
        Long wOrderId = params.getWOrderId();
        //运单信息
        KwtWaybillOrderV1 waybillOrder = waybillOrderV1Dao.selectById(wOrderId);
        if (waybillOrder == null) {
            return HttpResult.error("运单" + wOrderId + "不存在，请确认！");
        }
        //已出车、到达装货地、已装货、到达卸货地、已卸货的车辆运单才能卸货
        if (!waybillOrder.getStatus().equals(CarWaybillEnum.APPROVAL_TREAT.getCode())
                && waybillOrder.getStatus().equals(CarWaybillEnum.APPROVAL_NO_PASS.getCode())
                && waybillOrder.getStatus().equals(CarWaybillEnum.APPROVAL_IN.getCode())) {
            return HttpResult.error("运单" + waybillOrder.getWOrderNo() + "当前状态已不能审核！");
        }
        //变更榜单信息校验
        if (CollectionUtils.isNotEmpty(params.getTickets())) {
            //变更榜单信息
            List<WaybillOrderTicketV4Dto> tickets = params.getTickets();
            for (WaybillOrderTicketV4Dto ticket : tickets) {
                //地址信息
                KwtWaybillOrderAddress address = waybillOrderAddressDao.selectById(ticket.getWAddressId());
                if (address == null) {
                    return HttpResult.error("运单该地址已不存在！");
                }
            }
        }

        /*2、更新榜单信息*/
        /*2.1、同步更新变更榜单信息*/
        editTicket(params);

        /*2.2、更新榜单状态为审核通过*/
        List<KwtWaybillOrderTicket> tickets = waybillOrderTicketDao.findWaybillOrderTicket(wOrderId, null, null);
        for (KwtWaybillOrderTicket ticket : tickets) {
            ticket.setStatus(Global.NUMERICAL_TWO);
            waybillOrderTicketDao.updateById(ticket);
        }

        /*3、修改运单状态*/
        waybillOrder.setStatus(CarWaybillEnum.APPROVAL_PASS.getCode());
        waybillOrderV1Dao.updateById(waybillOrder);

        /*4、新增运单状态记录*/
        setWaybillOrderTrack(waybillOrder.getId(), null, null, null, waybillOrder.getStatus(), null);

        /*5、修改运单-子单状态*/
        List<KwtWaybillOrderSubtask> subtasks = waybillOrderSubtaskDao.findByWOrderId(wOrderId);
        for (KwtWaybillOrderSubtask subtask : subtasks) {
            subtask.setStatus(waybillOrder.getStatus());
            waybillOrderSubtaskDao.updateById(subtask);
        }

        /*6、更新司机/车辆数据*/
        //更新司机信息
        editDriver(waybillOrder.getDriverId());
        //更新车辆信息
        editTruck(waybillOrder.getTruckId());

        /*7、物流订单信息更新*/
        editLogisticsOrder(subtasks);
        //8.运单常用线路保持
        //8.1根据订单号获取地址信息
        editTruckRoute(params, waybillOrder, wOrderId);
        return HttpResult.ok();
    }

    private void editTruckRoute(WaybillOrderTicketApprovalV2Dto params, KwtWaybillOrderV1 waybillOrder, Long wOrderId) {
        try {
            List<KwtWaybillOrderAddress> addressList = waybillOrderAddressRepository.queryByWOrderId(params.getWOrderId());
            if (CollectionUtils.isNotEmpty(addressList)){
                Set<Long> addressIds = addressList.stream()
                        .map(KwtWaybillOrderAddress::getId)
                        .collect(Collectors.toSet());
                //运单id和地址类型组装key映射地址对象
                Map<String, KwtWaybillOrderAddress> keyAndAddressMap = addressList.stream()
                        .peek(a -> a.setWOrderIdAddressTypeKey(a.getWOrderId() + CommonConstants.UNDERSCORE + a.getAddressType()))
                        .collect(Collectors.toMap(KwtWaybillOrderAddress::getWOrderIdAddressTypeKey, Function.identity(), (k1, k2) -> k1));
                //查询运单状态信息
                //List<KwtWaybillOrderTrack> tracks =  kwtWaybillOrderTrackRepository.queryByAddressIds(addressIds);
                List<KwtWaybillOrderTicket> tracks = kwtWaybillOrderTicketRepository.queryByAddressIds(addressIds);
                //地址id映射运单状态
                Map<Long, KwtWaybillOrderTicket> addressIdAndTrackMap = tracks.stream()
                        .collect(Collectors.toMap(KwtWaybillOrderTicket::getWAddressId, Function.identity(), (k1, k2) -> k1));
                RTruckRouteVo rTruckRouteVo = new RTruckRouteVo();
                rTruckRouteVo.setTruckId(waybillOrder.getTruckId());
                rTruckRouteVo.setTruckNo(waybillOrder.getTruckNo());
                rTruckRouteVo.setDriverId(waybillOrder.getDriverId());
                rTruckRouteVo.setEntId(waybillOrder.getEntId());
                KwtWaybillOrderAddress startPoint = keyAndAddressMap.getOrDefault(wOrderId + CommonConstants.UNDERSCORE + AddressTypeEnum.SHIPMENT.getCode(), new KwtWaybillOrderAddress());
                rTruckRouteVo.setStartPoint(startPoint.getDetailAddress());
                KwtWaybillOrderAddress unloadingPoint = keyAndAddressMap.getOrDefault(wOrderId + CommonConstants.UNDERSCORE + AddressTypeEnum.TAKE.getCode(), new KwtWaybillOrderAddress());
                rTruckRouteVo.setUnloadingPoint(unloadingPoint.getDetailAddress());
                AtomicReference<Date> startTime = new AtomicReference<>();
                AtomicReference<Date> unloadingTime = new AtomicReference<>();
                addressList.forEach(a->{
                    KwtWaybillOrderTicket kwtWaybillOrderTrack = addressIdAndTrackMap.get(a.getId());
                    if (Objects.equals(a.getAddressType(), AddressTypeEnum.SHIPMENT.getCode())){
                        startTime.set(kwtWaybillOrderTrack.getOperateTime());
                    }
                    if (Objects.equals(a.getAddressType(), AddressTypeEnum.TAKE.getCode())){
                        unloadingTime.set(kwtWaybillOrderTrack.getOperateTime());
                    }
                });
                Long shortestTime = DateUtil.getDifferenceInMillis(unloadingTime.get(), startTime.get());
                rTruckRouteVo.setShortestTime(Objects.isNull(shortestTime) ? null: String.valueOf(shortestTime));

                //从中台查询轨迹信息
                VehicleDataDTO vehicleDataDTO = new VehicleDataDTO();
                vehicleDataDTO.setWOrderNo(waybillOrder.getWOrderNo());
                String s = "";
                try {
                    s = HttpUtil.postJson(urlConfigProperties.getApiBaseUrl()+ UrlConstants.QUERY_TRACE_URL, com.alibaba.fastjson.JSON.toJSONString(vehicleDataDTO), null);
                } catch (Exception e) {
                    log.error("查询任务轨迹异常",e);

                }
                if (org.apache.commons.lang3.StringUtils.isNotBlank(s)){
                    List<VehicleRouteData> vehicleReturnData = com.alibaba.fastjson.JSON.parseArray(s, VehicleRouteData.class);
                    rTruckRouteVo.setPointInfo(com.alibaba.fastjson.JSON.toJSONString(vehicleReturnData));
                }

                remoteFleetService.saveOrUpdate(rTruckRouteVo);
            }
        } catch (Exception e) {
            log.error("修改惯用线路异常:",e);
        }
    }

    /**
     * @param params {}
     * @desc 更新榜单信息-单证审核
     * @author zk
     * @date 2024/3/7
     **/
    public void editTicket(WaybillOrderTicketApprovalV2Dto params) {
        //变更榜单信息
        List<WaybillOrderTicketV4Dto> tickets = params.getTickets();
        if (CollectionUtils.isEmpty(tickets)) {
            return;
        }

        for (WaybillOrderTicketV4Dto ticket : tickets) {
            //车辆运单ID
            Long wOrderId = ticket.getWOrderId();

            /*1、更新装卸货榜单信息*/
            //榜单信息
            List<WaybillOrderTicketLoadingDto> loading = ticket.getLoading();
            waybillOrderTicketService.editTicketV1(loading, ticket.getWAddressId(), ticket.getUrls(), ticket.getOperateTime());

            /*2、更新车辆运单-子单*/
            //运单子单信息
            KwtWaybillOrderSubtask orderSubtask = waybillOrderSubtaskDao.selectById(ticket.getWSubtaskId());
            //物流运单信息
            KwtLogisticsOrder logisticsOrder = logisticsOrderDao.selectById(orderSubtask.getLOrderId());
            //运单-子单装货榜单信息
            List<KwtWaybillOrderTicket> loadTickets = waybillOrderTicketDao.findWaybillOrderTicketV1(wOrderId, ticket.getWSubtaskId(), AddressTypeEnum.SHIPMENT.getCode(), orderSubtask.getUnit());
            //运单-子单卸货榜单信息
            List<KwtWaybillOrderTicket> unloadTickets = waybillOrderTicketDao.findWaybillOrderTicketV1(wOrderId, ticket.getWSubtaskId(), AddressTypeEnum.TAKE.getCode(), orderSubtask.getUnit());
            //装货-总量
            BigDecimal loadAmount = loadTickets.stream().map(KwtWaybillOrderTicket::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            //卸货-总量
            BigDecimal unloadAmount = unloadTickets.stream().map(KwtWaybillOrderTicket::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            orderSubtask.setLoadAmount(loadAmount);
            orderSubtask.setUnloadAmount(unloadAmount);
            orderSubtask.setDeficitAmount(orderSubtask.getLoadAmount().subtract(orderSubtask.getUnloadAmount()));
            BigDecimal deficitPrice = deficitPrice(orderSubtask.getLoadAmount(), orderSubtask.getDeficitAmount(),
                    logisticsOrder.getLoss(), logisticsOrder.getLossUnit(), logisticsOrder.getGoodsPrice());
            orderSubtask.setDeficitPrice(deficitPrice);
            waybillOrderSubtaskDao.updateById(orderSubtask);
        }
    }

    /**
     * @param subtasks {}
     * @desc 更新物流订单信息-单证审核
     * @author zk
     * @date 2024/3/7
     **/
    public void editLogisticsOrder(List<KwtWaybillOrderSubtask> subtasks) {
        //数据处理
        for (KwtWaybillOrderSubtask subtask : subtasks) {
            /*1、物流订单信息更新*/
            //物流订单信息
            KwtLogisticsOrder logisticsOrder = logisticsOrderDao.selectById(subtask.getLOrderId());
            //装货统计
            Map<String, Object> queryParams = new HashMap<>(NumberConstant.SIXTEEN);
            queryParams.put("lOrderId", subtask.getLOrderId());
            queryParams.put("unit", logisticsOrder.getUnit());
            queryParams.put("type", NumberConstant.ONE);
            queryParams.put("passStatus", Global.NUMERICAL_ONE);
            WaybillCountVo loadCount = waybillOrderV1Dao.findTicketCountByAddress(queryParams);
            //卸货统计
            queryParams.put("type", NumberConstant.TWO);
            WaybillCountVo unloadCount = waybillOrderV1Dao.findTicketCountByAddress(queryParams);

            //委派量多退少补entrustAmount(委派未运量=运单子单承运委派量-运单子单装货量)
            BigDecimal residue = subtask.getEntrustAmount().subtract(subtask.getLoadAmount());
            logisticsOrder.setEntrustAmount(logisticsOrder.getEntrustAmount().subtract(residue));
            logisticsOrder.setLoadAmount(loadCount.getAmount());
            logisticsOrder.setLoadTime(loadCount.getLoadTime());
            logisticsOrder.setUnloadAmount(unloadCount.getAmount());
            logisticsOrder.setUnloadTime(unloadCount.getUnloadTime());
            logisticsOrder.setDeficitAmount(logisticsOrder.getLoadAmount().subtract(logisticsOrder.getUnloadAmount()));
            BigDecimal deficitPrice = deficitPrice(logisticsOrder.getLoadAmount(), logisticsOrder.getDeficitAmount(),
                    logisticsOrder.getLoss(), logisticsOrder.getLossUnit(), logisticsOrder.getGoodsPrice());
            logisticsOrder.setDeficitPrice(deficitPrice);
            logisticsOrder.setTotalTake(logisticsOrder.getTotalTake() == null ? NumberConstant.ONE : logisticsOrder.getTotalTake() + NumberConstant.ONE);
            logisticsOrderDao.updateById(logisticsOrder);

            /*2、物流订单地址运量信息更新*/
            List<KwtLogisticsOrderAmount> amounts = logisticsOrderAmountDao.findByLOrderId(subtask.getLOrderId());
            for (KwtLogisticsOrderAmount amount : amounts) {
                //物流运单地址信息
                KwtLogisticsOrderAddress address = logisticsOrderAddressDao.selectById(amount.getLAddressId());
                //运单地址进行统计
                queryParams.clear();
                queryParams.put("unit", logisticsOrder.getUnit());
                queryParams.put("lAddressId", amount.getLAddressId());
                queryParams.put("passStatus", Global.NUMERICAL_ONE);
                WaybillCountVo waybillCount = waybillOrderV1Dao.findTicketCountByAddress(queryParams);
                if (address.getAddressType().equals(AddressTypeEnum.SHIPMENT.getCode())) {
                    //计算单个地址需要回退委派量
                    BigDecimal countEntrustAmount = countEntrustAmount(subtask, amount.getLAddressId());
                    amount.setEntrustAmount(amount.getEntrustAmount().subtract(countEntrustAmount));
                    amount.setLoadAmount(waybillCount.getAmount());
                    amount.setLoadTime(waybillCount.getLoadTime() != null ? LocalDateTime.ofInstant(waybillCount.getLoadTime().toInstant(), ZoneId.systemDefault()) : null);
                } else {
                    amount.setUnloadAmount(waybillCount.getAmount());
                    amount.setUnloadTime(waybillCount.getUnloadTime() != null ? LocalDateTime.ofInstant(waybillCount.getUnloadTime().toInstant(), ZoneId.systemDefault()) : null);
                }
                logisticsOrderAmountDao.updateById(amount);
            }

            /*3、物流订单辅助单位信息更新*/
            kwtLogisticsOrderGoodsService.editLogisticsOrderGoodsLoading(logisticsOrder.getId());

            /*4、校验当前承运订单是否运输完成(修改状态+统计量)*/
            editLogisticsTotalCount(logisticsOrder.getId());
        }
    }

    /**
     * @param subtask {}
     * @desc 计算单个地址需要回退委派量-单证审核
     * @author zk
     * @date 2024/3/7
     **/
    public BigDecimal countEntrustAmount(KwtWaybillOrderSubtask subtask, Long lAddressId) {
        List<KwtWaybillOrderAddress> addresses = waybillOrderAddressDao.findByLAddressIds(subtask.getWOrderId(), new ArrayList<>(){{add(lAddressId);}});
        //运单地址进行统计
        Map<String, Object> queryParams = new HashMap<>(NumberConstant.SIXTEEN);
        queryParams.put("wOrderId", subtask.getWOrderId());
        queryParams.put("lAddressId", lAddressId);
        queryParams.put("passStatus", Global.NUMERICAL_ONE);
        queryParams.put("unit", subtask.getUnit());
        WaybillCountVo waybillCount = waybillOrderV1Dao.findTicketCountByAddress(queryParams);
        //地址总委派量
        BigDecimal entrustAmount = addresses.stream().map(KwtWaybillOrderAddress::getEntrustAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        //委派量多退少补entrustAmount(委派未运量=运单子单承运委派量-运单子单装货量)
        return entrustAmount.subtract(waybillCount.getAmount());
    }

    /**
     * @param lOrderId 承运订单ID
     * @desc 校验当前承运订单是否运输完成(修改状态 + 统计量)
     * @author zk
     * @date 2024/3/8
     **/
    public void editLogisticsTotalCount(Long lOrderId) {
        /*1、物流订单信息更新*/
        //物流订单信息
        KwtLogisticsOrder logisticsOrder = logisticsOrderDao.selectById(lOrderId);
        //装货统计(当前物流订单)
        Map<String, Object> queryParams = new HashMap<>(NumberConstant.SIXTEEN);
        queryParams.put("lOrderId", lOrderId);
        queryParams.put("unit", logisticsOrder.getUnit());
        queryParams.put("type", NumberConstant.ONE);
        queryParams.put("passStatus", Global.NUMERICAL_ONE);
        WaybillCountVo loadCount = waybillOrderV1Dao.findTicketCountByAddress(queryParams);
        //卸货统计(当前物流订单)
        queryParams.put("type", NumberConstant.TWO);
        WaybillCountVo unloadCount = waybillOrderV1Dao.findTicketCountByAddress(queryParams);

        //下级物流订单统计
        Map<String, Object> params = new HashMap<>(){{put("upperlOrderId", lOrderId); put("ownOrderId", lOrderId);}};
        List<KwtLogisticsOrder> logisticsOrders = logisticsOrderDao.findLogisticsOrder(params);
        BigDecimal totalLoadAmount = logisticsOrders.stream().map(KwtLogisticsOrder::getTotalLoadAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal totalUnloadAmount = logisticsOrders.stream().map(KwtLogisticsOrder::getTotalUnloadAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        int sum = logisticsOrders.stream().mapToInt(KwtLogisticsOrder::getTotalTake).sum();
        int totalTake = waybillOrderV1Dao.findWaybillOrderCountByLOrderId(lOrderId);
        logisticsOrder.setTotalTake(totalTake + sum);
        logisticsOrder.setTotalLoadAmount(loadCount.getAmount().add(totalLoadAmount));
        logisticsOrder.setTotalUnloadAmount(unloadCount.getAmount().add(totalUnloadAmount));
        logisticsOrderDao.updateById(logisticsOrder);

        /*2、物流订单地址运量信息更新*/
        List<KwtLogisticsOrderAmount> amounts = logisticsOrderAmountDao.findByLOrderId(lOrderId);
        for (KwtLogisticsOrderAmount amount : amounts) {
            //物流运单地址信息
            KwtLogisticsOrderAddress address = logisticsOrderAddressDao.selectById(amount.getLAddressId());
            //运单地址进行统计
            BigDecimal totalAmount = waybillOrderTicketService.getAmount(amount.getLAddressId(), logisticsOrder.getUnit(), address.getAddressType());

            if (address.getAddressType().equals(AddressTypeEnum.SHIPMENT.getCode())) {
                amount.setTotalLoadAmount(totalAmount);
            } else {
                amount.setTotalUnloadAmount(totalAmount);
            }
            logisticsOrderAmountDao.updateById(amount);
        }

        /*3、物流订单辅助单位信息更新*/
        kwtLogisticsOrderGoodsService.editLogisticsOrderGoodsTotalLoading(logisticsOrder.getId());

        /*4、递归处理上级物流订单*/
        //获取所有上级物流订单ID
        String pids = logisticsOrder.getPids();
        if (StringUtils.isNotBlank(pids)) {
            String[] idArray = pids.split(Global.COMMA);
            for (String id : idArray) {
                Long pid = Long.parseLong(id);
                //当前物流订单ID除外
                if (!pid.equals(lOrderId)) {
                    /*校验当前承运订单是否运输完成*/
                    editLogisticsTotalCount(pid);
                }
            }
        }
    }

    /**
     * @param wOrderId 运单ID
     * @desc 修改单证查询运单
     * @author zk
     * @date 2024/3/11
     **/
    public HttpResult ticketApproval(Long wOrderId) {
        //车辆运单信息
        KwtWaybillOrderV1 waybillOrder = waybillOrderV1Dao.selectById(wOrderId);
        if (waybillOrder == null) {
            return HttpResult.ok("车辆运单信息不存在！");
        }

        //操作人
        List<KwtWaybillOrderTicket> tickets = waybillOrderTicketDao.findWaybillOrderTicket(wOrderId, null, null);
        List<Long> userIds = tickets.stream().flatMap(item -> Stream.of(item.getCreateBy(), item.getUpdateBy())).toList();
        List<UserCacheResDto> users = remoteSystemService.queryUserCacheByIds(userIds);
        Map<Long, UserCacheResDto> usersMap = new HashMap<>(Global.NUMERICAL_SIXTEEN);
        users.forEach(e -> usersMap.put(e.getId(), e));
        //单位
        Map<String, Map<String, String>> dict = remoteSystemService.queryDictByType(List.of(DictTypeEnum.UNIT_TYPE.getType()));
        Map<String, String> unitMap = CollectionUtils.isNotEmpty(dict) ? dict.get(DictTypeEnum.UNIT_TYPE.getType()) : new HashMap<>(NumberConstant.SIXTEEN);

        /*数据处理*/
        List<Map<String, Object>> addressList = new ArrayList<>();
        List<Integer> typeList = new ArrayList<>() {{
            add(AddressTypeEnum.SHIPMENT.getCode());
            add(AddressTypeEnum.TAKE.getCode());
        }};
        for (Integer type : typeList) {
            //装货地址
            List<KwtWaybillOrderAddress> addresses = waybillOrderAddressDao.findByAddresses(wOrderId, type);
            for (KwtWaybillOrderAddress address : addresses) {
                //子单信息
                KwtWaybillOrderSubtask subtask = waybillOrderSubtaskDao.selectById(address.getWSubtaskId());
                //物流订单商品信息
                KwtLogisticsOrderGoods goods = logisticsOrderGoodsDao.findByGoods(subtask != null ? subtask.getLOrderId() : null);
                //榜单信息
                KwtWaybillOrderTicket ticket = waybillOrderTicketDao.findWaybillOrderTicketV2(address.getId(), subtask.getUnit());
                //辅助单位
                List<WaybillOrderLoadingVO> loading = waybillOrderTicketService.agreementV1(subtask, address.getId());
                Map<String, Object> trackData = new HashMap<>(NumberConstant.SIXTEEN);
                trackData.put("wTicketId", ticket != null ? ticket.getId() : null);
                trackData.put("wOrderId", ticket != null ? ticket.getWOrderId() : null);
                trackData.put("wSubtaskId", subtask.getId());
                trackData.put("wAddressId", address.getId());
                trackData.put("addressType", address.getAddressType());
                trackData.put("urls", ticket != null ? FileUtils.spliceBatch(ticket.getUrls()) : null);
                trackData.put("operateTime", ticket != null ? DateUtil.dateTimeFormatter(ticket.getOperateTime()) : null);
                trackData.put("createTime", ticket != null ? DateUtil.dateTimeFormatter(ticket.getCreateTime()) : null);
                trackData.put("approvalStatus", ticket != null ? ticket.getStatus() : null);
                trackData.put("approvalStatusName", ticket != null ? ApproveStatusEnum.getName(ticket.getStatus()) : null);
                trackData.put("approvalByName", ticket != null && ticket.getStatus() != Global.NUMERICAL_ZERO ? usersMap.get(ticket.getUpdateBy()) != null ? usersMap.get(ticket.getUpdateBy()).getName() : null : null);
                trackData.put("approvalContent", ticket != null && ticket.getStatus() != Global.NUMERICAL_ZERO ? ticket.getRemark() : null);
                trackData.put("approvalTime", ticket != null && ticket.getStatus() != Global.NUMERICAL_ZERO ? ticket.getUpdateTime() : null);
                trackData.put("createByName", ticket != null ? usersMap.get(ticket.getCreateBy()) == null ? waybillOrder.getDriverName() : usersMap.get(ticket.getCreateBy()).getName() : null);
                trackData.put("addressName", address.getName());
                trackData.put("addressCityName", address.getCityName());
                trackData.put("addressDetail", address.getDetailAddress());
                trackData.put("goodsName", goods != null ? goods.getGoodsName() : null);
                trackData.put("unit", subtask.getUnit());
                trackData.put("unitName", unitMap.get(subtask.getUnit()));
                trackData.put("entrustAmount", address.getEntrustAmount());
                trackData.put("loading", loading);
                addressList.add(trackData);
            }
        }

        //数据组装
        Map<String, Object> result = new HashMap<>(Global.NUMERICAL_SIXTEEN);
        result.put("wOrderId", wOrderId);
        result.put("wOrderNo", waybillOrder.getWOrderNo());
        result.put("status", waybillOrder.getStatus());
        result.put("statusName", CarWaybillEnum.getName(waybillOrder.getStatus()));
        result.put("truckNo", waybillOrder.getTruckNo());
        result.put("driverName", waybillOrder.getDriverName());
        result.put("driverPhone", waybillOrder.getDriverPhone());
        result.put("driverIdcard", waybillOrder.getDriverIdcard());
        result.put("createTime", waybillOrder.getCreateTime());
        result.put("addresses", addressList);
        return HttpResult.ok(result);
    }

    /**
     * @param wAddressId 运单地址ID
     * @desc 运单单证信息
     * @author zk
     * @date 2024/3/11
     **/
    public HttpResult ticketInfo(Long wAddressId) {
        //运单地址信息
        KwtWaybillOrderAddress address = waybillOrderAddressDao.selectById(wAddressId);
        if (address == null) {
            return HttpResult.ok("车辆运单地址信息不存在！");
        }
        //车辆运单信息
        Long wOrderId = address.getWOrderId();
        KwtWaybillOrderV1 waybillOrder = waybillOrderV1Dao.selectById(wOrderId);
        if (waybillOrder == null) {
            return HttpResult.ok("车辆运单信息不存在！");
        }

        //操作人
        List<KwtWaybillOrderTicket> tickets = waybillOrderTicketDao.findWaybillOrderTicket(wOrderId, null, null);
        List<Long> userIds = tickets.stream().map(KwtWaybillOrderTicket::getCreateBy).toList();
        List<UserCacheResDto> users = remoteSystemService.queryUserCacheByIds(userIds);
        Map<Long, UserCacheResDto> usersMap = new HashMap<>(Global.NUMERICAL_SIXTEEN);
        users.forEach(e -> usersMap.put(e.getId(), e));
        //单位
        Map<String, Map<String, String>> dict = remoteSystemService.queryDictByType(List.of(DictTypeEnum.UNIT_TYPE.getType()));
        Map<String, String> unitMap = CollectionUtils.isNotEmpty(dict) ? dict.get(DictTypeEnum.UNIT_TYPE.getType()) : new HashMap<>(NumberConstant.SIXTEEN);

        //子单信息
        KwtWaybillOrderSubtask subtask = waybillOrderSubtaskDao.selectById(address.getWSubtaskId());
        //物流订单商品信息
        KwtLogisticsOrderGoods goods = logisticsOrderGoodsDao.findByGoods(subtask != null ? subtask.getLOrderId() : null);
        //榜单信息
        KwtWaybillOrderTicket ticket = waybillOrderTicketDao.findWaybillOrderTicketV2(address.getId(), subtask.getUnit());
        //辅助单位
        List<WaybillOrderLoadingVO> loading = waybillOrderTicketService.agreementV1(subtask, address.getId());
        //辅助单位
        List<GoodsUnitVo> assistUnit = kwtLogisticsOrderGoodsService.assistUnit(subtask.getLOrderId());

        //数据组装
        Map<String, Object> result = new HashMap<>(Global.NUMERICAL_SIXTEEN);
        result.put("wOrderId", wOrderId);
        result.put("wOrderNo", waybillOrder.getWOrderNo());
        result.put("status", waybillOrder.getStatus());
        result.put("statusName", CarWaybillEnum.getName(waybillOrder.getStatus()));
        result.put("truckNo", waybillOrder.getTruckNo());
        result.put("driverName", waybillOrder.getDriverName());
        result.put("driverPhone", waybillOrder.getDriverPhone());
        result.put("driverIdcard", waybillOrder.getDriverIdcard());
        result.put("wTicketId", ticket != null ? ticket.getId() : null);
        result.put("wSubtaskId", subtask.getId());
        result.put("wAddressId", address.getId());
        result.put("urls", ticket != null ? FileUtils.spliceBatch(ticket.getUrls()) : null);
        result.put("operateTime", ticket != null ? DateUtil.dateTimeFormatter(ticket.getOperateTime()) : null);
        result.put("approvalStatus", ticket != null ? ticket.getStatus() : null);
        result.put("createByName", ticket != null ? usersMap.get(ticket.getCreateBy()) == null ? waybillOrder.getDriverName() : usersMap.get(ticket.getCreateBy()).getName() : null);
        result.put("createTime", ticket != null ? ticket.getCreateTime() : null);
        result.put("addressName", address.getName());
        result.put("addressCityName", address.getCityName());
        result.put("addressDetail", address.getDetailAddress());
        result.put("goodsName", goods != null ? goods.getGoodsName() : null);
        result.put("unit", subtask.getUnit());
        result.put("unitName", unitMap.get(subtask.getUnit()));
        result.put("amount", ticket != null ? ticket.getAmount() : null);
        result.put("entrustAmount", address.getEntrustAmount());
        result.put("loading", loading);
        result.put("assistUnit", assistUnit);
        return HttpResult.ok(result);
    }

    /**
     * @param wOrderId 运单ID
     * @desc 修改单证查询运单
     * @author zk
     * @date 2024/3/11
     **/
    public HttpResult ticketWaybillOrder(Long wOrderId) {
        //车辆运单信息
        KwtWaybillOrderV1 waybillOrder = waybillOrderV1Dao.selectById(wOrderId);
        if (waybillOrder == null) {
            return HttpResult.ok("车辆运单信息不存在！");
        }
        //运单状态
        List<KwtWaybillOrderTrack> tracks = waybillOrderTrackDao.findTrack(wOrderId, null, null, null);
        //操作人
        List<Long> userIds = tracks.stream().map(KwtWaybillOrderTrack::getCreateBy).toList();
        List<UserCacheResDto> users = remoteSystemService.queryUserCacheByIds(userIds);
        Map<Long, UserCacheResDto> usersMap = new HashMap<>(Global.NUMERICAL_SIXTEEN);
        users.forEach(e -> usersMap.put(e.getId(), e));
        //单位
        Map<String, Map<String, String>> dict = remoteSystemService.queryDictByType(List.of(DictTypeEnum.UNIT_TYPE.getType()));
        Map<String, String> unitMap = CollectionUtils.isNotEmpty(dict) ? dict.get(DictTypeEnum.UNIT_TYPE.getType()) : new HashMap<>(NumberConstant.SIXTEEN);

        /*数据处理*/
        List<Map<String, Object>> trackList = new ArrayList<>();
        //运单状态(待接单、待出车、出车)
        List<Integer> statusList = CarWaybillEnum.initWaybillStatusV1();
        for (Integer status : statusList) {
            KwtWaybillOrderTrack track = waybillOrderTrackDao.findWaybillOrderTrack(wOrderId, null, null, status);
            Map<String, Object> trackData = new HashMap<>(NumberConstant.SIXTEEN);
            trackData.put("id", track != null ? track.getId() : null);
            trackData.put("wOrderId", wOrderId);
            trackData.put("wSubtaskId", track != null ? track.getWSubtaskId() : null);
            trackData.put("wAddressId", track != null ? track.getWAddressId() : null);
            trackData.put("operateTime", track != null ? DateUtils.format(track.getOperateTime(), DateUtils.FORMAT11) : null);
            trackData.put("operateStatus", track != null);
            trackData.put("createTime", track != null ? track.getCreateTime() : null);
            trackData.put("createByName", track != null ? usersMap.get(track.getCreateBy()) == null ? waybillOrder.getDriverName() : usersMap.get(track.getCreateBy()).getName() : null);
            trackData.put("status", status);
            trackData.put("statusName", CarWaybillEnum.getAlias(status));
            trackList.add(trackData);
        }

        //运单状态处理(到达装货点、已装货、到达卸货点、已卸货)
        List<KwtWaybillOrderAddress> addresses = waybillOrderAddressDao.findByAddresses(wOrderId, null);
        for (KwtWaybillOrderAddress address : addresses) {
            if (address.getAddressType().equals(AddressTypeEnum.SHIPMENT.getCode())) {
                statusList = new ArrayList<>() {{
                    add(CarWaybillEnum.WAIT_LOADING.getCode());
                    add(CarWaybillEnum.COMPLETION_LOADING.getCode());
                }};
            } else {
                statusList = new ArrayList<>() {{
                    add(CarWaybillEnum.WAIT_UNLOADING.getCode());
                    add(CarWaybillEnum.COMPLETION_UNLOADING.getCode());
                }};
            }

            //子单信息
            KwtWaybillOrderSubtask subtask = waybillOrderSubtaskDao.selectById(address.getWSubtaskId());
            //物流订单商品信息
            KwtLogisticsOrderGoods goods = logisticsOrderGoodsDao.findByGoods(subtask != null ? subtask.getLOrderId() : null);
            for (Integer status : statusList) {
                //状态记录
                KwtWaybillOrderTrack track = waybillOrderTrackDao.findWaybillOrderTrack(wOrderId, subtask.getId(), address.getId(), status);
                //辅助单位
                List<WaybillOrderLoadingVO> loading = track != null ? waybillOrderTicketService.agreementV1(subtask, track.getWAddressId()) : null;
                //辅助单位
                List<GoodsUnitVo> assistUnit = kwtLogisticsOrderGoodsService.assistUnit(subtask.getLOrderId());
                Map<String, Object> trackData = new HashMap<>(NumberConstant.SIXTEEN);
                trackData.put("id", track != null ? track.getId() : null);
                trackData.put("wOrderId", address.getWOrderId());
                trackData.put("wSubtaskId", address.getWSubtaskId());
                trackData.put("wAddressId", address.getId());
                trackData.put("operateTime", track != null ? DateUtils.format(track.getOperateTime(), DateUtils.FORMAT11) : null);
                trackData.put("operateStatus", track != null);
                trackData.put("createTime", track != null ? track.getCreateTime() : null);
                trackData.put("createByName", track != null ? usersMap.get(track.getCreateBy()) == null ? waybillOrder.getDriverName() : usersMap.get(track.getCreateBy()).getName() : null);
                trackData.put("status", status);
                trackData.put("statusName", CarWaybillEnum.getName(status));
                trackData.put("planTime", track != null ? address.getPlanTime() : null);
                trackData.put("entrustAmount", track != null ? address.getEntrustAmount() : null);
                trackData.put("unit", subtask.getUnit());
                trackData.put("unitName", unitMap.get(subtask.getUnit()));
                trackData.put("goodsName", goods != null ? goods.getGoodsName() : null);
                trackData.put("addressName", address.getName());
                trackData.put("addressCityName", address.getCityName());
                trackData.put("addressDetail", address.getDetailAddress());
                trackData.put("loading", loading);
                trackData.put("assistUnit", assistUnit);
                trackList.add(trackData);
            }
        }

        //数据组装
        Map<String, Object> result = new HashMap<>(Global.NUMERICAL_SIXTEEN);
        result.put("wOrderId", wOrderId);
        result.put("wOrderNo", waybillOrder.getWOrderNo());
        result.put("status", waybillOrder.getStatus());
        result.put("statusName", CarWaybillEnum.getName(waybillOrder.getStatus()));
        result.put("truckNo", waybillOrder.getTruckNo());
        result.put("driverName", waybillOrder.getDriverName());
        result.put("driverPhone", waybillOrder.getDriverPhone());
        result.put("driverIdcard", waybillOrder.getDriverIdcard());
        result.put("createTime", waybillOrder.getCreateTime());
        result.put("trackList", trackList);
        return HttpResult.ok(result);
    }

    /**
     * @param wOrderId 运单ID
     * @desc 变更车辆/司机查询
     * @author zk
     * @date 2023/8/2
     **/
    public HttpResult changeWaybillOrder(@RequestParam("wOrderId") Long wOrderId) {
        //车辆运单信息
        KwtWaybillOrderV1 waybillOrder = waybillOrderV1Dao.selectById(wOrderId);
        if (waybillOrder == null) {
            return HttpResult.error("车辆运单不存在！");
        }

        //数据组装
        Map<String, Object> result = new HashMap<>(NumberConstant.SIXTEEN);
        result.put("id", wOrderId);
        result.put("wOrderId", wOrderId);
        result.put("wOrderNo", waybillOrder.getWOrderNo());
        result.put("statusName", CarWaybillEnum.getName(waybillOrder.getStatus()));
        result.put("truckNo", waybillOrder.getTruckNo());
        result.put("truckId", waybillOrder.getTruckId());
        result.put("driverId", waybillOrder.getDriverId());
        result.put("driverPhone", waybillOrder.getDriverPhone());
        result.put("driverIdcard", waybillOrder.getDriverIdcard());
        result.put("driverName", waybillOrder.getDriverName());
        RTruckVo truck = remoteFleetService.findTruck(waybillOrder.getTruckId());
        result.put("trailerNo", truck != null ? truck.getTrailerNo() : null);
        return HttpResult.ok(result);
    }

    /**
     * @param params 参数
     * @desc 变更司机
     * @author zk
     * @date 2023/8/2
     **/
    public HttpResult changeDriver(@RequestBody @Valid ChangeDriverDto params) {
        /*数据校验*/
        //车辆运单信息
        KwtWaybillOrderV1 waybillOrder = waybillOrderV1Dao.selectById(params.getWOrderId());
        if (waybillOrder == null) {
            return HttpResult.error("车辆运单不存在！");
        }
        if (!CarWaybillEnum.changeDriver(waybillOrder.getStatus())) {
            return HttpResult.error("车辆运单当前状态不能变更司机！");
        }

        /*更新车辆运单**/
        changeWaybillOrder(params, null);
        return HttpResult.ok("更换司机成功！");
    }

    /**
     * @param params 参数
     * @desc 变更车辆
     * @author zk
     * @date 2023/8/2
     **/
    public HttpResult changeTruck(@RequestBody @Valid ChangeTruckDto params) {
        /*数据校验**/
        SckwWaybillOrder wOrder = new SckwWaybillOrder();
        //车辆运单信息
        KwtWaybillOrderV1 waybillOrder = waybillOrderV1Dao.selectById(params.getWOrderId());
        if (waybillOrder == null) {
            return HttpResult.error("车辆运单不存在！");
        }
        if (!CarWaybillEnum.changeTruck(waybillOrder.getStatus())) {
            return HttpResult.error("车辆运单当前状态不能变更车辆！");
        }

        /*更新车辆运单**/
        changeWaybillOrder(null, params);
        return HttpResult.ok("更换车辆成功！");
    }

    /**
     * @param driver 司机信息
     * @param truck  车辆信息
     * @desc 更新车辆运单信息
     * @author zk
     * @date 2023/8/2
     **/
    public void changeWaybillOrder(ChangeDriverDto driver, ChangeTruckDto truck) {
        //车辆运单信息
        KwtWaybillOrderV1 waybillOrder = new KwtWaybillOrderV1();
        if (driver != null) {
            waybillOrder.setId(driver.getWOrderId());
            waybillOrder.setDriverId(driver.getDriverId());
            waybillOrder.setDriverPhone(driver.getDriverPhone());
            waybillOrder.setDriverName(driver.getDriverName());
            waybillOrder.setDriverIdcard(driver.getDriverIdcard());
        }
        if (truck != null) {
            waybillOrder.setId(truck.getWOrderId());
            waybillOrder.setTruckId(truck.getTruckId());
            waybillOrder.setTruckNo(truck.getTruckNo());
        }
        waybillOrderV1Dao.updateById(waybillOrder);
    }

    /**
     * @param driverId 司机档案ID
     * @desc 更新司机信息
     * @author zk
     * @date 2023/8/3
     **/
    public void editDriver(Long driverId) {
        //数据统计
        WaybillCountVo countVo = waybillOrderV1Dao.findCountByDriverOrTruck(driverId, null);
        WaybillCountVo amountVo = waybillOrderV1Dao.findAmountByDriverOrTruck(driverId, null);
        RDriverVo driver = new RDriverVo();
        driver.setId(driverId);
        driver.setTotalComplete(countVo.getTotalComplete());
        driver.setTotalTake(countVo.getTotalTake());
        driver.setTotalWeight(amountVo.getLoadAmount());
        driver.setBusinessStatus(countVo.getTotalExecute() > 0 ? 1 : 0);
        remoteFleetService.updateById(driver);
    }

    /**
     * @param truckId 车辆档案ID
     * @desc 更新车辆信息
     * @author zk
     * @date 2023/8/3
     **/
    public void editTruck(Long truckId) {
        //数据统计
        WaybillCountVo countVo = waybillOrderV1Dao.findCountByDriverOrTruck(null, truckId);
        WaybillCountVo amountVo = waybillOrderV1Dao.findAmountByDriverOrTruck(null, truckId);
        RTruckVo truck = new RTruckVo();
        truck.setId(truckId);
        truck.setTotalComplete(countVo.getTotalComplete());
        truck.setTotalTake(countVo.getTotalTake());
        truck.setTotalWeight(amountVo.getLoadAmount());
        truck.setBusinessStatus(countVo.getTotalExecute() > 0 ? 1 : 0);
        remoteFleetService.updateById(truck);
    }

    /**
     * @param type  字典类型
     * @param value 字典值
     * @desc 获取数据字典值
     * @author zk
     * @date 2023/8/30
     **/
    public String getDictValue(String type, String value) {
        if (StringUtils.isBlank(type) || StringUtils.isBlank(value)) {
            return null;
        }
        List<String> dictKey = new ArrayList<>() {{
            add(type + Global.POUND + value);
        }};
        Map<String, SysDictResDto> dicts = remoteSystemService.queryDictMapByTypeValues(String.join(Global.COMMA, dictKey));
        SysDictResDto dict = dicts == null ? null : dicts.get(DictTypeEnum.APPROVED_DRIVING.getType() + Global.POUND + value);
        return dict != null ? dict.getLabel() : null;
    }

    /**
     * @param dictKey 字典值
     * @desc 获取数据字典
     * @author zk
     * @date 2023/9/11
     **/
    public Map<String, SysDictResDto> dict(List<String> dictKey) {
        if (CollectionUtils.isEmpty(dictKey)) {
            return Collections.emptyMap();
        }
        dictKey = dictKey.stream().distinct().collect(Collectors.toList());
        return remoteSystemService.queryDictMapByTypeValues(String.join(Global.COMMA, dictKey));
    }

    /**
     * @param loadAmount    装货量
     * @param deficitAmount 亏吨量
     * @param loss          合理损耗
     * @param goodsPrice    货值单价
     * @desc 计算亏吨扣款
     * @author zk
     * @date 2023/7/27
     **/
    public static BigDecimal deficitPrice(BigDecimal loadAmount, BigDecimal deficitAmount, BigDecimal loss,
                                          String lossUnit, BigDecimal goodsPrice) {
        //亏吨<=0
        if (deficitAmount == null || deficitAmount.doubleValue() <= 0) {
            return new BigDecimal(Global.AMOUNT);
        }
        //承运订单亏吨扣款=（承运订单亏吨量 -（承运订单装货量 * 承运订单合理损耗））* 扣亏货值
        loss = loss == null ? new BigDecimal(Global.AMOUNT) : loss;
        if (loss.doubleValue() > 0 && StringUtils.isNotBlank(lossUnit)) {
            if (lossUnit.equals(String.valueOf(TaxRateTypeEnum.PERCENT.getCode()))) {
                loss = loss.divide(new BigDecimal(TaxRateTypeEnum.PERCENT.getValue()));
            }
            if (lossUnit.equals(String.valueOf(TaxRateTypeEnum.MILLIMETER.getCode()))) {
                loss = loss.divide(new BigDecimal(TaxRateTypeEnum.MILLIMETER.getValue()));
            }
        }

        goodsPrice = goodsPrice == null ? new BigDecimal(Global.AMOUNT) : goodsPrice;
        BigDecimal deficitLossAmount = deficitAmount.subtract(loadAmount.multiply(loss).setScale(2, RoundingMode.HALF_UP));
        //扣亏量=亏吨量-合理损耗值【要求大于0，如果小于0则扣亏货量取0】
        if (deficitLossAmount.doubleValue() <= 0) {
            return new BigDecimal(Global.AMOUNT);
        }
        //罚款值=扣亏量 * 扣亏货值
        return deficitLossAmount.multiply(goodsPrice).setScale(4, RoundingMode.HALF_UP);
    }

    /**
     * @param params
     * @desc 订单信息
     * @author zk
     * @date 2024/3/13
     **/
    public WaybillOrderDetailVo queryBillOrderInfo(WaybillOrderRequest params) {
        if (params.getOrderId() == null) {
            throw new RuntimeException("运单号id不能为空");
        }
        //运单信息
        KwtWaybillOrderV1 waybillOrder = waybillOrderV1Dao.selectById(params.getOrderId());
        if (waybillOrder == null) {
            throw new RuntimeException("运单" + params.getOrderId() + "不存在，请确认！");
        }
        WaybillOrderDetailVo orderDetailVo = new WaybillOrderDetailVo();
        //车队车辆映射关系
        RFleetDriverVo fleetByDriveId = remoteFleetService.findFleetByDriveId(waybillOrder.getDriverId());
        if  (fleetByDriveId == null) {
            throw new RuntimeException("运单:" + params.getOrderId() + ", 车辆信息不存在，请确认！");
        }

        //查询车辆信息
        RFleetVo fleetVO = remoteFleetService.findFleetById(fleetByDriveId.getFleetId());
        orderDetailVo.setDriverId(waybillOrder.getDriverId());
        orderDetailVo.setDriverName(waybillOrder.getDriverName());
        orderDetailVo.setTruckNo(waybillOrder.getTruckNo());
        orderDetailVo.setFleetId(fleetByDriveId.getFleetId());
        orderDetailVo.setFleetName(Optional.ofNullable(fleetVO).map(RFleetVo::getName).orElse(""));

        //查询企业信息
        KwsEnterpriseResDto entCacheResDto = remoteSystemService.queryEnterpriseByEntId(waybillOrder.getEntId());
        orderDetailVo.setEntId(waybillOrder.getEntId());
        orderDetailVo.setEntName(Optional.ofNullable(entCacheResDto).map(KwsEnterpriseResDto::getFirmName).orElse(""));

        //查询位置信息
        List<KwtWaybillOrderAddress> orderAddresses = waybillOrderAddressRepository.queryBywOrderIds(Arrays.asList(waybillOrder.getId()));
        if (CollectionUtils.isEmpty(orderAddresses)) {
            throw new RuntimeException("运单:" + params.getOrderId() + ", 地址信息不存在，请确认！");
        }

        Map<Integer, String> addressNameMap = orderAddresses.stream()
                .filter(address -> address.getAddressType() != null && (address.getAddressType() == 1 || address.getAddressType() == 2))
                .collect(Collectors.groupingBy(
                        KwtWaybillOrderAddress::getAddressType,
                        Collectors.collectingAndThen(
                                Collectors.mapping(KwtWaybillOrderAddress::getName, Collectors.toList()),
                                list -> list.isEmpty() ? "" : list.get(0)
                        )
                ));
        orderDetailVo.setAddresses(addressNameMap);

        return orderDetailVo;
    }

    public PageDataResult<WaybillOrderResp> findBillOrderListPage(WaybillOrderReq req) {
        log.info("查询订单列表请求阐述：{}",JSON.toJSONString( req));
        Integer status = org.apache.commons.lang3.StringUtils.isNoneBlank(req.getStatus()) ?
                Integer.parseInt(req.getStatus()) : null;
        Set<Long> allEnt = getAllEnt(req);
        //物流订单号集合
        Set<Long> logOrderIds = getLogOrderIds(req);
        boolean b1 = !org.apache.commons.lang3.StringUtils.isAllBlank(req.getLogisticsOrderNo(), req.getGoodsName(),
                req.getCarrierId(), req.getConsignorId());
        if(org.apache.commons.collections4.CollectionUtils.isEmpty(logOrderIds) && b1){
            return PageDataResult.empty(req.getPageNum(), req.getPageSize());
        }

        //查询运单信息
        //运单id集合
        Set<Long> billOrderIds = getBillOrderIds(req);
        boolean b = Stream.of(req.getWaybillNo(), req.getTruckNo(), req.getDriverName(), req.getPhone(),
                        req.getLoadStartTime(),req.getLoadEndTime(),req.getUnloadStartTime(),req.getUnloadEndTime())
                        .anyMatch(StringUtils::isNotBlank);
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(billOrderIds) && b){
            return PageDataResult.empty(req.getPageNum(), req.getPageSize());
        }

        IPage<KwtWaybillOrderSubtask> page = waybillOrderSubtaskRepository.queryByPage(allEnt ,logOrderIds,
                billOrderIds,status, req.getPageNum(), req.getPageSize());
        List<KwtWaybillOrderSubtask> records = page.getRecords();
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(records)){
            return PageDataResult.empty(req.getPageNum(), req.getPageSize());
        }
        //运单id集合
        Set<Long> wayBillOrderIds = Sets.newHashSet();
        //物流订单id集合
        Set<Long> logicsOrderIds = Sets.newHashSet();
        //子运单id集合
        Set<Long> subWayBillOrderIds = Sets.newHashSet();
        records.forEach(x->{
            wayBillOrderIds.add(x.getWOrderId());
            logicsOrderIds.add(x.getLOrderId());
            subWayBillOrderIds.add(x.getId());
        });

        //查询主运单信息
        Map<Long, KwtWaybillOrder> waybillOrderIdAndBillOrderMap = getLongKwtWaybillOrderMap(wayBillOrderIds);
        //查询承运托运单位信息
        Map<String, KwtLogisticsOrderUnit> logOrderIdUnitTypeKeyAndUnitMap = getStringKwtLogisticsOrderUnitMap(new ArrayList<>(logicsOrderIds));

        //查询装卸货地址
        List<KwtWaybillOrderAddress> orderAddresses = waybillOrderAddressRepository.queryBySubBillOrderId(subWayBillOrderIds);
        Map<String, KwtWaybillOrderAddress> subOrderIdAddressTypeKeyAndAddressMap = Maps.newHashMap();
        Set<Long> addressIds = Sets.newHashSet() ;
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(orderAddresses)){
             subOrderIdAddressTypeKeyAndAddressMap =
                    orderAddresses.stream().peek(x -> x.setSubOrderIdAddressTypeKey(x.getWSubtaskId() + "-" + x.getAddressType()))
                    .collect(Collectors.toMap(KwtWaybillOrderAddress::getSubOrderIdAddressTypeKey, Function.identity()
                            , (k1, k2) -> k1));
            addressIds =
                    orderAddresses.stream().map(KwtWaybillOrderAddress::getId).collect(Collectors.toSet());
        }

        // 查询运单相关的装卸货时间信息
        Map<String, KwtWaybillOrderTicket> subBillIdAddressIdKeyAndOrderTrackMap = getStringKwtWaybillOrderTrackMap(addressIds);

        //更具物流订单查询商品
        List<KwtLogisticsOrderGoods> logisticsOrderGoods =
                kwtLogisticsOrderGoodsRepository.queryByLogOrderIds(new ArrayList<>(logicsOrderIds));
        Map<Long, KwtLogisticsOrderGoods> logOrderIdAndGoodsIdMap = Maps.newHashMap();
        List<Long> goodsIds = Lists.newArrayList() ;
        if (CollectionUtils.isNotEmpty(logisticsOrderGoods)){
            goodsIds = logisticsOrderGoods.stream()
                    .map(KwtLogisticsOrderGoods::getGoodsId).distinct().collect(Collectors.toList());
            logOrderIdAndGoodsIdMap =
                    logisticsOrderGoods.stream().collect(Collectors.toMap(KwtLogisticsOrderGoods::getLOrderId,
                            Function.identity(),
                    (k1, k2) -> k1));
        }
        //查询商品信息
        Map<Long, KwpGoods> kwpGoodsMap = goodsInfoService.getGoodsByIds(goodsIds);

        //查询订单信息
        List<KwtLogisticsOrder> kwtLogisticsOrders = kwtLogisticsOrderRepository.queryByLogisticsOrderIds(new ArrayList<>(logicsOrderIds));
        Map<Long, KwtLogisticsOrder> logIdAndOrderMap =  Maps.newHashMap();
        if (CollectionUtils.isNotEmpty(kwtLogisticsOrders)){
           logIdAndOrderMap = kwtLogisticsOrders.stream()
                   .collect(Collectors.toMap(KwtLogisticsOrder::getId,
                             Function.identity(), (k1,
                                                                                                                                                        k2) -> k1));
        }
        Map<String, KwtWaybillOrderAddress> finalSubOrderIdAddressTypeKeyAndAddressMap = subOrderIdAddressTypeKeyAndAddressMap;
        Map<Long, KwtLogisticsOrderGoods> finalLogOrderIdAndGoodsIdMap = logOrderIdAndGoodsIdMap;
        Map<Long, KwtLogisticsOrder> finalLogIdAndOrderMap = logIdAndOrderMap;
        List<WaybillOrderResp> resps = records.stream()
                .map(record -> getWaybillOrderResp(record, waybillOrderIdAndBillOrderMap,
                        logOrderIdUnitTypeKeyAndUnitMap, finalLogOrderIdAndGoodsIdMap, kwpGoodsMap, finalSubOrderIdAddressTypeKeyAndAddressMap, subBillIdAddressIdKeyAndOrderTrackMap, finalLogIdAndOrderMap))
                .collect(Collectors.toList());

        return PageDataResult.of(page,resps);
    }

    @NotNull
    private Map<Long, KwtWaybillOrder> getLongKwtWaybillOrderMap(Set<Long> wayBillOrderIds) {
        List<KwtWaybillOrder> waybillOrders = kwtWaybillOrderRepository.queryByBillOrderIds(wayBillOrderIds);
        Map<Long, KwtWaybillOrder> waybillOrderIdAndBillOrderMap = Maps.newHashMap();
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(waybillOrders)){
            waybillOrderIdAndBillOrderMap = waybillOrders.stream()
                    .collect(Collectors.toMap(KwtWaybillOrder::getId, Function.identity(), (k1, k2) -> k1));
        }
        return waybillOrderIdAndBillOrderMap;
    }
    @NotNull
    private Set<Long> getAllEnt(WaybillOrderReq req) {
        Set<Long> allEnt = Sets.newHashSet();
        //根据企业类型查询企业
        if (StringUtils.isBlank(req.getEntId())){
            req.setEntId(String.valueOf(LoginUserHolder.getEntId()));
        }

        if (StringUtils.isBlank(req.getEntId())){
            return allEnt;
        }
        allEnt.add( Long.parseLong(req.getEntId()));
        EntCacheResDto entCacheResDto = remoteSystemService.queryEntTreeById(Long.parseLong(req.getEntId()));
        if (Objects.nonNull(entCacheResDto)) {
            EntCacheResDto entCacheResDto1 = remoteSystemService.queryEntTreeById(entCacheResDto.getId());
            List<EntCacheResDto> child = entCacheResDto1.getChild();
            if (CollectionUtils.isNotEmpty(child)) {
                allEnt.addAll(child.stream()
                        .map(EntCacheResDto::getId).toList());
            }
        }
        return allEnt;
    }

    @NotNull
    private Map<String, KwtLogisticsOrderUnit> getStringKwtLogisticsOrderUnitMap(List<Long> logicsOrderIds) {
        List<KwtLogisticsOrderUnit> logisticsOrderUnits = kwtLogisticsOrderUnitRepository.queryByLogOrderIds(logicsOrderIds);
        Map<String, KwtLogisticsOrderUnit> logOrderIdUnitTypeKeyAndUnitMap = Maps.newHashMap();
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(logisticsOrderUnits)){
            logOrderIdUnitTypeKeyAndUnitMap =
                    logisticsOrderUnits.stream()
                    .collect(Collectors.toMap(x -> x.getLOrderId() + "-" + x.getUnitType(),
                            Function.identity(), (k1, k2) -> k1));
        }
        return logOrderIdUnitTypeKeyAndUnitMap;
    }

    @NotNull
    private Map<String, KwtWaybillOrderTicket> getStringKwtWaybillOrderTrackMap(Set<Long> addressIds) {
        List<KwtWaybillOrderTicket> kwtWaybillOrderTracks = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(addressIds)){
            // kwtWaybillOrderTracks = kwtWaybillOrderTrackRepository.queryByAddressIds(addressIds);
             kwtWaybillOrderTracks = kwtWaybillOrderTicketRepository.queryByAddressIds(addressIds);
        }
        Map<String, KwtWaybillOrderTicket> subBillIdAddressIdKeyAndOrderTrackMap = Maps.newHashMap();
        if (CollectionUtils.isNotEmpty(kwtWaybillOrderTracks)){
            subBillIdAddressIdKeyAndOrderTrackMap =
                    kwtWaybillOrderTracks.stream()
                            .collect(Collectors.toMap(x -> x.getWSubtaskId() + "-" + x.getWAddressId(),
                                    Function.identity(), (k1, k2) -> k1));
        }
        return subBillIdAddressIdKeyAndOrderTrackMap;
    }

    @NotNull
    private Set<Long> getLogOrderIds(WaybillOrderReq req) {
        Set<Long> logOrderIds = Sets.newHashSet();
        if (StringUtils.isNotBlank(req.getLogisticsOrderId())){
            logOrderIds.add(Long.parseLong(req.getLogisticsOrderId()));
        }

        if (StringUtils.isNotBlank(req.getBillingMethod() )){
            List<KwtLogisticsOrder> kwtLogisticsOrder = logisticsOrderRepository.queryByBillMethod(req.getBillingMethod());
            if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(kwtLogisticsOrder)){
                logOrderIds.addAll(kwtLogisticsOrder.stream()
                        .map(KwtLogisticsOrder::getId)
                        .collect(Collectors.toSet()));
            }
        }
        if (StringUtils.isNotBlank(req.getLogisticsOrderNo()) && StringUtils.isBlank(req.getLogisticsOrderId())){
            KwtLogisticsOrder kwtLogisticsOrder = logisticsOrderRepository.queryByLogisticsOrderNo(req.getLogisticsOrderNo());
            if (Objects.nonNull(kwtLogisticsOrder)){
                logOrderIds.add(kwtLogisticsOrder.getId());
            }
        }
        Set<Long> entIds = Sets.newHashSet();
        if (StringUtils.isNotBlank(req.getConsignorId())){
            entIds.add(Long.parseLong(req.getConsignorId()));
        }
        if (StringUtils.isNotBlank(req.getCarrierId())){
            entIds.add(Long.parseLong(req.getCarrierId()));
        }
        //根据单位查询订单id
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(entIds)){
            List<KwtLogisticsOrderUnit> unitList = kwtLogisticsOrderUnitRepository.queryByEntIds(entIds);
            if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(unitList)){
                logOrderIds.addAll(unitList.stream()
                        .map(KwtLogisticsOrderUnit::getLOrderId)
                        .collect(Collectors.toSet())) ;
            }
         }
        List<KwtLogisticsOrderGoods> logisticsOrderGoods =null ;
        if (org.apache.commons.lang3.StringUtils.isNotBlank(req.getGoodsName())){
            List<KwpGoods> goods = goodsInfoService.findGoodsByGoodsName(req.getGoodsName());
            if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(goods)){
                Set<Long> goodsIds = goods.stream()
                        .map(KwpGoods::getId)
                        .collect(Collectors.toSet());
               logisticsOrderGoods = kwtLogisticsOrderGoodsRepository.queryByGoodsIds(goodsIds);
            }
        }
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(logisticsOrderGoods)){
            logOrderIds.addAll(logisticsOrderGoods.stream()
                    .map(KwtLogisticsOrderGoods::getLOrderId)
                    .collect(Collectors.toSet()));
        }

        return logOrderIds;
    }

    @NotNull
    private Set<Long> getBillOrderIds(WaybillOrderReq req) {
        Set<Long> billOrderIds = Sets.newHashSet();
        KwtWaybillOrder order = getKwtWaybillOrder(req);
        boolean b = Stream.of(req.getWaybillNo(), req.getTruckNo(), req.getDriverName(), req.getPhone()).anyMatch(StringUtils::isNotBlank);
        if (b){
            List<KwtWaybillOrder> waybillOrders = kwtWaybillOrderRepository.queryByCondition(order);
            if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(waybillOrders)){
                billOrderIds.addAll(waybillOrders.stream()
                        .map(KwtWaybillOrder::getId)
                        .collect(Collectors.toSet()));
            }
        }
        if (org.apache.commons.lang3.StringUtils.isNoneBlank(req.getLoadStartTime(),req.getLoadEndTime())){
            Date loadStartTime = DateUtils.formatDate(req.getLoadStartTime());
            Date loadEndTime = DateUtils.formatDate(req.getLoadEndTime());
            List<KwtWaybillOrderTicket> tickets = kwtWaybillOrderTicketRepository.queryByOperateTime(loadStartTime,
                    loadEndTime,1);
            if (org.apache.commons.collections4.CollectionUtils.isNotEmpty( tickets)){
                billOrderIds.addAll(tickets.stream()
                        .map(KwtWaybillOrderTicket::getWOrderId)
                        .collect(Collectors.toSet()));
            }
        }

        if (org.apache.commons.lang3.StringUtils.isNoneBlank(req.getUnloadStartTime(),req.getUnloadEndTime())){
            Date unloadStartTime = DateUtils.formatDate(req.getUnloadStartTime());
            Date unloadEndTime = DateUtils.formatDate(req.getUnloadEndTime());
            List<KwtWaybillOrderTicket> tickets = kwtWaybillOrderTicketRepository.queryByOperateTime(unloadStartTime,
                    unloadEndTime,2);
            if (org.apache.commons.collections4.CollectionUtils.isNotEmpty( tickets)){
                billOrderIds.addAll(tickets.stream()
                        .map(KwtWaybillOrderTicket::getWOrderId)
                        .collect(Collectors.toSet()));
            }
        }
        return billOrderIds;
    }

    @NotNull
    private static WaybillOrderResp getWaybillOrderResp(KwtWaybillOrderSubtask record, Map<Long, KwtWaybillOrder> finalWaybillOrderIdAndBillOrderMap,
                                                        Map<String, KwtLogisticsOrderUnit> finalLogOrderIdUnitTypeKeyAndUnitMap,
                                                        Map<Long, KwtLogisticsOrderGoods> finalLogOrderIdAndGoodsIdMap,
                                                        Map<Long, KwpGoods> kwpGoodsMap,
                                                        Map<String, KwtWaybillOrderAddress> finalSubOrderIdAddressTypeKeyAndAddressMap,
                                                        Map<String, KwtWaybillOrderTicket> finalSubBillIdAddressIdKeyAndOrderTrackMap,
                                                        Map<Long, KwtLogisticsOrder> finalLogIdAndOrderMap) {
        WaybillOrderResp waybillOrderResp = new WaybillOrderResp();
        KwtWaybillOrder billOrder = finalWaybillOrderIdAndBillOrderMap.getOrDefault(record.getWOrderId(),
                new KwtWaybillOrder());
        waybillOrderResp.setWaybillOrderId(String.valueOf(billOrder.getId()));
        waybillOrderResp.setWaybillOrderNo(billOrder.getWOrderNo());
        waybillOrderResp.setLogisticsOrderId(String.valueOf(record.getLOrderId()));
        KwtLogisticsOrder order = finalLogIdAndOrderMap.getOrDefault(record.getLOrderId(), new KwtLogisticsOrder());
        waybillOrderResp.setLogisticsOrderNo(order.getLOrderNo());
        KwtLogisticsOrderUnit consignUnit = finalLogOrderIdUnitTypeKeyAndUnitMap.getOrDefault(record.getLOrderId() + "-" + NumberConstant.ONE,
                new KwtLogisticsOrderUnit());
        waybillOrderResp.setConsignUnitId(String.valueOf(consignUnit.getEntId()));
        waybillOrderResp.setConsignUnitName(consignUnit.getFirmName());
        KwtLogisticsOrderUnit carriageUnit =
                finalLogOrderIdUnitTypeKeyAndUnitMap.getOrDefault(record.getLOrderId() + "-" + NumberConstant.TWO,
                new KwtLogisticsOrderUnit());
        waybillOrderResp.setCarriageUnitId(String.valueOf(carriageUnit.getEntId()));
        waybillOrderResp.setCarriageUnitName(carriageUnit.getFirmName());
        waybillOrderResp.setTruckNo(billOrder.getTruckNo());
        waybillOrderResp.setDriverName(billOrder.getDriverName());
        waybillOrderResp.setDriverPhone(billOrder.getDriverPhone());
        Long lOrderId = record.getLOrderId();

        KwtLogisticsOrderGoods goods = finalLogOrderIdAndGoodsIdMap.getOrDefault(lOrderId,
                new KwtLogisticsOrderGoods());
        KwpGoods kwpGoods = kwpGoodsMap.get(goods.getGoodsId());
        if (Objects.nonNull(kwpGoods)){
            waybillOrderResp.setGoodsName(kwpGoods.getName()+"/"+kwpGoods.getGoodsType()+"/"+kwpGoods.getSpec());
        }
        waybillOrderResp.setTaskNum(Objects.nonNull(billOrder.getEntrustAmount()) ?
                billOrder.getEntrustAmount().setScale(2, RoundingMode.HALF_UP).toPlainString() : "0.00");
        waybillOrderResp.setLoadingNetWeight(Objects.nonNull(billOrder.getLoadAmount()) ?
                billOrder.getLoadAmount().setScale(2, RoundingMode.HALF_UP).toPlainString() : "0.00");
        KwtWaybillOrderAddress loadingAdd = finalSubOrderIdAddressTypeKeyAndAddressMap.getOrDefault(record.getId() + "-" + AddressTypeEnum.SHIPMENT.getCode(),
                new KwtWaybillOrderAddress());
        waybillOrderResp.setLoadingAddress(loadingAdd.getDetailAddress());
        waybillOrderResp.setUnloadingNetWeight(Objects.nonNull(billOrder.getUnloadAmount()) ?
                billOrder.getUnloadAmount().setScale(2, RoundingMode.HALF_UP).toPlainString() : "0.00");
        KwtWaybillOrderAddress unloadingAdd =
                finalSubOrderIdAddressTypeKeyAndAddressMap.getOrDefault(record.getId() + "-" + AddressTypeEnum.SHIPMENT.getCode(),
                new KwtWaybillOrderAddress());
        waybillOrderResp.setUnloadingAddress(unloadingAdd.getDetailAddress());

        KwtWaybillOrderTicket loadTrack =
                finalSubBillIdAddressIdKeyAndOrderTrackMap.getOrDefault(record.getId() + "-" + loadingAdd.getId(),
                new KwtWaybillOrderTicket());

        waybillOrderResp.setAcceptTime(DateUtils.format(record.getCreateTime(),DateUtils.DATE_TIME_PATTERN));
        KwtWaybillOrderTicket unloadTrack =
                finalSubBillIdAddressIdKeyAndOrderTrackMap.getOrDefault(record.getId() + "-" + loadingAdd.getId(),
                        new KwtWaybillOrderTicket());
        waybillOrderResp.setLoadingTime(DateUtils.format(loadTrack.getOperateTime(),DateUtils.DATE_TIME_PATTERN));
        //todo  cxf
        waybillOrderResp.setOffsiteTime(DateUtils.format(unloadTrack.getOperateTime(),DateUtils.DATE_TIME_PATTERN));
        waybillOrderResp.setUnloadingTime(DateUtils.format(unloadTrack.getOperateTime(),DateUtils.DATE_TIME_PATTERN));
        if (Objects.equals(record.getStatus(), CarWaybillV1Enum.WAIT_UNLOADING.getCode())){
            waybillOrderResp.setCompleteTime(DateUtils.format(record.getUpdateTime(),DateUtils.DATE_TIME_PATTERN));
        }

        waybillOrderResp.setStatus(String.valueOf(record.getStatus()));
        waybillOrderResp.setStatusDesc(CarWaybillV1Enum.geDesc(record.getStatus()));
        return waybillOrderResp;
    }

    @NotNull
    private static KwtWaybillOrder getKwtWaybillOrder(WaybillOrderReq req) {
        KwtWaybillOrder order = new KwtWaybillOrder();
        order.setWOrderNo(req.getWaybillNo());
        order.setTruckNo(req.getTruckNo());
        order.setDriverName(req.getDriverName());
        order.setDriverPhone(req.getPhone());
        return order;
    }

    public WaybillOrderDetailResp queryBillOrderDetail(WaybillOrderRequest req) {
        log.info("查询运单详情请求：{}",JSON.toJSONString( req));
        Long orderId = req.getOrderId();
        KwtWaybillOrder billOrder = kwtWaybillOrderRepository.queryByBillOrderId(orderId);
        if (Objects.isNull(billOrder)){
            throw new BusinessException("运单信息不存在");
        }
        //查询车辆信息
        RTruckVo truck = remoteFleetService.findTruck(billOrder.getTruckId());
        //查询子运单
        KwtWaybillOrderSubtask subtask = kwtWaybillOrderSubtaskRepository.queryByBillOrderId(billOrder.getId());
        if (Objects.isNull(subtask)){
            throw new BusinessException("子运单信息不存在");
        }
        //查询物流信息
        KwtLogisticsOrder logOrder = kwtLogisticsOrderRepository.queryByLogisticsOrderId(subtask.getLOrderId());
        if (Objects.isNull(logOrder)){
            throw new BusinessException("物流信息不存在");
        }

        RFleetVo fleet = null;
        try {
            fleet = remoteFleetService.findFleetByTruckId(billOrder.getTruckId(),LoginUserHolder.getEntId());
        } catch (Exception e) {
            log.info("查询车队信息异常：{}",  e.getMessage());
        }

        //查询商品信息
        KwtLogisticsOrderGoods goods = kwtLogisticsOrderGoodsRepository.queryByLogOrderId(logOrder.getId());
        KwpGoods kwpGoods = null;
        if(Objects.nonNull(goods)){
            kwpGoods = goodsInfoService.getGoodsById(goods.getGoodsId());
        }
        //查询运单装货地址卸货地址
        List<KwtWaybillOrderAddress> kwtWaybillOrderAddresses = waybillOrderAddressRepository.queryByWOrderId(billOrder.getId());
        Map<String, KwtWaybillOrderAddress> keyAndAddressMap = Maps.newHashMap() ;
        if(org.apache.commons.collections4.CollectionUtils.isNotEmpty(kwtWaybillOrderAddresses)){
            keyAndAddressMap = kwtWaybillOrderAddresses.stream()
                    .collect(Collectors.toMap(x -> x.getWOrderId() + "-" + x.getAddressType(),
                    Function.identity(), (x, y) -> x));
        }

        //查询企业信息
        List<KwtLogisticsOrderUnit> unitList = kwtLogisticsOrderUnitRepository.queryByLOrderId(logOrder.getId());
        Map<String, KwtLogisticsOrderUnit> logisticsOrderUnitMap = Maps.newHashMap() ;
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(unitList)){
            logisticsOrderUnitMap = unitList.stream()
                    .collect(Collectors.toMap(x -> x.getLOrderId() + "-" + x.getUnitType(), Function.identity(), (x, y) -> x));
        }

        //查询轨迹
        List<KwtWaybillOrderNode> kwtWaybillOrderNodes = kwtWaybillOrderNodeRepository.queryNodesByOrderId(billOrder.getId(), subtask.getId());
        List<KwtWaybillOrderNode> nodeList = Lists.newArrayList() ;
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(kwtWaybillOrderNodes)){
            nodeList = kwtWaybillOrderNodes.stream()
                    .filter(x->Objects.nonNull(x.getWeighbridgeId()))
                    .sorted(Comparator.comparing(KwtWaybillOrderNode::getCreateTime))
                    .collect(Collectors.toList());
        }

        //查询用户
        UserCacheResDto userCacheResDto = remoteSystemService.queryUserCacheById(subtask.getUnloadOperator());
        //根据物流订单查询运单号
        List<KwtWaybillOrderSubtask> waybillOrderSubtasks = kwtWaybillOrderSubtaskRepository.queryByLogId(logOrder.getId());
        List<KwtWaybillOrder> billOrders = Lists.newArrayList() ;
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(waybillOrderSubtasks)){
            Set<Long> billOrderIds = waybillOrderSubtasks.stream()
                    .map(KwtWaybillOrderSubtask::getWOrderId)
                    .collect(Collectors.toSet());
            if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(billOrderIds)){
                billOrders = kwtWaybillOrderRepository.queryByBillOrderIds(billOrderIds);
            };
        }

        //装卸货信息
        List<KwtWaybillOrderTicket> orderTicketList = kwtWaybillOrderTicketRepository.queryByWOrderId(req.getOrderId());
        if (CollectionUtils.isEmpty(orderTicketList)) {
            throw new BusinessPlatfromException(ErrorCodeEnum.WAYBILL_ORDER_NOT_TICKET, "当前车辆无物流运单装卸货信息");
        }
        Map<String, KwtWaybillOrderTicket> ticketMap = orderTicketList.stream().collect(
                Collectors.toMap(ticket -> ticket.getWOrderId() + "-" + ticket.getType(),
                        Function.identity(), (x, y) -> x));

        return getWaybillOrderDetailResp( subtask,billOrder, logOrder, truck, fleet, goods,
                keyAndAddressMap,kwpGoods,logisticsOrderUnitMap,nodeList,userCacheResDto,billOrders,ticketMap);
    }

    @NotNull
    private static WaybillOrderDetailResp getWaybillOrderDetailResp( KwtWaybillOrderSubtask subtask,
                                                                     KwtWaybillOrder billOrder,
                                                                     KwtLogisticsOrder logOrder,
                                                                     RTruckVo truck, RFleetVo fleet,
                                                                     KwtLogisticsOrderGoods goods,
                                                                     Map<String, KwtWaybillOrderAddress> keyAndAddressMap,
                                                                     KwpGoods kwpGoods,
                                                                     Map<String, KwtLogisticsOrderUnit> logisticsOrderUnitMap,
                                                                     List<KwtWaybillOrderNode> nodeList,
                                                                     UserCacheResDto userCacheResDto,
                                                                     List<KwtWaybillOrder> billOrders,
                                                                     Map<String, KwtWaybillOrderTicket> ticketMap) {
        WaybillOrderDetailResp waybillOrderDetailResp = new WaybillOrderDetailResp();
        waybillOrderDetailResp.setWaybillOrderId(String.valueOf(billOrder.getId()));
        waybillOrderDetailResp.setWaybillOrderNo(billOrder.getWOrderNo());
        waybillOrderDetailResp.setLogisticOrderNo(logOrder.getLOrderNo());
        waybillOrderDetailResp.setPriceType(String.valueOf(logOrder.getBillingMode()));
        waybillOrderDetailResp.setPriceTypeDesc(DictEnum.getLabel(DictTypeEnum.CHARGING_TYPE.getType(),logOrder.getBillingMode()));
        waybillOrderDetailResp.setTruckNo(billOrder.getTruckNo());
        waybillOrderDetailResp.setCarAxis(Objects.nonNull(truck) ? truck.getCarAxis() : "");
        waybillOrderDetailResp.setFleetName(Optional.ofNullable(fleet).map(RFleetVo::getName).orElse( ""));
        waybillOrderDetailResp.setDriverName(billOrder.getDriverName());
        waybillOrderDetailResp.setDriverPhone(billOrder.getDriverPhone());
        waybillOrderDetailResp.setDriverIdCard(billOrder.getDriverIdcard());
        if (Objects.nonNull(kwpGoods)){
            waybillOrderDetailResp.setGoodsName(kwpGoods.getName()+ "/" +goods.getGoodsType()+"/"+ kwpGoods.getSpec());
        }
        KwtWaybillOrderAddress loadAdd = keyAndAddressMap.getOrDefault(billOrder.getId() + "-" + AddressTypeEnum.SHIPMENT.getCode(), new KwtWaybillOrderAddress());
        waybillOrderDetailResp.setLoadAddress(loadAdd.getDetailAddress());
        KwtWaybillOrderAddress unLoadAdd = keyAndAddressMap.getOrDefault(billOrder.getId() + "-" + AddressTypeEnum.TAKE.getCode(), new KwtWaybillOrderAddress());
        waybillOrderDetailResp.setUnloadAddress(unLoadAdd.getDetailAddress());

        //预计里程
        double distanceKm = DistanceUtils.calculateDistance(
                Optional.ofNullable(loadAdd.getLat()).map(Double::valueOf).orElse(null),
                Optional.ofNullable(loadAdd.getLng()).map(Double::valueOf).orElse(null),
                Optional.ofNullable(unLoadAdd.getLat()).map(Double::valueOf).orElse(null),
                Optional.ofNullable(unLoadAdd.getLng()).map(Double::valueOf).orElse(null));
        waybillOrderDetailResp.setDistanceKm(distanceKm);

        waybillOrderDetailResp.setTaskVolume(Objects.nonNull(subtask.getEntrustAmount()) ?
                subtask.getEntrustAmount().setScale(2, RoundingMode.HALF_UP).toPlainString() : "");
        waybillOrderDetailResp.setLoadAmount(Objects.nonNull(subtask.getLoadAmount()) ?
                subtask.getLoadAmount().setScale(2, RoundingMode.HALF_UP).toPlainString() : "");
        waybillOrderDetailResp.setUnloadAmount(Objects.nonNull(subtask.getUnloadAmount()) ?
                subtask.getUnloadAmount().setScale(2, RoundingMode.HALF_UP).toPlainString() : "");

        KwtLogisticsOrderUnit transEnt = logisticsOrderUnitMap.getOrDefault(logOrder.getId() + "-" + UnitTypeEnum.CONSIGN.getCode(), new KwtLogisticsOrderUnit());
        KwtLogisticsOrderUnit carrierEnt = logisticsOrderUnitMap.getOrDefault(logOrder.getId() + "-" + UnitTypeEnum.CARRIAGE.getCode(), new KwtLogisticsOrderUnit());
        waybillOrderDetailResp.setTransEntName(transEnt.getFirmName());
        waybillOrderDetailResp.setCarrierEntName(carrierEnt.getFirmName());

        //皮重
        KwtWaybillOrderTicket tareAmountTicket = ticketMap.getOrDefault(subtask.getWOrderId() + "-" + AddressTypeEnum.SHIPMENT.getCode(), new KwtWaybillOrderTicket());
        waybillOrderDetailResp.setTareAmount(tareAmountTicket.getTareAmount());
        //毛重
        KwtWaybillOrderTicket grossAmountTicket = ticketMap.getOrDefault(subtask.getWOrderId() + "-" + AddressTypeEnum.TAKE.getCode(), new KwtWaybillOrderTicket());
        waybillOrderDetailResp.setGrossAmount(grossAmountTicket.getTareAmount());

        waybillOrderDetailResp.setStatus(subtask.getStatus());
        waybillOrderDetailResp.setStatusDesc(CarWaybillV1Enum.geDesc(subtask.getStatus()));
        waybillOrderDetailResp.setLegalLoad(truck.getActualWeight());
        
        // 计算装货完成率 = (装货量 / 任务量) × 100%
        String loadCompleteRate = "0.00%";
        if (Objects.nonNull(subtask.getLoadAmount()) && Objects.nonNull(subtask.getEntrustAmount())
                && subtask.getEntrustAmount().compareTo(BigDecimal.ZERO) > 0) {
            BigDecimal rate = subtask.getLoadAmount()
                    .divide(subtask.getEntrustAmount(), 4, RoundingMode.HALF_UP)
                    .multiply(new BigDecimal("100"))
                    .setScale(2, RoundingMode.HALF_UP);
            loadCompleteRate = rate.toPlainString() + "%";
        }
        waybillOrderDetailResp.setLoadCompleteRate(loadCompleteRate);
        
        // 计算货损率 = ((装货量 - 卸货量) / 装货量) × 100%
        String lossRate = "0.00%";
        if (Objects.nonNull(subtask.getLoadAmount()) && Objects.nonNull(subtask.getUnloadAmount())
                && subtask.getLoadAmount().compareTo(BigDecimal.ZERO) > 0) {
            BigDecimal rate = subtask.getLoadAmount().subtract(subtask.getUnloadAmount())
                    .divide(subtask.getLoadAmount(), 4, RoundingMode.HALF_UP)
                    .multiply(new BigDecimal("100"))
                    .setScale(2, RoundingMode.HALF_UP);
            lossRate = rate.toPlainString() + "%";
        }
        waybillOrderDetailResp.setLossRate(lossRate);
        if(org.apache.commons.collections4.CollectionUtils.isNotEmpty(nodeList)){
            List<WaybillOrderDetailResp.WeighingRecord> records = nodeList.stream().map(node -> {
                WaybillOrderDetailResp.WeighingRecord weighingRecord = new WaybillOrderDetailResp.WeighingRecord();
                weighingRecord.setWeighingTime(DateUtils.format(node.getCreateTime(), DateUtils.DATE_TIME_PATTERN));
                weighingRecord.setWeighingDesc(node.getRemark());
                weighingRecord.setWeighingName(node.getWeighbridgeName());
                weighingRecord.setWeighingImgUrl(node.getWeighUrl()) ;
                return weighingRecord;
            }).collect(Collectors.toList());
            waybillOrderDetailResp.setWeighingRecords(records);
        }
        WaybillOrderDetailResp.BillInfo billInfo = new WaybillOrderDetailResp.BillInfo();
        billInfo.setUploadByLabel(Objects.nonNull(userCacheResDto) ? userCacheResDto.getName() : "" );
        billInfo.setUploadTime(DateUtils.format(subtask.getUnloadUploadTime(),DateUtils.DATE_TIME_PATTERN));
        billInfo.setBillUrl(subtask.getUnloadUrl());
        waybillOrderDetailResp.setBillInfo(billInfo);
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(billOrders)){
            List<Long> billOrderIdList = billOrders.stream()
                    .filter(b -> Objects.equals(b.getStatus(), CarWaybillV1Enum.COMPLETION_LOADING.getCode()) && !Objects.equals(b.getId(),billOrder.getId()))
                    .map(KwtWaybillOrder::getId)
                    .collect(Collectors.toList());
            waybillOrderDetailResp.setBillOrderIdList(billOrderIdList);
        }
        return waybillOrderDetailResp;
    }

    @Transactional(rollbackFor = Exception.class)
    public Boolean reviewWaybillOrder(@Valid ReviewWaybillOrderReq req) {
        log.info("审核运单请求参数：{}", JSON.toJSONString(req));
        Long waybillId = Long.parseLong(req.getWaybillId());
        Integer status = Integer.parseInt(req.getStatus());
        //查询运单信息
        KwtWaybillOrder billOrder = kwtWaybillOrderRepository.queryByBillOrderId(waybillId);
        if (Objects.isNull(billOrder)){
            throw new BusinessException("运单信息不存在");
        }
        KwtWaybillOrderSubtask subtask = kwtWaybillOrderSubtaskRepository.queryByBillOrderId(waybillId);
        if (Objects.isNull(subtask)){
            throw new BusinessException("子运单信息不存在");
        }
        KwtWaybillOrder updateOrder = new KwtWaybillOrder();
        updateOrder.setId(billOrder.getId());
        KwtWaybillOrderSubtask updateSubtask = new KwtWaybillOrderSubtask();
        updateSubtask.setId(subtask.getId());
        //KwtWaybillOrderTicket kwtWaybillOrderTicket = new KwtWaybillOrderTicket();
        //单证审核 运单当前状态是已卸货，传入的订单是已完成
        List<Integer> statusList = Arrays.asList(CarWaybillV1Enum.WAIT_UNLOADING.getCode(), CarWaybillV1Enum.COMPLETION_UNLOADING.getCode());
        if (statusList.contains( status) && Objects.equals(billOrder.getStatus(), CarWaybillV1Enum.COMPLETION_LOADING.getCode())){
            updateOrder.setStatus( status);
            updateOrder.setRemark(req.getRemark());
            updateSubtask.setStatus(status);
            updateSubtask.setRemark(req.getRemark());
            updateSubtask.setUnloadAmount(org.apache.commons.lang3.StringUtils.isBlank(req.getUnloadAmount()) ? null  :  new BigDecimal(req.getUnloadAmount()));
            if (org.apache.commons.lang3.StringUtils.isNotBlank(req.getAddressUrl())){
                updateSubtask.setUnloadUrl(req.getAddressUrl());
            }
            if(org.apache.commons.lang3.StringUtils.isNotBlank(req.getUploadUser())){
                updateSubtask.setUnloadOperator(Long.valueOf(req.getUploadUser()));
            }
            if (org.apache.commons.lang3.StringUtils.isNotBlank(req.getUploadTime())){
                updateSubtask.setUnloadUploadTime(DateUtils.parse(req.getUploadTime(), DateUtils.DATE_TIME_PATTERN));
            }
            boolean b = kwtWaybillOrderRepository.updateById(updateOrder) && kwtWaybillOrderSubtaskRepository.updateById(updateSubtask);
            //修改物流订单数据
            KwtLogisticsOrder kwtLogistics= kwtLogisticsOrderRepository.queryByLogisticsOrderId(subtask.getLOrderId());
            //获取更新 订单状态
            KwtLogisticsOrder kwtLogisticsOrder = getKwtLogisticsOrder(kwtLogistics, subtask);
            boolean b1 = kwtLogisticsOrderRepository.updateById(kwtLogisticsOrder);
            //如果物流订单状态是已完成需要通知贸易订单完成
            noticeTraderOrder(kwtLogisticsOrder, kwtLogistics);

            // 存储记录
            String remark = null;
            if (Objects.equals(status, CarWaybillV1Enum.COMPLETION_UNLOADING.getCode())){
                 remark = "审核驳回，运单【"+ billOrder.getWOrderNo() + "】已驳回";
            }else {
                 remark = "审核通过，运单【"+ billOrder.getWOrderNo() + "】已完成";
            }

            saveNode(billOrder, subtask, status,remark);
            if (!b || !b1){
                throw new BusinessException("审核运单失败");
            }

            return Boolean.TRUE;
        }
        // 驳回的订单可以通过完善单证变成已完成
        if (Objects.equals(billOrder.getStatus(), CarWaybillV1Enum.COMPLETION_UNLOADING.getCode()) && Objects.equals(status,
                CarWaybillV1Enum.WAIT_UNLOADING.getCode())){
            updateOrder.setStatus(status);
            updateOrder.setRemark(req.getRemark());
            updateSubtask.setStatus(status);
            updateSubtask.setRemark(req.getRemark());
            updateSubtask.setUnloadAmount(org.apache.commons.lang3.StringUtils.isNotBlank(req.getUnloadAmount()) ? new BigDecimal(req.getUnloadAmount()) : null);
            if (org.apache.commons.lang3.StringUtils.isNotBlank(req.getAddressUrl())){
                updateSubtask.setUnloadUrl(req.getAddressUrl());
            }
            if(org.apache.commons.lang3.StringUtils.isNotBlank(req.getUploadUser())){
                updateSubtask.setUnloadOperator(Long.valueOf(req.getUploadUser()));
            }
            if (org.apache.commons.lang3.StringUtils.isNotBlank(req.getUploadTime())){
                updateSubtask.setUnloadUploadTime(DateUtils.parse(req.getUploadTime(), DateUtils.DATE_TIME_PATTERN));
            }
            boolean b = kwtWaybillOrderRepository.updateById(updateOrder) && kwtWaybillOrderSubtaskRepository.updateById(updateSubtask);
//            kwtWaybillOrderTicket.setWOrderId(waybillId);
//            kwtWaybillOrderTicket.setUrls(req.getAddressUrl());
//            kwtWaybillOrderTicket.setUploadingTime(new Date());
//            Boolean b1 = kwtWaybillOrderTicketRepository.updateByBillOrderIdAndType(kwtWaybillOrderTicket, 2);
            // 存储记录
            Long currentRoleId = LoginUserHolder.getCurrentRoleId();
            KwsRoleDto kwsRoleDto = remoteSystemService.queryByRoleIdAndEntId(currentRoleId);
            String roleName =  Objects.nonNull(kwsRoleDto) ? kwsRoleDto.getName() : "";
            String remark = "供应方，【"+roleName+"】【"+LoginUserHolder.getUserName()+"】已审核单证";
            saveNode(billOrder, subtask, status,remark);
            if (!b ){
               throw new BusinessException("完善单证失败");
            }
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    private void noticeTraderOrder(KwtLogisticsOrder kwtLogisticsOrder, KwtLogisticsOrder kwtLogistics) {

        if (!Objects.equals(kwtLogisticsOrder.getStatus(),LogisticsOrderV1Enum.HAVE_RECONCILED.getCode())){
           return;
        }
        // 根据贸易订单id查询物理订单
        List<KwtLogisticsOrder> kwtLogisticsOrders = kwtLogisticsOrderRepository.queryByTradeOrderId(kwtLogisticsOrder.getTOrderId());
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(kwtLogisticsOrders)){
            return;
        }
        //判断所有的物流订单都都已经完成
        boolean b = kwtLogisticsOrders.stream()
                .allMatch(x -> Arrays.asList(LogisticsOrderV1Enum.HAVE_RECONCILED.getCode(), LogisticsOrderV1Enum.REJECT_ORDER.getCode()).contains(x.getStatus()));
        if (!b){
            return;
        }
        TradeOrderSettlePara tradeOrderSettlePara = new TradeOrderSettlePara();
        tradeOrderSettlePara.setTOrderId(kwtLogistics.getTOrderId());
        BigDecimal loadAmount = kwtLogisticsOrders.stream()
                .map(KwtLogisticsOrder::getLoadAmount)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal unloadAmount = kwtLogisticsOrders.stream()
                .map(KwtLogisticsOrder::getUnloadAmount)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        tradeOrderSettlePara.setLoadAmount(loadAmount);
        tradeOrderSettlePara.setUnloadAmount(unloadAmount);
        log.info("运单审核通过修改贸易订单状态请求参数：{}",JSON.toJSONString(tradeOrderSettlePara));
        tradeOrderInfoService.orderSettle(tradeOrderSettlePara);
    }

    private void saveNode(KwtWaybillOrder billOrder, KwtWaybillOrderSubtask subtask, Integer status,String remark) {
        KwtWaybillOrderNode kwtWaybillOrderNode = new KwtWaybillOrderNode();
        kwtWaybillOrderNode.setTruckId(billOrder.getTruckId());
        kwtWaybillOrderNode.setTruckNo(billOrder.getTruckNo());
        kwtWaybillOrderNode.setDriverId(billOrder.getDriverId());
        kwtWaybillOrderNode.setDriverName(billOrder.getDriverName());

        kwtWaybillOrderNode.setWOrderId(billOrder.getId());
        kwtWaybillOrderNode.setWSubtaskId(subtask.getId());
        kwtWaybillOrderNode.setOrderStatus(status);
        kwtWaybillOrderNode.setRemark(remark);
        kwtWaybillOrderNode.setCreateBy(LoginUserHolder.getUserId());
        kwtWaybillOrderNode.setTruckId(billOrder.getTruckId());
        kwtWaybillOrderNodeRepository.save(kwtWaybillOrderNode);
    }

    @NotNull
    private  KwtLogisticsOrder getKwtLogisticsOrder(KwtLogisticsOrder kwtLogistics, KwtWaybillOrderSubtask subtask) {
        if (Objects.isNull(kwtLogistics)){
            throw new BusinessException("物流订单信息不存在");
        }
        //调物流订单完结订单
        List<KwtWaybillOrderSubtask> waybillOrderSubtasks = kwtWaybillOrderSubtaskRepository.queryByLogId(subtask.getLOrderId());
        boolean b2 = waybillOrderSubtasks.stream()
                .allMatch(x -> Arrays.asList(CarWaybillV1Enum.WAIT_UNLOADING.getCode(), CarWaybillV1Enum.APPROVAL_TREAT.getCode()).contains(x.getStatus()));
        // KwtLogisticsOrder logisticsOrder = kwtLogisticsOrderRepository.queryByLogisticsOrderId(subtask.getLOrderId());

        BigDecimal entrustAmount  = Objects.isNull(kwtLogistics.getEntrustAmount())  ? BigDecimal.ZERO: kwtLogistics.getEntrustAmount();
        BigDecimal subEntrustAmount = Objects.isNull(subtask.getEntrustAmount()) ? BigDecimal.ZERO: subtask.getEntrustAmount();
        BigDecimal loadAmount  = Objects.isNull(kwtLogistics.getLoadAmount())  ? BigDecimal.ZERO: kwtLogistics.getLoadAmount();
        BigDecimal subLoadAmount = Objects.isNull(subtask.getLoadAmount()) ? BigDecimal.ZERO: subtask.getLoadAmount();
        BigDecimal unloadAmount  = Objects.isNull(kwtLogistics.getUnloadAmount())  ? BigDecimal.ZERO: kwtLogistics.getUnloadAmount();
        BigDecimal subUnloadAmount = Objects.isNull(subtask.getUnloadAmount()) ? BigDecimal.ZERO: subtask.getUnloadAmount();


        KwtLogisticsOrder kwtLogisticsOrder = new KwtLogisticsOrder();
        kwtLogisticsOrder.setId(kwtLogistics.getId());
        kwtLogisticsOrder.setEntrustAmount(entrustAmount.add(subEntrustAmount));
        kwtLogisticsOrder.setLoadAmount(loadAmount.add(subLoadAmount));
        kwtLogisticsOrder.setUnloadAmount(unloadAmount.add(subUnloadAmount));
        if (b2){
            //调物流订单完结订单
            kwtLogisticsOrder.setStatus(LogisticsOrderV1Enum.HAVE_RECONCILED.getCode());
        }
        return kwtLogisticsOrder;
    }

    public StatisticsWaybillResp statisticsWaybillOrder(@RequestBody WaybillOrderReq req) {

        log.info("运单状态统计：{}",JSON.toJSONString(req));
        StatisticsWaybillResp statisticsWaybillResp = new StatisticsWaybillResp();

        statisticsWaybillResp.setTotalNum("0");
        List<CarWaybillV1Enum> carWaybillV1Enums = Arrays.stream(CarWaybillV1Enum.values())
                .sorted(Comparator.comparing(CarWaybillV1Enum::getCode))
                .collect(Collectors.toList());

        Integer status = org.apache.commons.lang3.StringUtils.isNoneBlank(req.getStatus()) ?
                Integer.parseInt(req.getStatus()) : null;
        Set<Long> allEnt = getAllEnt(req);
        //物流订单号集合
        Set<Long> logOrderIds = getLogOrderIds(req);
        boolean b1 = !org.apache.commons.lang3.StringUtils.isAllBlank(req.getLogisticsOrderNo(), req.getGoodsName(),
                req.getCarrierId(), req.getConsignorId());
        if(org.apache.commons.collections4.CollectionUtils.isEmpty(logOrderIds) && b1){
            Map<Integer, List<KwtWaybillOrder>> stausAndBillOrdersMap = Maps.newHashMap();
            List<StatisticsWaybillResp.OrderBillStatusStatistics> statusStatistics = carWaybillV1Enums.stream()
                    .map(c -> getOrderBillStatusStatistics(c, stausAndBillOrdersMap))
                    .collect(Collectors.toList());
            statisticsWaybillResp.setOrderStatusStatistics(statusStatistics);
            return statisticsWaybillResp;
        }
        //查询运单信息
        //运单id集合
        Set<Long> billOrderIds = getBillOrderIds(req);
        boolean b = Stream.of(req.getWaybillNo(), req.getTruckNo(), req.getDriverName(), req.getPhone(),
                        req.getLoadStartTime(),req.getLoadEndTime(),req.getUnloadStartTime(),req.getUnloadEndTime())
                .anyMatch(StringUtils::isNotBlank);
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(billOrderIds) && b){
            Map<Integer, List<KwtWaybillOrder>> stausAndBillOrdersMap = Maps.newHashMap();
            List<StatisticsWaybillResp.OrderBillStatusStatistics> statusStatistics = carWaybillV1Enums.stream()
                    .map(c -> getOrderBillStatusStatistics(c, stausAndBillOrdersMap))
                    .collect(Collectors.toList());
            statisticsWaybillResp.setOrderStatusStatistics(statusStatistics);
            return statisticsWaybillResp;
        }

        List<KwtWaybillOrder> orders = kwtWaybillOrderRepository.findList(allEnt,status,billOrderIds,logOrderIds);

        if (CollectionUtils.isEmpty(orders)) {
            Map<Integer, List<KwtWaybillOrder>> stausAndBillOrdersMap = Maps.newHashMap();
            List<StatisticsWaybillResp.OrderBillStatusStatistics> statusStatistics = carWaybillV1Enums.stream()
                    .map(c -> getOrderBillStatusStatistics(c, stausAndBillOrdersMap))
                    .collect(Collectors.toList());
            statisticsWaybillResp.setOrderStatusStatistics(statusStatistics);
            return statisticsWaybillResp;
        }
        Map<Integer,List<KwtWaybillOrder>> stausAndBillOrdersMap = orders.stream().collect(Collectors.groupingBy(KwtWaybillOrder::getStatus));
        List<StatisticsWaybillResp.OrderBillStatusStatistics> statusStatis = carWaybillV1Enums.stream()
                .map(c -> getOrderBillStatusStatistics(c, stausAndBillOrdersMap))
                .collect(Collectors.toList());
        statisticsWaybillResp.setOrderStatusStatistics(statusStatis);
        statisticsWaybillResp.setTotalNum(String.valueOf(orders.size()));
       return statisticsWaybillResp;
    }

    private static StatisticsWaybillResp.OrderBillStatusStatistics getOrderBillStatusStatistics(CarWaybillV1Enum c, Map<Integer, List<KwtWaybillOrder>> finalStausAndBillOrdersMap) {
        StatisticsWaybillResp.OrderBillStatusStatistics orderBillStatusStatistics = new StatisticsWaybillResp.OrderBillStatusStatistics();
        orderBillStatusStatistics.setOrderStatus(String.valueOf(c.getCode()));
        orderBillStatusStatistics.setOrderStatusDesc(c.getDestination());
        orderBillStatusStatistics.setOrderNum(String.valueOf(finalStausAndBillOrdersMap.getOrDefault(c.getCode(), new ArrayList<>()).size()));
        return orderBillStatusStatistics;
    }

    /**
     * 查询运单节点轨迹时间线
     *
     * @param req 请求参数
     * @return 节点轨迹列表
     * @author system
     * @date 2025/06/24
     */
    public WaybillOrderNodeVo queryWaybillOrderNodeTimeline(WaybillOrderNodeReq req) {
        log.info("查询运单节点轨迹，请求参数：{}", JSON.toJSONString(req));
        
        // 查询节点轨迹数据
        List<KwtWaybillOrderNode> nodes = kwtWaybillOrderNodeRepository.queryNodesByOrderId(
                req.getWOrderId(), req.getWSubtaskId());
        
        if (CollectionUtils.isEmpty(nodes)) {
            return new WaybillOrderNodeVo();
        }

        // 查询运单子单信息，用于获取商品名称和重量
        Set<Long> subtaskIds = nodes.stream()
                .map(KwtWaybillOrderNode::getWSubtaskId)
                .collect(Collectors.toSet());
        List<KwtWaybillOrderSubtask> subtasks = kwtWaybillOrderSubtaskRepository.listByIds(subtaskIds);
        Map<Long, KwtWaybillOrderSubtask> subtaskMap = subtasks.stream()
                .collect(Collectors.toMap(KwtWaybillOrderSubtask::getId, Function.identity()));

        // 查询物流订单商品信息
        Set<Long> logisticsOrderIds = subtasks.stream()
                .map(KwtWaybillOrderSubtask::getLOrderId)
                .collect(Collectors.toSet());
        List<KwtLogisticsOrderGoods> goodsList = kwtLogisticsOrderGoodsRepository.queryByLogOrderIds(
                new ArrayList<>(logisticsOrderIds));
        Map<Long, KwtLogisticsOrderGoods> goodsMap = goodsList.stream()
                .collect(Collectors.toMap(KwtLogisticsOrderGoods::getLOrderId, Function.identity(), (k1, k2) -> k1));


        // 单位字典
//        Map<String, Map<String, String>> dict = remoteSystemService.queryDictByType(
//                List.of(DictTypeEnum.UNIT_TYPE.getType()));
//        Map<String, String> unitMap = CollectionUtils.isNotEmpty(dict) ?
//                dict.get(DictTypeEnum.UNIT_TYPE.getType()) : new HashMap<>(NumberConstant.SIXTEEN);

        // 转换为VO对象
        WaybillOrderNodeVo waybillOrderNodeVo = new WaybillOrderNodeVo();
        //获取时间线
        List<WaybillOrderNodeVo.Timeline> voList = getTimelines(nodes);
        waybillOrderNodeVo.setTimelines(voList);
        // 获取时间节点
        List<WaybillOrderNodeVo.WaybillOrderNode> nodeList = getWaybillOrderNodes(voList);
        waybillOrderNodeVo.setWaybillOrderNodes(nodeList);
        return waybillOrderNodeVo;
    }

    @NotNull
    private List<WaybillOrderNodeVo.Timeline> getTimelines(List<KwtWaybillOrderNode> nodes) {
        List<WaybillOrderNodeVo.Timeline> voList = new ArrayList<>();
        for (KwtWaybillOrderNode node : nodes) {
            WaybillOrderNodeVo.Timeline vo = new WaybillOrderNodeVo.Timeline();
            //WaybillOrderNodeVo vo = new WaybillOrderNodeVo();
            vo.setId(node.getId());
            vo.setCreateTime(DateUtils.format(node.getCreateTime(), DateUtils.DATE_TIME_PATTERN));
            vo.setOrderStatus(node.getOrderStatus());
            vo.setOrderStatusName(CarWaybillV1Enum.geDesc(node.getOrderStatus()));
            vo.setTruckNo(node.getTruckNo());
            vo.setDriverName(node.getDriverName());
            vo.setWeighbridgeName(node.getWeighbridgeName());
            vo.setLng(node.getLng());
            vo.setLat(node.getLat());
            vo.setHasWeighbridge(node.getWeighbridgeId() != null);

            // 构建状态描述
            //KwtWaybillOrderSubtask subtask = subtaskMap.get(node.getWSubtaskId());
           // String statusDesc = buildStatusDescription(node, subtask, goodsMap, unitMap);
            vo.setRemark(node.getRemark());

            // 构建地址信息
            String address = buildAddressFromLatLng(node.getLng(), node.getLat());
            vo.setAddress(address);

            voList.add(vo);
        }
        return voList;
    }

    @NotNull
    private static List<WaybillOrderNodeVo.WaybillOrderNode> getWaybillOrderNodes(List<WaybillOrderNodeVo.Timeline> voList) {
        Map<Integer, List<WaybillOrderNodeVo.Timeline>> statusAndTimelineMap = voList.stream()
                .filter(t ->!Arrays.asList(CarWaybillV1Enum.WAIT_UNLOADING.getCode(),CarWaybillV1Enum.APPROVAL_TREAT.getCode(), CarWaybillV1Enum.COMPLETION_UNLOADING.getCode()).contains(t.getOrderStatus()))
                .sorted(Comparator.comparing(WaybillOrderNodeVo.Timeline::getCreateTime))
                .collect(Collectors.groupingBy(WaybillOrderNodeVo.Timeline::getOrderStatus));
        List<WaybillOrderNodeVo.WaybillOrderNode> nodeList = Lists.newArrayList();
        statusAndTimelineMap.forEach((status, timelines) -> {
            WaybillOrderNodeVo.WaybillOrderNode waybillOrderNode = new WaybillOrderNodeVo.WaybillOrderNode();
            if(org.apache.commons.collections4.CollectionUtils.isNotEmpty(timelines) && Objects.nonNull(timelines.get(0))){
                WaybillOrderNodeVo.Timeline timeline = timelines.get(0);
                waybillOrderNode.setId(timeline.getId());
                waybillOrderNode.setCreateTime(timeline.getCreateTime());
                waybillOrderNode.setOrderStatus(timeline.getOrderStatus());
                waybillOrderNode.setOrderStatusName(CarWaybillV1Enum.geDesc( timeline.getOrderStatus()));
                nodeList.add(waybillOrderNode);
            }
        });
        return nodeList;
    }

    /**
     * 构建状态描述文本
     * 格式：车辆【川A5478C】司机【张三】装载货物【铁矿石】【参运】【28.70吨】
     */
    private String buildStatusDescription(KwtWaybillOrderNode node, 
                                          KwtWaybillOrderSubtask subtask,
                                          Map<Long, KwtLogisticsOrderGoods> goodsMap,
                                          Map<String, String> unitMap) {
        if (Objects.isNull(subtask)){
            return "";
        }
        StringBuilder sb = new StringBuilder();

        if (Objects.equals(node.getOrderStatus(), CarWaybillV1Enum.PENDING_VEHICLE.getCode())) {
            sb.append(" 车辆【").append(node.getTruckNo()).append("】");
            sb.append(" 司机【").append(node.getDriverName()).append("】接单成功");
            sb.append(" 预计任务重量【").append(subtask.getEntrustAmount()).append(subtask.getUnit()).append("】");
        }

        if (Objects.equals(node.getOrderStatus(), CarWaybillV1Enum.REFUSE_TRAFFIC.getCode())) {
            sb.append(" 已到达装货点,").append(node.getWeighbridgeName()).append("】").append(subtask.getEntrustAmount()).append(subtask.getUnit());
        }
        if (Objects.equals(node.getOrderStatus(), CarWaybillV1Enum.EXIT_COMPLETED.getCode())) {
            sb.append(" 装货完成,").append(node.getTruckNo()).append(node.getDriverName());
            sb.append(node.getWeighbridgeName()).append("称重").append(subtask.getLoadAmount());
        }

        if (Objects.equals(node.getOrderStatus(), CarWaybillV1Enum.WAIT_LOADING.getCode())) {
            sb.append(" 司机【").append(node.getDriverName()).append("】已确认离场");
        }
        return sb.toString();
    }

    /**
     * 根据状态获取标签
     */
    private String getStatusLabel(Integer status) {
        if (status == null) {
            return "";
        }
        // 根据具体业务逻辑返回标签，如：参运、实装、实卸等
        // CarWaybillV1Enum: 1-已接单, 5-到达装货点, 10-已装货, 15-已离场, 20-已卸货, 25-已完成, 30-审核驳回, 99-已取消
        if (status.equals(CarWaybillV1Enum.EXIT_COMPLETED.getCode())) {
            // 10-已装货
            return "实装";
        } else if (status.equals(CarWaybillV1Enum.COMPLETION_LOADING.getCode())) {
            // 20-已卸货
            return "实卸";
        } else if (status.equals(CarWaybillV1Enum.WAIT_LOADING.getCode())) {
            // 15-已离场
            return "参运";
        }
        return "";
    }

    /**
     * 根据状态获取对应的重量
     */
    private String getWeightByStatus(Integer status, KwtWaybillOrderSubtask subtask) {
        if (status == null || subtask == null) {
            return "";
        }
        
        // 根据状态返回不同的重量
        // CarWaybillV1Enum: 1-已接单, 5-到达装货点, 10-已装货, 15-已离场, 20-已卸货, 25-已完成, 30-审核驳回, 99-已取消
        if (status.equals(CarWaybillV1Enum.WAIT_LOADING.getCode())) {
            // 15-已离场-参运显示委托量
            return String.valueOf(subtask.getEntrustAmount());
        } else if (status.equals(CarWaybillV1Enum.EXIT_COMPLETED.getCode())) {
            // 10-已装货-装货显示实装量
            return String.valueOf(subtask.getLoadAmount());
        } else if (status.equals(CarWaybillV1Enum.COMPLETION_LOADING.getCode())) {
            // 20-已卸货-卸货显示实卸量
            return String.valueOf(subtask.getUnloadAmount());
        }
        
        return "";
    }

    /**
     * 根据经纬度构建地址信息
     * 实际项目中可以调用地图服务API进行逆地理编码
     */
    private String buildAddressFromLatLng(String lng, String lat) {
        if (StringUtils.isBlank(lng) || StringUtils.isBlank(lat)) {
            return "";
        }
        // 这里可以调用高德/百度等地图API进行逆地理编码
        // 暂时返回经纬度格式
        return String.format("经度:%s, 纬度:%s", lng, lat);
    }
}
