package com.sckw.transport.service;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.pagehelper.PageHelper;
import com.sckw.core.common.enums.NumberConstant;
import com.sckw.core.common.enums.enums.DictTypeEnum;
import com.sckw.core.exception.BusinessException;
import com.sckw.core.model.constant.Global;
import com.sckw.core.model.enums.*;
import com.sckw.core.model.page.PageResult;
import com.sckw.core.utils.*;
import com.sckw.core.web.constant.HttpStatus;
import com.sckw.core.web.context.LoginUserHolder;
import com.sckw.core.web.response.HttpResult;
import com.sckw.excel.utils.DateUtil;
import com.sckw.fleet.api.RemoteFleetService;
import com.sckw.fleet.api.model.vo.RDriverVo;
import com.sckw.fleet.api.model.vo.RTruckVo;
import com.sckw.mongo.enums.BusinessTypeEnum;
import com.sckw.mongo.model.SckwLogisticsOrder;
import com.sckw.mongo.model.SckwWaybillOrder;
import com.sckw.order.api.dubbo.TradeOrderInfoService;
import com.sckw.order.api.model.CompleteLogisticsOrderParam;
import com.sckw.order.api.model.UpdateActualAmountParam;
import com.sckw.redis.constant.RedisConstant;
import com.sckw.redis.utils.RedissonUtils;
import com.sckw.stream.enums.MessageEnum;
import com.sckw.stream.model.SckwBusSum;
import com.sckw.stream.model.SckwMessage;
import com.sckw.stream.model.UserInfo;
import com.sckw.system.api.RemoteSystemService;
import com.sckw.system.api.model.dto.res.EntCacheResDto;
import com.sckw.system.api.model.dto.res.SysDictResDto;
import com.sckw.transport.dao.*;
import com.sckw.transport.model.*;
import com.sckw.transport.model.dto.*;
import com.sckw.transport.model.vo.LogisticsCountVo;
import com.sckw.transport.model.vo.UserInfoVo;
import com.sckw.transport.model.vo.WaybillCountVo;
import com.sckw.transport.model.vo.WaybillOrderDriverVo;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.stream.function.StreamBridge;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author zk
 * @desc 车辆运单
 * @date 2023/7/19 0019
 */
@Slf4j
@Service
@SuppressWarnings("all")
public class KwtWaybillOrderService {

    @Autowired
    KwtWaybillOrderMapper waybillOrderDao;
    @Autowired
    KwtLogisticsOrderMapper logisticsOrderDao;
    @Autowired
    KwtLogisticsOrderTrackMapper logisticsOrderTrackDao;
    @Autowired
    KwtLogisticsOrderAddressMapper logisticsOrderAddressDao;
    @Autowired
    KwtWaybillOrderAddressMapper waybillOrderAddressDao;
    @Autowired
    KwtWaybillOrderTrackMapper waybillOrderTrackDao;
    @Autowired
    KwtWaybillOrderTicketMapper waybillOrderTicketDao;
    @Autowired
    KwtLogisticsOrderUnitMapper logisticsOrderUnitDao;
    @Autowired
    KwtLogisticsOrderGoodsMapper logisticsOrderGoodsDao;
    @Autowired
    KwtLogisticsOrderCirculateMapper logisticsOrderCirculateDao;
    @Autowired
    CommonService commonService;
    @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)
    private RemoteFleetService remoteFleetService;
    @DubboReference(version = "1.0.0", group = "design", check = false)
    private TradeOrderInfoService tradeOrderInfoService;

    /**
     * @param driverId 司机ID
     * @desc 统计司机任务数(待接单 / 出车 / 执行 / 完结)
     * @author zk
     * @date 2023/8/1
     **/
    public Map<String, Object> findStatisticsCountByDriver(Long driverId) {
        return waybillOrderDao.findStatisticsCountByDriver(driverId);
    }

    /**
     * @param params {driverId 司机ID, month月份}
     * @desc 统计司机任务数（任务数/委派量/装货量/卸货量/亏吨量/亏吨扣款）
     * @author zk
     * @date 2023/8/1
     **/
    public Map<String, Object> findStatisticsSumByDriver(Map params) {
        Map<String, Object> data = waybillOrderDao.findStatisticsSumByDriver(params);
        BigDecimal deficitLossAmount = waybillOrderDao.deficitLossAmountByDriver(params);
        deficitLossAmount = deficitLossAmount.setScale(2, RoundingMode.HALF_UP);
        data.put("deficitLossAmount", deficitLossAmount.compareTo(new BigDecimal("0.00")) <= 0 ? Global.AMOUNT : deficitLossAmount);
        return data;
    }

    /**
     * @param params {driverId 司机ID, busStatus  1待接单/2出车/3执行/4完结, month月份}
     * @desc 统计司机任务数（任务数/委派量/装货量/卸货量/亏吨量/亏吨扣款）
     * @author zk
     * @date 2023/8/1
     **/
    public List<WaybillOrderDriverVo> findWaybillOrderByDriver(Map params) {
        /**参数处理**/
        //业务状态busStatus  1待接单/2出车/3执行/4完结
        Integer busStatus = NumberUtils.parseInt(params.get("busStatus"));
        Object driverId = StringUtils.isBlank(params.get("driverId")) ? LoginUserHolder.getUserId() : params.get("driverId");
        params.put("driverId", driverId);
        // 设置分页参数
        PageHelper.startPage(PageResult.getPage(params), PageResult.getPageSize(params));

        /**数据查询**/
        List<WaybillOrderDriverVo> waybillOrders = new ArrayList();
        if (busStatus == Global.NUMERICAL_ONE) {
            //查询司机任务列表-待接单
            waybillOrders = waybillOrderDao.findWaitWaybillOrderByDriver(params);
        } else {
            //查询司机任务列表-出车/执行/完结
            waybillOrders = waybillOrderDao.findOtherWaybillOrderByDriver(params);
            //出车-出车时间
            if (busStatus == Global.NUMERICAL_TWO) {
                for (WaybillOrderDriverVo waybillOrder : waybillOrders) {
                    KwtWaybillOrderTrack track = waybillOrderTrackDao.findWaybillOrderTrack(waybillOrder.getWOrderId(), waybillOrder.getStatus());
                    waybillOrder.setOperateTime(track != null ? track.getOperateTime() : null);
                }
            }
        }

        /**数据配置**/
        List<Long> entIds = new ArrayList<>();
        List<String> dictKey = new ArrayList<>();
        for (WaybillOrderDriverVo waybillOrder : waybillOrders) {
            entIds.add(waybillOrder.getCarrierEntId());
            dictKey.add(DictTypeEnum.UNIT_TYPE.getType() + Global.POUND + waybillOrder.getUnit());
        }
        //企业数据集
        entIds = entIds.stream().distinct().collect(Collectors.toList());
        Map<Long, EntCacheResDto> ents = remoteSystemService.queryEntCacheMapByIds(entIds);
        //数据字典
        Map<String, SysDictResDto> dicts = this.dict(dictKey);

        //数据组装
        for (WaybillOrderDriverVo waybillOrder : waybillOrders) {
            EntCacheResDto ent = ents == null ? null : ents.get(waybillOrder.getCarrierEntId());
            SysDictResDto unit = dicts == null ? null : dicts.get(DictTypeEnum.UNIT_TYPE.getType() + Global.POUND + waybillOrder.getUnit());
            //String value = getDictValue(DictTypeEnum.UNIT_TYPE.getType(), waybillOrder.getUnit());
            waybillOrder.setCarrierFirmName(ent != null ? ent.getFirmName() : null);
            waybillOrder.setUnitName(unit != null ? unit.getLabel() : null);
        }
        return waybillOrders;
    }

    /**
     * @param wOrderId
     * @desc 变更车辆/司机查询
     * @author zk
     * @date 2023/8/2
     **/
    public HttpResult changeWaybillOrder(@RequestParam("wOrderId") Long wOrderId) {
        //车辆运单信息
        KwtWaybillOrder waybillOrder = waybillOrderDao.selectById(wOrderId);
        //循环派车信息
        KwtLogisticsOrderCirculate circulate = logisticsOrderCirculateDao.selectById(wOrderId);
        if (waybillOrder == null && circulate == null) {
            return HttpResult.error("车辆运单不存在！");
        }

        Map<String, Object> result = new HashMap();
        result.put("id", wOrderId);
        result.put("wOrderId", wOrderId);
        if (waybillOrder != null) {
            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());
        } else {
            result.put("status", CarWaybillEnum.PENDING_ORDER.getCode());
            result.put("statusName", CarWaybillEnum.PENDING_ORDER.getDestination());
            result.put("truckNo", circulate.getTruckNo());
            result.put("truckId", circulate.getTruckId());
            result.put("driverId", circulate.getDriverId());
            result.put("driverPhone", circulate.getDriverPhone());
            result.put("driverIdcard", circulate.getDriverIdcard());
            result.put("driverName", circulate.getDriverName());
        }


        Object truckId = result.get("truckId");
        if (truckId != null) {
            RTruckVo truck = findTruck(Long.parseLong(String.valueOf(truckId)));
            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) {
        /**数据校验**/
        SckwWaybillOrder wOrder = new SckwWaybillOrder();
        //车辆运单信息
        KwtWaybillOrder waybillOrder = waybillOrderDao.selectById(params.getWOrderId());
        //循环派车信息
        KwtLogisticsOrderCirculate circulate = logisticsOrderCirculateDao.selectById(params.getWOrderId());
        if (waybillOrder == null && circulate == null) {
            return HttpResult.error("车辆运单不存在！");
        }
        if (waybillOrder != null) {
            if (!CarWaybillEnum.changeDriver(waybillOrder.getStatus())) {
                return HttpResult.error("车辆运单当前状态不能变更司机！");
            }
        }

        /**循环派车**/
        if (params.getType() == Global.NUMERICAL_TWO) {
            /**更新循环派车信息**/
            if (circulate != null) {
                changeWaybillOrderCirculate(circulate.getId(), params, null);
                wOrder.set_id(circulate.getId());
            } else {
                circulate = logisticsOrderCirculateDao.findCirculate(waybillOrder.getLOrderId(), waybillOrder.getTruckId(), waybillOrder.getDriverId());
                changeWaybillOrderCirculate(circulate.getId(), params, null);
            }
        }

        if (waybillOrder != null) {
            if (!CarWaybillEnum.changeDriver(waybillOrder.getStatus())) {
                return HttpResult.error("车辆运单当前状态不能变更司机！");
            }
            /**更新车辆运单**/
            changeWaybillOrder(params, null);
            wOrder.set_id(params.getWOrderId());
        }

        /**Mongodb数据更新**/
        wOrder.setDriverId(params.getDriverId());
        wOrder.setDriverName(params.getDriverName());
        wOrder.setDriverPhone(params.getDriverPhone());
        wOrder.setDriverIdcard(params.getDriverIdcard());
        editSckwWaybillOrder(wOrder, waybillOrder, 2);
        return HttpResult.ok("更换司机成功！");
    }

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

        /**循环派车**/
        if (params.getType() == Global.NUMERICAL_TWO) {
            /**更新循环派车信息**/
            if (circulate != null) {
                changeWaybillOrderCirculate(circulate.getId(), null, params);
                wOrder.set_id(circulate.getId());
            } else {
                circulate = logisticsOrderCirculateDao.findCirculate(waybillOrder.getLOrderId(), waybillOrder.getTruckId(), waybillOrder.getDriverId());
                changeWaybillOrderCirculate(circulate.getId(), null, params);
            }
        }

        if (waybillOrder != null) {
            /**更新车辆运单**/
            changeWaybillOrder(null, params);
            wOrder.set_id(params.getWOrderId());
        }

        /**Mongodb数据更新**/
        wOrder.setTruckId(params.getTruckId());
        wOrder.setTruckNo(params.getTruckNo());
        wOrder.setTruckType(params.getTruckType());
        wOrder.setTruckEnergyType(params.getTruckEnergyType());
        wOrder.setTruckUseType(params.getTruckUseType());
        wOrder.setTruckColor(params.getTruckColor());
        wOrder.setTruckTrailerNo(params.getTruckTrailerNo());
        editSckwWaybillOrder(wOrder, waybillOrder, 2);
        return HttpResult.ok("更换车辆成功！");
    }

    /**
     * @param circulateId 循环派车信息ID
     * @param driver      司机信息
     * @param truck       车辆信息
     * @desc 变更循环派车信息
     * @author zk
     * @date 2023/8/2
     **/
    public void changeWaybillOrderCirculate(Long circulateId, ChangeDriverDto driver, ChangeTruckDto truck) {
        //循环派车信息
        KwtLogisticsOrderCirculate circulate = new KwtLogisticsOrderCirculate();
        if (driver != null) {
            circulate.setDriverId(driver.getDriverId());
            circulate.setDriverPhone(driver.getDriverPhone());
            circulate.setDriverName(driver.getDriverName());
            circulate.setDriverIdcard(driver.getDriverIdcard());
        }
        if (truck != null) {
            circulate.setTruckId(truck.getTruckId());
            circulate.setTruckNo(truck.getTruckNo());
        }
        circulate.setId(circulateId);
        logisticsOrderCirculateDao.updateById(circulate);
    }

    /**
     * @param driver 司机信息
     * @param truck  车辆信息
     * @desc 更新车辆运单信息
     * @author zk
     * @date 2023/8/2
     **/
    public void changeWaybillOrder(ChangeDriverDto driver, ChangeTruckDto truck) {
        //车辆运单信息
        KwtWaybillOrder waybillOrder = new KwtWaybillOrder();
        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());
        }
        waybillOrderDao.updateById(waybillOrder);
    }


    /**
     * @param params
     * @desc 派车
     * @author zk
     * @date 2023/7/19
     **/
    @Transactional(rollbackFor = Exception.class)
    public HttpResult sendCar(List<SendCarDto1> params) {
        /**校验**/
        //承运单信息
        KwtLogisticsOrder logisticsOrder = logisticsOrderDao.selectById(params.get(0).getLOrderId());
        HttpResult result = checkWaybillOrder(params, logisticsOrder);
        if (result.getCode() != HttpStatus.SUCCESS_CODE) {
            return result;
        }
        //下游司机委派量累加（趟次）
        BigDecimal ranksAmount = (BigDecimal) result.getData();

        /**数据处理**/
        result = setWaybillOrder(params, logisticsOrder);
        if (result.getCode() != HttpStatus.SUCCESS_CODE) {
            return result;
        }
        //Mongodb数据存储model
        List<SckwWaybillOrder> sckwWaybillOrders = (List<SckwWaybillOrder>) result.getData();

        /**变更承运单状态（累计派车量等于剩余可运量）/已委托量entrust_amount**/
        //更新当前承运订单委派量entrustAmount
        BigDecimal entrustAmount = logisticsOrder.getEntrustAmount() == null ? new BigDecimal(Global.AMOUNT) : logisticsOrder.getEntrustAmount();
        logisticsOrder.setEntrustAmount(entrustAmount.add(ranksAmount));
        logisticsOrderDao.updateById(logisticsOrder);
        //派车更新承运订单信息
        setLogisticsBySendCar(logisticsOrder.getId());

        /**Mongodb数据存储**/
        //1车辆订单
        for (SckwWaybillOrder waybillOrder : sckwWaybillOrders) {
            editSckwWaybillOrder(waybillOrder, null, Global.NUMERICAL_ONE);
        }

        //2承运订单
        SckwLogisticsOrder lOrder = new SckwLogisticsOrder();
        editSckwLogisticsOrder(lOrder, logisticsOrder);

        /**发送消息**/
        return HttpResult.ok();
    }

    /**
     * @param params         派车请求参数
     * @param logisticsOrder 物流订单
     * @desc 派车校验
     * @author zk
     * @date 2023/7/19
     **/
    public HttpResult checkWaybillOrder(List<SendCarDto1> params, KwtLogisticsOrder logisticsOrder) {
        /**校验物流运单是否可以派车**/
        if (logisticsOrder == null) {
            return HttpResult.error("订单已不存在！");
        }

        //状态校验
        if (logisticsOrder.getStatus() != LogisticsOrderEnum.WAIT_DELIVERY.getCode()
                && logisticsOrder.getStatus() != LogisticsOrderEnum.IN_TRANSIT.getCode()) {
            return HttpResult.error("订单" + 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("剩余可运量已不能派车！");
        }

        /**校验是车辆委托量否超过物流订单剩余量**/
        //下游司机委派量累加（趟次）
        BigDecimal ranksAmount = new BigDecimal(Global.AMOUNT);
        for (SendCarDto1 sendCarDto : params) {
            if (sendCarDto.getType() == Global.NUMERICAL_ONE) {
                //趟次派车趟次数量必填
                if (sendCarDto.getCount() == null || sendCarDto.getCount() <= 0) {
                    return HttpResult.error(sendCarDto.getTruckNo() + "趟次必须等于或大于0！");
                }
                //承运订单该车辆计划运输总量：核定载量 * 趟次
                Double truckEntrustAmount = sendCarDto.getEntrustAmount() * sendCarDto.getCount();
                ranksAmount = ranksAmount.add(new BigDecimal(truckEntrustAmount));

                //当前下游司机委派量 + 历史下游司机委派量 + 分包量
                BigDecimal actualAmount = ranksAmount.add(entrustAmountTotal);
                if (actualAmount.doubleValue() > logisticsOrder.getAmount().doubleValue()) {
                    return HttpResult.error("累计派车量已大于剩余可运量！");
                }
            }
        }
        return HttpResult.ok(ranksAmount);
    }

    /**
     * @param params         派车请求参数
     * @param logisticsOrder 物流订单
     * @desc 派车存储
     * @author zk
     * @date 2023/7/19
     **/
    public HttpResult setWaybillOrder(List<SendCarDto1> params, KwtLogisticsOrder logisticsOrder) {
        /**获取基础信息**/
        //装货地址
        KwtWaybillOrderAddress loadAddress = this.getAddress(logisticsOrder.getId(), Global.NUMERICAL_ONE, Global.NUMERICAL_ONE);
        //卸货地址
        KwtWaybillOrderAddress unloadAddress = this.getAddress(logisticsOrder.getId(), Global.NUMERICAL_TWO, Global.NUMERICAL_ONE);
        //托运企业
        KwtLogisticsOrderUnit checkEnt = logisticsOrderUnitDao.findByUnit(logisticsOrder.getId(), Global.NUMERICAL_ONE);
        //承运企业
        KwtLogisticsOrderUnit carrierEnt = logisticsOrderUnitDao.findByUnit(logisticsOrder.getId(), Global.NUMERICAL_TWO);
        //商品信息
        KwtLogisticsOrderGoods goods = logisticsOrderGoodsDao.findByGoods(logisticsOrder.getId());

        /**MySql车辆运单数据处理/存储**/
        List<SckwWaybillOrder> sckwWaybillOrders = new ArrayList();
        for (SendCarDto1 sendCarDto : params) {
            /**KwtWaybillOrder数据组装**/
            KwtWaybillOrder waybillOrder = this.setKwtWaybillOrder(sendCarDto);
            /**数据存储**/
            if (sendCarDto.getType() == Global.NUMERICAL_ONE) {
                for (int i = 0; i < sendCarDto.getCount(); i++) {
                    //车辆运单存储
                    String wOrderNo = getRedisGenerateWaybillOrderNo(RedisOrderGenerateEnum.WAYBILL_ORDER, OrderRuleEnum.WAYBILL_ORDER, logisticsOrder.getLOrderNo());
                    waybillOrder.setId(null);
                    waybillOrder.setWOrderNo(wOrderNo);
                    ranksSave(waybillOrder, loadAddress, unloadAddress);

                    /**SckwWaybillOrder数据组装**/
                    SckwWaybillOrder mongoOrder = setSckwWaybillOrder(sendCarDto, waybillOrder, logisticsOrder, loadAddress,
                            unloadAddress, checkEnt, carrierEnt, goods);
                    sckwWaybillOrders.add(mongoOrder);
                }
            } else {
                //循环派车存储
                KwtLogisticsOrderCirculate circulate = circulateSave(waybillOrder);
                if (circulate != null) {
                    /**SckwWaybillOrder数据组装**/
                    SckwWaybillOrder mongoOrder = setSckwWaybillOrder(sendCarDto, waybillOrder, logisticsOrder, loadAddress,
                            unloadAddress, checkEnt, carrierEnt, goods);
                    mongoOrder.set_id(circulate.getId());
                    mongoOrder.setWOrderId(null);
                    mongoOrder.setWOrderNo(null);
                    sckwWaybillOrders.add(mongoOrder);
                }
            }
        }

        /**Mongodb数据存储
         for (SckwWaybillOrder waybillOrder:sckwWaybillOrders) {
         //rabbitMq业务汇总数据发送/消费对象
         SckwBusSum busSum = new SckwBusSum();
         //业务汇总类型
         busSum.setBusSumType(BusinessTypeEnum.WAYBILL_ORDER_TYPE.getName());
         //操作对象（1新增/2修改/3替换数据）
         busSum.setMethod(1);
         //业务汇总数据对象
         busSum.setObject(waybillOrder);
         streamBridge.send("sckw-busSum", busSum);
         }**/

        return HttpResult.ok(sckwWaybillOrders);
    }

    /**
     * 获取生成车辆运单单据号最大值处理
     */
    public String getRedisGenerateWaybillOrderNo(RedisOrderGenerateEnum redisOrderGenerateEnum, OrderRuleEnum orderRuleEnum, String lOrderNo) {
        Date date = new Date();
        String lockKey = String.format(RedisConstant.WAYBILL_NO_GENERATE_KEY, DateUtils.formatDateToYYMMDD(date)) + lOrderNo;
        String key = OrderGenerateSeqNoUtils.getKeyNotDate(RedisOrderGenerateEnum.WAYBILL_ORDER, OrderRuleEnum.WAYBILL_ORDER, lOrderNo);
        try {
            if (Boolean.FALSE.equals(RedissonUtils.exists(key))) {
                if (Boolean.FALSE.equals(RedissonUtils.tryLock(lockKey, 5L, 10L))) {
                    throw new BusinessException("业务繁忙，请稍后再试！");
                }
                String maxOrderNo = waybillOrderDao.getMaxOrderNo(lOrderNo);
                if (StringUtils.isNotBlank(maxOrderNo)) {
                    Long maxNum = Long.valueOf(StringUtils.subStrFromIndexToEnd(maxOrderNo, 3));
                    RedissonUtils.setAtomicLong(key, maxNum, DateUtils.getSecondsDay());
                }
            }
            return OrderGenerateSeqNoUtils.getWaybillSeqNo(RedisOrderGenerateEnum.WAYBILL_ORDER, OrderRuleEnum.WAYBILL_ORDER, lOrderNo);
        } finally {
            RedissonUtils.unlock(lockKey);
        }
    }

    /**
     * @param waybillOrder  车辆订单信息
     * @param loadAddress   装货地址信息
     * @param unloadAddress 卸货地址信息
     * @desc 趟次派车数据存储
     * @author zk
     * @date 2023/7/21
     **/
    public void ranksSave(KwtWaybillOrder waybillOrder, KwtWaybillOrderAddress loadAddress, KwtWaybillOrderAddress unloadAddress) {
        /**车辆运单信息**/
        waybillOrderDao.insert(waybillOrder);

        /**车辆运单地址信息**/
        loadAddress.setId(null);
        loadAddress.setWOrderId(waybillOrder.getId());
        loadAddress.setCreateTime(waybillOrder.getCreateTime());
        loadAddress.setUpdateTime(waybillOrder.getUpdateTime());
        waybillOrderAddressDao.insert(loadAddress);
        unloadAddress.setId(null);
        unloadAddress.setWOrderId(waybillOrder.getId());
        unloadAddress.setCreateTime(waybillOrder.getCreateTime());
        unloadAddress.setUpdateTime(waybillOrder.getUpdateTime());
        waybillOrderAddressDao.insert(unloadAddress);

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

    /**
     * @param waybillOrder 车辆订单信息
     * @desc 循环派车数据存储
     * @author zk
     * @date 2023/7/21
     **/
    public KwtLogisticsOrderCirculate circulateSave(KwtWaybillOrder waybillOrder) {
        //循环派车信息
        KwtLogisticsOrderCirculate circulate = logisticsOrderCirculateDao.findCirculate(waybillOrder.getLOrderId(),
                waybillOrder.getTruckId(), waybillOrder.getDriverId());
        if (circulate == null) {
            circulate = new KwtLogisticsOrderCirculate();
            BeanUtils.copyProperties(waybillOrder, circulate);
            circulate.setWOrderId(null);
            circulate.setStatus(0);
            int count = logisticsOrderCirculateDao.insert(circulate);
            return count > 0 ? circulate : null;
        } else {
            //更新原循环单ID
            Long newId = new IdWorker(Global.NUMERICAL_ONE).nextId();
            logisticsOrderCirculateDao.updateIdByKey(newId, null, circulate.getId(), LoginUserHolder.getUserId(), new Date());

            BeanUtils.copyProperties(waybillOrder, circulate);
            circulate.setId(newId);
            circulate.setWOrderId(null);
            circulate.setStatus(0);
            int count = logisticsOrderCirculateDao.updateById(circulate);
            return count > 0 ? circulate : null;
        }
    }

    /**
     * @param orderId     订单ID
     * @param addressType 地址类型（1装货地址、2卸货地址）
     * @param type        订单类型（1物流订单、2车辆运单）
     * @desc 获取订单地址信息
     * @author zk
     * @date 2023/7/20
     **/
    public KwtWaybillOrderAddress getAddress(Long orderId, int addressType, int type) {
        /**查询数据**/
        KwtWaybillOrderAddress address = new KwtWaybillOrderAddress();
        if (type == Global.NUMERICAL_ONE) {
            KwtLogisticsOrderAddress orderAddress = logisticsOrderAddressDao.findByAddress(orderId, addressType);
            BeanUtils.copyProperties(orderAddress, address);
        }
        if (type == Global.NUMERICAL_TWO) {
            KwtWaybillOrderAddress orderAddress = waybillOrderAddressDao.findByAddress(orderId, addressType);
            BeanUtils.copyProperties(orderAddress, address);
        }

        /**组装数据**/
        address.setId(null);
        address.setCreateBy(null);
        address.setCreateTime(null);
        address.setUpdateBy(null);
        address.setUpdateBy(null);
        return address;
    }

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

    /**
     * @param sendCarDto 派车请求参数
     * @desc 车辆运单对象赋值-趟次
     * @author zk
     * @date 2023/7/20
     **/
    public KwtWaybillOrder setKwtWaybillOrder(SendCarDto1 sendCarDto) {
        KwtWaybillOrder waybillOrder = new KwtWaybillOrder();
        waybillOrder.setEntId(LoginUserHolder.getEntId());
        waybillOrder.setLOrderId(sendCarDto.getLOrderId());
        waybillOrder.setType(sendCarDto.getType());
        waybillOrder.setStartTime(sendCarDto.getLoadDateTime());
        waybillOrder.setEndTime(sendCarDto.getUnloadDateTime());
        waybillOrder.setTruckId(sendCarDto.getTruckId());
        waybillOrder.setTruckNo(sendCarDto.getTruckNo());
        waybillOrder.setDriverId(sendCarDto.getDriverId());
        waybillOrder.setDriverName(sendCarDto.getDriverName());
        waybillOrder.setDriverPhone(sendCarDto.getDriverPhone());
        waybillOrder.setDriverIdcard(sendCarDto.getDriverIdcard());
        waybillOrder.setEntrustAmount(new BigDecimal(sendCarDto.getEntrustAmount()));
        waybillOrder.setUnloadAmount(new BigDecimal(Global.AMOUNT));
        waybillOrder.setLoadAmount(new BigDecimal(Global.AMOUNT));
        waybillOrder.setDeficitAmount(new BigDecimal(Global.AMOUNT));
        waybillOrder.setStatus(CarWaybillEnum.PENDING_ORDER.getCode());
        return waybillOrder;
    }

    /**
     * @param sendCarDto 派车请求参数
     * @desc 车辆运单对象赋值-循环
     * @author zk
     * @date 2023/7/20
     **/
    public KwtWaybillOrder setKwtWaybillOrder(KwtLogisticsOrderCirculate circulate, OperateSendCarDto params, String wOrderNo) {
        KwtWaybillOrder waybillOrder = new KwtWaybillOrder();
        waybillOrder.setId(circulate.getId());
        waybillOrder.setEntId(LoginUserHolder.getEntId());
        waybillOrder.setLOrderId(circulate.getLOrderId());
        waybillOrder.setWOrderNo(wOrderNo);
        waybillOrder.setType(params.getType());
        waybillOrder.setStartTime(circulate.getStartTime());
        waybillOrder.setEndTime(circulate.getEndTime());
        waybillOrder.setTruckId(circulate.getTruckId());
        waybillOrder.setTruckNo(circulate.getTruckNo());
        waybillOrder.setDriverId(circulate.getDriverId());
        waybillOrder.setDriverName(circulate.getDriverName());
        waybillOrder.setDriverPhone(circulate.getDriverPhone());
        waybillOrder.setDriverIdcard(circulate.getDriverIdcard());
        waybillOrder.setEntrustAmount(circulate.getEntrustAmount());
        waybillOrder.setStatus(CarWaybillEnum.PENDING_VEHICLE.getCode());
        waybillOrder.setCreateBy(circulate.getCreateBy());
        return waybillOrder;
    }

    /**
     * @param sendCarDto     派车请求参数
     * @param logisticsOrder 承运订单
     * @param loadAddress    装货地址
     * @param unloadAddress  卸货地址
     * @param checkEnt       托运企业
     * @param carrierEnt     承运企业
     * @param goods          商品信息
     * @desc mongodb车辆运单对象赋值
     * @author zk
     * @date 2023/7/20
     **/
    public SckwWaybillOrder setSckwWaybillOrder(SendCarDto1 sendCarDto, KwtWaybillOrder waybillOrder,
                                                KwtLogisticsOrder logisticsOrder, KwtWaybillOrderAddress loadAddress,
                                                KwtWaybillOrderAddress unloadAddress, KwtLogisticsOrderUnit checkEnt,
                                                KwtLogisticsOrderUnit carrierEnt, KwtLogisticsOrderGoods goods) {
        //基础信息
        SckwWaybillOrder order = new SckwWaybillOrder();
        order.set_id(new IdWorker(1).nextId());
        order.setWOrderId(waybillOrder.getId());
        order.setWOrderNo(waybillOrder.getWOrderNo());
        order.setLOrderId(logisticsOrder.getId());
        order.setLOrderNo(logisticsOrder.getLOrderNo());
        order.setTOrderId(logisticsOrder.getTOrderId());
        order.setTOrderNo(logisticsOrder.getTOrderNo());
        order.setEntId(LoginUserHolder.getEntId());
        order.setFirmName(LoginUserHolder.getEntName());

        //车辆信息
        order.setTruckId(sendCarDto.getTruckId());
        order.setTruckNo(sendCarDto.getTruckNo());
        order.setTruckType(sendCarDto.getTruckType());
        order.setTruckEnergyType(sendCarDto.getTruckEnergyType());
        order.setTruckUseType(sendCarDto.getTruckUseType());
        order.setTruckColor(sendCarDto.getTruckColor());
        order.setTruckTrailerNo(sendCarDto.getTruckTrailerNo());

        //司机信息
        order.setDriverId(sendCarDto.getDriverId());
        order.setDriverName(sendCarDto.getDriverName());
        order.setDriverPhone(sendCarDto.getDriverPhone());
        order.setDriverIdcard(sendCarDto.getDriverIdcard());

        //运输信息
        order.setType(sendCarDto.getType());
        order.setStartTime(sendCarDto.getLoadDateTime());
        order.setEndTime(sendCarDto.getUnloadDateTime());
        order.setEntrustAmount(new BigDecimal(sendCarDto.getEntrustAmount()));
        order.setUnit(logisticsOrder.getUnit());
        order.setLoadAmount(new BigDecimal(Global.AMOUNT));
        order.setLoadTareAmount(new BigDecimal(Global.AMOUNT));
        order.setLoadGrossAmount(new BigDecimal(Global.AMOUNT));
        order.setLoadUrls(Global.EMPTY_STRING);
        order.setUnloadAmount(new BigDecimal(Global.AMOUNT));
        order.setUnloadTareAmount(new BigDecimal(Global.AMOUNT));
        order.setUnloadGrossAmount(new BigDecimal(Global.AMOUNT));
        order.setUnloadUrls(Global.EMPTY_STRING);
        order.setDeficitAmount(new BigDecimal(Global.AMOUNT));
        order.setDeficitPrice(new BigDecimal(Global.AMOUNT));
        order.setLoss(logisticsOrder.getLoss());
        order.setLossUnit(logisticsOrder.getLossUnit());
        order.setGoodsPrice(logisticsOrder.getGoodsPrice());
        order.setGoodsPriceUnit(logisticsOrder.getGoodsPriceUnit());

        //商品信息
        order.setGoodsId(goods.getGoodsId());
        order.setGoodsCode(null);
        order.setGoodsName(goods.getGoodsName());
        order.setGoodsType(goods.getGoodsType());
        order.setGoodsType(null);
        order.setGoodsIndustry(null);
        order.setGoodsSpec(null);

        //托运/承运企业信息
        order.setCheckEntId(checkEnt.getEntId());
        order.setCheckFirmName(checkEnt.getFirmName());
        order.setCheckContacts(checkEnt.getContacts());
        order.setCheckPhone(checkEnt.getPhone());
        order.setCarrierEntId(carrierEnt.getEntId());
        order.setCarrierFirmName(carrierEnt.getFirmName());
        order.setCarrierContacts(carrierEnt.getContacts());
        order.setCarrierPhone(carrierEnt.getPhone());

        //装卸货地址相关信息
        order.setLoadName(loadAddress.getName());
        order.setLoadType(loadAddress.getType());
        order.setLoadContacts(loadAddress.getContacts());
        order.setLoadPhone(loadAddress.getPhone());
        order.setLoadCityCode(loadAddress.getCityCode() == null ? null : String.valueOf(loadAddress.getCityCode()));
        order.setLoadCityName(loadAddress.getCityName());
        order.setLoadDetailAddress(loadAddress.getDetailAddress());
        order.setLoadLat(loadAddress.getLat());
        order.setLoadLng(loadAddress.getLng());
        order.setUnloadName(unloadAddress.getName());
        order.setUnloadType(unloadAddress.getType());
        order.setUnloadContacts(unloadAddress.getContacts());
        order.setUnloadPhone(unloadAddress.getPhone());
        order.setUnloadCityCode(unloadAddress.getCityCode() == null ? null : String.valueOf(unloadAddress.getCityCode()));
        order.setUnloadCityName(unloadAddress.getCityName());
        order.setUnloadDetailAddress(unloadAddress.getDetailAddress());
        order.setUnloadLat(unloadAddress.getLat());
        order.setUnloadLng(unloadAddress.getLng());

        //操作人信息
        order.setStatus(waybillOrder.getStatus());
        order.setCreateBy(LoginUserHolder.getUserId());
        order.setCreateByName(LoginUserHolder.getUserName());
        order.setCreateTime(waybillOrder.getCreateTime());
        order.setUpdateBy(LoginUserHolder.getUserId());
        order.setUpdateByName(LoginUserHolder.getUserName());
        order.setUpdateTime(waybillOrder.getUpdateTime());
        order.setDelFlag(waybillOrder.getDelFlag());
        return order;
    }

    /**
     * @param circulate 循环派车信息
     * @desc mongodb车辆运单对象赋值(运单卸货mongodb重新生成一条数据)
     * @author zk
     * @date 2023/8/30
     **/
    public SckwWaybillOrder setSckwWaybillOrder(KwtLogisticsOrderCirculate circulate) {
        //基础信息
        SckwWaybillOrder order = new SckwWaybillOrder();
        order.set_id(circulate.getId());
        order.setWOrderId(null);
        order.setWOrderNo(null);

        //运输信息
        order.setLoadAmount(new BigDecimal(Global.AMOUNT));
        order.setLoadTareAmount(new BigDecimal(Global.AMOUNT));
        order.setLoadGrossAmount(new BigDecimal(Global.AMOUNT));
        order.setLoadUrls(Global.EMPTY_STRING);
        order.setUnloadAmount(new BigDecimal(Global.AMOUNT));
        order.setUnloadTareAmount(new BigDecimal(Global.AMOUNT));
        order.setUnloadGrossAmount(new BigDecimal(Global.AMOUNT));
        order.setUnloadUrls(Global.EMPTY_STRING);
        order.setDeficitAmount(new BigDecimal(Global.AMOUNT));
        order.setDeficitPrice(new BigDecimal(Global.AMOUNT));

        //操作人信息
        order.setStatus(CarWaybillEnum.PENDING_ORDER.getCode());
        order.setUpdateBy(LoginUserHolder.getUserId());
        order.setUpdateByName(LoginUserHolder.getUserName());
        order.setUpdateTime(circulate.getUpdateTime());
        order.setDelFlag(Global.NO);
        return order;
    }

    /**
     * @param lOrderId 承运订单ID
     * @description 派车更新承运订单信息
     * @author zk
     * @date 2023/7/24
     **/
    public void setLogisticsBySendCar(Long lOrderId) {
        /**
         状态判断是否是分包承运单（不考虑该承运单下级分包）
         存在：更新当前承运订单状态及委派量entrustAmount，并且校验承运订单所有父级状态是否需要修改（是修改状态，否则不修改）
         不存在：更新当前承运订单状态及委派量entrustAmount
         **/
        //承运单信息
        KwtLogisticsOrder logisticsOrder = logisticsOrderDao.selectById(lOrderId);

        //当前承运订单所属分包层级
        //int level = checkLogisticsLevel(logisticsOrder);
        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() == 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);

                    /**Mongodb数据更新**/
                    //2承运订单
                    SckwLogisticsOrder lOrder = new SckwLogisticsOrder();
                    editSckwLogisticsOrder(lOrder, order);
                }
            }
        }
    }

    /**
     * @param logisticsOrder 承运订单
     * @description 当前承运订单所属分包层级
     * @author zk
     * @date 2023/7/24
     **/
    public int logisticsLevel(KwtLogisticsOrder logisticsOrder) {
        String pids = logisticsOrder.getPids();
        String[] idArrays = StringUtils.isBlank(pids) ? new String[0] : pids.split(Global.COMMA);
        return idArrays.length <= 1 ? Global.NUMERICAL_ONE : (idArrays.length - Global.NUMERICAL_ONE);
    }

    /**
     * @param ids 车辆运单主键ID，多个已逗号隔开
     * @description 取消派车(趟次派车)
     * @author zk
     * @date 2023/7/24
     **/
    @Transactional(rollbackFor = Exception.class)
    public HttpResult cancelSendCar(List<Long> ids) {
        /**1数据校验**/
        if (CollectionUtils.isEmpty(ids)) {
            return HttpResult.error("请选择需要撤回的车辆运单！");
        }
        //1校验运单ID是否有效/2循环派车才能撤回/3运单当前状态是否可以撤回
        for (Long id : ids) {
            KwtWaybillOrder order = waybillOrderDao.selectById(id);
            //1校验运单ID是否有效
            if (order != null) {
                //3待接单的车辆运单才能撤回
                if (order.getStatus() != CarWaybillEnum.PENDING_ORDER.getCode()) {
                    return HttpResult.error("运单" + order.getWOrderNo() + "当前状态已不能撤回！");
                }
            } else {
                //循环派车信息
                KwtLogisticsOrderCirculate circulate = logisticsOrderCirculateDao.selectById(id);
                //2循环派车才能撤回
                if (circulate != null) {
                    return HttpResult.error("循环派车单不能撤回！");
                }
                return HttpResult.error("选择撤回车辆运单的数据不存在！");
            }
        }

        /**业务处理**/
        for (Long id : ids) {
            KwtWaybillOrder waybillOrder = waybillOrderDao.selectById(id);
            if (waybillOrder != null) {
                //待接单的车辆运单才能撤回
                if (waybillOrder.getStatus() == CarWaybillEnum.PENDING_ORDER.getCode()) {
                    /**2更新车辆运单**/
                    waybillOrder.setStatus(CarWaybillEnum.REVOKED.getCode());
                    waybillOrderDao.updateById(waybillOrder);

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

                    /**4回退承运订单entrustAmount**/
                    KwtLogisticsOrder logisticsOrder = logisticsOrderDao.selectById(waybillOrder.getLOrderId());
                    //承运订单已委派量=承运订单原委派量+当前车辆运单委派量
                    BigDecimal entrustAmount = logisticsOrder.getEntrustAmount() == null ? new BigDecimal(Global.AMOUNT) : logisticsOrder.getEntrustAmount();
                    logisticsOrder.setEntrustAmount(entrustAmount.subtract(waybillOrder.getEntrustAmount()));
                    logisticsOrderDao.updateById(logisticsOrder);

                    /**5Mongodb数据更新**/
                    //1车辆订单
                    SckwWaybillOrder wOrder = new SckwWaybillOrder();
                    wOrder.set_id(waybillOrder.getId());
                    editSckwWaybillOrder(wOrder, waybillOrder, 2);

                    //2承运订单
                    SckwLogisticsOrder lOrder = new SckwLogisticsOrder();
                    editSckwLogisticsOrder(lOrder, logisticsOrder);

                    /**6发送消息**/

                }
            } else {
                return HttpResult.error("选择撤回的数据已不存在！");
            }
        }

        return HttpResult.ok("车辆运单撤回成功!");
    }

    public HttpResult cancelSendCarV1(List<Long> ids) {
        /**1数据校验**/
        if (CollectionUtils.isEmpty(ids)) {
            return HttpResult.error("请选择需要撤回的车辆运单！");
        }
        //1校验运单ID是否有效/2循环派车才能撤回/3运单当前状态是否可以撤回
        for (Long id : ids) {
            KwtWaybillOrder order = waybillOrderDao.selectById(id);
            //1校验运单ID是否有效
            if (order != null) {
                //3待接单的车辆运单才能撤回
                if (order.getStatus() != CarWaybillEnum.PENDING_ORDER.getCode()) {
                    return HttpResult.error("运单" + order.getWOrderNo() + "当前状态已不能撤回！");
                }
            } else {
                //循环派车信息
                KwtLogisticsOrderCirculate circulate = logisticsOrderCirculateDao.selectById(id);
                //2循环派车才能撤回
                if (circulate != null) {
                    return HttpResult.error("循环派车单不能撤回！");
                }
                return HttpResult.error("选择撤回车辆运单的数据不存在！");
            }
        }

        /**业务处理**/
        List<KwtWaybillOrder> waybillOrders = new ArrayList();
        Map<Long, KwtLogisticsOrder> logisticsOrderData = new HashMap();
        for (Long id : ids) {
            KwtWaybillOrder waybillOrder = waybillOrderDao.selectById(id);
            if (waybillOrder != null) {
                //待接单的车辆运单才能撤回
                if (waybillOrder.getStatus() == CarWaybillEnum.PENDING_ORDER.getCode()) {
                    /**2更新车辆运单**/
                    waybillOrder.setStatus(CarWaybillEnum.REVOKED.getCode());
                    waybillOrderDao.updateById(waybillOrder);
                    waybillOrders.add(waybillOrder);

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

                    /**4回退承运订单entrustAmount**/
                    KwtLogisticsOrder logisticsOrder = logisticsOrderDao.selectById(waybillOrder.getLOrderId());
                    //承运订单已委派量=承运订单原委派量+当前车辆运单委派量
                    BigDecimal entrustAmount = logisticsOrder.getEntrustAmount() == null ? new BigDecimal(Global.AMOUNT) : logisticsOrder.getEntrustAmount();
                    logisticsOrder.setEntrustAmount(entrustAmount.subtract(waybillOrder.getEntrustAmount()));
                    logisticsOrderDao.updateById(logisticsOrder);
                    logisticsOrderData.put(logisticsOrder.getId(), logisticsOrder);
                }
            }
        }

        /**5Mongodb数据更新**/
        //1车辆订单
        for (KwtWaybillOrder waybillOrder : waybillOrders) {
            SckwWaybillOrder wOrder = new SckwWaybillOrder();
            wOrder.set_id(waybillOrder.getId());
            editSckwWaybillOrder(wOrder, waybillOrder, 2);
        }

        //2承运订单
        for (Map.Entry<Long, KwtLogisticsOrder> entry : logisticsOrderData.entrySet()) {
            SckwLogisticsOrder lOrder = new SckwLogisticsOrder();
            editSckwLogisticsOrder(lOrder, entry.getValue());
        }

        return HttpResult.ok("车辆运单撤回成功!");
    }

    /**
     * @param lorderId 物流运单id
     * @desc 取消派车-物流订单完结(趟次/循环派车)
     * @author zk
     * @date 2023/7/24
     **/
    public void cancelSendCar(Long lorderId) {
        /**1数据校验**/
        KwtLogisticsOrder order = logisticsOrderDao.selectById(lorderId);
        if (order == null) {
            return;
        }

        /**1-5循环派车失效kwt_logistics_order_circulate**/
        //趟次派车信息
        List<KwtWaybillOrder> waybillOrders = waybillOrderDao.findWaybillOrder(new HashMap<>(Global.NUMERICAL_SIXTEEN) {{
            put("lOrderId", lorderId);
            put("status", CarWaybillEnum.PENDING_ORDER.getCode());
        }});
        for (KwtWaybillOrder waybillOrder : waybillOrders) {
            waybillOrder.setStatus(CarWaybillEnum.REVOKED.getCode());
            waybillOrderDao.updateById(waybillOrder);

            setWaybillOrderTrack(waybillOrder.getId(), waybillOrder.getUpdateTime(), waybillOrder.getStatus(), "完结物流订单时撤回车辆运单！");

            //车辆订单-Mongodb数据更新
            SckwWaybillOrder wOrder = new SckwWaybillOrder();
            wOrder.set_id(waybillOrder.getId());
            editSckwWaybillOrder(wOrder, waybillOrder, 2);
        }

        //循环派车信息
        List<KwtLogisticsOrderCirculate> circulates = logisticsOrderCirculateDao.findCirculateList(lorderId, null, null, 0);
        for (KwtLogisticsOrderCirculate circulate : circulates) {
            circulate.setStatus(Global.NUMERICAL_ONE);
            circulate.setRemark("完结物流订单时撤回车辆运单！");
            logisticsOrderCirculateDao.updateById(circulate);

            //车辆订单-Mongodb数据更新
            SckwWaybillOrder wOrder = new SckwWaybillOrder();
            wOrder.set_id(circulate.getId());
            KwtWaybillOrder waybillOrder = new KwtWaybillOrder();
            waybillOrder.setStatus(CarWaybillEnum.REVOKED.getCode());
            waybillOrder.setUpdateTime(circulate.getUpdateTime());
            waybillOrder.setUpdateBy(circulate.getUpdateBy());
            editSckwWaybillOrder(wOrder, waybillOrder, 2);
        }
    }

    /**
     * @param wOrder mongodb中车辆运单信息
     * @param order  车辆运单信息
     * @param method 操作对象（1新增/2修改/3替换数据）
     * @description 更新mongodb中车辆运单信息
     * @author zk
     * @date 2023/7/26
     **/
    public void editSckwWaybillOrder(SckwWaybillOrder wOrder, KwtWaybillOrder order, int method) {
        wOrder.setWOrderId(order != null ? order.getId() : wOrder.getWOrderId());
        wOrder.setStatus(order != null ? order.getStatus() : wOrder.getStatus());
        wOrder.setUpdateTime(order != null ? order.getUpdateTime() : wOrder.getUpdateTime());
        wOrder.setUpdateBy(order != null ? order.getUpdateBy() : wOrder.getUpdateBy());
        //rabbitMq业务汇总数据发送/消费对象
        SckwBusSum busSum = new SckwBusSum();
        //业务汇总类型
        busSum.setBusSumType(BusinessTypeEnum.WAYBILL_ORDER_TYPE.getName());
        //操作对象（1新增/2修改/3替换数据）
        busSum.setMethod(method);
        //业务汇总数据对象
        busSum.setObject(wOrder);
        streamBridge.send("sckw-busSum", busSum);
    }

    /**
     * @param lOrder mongodb中承运订单信息
     * @param order  承运订单
     * @description 更新mongodb中承运订单信息
     * @author zk
     * @date 2023/7/26
     **/
    public void editSckwLogisticsOrder(SckwLogisticsOrder lOrder, KwtLogisticsOrder order) {
        lOrder.set_id(order != null ? order.getId() : lOrder.get_id());
        lOrder.setLOrderId(order != null ? order.getId() : lOrder.getLOrderId());
        lOrder.setEntrustAmount(order != null ? order.getEntrustAmount() : lOrder.getEntrustAmount());
        lOrder.setStatus(order != null ? String.valueOf(order.getStatus()) : lOrder.getStatus());
        lOrder.setUpdateTime(order != null ? order.getUpdateTime() : lOrder.getUpdateTime());
        lOrder.setUpdateBy(order != null ? order.getUpdateBy() : lOrder.getUpdateBy());
        //rabbitMq业务汇总数据发送/消费对象
        SckwBusSum busSum = new SckwBusSum();
        //业务汇总类型
        busSum.setBusSumType(BusinessTypeEnum.LOGISTICS_ORDER_TYPE.getName());
        //操作对象（1新增/2修改/3替换数据）
        busSum.setMethod(2);
        //业务汇总数据对象
        busSum.setObject(lOrder);
        streamBridge.send("sckw-busSum", busSum);
    }

    /**
     * @param params {}
     * @description 确认接单
     * @author zk
     * @date 2023/7/25
     **/
    @Transactional(rollbackFor = Exception.class)
    public HttpResult confirmSendCar(OperateSendCarDto params) {
        /**趟次派车**/
        if (params.getType() == Global.NUMERICAL_ONE) {
            /**1数据校验**/
            KwtWaybillOrder waybillOrder = waybillOrderDao.selectById(params.getWOrderId());
            if (waybillOrder == null) {
                return HttpResult.error("车辆趟次运单不存在！");
            }
            //待接单车辆运单才能拒绝接单
            if (waybillOrder.getStatus() != CarWaybillEnum.PENDING_ORDER.getCode()) {
                return HttpResult.error("车辆运单当前状态已不能拒绝接单！");
            }

            /**2更新车辆运单**/
            waybillOrder.setStatus(CarWaybillEnum.PENDING_VEHICLE.getCode());
            waybillOrderDao.updateById(waybillOrder);

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

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

            /**5Mongodb数据更新**/
            //1车辆运单
            SckwWaybillOrder wOrder = new SckwWaybillOrder();
            wOrder.set_id(waybillOrder.getId());
            editSckwWaybillOrder(wOrder, waybillOrder, 2);

            /**5发送消息**/

        }

        /**循环派车**/
        if (params.getType() == Global.NUMERICAL_TWO) {
            /**1数据校验**/
            /*KwtLogisticsOrderCirculate circulate = logisticsOrderCirculateDao.findCirculate(params.getLOrderId(),
                    params.getTruckId(), params.getDriverId(), 0);*/
            KwtLogisticsOrderCirculate circulate = logisticsOrderCirculateDao.selectById(params.getWOrderId());
            if (circulate == null) {
                return HttpResult.error("车辆循环运单不存在！");
            }
            if (circulate.getWOrderId() != null) {
                return HttpResult.error("车辆循环运单不能接单！");
            }
            //承运单信息
            KwtLogisticsOrder logisticsOrder = logisticsOrderDao.selectById(circulate.getLOrderId());
            //剩余未派量=上级委派量-分包量-下级委派量
            BigDecimal residue = logisticsOrder.getAmount().subtract(logisticsOrder.getEntrustAmount()).subtract(logisticsOrder.getSubcontractAmount());
            if (logisticsOrder.getStatus() != LogisticsOrderEnum.IN_TRANSIT.getCode() || residue.compareTo(new BigDecimal(Global.AMOUNT)) <= 0) {
                return HttpResult.error("已不能接单！");
            }

            /**2获取基础信息**/
            //装货地址
            KwtWaybillOrderAddress loadAddress = this.getAddress(circulate.getLOrderId(), Global.NUMERICAL_ONE, Global.NUMERICAL_ONE);
            //卸货地址
            KwtWaybillOrderAddress unloadAddress = this.getAddress(circulate.getLOrderId(), Global.NUMERICAL_TWO, Global.NUMERICAL_ONE);
            //KwtWaybillOrder数据组装
            String wOrderNo = getRedisGenerateWaybillOrderNo(RedisOrderGenerateEnum.WAYBILL_ORDER, OrderRuleEnum.WAYBILL_ORDER, logisticsOrder.getLOrderNo());
            KwtWaybillOrder waybillOrder = setKwtWaybillOrder(circulate, params, wOrderNo);

            /**2车辆运单存储**/
            ranksSave(waybillOrder, loadAddress, unloadAddress);
            //补上车辆运单待接单状态
            setWaybillOrderTrack(circulate, waybillOrder.getId());

            /**3更新承运订单信息**/
            //承运订单已委派量:承运订单历史委派量+当前运单委派量
            BigDecimal entrustAmount = logisticsOrder.getEntrustAmount() == null ? new BigDecimal(Global.AMOUNT) : logisticsOrder.getEntrustAmount();
            logisticsOrder.setEntrustAmount(entrustAmount.add(waybillOrder.getEntrustAmount()));
            logisticsOrderDao.updateById(logisticsOrder);

            /**4更新循环派车数据**/
            circulate.setWOrderId(waybillOrder.getId());
            circulate.setTotalTake(circulate.getTotalTake() != null ? circulate.getTotalTake() + Global.NUMERICAL_ONE : Global.NUMERICAL_ONE);
            logisticsOrderCirculateDao.updateById(circulate);

            /**5Mongodb数据更新**/
            //1车辆订单
            SckwWaybillOrder wOrder = new SckwWaybillOrder();
            wOrder.setWOrderNo(waybillOrder.getWOrderNo());
            editSckwWaybillOrder(wOrder, waybillOrder, 2);

            //2承运订单
            SckwLogisticsOrder lOrder = new SckwLogisticsOrder();
            editSckwLogisticsOrder(lOrder, logisticsOrder);

            /**6发送消息**/
        }
        return HttpResult.ok("确认接单成功！");
    }

    /**
     * @param circulate 循环派车记录
     * @param wOrderId  车辆订单ID
     * @desc 新增循环派车接单后车辆运单待接单记录
     * @author zk
     * @date 2023/7/26
     **/
    public KwtWaybillOrderTrack setWaybillOrderTrack(KwtLogisticsOrderCirculate circulate, Long wOrderId) {
        KwtWaybillOrderTrack orderTrack = new KwtWaybillOrderTrack();
        orderTrack.setWOrderId(wOrderId);
        orderTrack.setOperateTime(circulate.getCreateTime());
        orderTrack.setStatus(CarWaybillEnum.PENDING_ORDER.getCode());
        orderTrack.setCreateBy(circulate.getCreateBy());
        orderTrack.setCreateTime(circulate.getCreateTime());
        orderTrack.setUpdateBy(circulate.getCreateBy());
        orderTrack.setUpdateTime(circulate.getUpdateTime());
        int count = waybillOrderTrackDao.insert(orderTrack);
        return count > 0 ? orderTrack : null;
    }

    /**
     * @param params {}
     * @description 拒绝接单
     * @author zk
     * @date 2023/7/25
     **/
    @Transactional(rollbackFor = Exception.class)
    public HttpResult refuseSendCar(OperateSendCarDto params) {
        /**趟次派车**/
        if (params.getType() == Global.NUMERICAL_ONE) {
            /**1数据校验**/
            KwtWaybillOrder waybillOrder = waybillOrderDao.selectById(params.getWOrderId());
            if (waybillOrder == null) {
                return HttpResult.error("车辆趟次运单不存在！");
            }
            //待接单车辆运单才能拒绝接单
            if (waybillOrder.getStatus() != CarWaybillEnum.PENDING_ORDER.getCode()) {
                return HttpResult.error("车辆运单当前状态已不能拒绝接单！");
            }

            /**2更新车辆运单**/
            waybillOrder.setStatus(CarWaybillEnum.REVOKED.getCode());
            waybillOrderDao.updateById(waybillOrder);

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

            /**4回退承运订单entrustAmount**/
            KwtLogisticsOrder logisticsOrder = logisticsOrderDao.selectById(waybillOrder.getLOrderId());
            //承运订单已委派量=承运订单原委派量+当前车辆运单委派量
            BigDecimal entrustAmount = logisticsOrder.getEntrustAmount() == null ? new BigDecimal(Global.AMOUNT) : logisticsOrder.getEntrustAmount();
            logisticsOrder.setEntrustAmount(entrustAmount.subtract(waybillOrder.getEntrustAmount()));
            logisticsOrderDao.updateById(logisticsOrder);

            /**5Mongodb数据更新**/
            //1车辆运单
            SckwWaybillOrder wOrder = new SckwWaybillOrder();
            wOrder.set_id(waybillOrder.getId());
            editSckwWaybillOrder(wOrder, waybillOrder, 2);

            //2承运订单
            SckwLogisticsOrder lOrder = new SckwLogisticsOrder();
            editSckwLogisticsOrder(lOrder, 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.setMsgUrl(null);
            msg.setUserInfos(users);
            msg.setCreateBy(LoginUserHolder.getUserId());
            streamBridge.send("sckw-message", JSON.toJSONString(msg));
        }

        /**循环派车**/
        if (params.getType() == Global.NUMERICAL_TWO) {
            /**1数据校验**/
            /*KwtLogisticsOrderCirculate circulate = logisticsOrderCirculateDao.findCirculate(params.getLOrderId(),
                    params.getTruckId(), params.getDriverId(), 0);*/
            KwtLogisticsOrderCirculate circulate = logisticsOrderCirculateDao.selectById(params.getWOrderId());
            if (circulate == null) {
                return HttpResult.error("车辆循环运单不存在！");
            }

            /**2更新循环单状态为失效**/
            circulate.setStatus(Global.YES);
            circulate.setRemark(params.getRemark());
            logisticsOrderCirculateDao.updateById(circulate);

            /**3Mongodb数据更新**/
            SckwWaybillOrder wOrder = new SckwWaybillOrder();
            wOrder.set_id(circulate.getId());
            KwtWaybillOrder waybillOrder = new KwtWaybillOrder();
            waybillOrder.setStatus(CarWaybillEnum.REJECT_ORDER.getCode());
            waybillOrder.setUpdateTime(circulate.getUpdateTime());
            waybillOrder.setUpdateBy(circulate.getUpdateBy());
            editSckwWaybillOrder(wOrder, waybillOrder, 2);

            /**4发送消息**/
            KwtLogisticsOrder logisticsOrder = logisticsOrderDao.selectById(circulate.getLOrderId());
            List<UserInfo> users = new ArrayList<>() {{
                add(new UserInfo(circulate.getCreateBy(), circulate.getEntId()));
            }};
            Map<String, Object> msgParams = new HashMap<>() {{
                put("orderNo", logisticsOrder.getLOrderNo());
                put("driverName", waybillOrder.getDriverName());
            }};
            SckwMessage msg = new SckwMessage();
            msg.setRequestId(UUIDUtils.get32UUID());
            msg.setMessageEnum(MessageEnum.WAYBILL_REFUSE_SENDCAR_CIRCULATE);
            msg.setParams(msgParams);
            msg.setMsgUrl(null);
            msg.setUserInfos(users);
            msg.setCreateBy(LoginUserHolder.getUserId());
            streamBridge.send("sckw-message", JSON.toJSONString(msg));
        }
        return HttpResult.ok("拒绝接单成功!");
    }

    /**
     * @param params 确认/拒绝出车参数
     * @description 确认出车
     * @author zk
     * @date 2023/7/26
     **/
    @Transactional(rollbackFor = Exception.class)
    public HttpResult confirmDeparture(OperateWaybillDto params) {
        /**1数据校验**/
        KwtWaybillOrder waybillOrder = waybillOrderDao.selectById(params.getWOrderId());
        if (waybillOrder == null) {
            return HttpResult.error("车辆运单不存在！");
        }
        //待出车车辆运单才能出车
        if (waybillOrder.getStatus() != CarWaybillEnum.PENDING_VEHICLE.getCode()) {
            return HttpResult.error("车辆运单当前状态已不能出车！");
        }
        //车辆任务中校验
        Map<String, Object> queryParams = new HashMap<>(Global.NUMERICAL_SIXTEEN) {{
            put("truckNo", waybillOrder.getTruckNo());
            put("busStatus", 3);
        }};
        List<KwtWaybillOrder> waybillOrders = waybillOrderDao.findWaybillOrder(queryParams);
        if (!CollectionUtils.isEmpty(waybillOrders)) {
            return HttpResult.error("车辆正在任务中，不能出车！");
        }

        /**2更新车辆运单**/
        waybillOrder.setStatus(CarWaybillEnum.EXIT_COMPLETED.getCode());
        waybillOrderDao.updateById(waybillOrder);

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

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

        /**5Mongodb数据更新**/
        //1车辆运单
        SckwWaybillOrder wOrder = new SckwWaybillOrder();
        wOrder.set_id(waybillOrder.getId());
        editSckwWaybillOrder(wOrder, waybillOrder, 2);

        /**5发送消息**/

        return HttpResult.ok("确认出车成功！");
    }

    /**
     * @param params 确认/拒绝出车参数
     * @description 拒绝出车
     * @author zk
     * @date 2023/7/26
     **/
    @Transactional(rollbackFor = Exception.class)
    public HttpResult refuseDeparture(OperateWaybillDto params) {
        /**1数据校验**/
        KwtWaybillOrder waybillOrder = waybillOrderDao.selectById(params.getWOrderId());
        if (waybillOrder == null) {
            return HttpResult.error("车辆运单不存在！");
        }
        //待出车车辆运单才能拒绝出车
        if (waybillOrder.getStatus() != CarWaybillEnum.PENDING_VEHICLE.getCode()) {
            return HttpResult.error("车辆运单当前状态已不能拒绝出车！");
        }

        /**2更新车辆运单**/
        waybillOrder.setStatus(CarWaybillEnum.REFUSE_TRAFFIC.getCode());
        waybillOrderDao.updateById(waybillOrder);

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

        /**4循环派车重置派车信息kwt_logistics_order_circulate**/
        if (waybillOrder.getType() == Global.NUMERICAL_TWO) {
            //循环派车信息
            KwtLogisticsOrderCirculate circulate = logisticsOrderCirculateDao.findCirculate(waybillOrder.getLOrderId(),
                    waybillOrder.getTruckId(), waybillOrder.getDriverId());
            circulate.setStatus(Global.NUMERICAL_ONE);
            circulate.setWOrderId(null);
            logisticsOrderCirculateDao.updateById(circulate);
        }

        /**5回退承运订单entrustAmount**/
        KwtLogisticsOrder logisticsOrder = logisticsOrderDao.selectById(waybillOrder.getLOrderId());
        //承运订单已委派量=承运订单原委派量+当前车辆运单委派量
        BigDecimal entrustAmount = logisticsOrder.getEntrustAmount() == null ? new BigDecimal(Global.AMOUNT) : logisticsOrder.getEntrustAmount();
        logisticsOrder.setEntrustAmount(entrustAmount.subtract(waybillOrder.getEntrustAmount()));
        logisticsOrderDao.updateById(logisticsOrder);

        /**6Mongodb数据更新**/
        //1车辆运单
        SckwWaybillOrder wOrder = new SckwWaybillOrder();
        wOrder.set_id(waybillOrder.getId());
        editSckwWaybillOrder(wOrder, waybillOrder, 2);

        //2承运订单
        SckwLogisticsOrder lOrder = new SckwLogisticsOrder();
        editSckwLogisticsOrder(lOrder, logisticsOrder);

        /**7发送消息**/
        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.setMsgUrl(null);
        msg.setUserInfos(users);
        msg.setCreateBy(LoginUserHolder.getUserId());
        streamBridge.send("sckw-message", JSON.toJSONString(msg));

        return HttpResult.ok("拒绝出车成功！");
    }

    /**
     * @param params {}
     * @desc 到达装货地点
     * @author zk
     * @date 2023/7/26
     **/
    @Transactional(rollbackFor = Exception.class)
    public HttpResult arriveLoadLocation(OperateWaybillDto params) {
        /**1数据校验**/
        KwtWaybillOrder waybillOrder = waybillOrderDao.selectById(params.getWOrderId());
        if (waybillOrder == null) {
            return HttpResult.error("车辆运单不存在！");
        }
        //已出车车辆运单才能到达装货地点
        if (waybillOrder.getStatus() != CarWaybillEnum.EXIT_COMPLETED.getCode()) {
            return HttpResult.error("车辆运单当前状态已不能到达装货地点！");
        }

        /**2更新车辆运单**/
        waybillOrder.setStatus(CarWaybillEnum.WAIT_LOADING.getCode());
        waybillOrderDao.updateById(waybillOrder);

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

        /**4Mongodb数据更新**/
        //1车辆运单
        SckwWaybillOrder wOrder = new SckwWaybillOrder();
        wOrder.set_id(waybillOrder.getId());
        editSckwWaybillOrder(wOrder, waybillOrder, 2);

        /**5发送消息**/

        return HttpResult.ok("到达装货地点成功！");
    }

    /**
     * @param params {}
     * @desc 装货
     * @author zk
     * @date 2023/7/26
     **/
    @Transactional(rollbackFor = Exception.class)
    public HttpResult loading(WaybillOrderTicketDto params) {
        /**1数据校验**/
        KwtWaybillOrder waybillOrder = waybillOrderDao.selectById(params.getWOrderId());
        if (waybillOrder == null) {
            return HttpResult.error("车辆运单不存在！");
        }
        //到达装货地车辆运单才能装货
        if (waybillOrder.getStatus() != CarWaybillEnum.WAIT_LOADING.getCode()) {
            return HttpResult.error("车辆运单当前状态已不能装货！");
        }

        /**2更新车辆运单**/
        waybillOrder.setLoadAmount(params.getAmount());
        waybillOrder.setStatus(CarWaybillEnum.COMPLETION_LOADING.getCode());
        waybillOrderDao.updateById(waybillOrder);

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

        /**4新增装卸货榜单信息**/
        KwtWaybillOrderTicket ticket = new KwtWaybillOrderTicket();
        ticket.setWOrderId(waybillOrder.getId());
        ticket.setType(Global.NUMERICAL_ONE);
        ticket.setAmount(waybillOrder.getLoadAmount());
        ticket.setUrls(FileUtils.replaceAllBatch(params.getUrls()));
        ticket.setOperateTime(params.getOperateTime());
        waybillOrderTicketDao.insert(ticket);

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

        /**6更新承运订单entrustAmount
         KwtLogisticsOrder logisticsOrder = logisticsOrderDao.selectById(waybillOrder.getLOrderId());
         //承运订单已装货量=承运订单原装货量+当前车辆运单装货量
         BigDecimal loadAmount = logisticsOrder.getLoadAmount() == null ? new BigDecimal(Global.AMOUNT) : logisticsOrder.getLoadAmount();
         logisticsOrder.setLoadAmount(loadAmount.add(waybillOrder.getLoadAmount()));
         logisticsOrder.setLoadTime(logisticsOrder.getLoadTime() == null ?waybillOrder.getUpdateTime() : logisticsOrder.getLoadTime());
         logisticsOrderDao.updateById(logisticsOrder);**/

        /**7Mongodb数据更新**/
        //1车辆运单
        SckwWaybillOrder wOrder = new SckwWaybillOrder();
        wOrder.set_id(waybillOrder.getId());
        wOrder.setLoadAmount(waybillOrder.getLoadAmount());
        wOrder.setLoadUrls(FileUtils.replaceAllBatch(params.getUrls()));
        wOrder.setLoadTime(params.getOperateTime());
        editSckwWaybillOrder(wOrder, waybillOrder, 2);

        //2承运订单
        /*SckwLogisticsOrder lOrder = new SckwLogisticsOrder();
        lOrder.setLoadTime(logisticsOrder.getLoadTime());
        lOrder.setLoadAmount(logisticsOrder.getLoadAmount());
        editSckwLogisticsOrder(lOrder, logisticsOrder);*/

        /**8发送消息**/

        return HttpResult.ok("装货成功！");
    }

    /**
     * @param params {}
     * @desc 到达卸货地点
     * @author zk
     * @date 2023/7/26
     **/
    @Transactional(rollbackFor = Exception.class)
    public HttpResult arriveUnloadLocation(OperateWaybillDto params) {
        /**1数据校验**/
        KwtWaybillOrder waybillOrder = waybillOrderDao.selectById(params.getWOrderId());
        if (waybillOrder == null) {
            return HttpResult.error("车辆运单不存在！");
        }
        //已装货车辆运单才能到达卸货地点
        if (waybillOrder.getStatus() != CarWaybillEnum.COMPLETION_LOADING.getCode()) {
            return HttpResult.error("车辆运单当前状态已不能到达卸货地点！");
        }

        /**2更新车辆运单**/
        waybillOrder.setStatus(CarWaybillEnum.WAIT_UNLOADING.getCode());
        waybillOrderDao.updateById(waybillOrder);

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

        /**4Mongodb数据更新**/
        //1车辆运单
        SckwWaybillOrder wOrder = new SckwWaybillOrder();
        wOrder.set_id(waybillOrder.getId());
        editSckwWaybillOrder(wOrder, waybillOrder, 2);

        /**5发送消息**/

        return HttpResult.ok("到达卸货地点成功！");
    }

    /**
     * @param params {}
     * @desc 卸货
     * @author zk
     * @date 2023/7/26
     **/
    @Transactional(rollbackFor = Exception.class)
    public HttpResult unloading(WaybillOrderTicketDto params) {
        /**1数据校验**/
        KwtWaybillOrder waybillOrder = waybillOrderDao.selectById(params.getWOrderId());
        if (waybillOrder == null) {
            return HttpResult.error("车辆运单不存在！");
        }
        //到达卸货地车辆运单才能卸货
        if (waybillOrder.getStatus() != CarWaybillEnum.WAIT_UNLOADING.getCode()) {
            return HttpResult.error("车辆运单当前状态已不能装货！");
        }

        /**2更新车辆运单**/
        KwtLogisticsOrder logisticsOrder = logisticsOrderDao.selectById(waybillOrder.getLOrderId());
        waybillOrder.setUnloadAmount(params.getAmount());
        waybillOrder.setDeficitAmount(waybillOrder.getLoadAmount().subtract(waybillOrder.getUnloadAmount()));
        BigDecimal deficitPrice = deficitPrice(waybillOrder.getLoadAmount(), waybillOrder.getDeficitAmount(),
                logisticsOrder.getLoss(), logisticsOrder.getLossUnit(), logisticsOrder.getGoodsPrice());
        waybillOrder.setDeficitPrice(deficitPrice);
        waybillOrder.setStatus(CarWaybillEnum.COMPLETION_UNLOADING.getCode());
        waybillOrderDao.updateById(waybillOrder);

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

        /**4新增装卸货榜单信息**/
        KwtWaybillOrderTicket ticket = new KwtWaybillOrderTicket();
        ticket.setWOrderId(waybillOrder.getId());
        ticket.setType(Global.NUMERICAL_TWO);
        ticket.setAmount(waybillOrder.getUnloadAmount());
        ticket.setUrls(FileUtils.replaceAllBatch(params.getUrls()));
        ticket.setOperateTime(params.getOperateTime());
        waybillOrderTicketDao.insert(ticket);

        /**5循环派车重置派车信息kwt_logistics_order_circulate**/
        if (waybillOrder.getType() == Global.NUMERICAL_TWO) {
            //循环派车信息
            KwtLogisticsOrderCirculate circulate = logisticsOrderCirculateDao.findCirculate(waybillOrder.getLOrderId(),
                    waybillOrder.getTruckId(), waybillOrder.getDriverId());
            /*circulate.setWOrderId(null);
            logisticsOrderCirculateDao.updateById(circulate);*/
            Long newId = new IdWorker(Global.NUMERICAL_ONE).nextId();
            logisticsOrderCirculateDao.updateIdByKey(newId, null, circulate.getId(), waybillOrder.getUpdateBy(), waybillOrder.getUpdateTime());

            circulate = logisticsOrderCirculateDao.selectById(newId);
            //Mongodb 重新生成一条运单数据
            SckwWaybillOrder wOrder = setSckwWaybillOrder(circulate);
            wOrder.setWOrderId(waybillOrder.getId());
            editSckwWaybillOrder(wOrder, null, 3);
        }

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

        /**7更新承运订单entrustAmount
         //更新卸货量/卸货时间/亏吨/亏吨扣款
         //承运订单卸货量=承运订单原卸货量+当前车辆运单卸货量
         BigDecimal unloadAmount = logisticsOrder.getUnloadAmount() == null ? new BigDecimal(Global.AMOUNT) : logisticsOrder.getUnloadAmount();
         logisticsOrder.setUnloadAmount(unloadAmount.add(waybillOrder.getUnloadAmount()));
         logisticsOrder.setUnloadTime(waybillOrder.getUpdateTime());
         //承运订单亏吨量=承运订单装货量-承运订单卸货量
         logisticsOrder.setDeficitAmount(logisticsOrder.getLoadAmount().subtract(logisticsOrder.getUnloadAmount()));
         //承运订单亏吨扣款
         deficitPrice = deficitPrice(logisticsOrder.getLoadAmount(), logisticsOrder.getDeficitAmount(),
         logisticsOrder.getLoss(), logisticsOrder.getGoodsPrice());
         logisticsOrder.setDeficitPrice(deficitPrice);
         logisticsOrderDao.updateById(logisticsOrder);**/

        /**8Mongodb数据更新**/
        //1车辆运单
        SckwWaybillOrder wOrder = new SckwWaybillOrder();
        wOrder.set_id(waybillOrder.getId());
        wOrder.setUnloadAmount(waybillOrder.getUnloadAmount());
        wOrder.setDeficitAmount(waybillOrder.getDeficitAmount());
        wOrder.setDeficitPrice(waybillOrder.getDeficitPrice());
        wOrder.setUnloadUrls(FileUtils.replaceAllBatch(params.getUrls()));
        wOrder.setUnloadTime(params.getOperateTime());
        editSckwWaybillOrder(wOrder, waybillOrder, 2);

        //2承运订单
        /*SckwLogisticsOrder lOrder = new SckwLogisticsOrder();
        lOrder.setUnloadTime(logisticsOrder.getUnloadTime());
        lOrder.setUnloadAmount(logisticsOrder.getUnloadAmount());
        lOrder.setDeficitAmount(logisticsOrder.getDeficitAmount());
        lOrder.setDeficitPrice(logisticsOrder.getDeficitPrice());
        editSckwLogisticsOrder(lOrder, logisticsOrder);*/

        /**9发送消息**/

        return HttpResult.ok("卸货成功！");
    }

    /**
     * @param loadAmount    装货量
     * @param deficitAmount 亏吨量
     * @param loss          合理损耗
     * @param goodsPrice    货值单价
     * @desc 计算亏吨扣款
     * @author zk
     * @date 2023/7/27
     **/
    public BigDecimal deficitPrice(BigDecimal loadAmount, BigDecimal deficitAmount, BigDecimal loss,
                                   String lossUnit, BigDecimal goodsPrice) {
        //亏吨<=0
        if (deficitAmount.compareTo(new BigDecimal(Global.AMOUNT)) <= 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);
        }
        //罚款值=扣亏量 * 扣亏货值
        BigDecimal deficitPrice = deficitLossAmount.multiply(goodsPrice).setScale(4, RoundingMode.HALF_UP);
        return deficitPrice;
    }

    /**
     * @param lOrderId 承运订单ID
     * @description 校验当前承运订单是否运输完成(修改状态 + 统计量)
     * @author zk
     * @date 2023/7/27
     **/
    public void checkLogisticsByStatus(Long lOrderId) {
        /**
         校验当前承运订单是否运输完成（虑该当前承运订单上下级物流订单）
         1存在下级分包，下级物流订单和当前物流订单全部运输完成则修改当前物流订单状态为已完成（HAVE_FINISHED）、统计值
         2当前物流订单属于分包：需要判断上级及同级分包全部运输完成修改上级物流订单状态为已完成（HAVE_FINISHED）、统计值-一直向上到一级物流订单
         **/

        /**1存在下级分包**/
        KwtLogisticsOrder logisticsOrder = logisticsOrderDao.selectById(lOrderId);
        /**1-1校验下级分包是否全部运输完成**/
        boolean subcontractBool = checkSubcontract(logisticsOrder);

        /**1-2校验当前承运订单是否运输完成**/
        //车辆运单统计(运输中的物流订单+车辆运单审核通过)
        WaybillCountVo waybillCount = waybillOrderDao.findWaybillOrderCount(new HashMap() {{
            put("upperlOrderId", logisticsOrder.getId());
            put("passStatus", Global.NUMERICAL_ONE);
            put("logisticsStatus", LogisticsOrderEnum.IN_TRANSIT.getCode());
        }});
        //物流订单统计(运输完成后的物流订单)
        LogisticsCountVo LogisticsCount = logisticsOrderDao.findLogisticsOrderCount(new HashMap() {{
            put("upperlOrderId", logisticsOrder.getId());
            put("finishedStatus", Global.NUMERICAL_ONE);
        }});

        logisticsOrder.setTotalLoadAmount(waybillCount.getLoadAmount().add(LogisticsCount.getLoadAmount()));
        logisticsOrder.setTotalUnloadAmount(waybillCount.getUnloadAmount().add(LogisticsCount.getUnloadAmount()));
        logisticsOrderDao.updateById(logisticsOrder);

        /**1-3更新贸易订单总量**/
        if (logisticsLevel(logisticsOrder) == Global.NUMERICAL_ONE) {
            //物流订单统计(运输完成后的物流订单)
            LogisticsCountVo tradeCount = logisticsOrderDao.findLogisticsOrderCount(new HashMap<>() {{
                put("tOrderId", logisticsOrder.getTOrderId());
                put("level", Global.NUMERICAL_ONE);
            }});
            //查询贸易订单关联物流运单是否全部完结-totalUnfinished
            WaybillCountVo tradeCount1 = waybillOrderDao.findWaybillOrderCount(new HashMap<>() {{
                put("tOrderId", logisticsOrder.getTOrderId());
            }});
            UpdateActualAmountParam tradeOrder = new UpdateActualAmountParam();
            tradeOrder.setTOrderId(logisticsOrder.getTOrderId());
            tradeOrder.setActualLoadAmount(tradeCount.getLoadAmount());
            tradeOrder.setActualUnloadAmount(tradeCount.getUnloadAmount());
            tradeOrder.setUpdateBy(LoginUserHolder.getUserId());
            tradeOrder.setUpdateByName(LoginUserHolder.getUserName());
            tradeOrderInfoService.updateActualAmount(tradeOrder);
        }

        /**1-4Mongodb数据更新**/
        //承运订单
        SckwLogisticsOrder lOrder = new SckwLogisticsOrder();
        lOrder.setTotalLoadAmount(logisticsOrder.getTotalLoadAmount());
        lOrder.setTotalUnloadAmount(logisticsOrder.getTotalUnloadAmount());
        editSckwLogisticsOrder(lOrder, logisticsOrder);

        /**2当前物流订单属于分包(存在上级物流订单)**/
        //获取所有上级物流订单ID（当前物流订单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)) {
                    /**校验当前承运订单是否运输完成**/
                    checkLogisticsByStatus(pid);
                }
            }
        }
    }

    /**
     * @param lOrderId 承运订单ID
     * @description 校验当前承运订单是否运输完成(修改状态 + 统计量)
     * @author zk
     * @date 2023/7/27
     **/
    public void checkLogisticsByStatusV1(Long lOrderId) {
        /**
         校验当前承运订单是否运输完成（虑该当前承运订单上下级物流订单）
         1存在下级分包，下级物流订单和当前物流订单全部运输完成则修改当前物流订单状态为已完成（HAVE_FINISHED）、统计值
         2当前物流订单属于分包：需要判断上级及同级分包全部运输完成修改上级物流订单状态为已完成（HAVE_FINISHED）、统计值-一直向上到一级物流订单
         **/

        /**1存在下级分包**/
        KwtLogisticsOrder logisticsOrder = logisticsOrderDao.selectById(lOrderId);
        /**1-1校验下级分包是否全部运输完成**/
        boolean subcontractBool = checkSubcontract(logisticsOrder);

        /**1-2校验当前承运订单是否运输完成**/
        //车辆运单统计(运输中的物流订单+车辆运单审核通过)
        WaybillCountVo waybillCount = waybillOrderDao.findWaybillOrderCount(new HashMap() {{
            put("upperlOrderId", logisticsOrder.getId());
            put("passStatus", Global.NUMERICAL_ONE);
            put("logisticsStatus", LogisticsOrderEnum.IN_TRANSIT.getCode());
        }});
        //物流订单统计(运输完成后的物流订单)
        LogisticsCountVo LogisticsCount = logisticsOrderDao.findLogisticsOrderCount(new HashMap() {{
            put("upperlOrderId", logisticsOrder.getId());
            put("finishedStatus", Global.NUMERICAL_ONE);
        }});

        logisticsOrder.setTotalLoadAmount(waybillCount.getLoadAmount().add(LogisticsCount.getLoadAmount()));
        logisticsOrder.setTotalUnloadAmount(waybillCount.getUnloadAmount().add(LogisticsCount.getUnloadAmount()));
        BigDecimal subcontractAmount = logisticsOrder.getSubcontractAmount() == null ? new BigDecimal(Global.AMOUNT) : logisticsOrder.getSubcontractAmount();
        //物流运单状态（不包含已完成、已对账、已结算）+ 物流订单上级委派量-下游分包总量 <= 自己承运总装货量 + 下级分包全部运输完成
        if (!LogisticsOrderEnum.transportCompleted(logisticsOrder.getStatus())
                && logisticsOrder.getAmount().subtract(subcontractAmount).compareTo(waybillCount.getLoadAmount()) <= 0
                && subcontractBool) {
            //---------------------------------------------zk 2023-08-01 全量可运
            /**1-3下级分包承运订单运输完成**/
            logisticsOrder.setStatus(LogisticsOrderEnum.HAVE_FINISHED.getCode());//取消自动完结
            logisticsOrderDao.updateById(logisticsOrder);

            /**1-4承运订单状态记录**/
            KwtLogisticsOrderTrack orderTrack = new KwtLogisticsOrderTrack();
            orderTrack.setLOrderId(logisticsOrder.getId());
            orderTrack.setStatus(logisticsOrder.getStatus());
            orderTrack.setRemark(LogisticsOrderEnum.getName(logisticsOrder.getStatus()));
            logisticsOrderTrackDao.insert(orderTrack);

            /**1-5循环派车失效kwt_logistics_order_circulate**/
            //循环派车信息
            List<KwtLogisticsOrderCirculate> circulates = logisticsOrderCirculateDao.findCirculateList(logisticsOrder.getId(), null, null, 0);
            for (KwtLogisticsOrderCirculate circulate : circulates) {
                circulate.setStatus(Global.NUMERICAL_ONE);
                logisticsOrderCirculateDao.updateById(circulate);

                //车辆订单-Mongodb数据更新
                SckwWaybillOrder wOrder = new SckwWaybillOrder();
                wOrder.set_id(circulate.getId());
                KwtWaybillOrder waybillOrder = new KwtWaybillOrder();
                waybillOrder.setStatus(CarWaybillEnum.REVOKED.getCode());
                waybillOrder.setUpdateTime(circulate.getUpdateTime());
                waybillOrder.setUpdateBy(circulate.getUpdateBy());
                editSckwWaybillOrder(wOrder, waybillOrder, 2);
            }
        } else {
            logisticsOrderDao.updateById(logisticsOrder);
        }

        /**1-6更新贸易订单总量**/
        if (logisticsLevel(logisticsOrder) == Global.NUMERICAL_ONE) {
            //查询贸易订单总装货量/总卸货量
            WaybillCountVo tradeCount = waybillOrderDao.findWaybillOrderCount(new HashMap() {{
                put("tOrderId", logisticsOrder.getTOrderId());
                put("passStatus", Global.NUMERICAL_ONE);
            }});
            //查询贸易订单关联物流运单是否全部完结-totalUnfinished
            WaybillCountVo tradeCount1 = waybillOrderDao.findWaybillOrderCount(new HashMap() {{
                put("tOrderId", logisticsOrder.getTOrderId());
            }});
            CompleteLogisticsOrderParam tradeOrder = new CompleteLogisticsOrderParam();
            tradeOrder.setTOrderId(logisticsOrder.getTOrderId());
            tradeOrder.setActualLoadAmount(tradeCount.getLoadAmount());
            tradeOrder.setActualUnloadAmount(tradeCount.getUnloadAmount());
            tradeOrder.setIsAllComplete(tradeCount1.getTotalUnfinished() > 0 ? false : true);
            tradeOrder.setUpdateBy(LoginUserHolder.getUserId());
            tradeOrder.setUpdateByName(LoginUserHolder.getUserName());
            tradeOrderInfoService.completeLogisticsOrder(tradeOrder);
        }

        /**1-7Mongodb数据更新**/
        //承运订单
        SckwLogisticsOrder lOrder = new SckwLogisticsOrder();
        lOrder.setTotalLoadAmount(waybillCount.getLoadAmount());
        lOrder.setTotalUnloadAmount(waybillCount.getUnloadAmount());
        editSckwLogisticsOrder(lOrder, logisticsOrder);

        /**2当前物流订单属于分包(存在上级物流订单)**/
        //获取所有上级物流订单ID（当前物流订单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)) {
                    /**校验当前承运订单是否运输完成**/
                    checkLogisticsByStatus(pid);
                }
            }
        }
    }

    /**
     * @param logisticsOrder 物流订单
     * @desc 校验下级分包是否全部运输完成
     * @author zk
     * @date 2023/7/26
     **/
    public boolean checkSubcontract(KwtLogisticsOrder logisticsOrder) {
        boolean subcontractBool = true;
        BigDecimal subcontractAmount = logisticsOrder.getSubcontractAmount() == null ? new BigDecimal(Global.AMOUNT) : logisticsOrder.getSubcontractAmount();
        if (subcontractAmount.compareTo(new BigDecimal(Global.AMOUNT)) > 0) {
            /**1-1校验下级分包是否全部运输完成**/
            List<KwtLogisticsOrder> logisticsOrders = logisticsOrderDao.findLogisticsOrder(
                    new HashMap() {{
                        put("upperlOrderId", logisticsOrder.getId());
                        put("ownOrderId", logisticsOrder.getId());
                    }});
            for (KwtLogisticsOrder logisticsOrder1 : logisticsOrders) {
                if (!LogisticsOrderEnum.transportCompleted(logisticsOrder1.getStatus())) {
                    //下级分包承运订单运输未完成
                    subcontractBool = false;
                    continue;
                }
            }
        }
        return subcontractBool;
    }

    /**
     * @param params {}
     * @desc 修改单证
     * @author zk
     * @date 2023/7/26
     **/
    @Transactional(rollbackFor = Exception.class)
    public HttpResult editTicket(WaybillOrderTicketDto params) {
        /**1校验**/
        KwtWaybillOrder waybillOrder = waybillOrderDao.selectById(params.getWOrderId());
        if (waybillOrder == null) {
            return HttpResult.error("车辆运单信息不存在！");
        }
        KwtWaybillOrderTicket ticket = waybillOrderTicketDao.findWaybillOrderTicket(params.getWOrderId(), params.getType());
        if (ticket == null) {
            return HttpResult.error("车辆运单榜单信息不存在！");
        }
        if (params.getType() == Global.NUMERICAL_ONE && (waybillOrder.getStatus() != CarWaybillEnum.COMPLETION_LOADING.getCode()
                && waybillOrder.getStatus() != CarWaybillEnum.WAIT_UNLOADING.getCode()
                && waybillOrder.getStatus() != CarWaybillEnum.COMPLETION_UNLOADING.getCode())) {
            return HttpResult.error("当前运单不能编辑装货榜单！");
        }
        if (params.getType() == Global.NUMERICAL_TWO && waybillOrder.getStatus() != CarWaybillEnum.COMPLETION_UNLOADING.getCode()) {
            return HttpResult.error("当前运单不能编辑卸货榜单！");
        }

        /**2更新车辆运单信息**/
        KwtLogisticsOrder logisticsOrder = logisticsOrderDao.selectById(waybillOrder.getLOrderId());
        waybillOrder.setLoadAmount(params.getType() == Global.NUMERICAL_ONE ? params.getAmount() : waybillOrder.getLoadAmount());
        waybillOrder.setUnloadAmount(params.getType() == Global.NUMERICAL_TWO ? params.getAmount() : waybillOrder.getUnloadAmount());
        waybillOrder.setDeficitAmount(waybillOrder.getLoadAmount().subtract(waybillOrder.getUnloadAmount()));
        BigDecimal deficitPrice = deficitPrice(waybillOrder.getLoadAmount(), waybillOrder.getDeficitAmount(),
                logisticsOrder.getLoss(), logisticsOrder.getLossUnit(), logisticsOrder.getGoodsPrice());
        waybillOrder.setDeficitPrice(deficitPrice);
        waybillOrderDao.updateById(waybillOrder);

        /**3更新榜单信息**/
        BeanUtils.copyProperties(params, ticket);
        ticket.setUrls(FileUtils.replaceAllBatch(ticket.getUrls()));
        waybillOrderTicketDao.updateById(ticket);

        /**4Mongodb数据更新**/
        //1车辆运单
        SckwWaybillOrder wOrder = new SckwWaybillOrder();
        wOrder.set_id(waybillOrder.getId());
        wOrder.setLoadAmount(params.getType() == Global.NUMERICAL_ONE ? params.getAmount() : null);
        wOrder.setLoadTime(params.getType() == Global.NUMERICAL_ONE ? params.getOperateTime() : null);
        wOrder.setLoadUrls(params.getType() == Global.NUMERICAL_ONE ? FileUtils.replaceAllBatch(params.getUrls()) : null);
        wOrder.setUnloadAmount(params.getType() == Global.NUMERICAL_TWO ? params.getAmount() : null);
        wOrder.setUnloadTime(params.getType() == Global.NUMERICAL_TWO ? params.getOperateTime() : null);
        wOrder.setUnloadUrls(params.getType() == Global.NUMERICAL_TWO ? FileUtils.replaceAllBatch(params.getUrls()) : null);
        wOrder.setDeficitAmount(waybillOrder.getDeficitAmount());
        wOrder.setDeficitPrice(waybillOrder.getDeficitPrice());
        editSckwWaybillOrder(wOrder, waybillOrder, Global.NUMERICAL_TWO);

        //2承运订单
        /*SckwLogisticsOrder lOrder = new SckwLogisticsOrder();
        lOrder.setUnloadTime(logisticsOrder.getUnloadTime());
        lOrder.setUnloadAmount(logisticsOrder.getUnloadAmount());
        lOrder.setDeficitAmount(logisticsOrder.getDeficitAmount());
        lOrder.setDeficitPrice(logisticsOrder.getDeficitPrice());
        editSckwLogisticsOrder(lOrder, logisticsOrder);*/

        return HttpResult.ok("修改单证成功！");
    }

    /**
     * @param params {}
     * @desc 单证审核（编辑单证）
     * @author zk
     * @date 2023/7/26
     **/
    @Transactional(rollbackFor = Exception.class)
    public HttpResult editTicket(WaybillOrderTicketV1Dto params) {
        /**1数据校验**/
        KwtWaybillOrder waybillOrder = waybillOrderDao.selectById(params.getWOrderId());
        if (waybillOrder == null) {
            return HttpResult.error("车辆运单不存在！");
        }
        //已卸货/审批不通过车辆运单才能审核
        if (waybillOrder.getStatus() != CarWaybillEnum.COMPLETION_UNLOADING.getCode()
                && waybillOrder.getStatus() != CarWaybillEnum.APPROVAL_NO_PASS.getCode()) {
            return HttpResult.error("车辆运单当前状态不能编辑！");
        }

        /**2更新车辆运单**/
        KwtLogisticsOrder logisticsOrder = logisticsOrderDao.selectById(waybillOrder.getLOrderId());
        waybillOrder.setLoadAmount(params.getLoadAmount());
        waybillOrder.setUnloadAmount(params.getUnloadAmount());
        waybillOrder.setDeficitAmount(waybillOrder.getLoadAmount().subtract(waybillOrder.getUnloadAmount()));
        BigDecimal deficitPrice = deficitPrice(waybillOrder.getLoadAmount(), waybillOrder.getDeficitAmount(),
                logisticsOrder.getLoss(), logisticsOrder.getLossUnit(), logisticsOrder.getGoodsPrice());
        waybillOrder.setDeficitPrice(deficitPrice);
        waybillOrder.setStatus(CarWaybillEnum.APPROVAL_IN.getCode());
        waybillOrderDao.updateById(waybillOrder);

        /**3更新榜单信息**/
        KwtWaybillOrderTicket loadTicket = waybillOrderTicketDao.findWaybillOrderTicket(params.getWOrderId(), Global.NUMERICAL_ONE);
        loadTicket.setAmount(params.getLoadAmount());
        loadTicket.setUrls(FileUtils.replaceAllBatch(params.getLoadUrls()));
        loadTicket.setOperateTime(params.getLoadOperateTime());
        waybillOrderTicketDao.updateById(loadTicket);
        KwtWaybillOrderTicket unloadTicket = waybillOrderTicketDao.findWaybillOrderTicket(params.getWOrderId(), Global.NUMERICAL_TWO);
        unloadTicket.setAmount(params.getUnloadAmount());
        unloadTicket.setUrls(FileUtils.replaceAllBatch(params.getUnloadUrls()));
        unloadTicket.setOperateTime(params.getUnloadOperateTime());
        waybillOrderTicketDao.updateById(unloadTicket);

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

        /**5Mongodb数据更新**/
        //1车辆运单
        SckwWaybillOrder wOrder = new SckwWaybillOrder();
        wOrder.set_id(waybillOrder.getId());
        wOrder.setLoadAmount(waybillOrder.getLoadAmount());
        wOrder.setLoadTime(params.getLoadOperateTime());
        wOrder.setLoadUrls(FileUtils.replaceAllBatch(params.getLoadUrls()));
        wOrder.setUnloadAmount(waybillOrder.getUnloadAmount());
        wOrder.setUnloadTime(params.getUnloadOperateTime());
        wOrder.setUnloadUrls(FileUtils.replaceAllBatch(params.getUnloadUrls()));
        wOrder.setDeficitAmount(waybillOrder.getDeficitAmount());
        wOrder.setDeficitPrice(waybillOrder.getDeficitPrice());
        editSckwWaybillOrder(wOrder, waybillOrder, Global.NUMERICAL_TWO);

        /**5发送消息**/

        return HttpResult.ok("车辆运单单证更新完成！");
    }

    /**
     * @param wOrderId
     * @desc 修改单证查询运单
     * @author zk
     * @date 2023/8/10
     **/
    public HttpResult ticketWaybillOrder(Long wOrderId) {
        //车辆运单信息
        KwtWaybillOrder waybillOrder = waybillOrderDao.selectById(wOrderId);
        if (waybillOrder == null) {
            return HttpResult.error("车辆运单信息不存在！");
        }
        //装货榜单
        KwtWaybillOrderTicket loadTicket = waybillOrderTicketDao.findWaybillOrderTicket(wOrderId, Global.NUMERICAL_ONE);
        //卸货榜单
        KwtWaybillOrderTicket unloadTicket = waybillOrderTicketDao.findWaybillOrderTicket(wOrderId, Global.NUMERICAL_TWO);
        //装货地址
        KwtWaybillOrderAddress loadAddress = this.getAddress(waybillOrder.getId(), Global.NUMERICAL_ONE, Global.NUMERICAL_TWO);
        //卸货地址
        KwtWaybillOrderAddress unloadAddress = this.getAddress(waybillOrder.getId(), Global.NUMERICAL_TWO, Global.NUMERICAL_TWO);
        //商品信息
        KwtLogisticsOrderGoods goods = logisticsOrderGoodsDao.findByGoods(waybillOrder.getLOrderId());
        //审批意见
        KwtWaybillOrderTrack track = waybillOrderTrackDao.findWaybillOrderTrack(waybillOrder.getId(), CarWaybillEnum.APPROVAL_NO_PASS.getCode());

        //用户数据集
        List<Long> createBys = new ArrayList() {{
            add(loadTicket != null ? loadTicket.getUpdateBy() : null);
            add(unloadTicket != null ? unloadTicket.getUpdateBy() : null);
            add(track != null ? track.getCreateBy() : null);
        }};
        createBys = createBys.stream().distinct().collect(Collectors.toList());
        List<UserInfoVo> users = commonService.findUserList(createBys);
        Map<Long, String> usersMap = new HashMap<>(Global.NUMERICAL_SIXTEEN);
        users.forEach(e -> usersMap.put(e.getId(), e.getName()));

        Map result = new HashMap();
        result.put("wOrderId", wOrderId);
        result.put("wOrderNo", waybillOrder.getWOrderNo());
        result.put("status", waybillOrder.getStatus());
        result.put("truckNo", waybillOrder.getTruckNo());
        result.put("driverName", waybillOrder.getDriverName());
        result.put("driverPhone", waybillOrder.getDriverPhone());
        result.put("driverIdcard", waybillOrder.getDriverIdcard());
        result.put("goodsName", goods != null ? goods.getGoodsName() : null);
        result.put("loadStatus", loadTicket != null ? 0 : 1);
        result.put("loadAmount", loadTicket != null ? loadTicket.getAmount() : null);
        result.put("loadUrls", loadTicket != null ? FileUtils.spliceBatch(loadTicket.getUrls()) : null);
        result.put("loadOperateTime", loadTicket != null ? DateUtil.dateTimeFormatter(loadTicket.getOperateTime()) : null);
        result.put("loadCreateTime", loadTicket != null ? DateUtil.dateTimeFormatter(loadTicket.getCreateTime()) : null);
        result.put("loadCreateByName", usersMap.get(loadTicket.getUpdateBy()));
        result.put("loadCityName", loadAddress != null ? loadAddress.getCityName() : null);
        result.put("loadDetailAddress", loadAddress != null ? loadAddress.getDetailAddress() : null);
        result.put("unloadStatus", loadTicket != null ? 0 : 1);
        result.put("unloadAmount", unloadTicket != null ? unloadTicket.getAmount() : null);
        result.put("unloadUrls", unloadTicket != null ? FileUtils.spliceBatch(unloadTicket.getUrls()) : null);
        result.put("unloadOperateTime", unloadTicket != null ? DateUtil.dateTimeFormatter(unloadTicket.getOperateTime()) : null);
        result.put("unloadCreateTime", unloadTicket != null ? DateUtil.dateTimeFormatter(unloadTicket.getCreateTime()) : null);
        result.put("unloadCreateByName", usersMap.get(unloadTicket.getUpdateBy()));
        result.put("unloadCityName", unloadAddress != null ? unloadAddress.getCityName() : null);
        result.put("unloadDetailAddress", unloadAddress != null ? unloadAddress.getDetailAddress() : null);
        result.put("approvalTime", track != null ? DateUtils.formatV1(track.getCreateTime()) : null);
        result.put("approvalOpinions", track != null ? track.getRemark() : null);
        result.put("approver", usersMap.get(track != null ? track.getUpdateBy() : null));
        return HttpResult.ok(result);
    }

    /**
     * @param params {}
     * @desc 单证审核
     * @author zk
     * @date 2023/7/26
     **/
    @Transactional(rollbackFor = Exception.class)
    public HttpResult approvalTicket(WaybillOrderApprovalDto params) {
        /**1数据校验**/
        KwtWaybillOrder waybillOrder = waybillOrderDao.selectById(params.getWOrderId());
        if (waybillOrder == null) {
            return HttpResult.error("车辆运单不存在！");
        }
        //已卸货/审批不通过车辆运单才能审核
        if (waybillOrder.getStatus() != CarWaybillEnum.COMPLETION_UNLOADING.getCode()
                && waybillOrder.getStatus() != CarWaybillEnum.APPROVAL_NO_PASS.getCode()
                && waybillOrder.getStatus() != CarWaybillEnum.APPROVAL_IN.getCode()) {
            return HttpResult.error("车辆运单当前状态已不能审核！");
        }
        //已卸货/审批不通过车辆运单只能审批通过或审批不通过
        if (params.getStatus() != Global.NO && params.getStatus() != Global.YES) {
            return HttpResult.error("车辆运单当前状态只能审批通过或审批不通过！");
        }

        /**2更新车辆运单**/
        int status = params.getStatus() == Global.NO ? CarWaybillEnum.APPROVAL_PASS.getCode() : CarWaybillEnum.APPROVAL_NO_PASS.getCode();
        waybillOrder.setStatus(status);
        waybillOrderDao.updateById(waybillOrder);

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

        if (waybillOrder.getStatus() == CarWaybillEnum.APPROVAL_PASS.getCode()) {
            /**4跟新司机/车辆数据**/
            //更新司机信息
            editDriver(waybillOrder.getDriverId());
            //更新车辆信息
            editTruck(waybillOrder.getTruckId());

            /**5更新承运订单信息**/
            //更新卸货量/卸货时间/亏吨/亏吨扣款
            Map queryParams = new HashMap();
            queryParams.put("lOrderId", waybillOrder.getLOrderId());
            queryParams.put("passStatus", Global.NUMERICAL_ONE);
            WaybillCountVo waybillCount = waybillOrderDao.findWaybillOrderCount(queryParams);

            //委派未运量=承运委派量-装货量
            KwtLogisticsOrder logisticsOrder = logisticsOrderDao.selectById(waybillOrder.getLOrderId());
            BigDecimal residue = waybillOrder.getEntrustAmount().subtract(waybillOrder.getLoadAmount());
            logisticsOrder.setEntrustAmount(logisticsOrder.getEntrustAmount().subtract(residue));
            logisticsOrder.setLoadAmount(waybillCount.getLoadAmount());
            logisticsOrder.setLoadTime(waybillCount.getLoadTime());
            logisticsOrder.setUnloadAmount(waybillCount.getUnloadAmount());
            logisticsOrder.setUnloadTime(waybillCount.getUnloadTime());
            logisticsOrder.setDeficitAmount(waybillCount.getDeficitAmount());
            BigDecimal deficitPrice = deficitPrice(waybillCount.getLoadAmount(), waybillCount.getDeficitAmount(),
                    logisticsOrder.getLoss(), logisticsOrder.getLossUnit(), logisticsOrder.getGoodsPrice());
            logisticsOrder.setDeficitPrice(deficitPrice);
            logisticsOrderDao.updateById(logisticsOrder);

            /**6Mongodb数据更新**/
            //2承运订单
            SckwLogisticsOrder lOrder = new SckwLogisticsOrder();
            lOrder.setLoadAmount(logisticsOrder.getLoadAmount());
            lOrder.setLoadTime(logisticsOrder.getLoadTime());
            lOrder.setUnloadAmount(logisticsOrder.getUnloadAmount());
            lOrder.setUnloadTime(logisticsOrder.getUnloadTime());
            lOrder.setDeficitAmount(logisticsOrder.getDeficitAmount());
            lOrder.setDeficitPrice(logisticsOrder.getDeficitPrice());
            editSckwLogisticsOrder(lOrder, logisticsOrder);

            /**7校验当前承运订单是否运输完成(修改状态+统计量)**/
            checkLogisticsByStatus(waybillOrder.getLOrderId());
        }

        /**8Mongodb数据更新**/
        //1车辆运单
        SckwWaybillOrder wOrder = new SckwWaybillOrder();
        wOrder.set_id(waybillOrder.getId());
        editSckwWaybillOrder(wOrder, waybillOrder, Global.NUMERICAL_TWO);

        /**8发送消息**/

        return HttpResult.ok("车辆运单审核完成！");
    }

    /**
     * @param params {}
     * @desc 单证审核（编辑单证）
     * @author zk
     * @date 2023/7/26
     **/
    @Transactional(rollbackFor = Exception.class)
    public HttpResult approvalEditTicket(WaybillOrderTicketApprovalDto params) {
        /**1数据校验**/
        KwtWaybillOrder waybillOrder = waybillOrderDao.selectById(params.getWOrderId());
        if (waybillOrder == null) {
            return HttpResult.error("车辆运单不存在！");
        }
        //已卸货/审批不通过车辆运单才能审核
        if (waybillOrder.getStatus() != CarWaybillEnum.COMPLETION_UNLOADING.getCode()
                && waybillOrder.getStatus() != CarWaybillEnum.APPROVAL_NO_PASS.getCode()
                && waybillOrder.getStatus() != CarWaybillEnum.APPROVAL_IN.getCode()) {
            return HttpResult.error("车辆运单当前状态已不能审核！");
        }
        //已卸货/审批不通过车辆运单只能审批通过或审批不通过
        if (params.getStatus() != Global.NO && params.getStatus() != Global.YES) {
            return HttpResult.error("车辆运单当前状态只能审批通过或审批不通过！");
        }

        /**2更新车辆运单**/
        KwtLogisticsOrder logisticsOrder = logisticsOrderDao.selectById(waybillOrder.getLOrderId());
        int status = params.getStatus() == Global.NO ? CarWaybillEnum.APPROVAL_PASS.getCode() : CarWaybillEnum.APPROVAL_NO_PASS.getCode();
        waybillOrder.setLoadAmount(params.getLoadAmount());
        waybillOrder.setUnloadAmount(params.getUnloadAmount());
        waybillOrder.setDeficitAmount(waybillOrder.getLoadAmount().subtract(waybillOrder.getUnloadAmount()));
        BigDecimal deficitPrice = deficitPrice(waybillOrder.getLoadAmount(), waybillOrder.getDeficitAmount(),
                logisticsOrder.getLoss(), logisticsOrder.getLossUnit(), logisticsOrder.getGoodsPrice());
        waybillOrder.setDeficitPrice(deficitPrice);
        waybillOrder.setStatus(status);
        waybillOrderDao.updateById(waybillOrder);

        /**3更新榜单信息**/
        KwtWaybillOrderTicket loadTicket = waybillOrderTicketDao.findWaybillOrderTicket(params.getWOrderId(), Global.NUMERICAL_ONE);
        loadTicket.setAmount(params.getLoadAmount());
        loadTicket.setUrls(FileUtils.replaceAllBatch(params.getLoadUrls()));
        loadTicket.setOperateTime(params.getLoadOperateTime());
        waybillOrderTicketDao.updateById(loadTicket);
        KwtWaybillOrderTicket unloadTicket = waybillOrderTicketDao.findWaybillOrderTicket(params.getWOrderId(), Global.NUMERICAL_TWO);
        unloadTicket.setAmount(params.getUnloadAmount());
        unloadTicket.setUrls(FileUtils.replaceAllBatch(params.getUnloadUrls()));
        unloadTicket.setOperateTime(params.getUnloadOperateTime());
        waybillOrderTicketDao.updateById(unloadTicket);

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

        if (waybillOrder.getStatus() == CarWaybillEnum.APPROVAL_PASS.getCode()) {
            /**5跟新司机/车辆数据**/
            //更新司机信息
            editDriver(waybillOrder.getDriverId());
            //更新车辆信息
            editTruck(waybillOrder.getTruckId());

            /**6更新承运订单信息**/
            //更新卸货量/卸货时间/亏吨/亏吨扣款
            Map queryParams = new HashMap();
            queryParams.put("lOrderId", waybillOrder.getLOrderId());
            queryParams.put("passStatus", Global.NUMERICAL_ONE);
            WaybillCountVo waybillCount = waybillOrderDao.findWaybillOrderCount(queryParams);

            //委派未运量=承运委派量-装货量
            BigDecimal residue = waybillOrder.getEntrustAmount().subtract(waybillOrder.getLoadAmount());
            logisticsOrder.setEntrustAmount(logisticsOrder.getEntrustAmount().subtract(residue));
            logisticsOrder.setLoadAmount(waybillCount.getLoadAmount());
            logisticsOrder.setLoadTime(waybillCount.getLoadTime());
            logisticsOrder.setUnloadAmount(waybillCount.getUnloadAmount());
            logisticsOrder.setUnloadTime(waybillCount.getUnloadTime());
            logisticsOrder.setDeficitAmount(waybillCount.getDeficitAmount());
            deficitPrice = deficitPrice(waybillCount.getLoadAmount(), waybillCount.getDeficitAmount(),
                    logisticsOrder.getLoss(), logisticsOrder.getLossUnit(), logisticsOrder.getGoodsPrice());
            logisticsOrder.setDeficitPrice(deficitPrice);
            logisticsOrderDao.updateById(logisticsOrder);

            /**7Mongodb数据更新**/
            //2承运订单
            SckwLogisticsOrder lOrder = new SckwLogisticsOrder();
            lOrder.setLoadAmount(logisticsOrder.getLoadAmount());
            lOrder.setLoadTime(logisticsOrder.getLoadTime());
            lOrder.setUnloadAmount(logisticsOrder.getUnloadAmount());
            lOrder.setUnloadTime(logisticsOrder.getUnloadTime());
            lOrder.setDeficitAmount(logisticsOrder.getDeficitAmount());
            lOrder.setDeficitPrice(logisticsOrder.getDeficitPrice());
            editSckwLogisticsOrder(lOrder, logisticsOrder);

            /**8校验当前承运订单是否运输完成(修改状态+统计量)**/
            checkLogisticsByStatus(waybillOrder.getLOrderId());
        }

        /**9Mongodb数据更新**/
        //1车辆运单
        SckwWaybillOrder wOrder = new SckwWaybillOrder();
        wOrder.set_id(waybillOrder.getId());
        wOrder.setLoadAmount(waybillOrder.getLoadAmount());
        wOrder.setLoadTime(params.getLoadOperateTime());
        wOrder.setLoadUrls(FileUtils.replaceAllBatch(params.getLoadUrls()));
        wOrder.setUnloadAmount(waybillOrder.getUnloadAmount());
        wOrder.setUnloadTime(params.getUnloadOperateTime());
        wOrder.setUnloadUrls(FileUtils.replaceAllBatch(params.getUnloadUrls()));
        wOrder.setDeficitAmount(waybillOrder.getDeficitAmount());
        wOrder.setDeficitPrice(waybillOrder.getDeficitPrice());
        editSckwWaybillOrder(wOrder, waybillOrder, Global.NUMERICAL_TWO);

        /**8发送消息**/

        return HttpResult.ok("车辆运单审核完成！");
    }

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

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

    /**
     * @param truckId 车辆档案ID
     * @desc 车辆信息
     * @author zk
     * @date 2023/8/3
     **/
    public RTruckVo findTruck(Long truckId) {
        return remoteFleetService.findTruck(truckId);
    }

    /** 当前物流订单是全量下游则只能全量可运、否则可委托量或全量
     校验上游是否全量，并获取全量跟节点物流订单或贸易订单(可委派量)
     1、派车、循环派车接单需校验贸易订单/物流订单是否委派完成；
     2、装货需要统计物流订单总装货量；
     3、卸货需要统计物流订单总卸货量，变更上游状态；
     */

    /**
     * @param lOrderId      物流订单信息ID
     * @param entrustAmount 委托量
     * @desc 校验委托量是否大于剩余可运量（趟次派车/循环运单接单、委托/全量可运）
     * @author zk
     * @date 2023/8/7
     **/
    public boolean checkResidueAmount(Long lOrderId, BigDecimal entrustAmount) {
        //物流订单
        KwtLogisticsOrder logisticsOrder = logisticsOrderDao.selectById(lOrderId);
        /**存在全量可运**/
        if (isComplete(logisticsOrder)) {
            //获取所有上级物流订单ID（当前物流订单ID除外）
            List<Long> idArray = (List) CollectionUtils.toList(logisticsOrder.getPids(), false);
            for (Long id : idArray) {
                //当前物流订单ID除外
                if (id != lOrderId) {
                    KwtLogisticsOrder order = logisticsOrderDao.selectById(id);
                    if (!isComplete(order)) {

                    }
                }
            }


        }
        return true;
    }

    /**
     * @param params 物流订单信息
     * @desc 校验物流订单是否全量可运
     * @author zk
     * @date 2023/8/7
     **/
    public boolean isComplete(KwtLogisticsOrder params) {
        if (params == null) {
            return true;
        }

        //全量可运-已委托量(上游给他分配的量)为0
        BigDecimal entrustAmount = params.getEntrustAmount() == null ? new BigDecimal(Global.AMOUNT) : params.getEntrustAmount();
        if (entrustAmount.compareTo(new BigDecimal(Global.AMOUNT)) == 0) {
            return true;
        }
        return false;
    }

    /**
     * @param params 物流订单信息
     * @desc 校验物流订单是否有分包
     * @author zk
     * @date 2023/8/7
     **/
    public boolean isSubcontract(KwtLogisticsOrder params) {
        if (params == null) {
            return true;
        }

        //存在下级分包
        BigDecimal subcontractAmount = params.getSubcontractAmount() == null ? new BigDecimal(Global.AMOUNT) : params.getSubcontractAmount();
        if (subcontractAmount.compareTo(new BigDecimal(Global.AMOUNT)) > 0) {
            return true;
        }
        return false;
    }

    /**
     * 承运订单-托运订单-订单详情数据统计
     * @param orderId
     * @param type
     * @return
     */
    public Map<String, Integer> statisticsByOrderId(String orderId, String type) {
        Map<String, Integer> map = new HashMap<>();
        if (String.valueOf(NumberConstant.ONE).equals(type)) {
            map = statisticsConsignByOrderId(orderId);
        } else if (String.valueOf(NumberConstant.TWO).equals(type)) {
            map = statisticsCarriageByOrderId(orderId);
        } else {
            throw new BusinessException("统计类型异常");
        }
        return map;
    }

    /**
     * 承运数据统计
     * @param orderId
     * @return
     */
    private Map<String, Integer> statisticsCarriageByOrderId(String orderId) {
        Map<String, Integer> map = new HashMap<>();
        /**
         * 【进行】：对应【待接单】、【待出车】、【已出车】、【到达装货地点】、【已装货】、【已卸货】、【到达卸货地点】【审核不通过:12】【单证更新审核中】
         * 【完成】：对应【已核单】
         * 【退回】：对应【拒绝接单】、【拒绝出车】、【单趟撤回】
         * */
        List<Integer> orderStatusList = new ArrayList<>();
        orderStatusList.add(CarWaybillEnum.PENDING_ORDER.getCode());
        orderStatusList.add(CarWaybillEnum.PENDING_VEHICLE.getCode());
        orderStatusList.add(CarWaybillEnum.EXIT_COMPLETED.getCode());
        orderStatusList.add(CarWaybillEnum.WAIT_LOADING.getCode());
        orderStatusList.add(CarWaybillEnum.COMPLETION_LOADING.getCode());
        orderStatusList.add(CarWaybillEnum.WAIT_UNLOADING.getCode());
        orderStatusList.add(CarWaybillEnum.COMPLETION_UNLOADING.getCode());
        orderStatusList.add(CarWaybillEnum.APPROVAL_NO_PASS.getCode());
        orderStatusList.add(CarWaybillEnum.APPROVAL_IN.getCode());
        Integer proceed = logisticsOrderDao.selectCountByLorderId(orderId, orderStatusList);
        map.put("proceed", proceed);
        orderStatusList.clear();

        orderStatusList.add(CarWaybillEnum.APPROVAL_PASS.getCode());
        Integer finish = logisticsOrderDao.selectCountByLorderId(orderId, orderStatusList);
        map.put("finish", finish);

        orderStatusList.clear();
        orderStatusList.add(CarWaybillEnum.REJECT_ORDER.getCode());
        orderStatusList.add(CarWaybillEnum.REFUSE_TRAFFIC.getCode());
        orderStatusList.add(CarWaybillEnum.REVOKED.getCode());
//        orderStatusList.add(CarWaybillEnum.APPROVAL_NO_PASS.getCode());
        Integer cancel = logisticsOrderDao.selectCountByLorderId(orderId, orderStatusList);
        map.put("cancel", cancel);

        map.put("total", proceed + finish + cancel);
        return map;
    }

    /**
     * 托运数据统计
     * @param orderId
     * @return
     */
    private Map<String, Integer> statisticsConsignByOrderId(String orderId) {

        Map<String, Integer> map = new HashMap<>();
        /**
         * 【进行】：对应【待接单】、【待出车】、【已出车】、【到达装货地点】、【已装货】、【到达卸货地点】
         * 【完成】：对应【已卸货】、【已核单】
         * 【退回】：对应【拒绝接单】、【拒绝出车】、【单趟撤回】
         * */
        List<Integer> orderStatusList = new ArrayList<>();
        orderStatusList.add(CarWaybillEnum.PENDING_ORDER.getCode());
        orderStatusList.add(CarWaybillEnum.PENDING_VEHICLE.getCode());
        orderStatusList.add(CarWaybillEnum.EXIT_COMPLETED.getCode());
        orderStatusList.add(CarWaybillEnum.WAIT_LOADING.getCode());
        orderStatusList.add(CarWaybillEnum.COMPLETION_LOADING.getCode());
        orderStatusList.add(CarWaybillEnum.WAIT_UNLOADING.getCode());
        orderStatusList.add(CarWaybillEnum.APPROVAL_NO_PASS.getCode());
        orderStatusList.add(CarWaybillEnum.APPROVAL_IN.getCode());
        orderStatusList.add(CarWaybillEnum.COMPLETION_UNLOADING.getCode());
        orderStatusList.add(CarWaybillEnum.APPROVAL_NO_PASS.getCode());
        Integer proceed = logisticsOrderDao.selectCountByLorderId(orderId, orderStatusList);
        map.put("proceed", proceed);

        orderStatusList.clear();
        orderStatusList.add(CarWaybillEnum.APPROVAL_PASS.getCode());
        Integer finish = logisticsOrderDao.selectCountByLorderId(orderId, orderStatusList);
        map.put("finish", finish);

        orderStatusList.clear();
        orderStatusList.add(CarWaybillEnum.REJECT_ORDER.getCode());
        orderStatusList.add(CarWaybillEnum.REFUSE_TRAFFIC.getCode());
        orderStatusList.add(CarWaybillEnum.REVOKED.getCode());
        Integer cancel = logisticsOrderDao.selectCountByLorderId(orderId, orderStatusList);
        map.put("cancel", cancel);

        map.put("total", proceed + finish + cancel);
        return map;
    }

    /**
     * 查询已排量、待运量数据
     * @param orderId 物流订单id
     * @return
     */
    public HttpResult getLogisticsAmountByOrderId(String orderId) {
        KwtLogisticsOrder kwtLogisticsOrder = logisticsOrderDao.selectOne(new LambdaQueryWrapper<KwtLogisticsOrder>().eq(KwtLogisticsOrder::getId, Long.parseLong(orderId)));
        if (kwtLogisticsOrder == null) {
            return HttpResult.error("单据不存在!");
        }
        BigDecimal amount = kwtLogisticsOrder.getAmount();
        BigDecimal entrustAmount = kwtLogisticsOrder.getEntrustAmount() == null ? new BigDecimal("0.00") : kwtLogisticsOrder.getEntrustAmount();
        BigDecimal subcontractAmount = kwtLogisticsOrder.getSubcontractAmount() == null ? new BigDecimal("0.00") : kwtLogisticsOrder.getSubcontractAmount();
        BigDecimal waitDistributionAmount = amount.subtract(entrustAmount).subtract(subcontractAmount);
        Map<String, Map> map = new HashMap(NumberConstant.SIXTEEN);
        //无效的车辆运单状态(其他状态不参与统计中)
        List<Long> statusList = new ArrayList<>();
//        statusList.add(CarWaybillEnum.PENDING_ORDER.getCode().longValue());
//        statusList.add(CarWaybillEnum.PENDING_VEHICLE.getCode().longValue());
        statusList.add(CarWaybillEnum.REJECT_ORDER.getCode().longValue());
        statusList.add(CarWaybillEnum.REFUSE_TRAFFIC.getCode().longValue());
        statusList.add(CarWaybillEnum.REVOKED.getCode().longValue());
//        statusList.add(CarWaybillEnum.APPROVAL_NO_PASS.getCode().longValue());
        //趟次
        Map<String, Object> tripMap = waybillOrderDao.selectOrderByOrderId(Long.parseLong(orderId), 1, statusList);
        tripMap.put("waitDistributionAmount", waitDistributionAmount);
        map.put("trip", tripMap);
        //循环
        Map<String, Object> loopMap = waybillOrderDao.selectOrderByOrderId(Long.parseLong(orderId), 2, statusList);
        loopMap.put("waitDistributionAmount", waitDistributionAmount);
        map.put("loop", loopMap);
        return HttpResult.ok(map);
    }

    /**
     * @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));
    }
}
