package com.sckw.transport.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
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.CarWaybillEnum;
import com.sckw.core.model.enums.LogisticsOrderEnum;
import com.sckw.core.model.enums.OrderRuleEnum;
import com.sckw.core.model.enums.RedisOrderGenerateEnum;
import com.sckw.core.model.page.PageRes;
import com.sckw.core.model.page.PageResult;
import com.sckw.core.utils.*;
import com.sckw.core.web.constant.HttpStatus;
import com.sckw.core.web.context.LoginUserHolder;
import com.sckw.core.web.response.HttpResult;
import com.sckw.excel.utils.DateUtil;
import com.sckw.excel.utils.ValidUtil;
import com.sckw.fleet.api.RemoteFleetService;
import com.sckw.fleet.api.model.vo.RTruckVo;
import com.sckw.mongo.enums.BusinessTypeEnum;
import com.sckw.mongo.model.SckwLogisticsOrder;
import com.sckw.order.api.dubbo.TradeOrderInfoService;
import com.sckw.order.api.model.*;
import com.sckw.product.api.dubbo.GoodsInfoService;
import com.sckw.product.api.model.KwpGoods;
import com.sckw.redis.config.RedisLockUtil;
import com.sckw.stream.enums.MessageEnum;
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.common.config.MessageUrlConfig;
import com.sckw.transport.dao.*;
import com.sckw.transport.model.*;
import com.sckw.transport.model.dto.LogisticsOrderDTO;
import com.sckw.transport.model.dto.OrderCarDTO;
import com.sckw.transport.model.dto.OrderFinishDTO;
import com.sckw.transport.model.param.LogisticsConsignmentParam;
import com.sckw.transport.model.vo.OrderFinishVO;
import com.sckw.transport.model.vo.PurchaseLogisticOrderExcelVo;
import com.sckw.transport.model.vo.SellLogisticOrderExcelVo;
import com.sckw.transport.model.vo.WaybillCountVo;
import io.seata.core.context.RootContext;
import io.seata.spring.annotation.GlobalTransactional;
import jakarta.annotation.Resource;
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.util.ObjectUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @author lfdc
 * @description 物流托运/分包托运Service
 * @date 2023-06-28 11:06:07
 */
@Slf4j
@Service
public class LogisticsConsignmentService {

    @Resource
    private StreamBridge streamBridge;

    @Autowired
    RedisLockUtil redisLockUtil;

    @Autowired
    public TransportCommonService transportCommonService;

    @Autowired
    KwtWaybillOrderService waybillOrderService;

    @Autowired
    MessageUrlConfig messageUrlConfig;

    @Autowired
    public CommonService commonService;

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

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

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

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

    @Autowired
    public KwtLogisticsOrderGoodsMapper kwtLogisticsOrderGoodsMapper;

    @Autowired
    public KwtLogisticsOrderContractMapper kwtLogisticsOrderContractMapper;

    @Autowired
    public KwtLogisticsOrderMapper kwtLogisticsOrderMapper;

    @Autowired
    public KwtLogisticsOrderAddressMapper kwtLogisticsOrderAddressMapper;

    @Autowired
    public KwtLogisticsOrderTrackMapper kwtLogisticsOrderTrackMapper;

    @Autowired
    public KwtLogisticsOrderUnitMapper kwtLogisticsOrderUnitMapper;

    @Autowired
    public KwtWaybillOrderMapper waybillOrderMapper;

    /**
     * 采购订单-物流托运生成托运订单
     *
     * @param bo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public HttpResult purchaseLogisticsConsignment(LogisticsConsignmentParam bo) {
        HttpResult httpResult = ValidUtil.serviceValid(bo);
        if (HttpStatus.SUCCESS_CODE != httpResult.getCode()) {
            return HttpResult.error(httpResult.getMsg());
        }
        HttpResult checked = checkParamData(bo);
        if (checked.getCode() != HttpStatus.SUCCESS_CODE) {
            return HttpResult.error(checked.getMsg());
        }
        logisticsConsignmentInsert(bo);
        return HttpResult.ok();
    }

    private HttpResult checkParamData(LogisticsConsignmentParam bo) {
        if (!ObjectUtils.isEmpty(bo.getLoss())) {
            if (bo.getLoss().compareTo(new BigDecimal("0.00")) < 0) {
                return HttpResult.error("合理损耗填写时,必须大于0");
            }
        }
        if (!ObjectUtils.isEmpty(bo.getGoodsPrice())) {
            if (bo.getGoodsPrice().compareTo(new BigDecimal("0.00")) < 0) {
                return HttpResult.error("扣亏货值填写时,必须大于0");
            }
        }
        return HttpResult.ok();
    }

    /**
     * 销售订单-物流托运生成托运订单
     *
     * @param bo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public HttpResult sellLogisticsConsignment(LogisticsConsignmentParam bo) {
        HttpResult httpResult = ValidUtil.serviceValid(bo);
        if (HttpStatus.SUCCESS_CODE != httpResult.getCode()) {
            return HttpResult.error(httpResult.getMsg());
        }
        HttpResult checked = checkParamData(bo);
        if (checked.getCode() != HttpStatus.SUCCESS_CODE) {
            return HttpResult.error(checked.getMsg());
        }
        logisticsConsignmentInsert(bo);
        return HttpResult.ok();
    }

    void logisticsConsignmentInsert(LogisticsConsignmentParam bo) {
        commonService.getRedisGenerateOrderNo();
        Long count = kwtLogisticsOrderMapper.selectCount(new LambdaQueryWrapper<KwtLogisticsOrder>().eq(KwtLogisticsOrder::getTOrderId, bo.getTOrderId()));
        String lOrderNo = OrderGenerateSeqNoUtils.getSeqNo(RedisOrderGenerateEnum.LOGISTICS_ORDER, OrderRuleEnum.LOGISTICS_ORDER, "1", "0", String.valueOf(count + 1));
        OrderDetailRes tradeOrder = tradeOrderInfoService.getOrderDetailById(Long.parseLong(bo.getTOrderId()));
        if (tradeOrder == null) {
            log.error("订单id查找失败:{}", bo.getTOrderId());
            throw new BusinessException("单据错误,数据不存在");
        }
        KwtLogisticsOrder order = new KwtLogisticsOrder();
        if (!bo.getIsFullDose()) {
            BigDecimal amount = bo.getAmount();
            BigDecimal carryingCapacity = bo.getCarryingCapacity();
            if (bo.getCarryingCapacity().compareTo(new BigDecimal("0.00")) == 0) {
                log.error("可分配量分配错误:{}", bo.getTOrderId());
                throw new BusinessException("可分配量分配必须填写大于0");
            }
            if (amount.compareTo(carryingCapacity) < 0) {
                log.error("可分配量分配错误:{}", bo.getTOrderId());
                throw new BusinessException("可分配量分配错误");
            }
            if (ArrayUtil.isEmpty(bo.getCarryingCapacity())) {
                throw new BusinessException("不是全量分配时,分配量不能为空!");
            }
            order.setAmount(bo.getCarryingCapacity());
        } else {
            order.setAmount(new BigDecimal("0.00"));
            order.setSubcontractAmount(new BigDecimal("0.00"));
        }
        Long orderId = new IdWorker(NumberConstant.ONE).nextId();
        Integer orderStatus = LogisticsOrderEnum.PENDING_ORDER.getCode();
        insertLogisticsGoods(bo, lOrderNo, orderId);
        insertLogisticsOrder(bo, lOrderNo, order, tradeOrder, orderId, orderStatus);
        insertLogisticsOrderContract(bo, orderId);
        insertLogisticsOrderUnit(bo, orderId);
        insertLogisticsOrderAddress(bo, orderId);
        insertLogisticsOrderTrack(bo, orderId, orderStatus);
        sendMongoDB(lOrderNo, orderId, bo, tradeOrder, orderStatus);

        /**将生成的分配量->贸易订单*/
        CreateOrCancelLogisticsOrderParam param = new CreateOrCancelLogisticsOrderParam();
        param.setTOrderId(Long.valueOf(bo.getTOrderId()));
        param.setEntrustAmount(bo.getCarryingCapacity());
        param.setUpdateBy(LoginUserHolder.getUserId());
        param.setUpdateByName(LoginUserHolder.getUserName());
        HttpResult httpResult = tradeOrderInfoService.createOrCancelLogisticsOrder(param);
        if (httpResult.getCode() != HttpStatus.SUCCESS_CODE) {
            log.info("{}生成物流托运失败!,返回信息:{}", tradeOrder.getTOrderNo(), JSONObject.toJSONString(httpResult));
            throw new BusinessException("{" + tradeOrder.getTOrderNo() + "}生成物流托运失败!" + httpResult.getMsg());
        }
        /**消息列表*/
        EntCacheResDto consignentMap = remoteSystemService.queryEntTreeById(Long.parseLong(bo.getConsignCompanyId()));
        EntCacheResDto checkentMap = remoteSystemService.queryEntTreeById(Long.parseLong(bo.getCheckCompanyId()));
        //托运单位
        KwtLogisticsOrderUnit checkUnit = new KwtLogisticsOrderUnit();

        checkUnit.setUnitType(1);
        checkUnit.setFirmName(bo.getCheckCompany());
        checkUnit.setEntId(Long.parseLong(bo.getCheckCompanyId()));
        checkUnit.setTopEntId(checkentMap == null ? null : checkentMap.getId());
        checkUnit.setContactsId(Long.parseLong(bo.getCheckContactsId()));

        //承运单位
        KwtLogisticsOrderUnit carriageUnit = new KwtLogisticsOrderUnit();
        carriageUnit.setUnitType(2);
        carriageUnit.setFirmName(bo.getConsignCompany());
        carriageUnit.setEntId(Long.parseLong(bo.getConsignCompanyId()));
        carriageUnit.setTopEntId(consignentMap == null ? null : consignentMap.getId());
        carriageUnit.setContactsId(Long.parseLong(bo.getConsignContactsId()));

//        commonService.initIatingLogisticsConsignment(checkUnit, carriageUnit, lOrderNo, LoginUserHolder.getUserId(), LoginUserHolder.getEntId());
        commonService.newSendLogisticsOrderToMessage(checkUnit, carriageUnit, lOrderNo, LoginUserHolder.getUserId(), LoginUserHolder.getEntId(),
                messageUrlConfig.getPc().getConsignLogisticsAddOrderUrl(), messageUrlConfig.getApp().getConsignLogisticsAddOrderUrl(),
                messageUrlConfig.getPc().getCarriageLogisticsAddOrderUrl(), messageUrlConfig.getApp().getCarriageLogisticsAddOrderUrl(),
                MessageEnum.INITIATING_LOGISTICS_CONSIGNMENT, MessageEnum.NEW_CARRIAGE_ORDER, "1");
    }

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

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

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

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

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

    /**
     * 物流订单-商品信息
     *
     * @param bo       页面请求数据
     * @param lOrderNo 物流订单编号
     * @param orderId  物流订单表编号
     */
    private void insertLogisticsGoods(LogisticsConsignmentParam bo, String lOrderNo, Long orderId) {
        KwtLogisticsOrderGoods kwtLogisticsOrderGoods = new KwtLogisticsOrderGoods();
        kwtLogisticsOrderGoods.setId(new IdWorker(NumberConstant.ONE).nextId());
        kwtLogisticsOrderGoods.setGoodsId(Long.parseLong(bo.getGoodsId()));
        kwtLogisticsOrderGoods.setGoodsName(bo.getGoodsName());
        kwtLogisticsOrderGoods.setSkuId(StringUtils.isBlank(bo.getSkuId()) ? null : Long.parseLong(bo.getSkuId()));
        kwtLogisticsOrderGoods.setLOrderId(orderId);
        kwtLogisticsOrderGoods.setLOrderNo(lOrderNo);
        kwtLogisticsOrderGoods.setUpdateBy(LoginUserHolder.getUserId());
        kwtLogisticsOrderGoods.setUpdateTime(new Date());
        kwtLogisticsOrderGoods.setCreateBy(LoginUserHolder.getUserId());
        kwtLogisticsOrderGoods.setCreateTime(new Date());
        kwtLogisticsOrderGoodsMapper.insert(kwtLogisticsOrderGoods);
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

//    /**
//     * 采购订单获取车辆信息
//     *
//     * @param id
//     * @param page
//     * @param pageSize
//     * @return
//     */
//    public HttpResult purchaseLogisticsCar(String id, Integer page, Integer pageSize) {
//        Long count = getLogisticsCarDataCount(id);
//        Integer newPage = page - 1;
//        List<OrderCarDTO> list = getLogisticsCarData(id, newPage, pageSize);
//        PageResult build = PageResult.build(page, pageSize, count, list);
//        return HttpResult.ok(build);
//    }


    /**
     * 采购订单获取车辆信息
     *
     * @param ids
     * @param page
     * @param pageSize
     * @return
     */
    public PageRes<OrderCarDTO> purchaseLogisticsCar(String ids, Integer page, Integer pageSize) {
        PageHelper.startPage(page, pageSize);
        List<String> stringList = StringUtils.splitStrToList(ids, String.class);
        if (CollectionUtils.isEmpty(stringList)) {
            PageRes<OrderCarDTO> pageRes = new PageRes<>();
            pageRes.setPages(page);
            pageRes.setPageSize(pageSize);
            return pageRes;
        }
        List<Long> idsList = StringUtils.splitStrToList(ids, Long.class);
        List<OrderCarDTO> orderCarList = waybillOrderMapper.selectWaybillOrderCarListByTradeOrderId(idsList);
        PageInfo<OrderCarDTO> info = new PageInfo<>(orderCarList);
        if (CollectionUtils.isEmpty(orderCarList)) {
            PageRes<OrderCarDTO> pageRes = new PageRes<>();
            pageRes.setPage(page);
            pageRes.setPageSize(pageSize);
            return pageRes;
        }
        List<String> collected = orderCarList.stream().map(OrderCarDTO::getTruckNo).distinct().collect(Collectors.toList());
        for (OrderCarDTO orderCarDTO : orderCarList) {
            if (CollectionUtils.isNotEmpty(collected)) {
                Map<String, RTruckVo> truck = remoteFleetService.findTruck(collected);
                orderCarDTO.setStatusLabel(CarWaybillEnum.getName(orderCarDTO.getStatus()));
                orderCarDTO.setLoadAmount(truck.get(orderCarDTO.getTruckNo()) == null ?
                        null : (truck.get(orderCarDTO.getTruckNo()).getActualWeight() == null ?
                        null : (String.valueOf(truck.get(orderCarDTO.getTruckNo()).getActualWeight()))));
            }
        }
        List<OrderCarDTO> returnList = new ArrayList<>();
        returnList.addAll(orderCarList);
        return PageRes.build(info, returnList);
//        stringList = stringList.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
//        for (String id : stringList) {
//            List<OrderCarDTO> list = waybillOrderMapper.selectWaybillOrderCarListNotPage(id);
//            List<String> collect = list.stream().map(OrderCarDTO::getTruckNo).distinct().collect(Collectors.toList());
//            if (CollectionUtils.isNotEmpty(collect)) {
//                Map<String, RTruckVo> truck = remoteFleetService.findTruck(collect);
//                for (OrderCarDTO orderCarDTO : list) {
//                    orderCarDTO.setStatusLabel(CarWaybillEnum.getName(orderCarDTO.getStatus()));
//                    orderCarDTO.setLoadAmount(truck.get(orderCarDTO.getTruckNo()) == null ?
//                            null : (truck.get(orderCarDTO.getTruckNo()).getActualWeight() == null ?
//                            null : (String.valueOf(truck.get(orderCarDTO.getTruckNo()).getActualWeight()))));
//                }
//            }
//            if (CollectionUtils.isNotEmpty(list)) {
//                returnList.addAll(list);
//            }
//        }
//        List<OrderCarDTO> subList = new ArrayList<>();
//        if (CollectionUtils.isNotEmpty(returnList)) {
//            subList = returnList.stream().skip((page - 1) * pageSize).limit(pageSize).collect(Collectors.toList());
//        }
//        PageResult build = PageResult.build(page, pageSize, returnList.stream().count(), subList);
//        return HttpResult.ok(build);
    }

    //    /**
//     * 销售订单获取车辆信息
//     *
//     * @param id
//     * @param page
//     * @param pageSize
//     * @return
//     */
//    public HttpResult sellLogisticsCar(String id, Integer page, Integer pageSize) {
//        Long count = getLogisticsCarDataCount(id);
//        Integer newPage = (page - 1) * pageSize;
//        List<OrderCarDTO> list = getLogisticsCarData(id, newPage, pageSize);
//        PageResult build = PageResult.build(page, pageSize, count, list);
//        return HttpResult.ok(build);
//    }

    /**
     * 销售订单-车辆列表-销售订单id
     *
     * @param ids
     * @param page
     * @param pageSize
     * @return
     */
    public HttpResult sellLogisticsCar(String ids, Integer page, Integer pageSize) {
        List<String> stringList = StringUtils.splitStrToList(ids, String.class);
        if (CollectionUtils.isEmpty(stringList)) {
            return HttpResult.ok();
        }
        List<OrderCarDTO> returnList = new ArrayList<>();
        stringList = stringList.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
        for (String id : stringList) {
            List<OrderCarDTO> list = waybillOrderMapper.selectWaybillOrderCarListNotPage(id);
            List<String> collect = list.stream().map(OrderCarDTO::getTruckNo).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(collect)) {
                Map<String, RTruckVo> truck = remoteFleetService.findTruck(collect);
                for (OrderCarDTO orderCarDTO : list) {
                    orderCarDTO.setStatusLabel(CarWaybillEnum.getName(orderCarDTO.getStatus()));
                    orderCarDTO.setLoadAmount(truck.get(orderCarDTO.getTruckNo()) == null ?
                            null : (truck.get(orderCarDTO.getTruckNo()).getActualWeight() == null ?
                            null : (String.valueOf(truck.get(orderCarDTO.getTruckNo()).getActualWeight()))));
                }
            }
            if (CollectionUtils.isNotEmpty(list)) {
                returnList.addAll(list);
            }
        }
        List<OrderCarDTO> subList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(returnList)) {
            subList = returnList.stream().skip((page - 1) * pageSize).limit(pageSize).collect(Collectors.toList());
        }
        PageResult build = PageResult.build(page, pageSize, returnList.stream().count(), subList);
        return HttpResult.ok(build);
    }

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

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

    /**
     * 采购订单/销售订单-托运订单列表-撤销托运
     *
     * @param ids    物流订单id
     * @param remark 备注
     * @param type   单据操作类型
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public HttpResult cancelConsign(List<String> ids, String remark, String type) {
        if (CollectionUtils.isEmpty(ids) || ids.size() < NumberConstant.ONE) {
            throw new BusinessException("单据id不能为空");
        }
        HttpResult result = new HttpResult();
        //1采购 2销售
        if (String.valueOf(NumberConstant.ONE).equals(type)) {
            result = cancelConsignByOrder(ids, remark);
        } else if (String.valueOf(NumberConstant.TWO).equals(type)) {
            result = cancelConsignBySellOrder(ids, remark);
        } else {
            throw new BusinessException("类型错误!");
        }
        return result;
    }

    /**
     * 销售订单撤销托运
     *
     * @param ids
     */
    public HttpResult cancelConsignBySellOrder(List<String> ids, String remark) {
        HttpResult result = new HttpResult();
        String s = ids.get(0);
        /**当前单据作废
         * 托运数量回归溯
         */
        KwtLogisticsOrder kwtLogisticsOrder = kwtLogisticsOrderMapper.selectOne(new LambdaUpdateWrapper<KwtLogisticsOrder>()
                .eq(KwtLogisticsOrder::getId, s));
        if (kwtLogisticsOrder == null || (!LogisticsOrderEnum.PENDING_ORDER.getStatus().equals(String.valueOf(kwtLogisticsOrder.getStatus())))) {
            log.info("物流订单单据id:{}", s);
            result.setMsg("单据状态异常或单据不存在");
            result.setCode(HttpStatus.GLOBAL_EXCEPTION_CODE);
            return result;
        } else {
            /**撤退推送接口数据溯源修改贸易订单已委托量*/
            CreateOrCancelLogisticsOrderParam param = new CreateOrCancelLogisticsOrderParam();
            param.setTOrderId(kwtLogisticsOrder.getTOrderId());
            param.setEntrustAmount(kwtLogisticsOrder.getAmount().negate());
            param.setUpdateBy(LoginUserHolder.getUserId());
            param.setUpdateByName(LoginUserHolder.getUserName());
            HttpResult httpResult = tradeOrderInfoService.createOrCancelLogisticsOrder(param);
            log.info("销售订单撤销托运-溯源贸易订单请求数据:{},返回数据:{}", JSONObject.toJSONString(param), JSONObject.toJSONString(httpResult));
            if (HttpStatus.SUCCESS_CODE == httpResult.getCode()) {
//                    kwtLogisticsOrder.setDelFlag(NumberConstant.ONE);
                kwtLogisticsOrder.setUpdateTime(new Date());
                kwtLogisticsOrder.setUpdateBy(LoginUserHolder.getUserId());
                kwtLogisticsOrderMapper.update(null, new LambdaUpdateWrapper<KwtLogisticsOrder>()
                        .eq(KwtLogisticsOrder::getId, kwtLogisticsOrder.getId())
                        .set(KwtLogisticsOrder::getStatus, LogisticsOrderEnum.CANCEL_ORDER.getCode())
                        .set(KwtLogisticsOrder::getUpdateBy, LoginUserHolder.getUserId())
                        .set(KwtLogisticsOrder::getUpdateTime, new Date()));
                KwtLogisticsOrderTrack orderTrack = kwtLogisticsOrderTrackMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrderTrack>()
                        .eq(KwtLogisticsOrderTrack::getLOrderId, s)
                        .eq(KwtLogisticsOrderTrack::getStatus, LogisticsOrderEnum.CANCEL_ORDER.getCode())
                );
                if (orderTrack == null) {
                    KwtLogisticsOrderTrack track = new KwtLogisticsOrderTrack();
                    track.setId(new IdWorker(NumberConstant.ONE).nextId());
                    track.setLOrderId(Long.valueOf(s));
                    track.setRemark(remark);
                    track.setStatus(LogisticsOrderEnum.CANCEL_ORDER.getCode());
                    track.setCreateBy(LoginUserHolder.getUserId());
                    track.setCreateTime(new Date());
                    track.setUpdateBy(LoginUserHolder.getUserId());
                    track.setUpdateTime(new Date());
                    kwtLogisticsOrderTrackMapper.insert(track);
                } else {
                    orderTrack.setRemark(remark);
                    orderTrack.setStatus(LogisticsOrderEnum.CANCEL_ORDER.getCode());
                    orderTrack.setUpdateBy(LoginUserHolder.getUserId());
                    orderTrack.setUpdateTime(new Date());
                    kwtLogisticsOrderTrackMapper.updateById(orderTrack);
                }
                //mongoDb数据
                SckwLogisticsOrder logisticsOrder = new SckwLogisticsOrder();
                logisticsOrder.set_id(Long.valueOf(s));
                logisticsOrder.setLOrderId(Long.valueOf(s));
                logisticsOrder.setStatus(LogisticsOrderEnum.CANCEL_ORDER.getStatus());
                logisticsOrder.setUpdateByName(LoginUserHolder.getUserName());
                logisticsOrder.setUpdateBy(LoginUserHolder.getUserId());
                logisticsOrder.setUpdateTime(new Date());
                SckwBusSum sckwBusSum = new SckwBusSum();
                sckwBusSum.setBusSumType(BusinessTypeEnum.LOGISTICS_ORDER_TYPE.getName());
                sckwBusSum.setMethod(NumberConstant.TWO);
                sckwBusSum.setObject(logisticsOrder);
                streamBridge.send("sckw-busSum", JSON.toJSONString(sckwBusSum));
                result.setMsg("操作成功");
                result.setCode(HttpStatus.SUCCESS_CODE);

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

    /**
     * 采购订单撤销托运
     *
     * @param ids
     */
    public HttpResult cancelConsignByOrder(List<String> ids, String remark) {
        HttpResult result = new HttpResult();
        String id = ids.get(0);
        /**当前单据作废
         * 托运数量回归溯
         */
        KwtLogisticsOrder kwtLogisticsOrder = kwtLogisticsOrderMapper.selectOne(new LambdaUpdateWrapper<KwtLogisticsOrder>()
                .eq(KwtLogisticsOrder::getId, Long.parseLong(id)));
        if (kwtLogisticsOrder == null || (!LogisticsOrderEnum.PENDING_ORDER.getStatus().equals(String.valueOf(kwtLogisticsOrder.getStatus())))) {
            log.info("物流订单单据id:{}", id);
            result.setCode(HttpStatus.GLOBAL_EXCEPTION_CODE);
            result.setMsg("单据状态异常或单据不存在");
            return result;
        } else {
            /**撤退推送接口数据溯源修改贸易订单已委托量*/
            CreateOrCancelLogisticsOrderParam param = new CreateOrCancelLogisticsOrderParam();
            param.setTOrderId(kwtLogisticsOrder.getTOrderId());
            param.setEntrustAmount(kwtLogisticsOrder.getAmount().negate());
            param.setUpdateBy(LoginUserHolder.getUserId());
            param.setUpdateByName(LoginUserHolder.getUserName());
            HttpResult httpResult = tradeOrderInfoService.createOrCancelLogisticsOrder(param);
            log.info("采购订单撤销托运-溯源贸易订单请求数据:{},返回数据:{}", JSONObject.toJSONString(param), JSONObject.toJSONString(httpResult));
            if (HttpStatus.SUCCESS_CODE == httpResult.getCode()) {
//                    kwtLogisticsOrder.setDelFlag(NumberConstant.ONE);
//                    kwtLogisticsOrder.setUpdateTime(new Date());
//                    kwtLogisticsOrder.setUpdateBy(LoginUserHolder.getUserId());
                kwtLogisticsOrderMapper.update(null, new LambdaUpdateWrapper<KwtLogisticsOrder>()
                        .eq(KwtLogisticsOrder::getId, kwtLogisticsOrder.getId())
                        .set(KwtLogisticsOrder::getStatus, LogisticsOrderEnum.CANCEL_ORDER.getCode())
                        .set(KwtLogisticsOrder::getUpdateBy, LoginUserHolder.getUserId())
                        .set(KwtLogisticsOrder::getUpdateTime, new Date()));
                KwtLogisticsOrderTrack orderTrack = kwtLogisticsOrderTrackMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrderTrack>()
                        .eq(KwtLogisticsOrderTrack::getLOrderId, id)
                        .eq(KwtLogisticsOrderTrack::getStatus, LogisticsOrderEnum.CANCEL_ORDER.getCode())
                );
                if (orderTrack == null) {
                    KwtLogisticsOrderTrack track = new KwtLogisticsOrderTrack();
                    track.setId(new IdWorker(NumberConstant.ONE).nextId());
                    track.setLOrderId(Long.valueOf(id));
                    track.setRemark(remark);
                    track.setStatus(LogisticsOrderEnum.CANCEL_ORDER.getCode());
                    track.setCreateBy(LoginUserHolder.getUserId());
                    track.setCreateTime(new Date());
                    track.setUpdateBy(LoginUserHolder.getUserId());
                    track.setUpdateTime(new Date());
                    kwtLogisticsOrderTrackMapper.insert(track);
                } else {
                    orderTrack.setRemark(remark);
                    orderTrack.setStatus(LogisticsOrderEnum.CANCEL_ORDER.getCode());
                    orderTrack.setUpdateBy(LoginUserHolder.getUserId());
                    orderTrack.setUpdateTime(new Date());
                    kwtLogisticsOrderTrackMapper.updateById(orderTrack);
                }
                //mongoDb数据
                SckwLogisticsOrder logisticsOrder = new SckwLogisticsOrder();
                logisticsOrder.set_id(Long.valueOf(id));
                logisticsOrder.setLOrderId(Long.valueOf(id));
                logisticsOrder.setStatus(LogisticsOrderEnum.CANCEL_ORDER.getStatus());
                logisticsOrder.setUpdateByName(LoginUserHolder.getUserName());
                logisticsOrder.setUpdateBy(LoginUserHolder.getUserId());
                logisticsOrder.setUpdateTime(new Date());
                SckwBusSum sckwBusSum = new SckwBusSum();
                sckwBusSum.setBusSumType(BusinessTypeEnum.LOGISTICS_ORDER_TYPE.getName());
                sckwBusSum.setMethod(NumberConstant.TWO);
                sckwBusSum.setObject(logisticsOrder);
                streamBridge.send("sckw-busSum", JSON.toJSONString(sckwBusSum));
                result.setCode(HttpStatus.SUCCESS_CODE);

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

    /**
     * 采购订单/销售订单-完结订单
     *
     * @param orderFinishDTO 数据dto
     * @param type           类型
     * @return
     */
//    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional()
    public HttpResult orderFinish(OrderFinishDTO orderFinishDTO, String type) {
        HttpResult httpResult = ValidUtil.serviceValid(orderFinishDTO);
        if (!String.valueOf(httpResult.getCode()).equals(String.valueOf(HttpStatus.SUCCESS_CODE))) {
            return HttpResult.error(httpResult.getMsg());
        }
        //1采购 2销售
        if (String.valueOf(NumberConstant.ONE).equals(type)) {
            log.info("采购订单-托运订单列表-完结订单 处理开始 seata xid:{}", RootContext.getXID());
            purchaseOrderFinish(orderFinishDTO);
            log.info("采购订单-托运订单列表-完结订单 处理结束 seata xid:{}", RootContext.getXID());
        } else if (String.valueOf(NumberConstant.TWO).equals(type)) {
            log.info("销售订单-托运订单列表-完结订单 处理开始 seata xid:{}", RootContext.getXID());
            sellOrderFinish(orderFinishDTO);
            log.info("销售订单-托运订单列表-完结订单 处理结束 seata xid:{}", RootContext.getXID());
        } else {
            throw new RuntimeException("完结订单-单据类型异常!");
        }
        return HttpResult.ok("完结订单-成功");
    }

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

    /**
     * 采购订单-完结订单
     *
     * @param orderFinishDTO
     */
    public void purchaseOrderFinish(OrderFinishDTO orderFinishDTO) {
        /** 订单完结 物流运单状态为【待派车】、【运输中】可操作*/
        /**完结拦截 必须车辆运单无正在运输中的单据才能完结 状态有 待接单之后已核弹之前的状态 都不能完结*/
        /**完结订单-对应物流订单下子订单都要进行完结*/
        /**完结订单 不做页面填写数量与数据库数量进行计算验证-直接获取页面填写数据进行保存处理*/
        //物流订单id
        String id = orderFinishDTO.getId();
        KwtLogisticsOrder logisticsOrder = kwtLogisticsOrderMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrder>()
                .eq(KwtLogisticsOrder::getId, id));
        if (logisticsOrder == null) {
            throw new BusinessException("采购订单-完结订单-物流单据不存在!");
        }
        //todo 2023-09-01 根据要求去除校验 物流订单手动完结，实装量可大于分配量，实卸量目前暂定不可大于实装量；根据计费方式，当对应实装或实卸大于分配量时自然完结
//        BigDecimal amount = logisticsOrder.getAmount() == null ? new BigDecimal("0.00") : logisticsOrder.getAmount();
//        if (amount.compareTo(orderFinishDTO.getLoadAmount()) < 0) {
//            throw new BusinessException("完结订单,装货量不能大于运输总量");
//        }
//        if (orderFinishDTO.getUnloadAmount().compareTo(orderFinishDTO.getLoadAmount()) > 0) {
//            throw new BusinessException("完结订单,填写卸货量不能大于装货量");
//        }
        /**订单状态验证*/
        if (!LogisticsOrderEnum.WAIT_DELIVERY.getStatus().equals(String.valueOf(logisticsOrder.getStatus()))
                && !LogisticsOrderEnum.IN_TRANSIT.getStatus().equals(String.valueOf(logisticsOrder.getStatus()))) {
            throw new BusinessException("当前订单并不属于【待派车】,【运输中】状态");
        }
        //验证当前物流订单是否还存在进行的车辆运单
        boolean flag = commonService.judgmentWaybillOrderIsFinish(id);
        if (flag) {
            throw new BusinessException("检测您现在有运单正在执行中，该订单目前不可完结，请先将运单执行完毕！");
        }
        //修改单据本身数据
        logisticsOrder.setTotalLoadAmount(orderFinishDTO.getLoadAmount());
        logisticsOrder.setTotalUnloadAmount(orderFinishDTO.getUnloadAmount());
        logisticsOrder.setIgnoreAmount(logisticsOrder.getAmount());
        logisticsOrder.setStatus(LogisticsOrderEnum.HAVE_FINISHED.getCode());
        logisticsOrder.setUpdateTime(new Date());
        logisticsOrder.setUpdateBy(LoginUserHolder.getUserId());
        kwtLogisticsOrderMapper.updateById(logisticsOrder);
        //修改mongodb的数据
        updateMongoDbByLogisticsOrder(logisticsOrder, orderFinishDTO);
        //获取物流订单下的子单
        /**完结订单-对应物流订单下子订单都要进行完结*/
        List<KwtLogisticsOrder> kwtLogisticsOrders = kwtLogisticsOrderMapper.selectList(new LambdaQueryWrapper<KwtLogisticsOrder>()
                .eq(KwtLogisticsOrder::getDelFlag, NumberConstant.ZERO)
                .apply(id != null, "FIND_IN_SET ('" + id + "', pids)").ne(KwtLogisticsOrder::getId, id));
        //找到该订单下所有的物流订单
        if (!org.springframework.util.CollectionUtils.isEmpty(kwtLogisticsOrders)) {
            //修改单据状态
//            List<Long> ids = kwtLogisticsOrders.stream().map(KwtLogisticsOrder::getId).collect(Collectors.toList());
            //修改单据剩余运输量
            kwtLogisticsOrders.forEach(kwtLogisticsOrder -> {
                BigDecimal subtract = kwtLogisticsOrder.getAmount().subtract(kwtLogisticsOrder.getTotalLoadAmount());
                updateLogisticOrderAndTrack(kwtLogisticsOrder.getId(), orderFinishDTO, subtract);
                //修改mongodb的数据
                updateMongoDbByLogisticsOrder(kwtLogisticsOrder, orderFinishDTO);
            });
        }

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

        /**数据推送至贸易订单*/
        CompleteLogisticsOrderParam tradeOrder = new CompleteLogisticsOrderParam();
        //TODO 2023-09-07 修改使用直接传递页面数据 不统计计算
        //获取实际装货量-实际卸货量
//        Map<String, BigDecimal> map = kwtLogisticsOrderMapper.countAmountByTradeOrderId(logisticsOrder.getTOrderId());
        //获取是否订单已经全部处理完成
        List<Integer> statusList = new ArrayList<>();
        statusList.add(LogisticsOrderEnum.TO_BE_PLANNED.getCode());
        statusList.add(LogisticsOrderEnum.PENDING_ORDER.getCode());
        statusList.add(LogisticsOrderEnum.WAIT_DELIVERY.getCode());
        statusList.add(LogisticsOrderEnum.IN_TRANSIT.getCode());
        List<KwtLogisticsOrder> logisticsOrders = kwtLogisticsOrderMapper.selectList(new LambdaQueryWrapper<KwtLogisticsOrder>()
                .eq(KwtLogisticsOrder::getTOrderId, logisticsOrder.getTOrderId())
                .in(KwtLogisticsOrder::getStatus, statusList));
        if (org.springframework.util.CollectionUtils.isEmpty(logisticsOrders)) {
            tradeOrder.setIsAllComplete(true);
        }
        tradeOrder.setTOrderId(logisticsOrder.getTOrderId());
//        tradeOrder.setActualLoadAmount(map.get("totalLoadAmount"));
//        tradeOrder.setActualUnloadAmount(map.get("totalUnloadAmount"));
        tradeOrder.setActualLoadAmount(orderFinishDTO.getLoadAmount());
        tradeOrder.setActualUnloadAmount(orderFinishDTO.getUnloadAmount());
        tradeOrder.setUpdateBy(LoginUserHolder.getUserId());
        tradeOrder.setUpdateByName(LoginUserHolder.getUserName());
        log.info("采购订单手动完结订单请求参数:{}", JSONObject.toJSONString(tradeOrder));
        HttpResult httpResult = tradeOrderInfoService.completeLogisticsOrder(tradeOrder);
        if (httpResult.getCode() != HttpStatus.SUCCESS_CODE) {
            log.info("贸易订单-采购订单/销售订单-手动完结订单异常,传递信息:{},返回信息:{}", JSONObject.toJSONString(tradeOrder), JSONObject.toJSONString(httpResult));
            throw new BusinessException("单据完结出现错误！" + httpResult.getMsg());
        }
        CreateOrCancelLogisticsOrderParam param = new CreateOrCancelLogisticsOrderParam();
        param.setTOrderId(Long.valueOf(logisticsOrder.getTOrderId()));
        param.setEntrustAmount(orderFinishDTO.getLoadAmount().subtract(logisticsOrder.getAmount()));
        param.setUpdateBy(LoginUserHolder.getUserId());
        param.setUpdateByName(LoginUserHolder.getUserName());
        HttpResult result1 = tradeOrderInfoService.createOrCancelLogisticsOrder(param);
        if (result1.getCode() != HttpStatus.SUCCESS_CODE) {
            log.info("采购订单/销售订单完结订单,返回信息:{}", "id:" + logisticsOrder.getTOrderId() + "orderNo" + logisticsOrder.getTOrderNo(), JSONObject.toJSONString(result1));
            throw new BusinessException("{" + logisticsOrder.getTOrderNo() + "} 采购订单/销售订单完结订单失败!" + result1.getMsg());
        }
        transportCommonService.closeHandle(logisticsOrder.getId());
        waybillOrderService.cancelSendCar(logisticsOrder.getId());
        //todo 直接订单完结-不递归操作
//
//        //存在子集
//        if (CollectionUtils.isNotEmpty(kwtLogisticsOrders)) {
//            if (kwtLogisticsOrders.size() == 1 && !(kwtLogisticsOrders.get(0).getPids().contains(StringConstant.COMMA))) {
//                //不存在子集
//                /**
//                 * 验证是否存在进行中的车辆运单
//                 * 统计当前物流订单的 分配量/实装量/实卸量
//                 * 验证当前贸易订单是否存在进行中的物流运单
//                 * */
//                judgmentLogisticsOrderIsFinish(logisticsOrder);
//                //直接修改数据以及状态
//            } else {
//                //分组排序
//                Map<String, List<KwtLogisticsOrder>> collect1 = kwtLogisticsOrders.stream().collect(Collectors.groupingBy(KwtLogisticsOrder::getLevel,
//                        Collectors.collectingAndThen(Collectors.toList(),
//                                logisticsOrders -> logisticsOrders.stream().sorted(Comparator.comparing(KwtLogisticsOrder::getLevel).reversed())
//                                        .collect(Collectors.toList()))
//                ));
//                //查出来最原始的数据
//                List<KwtLogisticsOrder> orderLists = new ArrayList<>();
//                for (List<KwtLogisticsOrder> value : collect1.values()) {
//                    orderLists.addAll(value);
//                }
//                //当前订单下的最大分包等级
//                int maxLevel = kwtLogisticsOrderMapper.selectMaxLevel(id);
//                List<Map<String, Object>> list = new ArrayList<>();
//                for (int level = maxLevel; level > 0; level--) {
//                    if (maxLevel == level) {
//                        List<KwtLogisticsOrder> logisticsOrderList = collect1.get(String.valueOf(level));
//                        //操作最底层数据，溯源父级
//                        for (KwtLogisticsOrder kwtLogisticsOrder : logisticsOrderList) {
//                            BigDecimal entrustAmount = kwtLogisticsOrder.getEntrustAmount();
//                            BigDecimal subcontractAmount = kwtLogisticsOrder.getSubcontractAmount();
//                            BigDecimal amount = kwtLogisticsOrder.getAmount();
//                            BigDecimal loadAmount = kwtLogisticsOrder.getLoadAmount();
//                            BigDecimal unloadAmount = kwtLogisticsOrder.getUnloadAmount();
//                            //已完成的量
//                            BigDecimal subtract = subcontractAmount.add(loadAmount);
//                            //本身数据修改(剩余量=上游给的委托量-（分包量+实际装货）)
//                            //剩余量
//                            BigDecimal ignoreAmount = amount.subtract((subcontractAmount.add(loadAmount)));
//                            kwtLogisticsOrderMapper.update(null, new LambdaUpdateWrapper<KwtLogisticsOrder>()
//                                    .eq(KwtLogisticsOrder::getId, kwtLogisticsOrder.getId())
//                                    .set(KwtLogisticsOrder::getIgnoreAmount, ignoreAmount)
//                            );
//                            //最底下根节点-获取父级
//                            KwtLogisticsOrder selectOne = kwtLogisticsOrderMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrder>()
//                                    .eq(KwtLogisticsOrder::getId, kwtLogisticsOrder.getPid())
//                            );
//                            BigDecimal amount1 = selectOne.getAmount();
//                            BigDecimal loadAmount1 = selectOne.getLoadAmount();
//                            BigDecimal subcontractAmount1 = selectOne.getSubcontractAmount();
//                            BigDecimal ignoreAmount1 = selectOne.getIgnoreAmount();
//                            subcontractAmount1 = subcontractAmount1.subtract(subtract);
//                            ignoreAmount1 = amount1.subtract((subcontractAmount1.add(loadAmount1)));
//                            kwtLogisticsOrderMapper.update(null, new LambdaUpdateWrapper<KwtLogisticsOrder>()
//                                    .eq(KwtLogisticsOrder::getId, selectOne.getId())
//                                    .set(KwtLogisticsOrder::getSubcontractAmount, subcontractAmount1)
//                                    .set(KwtLogisticsOrder::getIgnoreAmount, ignoreAmount1)
//                            );
//                        }
////                    List<KwtLogisticsOrder> collect = logisticsOrderList.stream().filter(item -> StringUtils.isNotBlank(item.getPid())).collect(Collectors.toList());
//                    } else {
//                        //不是一级,也不是最后一级
//                        List<KwtLogisticsOrder> logisticsOrderList = collect1.get(String.valueOf(level));
//                        if (CollectionUtils.isNotEmpty(logisticsOrderList)) {
//                            for (KwtLogisticsOrder kwtLogisticsOrder : logisticsOrderList) {
//                                Map<String, Object> map = new HashMap<>(NumberConstant.SIXTEEN);
//                                List<Object> collect = list.stream().map(item -> item.get("level")).collect(Collectors.toList());
//                                if (!collect.contains(kwtLogisticsOrder.getId())) {
//                                    map.put("level", level);
//                                    map.put("id", kwtLogisticsOrder.getId());
//                                    list.add(map);
//                                }
//
//                            }
//                        }
//                    }
//                }
//                recursionLogisticsOrder(list);
//            }
////
////            List<Long> collect = kwtLogisticsOrders.stream().map(KwtLogisticsOrder::getId).collect(Collectors.toList());
////            //验证 是否存在进行中车辆运单
////            List<KwtLogisticsOrder> kwtLogisticsOrderList = kwtLogisticsOrderMapper.selectList(new LambdaQueryWrapper<KwtLogisticsOrder>().in(KwtLogisticsOrder::getId, collect));
////            if (CollectionUtils.isNotEmpty(kwtLogisticsOrderList)) {
////                judgmentLogisticsOrderIsFinish(logisticsOrder);
////            }
////            // 按照父级ID分组
////            //判断是不是一级(一级的情况下，pid为null 方便处理，赋值为OL)
////            List<KwtLogisticsOrder> list = kwtLogisticsOrders.stream()
////                    .map(object -> {
////                        KwtLogisticsOrder LogisticsOrder = new KwtLogisticsOrder();
////                        BeanUtils.copyProperties(object, LogisticsOrder);
////                        if (LogisticsOrder.getPid() == null) {
////                            LogisticsOrder.setPid(0L);
////                        }
////                        return LogisticsOrder;
////                    })
////                    .collect(Collectors.toList());
////            Map<Long, List<KwtLogisticsOrder>> groupByParentIdMap = list.stream().collect(Collectors.groupingBy(KwtLogisticsOrder::getPid));
////            //存放:对应的当前节点ID数据
////            Set<Long> topToLowerChildIdSet = new HashSet<>();
////            // 取出顶级数据(也就是父级ID为0的数据  父级ID也可以自定义 当前赋值0L)
////            List<KwtLogisticsOrder> topTreeNodes = groupByParentIdMap.get(0L);
////            if (CollectionUtils.isEmpty(topTreeNodes)) {
////                /**当前传输的代表不是一级 可能是二级或者三级
////                 topTreeNodes = groupByParentIdMap.get(Long.parseLong(id));*/
////                getMinimumChildIdArray(groupByParentIdMap, Long.parseLong(id), topToLowerChildIdSet);
////                System.out.println("当前节点【" + id + "】节点下所有的根节点数据集合:" + topToLowerChildIdSet.toString());
////                //根据等级分组倒序排序
////                List<KwtLogisticsOrder> orderList = kwtLogisticsOrderMapper.selectList(new LambdaQueryWrapper<KwtLogisticsOrder>()
////                        .in(KwtLogisticsOrder::getId, topToLowerChildIdSet)
////                );
////
////            } else {
////                for (KwtLogisticsOrder node : topTreeNodes) {
////                    getMinimumChildIdArray(groupByParentIdMap, node.getId(), topToLowerChildIdSet);
////                }
////                System.out.println("0节点(传输为一级)下所有的根节点数据集合:" + topToLowerChildIdSet.toString());
////            }
////            //处理当前传递的id下  全部完结需要改的量
////            BigDecimal decimals = new BigDecimal("0.00");
////            BigDecimal decimal = judgmentOrderFinish(id, topToLowerChildIdSet, decimals, logisticsOrder);
////            //返回给贸易订单实际装卸货量
////            Map map = countOrderNumber(logisticsOrder.getTOrderId());
////            //修改单据状态
//////            updateLogisticOrderStatus(id,orderFinishDTO);
//        } else {
//            throw new BusinessException("不存在物流订单,不可操作！");
//        }
    }

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

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


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

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

        }
        return amount;
    }


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

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

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

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

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

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

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

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

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

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

    public HttpResult addLogisticsNumberDemo() {
        String seqNo = OrderGenerateSeqNoUtils.getSeqNo(RedisOrderGenerateEnum.LOGISTICS_ORDER, OrderRuleEnum.LOGISTICS_ORDER, "0", "1", "3");
        String seqNo1 = OrderGenerateSeqNoUtils.getOtherSeqNo(RedisOrderGenerateEnum.LOGISTICS_ORDER, OrderRuleEnum.LOGISTICS_ORDER);
        System.out.println(seqNo);
        System.out.println(seqNo1);
        return HttpResult.ok(seqNo + ":" + seqNo1);
    }

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

    public HttpResult addWaybillNumberDemo() {
//        String seqNo = OrderGenerateSeqNoUtils.getWaybillSeqNo(RedisOrderGenerateEnum.WAYBILL_ORDER, OrderRuleEnum.WAYBILL_ORDER,"T2308290001101");
//        System.out.println(seqNo);
        return HttpResult.ok();
    }


}
