package com.sckw.transport.service;

import com.github.pagehelper.PageHelper;
import com.sckw.core.model.constant.Global;
import com.sckw.core.model.enums.CarWaybillEnum;
import com.sckw.core.model.enums.LogisticsOrderEnum;
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.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.stream.model.SckwBusSum;
import com.sckw.system.api.RemoteSystemService;
import com.sckw.system.api.model.dto.res.EntCacheResDto;
import com.sckw.transport.dao.*;
import com.sckw.transport.model.*;
import com.sckw.transport.model.dto.*;
import com.sckw.transport.model.vo.WaybillCountVo;
import com.sckw.transport.model.vo.WaybillOrderDriverVo;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
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 TODO
 * @date 2023/7/19 0019
 */
@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;
    @Resource
    private StreamBridge streamBridge;
    @DubboReference(version = "2.0.0", group = "design", check = false)
    private RemoteSystemService remoteSystemService;
    @DubboReference(version = "1.0.0", group = "design", check = false)
    private RemoteFleetService remoteFleetService;
    @DubboReference(version = "2.0.0", group = "design", check = false)
    private TradeOrderInfoService tradeOrderInfoService;

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

    /**
     * @param params {driverId 司机ID, month月份}
     * @desc 统计司机任务数（任务数/委派量/装货量/卸货量/亏吨量/亏吨扣款）
     * @author zk
     * @date 2023/8/1
     **/
    public Map findStatisticsSumByDriver(Map params){
        return waybillOrderDao.findStatisticsSumByDriver(params);
    }

    /**
     * @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 = Integer.parseInt(StringUtils.objectStr(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 == 1) {
            //查询司机任务列表-待接单
            waybillOrders = waybillOrderDao.findWaitWaybillOrderByDriver(params);
        } else {
            //查询司机任务列表-出车/执行/完结
            waybillOrders = waybillOrderDao.findOtherWaybillOrderByDriver(params);
        }

        /**数据组装**/
        List<Long> entIds = new ArrayList<>();
        for (WaybillOrderDriverVo waybillOrder:waybillOrders) {
            entIds.add(waybillOrder.getCarrierEntId());
        }
        //企业数据集
        entIds = entIds.stream().distinct().collect(Collectors.toList());
        Map<Long, EntCacheResDto> ents = remoteSystemService.queryEntCacheMapByIds(entIds);
        for (WaybillOrderDriverVo waybillOrder:waybillOrders) {
            EntCacheResDto ent = ents == null ? null : ents.get(waybillOrder.getCarrierEntId());
            waybillOrder.setCarrierFirmName(ent != null ? ent.getFirmName() : 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("status", 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", circulate.getStatus());
            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 (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(), Global.NO);
                changeWaybillOrderCirculate(circulate.getId(), params, null);
            }
        }

        if (waybillOrder != null) {
            if (!CarWaybillEnum.changeDriverAndTruck(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 (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(), Global.NO);
                changeWaybillOrderCirculate(circulate.getId(), null, params);
            }
        }

        if (waybillOrder != null) {
            if (!CarWaybillEnum.changeDriverAndTruck(waybillOrder.getStatus())) {
                return HttpResult.error("车辆运单当前状态不能变更车辆！");
            }
            /**更新车辆运单**/
            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.setId(circulateId);
            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());
        }
        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) {
            //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);
        }

        //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.compareTo(logisticsOrder.getAmount()) > 0) {
                    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);
        //卸货地址
        KwtWaybillOrderAddress unloadAddress = this.getAddress(logisticsOrder.getId(), Global.NUMERICAL_TWO);
        //托运企业
        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++) {
                    //车辆运单存储
                    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.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);
    }

    /**
     * @param waybillOrder 车辆订单信息
     * @param loadAddress 装货地址信息
     * @param unloadAddress 卸货地址信息
     * @desc 趟次派车数据存储
     * @author zk
     * @date 2023/7/21
     **/
    public void ranksSave(KwtWaybillOrder waybillOrder, KwtWaybillOrderAddress loadAddress, KwtWaybillOrderAddress unloadAddress) {
        /**车辆运单信息**/
        waybillOrder.setId(null);
        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.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(), 0);
        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;
        }
        return circulate;
    }

    /**
     * @param lOrderId 物流订单ID
     * @param addressType 地址类型（1装货地址、2卸货地址）
     * @desc 获取物流订单地址信息
     * @author zk
     * @date 2023/7/20
     **/
    public KwtWaybillOrderAddress getAddress(Long lOrderId, int addressType) {
        /**查询数据**/
        KwtLogisticsOrderAddress orderAddress = logisticsOrderAddressDao.findByAddress(lOrderId, addressType);

        /**组装数据**/
        KwtWaybillOrderAddress address = new KwtWaybillOrderAddress();
        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, int status, String remark) {
        KwtWaybillOrderTrack orderTrack = new KwtWaybillOrderTrack();
        orderTrack.setWOrderId(wOrderId);
        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.setWOrderNo("xxxxx");
        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 派车请求参数
     * @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.setLoadTime(sendCarDto.getLoadDateTime());
        order.setUnloadTime(sendCarDto.getUnloadDateTime());
        order.setType(sendCarDto.getType());
        order.setStartTime(sendCarDto.getLoadDateTime());
        order.setEndTime(sendCarDto.getUnloadDateTime());
        order.setEntrustAmount(new BigDecimal(sendCarDto.getEntrustAmount()));
        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(null);
        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());
        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());
        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 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.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("车辆运单撤回成功!");
    }

    /**
     * @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.getId());
        wOrder.setStatus(order.getStatus());
        wOrder.setUpdateTime(order.getUpdateTime());
        wOrder.setUpdateBy(order.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.getId());
        lOrder.setLOrderId(order.getId());
        lOrder.setEntrustAmount(order.getEntrustAmount());
        lOrder.setStatus(String.valueOf(order.getStatus()));
        lOrder.setUpdateTime(order.getUpdateTime());
        lOrder.setUpdateBy(order.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(), 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);
            //卸货地址
            KwtWaybillOrderAddress unloadAddress = this.getAddress(circulate.getLOrderId(), Global.NUMERICAL_TWO);
            //KwtWaybillOrder数据组装
            KwtWaybillOrder waybillOrder = new KwtWaybillOrder();
            waybillOrder.setEntId(LoginUserHolder.getEntId());
            waybillOrder.setLOrderId(circulate.getLOrderId());
            waybillOrder.setWOrderNo("xxxxxx");
            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());

            /**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());
            logisticsOrderCirculateDao.updateById(circulate);

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

            //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.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(), 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发送消息**/

        }

        /**循环派车**/
        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发送消息**/
        }

        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("车辆运单当前状态已不能出车！");
        }

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

        /**3新增运单状态记录**/
        setWaybillOrderTrack(waybillOrder.getId(), 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 确认/拒绝出车参数
     * @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(), 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(), 0);
            circulate.setStatus(Global.NUMERICAL_ONE);
            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发送消息**/

        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(), 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(), waybillOrder.getStatus(), params.getRemark());

        /**4新增装卸货榜单信息**/
        KwtWaybillOrderTicket ticket = new KwtWaybillOrderTicket();
        ticket.setWOrderId(waybillOrder.getId());
        ticket.setType(Global.NUMERICAL_ONE);
        ticket.setAmount(waybillOrder.getLoadAmount());
        ticket.setUrls(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(params.getUrls());
        wOrder.setLoadTime(waybillOrder.getUpdateTime());
        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(), 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.getGoodsPrice());
        waybillOrder.setDeficitPrice(deficitPrice);
        waybillOrder.setStatus(CarWaybillEnum.COMPLETION_UNLOADING.getCode());
        waybillOrderDao.updateById(waybillOrder);

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

        /**4新增装卸货榜单信息**/
        KwtWaybillOrderTicket ticket = new KwtWaybillOrderTicket();
        ticket.setWOrderId(waybillOrder.getId());
        ticket.setType(Global.NUMERICAL_TWO);
        ticket.setAmount(waybillOrder.getUnloadAmount());
        ticket.setUrls(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(), 0);
            circulate.setWOrderId(null);
            logisticsOrderCirculateDao.updateByPrimaryKey(circulate);
        }

        /**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(params.getUrls());
        wOrder.setUnloadTime(waybillOrder.getUpdateTime());
        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, BigDecimal goodsPrice) {
        //承运订单亏吨扣款=（承运订单亏吨量 -（承运订单装货量 * 承运订单合理损耗））* 扣亏货值
        loss = loss == null ? new BigDecimal(Global.AMOUNT) : loss;
        goodsPrice = goodsPrice == null ? new BigDecimal(Global.AMOUNT) : goodsPrice;
        BigDecimal deficitPrice = deficitAmount.subtract(loadAmount.multiply(loss).setScale(4, RoundingMode.HALF_UP))
                .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", 1); }});
        logisticsOrder.setTotalLoadAmount(waybillCount.getLoadAmount());
        logisticsOrder.setTotalUnloadAmount(waybillCount.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);
            }
        }

        /**1-6更新贸易订单总量**/
        if (logisticsLevel(logisticsOrder) == Global.NUMERICAL_ONE) {
            //查询贸易订单总装货量/总卸货量
            WaybillCountVo tradeCount = waybillOrderDao.findWaybillOrderCount( new HashMap(){{put("tOrderId", logisticsOrder.getTOrderId()); put("passStatus", 1); }});
            //查询贸易订单关联物流运单是否全部完结-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
     **/
    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("车辆运单榜单信息不存在！");
        }

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

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

        /**4Mongodb数据更新**/
        //1车辆运单
        SckwWaybillOrder wOrder = new SckwWaybillOrder();
        wOrder.set_id(waybillOrder.getId());
        wOrder.setLoadAmount(waybillOrder.getLoadAmount());
        wOrder.setLoadTime(params.getType() == 1 ? params.getOperateTime() : null);
        wOrder.setUnloadUrls(params.getType() == 1 ? params.getUrls() : null);
        wOrder.setUnloadAmount(waybillOrder.getUnloadAmount());
        wOrder.setUnloadTime(params.getType() == 2 ? params.getOperateTime() : null);
        wOrder.setLoadUrls(params.getType() == 2 ? params.getUrls() : null);
        wOrder.setDeficitAmount(waybillOrder.getDeficitAmount());
        wOrder.setDeficitPrice(waybillOrder.getDeficitPrice());
        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);*/

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

    /**
     * @param params {}
     * @desc 单证审核
     * @author zk
     * @date 2023/7/26
     **/
    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()) {
            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.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", 1);
            WaybillCountVo waybillCount = waybillOrderDao.findWaybillOrderCount(queryParams);

            //更新卸货量/卸货时间/亏吨/亏吨扣款
            KwtLogisticsOrder logisticsOrder = logisticsOrderDao.selectById(waybillOrder.getLOrderId());
            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.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, 2);

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