package cn.iocoder.yudao.module.order.service.orderSplit;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.apollo.core.event.BoxCheckOrderSchedulingEvent;
import cn.iocoder.yudao.framework.apollo.core.event.BoxCheckOrdersSchedulingEvent;
import cn.iocoder.yudao.framework.apollo.core.event.Order.OrderApprovalTypeCheckEvent;
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.code.CodeUtils;
import cn.iocoder.yudao.framework.i18n.core.I18nMessage;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.service.AbstractService;
import cn.iocoder.yudao.framework.mybatis.core.vo.PageVO;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.bpm.enums.WorkFlowEmus;
import cn.iocoder.yudao.module.depository.dal.dataobject.warehouse.WarehouseLineDO;
import cn.iocoder.yudao.module.depository.dal.mysql.warehouse.WarehouseLineMapper;
import cn.iocoder.yudao.module.depository.dal.mysql.warehouse.WarehouseMapper;
import cn.iocoder.yudao.module.depository.vo.warehouse.WarehouseLineBaseVO;
import cn.iocoder.yudao.module.depository.vo.warehouse.WarehouseRegionVO;
import cn.iocoder.yudao.module.ecw.dal.dataobject.region.RegionDO;
import cn.iocoder.yudao.module.ecw.service.region.RegionService;
import cn.iocoder.yudao.module.order.convert.order.OrderConvert;
import cn.iocoder.yudao.module.order.convert.orderConsignee.OrderConsigneeConvert;
import cn.iocoder.yudao.module.order.convert.orderConsignor.OrderConsignorConvert;
import cn.iocoder.yudao.module.order.convert.orderDeparture.OrderDepartureConvert;
import cn.iocoder.yudao.module.order.convert.orderItem.OrderItemConvert;
import cn.iocoder.yudao.module.order.convert.orderLocation.OrderLocationConvert;
import cn.iocoder.yudao.module.order.convert.orderSplit.OrderSplitConvert;
import cn.iocoder.yudao.module.order.dal.dataobject.approval.OrderApprovalDO;
import cn.iocoder.yudao.module.order.dal.dataobject.order.OrderDO;
import cn.iocoder.yudao.module.order.dal.dataobject.orderCargoControl.OrderCargoControlDO;
import cn.iocoder.yudao.module.order.dal.dataobject.orderConsignee.OrderConsigneeDO;
import cn.iocoder.yudao.module.order.dal.dataobject.orderConsignor.OrderConsignorDO;
import cn.iocoder.yudao.module.order.dal.dataobject.orderDeparture.OrderDepartureDO;
import cn.iocoder.yudao.module.order.dal.dataobject.orderItem.OrderItemDO;
import cn.iocoder.yudao.module.order.dal.dataobject.orderLabel.OrderLabelDO;
import cn.iocoder.yudao.module.order.dal.dataobject.orderLocation.OrderLocationDO;
import cn.iocoder.yudao.module.order.dal.dataobject.orderObjective.OrderObjectiveDO;
import cn.iocoder.yudao.module.order.dal.dataobject.orderSplit.OrderSplitDO;
import cn.iocoder.yudao.module.order.dal.dataobject.orderSplitItem.OrderSplitItemDO;
import cn.iocoder.yudao.module.order.dal.dataobject.orderWarehouseIn.OrderWarehouseInDO;
import cn.iocoder.yudao.module.order.dal.mysql.orderItem.OrderItemMapper;
import cn.iocoder.yudao.module.order.dal.mysql.orderSplit.OrderSplitMapper;
import cn.iocoder.yudao.module.order.dal.mysql.orderSplitItem.OrderSplitItemMapper;
import cn.iocoder.yudao.module.order.dto.OrderBackInfoDto;
import cn.iocoder.yudao.module.order.enums.*;
import cn.iocoder.yudao.module.order.service.approval.OrderApprovalService;
import cn.iocoder.yudao.module.order.service.order.*;
import cn.iocoder.yudao.module.order.service.orderCargoControl.OrderCargoControlService;
import cn.iocoder.yudao.module.order.service.orderLabel.OrderLabelService;
import cn.iocoder.yudao.module.order.service.orderWarehouseIn.OrderWarehouseInService;
import cn.iocoder.yudao.module.order.service.orderWarehousePicture.OrderWarehousePictureService;
import cn.iocoder.yudao.module.order.service.targetLog.TargetLogService;
import cn.iocoder.yudao.module.order.vo.approval.OrderApprovalCancelApplyReqVO;
import cn.iocoder.yudao.module.order.vo.approval.OrderSpecialBatchApplyOrderItemDetailVO;
import cn.iocoder.yudao.module.order.vo.order.ApplyInfoVO;
import cn.iocoder.yudao.module.order.vo.order.CostVO;
import cn.iocoder.yudao.module.order.vo.order.OrderBackVO;
import cn.iocoder.yudao.module.order.vo.order.WarehouseInInfoVO;
import cn.iocoder.yudao.module.order.vo.orderItem.OrderItemBackVO;
import cn.iocoder.yudao.module.order.vo.orderLocation.OrderLocationBackVO;
import cn.iocoder.yudao.module.order.vo.orderSplit.*;
import cn.iocoder.yudao.module.order.vo.orderSplitItem.OrderSpiltItemSpecsRecordVO;
import cn.iocoder.yudao.module.order.vo.orderSplitItem.OrderSplitItemBackVO;
import cn.iocoder.yudao.module.order.vo.orderWarehouseIn.OrderWarehouseInCreateReqVO;
import cn.iocoder.yudao.module.order.vo.orderWarehouseIn.OrderWarehouseInFinishReqVO;
import cn.iocoder.yudao.module.order.vo.orderWarehouseIn.OrderWarehouseInItemDto;
import cn.iocoder.yudao.module.wealth.service.receivable.ReceivableService;
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 org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.order.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.module.order.enums.OrderApprovalTypeEnum.ORDER_SPLIT;
import static cn.iocoder.yudao.module.order.enums.TargetLogEnum.SPLIT;

/**
 * 订单拆单 Service 实现类
 *
 * @author yanghao
 */
@Service
@Validated
public class OrderSplitServiceImpl extends AbstractService<OrderSplitMapper, OrderSplitDO> implements OrderSplitService {

    @Resource
    private OrderSplitMapper splitMapper;

    @Resource
    private OrderItemMapper orderItemMapper;

    @Resource
    private OrderSplitItemMapper splitItemMapper;
    @Resource
    private OrderSplitCheckService orderSplitCheckService;
    @Resource
    private OrderApprovalService orderApprovalService;

    @Resource
    private TargetLogService targetLogService;
    @Resource
    private OrderService orderService;
    @Resource
    private OrderBusinessService orderBusinessService;

    @Resource
    private RegionService regionService;

    @Resource
    private OrderQueryService orderQueryService;

    @Resource
    private OrderTimeService orderTimeService;

    @Resource
    private OrderGuanlianService orderGuanlianService;

    @Resource
    private OrderMutualService orderMutualService;

    @Resource
    private OrderItemService orderItemService;

    @Resource
    private OrderWarehouseInService orderWarehouseInService;

    @Resource
    private OrderLocationService orderLocationService;

    @Resource
    private ReceivableService receivableService;

    @Resource
    private OrderCargoControlService orderCargoControlService;

    @Resource
    private OrderObjectiveService orderObjectiveService;

    @Resource
    private WarehouseLineMapper warehouseLineMapper;

    @Resource
    private WarehouseMapper warehouseMapper;


    @Resource
    private OrderLabelService orderLabelService;

    @Resource
    private ApplicationContext applicationContext;

    @Resource
    private OrderWarehousePictureService orderWarehousePictureService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean createSplit(OrderSplitCreateReqVO createReqVO) {
        String parentOrderNo = createReqVO.getParentOrderNo();
        Long parentOrderId = createReqVO.getParentOrderId();

        //该订单是否有待处理异常或待处理审核则抛出异常
        orderQueryService.throwPendingExceptionOrProcessingApproval(parentOrderId);

        //出货拆单不需要校验
        if (createReqVO.isCheckOrderScheduling()) {
            applicationContext.publishEvent(new BoxCheckOrderSchedulingEvent(parentOrderId));
        }

        //草稿不可拆单
        OrderDO orderDO = orderService.getById(parentOrderId);
        if (OrderStatusEnum.DRAFT.getValue().equals(orderDO.getStatus())) {
            throw exception(ORDER_DRAFT_STATUS_NOT_ALLOWED_SPLIT);
        }
        if (orderDO.getTransportId() == 4 && OrderStatusEnum.IN_WAREHOUSE.getValue().equals(orderDO.getStatus()) && orderDO.getAirShipment() == 2) {
            throw exception(AIR_ORDER_IS_CONFIRM_CAN_NOT_SPLIT);
        }
        if (orderDO.getTransportId() == 4 && OrderStatusEnum.IN_WAREHOUSE.getValue().equals(orderDO.getStatus()) && orderDO.getAirShipment() > 2) {
            throw exception(AIR_ORDER_IS_READY_STOCK_NOT_SPLIT);
        }
        OrderApprovalTypeCheckEvent approvalTypeCheckEvent = new OrderApprovalTypeCheckEvent(orderDO.getOrderId(), null, ORDER_SPLIT.getValue(), null, false);
        applicationContext.publishEvent(approvalTypeCheckEvent);
        if (approvalTypeCheckEvent.getResult()) {
            throw exception(ORDER_IS_APPROVAL_IN_PROCESS);
        }
        if (Objects.equals(orderDO.getStatus(), OrderStatusEnum.SPLIT_ORDER.getValue())) {
            throw exception(ORDER_SPLIT_SUCCESS_AND_CANNOT_SPLIT_AGAIN_ORDER, orderDO.getOrderNo());
        }
        // 控货订单->部分控货和已放完货的订单不支持拆单
        if (orderDO.getIsCargoControl() && orderDO.getCargoControlStatus() > 0) {
            throw exception(CARGO_CONTROL_ORDER_PICK_NOT_SPLIT);
        }
        // 校验是否有已核销的应收单，如果有，则不能再次入仓修改
        receivableService.verificationReceivableIsWriteOff(parentOrderId, null);
        Long initialParentOrderId = Objects.isNull(orderDO.getInitialParentOrderId()) || orderDO.getInitialParentOrderId() == 0L ? orderDO.getOrderId() : orderDO.getInitialParentOrderId();
        String initialParentOrderNo = StringUtils.isBlank(orderDO.getInitialParentOrderNo()) ? orderDO.getOrderNo() : orderDO.getInitialParentOrderNo();
        // 目的地信息
        OrderObjectiveDO orderObjectiveDO = orderObjectiveService.getByOrderId(orderDO.getOrderId());
        RegionDO objective = JSONObject.parseObject(orderObjectiveDO.getObjective(), RegionDO.class);
        List<Integer> splitSeqList = new ArrayList<>();

        String split1OrderNo = null;
        //先看此订单有没有拆单缓存纪录
        List<OrderSplitDO> orderSplitDOList = splitMapper.selectList(new LambdaQueryWrapperX<OrderSplitDO>()
                .eq(OrderSplitDO::getUsed, Boolean.FALSE)
                .eq(OrderSplitDO::getParentOrderId, parentOrderId));
        String[] orderNoAndSeq = parentOrderNo.split(StrUtil.DASHED);
        parentOrderNo = orderNoAndSeq[0];
        if (CollectionUtil.isEmpty(orderSplitDOList)) {
            // 第一条：先插入自己本身的拆单和拆单项
            OrderSplitDO split1 = OrderSplitConvert.INSTANCE.convert(createReqVO);
            if (createReqVO.isPartRefundSplit()) {
                // 部分退场拆单，校验退场入仓的箱数是否一致
                split1.setRefundNum(createReqVO.getRefundNum());
            }
            if (!createReqVO.isCheckOrderScheduling()) {
                // 出货业务拆单需要初始化主订单(不能改变运输方式/渠道)
                split1.setTransportId(orderDO.getTransportId());
                split1.setChannelId(orderDO.getChannelId());
                split1.setDstWarehouseId(orderObjectiveDO.getObjectiveWarehouseId());
            } else {
                if (split1.getTransportId() == 1 || split1.getTransportId() == 2) {
                    split1.setChannelId(0L);
                }
                WarehouseLineDO lineDO = warehouseLineMapper.selectById(orderDO.getLineId());
                WarehouseLineBaseVO warehouseLineBaseVO = new WarehouseLineBaseVO();
                warehouseLineBaseVO.setStartWarehouseId(lineDO.getStartWarehouseId());
                warehouseLineBaseVO.setDestWarehouseId(split1.getDstWarehouseId());
                warehouseLineBaseVO.setTransportType(split1.getTransportId().toString());
                warehouseLineBaseVO.setStatus(0);

                //设置线路id
                List<WarehouseLineDO> warehouseLineDOList = warehouseLineMapper.selectList(warehouseLineBaseVO);
                if (CollectionUtil.isNotEmpty(warehouseLineDOList)) {
                    Long lineIdNew = warehouseLineDOList.stream().map(WarehouseLineDO::getId).findFirst().get();
                    split1.setLineId(lineIdNew);
                } else {
                    throw exception(ORDER_LINE_NOT_EXIST);
                }
                // 非出货拆单都按参数来获取目的地信息
                //通过目的仓获取shi
                WarehouseRegionVO warehouseRegion = warehouseMapper.findWarehouseRegion(createReqVO.getDstWarehouseId());
                Long shi = warehouseRegion.getShi();
                //通过shi获取 region
                objective = regionService.getRegion(shi);
            }

            if (!Objects.equals(orderDO.getTransportId(), split1.getTransportId())) {
                // 需要获取新的订单编号
                split1OrderNo = orderBusinessService.saveOrUpdateOrderNo(objective, split1.getTransportId(), orderDO.getIsExternalWarehouse(), StringUtils.isNotBlank(orderDO.getType()) && orderDO.getType().contains("1"));
                split1.setResetOrderNo(true);
            } else {
                Integer nextSeq = 1;

                if (orderNoAndSeq.length == 2) {
                    // 子订单拆单，保留子订单编号，保证不会跳号
                    split1OrderNo = orderNoAndSeq[0].concat(StrUtil.DASHED).concat(orderNoAndSeq[1]);
                    List<OrderSplitDO> orderSplitDOS = splitMapper.selectList(new LambdaQueryWrapperX<OrderSplitDO>().likeRight(OrderSplitDO::getParentOrderNo, parentOrderNo));
                    if (CollectionUtil.isNotEmpty(orderSplitDOS)) {
                        List<Integer> seqList = orderSplitDOS.stream().map(t -> CodeUtils.getSplitOrderNoSeq(t.getOrderNo())).collect(Collectors.toList());
                        splitSeqList.addAll(seqList);
                    }
                    if (CollectionUtil.isEmpty(splitSeqList)) {
                        throw exception(SPLIT_ORDER_LOG_NOT_FIND);
                    }
                    nextSeq = splitSeqList.stream().max(Integer::compareTo).get();
                    splitSeqList.add(nextSeq);
                } else {
                    split1OrderNo = CodeUtils.createSplitOrderNo(parentOrderNo, nextSeq);
                    splitSeqList.add(nextSeq);
                }
            }
            split1.setInitialParentOrderId(initialParentOrderId);
            split1.setInitialParentOrderNo(initialParentOrderNo);
            split1.setOrderNo(split1OrderNo);
            split1.setIsMaster(true);

            splitMapper.insert(split1);
            // 出货业务拆单需要初始化主订单(不能改变运输方式)，并自动创建指定运输方式的子订单，
            if (!createReqVO.isCheckOrderScheduling()) {
                // 再插入拆分订单项
                List<OrderItemDO> orderItemDOList = orderItemMapper.selectList(new LambdaQueryWrapperX<OrderItemDO>()
                        .eq(OrderItemDO::getOrderId, parentOrderId));
                // 获取订单的全部入仓记录
                List<OrderWarehouseInDO> warehouseInDOList = orderWarehouseInService.list(new LambdaQueryWrapper<OrderWarehouseInDO>().eq(OrderWarehouseInDO::getOrderId, parentOrderId));
                Map<Long, List<OrderWarehouseInDO>> warehouseInMap = warehouseInDOList.stream().collect(Collectors.groupingBy(OrderWarehouseInDO::getOrderItemId));
                List<OrderSplitItemDO> orderSplitItemDOList = orderItemDOList.stream()
                        .filter(t -> t.getWarehouseInInfoVO() != null
                                && !Integer.valueOf(0).equals(t.getWarehouseInInfoVO().getCartonsNum()))
                        .map(orderItemDO -> {
                            OrderSplitItemDO orderSplitItemDO = BeanUtil.copyProperties(orderItemDO, OrderSplitItemDO.class);
                            // 封装入仓记录
                            List<OrderWarehouseInDO> itemWarehouseInList = warehouseInMap.get(orderItemDO.getOrderItemId());
                            if (CollectionUtil.isNotEmpty(itemWarehouseInList)) {
                                List<OrderSpiltItemSpecsRecordVO> specsRecordVOList = itemWarehouseInList.stream().map(warehouseIn -> {
                                    OrderSpiltItemSpecsRecordVO specsRecordVO = new OrderSpiltItemSpecsRecordVO();
                                    List<OrderLocationDO> locationDOList = orderLocationService.list(new LambdaQueryWrapper<OrderLocationDO>()
                                            .eq(OrderLocationDO::getWarehouseInId, warehouseIn.getId())
                                            .eq(OrderLocationDO::getOrderId, warehouseIn.getOrderId())
                                            .eq(OrderLocationDO::getOrderItemId, warehouseIn.getOrderItemId()));
                                    if (CollectionUtil.isNotEmpty(locationDOList)) {
                                        specsRecordVO.setOrderLocationList(OrderLocationConvert.INSTANCE.convertList1(locationDOList));
                                    }
                                    specsRecordVO.setWarehouseInId(warehouseIn.getId());
                                    specsRecordVO.setInTime(warehouseIn.getInTime());
                                    specsRecordVO.setSpecificationType(warehouseIn.getSpecificationType());
                                    specsRecordVO.setNum(warehouseIn.getCartonsNum());
                                    specsRecordVO.setQuantity(warehouseIn.getQuantityAll());
                                    specsRecordVO.setExpressNo(warehouseIn.getExpressNo());
                                    specsRecordVO.setVolume(warehouseIn.getVolume());
                                    specsRecordVO.setWeight(warehouseIn.getWeight());
                                    specsRecordVO.setUnit(warehouseIn.getUnit());
                                    specsRecordVO.setBoxGauge(warehouseIn.getBoxGauge());
                                    specsRecordVO.setOrderWarehouseInDetailsVOList(warehouseIn.getOrderWarehouseInDetailsVOList());
                                    return specsRecordVO;
                                }).collect(Collectors.toList());
                                if (CollectionUtil.isNotEmpty(specsRecordVOList)) {
                                    orderSplitItemDO.setSpecsRecordVOList(specsRecordVOList);
                                    orderSplitItemDO.setSpecsRecord(JSONObject.toJSONString(specsRecordVOList));
                                }
                            }

                            orderSplitItemDO.setNum(orderItemDO.getWarehouseInInfoVO().getCartonsNum());
                            orderSplitItemDO.setQuantity(orderItemDO.getWarehouseInInfoVO().getQuantityAll());
                            orderSplitItemDO.setBoxGauge(orderItemDO.getWarehouseInInfoVO().getBoxGauge());
                            orderSplitItemDO.setWeight(orderItemDO.getWarehouseInInfoVO().getWeight());
                            orderSplitItemDO.setVolume(orderItemDO.getWarehouseInInfoVO().getVolume());
                            orderSplitItemDO.setChargeQuantity(orderItemDO.getChargeQuantity());
                            orderSplitItemDO.setChargeWeight(orderItemDO.getChargeWeight());
                            orderSplitItemDO.setChargeVolume(orderItemDO.getChargeVolume());
                            orderSplitItemDO.setWorth(orderItemDO.getWorth());
                            orderSplitItemDO.setOrderSplitId(split1.getId());
                            return orderSplitItemDO;
                        }).collect(Collectors.toList());
                splitItemMapper.insertBatch(orderSplitItemDOList);


//                List<OrderSplitDO> orderSplitDOS = splitMapper.selectList(new LambdaQueryWrapperX<OrderSplitDO>().eq(OrderSplitDO::getInitialParentOrderId, initialParentOrderId));
//                if (CollectionUtil.isEmpty(orderSplitDOS)) {
                List<OrderSplitDO> orderSplitDOS = splitMapper.selectList(new LambdaQueryWrapperX<OrderSplitDO>().likeRight(OrderSplitDO::getParentOrderNo, parentOrderNo));
//                }
                List<String> orderNoList = orderSplitDOS.stream().map(OrderSplitDO::getOrderNo).collect(Collectors.toList());
                if (CollectionUtil.isNotEmpty(orderNoList)) {
                    splitSeqList = orderNoList.stream().map(CodeUtils::getSplitOrderNoSeq).sorted().collect(Collectors.toList());
                }
                // 不需要校验排单的都是出货阶段拆单，则需要默认生成
                Integer max = splitSeqList.stream().max(Integer::compareTo).orElse(0);
                // 插入拆分订单
                OrderSplitDO split2 = OrderSplitConvert.INSTANCE.convert(createReqVO);

                split2.setInitialParentOrderId(initialParentOrderId);
                split2.setInitialParentOrderNo(initialParentOrderNo);
                if (split2.getTransportId() == 1 || split2.getTransportId() == 2) {
                    split2.setChannelId(0L);
                }
                if (!Objects.equals(orderDO.getTransportId(), split2.getTransportId())) {
                    // 非出货拆单都按参数来获取目的地信息
                    //通过目的仓获取shi
                    WarehouseRegionVO warehouseRegion = warehouseMapper.findWarehouseRegion(createReqVO.getDstWarehouseId());
                    Long shi = warehouseRegion.getShi();
                    //通过shi获取 region
                    objective = regionService.getRegion(shi);
                    String newOrderNo = orderBusinessService.saveOrUpdateOrderNo(objective, split2.getTransportId(), orderDO.getIsExternalWarehouse(), StringUtils.isNotBlank(orderDO.getType()) && orderDO.getType().contains("1"));
                    split2.setResetOrderNo(true);
                    split2.setOrderNo(newOrderNo);
                } else {
                    split2.setOrderNo(CodeUtils.createSplitOrderNo(parentOrderNo.split("-")[0], max + 1));
                }
                WarehouseLineDO lineDO = warehouseLineMapper.selectById(orderDO.getLineId());
                WarehouseLineBaseVO warehouseLineBaseVO = new WarehouseLineBaseVO();
                warehouseLineBaseVO.setStartWarehouseId(lineDO.getStartWarehouseId());
                warehouseLineBaseVO.setDestWarehouseId(split2.getDstWarehouseId());
                warehouseLineBaseVO.setTransportType(split2.getTransportId().toString());
                warehouseLineBaseVO.setStatus(0);
                //设置线路id
                List<WarehouseLineDO> warehouseLineDOList = warehouseLineMapper.selectList(warehouseLineBaseVO);
                if (CollectionUtil.isNotEmpty(warehouseLineDOList)) {
                    Long lineIdNew = warehouseLineDOList.stream().map(WarehouseLineDO::getId).findFirst().get();
                    split2.setLineId(lineIdNew);
                } else {
                    throw exception(ORDER_LINE_NOT_EXIST);
                }
                split2.setIsMaster(false);
                if (createReqVO.isPartRefundSplit()) {
                    // 部分退场拆单，校验退场入仓的箱数是否一致
                    split2.setRefundNum(createReqVO.getRefundNum());
                }
                splitMapper.insert(split2);
            }
        }
        //若存在缓存纪录，则找到所有的拆单号，然后向后追加
        else {

            List<OrderSplitDO> orderSplitDOS = splitMapper.selectList(new LambdaQueryWrapperX<OrderSplitDO>().likeRight(OrderSplitDO::getParentOrderNo, parentOrderNo));
            List<String> orderNoList = orderSplitDOS.stream().map(OrderSplitDO::getOrderNo).collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(orderNoList)) {
                splitSeqList = orderNoList.stream().map(CodeUtils::getSplitOrderNoSeq).sorted().collect(Collectors.toList());
            }
            Integer max = splitSeqList.stream().max(Integer::compareTo).orElse(0);
            // 插入拆分订单
            OrderSplitDO split2 = OrderSplitConvert.INSTANCE.convert(createReqVO);
            split2.setInitialParentOrderId(initialParentOrderId);
            split2.setInitialParentOrderNo(initialParentOrderNo);
            split2.setIsMaster(false);
            if (split2.getTransportId() == 1 || split2.getTransportId() == 2) {
                split2.setChannelId(0L);
            }
            if (!Objects.equals(orderDO.getTransportId(), split2.getTransportId())) {
                // 需要获取新的订单编号
                // 非出货拆单都按参数来获取目的地信息
                //通过目的仓获取shi
                WarehouseRegionVO warehouseRegion = warehouseMapper.findWarehouseRegion(createReqVO.getDstWarehouseId());
                Long shi = warehouseRegion.getShi();
                //通过shi获取 region
                objective = regionService.getRegion(shi);
                String newOrderNo = orderBusinessService.saveOrUpdateOrderNo(objective, split2.getTransportId(), orderDO.getIsExternalWarehouse(), StringUtils.isNotBlank(orderDO.getType()) && orderDO.getType().contains("1"));
                split2.setResetOrderNo(true);
                split2.setOrderNo(newOrderNo);
            } else {
                split2.setOrderNo(CodeUtils.createSplitOrderNo(parentOrderNo.split("-")[0], max + 1));
            }
            WarehouseLineDO lineDO = warehouseLineMapper.selectById(orderDO.getLineId());
            WarehouseLineBaseVO warehouseLineBaseVO = new WarehouseLineBaseVO();
            warehouseLineBaseVO.setStartWarehouseId(lineDO.getStartWarehouseId());
            warehouseLineBaseVO.setDestWarehouseId(split2.getDstWarehouseId());
            warehouseLineBaseVO.setTransportType(split2.getTransportId().toString());
            warehouseLineBaseVO.setStatus(0);
            //设置线路id
            List<WarehouseLineDO> warehouseLineDOList = warehouseLineMapper.selectList(warehouseLineBaseVO);
            if (CollectionUtil.isNotEmpty(warehouseLineDOList)) {
                Long lineIdNew = warehouseLineDOList.stream().map(WarehouseLineDO::getId).findFirst().get();
                split2.setLineId(lineIdNew);
            } else {
                throw exception(ORDER_LINE_NOT_EXIST);
            }
            if (createReqVO.isPartRefundSplit()) {
                // 部分退场拆单，校验退场入仓的箱数是否一致
                split2.setRefundNum(createReqVO.getRefundNum());
            }
            splitMapper.insert(split2);
        }


        // 返回
        return true;
    }


    @Override
    public void updateSplit(OrderSplitUpdateReqVO updateReqVO) {
        // 校验存在
        this.validateSplitExists(updateReqVO.getId());
        // 更新
        OrderSplitDO updateObj = OrderSplitConvert.INSTANCE.convert(updateReqVO);
        splitMapper.updateById(updateObj);
    }


    @Override
    public Boolean deleteAllSplit(Long orderId) {
        OrderDO orderDO = orderQueryService.getOrderById(orderId);
        if (orderDO == null) {
            throw exception(ORDER_NOT_EXISTS);
        }
        // TODO 需要调整异常说明为 -> 订单正在进行拆单审批,无法重置拆单
        if (Objects.equals(orderDO.getAuditType(), ORDER_SPLIT.getValue())) {
            throw exception(ORDER_HAS_PROCESSING_APPROVAL, orderDO.getOrderNo());
        }
//        if (Objects.equals(orderDO.getStatus(), OrderStatusEnum.SPLIT_ORDER.getValue())) {
//            throw exception(ORDER_SPLIT_SUCCESS_AND_CANNOT_SPLIT_AGAIN_ORDER, orderDO.getOrderNo());
//        }
        splitItemMapper.deleteByOrderIdAndUsed(orderId);
        splitMapper.deleteByOrderIdAndUsed(orderId);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteSplit(Long id) {
        // 校验存在
        OrderSplitDO orderSplitDO = splitMapper.selectById(id);
        if (orderSplitDO == null) {
            throw exception(ORDER_SPLIT_NOT_EXISTS);
        }
        OrderDO orderDO = orderQueryService.getOrderById(orderSplitDO.getParentOrderId());
        if (orderDO == null) {
            throw exception(ORDER_NOT_EXISTS);
        }
        if (orderDO.getAuditType() != 0) {
            throw exception(ORDER_HAS_PROCESSING_APPROVAL, orderDO.getOrderNo());
        }
        if (Objects.equals(orderDO.getStatus(), OrderStatusEnum.SPLIT_ORDER.getValue())) {
            throw exception(ORDER_SPLIT_SUCCESS_AND_CANNOT_SPLIT_AGAIN_ORDER, orderDO.getOrderNo());
        }
        // 控货订单->部分控货和已放完货的订单不支持拆单
        if (orderDO.getIsCargoControl() && orderDO.getCargoControlStatus() > 0) {
            throw exception(CARGO_CONTROL_ORDER_PICK_NOT_SPLIT);
        }
        List<OrderSplitDO> orderSplitDOList = splitMapper.selectList(new LambdaQueryWrapperX<OrderSplitDO>()
                .eq(OrderSplitDO::getUsed, Boolean.FALSE)
                .eq(OrderSplitDO::getParentOrderId, orderSplitDO.getParentOrderId()));

        if (orderSplitDOList.size() <= 2) {
            // 当只有2个子单时，删除所有拆单缓存数据，就是不拆单了。
            orderSplitDOList.forEach(split -> {
                splitItemMapper.delete(new LambdaQueryWrapperX<OrderSplitItemDO>().eq(OrderSplitItemDO::getOrderSplitId, split.getId()));
                splitMapper.deleteById(split.getId());
            });
        } else {
            // 当多余2个子单时，需要判断，当前删除的拆单是否为最后一个，不允许跳号删除
            OrderSplitDO maxOrderSplitDO = orderSplitDOList.stream().max(Comparator.comparing(OrderSplitDO::getId)).get();
            if (!Objects.equals(orderSplitDO.getId(), maxOrderSplitDO.getId())) {
                throw exception(SPILT_ORDER_NOT_SKIP_NUMBER_DELETE);
            }
            // 当有多于2个子单时，删除当前子拆单下所有的拆单项品名数据
            splitItemMapper.delete(new LambdaQueryWrapper<OrderSplitItemDO>().eq(OrderSplitItemDO::getOrderSplitId, id));
//            // 当有多于2个子单时，删除当前子拆单，并把当前子拆单的数据 放入 子拆单-master的item中
//            List<OrderSplitItemDO> waitDeleteItemList = splitItemMapper.selectList(new LambdaQueryWrapperX<OrderSplitItemDO>()
//                    .eq(OrderSplitItemDO::getOrderSplitId, orderSplitDO.getId()));
//
//            if (CollectionUtil.isNotEmpty(waitDeleteItemList)) {
//                // 查询master
//                OrderSplitDO orderSplitMaster = orderSplitDOList.stream().filter(t -> Boolean.TRUE.equals(t.getIsMaster())).findFirst().orElse(null);
//                if (orderSplitMaster != null) {
//                    List<OrderSplitItemDO> masterItemList = splitItemMapper.selectList(new LambdaQueryWrapperX<OrderSplitItemDO>()
//                            .eq(OrderSplitItemDO::getUsed, Boolean.FALSE)
//                            .eq(OrderSplitItemDO::getOrderSplitId, orderSplitMaster.getId()));
//
//                    // 将waitDeleteItem的信息合并到masterItem中去
//                    for (OrderSplitItemDO waitDeleteItem : waitDeleteItemList) {
//
//                        OrderSplitItemDO splitMasterItemDO = masterItemList.stream().filter(masterItem -> masterItem.getOrderItemId().equals(waitDeleteItem.getOrderItemId())).findFirst().orElse(null);
//
//                        if (Objects.nonNull(splitMasterItemDO)) {
//                            splitMasterItemDO.setNum(splitMasterItemDO.getNum() + waitDeleteItem.getNum());
//                            splitMasterItemDO.setQuantity(splitMasterItemDO.getQuantity() + waitDeleteItem.getQuantity());
//                            splitMasterItemDO.setVolume(splitMasterItemDO.getVolume().add(waitDeleteItem.getVolume()));
//                            splitMasterItemDO.setWeight(splitMasterItemDO.getWeight().add(waitDeleteItem.getWeight()));
//                            splitMasterItemDO.setChargeVolume(splitMasterItemDO.getChargeVolume().add(waitDeleteItem.getChargeVolume()));
//                            splitMasterItemDO.setChargeWeight(splitMasterItemDO.getChargeWeight().add(waitDeleteItem.getChargeWeight()));
//                            splitMasterItemDO.setChargeQuantity(splitMasterItemDO.getChargeQuantity().add(waitDeleteItem.getChargeQuantity()));
//                            splitMasterItemDO.setWorth(splitMasterItemDO.getWorth().add(waitDeleteItem.getWorth()));
//                            // 合并item
//                            splitItemMapper.updateById(splitMasterItemDO);
//                            // 删除item
//                            splitItemMapper.deleteById(waitDeleteItem);
//                        } else {
//                            // 当主拆单中没有此订单项时，将主拆单id更新到此拆单项中，并入主拆单下面
//                            waitDeleteItem.setOrderSplitId(orderSplitMaster.getId());
//                            // 合并item到主拆单下
//                            splitItemMapper.updateById(waitDeleteItem);
//                        }
//
//                    }
//                }
//            }
            // 删除
            splitMapper.deleteById(id);
        }

        return true;
    }

    private void validateSplitExists(Long id) {
        if (splitMapper.selectById(id) == null) {
            throw exception(ORDER_SPLIT_NOT_EXISTS);
        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean splitApply(OrderSplitApplyReqVO applyReqVO) {

        Long orderId = applyReqVO.getOrderId();

        //该订单是否有待处理异常或待处理审核则抛出异常
        orderQueryService.throwPendingExceptionOrProcessingApproval(orderId);

        //草稿不可拆单
        OrderDO orderDO = orderService.getById(orderId);
        if (OrderStatusEnum.DRAFT.getValue().equals(orderDO.getStatus())) {
            throw exception(ORDER_DRAFT_STATUS_NOT_ALLOWED_SPLIT);
        }

        //出货拆单不需要校验
        if (applyReqVO.isCheckOrderScheduling()) {
            applicationContext.publishEvent(new BoxCheckOrderSchedulingEvent(orderId));
        }

        // 校验是否有已核销的应收单，如果有，则不能再次入仓修改
        receivableService.verificationReceivableIsWriteOff(orderId, null);
        // 货值需要匹配整个订单的
        BigDecimal totalWorth = BigDecimal.ZERO;
        if (StringUtils.isNotBlank(orderDO.getCost())) {
            CostVO costVO = JSONObject.parseObject(orderDO.getCost(), CostVO.class);
            totalWorth = Objects.nonNull(costVO.getTotalWorth()) ? costVO.getTotalWorth() : BigDecimal.ZERO;
        }
        //申请信息组装
        OrderSplitApplyDetailDto orderSplitApplyDetailDto = new OrderSplitApplyDetailDto();
        orderSplitApplyDetailDto.setOrderId(orderId);
        // 拆单申请detail
        List<OrderSplitBackVO> orderSplitBackVOList = this.listByOrderId(orderId, 0);
        if (orderSplitBackVOList.size() < 2) {
            throw exception(ORDER_SPLIT_AT_LEAST_TWO);
        }
        // 校验拆单申请的数据是否合法(注：拆出的订单项值不能为空)
        for (OrderSplitBackVO orderSplitBackVO : orderSplitBackVOList) {
            if (CollectionUtil.isEmpty(orderSplitBackVO.getOrderSplitItemBackVOList())) {
                // 拆分的订单项为空抛出异常
                throw exception(SPLIT_ORDER_ITEM_NOT_NULL, orderSplitBackVO.getOrderNo());
            }
        }
        List<OrderItemDO> orderItems = orderItemService.getOrderItemsByOrderId(CollectionUtil.newArrayList(orderDO.getOrderId()));
        List<OrderSplitItemDO> orderAllSplitItemDOList = new ArrayList<>();
        for (OrderItemDO orderItemDO : orderItems) {
            WarehouseInInfoVO warehouseInInfoVO = orderItemDO.getWarehouseInInfoVO();
            if (Objects.nonNull(warehouseInInfoVO) && warehouseInInfoVO.getCartonsNum() > 0) {
                // 校验所有拆单项与原单的强一致
                List<OrderSplitItemDO> orderSplitItemDOList = splitItemMapper.selectList(new LambdaQueryWrapperX<OrderSplitItemDO>()
                        .eq(OrderSplitItemDO::getUsed, false)
                        .eq(OrderSplitItemDO::getOrderItemId, orderItemDO.getOrderItemId()));
                if (CollectionUtil.isEmpty(orderSplitItemDOList)) {
                    throw exception(SPLIT_ORDER_ITEM_PROD_NOT_NULL, I18nMessage.getLang() == 0 ? orderItemDO.getProdTitleZh() : orderItemDO.getProdTitleEn());
                }
                orderSplitCheckService.splitConsistencyCheck(orderSplitItemDOList, warehouseInInfoVO.getCartonsNum(), Objects.isNull(warehouseInInfoVO.getQuantityAll()) ? 0 : warehouseInInfoVO.getQuantityAll(),
                        warehouseInInfoVO.getWeight(), warehouseInInfoVO.getVolume(), orderItemDO.getChargeWeight(),
                        orderItemDO.getChargeVolume(), orderItemDO.getChargeQuantity());
                orderAllSplitItemDOList.addAll(orderSplitItemDOList);
            }
        }
        // 校验所有拆单项货值与原单总货值的强一致
        orderSplitCheckService.splitWorthConsistencyCheck(orderAllSplitItemDOList, totalWorth);
        OrderObjectiveDO objectiveDO = orderObjectiveService.getByOrderId(orderId);
        if (Objects.isNull(objectiveDO)) {
            throw exception(OBJECTIVE_NOT_EXISTS);
        }
        // 当所有流程校验结束后,需要处理提交申请的订单拆单是否有订单编号进行变化，如果有需要重新获取最新订单编号并生成
//        for (OrderSplitBackVO orderSplitBackVO : orderSplitBackVOList) {
//           if (orderSplitBackVO.getResetOrderNo()){
//               // 重新生成拆单订单编号
//               String newOrderNo = orderBusinessService.saveOrUpdateOrderNo(JSONObject.parseObject(objectiveDO.getObjective(), RegionDO.class),
//                       orderSplitBackVO.getTransportId(), orderDO.getIsExternalWarehouse(),
//                       StringUtils.isNotBlank(orderDO.getType()) && orderDO.getType().contains("1"));
//               orderSplitBackVO.setOrderNo(newOrderNo);
//               // 更新最新的拆单订单编号到拆单记录中去
//               splitMapper.update(null, new LambdaUpdateWrapper<OrderSplitDO>().set(OrderSplitDO::getOrderNo, newOrderNo).eq(OrderSplitDO::getId, orderSplitBackVO.getId()));
//           }
//        }
        orderSplitApplyDetailDto.setOrderSplitBackVOList(orderSplitBackVOList);

        //创建审批单，发起流程
        OrderApprovalDO orderApprovalDO = new OrderApprovalDO();
        orderApprovalDO.setFollowUpSalesmanId(String.valueOf(SecurityFrameworkUtils.getLoginUserId()));
        orderApprovalDO.setOrderId(orderId);
        //拆单申请
        orderApprovalDO.setType(6);
        orderApprovalDO.setDetails(JSON.toJSONString(orderSplitApplyDetailDto));
        orderApprovalDO.setStatus(ApprovalResultStatusEnum.processing.getValue());
        // 空运拆单和海运拆单需要分开创建流程
        WorkFlowEmus workFlowEnum = TransportTypeShortEnum.SEA_CONTAINER.getValue().equals(orderDO.getTransportId())
                || TransportTypeShortEnum.MARINE_CONTAINER.getValue().equals(orderDO.getTransportId()) ? WorkFlowEmus.ORDER_SPLIT_ORDER : WorkFlowEmus.AIR_SPLIT_ORDER;
        orderApprovalService.applyAndCreate(orderApprovalDO, workFlowEnum, applyReqVO.getCopyUserId());

        //更新订单状态 20-拆单申请中
        Integer auditType = OrderApprovalTypeResultEnum.order_split_processing.getType();
        orderService.updateStatus(orderId, null, null, null, OrderWarehouseInStatusEnum.order_split_applying.getValue(), null, auditType, OrderApprovalTypeResultEnum.typeAndResultOf(auditType, 1).getDesc(), false);

        //纪录仓库操作
        orderBusinessService.addOrderOperateLog(orderId, "仓库操作", "提交拆单申请", "");

        return true;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void splitApplyCallback(String approvalId, Integer result) {

        OrderApprovalDO orderApprovalDO = orderApprovalService.getById(approvalId);

        //detail转对象
        OrderSplitApplyDetailDto orderSplitApplyDetailDto = JSON.parseObject(orderApprovalDO.getDetails(), OrderSplitApplyDetailDto.class);
        Long orderId = orderSplitApplyDetailDto.getOrderId();

        //更新审核单状态
        orderApprovalService.callbackUpdate(orderApprovalDO, orderApprovalDO.getFormId(), result);

        String processingResults = orderApprovalDO.getProcessingResults();
        if (ApprovalResultStatusEnum.reject.getValue().equals(result)) {
            //更新订单状态  入仓-拆单-已拒绝
            Integer auditType = OrderApprovalTypeResultEnum.order_split_reject.getType();
            orderService.updateStatus(orderId, null, null, null, OrderWarehouseInStatusEnum.warehouse_finished.getValue(), null,
                    0, OrderApprovalTypeResultEnum.typeAndResultOf(auditType, result).getDesc(), false);

            //纪录仓库操作
            orderBusinessService.addOrderOperateLog(orderId, "仓库操作", "拆单申请拒绝", "");
        } else if (ApprovalResultStatusEnum.cancel.getValue().equals(result)) {
            //更新订单状态  入仓-拆单-已取消
            Integer auditType = OrderApprovalTypeResultEnum.order_split_cancel.getType();
            orderService.updateStatus(orderId, null, null, null, OrderWarehouseInStatusEnum.warehouse_finished.getValue(), null,
                    0, OrderApprovalTypeResultEnum.typeAndResultOf(auditType, result).getDesc(), false);

            splitItemMapper.deleteByOrderIdAndUsed(orderId);
            splitMapper.deleteByOrderIdAndUsed(orderId);

            //纪录仓库操作
            orderBusinessService.addOrderOperateLog(orderId, "仓库操作", "拆单申请取消", "");
        } else if (ApprovalResultStatusEnum.pass.getValue().equals(result)) {
            //更新订单状态  已拆单
            this.splitSuccess(orderSplitApplyDetailDto, processingResults);
            // 拆单通过后标记拆单缓存记录已使用
            List<OrderSplitDO> orderSplitDOList = splitMapper.selectList(new LambdaQueryWrapper<OrderSplitDO>().eq(OrderSplitDO::getParentOrderId, orderId));
            for (OrderSplitDO orderSplitDO : orderSplitDOList) {
                splitItemMapper.update(null, new LambdaUpdateWrapper<OrderSplitItemDO>()
                        .set(OrderSplitItemDO::getUsed, Boolean.TRUE)
                        .eq(OrderSplitItemDO::getOrderSplitId, orderSplitDO.getId()));
                orderSplitDO.setUsed(Boolean.TRUE);
                splitMapper.updateById(orderSplitDO);
            }
            //纪录仓库操作
            orderBusinessService.addOrderOperateLog(orderId, "仓库操作", "拆单申请通过", "");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean cancelSplitApply(OrderApprovalCancelApplyReqVO cancelApplyReqVO) {

        Long orderId = cancelApplyReqVO.getOrderId();

        OrderApprovalDO orderApprovalDO = orderApprovalService.selectOne(new LambdaQueryWrapperX<OrderApprovalDO>()
                .eq(OrderApprovalDO::getOrderId, orderId)
                .eq(OrderApprovalDO::getType, 6).orderByDesc(OrderApprovalDO::getOrderApprovalId).last("limit 1"));
        // 当没有申请时，直接删除缓存拆单数据
        // 有申请时，取消申请，同时删除数据
        if (orderApprovalDO != null) {
            if (!ApprovalResultStatusEnum.processing.getValue().equals(orderApprovalDO.getStatus())) {
                throw exception(ORDER_APPROVAL_STATUS_NOT_CORRECT);
            }

            // 设置拆单申请流程为已取消
            orderApprovalService.cancelApplyAndUpdate(orderApprovalDO, cancelApplyReqVO.getReason());

        }

        return true;
    }

    @Override
    public List<OrderSplitBackVO> listByOrderId(Long orderId, Integer lang) {
        List<OrderSplitBackVO> orderSplitBackVOList = splitMapper.listByOrderId(orderId, lang);
        if (CollectionUtil.isNotEmpty(orderSplitBackVOList)) {
            orderSplitBackVOList.forEach(orderSplitBackVO -> {
                List<OrderSplitItemBackVO> orderSplitItemBackVOList = splitItemMapper.getListByOrderSplitId(orderSplitBackVO.getId(), lang);
                orderSplitBackVO.setOrderSplitItemBackVOList(orderSplitItemBackVOList);
            });
        }
        return orderSplitBackVOList;
    }

    @Override
    public OrderSplitDO getSplit(Long id) {
        return splitMapper.selectById(id);
    }

    @Override
    public List<OrderSplitDO> getSplitList(Collection<Long> ids) {
        return splitMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<OrderSplitDO> getSplitPage(OrderSplitQueryVO query, PageVO page) {
        return splitMapper.selectPage(page, query);
    }

    @Override
    public List<OrderSplitDO> getSplitList(OrderSplitQueryVO query) {
        return splitMapper.selectList(query);
    }

    @Override
    public void splitCancelByOrderId(Long orderId) {
        splitItemMapper.deleteByOrderIdAndUsed(orderId);
        splitMapper.deleteByOrderIdAndUsed(orderId);
    }

    @Override
    public void splitSuccess(OrderSplitApplyDetailDto orderSplitApplyDetailDto, String auditResult) {
        Long orderId = orderSplitApplyDetailDto.getOrderId();

        OrderBackVO parentOrderBackVo = orderQueryService.getOrder(orderId);
        String[] orderNoAndSeq = parentOrderBackVo.getOrderNo().split(StrUtil.DASHED);
        StringBuilder splitOrderNoSb = null;
        List<OrderSplitBackVO> orderSplitBackVOList = orderSplitApplyDetailDto.getOrderSplitBackVOList();
        for (OrderSplitBackVO backVO : orderSplitBackVOList) {
            if (Objects.isNull(splitOrderNoSb)) {
                splitOrderNoSb = new StringBuilder();
                splitOrderNoSb.append(backVO.getOrderNo());
            } else {
                splitOrderNoSb.append(StrUtil.COMMA).append(backVO.getOrderNo());
            }
        }
        String splitMessage = String.format("订单【%s】拆单成【%s】", parentOrderBackVo.getOrderNo(), splitOrderNoSb);
        boolean isBoxSplitOrder = orderSplitApplyDetailDto.isBoxSplitOrder();
        boolean isPartRefundSplit = orderSplitApplyDetailDto.isPartRefundSplit();
        boolean splitSeparateOrder = 3 == parentOrderBackVo.getTransportId(); // 当父订单为空运订单时，拆单的子订单都为独立订单
        List<OrderItemBackVO> orderItemBackList = parentOrderBackVo.getOrderItemVOList();
//        List<OrderItemDO> orderItemDOList = orderItemMapper.selectList(new LambdaQueryWrapper<OrderItemDO>().eq(OrderItemDO::getOrderId, orderId));
        List<Long> orderIds = new ArrayList<>();//拆单后的订单ID集合
        List<OrderDO> orderChildren = new ArrayList<>();//拆单后的子订单ID集合
        if (CollectionUtil.isNotEmpty(orderSplitBackVOList)) {
            if (!splitSeparateOrder) {
                // 当子订单中有一个子订单为空运订单，则所有子订单都为独立订单
                splitSeparateOrder = orderSplitBackVOList.stream().anyMatch(vo -> 3 == vo.getTransportId());
            }
            for (OrderSplitBackVO orderSplitBackVO : orderSplitBackVOList) {

                OrderDO orderDO = OrderConvert.INSTANCE.convert(parentOrderBackVo);
                orderDO.setCreator(parentOrderBackVo.getCreator());
                orderDO.setParentNumber(orderSplitBackVO.getParentOrderNo());
                orderDO.setParentOrderId(orderSplitBackVO.getParentOrderId());
                orderDO.setInitialParentOrderId(orderSplitBackVO.getInitialParentOrderId());
                orderDO.setInitialParentOrderNo(orderSplitBackVO.getInitialParentOrderNo());
                orderDO.setOrderNo(orderSplitBackVO.getOrderNo());
                orderDO.setOrderId(null);
                orderDO.setIsMaster(orderSplitBackVO.getIsMaster());
                orderDO.setIsBoxSplitOrder(isBoxSplitOrder);
                orderDO.setPartRefundSplit(isPartRefundSplit);
                orderDO.setTransportId(orderSplitBackVO.getTransportId());
                orderDO.setChannelId(orderSplitBackVO.getChannelId());
                orderDO.setSplitSeparateOrder(splitSeparateOrder);
                orderDO.setMinMeteringVolume(BigDecimal.ZERO);
                orderDO.setMinMeteringWeight(BigDecimal.ZERO);
                orderDO.setMinMeteringQuantity(BigDecimal.ZERO);
                if (splitSeparateOrder && (!orderSplitBackVO.getIsMaster() && (isBoxSplitOrder || isPartRefundSplit))) {
                    // 如果是独立订单，并且非装柜、部分退场拆单的主订单(出货阶段拆单的主订单要继续走原单业务逻辑，所以不要重置这些属性)，则重置订单的重泡货属性
                    orderDO.setOrderType(1);
                    orderDO.setPickleType(1);
                    if (orderSplitBackVO.getTransportId() == 3) {
                        orderDO.setAirShipment(1);
                    } else {
                        orderDO.setAirShipment(0);
                    }
                }
                //重置状态
                if (!isBoxSplitOrder) {
                    orderDO.setStatus(OrderStatusEnum.ORDER_PLACED.getValue());
                    // 当订单状态改为已下单时，重置出货状态为0
                    orderDO.setAirShipment(0);
                    orderDO.setInWarehouseState(0);
                    orderDO.setAbnormalState(0);
                    orderDO.setShipmentState(0);
                    orderDO.setAuditType(0);
                    orderDO.setAuditResult("");
                }
                //重置入仓数量
                orderDO.setSumQuantity(0);
                orderDO.setSumWeight(BigDecimal.ZERO);
                orderDO.setSumVolume(BigDecimal.ZERO);
                orderDO.setSumNum(0);

                //重置泡货重
                orderDO.setVWeight(BigDecimal.ZERO);
                orderDO.setWVolume(BigDecimal.ZERO);

                orderDO.setOrderItemDOList(OrderItemConvert.INSTANCE.convertList1(orderItemBackList));

                //出货的第一个订单保持原订单的状态
                if (orderSplitBackVO.getIsMaster() && isBoxSplitOrder) {
                    List<OrderItemDO> itemList = orderDO.getOrderItemDOList();
                    for (OrderItemDO itemDO : itemList) {
                        //需要修改入仓信息
                        WarehouseInInfoVO warehouseInInfoVO = new WarehouseInInfoVO();
                        warehouseInInfoVO.setCartonsNum(itemDO.getNum());
                        warehouseInInfoVO.setQuantityAll(itemDO.getQuantity());
                        warehouseInInfoVO.setVolume(itemDO.getVolume());
                        warehouseInInfoVO.setWeight(itemDO.getWeight());

                        //设置老储位
                        WarehouseInInfoVO warehouseInInfoVOOld = itemDO.getWarehouseInInfoVO();
                        if (warehouseInInfoVOOld != null) {
                            List<OrderLocationBackVO> orderLocationBackVOList = warehouseInInfoVOOld.getOrderLocationBackVOList();
                            warehouseInInfoVO.setOrderLocationBackVOList(orderLocationBackVOList);
                        }

                        itemDO.setWarehouseInInfo(JSON.toJSONString(warehouseInInfoVO));
                    }
                    orderDO.setSumNum(itemList.stream().mapToInt(OrderItemDO::getNum).sum());
                    orderDO.setSumQuantity(itemList.stream().mapToInt(OrderItemDO::getQuantity).sum());
                    orderDO.setSumVolume(itemList.stream().map(OrderItemDO::getVolume).reduce(BigDecimal.ZERO, BigDecimal::add));
                    orderDO.setSumWeight(itemList.stream().map(OrderItemDO::getWeight).reduce(BigDecimal.ZERO, BigDecimal::add));
                } else {
//                    if (!isPartRefundSplit) {
//                        // 不是部分退场拆单才会将非主拆单状态重置，否则也保持原状态
//                        orderDO.setStatus(OrderStatusEnum.ORDER_PLACED.getValue());
//                    }
                    if (!isPartRefundSplit) {
                        orderDO.setStatus(OrderStatusEnum.ORDER_PLACED.getValue());
                        // 当订单状态改为已下单时，重置出货状态为0
                        orderDO.setAirShipment(0);
                        orderDO.setInWarehouseState(0);
                        orderDO.setAbnormalState(0);
                        orderDO.setShipmentState(0);
                        orderDO.setAuditType(0);
                        orderDO.setAuditResult("");
                    }
                }

                OrderConsignorDO orderConsignorDO = OrderConsignorConvert.INSTANCE.convert(parentOrderBackVo.getConsignorVO());
                orderDO.setOrderConsignorDO(orderConsignorDO);

                OrderConsigneeDO orderConsigneeDO = OrderConsigneeConvert.INSTANCE.convert(parentOrderBackVo.getConsigneeVO());
                orderDO.setOrderConsigneeDO(orderConsigneeDO);

                OrderDepartureDO orderDepartureDO = OrderDepartureConvert.INSTANCE.convert(parentOrderBackVo.getOrderDepartureVO());
                orderDO.setOrderDepartureDO(orderDepartureDO);
                if (Objects.nonNull(orderSplitBackVO.getLineId())) {
                    WarehouseLineDO lineDO = warehouseLineMapper.selectById(orderDO.getLineId());
                    WarehouseLineBaseVO warehouseLineBaseVO = new WarehouseLineBaseVO();
                    warehouseLineBaseVO.setStartWarehouseId(lineDO.getStartWarehouseId());
                    warehouseLineBaseVO.setDestWarehouseId(orderSplitBackVO.getDstWarehouseId());
                    warehouseLineBaseVO.setTransportType(orderSplitBackVO.getTransportId().toString());
                    warehouseLineBaseVO.setStatus(0);

                    //设置线路id
                    List<WarehouseLineDO> warehouseLineDOList = warehouseLineMapper.selectList(warehouseLineBaseVO);
                    if (CollectionUtil.isNotEmpty(warehouseLineDOList)) {
                        Long lineIdNew = warehouseLineDOList.stream().map(WarehouseLineDO::getId).findFirst().get();
                        orderDO.setLineId(lineIdNew);
                    }
                }
                //通过目的仓获取shi
                WarehouseRegionVO warehouseRegion = warehouseMapper.findWarehouseRegion(orderSplitBackVO.getDstWarehouseId());
                Long shi = warehouseRegion.getShi();

                //通过shi获取 region
                RegionDO region = regionService.getRegion(shi);

                //OrderObjectiveDO
                OrderObjectiveDO orderObjectiveDO = new OrderObjectiveDO();
                orderObjectiveDO.setOrderId(orderId);
                orderObjectiveDO.setObjectiveId(shi);
                orderObjectiveDO.setObjectiveCountryId(warehouseRegion.getGuojia());
                orderObjectiveDO.setObjectiveWarehouseId(orderSplitBackVO.getDstWarehouseId());
                orderObjectiveDO.setObjective(JSON.toJSONString(region));
                orderObjectiveDO.setType(0);
                orderObjectiveDO.setIsThis(false);

                orderDO.setOrderObjectiveDO(orderObjectiveDO);

                //设置控货人
                OrderCargoControlDO orderCargoControlDO = orderCargoControlService.getActualOrderCargoControlByOrderId(orderId);
                if (orderCargoControlDO != null) {
                    orderCargoControlDO.setId(null);
                    orderDO.setOrderCargoControlDO(orderCargoControlDO);
                }

                //设置orderItem
                List<OrderSplitItemBackVO> orderSplitItemBackVOList = orderSplitBackVO.getOrderSplitItemBackVOList();
                List<OrderItemDO> orderItemDOList = orderDO.getOrderItemDOList();
                if (CollectionUtil.isNotEmpty(orderItemDOList)) {
                    List<OrderItemDO> splitOrderItemDOList = new ArrayList<>();
                    for (OrderItemDO orderItemDO : orderItemDOList) {
                        OrderItemDO newOrderItemDO = new OrderItemDO();
                        BeanUtils.copyProperties(orderItemDO, newOrderItemDO);
                        OrderItemDO splitItem = getSplitOrderItemDO(orderSplitItemBackVOList, newOrderItemDO, splitSeparateOrder);
                        if (Objects.nonNull(splitItem)) {
                            splitOrderItemDOList.add(splitItem);
                        }
                    }
                    if (CollectionUtil.isEmpty(splitOrderItemDOList)) {
                        throw exception(SPLIT_ORDER_ITEM_NOT_NULL, orderSplitBackVO.getOrderNo());
                    }
                    orderDO.setOrderItemDOList(splitOrderItemDOList.stream().peek(item -> item.setOrderItemId(null)).collect(Collectors.toList()));
                }

                if (!orderSplitBackVO.getIsMaster() && !isPartRefundSplit) {
                    // 拆出的单清空自编号和提单号,isMater一定是第一个
                    // 但是部分退场拆单这里不要置空，部分退场拆单只是拆单，还没有完成退场，完成退场会单独去清空
                    orderDO.setContainerNumber(null);
                    orderDO.setTidanNo(null);
                }
                orderDO.setAuditType(0);
                // 执行拆单流程，调用订单接口
                orderService.splitOrder(orderDO, splitMessage);
                orderChildren.add(orderDO);
                orderIds.add(orderDO.getOrderId());

                //20230115 task #1358 子 拆单后子订单沿用父订单的优惠、成交单价、单个品名收款数据 / pda-拆单入仓确认
                //根据此任务，改动点是在拆单后将每个单品进行入仓操作，让其处于入仓中的状态
                //先查询原订单的入仓数据，为后面子订单提供入仓依据
                List<OrderLocationDO> orderLocationDOList = orderLocationService.getOrderLocationListByOrderId(orderId);

                //再处理订单项入仓记录
//                Date date = new Date();
//                List<OrderItemDO> orderItems = orderItemService.getOrderItemsByOrderId(CollectionUtil.newArrayList(orderDO.getOrderId()));
//                for (OrderItemDO orderItemDO : orderItems) {
                //父订单此ProdId对应的OrderItemId(只取1个)
                for (OrderItemDO orderItemDO : orderDO.getOrderItemDOList()) {

                    // TODO 当前主拆单设置默认入仓记录，后期看需求是否改自定义，其他子拆单都为自定义入仓记录
                    OrderWarehouseInCreateReqVO orderWarehouseInCreateReqVO = orderItemDO.getOrderWarehouseInCreateReqVO();
                    orderWarehouseInCreateReqVO.setOrderItemId(orderItemDO.getOrderItemId());
                    orderWarehouseInCreateReqVO.setOrderNo(orderItemDO.getOrderNo());
                    orderWarehouseInCreateReqVO.setOrderId(orderItemDO.getOrderId());
                    if (CollectionUtil.isNotEmpty(orderItemDO.getSpecsRecordVOList())) {
                        // 对有自定义规格记录的子拆单，入仓记录需要重新封装
                        List<OrderWarehouseInItemDto> warehouseInItemDtoList = orderItemDO.getSpecsRecordVOList().stream().map(specsRecordVO -> OrderWarehouseInItemDto.builder()
                                .cartonsNum(specsRecordVO.getNum())
                                .quantityAll(specsRecordVO.getQuantity())
                                .specificationType(specsRecordVO.getSpecificationType())
                                .unit(specsRecordVO.getUnit())
                                .boxGauge(specsRecordVO.getBoxGauge())
                                .expressNo(specsRecordVO.getExpressNo())
                                .remark(specsRecordVO.getRemark())
                                .orderWarehouseInDetailsVOList(specsRecordVO.getOrderWarehouseInDetailsVOList())
                                .orderLocationCreateReqVOList(specsRecordVO.getOrderLocationList())
                                .volume(specsRecordVO.getVolume())
                                .weight(specsRecordVO.getWeight())
                                .build()).filter(Objects::nonNull).collect(Collectors.toList());
                        orderWarehouseInCreateReqVO.setOrderWarehouseInItemDoList(warehouseInItemDtoList);
//                        List<OrderLocationUpdateReqVO> orderLocationList = orderItemDO.getSpecsRecordVOList().stream().map(sr -> sr.getOrderLocationList()).filter(CollectionUtil::isNotEmpty).collect(Collectors.toList());
                    }

                    // 复制源品名的入仓影像到拆单子订单中
                    Long orgItemId = orderItemDO.getOrgItemId();
                    if (orgItemId != null) {
                        List<String> orderItemWarehousePictureUrlList = orderWarehousePictureService.getOrderItemWarehousePictureUrlList(orgItemId);
                        if (CollectionUtil.isNotEmpty(orderItemWarehousePictureUrlList)) {
                            orderWarehouseInCreateReqVO.setPictureUrls(orderItemWarehousePictureUrlList);
                        }
                    }

                    //每个订单项进行自动入仓中
                    orderWarehouseInService.createOrderWarehouseIn(orderWarehouseInCreateReqVO);
                }

                //装柜第一个订单处理成 已入仓
                if (orderSplitBackVO.getIsMaster()) {
                    OrderWarehouseInFinishReqVO orderWarehouseInFinishReqVO = new OrderWarehouseInFinishReqVO();
                    Long orderIdNew = orderDO.getOrderId();
                    orderWarehouseInFinishReqVO.setOrderId(orderIdNew);
                    orderWarehouseInFinishReqVO.setUpdateLabel(false);
                    orderWarehouseInFinishReqVO.setIsAddOrderOperateLog(false);
                    orderWarehouseInFinishReqVO.setIsSplitIn(true);
                    orderWarehouseInFinishReqVO.setUpdateWarehouseInUrl(false);
                    orderWarehouseInService.finishWarehouseIn(orderWarehouseInFinishReqVO);
                }

            }
            //创建标签箱号
            // 获取子订单集合
//            List<OrderDO> orderChildren = orderQueryService.getOrderChildren(orderIds);
            // 更新标签号
            orderLabelService.updateSplitOrderLabel(orderId, orderChildren);


            //计算业绩
//            Date date = new Date();
//            targetLogService.addTargetLog(orderId,date, TargetLogEnum.SPLIT);
//            targetLogService.addTargetLogs(orderIds,date, TargetLogEnum.SPLIT);
        } else {
            log.error("拆单数据为空");
        }

        // 判断如果是子拆单进行的再此拆单，原单不用更改主状态，只需要修改审批类型即可
        Integer status = null;
        Integer warehouseInStatus = OrderWarehouseInStatusEnum.warehouse_finished.getValue();
        if (orderNoAndSeq.length == 1) {
            // 母订单拆单，改变状态，否则就是子订单拆单，继承原单号，修改拆单后的数据值
            status = OrderStatusEnum.SPLIT_ORDER.getValue();
            warehouseInStatus = OrderWarehouseInStatusEnum.order_split_finished.getValue();
            // 拆单成功更新订单操作日志，添加被拆母订单拆单记录描述
            orderBusinessService.addOrderOperateLog(orderId, "订单操作", splitMessage, "");
        }
        orderService.updateStatus(orderId, null, status, null, warehouseInStatus,
                null, 0, OrderApprovalTypeResultEnum.order_split_pass.getDesc(), false);

        // 原订单的应收单归档删除 (这些应收都是未核销的，核销的是不能拆单的)
        // 拆单删除原单可能的业绩日志
        targetLogService.addTargetLog(orderId, null, SPLIT);
        // 判断是否为子拆单进行的再次拆单，如果是，其订单编号和订单id未变，则不用处理关联和互斥业务
        if (orderNoAndSeq.length == 1) {
            receivableService.deleteReceivableByOrderId(orderId);
            // 处理关联关系
            if (splitSeparateOrder) {
                orderGuanlianService.deleteRelationByOrderId(orderId);
            } else {
                orderGuanlianService.dealGuanlianByOrderId(orderId, orderIds, 1);
            }
            // 处理互斥关系
            orderMutualService.dealMutualByOrderId(orderId, orderIds, 1);
        } else {
            // 如果是子订单再拆单，那么原单的费用申请应收记录不用删除，继续继承, 订单计算的应收与订单特性费用则删除
            receivableService.deleteReceivableByOrderIdAndFeeSource(orderId, Arrays.asList(1, 3));
            if (splitSeparateOrder) {
                orderGuanlianService.deleteRelationByOrderId(orderId);
            }
        }
        //20221105 原订单不删除，修改为在查询时过滤掉已拆单的订单
        // orderService.deleteOrder(orderId);
    }

    @Nullable
    private OrderItemDO getSplitOrderItemDO(List<OrderSplitItemBackVO> orderSplitItemBackVOList, OrderItemDO newOrderItemDO, boolean splitSeparateOrder) {
        for (OrderSplitItemBackVO orderSplitItemBackVO : orderSplitItemBackVOList) {
            if (orderSplitItemBackVO.getOrderItemId().equals(newOrderItemDO.getOrderItemId())) {
                newOrderItemDO.setOrgItemId(orderSplitItemBackVO.getOrderItemId());// 保存原订单项id
                newOrderItemDO.setNum(orderSplitItemBackVO.getNum());
                newOrderItemDO.setQuantity(orderSplitItemBackVO.getQuantity());
                newOrderItemDO.setBoxGauge(orderSplitItemBackVO.getBoxGauge());
                newOrderItemDO.setVolume(orderSplitItemBackVO.getVolume());
                newOrderItemDO.setWeight(orderSplitItemBackVO.getWeight());
                newOrderItemDO.setWorth(orderSplitItemBackVO.getWorth());
                newOrderItemDO.setChargeQuantity(orderSplitItemBackVO.getChargeQuantity());
                newOrderItemDO.setChargeWeight(orderSplitItemBackVO.getChargeWeight());
                newOrderItemDO.setChargeVolume(orderSplitItemBackVO.getChargeVolume());
                if (splitSeparateOrder) {
                    // 独立订单, 重置原有特价
                    // TODO 是否排除出货相关拆单的主拆单订单，因为出货阶段的主拆单订单是走的原单业务
                    newOrderItemDO.setSpecialPriceType(Boolean.FALSE);
                    newOrderItemDO.setChannelManualPricing(Boolean.FALSE);
                    // 是否拆单自定义价格以当前拆单项的设置为准
                    newOrderItemDO.setSplitCustomPriceType(orderSplitItemBackVO.getSplitCustomPriceType());
                }
                if (TransportTypeShortEnum.AIR_FREIGHT_LINE.getValue().equals(newOrderItemDO.getTransportId()) || TransportTypeShortEnum.AIR_SEA_COMBINED_TRANSPORT.getValue().equals(newOrderItemDO.getTransportId())) {
                    // 空运比较成交单价是否重新设置，并记录日志
                    List<ApplyInfoVO> applyInfoVOList = new ArrayList<>();
                    if (orderSplitItemBackVO.getSplitCustomPriceType()) {
                        // TODO 运费成交单价有自定义值并且大于0，且与原单成交单价不同时，表示拆单后的子单品名单价有变动，需要记录日志
                        ApplyInfoVO applyInfoVO = new ApplyInfoVO();
                        // 是否模式变动
                        if (newOrderItemDO.getCharging() == 0) {
                            applyInfoVO.setName(orderSplitItemBackVO.getProdTitleZh() + "/" + orderSplitItemBackVO.getProdTitleEn() + "拆单时运费成交单价自定义");
                        } else {
                            applyInfoVO.setName(orderSplitItemBackVO.getProdTitleZh() + "/" + orderSplitItemBackVO.getProdTitleEn() + "拆单时全包价成交单价自定义");
                        }
                        applyInfoVO.setOrgValue(newOrderItemDO.getOneSeaFreight().toString());
                        applyInfoVO.setNewValue(orderSplitItemBackVO.getOneSeaFreight().toString());
                        applyInfoVOList.add(applyInfoVO);
                        newOrderItemDO.setOneSeaFreight(orderSplitItemBackVO.getOneSeaFreight());
                        newOrderItemDO.setSplitCustomPriceType(true);
                    }
                    if (newOrderItemDO.getCharging() == 0) {
                        if (orderSplitItemBackVO.getSplitCustomPriceType()) {
                            // TODO 清关费成交单价有自定义值并且大于0，且与原单成交单价不同时，表示拆单后的子单品名单价有变动，需要记录日志
                            ApplyInfoVO applyInfoVO = new ApplyInfoVO();
                            applyInfoVO.setName(orderSplitItemBackVO.getProdTitleZh() + "/" + orderSplitItemBackVO.getProdTitleEn() + "拆单时清关费成交单价自定义");
                            applyInfoVO.setOrgValue(newOrderItemDO.getOneClearanceFreight().toString());
                            applyInfoVO.setNewValue(orderSplitItemBackVO.getOneClearanceFreight().toString());
                            applyInfoVOList.add(applyInfoVO);
                            newOrderItemDO.setOneClearanceFreight(orderSplitItemBackVO.getOneClearanceFreight());
                            newOrderItemDO.setSplitCustomPriceType(true);
                        }
                    }
                    newOrderItemDO.setApplyInfoVOList(applyInfoVOList);
                }
                WarehouseInInfoVO warehouseInInfoVO = newOrderItemDO.getWarehouseInInfoVO();
                warehouseInInfoVO.setCartonsNum(orderSplitItemBackVO.getNum());
                warehouseInInfoVO.setQuantityAll(orderSplitItemBackVO.getQuantity());
                warehouseInInfoVO.setVolume(orderSplitItemBackVO.getVolume());
                warehouseInInfoVO.setWeight(orderSplitItemBackVO.getWeight());
                newOrderItemDO.setWarehouseInInfoVO(warehouseInInfoVO);
                newOrderItemDO.setWarehouseInInfo(JSON.toJSONString(warehouseInInfoVO));
                OrderWarehouseInCreateReqVO orderWarehouseInCreateReqVO = OrderItemConvert.INSTANCE.convertToOrderWarehouseInCreateReqVO(newOrderItemDO);

                //查询入仓时间
                // OrderWarehouseInDO parentOrderWarehouseInDO = orderWarehouseInList.stream().filter(t -> t.getOrderItemId().equals(orderItemDO.getOrderItemId()))
                //         .sorted(Comparator.comparing(OrderWarehouseInDO::getInTime))
                //         .findFirst().orElse(null);
                OrderWarehouseInDO parentOrderWarehouseInDO = orderWarehouseInService.getMinOrderWarehouseInByOrderItemId(newOrderItemDO.getOrderItemId());
                orderWarehouseInCreateReqVO.setInTime(parentOrderWarehouseInDO != null ? parentOrderWarehouseInDO.getInTime() : new Date());
                //5-拆单后入仓
                orderWarehouseInCreateReqVO.setSource(5);

                //查询入仓
                OrderWarehouseInItemDto orderWarehouseInItemDto = OrderWarehouseInItemDto.builder()
                        .cartonsNum(newOrderItemDO.getNum())
                        .quantityAll(newOrderItemDO.getQuantity())
                        .specificationType(parentOrderWarehouseInDO != null ? parentOrderWarehouseInDO.getSpecificationType() : 1)
                        .unit(parentOrderWarehouseInDO != null ? parentOrderWarehouseInDO.getUnit() : "1")
                        .boxGauge(newOrderItemDO.getBoxGauge())
                        .volume(newOrderItemDO.getVolume()).weight(newOrderItemDO.getWeight())
                        //TODO yanghao 20230228 设置老储位
                        // .orderLocationCreateReqVOList(orderLocationCreateReqVOS)
                        .build();

                orderWarehouseInCreateReqVO.setOrderWarehouseInItemDoList(CollectionUtil.newArrayList(orderWarehouseInItemDto));

                orderWarehouseInCreateReqVO.setIsSplitOrderAutoCreate(true);
                orderWarehouseInCreateReqVO.setIsAddOrderOperateLog(false);

                newOrderItemDO.setOrderWarehouseInCreateReqVO(orderWarehouseInCreateReqVO);

                if (StringUtils.isNotBlank(orderSplitItemBackVO.getSpecsRecord())) {
                    newOrderItemDO.setSpecsRecordVOList(JSONObject.parseArray(orderSplitItemBackVO.getSpecsRecord(), OrderSpiltItemSpecsRecordVO.class));
                }
                return newOrderItemDO;
            }
        }
        return null;
    }

    @Override
    public void removeByOrderId(Long orderId) {
        // 删除拆单时需要删除拆单项
        splitItemMapper.deleteByOrderIdAndUsed(orderId);
        splitMapper.deleteByOrderIdAndUsed(orderId);
    }

    @Override
    public OrderSplitRevokeApplyDetailDto revokeSplitInfo(Long orderId) {
        OrderDO orderDO = orderService.getById(orderId);
        if (Objects.nonNull(orderDO.getInitialParentOrderId()) && orderDO.getInitialParentOrderId() > 0L) {
            // 获取母订单信息
            orderDO = orderService.getById(orderDO.getInitialParentOrderId());
        } else {
            String[] orderNoAndSeq = orderDO.getOrderNo().split(StrUtil.DASHED);
            // 判断当前订单是母订单还是子订单，并且获取所有子订单
            if (orderNoAndSeq.length == 2) {
                // 获取母订单信息
                orderDO = orderService.getOne(new LambdaQueryWrapper<OrderDO>().eq(OrderDO::getOrderNo, orderNoAndSeq[0]));
            }
        }

        // 检查是否审批中的撤销拆单申请
        OrderApprovalDO orderApprovalDO = orderApprovalService.getOne(new LambdaQueryWrapper<OrderApprovalDO>().eq(OrderApprovalDO::getOrderId, orderDO.getOrderId())
                .eq(OrderApprovalDO::getType, OrderApprovalTypeEnum.ORDER_SPLIT_REVOKE.getValue())
                .eq(OrderApprovalDO::getStatus, OrderApprovalTypeResultEnum.order_split_revoke_processing.getResult())
                .orderByDesc(OrderApprovalDO::getOrderApprovalId).last("limit 1"));
        if (Objects.nonNull(orderApprovalDO)) {
            OrderSplitRevokeApplyDetailDto orderSplitRevokeApplyDetailDto = JSONObject.parseObject(orderApprovalDO.getDetails(), OrderSplitRevokeApplyDetailDto.class);
            orderSplitRevokeApplyDetailDto.setType(orderApprovalDO.getType());
            orderSplitRevokeApplyDetailDto.setFormId(orderApprovalDO.getFormId());
            orderSplitRevokeApplyDetailDto.setOrderId(orderApprovalDO.getOrderId());
            return orderSplitRevokeApplyDetailDto;
        }

        // 获取所有子订单信息
        List<OrderDO> childrenOrderList = orderService.list(new LambdaQueryWrapper<OrderDO>().eq(OrderDO::getInitialParentOrderId, orderDO.getOrderId()));
        if (CollectionUtil.isEmpty(childrenOrderList)) {
            childrenOrderList = orderQueryService.getOrderChildrenLikeByOrderNo(orderDO.getOrderNo().concat(StrUtil.DASHED));
        }
        if (CollectionUtil.isEmpty(childrenOrderList)) {
            throw exception(ORDER_NOT_IS_SPLIT_ORDER);
        }
        return getOrderSplitRevokeApplyDetailDto(orderDO, orderDO.getOrderId(), childrenOrderList);
    }


    @Override
    public OrderSplitRevokeApplyDetailDto revokeSplitInfoByApprovalId(Long approvalId) {
        // 撤销拆单申请的审批详情
        OrderApprovalDO orderApprovalDO = orderApprovalService.getById(approvalId);
        if (Objects.nonNull(orderApprovalDO)) {
            OrderSplitRevokeApplyDetailDto orderSplitRevokeApplyDetailDto = JSONObject.parseObject(orderApprovalDO.getDetails(), OrderSplitRevokeApplyDetailDto.class);
            orderSplitRevokeApplyDetailDto.setType(orderApprovalDO.getType());
            orderSplitRevokeApplyDetailDto.setFormId(orderApprovalDO.getFormId());
            orderSplitRevokeApplyDetailDto.setOrderId(orderApprovalDO.getOrderId());
            return orderSplitRevokeApplyDetailDto;
        }
        return null;
    }

    @Override
    public boolean revoke(OrderSplitApplyReqVO applyReqVO) {
        OrderDO orderDO = orderService.getById(applyReqVO.getOrderId());
        if (Objects.nonNull(orderDO.getInitialParentOrderId()) && orderDO.getInitialParentOrderId() > 0L) {
            // 获取母订单信息
            orderDO = orderService.getById(orderDO.getInitialParentOrderId());
        } else {
            String[] orderNoAndSeq = orderDO.getOrderNo().split(StrUtil.DASHED);
            // 判断当前订单是母订单还是子订单，并且获取所有子订单
            if (orderNoAndSeq.length == 2) {
                // 获取母订单信息
                orderDO = orderService.getOne(new LambdaQueryWrapper<OrderDO>().eq(OrderDO::getOrderNo, orderNoAndSeq[0]));
            }
        }
        // 获取所有子订单信息
        List<OrderDO> childrenOrderList = orderService.list(new LambdaQueryWrapper<OrderDO>().eq(OrderDO::getInitialParentOrderId, orderDO.getOrderId()));
        if (CollectionUtil.isEmpty(childrenOrderList)) {
            childrenOrderList = orderQueryService.getOrderChildrenLikeByOrderNo(orderDO.getOrderNo().concat(StrUtil.DASHED));
        }
        if (CollectionUtil.isEmpty(childrenOrderList)) {
            throw exception(ORDER_NOT_IS_SPLIT_ORDER);
        }
        // 所有子订单的订单id
        List<Long> orderIds = childrenOrderList.stream().map(OrderDO::getOrderId).collect(Collectors.toList());
        // 校验标签箱号范围值
//        this.checkLabel(orderDO, orderIds);
        OrderSplitRevokeApplyDetailDto orderSplitRevokeApplyDetailDto = getOrderSplitRevokeApplyDetailDto(orderDO, orderDO.getOrderId(), childrenOrderList);
        // TODO 校验通过后开始提交撤销拆单审批请求
        //创建审批单，发起流程
        OrderApprovalDO orderApprovalDO = new OrderApprovalDO();
        orderApprovalDO.setFollowUpSalesmanId(String.valueOf(SecurityFrameworkUtils.getLoginUserId()));
        orderApprovalDO.setOrderId(orderDO.getOrderId());
        //撤销拆单申请
        //更新订单审批类型 28-拆单申请中
        Integer auditType = OrderApprovalTypeResultEnum.order_split_revoke_processing.getType();
        orderApprovalDO.setType(auditType);
        orderApprovalDO.setDetails(JSON.toJSONString(orderSplitRevokeApplyDetailDto));
        orderApprovalDO.setStatus(ApprovalResultStatusEnum.processing.getValue());
        orderApprovalService.applyAndCreate(orderApprovalDO, WorkFlowEmus.REVOKE_SPLIT_ORDER, applyReqVO.getCopyUserId());

        for (OrderDO orderChildren : childrenOrderList) {

            orderService.updateStatus(orderChildren.getOrderId(), null, null, null, OrderWarehouseInStatusEnum.order_split_revoke_applying.getValue(), null, auditType, OrderApprovalTypeResultEnum.typeAndResultOf(auditType, 1).getDesc(), false);

            //纪录仓库操作
            orderBusinessService.addOrderOperateLog(orderChildren.getOrderId(), "仓库操作", "提交撤销拆单申请", "");
        }
        return true;
    }

    private void checkLabel(OrderDO orderDO, List<Long> childrenOrderIds) {
        // 获取父订单的箱号范围
        List<OrderLabelDO> orderLabelDOList = orderLabelService.list(new LambdaQueryWrapper<OrderLabelDO>().in(OrderLabelDO::getOrderId, childrenOrderIds));
        List<Integer> labelList = new ArrayList<>();
        for (OrderLabelDO orderLabelDO : orderLabelDOList) {
            orderLabelService.getLabelList(labelList, orderLabelDO.getStart(), orderLabelDO.getEnd());
        }
        //判断标签箱号本身是否有重复
        long distinctSize = labelList.stream().distinct().count();
        if (distinctSize != labelList.size()) {
            throw ServiceExceptionUtil.exception(ORDER_LABEL_OVERLAY);
        }
        // 保证入箱总箱数与所有子订单的标签箱号一致
        if (orderDO.getSumNum() != labelList.size()) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.ORDER_LABEL_NUM_NOT_SAME_WITH_WAREHOUSE_IN_NUM);
        }
    }

    @NotNull
    private OrderSplitRevokeApplyDetailDto getOrderSplitRevokeApplyDetailDto(OrderDO orderDO, Long
            parentOrderId, List<OrderDO> orderChildrens) {
        List<OrderBackInfoDto> childrenOrderList = new ArrayList<>();
        // 检查子订单是否有已核销的应收单
        if (CollectionUtil.isNotEmpty(orderChildrens)) {
            StringBuilder sb1 = null;
            StringBuilder sb2 = null;
            StringBuilder sb3 = null;
            StringBuilder sb4 = null;
            StringBuilder sb5 = null;
            // 检查在排单中的订单
            List<Long> orderIds = orderChildrens.stream().map(OrderDO::getOrderId).collect(Collectors.toList());
            BoxCheckOrdersSchedulingEvent event = new BoxCheckOrdersSchedulingEvent(orderIds, null);
            applicationContext.publishEvent(event);
            for (OrderDO children : orderChildrens) {
                childrenOrderList.add(orderQueryService.info(children.getOrderId()));
                try {
                    // 校验是否有已核销的应收单，如果有，则不能再次入仓修改
                    receivableService.verificationReceivableIsWriteOff(children.getOrderId(), null);
                } catch (Exception e) {
                    log.error(e.getMessage());
                    // 检查有已核销的订单
                    if (sb1 == null) {
                        sb1 = new StringBuilder();
                        sb1.append(children.getOrderNo());
                    } else {
                        sb1.append(",").append(children.getOrderNo());
                    }
                }
                if (children.getAuditType() != 0) {
                    // 检查正在审批中的订单
                    if (sb2 == null) {
                        sb2 = new StringBuilder();
                        sb2.append(children.getOrderNo());
                    } else {
                        sb2.append(",").append(children.getOrderNo());
                    }
                }

                if (!Objects.equals(children.getStatus(), OrderStatusEnum.WAREHOUSING.getValue())
                        && !Objects.equals(children.getStatus(), OrderStatusEnum.IN_WAREHOUSE.getValue())
                        && !Objects.equals(children.getStatus(), OrderStatusEnum.SPLIT_ORDER.getValue())
                        && children.getShipmentState() != 0) {
                    // 检查子订单是否在入仓状态
                    if (sb3 == null) {
                        sb3 = new StringBuilder();
                        sb3.append(children.getOrderNo());
                    } else {
                        sb3.append(",").append(children.getOrderNo());
                    }
                }

                if (orderDO.getIsCargoControl()) {
                    // 检查控货订单的放货状态
                    if (children.getCargoControlStatus() > 1) {
                        if (sb4 == null) {
                            sb4 = new StringBuilder();
                            sb4.append(children.getOrderNo());
                        } else {
                            sb4.append(",").append(children.getOrderNo());
                        }
                    }
                }
                if ((CollectionUtil.isNotEmpty(event.getSchedulingOrderIds()) && event.getSchedulingOrderIds().contains(children.getOrderId()))) {
                    // 订单出货子状态shipmentState不为0，但是主状态status=5是入仓，表示已添加预装排单，此时也不能撤销拆单
                    if (sb5 == null) {
                        sb5 = new StringBuilder();
                        sb5.append(children.getOrderNo());
                    } else {
                        sb5.append(",").append(children.getOrderNo());
                    }
                }
            }
            if (sb1 != null) {
                throw exception(ORDER_HAS_BEEN_WRITTEN_OFF_UN_REVOKE_SPLIT, sb1.toString());
            }
            if (sb2 != null) {
                throw exception(ORDER_APPLYING_UN_REVOKE_SPLIT, sb2.toString());
            }
            if (sb3 != null) {
                throw exception(ORDER_NOT_WAREHOUSE_IN_UN_REVOKE_SPLIT, sb3.toString());
            }
            if (sb4 != null) {
                throw exception(CARGO_CONTROL_ORDERS_PICK_NOT_SPLIT, sb4.toString());
            }
            if (sb5 != null) {
                throw exception(ORDER_SCHEDULING_UN_REVOKE_SPLIT, sb5.toString());
            }
        }

        OrderSplitRevokeApplyDetailDto orderSplitRevokeApplyDetailDto = new OrderSplitRevokeApplyDetailDto();
        orderSplitRevokeApplyDetailDto.setParentOrder(orderQueryService.info(parentOrderId));
        orderSplitRevokeApplyDetailDto.setChildrenOrderList(childrenOrderList);
        return orderSplitRevokeApplyDetailDto;
    }


    @Override
    public boolean cancelRevoke(OrderApprovalCancelApplyReqVO cancelApplyReqVO) {
        OrderDO orderDO = orderService.getById(cancelApplyReqVO.getOrderId());
        Long parentOrderId;
        if (Objects.nonNull(orderDO.getParentOrderId()) && orderDO.getParentOrderId() > 0) {
            // 获取最一级父订单id
            parentOrderId = this.getParentOrderId(orderDO);
        } else {
            parentOrderId = orderDO.getOrderId();
        }
        // 检查是否审批中的撤销拆单申请
        OrderApprovalDO orderApprovalDO = orderApprovalService.getOne(new LambdaQueryWrapper<OrderApprovalDO>().eq(OrderApprovalDO::getOrderId, parentOrderId)
                .eq(OrderApprovalDO::getType, OrderApprovalTypeEnum.ORDER_SPLIT_REVOKE.getValue())
                .eq(OrderApprovalDO::getStatus, OrderApprovalTypeResultEnum.order_split_revoke_processing.getResult())
                .orderByDesc(OrderApprovalDO::getOrderApprovalId).last("limit 1"));
        if (Objects.nonNull(orderApprovalDO)) {
            orderApprovalService.cancelApplyAndUpdate(orderApprovalDO, cancelApplyReqVO.getReason());
        } else {
            throw exception(APPROVAL_NOT_EXISTS);
        }
        return true;
    }

    private Long getParentOrderId(OrderDO orderDO) {
        // 获取所有子订单信息
        OrderDO order;
        if (Objects.nonNull(orderDO.getInitialParentOrderId()) && orderDO.getInitialParentOrderId() > 0L) {
            // 获取母订单信息
            order = orderService.getById(orderDO.getInitialParentOrderId());
        } else {
            // 获取母订单信息
            order = orderService.getOne(new LambdaQueryWrapper<OrderDO>().eq(OrderDO::getOrderNo, orderDO.getOrderNo().split(StrUtil.DASHED)[0]));
        }
        return order.getOrderId();
    }


    @Override
    public void revokeSplitApplyCallback(String approvalId, Integer result) {
        OrderApprovalDO orderApprovalDO =
                orderApprovalService.getById(approvalId);

        //detail转对象
        OrderSplitRevokeApplyDetailDto orderSplitRevokeApplyDetailDto =
                JSON.parseObject(orderApprovalDO.getDetails(),
                        OrderSplitRevokeApplyDetailDto.class);

        OrderBackInfoDto parentOrder =
                orderSplitRevokeApplyDetailDto.getParentOrder();

        List<OrderBackInfoDto> childrenOrderList =
                orderSplitRevokeApplyDetailDto.getChildrenOrderList();

        //更新审核单状态
        orderApprovalService.callbackUpdate(orderApprovalDO,
                orderApprovalDO.getFormId(), result);

        String processingResults = orderApprovalDO.getProcessingResults();
        if (ApprovalResultStatusEnum.reject.getValue().equals(result)) {
            //更新订单状态  入仓-撤销拆单-已拒绝
            orderService.updateStatus(parentOrder.getOrderId(), null, null, null, OrderWarehouseInStatusEnum.order_split_finished.getValue(), null,
                    0, OrderApprovalTypeResultEnum.typeAndResultOf(orderApprovalDO.getType(), result).getDesc(), false);
            //纪录仓库操作
            orderBusinessService.addOrderOperateLog(parentOrder.getOrderId(), "仓库操作", "撤销拆单申请拒绝", "");
            for (OrderBackInfoDto orderBackInfoDto : childrenOrderList) {
                //更新订单状态  入仓-撤销拆单-已拒绝
                orderService.updateStatus(orderBackInfoDto.getOrderId(), null, null, null, OrderWarehouseInStatusEnum.warehouse_finished.getValue(), null,
                        0, OrderApprovalTypeResultEnum.typeAndResultOf(orderApprovalDO.getType(), result).getDesc(), false);
                //纪录仓库操作
                orderBusinessService.addOrderOperateLog(orderBackInfoDto.getOrderId(), "仓库操作", "撤销拆单申请拒绝", "");
            }
        } else if (ApprovalResultStatusEnum.cancel.getValue().equals(result)) {
            //更新订单状态  入仓-撤销拆单-已取消
            orderService.updateStatus(parentOrder.getOrderId(), null, null, null, OrderWarehouseInStatusEnum.order_split_finished.getValue(), null,
                    0, OrderApprovalTypeResultEnum.typeAndResultOf(orderApprovalDO.getType(), result).getDesc(), false);
            //纪录仓库操作
            orderBusinessService.addOrderOperateLog(parentOrder.getOrderId(), "仓库操作", "撤销拆单申请取消", "");
            for (OrderBackInfoDto orderBackInfoDto : childrenOrderList) {
                //更新订单状态  入仓-撤销拆单-已取消
                orderService.updateStatus(orderBackInfoDto.getOrderId(), null, null, null, OrderWarehouseInStatusEnum.warehouse_finished.getValue(), null,
                        0, OrderApprovalTypeResultEnum.typeAndResultOf(orderApprovalDO.getType(), result).getDesc(), false);
                //纪录仓库操作
                orderBusinessService.addOrderOperateLog(orderBackInfoDto.getOrderId(), "仓库操作", "撤销拆单申请取消", "");
            }
        } else if (ApprovalResultStatusEnum.pass.getValue().equals(result)) {
            OrderDO orderDO = orderService.getById(parentOrder.getOrderId());
            // 记录撤销拆单成功的动态日志
            orderBusinessService.addOrderTimeLog(orderDO.getStatus(),
                    orderDO, 10);
            // 所有子订单的订单id
//            List<Long> orderIds = childrenOrderList.stream().map(OrderBackInfoDto::getOrderId).collect(Collectors.toList());
            // 校验标签箱号范围值
//            this.checkLabel(orderDO, orderIds);
            // 补全原单的标签箱号记录
            orderLabelService.updateRevokeSplitOrderLabel(orderDO,
                    childrenOrderList);
            //更新订单状态  入仓-撤销拆单-已通过 ，注：避免原单是出货阶段进行的拆单，撤销拆单需要重置出货状态，出货阶段是不允许撤销拆单的
            orderService.updateStatus(parentOrder.getOrderId(),
                    null, OrderStatusEnum.IN_WAREHOUSE.getValue(),
                    null,
                    OrderWarehouseInStatusEnum.warehouse_finished.getValue(),
                    0,
                    0,
                    OrderApprovalTypeResultEnum.typeAndResultOf(orderApprovalDO.getType(),
                            result).getDesc(),
                    null,
                    false);
            // 撤销拆单将母订单的动态重置
            if (parentOrder.getTransportId() == 1) {
                orderTimeService.preReverseReviewDeleteOrderTime(parentOrder.getOrderId());
            } else if (parentOrder.getTransportId() == 3) {
                orderTimeService.sortingReverseReviewDeleteOrderTime(parentOrder.getOrderId());
            }
            //纪录仓库操作
            orderBusinessService.addOrderOperateLog(parentOrder.getOrderId(), "仓库操作", "已撤销拆单", "");
            for (OrderBackInfoDto orderBackInfoDto : childrenOrderList) {
                // 如果子拆单是已拆单状态，说明其进行了二次拆单，则需要操作删除其相关拆单记录信息
//                if (Objects.equals(orderBackInfoDto.getStatus(), OrderStatusEnum.SPLIT_ORDER.getValue())) {
                // 根据子拆单，删除子拆单的再次拆单记录信息
                splitItemMapper.deleteByOrderId(orderBackInfoDto.getOrderId());
                splitMapper.deleteByOrderId(orderBackInfoDto.getOrderId());
//                }
            }
            // 根据母订单id删除相关拆单信息
            splitItemMapper.deleteByOrderId(parentOrder.getOrderId());
            splitMapper.deleteByOrderId(parentOrder.getOrderId());
            // 删除已撤销的拆单 处理审批流BUG
            orderService.deleteOrderByParentOrderId(parentOrder.getOrderId(),
                    childrenOrderList);

        }
    }
}
