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

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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.i18n.core.I18nMessage;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.depository.service.warehouse.WarehouseService;
import cn.iocoder.yudao.module.ecw.dal.dataobject.unit.UnitDO;
import cn.iocoder.yudao.module.ecw.service.unit.UnitService;
import cn.iocoder.yudao.module.order.dal.dataobject.order.OrderDO;
import cn.iocoder.yudao.module.order.dal.dataobject.orderItem.OrderItemDO;
import cn.iocoder.yudao.module.order.dal.dataobject.orderSplit.OrderSplitDO;
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.orderWarehouseIn.OrderWarehouseInMapper;
import cn.iocoder.yudao.module.order.enums.OrderStatusEnum;
import cn.iocoder.yudao.module.order.enums.TransportTypeShortEnum;
import cn.iocoder.yudao.module.order.service.order.OrderQueryService;
import cn.iocoder.yudao.module.order.service.orderSplit.OrderSplitCheckService;
import cn.iocoder.yudao.module.order.vo.order.CostVO;
import cn.iocoder.yudao.module.order.vo.order.WarehouseInInfoVO;
import cn.iocoder.yudao.module.product.component.ProdCostCalculation;
import cn.iocoder.yudao.module.product.param.ProdConditionParam;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import cn.iocoder.yudao.framework.mybatis.core.vo.PageVO;
import cn.iocoder.yudao.framework.mybatis.core.service.AbstractService;
import cn.iocoder.yudao.module.order.vo.orderSplitItem.*;
import cn.iocoder.yudao.module.order.dal.dataobject.orderSplitItem.OrderSplitItemDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.order.dal.mysql.orderSplitItem.OrderSplitItemMapper;

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.ErrorCodeConstants.ORDER_SPLIT_ITEM_VOLUME_FEW_EXCEPTION;

/**
 * 订单拆单产品项 Service 实现类
 *
 * @author yanghao
 */
@Service
@Validated
public class OrderSplitItemServiceImpl extends AbstractService<OrderSplitItemMapper, OrderSplitItemDO> implements OrderSplitItemService {

    @Resource
    private OrderSplitItemMapper splitItemMapper;
    @Resource
    private ProdCostCalculation calculation;
    @Resource
    private OrderItemMapper orderItemMapper;

    @Resource
    private OrderQueryService orderQueryService;

    @Resource
    private OrderSplitMapper splitMapper;

    @Resource
    private OrderSplitCheckService orderSplitCheckService;

    @Resource
    private WarehouseService warehouseService;
    @Resource
    private OrderWarehouseInMapper orderWarehouseInMapper;
    @Resource
    private UnitService unitService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean createSplitItem(OrderSplitItemCreateReqVO createReqVO) {

        Long orderItemId = createReqVO.getOrderItemId();
        Long orderSplitId = createReqVO.getOrderSplitId();

        OrderItemDO sourceOrderItemDo = orderItemMapper.selectById(orderItemId);
        if (sourceOrderItemDo == null) {
            throw exception(ORDER_ITEM_NOT_EXISTS);
        }
        // 判断当前订单是否有审批业务，有则不能进行拆单放入业务
        OrderDO orderDO = orderQueryService.getOrderById(sourceOrderItemDo.getOrderId());
        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<OrderWarehouseInDO> warehouseInDOList = orderWarehouseInMapper.selectList(new LambdaQueryWrapper<OrderWarehouseInDO>()
                .eq(OrderWarehouseInDO::getOrderItemId, sourceOrderItemDo.getOrderItemId())
                .eq(OrderWarehouseInDO::getOrderId, sourceOrderItemDo.getOrderId()));
        Map<Long, OrderWarehouseInDO> warehouseInMap = warehouseInDOList.stream().collect(Collectors.toMap(OrderWarehouseInDO::getId, v -> v, (v1, v2) -> v2));
        OrderSplitDO orderSplitDO = splitMapper.selectById(orderSplitId);

        if (orderSplitDO == null) {
            throw exception(ORDER_SPLIT_NOT_EXISTS);
        }
        if (Objects.isNull(sourceOrderItemDo.getWarehouseInInfoVO())) {
            throw exception(SPLIT_ORDER_WAREHOUSE_IN_DATA_EXCEPTION);
        }
        WarehouseInInfoVO warehouseInInfoVO = sourceOrderItemDo.getWarehouseInInfoVO();
        OrderSplitDO splitMaster = null;
        OrderSplitItemDO orderSplitMasterItemDO = null;
        List<OrderSplitItemDO> orderSplitMasterItemDOList = null;
        if (createReqVO.getShipmentSplit()) {
            splitMaster = splitMapper.selectOne(new LambdaQueryWrapperX<OrderSplitDO>()
                    .eq(OrderSplitDO::getParentOrderId, orderSplitDO.getParentOrderId())
                    .eq(OrderSplitDO::getUsed, Boolean.FALSE)
                    .eq(OrderSplitDO::getIsMaster, true));
            if (Objects.isNull(splitMaster)) {
                throw exception(ORDER_SPLIT_NOT_EXISTS);
            }
            orderSplitMasterItemDOList = splitItemMapper.selectList(new LambdaQueryWrapperX<OrderSplitItemDO>()
                    .eq(OrderSplitItemDO::getOrderSplitId, splitMaster.getId())
                    .eq(OrderSplitItemDO::getUsed, Boolean.FALSE));
            if (CollectionUtil.isEmpty(orderSplitMasterItemDOList)) {
                throw exception(ORDER_SPLIT_NOT_EXISTS);
            }
            orderSplitMasterItemDO = orderSplitMasterItemDOList.stream().filter(item -> Objects.equals(item.getOrderItemId(), orderItemId)).findFirst().orElse(null);
            if (Objects.isNull(orderSplitMasterItemDO)) {
                throw exception(ORDER_SPLIT_NOT_EXISTS);
            }
        }

        //原单箱数、数量
        int allNum = Objects.isNull(warehouseInInfoVO.getCartonsNum()) ? 0 : warehouseInInfoVO.getCartonsNum();
        int quantity = Objects.isNull(warehouseInInfoVO.getQuantityAll()) ? 0 : warehouseInInfoVO.getQuantityAll();
        if (allNum <= 0) {
            throw exception(ORDER_SPLIT_ITEM_NOT_REMOVABLE_NUM);
        }
        // TODO 货值需要匹配整个订单的
        CostVO costVO = JSONObject.parseObject(orderDO.getCost(), CostVO.class);
        BigDecimal totalWorth = costVO.getTotalWorth();
        // 原单入仓属性
        BigDecimal weight = warehouseInInfoVO.getWeight();
        BigDecimal volume = warehouseInInfoVO.getVolume();
        String boxGauge = warehouseInInfoVO.getBoxGauge();

        // 原单收费属性
        BigDecimal chargeWeight = sourceOrderItemDo.getChargeWeight();
        BigDecimal chargeVolume = sourceOrderItemDo.getChargeVolume();
        BigDecimal chargeQuantity = sourceOrderItemDo.getChargeQuantity();

        boolean isSpecsRecord = false;
        // 根据规格记录来计算拆单数据参数
        if (CollectionUtil.isNotEmpty(createReqVO.getSpecsRecordVOList())) {
            // 判断规格记录是否为已知的原入仓记录规格
            orderSplitCheckService.checkWarehouseInId(createReqVO.getSpecsRecordVOList(), warehouseInDOList);
            for (OrderSpiltItemSpecsRecordVO record : createReqVO.getSpecsRecordVOList()) {
                // 为拆单的入仓记录补充原单入仓时间
                OrderWarehouseInDO warehouseInDO = warehouseInMap.get(record.getWarehouseInId());
                if (Objects.nonNull(warehouseInDO)) {
                    record.setInTime(warehouseInDO.getInTime());
                    // 箱明细补充
                    record.setOrderWarehouseInDetailsVOList(warehouseInDO.getOrderWarehouseInDetailsVOList());
                }
            }
            boxGauge = createReqVO.getSpecsRecordVOList().stream().map(OrderSpiltItemSpecsRecordVO::getBoxGauge).findFirst().get();
            createReqVO.setNum(createReqVO.getSpecsRecordVOList().stream().map(OrderSpiltItemSpecsRecordVO::getNum).filter(Objects::nonNull).mapToInt(Integer::intValue).sum());
            createReqVO.setQuantity(createReqVO.getSpecsRecordVOList().stream().map(OrderSpiltItemSpecsRecordVO::getQuantity).filter(Objects::nonNull).mapToInt(Integer::intValue).sum());
            createReqVO.setVolume(createReqVO.getSpecsRecordVOList().stream().map(OrderSpiltItemSpecsRecordVO::getVolume).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
            createReqVO.setWeight(createReqVO.getSpecsRecordVOList().stream().map(OrderSpiltItemSpecsRecordVO::getWeight).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
            isSpecsRecord = true;
        }
        boolean quantityRequired = warehouseService.quantityRequired(orderDO.getLineId());
        if (quantityRequired) {
            if (Objects.isNull(createReqVO.getQuantity()) || createReqVO.getQuantity() == 0 || createReqVO.getQuantity() < 0) {
                throw exception(CALCULATION_UNIT_QUANTITY_NOT_NULL);
            }
        }
        if (createReqVO.getShipmentSplit()) {
            //主拆单箱数、数量
            int masterNum = orderSplitMasterItemDO.getNum();
            int masterQuantity = orderSplitMasterItemDO.getQuantity();
            if (masterNum <= 0) {
                throw exception(ORDER_SPLIT_ITEM_NOT_REMOVABLE_NUM);
            }
            // 主拆单入仓属性
            BigDecimal masterWeight = orderSplitMasterItemDO.getWeight();
            BigDecimal masterVolume = orderSplitMasterItemDO.getVolume();
            BigDecimal masterWorth = orderSplitMasterItemDO.getWorth();
            String masterBoxGauge = orderSplitMasterItemDO.getBoxGauge();
            // 主拆单收费属性
            BigDecimal masterChargeWeight = orderSplitMasterItemDO.getChargeWeight();
            BigDecimal masterChargeVolume = orderSplitMasterItemDO.getChargeVolume();
            BigDecimal masterChargeQuantity = orderSplitMasterItemDO.getChargeQuantity();
            // 避免平均值计算的误差造成拆单数值无法通过强一致校验，在该订单项从主订单全部拆出时，对拆单数据进行验证
            if (allNum == createReqVO.getNum()) {
                // 当此拆单项全部从主订单拆出时
                if (Objects.isNull(createReqVO.getVolume())) {
                    createReqVO.setVolume(masterVolume);
                }
                if (Objects.isNull(createReqVO.getWeight())) {
                    createReqVO.setWeight(masterWeight);
                }
                if (Objects.isNull(createReqVO.getQuantity())) {
                    createReqVO.setQuantity(masterQuantity);
                }
                if (Objects.isNull(createReqVO.getChargeVolume())) {
                    createReqVO.setChargeVolume(masterChargeVolume);
                }
                if (Objects.isNull(createReqVO.getChargeWeight())) {
                    createReqVO.setChargeWeight(masterChargeWeight);
                }
                if (Objects.isNull(createReqVO.getWorth())) {
                    createReqVO.setChargeWeight(masterWorth);
                }
            }
        } else {
            // 避免平均值计算的误差造成拆单数值无法通过强一致校验，在该订单项从主订单全部拆出时，对拆单数据进行验证
            if (allNum == createReqVO.getNum()) {
                // 当此拆单项全部从主订单拆出时
                if (Objects.isNull(createReqVO.getVolume())) {
                    createReqVO.setVolume(volume);
                }
                if (Objects.isNull(createReqVO.getWeight())) {
                    createReqVO.setWeight(weight);
                }
                if (Objects.isNull(createReqVO.getQuantity())) {
                    createReqVO.setQuantity(quantity);
                }
                if (Objects.isNull(createReqVO.getChargeVolume())) {
                    createReqVO.setChargeVolume(chargeVolume);
                }
                if (Objects.isNull(createReqVO.getChargeWeight())) {
                    createReqVO.setChargeWeight(chargeWeight);
                }
            }
        }
        //当前子order的item 存在时增加，不存在时新增
        OrderSplitItemDO orderSplitItemDO = splitItemMapper.selectOne(new LambdaQueryWrapperX<OrderSplitItemDO>()
                .eq(OrderSplitItemDO::getOrderSplitId, orderSplitId)
                .eq(OrderSplitItemDO::getUsed, Boolean.FALSE)
                .eq(OrderSplitItemDO::getOrderItemId, createReqVO.getOrderItemId()));
        // 初始化当前子拆单数据
        //当前子拆单箱数、数量
        int splitNum = 0;
        int splitQuantity = 0;

        // 当前子拆单入仓属性
        BigDecimal splitWeight = BigDecimal.ZERO;
        BigDecimal splitVolume = BigDecimal.ZERO;
        BigDecimal splitWorth = BigDecimal.ZERO;

        // 当前子拆单收费属性
        BigDecimal splitChargeWeight = BigDecimal.ZERO;
        BigDecimal splitChargeVolume = BigDecimal.ZERO;
        BigDecimal splitChargeQuantity = BigDecimal.ZERO;

        // 判断是否要初始化拆单值
        if (orderSplitItemDO != null) {
            //当前子拆单箱数、数量
            splitNum = orderSplitItemDO.getNum();
            splitQuantity = orderSplitItemDO.getQuantity();

            // 当前子拆单入仓属性
            splitWeight = orderSplitItemDO.getWeight();
            splitVolume = orderSplitItemDO.getVolume();
            splitWorth = orderSplitItemDO.getWorth();

            // 当前子拆单收费属性
            splitChargeWeight = orderSplitItemDO.getChargeWeight();
            splitChargeVolume = orderSplitItemDO.getChargeVolume();
            splitChargeQuantity = orderSplitItemDO.getChargeQuantity();

            orderSplitItemDO.setNum(isSpecsRecord ? createReqVO.getNum() : (splitNum + createReqVO.getNum()));
            if (CollectionUtil.isNotEmpty(createReqVO.getSpecsRecordVOList())) {
                orderSplitItemDO.setSpecsRecord(JSONObject.toJSONString(createReqVO.getSpecsRecordVOList()));
            }
        } else {
            orderSplitItemDO = BeanUtil.copyProperties(sourceOrderItemDo, OrderSplitItemDO.class);
            orderSplitItemDO.setOrderSplitId(orderSplitId);
            orderSplitItemDO.setNum(createReqVO.getNum());
            orderSplitItemDO.setQuantity(0);
            orderSplitItemDO.setWeight(BigDecimal.ZERO);
            orderSplitItemDO.setVolume(BigDecimal.ZERO);
            orderSplitItemDO.setChargeQuantity(BigDecimal.ZERO);
            orderSplitItemDO.setChargeWeight(BigDecimal.ZERO);
            orderSplitItemDO.setChargeVolume(BigDecimal.ZERO);
            orderSplitItemDO.setWorth(BigDecimal.ZERO);

        }
        // 校验数量
        if (Objects.nonNull(createReqVO.getQuantity())) {
            orderSplitItemDO.setQuantity(isSpecsRecord ? createReqVO.getQuantity() : splitQuantity + createReqVO.getQuantity());
            orderSplitItemDO.setChargeQuantity(isSpecsRecord ? new BigDecimal(createReqVO.getQuantity()) : new BigDecimal(splitQuantity).add(new BigDecimal(createReqVO.getQuantity())));
            if (Objects.equals(orderSplitItemDO.getNum(), allNum)) {
                int quantityDifference = orderSplitItemDO.getQuantity() - quantity;
                if (quantityDifference != 0) {
                    if (quantityDifference > 0) {
                        throw exception(ORDER_SPLIT_ITEM_QUANTITY_MANY_EXCEPTION, quantityDifference);
                    } else {
                        throw exception(ORDER_SPLIT_ITEM_QUANTITY_FEW_EXCEPTION, -quantityDifference);
                    }
                }
            }
        } else {
            orderSplitItemDO.setQuantity(calcSplitValue(quantity, orderSplitItemDO.getNum(), allNum));
            orderSplitItemDO.setChargeQuantity(orderSplitItemDO.getChargeQuantity());
        }
        // 校验入仓重量
        if (Objects.nonNull(createReqVO.getWeight())) {
            orderSplitItemDO.setWeight(isSpecsRecord ? createReqVO.getWeight() : splitWeight.add(createReqVO.getWeight()));
            if (Objects.equals(orderSplitItemDO.getNum(), allNum)) {
                BigDecimal weightDifference = orderSplitItemDO.getWeight().subtract(weight);
                if (weightDifference.compareTo(BigDecimal.ZERO) != 0) {
                    if (weightDifference.compareTo(BigDecimal.ZERO) > 0) {
                        throw exception(ORDER_SPLIT_ITEM_WEIGHT_MANY_EXCEPTION, weightDifference.setScale(2, RoundingMode.HALF_UP));
                    } else {
                        throw exception(ORDER_SPLIT_ITEM_WEIGHT_FEW_EXCEPTION, weightDifference.negate().setScale(2, RoundingMode.HALF_UP));
                    }
                }
            }
        } else {
            orderSplitItemDO.setWeight(calcSplitValue(weight, orderSplitItemDO.getNum(), allNum));
        }
        if (orderSplitItemDO.getWeight().compareTo(BigDecimal.ZERO) == 0) {
            throw exception(ORDER_SPLIT_ITEM_WEIGHT_ERROR, I18nMessage.getLang() == 0 ? orderSplitItemDO.getProdTitleZh() : orderSplitItemDO.getProdTitleEn());
        }
        // 校验入仓体积
        if (Objects.nonNull(createReqVO.getVolume())) {
            orderSplitItemDO.setVolume(isSpecsRecord ? createReqVO.getVolume() : splitVolume.add(createReqVO.getVolume()));
            if (Objects.equals(orderSplitItemDO.getNum(), allNum)) {
                BigDecimal volumeDifference = orderSplitItemDO.getVolume().subtract(volume);
                if (volumeDifference.compareTo(BigDecimal.ZERO) != 0) {
                    if (volumeDifference.compareTo(BigDecimal.ZERO) > 0) {
                        throw exception(ORDER_SPLIT_ITEM_VOLUME_MANY_EXCEPTION, volumeDifference.setScale(2, RoundingMode.HALF_UP));
                    } else {
                        throw exception(ORDER_SPLIT_ITEM_VOLUME_FEW_EXCEPTION, volumeDifference.negate().setScale(2, RoundingMode.HALF_UP));
                    }
                }
            }
        } else {
            orderSplitItemDO.setVolume(calcSplitValue(volume, orderSplitItemDO.getNum(), allNum));
        }
        if (orderSplitItemDO.getVolume().compareTo(BigDecimal.ZERO) == 0) {
            throw exception(ORDER_SPLIT_ITEM_VOLUME_ERROR, I18nMessage.getLang() == 0 ? orderSplitItemDO.getProdTitleZh() : orderSplitItemDO.getProdTitleEn());
        }
        // 校验收费重量
        if (Objects.nonNull(createReqVO.getChargeWeight())) {
            orderSplitItemDO.setChargeWeight(isSpecsRecord ? createReqVO.getChargeWeight() : splitChargeWeight.add(createReqVO.getChargeWeight()));
            if (Objects.equals(orderSplitItemDO.getNum(), allNum)) {
                BigDecimal chargeWeightDifference = orderSplitItemDO.getChargeWeight().subtract(chargeWeight);
                if (chargeWeightDifference.compareTo(BigDecimal.ZERO) != 0) {
                    if (chargeWeightDifference.compareTo(BigDecimal.ZERO) > 0) {
                        throw exception(ORDER_SPLIT_ITEM_CHARGE_WEIGHT_MANY_EXCEPTION, chargeWeightDifference.setScale(2, RoundingMode.HALF_UP));
                    } else {
                        throw exception(ORDER_SPLIT_ITEM_CHARGE_WEIGHT_FEW_EXCEPTION, chargeWeightDifference.negate().setScale(2, RoundingMode.HALF_UP));
                    }
                }
            }
        } else {
            orderSplitItemDO.setChargeWeight(calcSplitValue(chargeWeight, orderSplitItemDO.getNum(), allNum));
        }
        // 校验收费体积
        if (Objects.nonNull(createReqVO.getChargeVolume())) {
            orderSplitItemDO.setChargeVolume(isSpecsRecord ? createReqVO.getChargeVolume() : splitChargeVolume.add(createReqVO.getChargeVolume()));
            if (Objects.equals(orderSplitItemDO.getNum(), allNum)) {
                BigDecimal chargeVolumeDifference = orderSplitItemDO.getChargeVolume().subtract(chargeVolume);
                if (chargeVolumeDifference.compareTo(BigDecimal.ZERO) != 0) {
                    if (chargeVolumeDifference.compareTo(BigDecimal.ZERO) > 0) {
                        throw exception(ORDER_SPLIT_ITEM_CHARGE_VOLUME_MANY_EXCEPTION, chargeVolumeDifference.setScale(2, RoundingMode.HALF_UP));
                    } else {
                        throw exception(ORDER_SPLIT_ITEM_CHARGE_VOLUME_FEW_EXCEPTION, chargeVolumeDifference.negate().setScale(2, RoundingMode.HALF_UP));
                    }
                }
            }
        } else {
            orderSplitItemDO.setChargeVolume(calcSplitValue(chargeVolume, orderSplitItemDO.getNum(), allNum));
        }
        // 校验货值
        if (Objects.nonNull(createReqVO.getWorth())) {
            orderSplitItemDO.setWorth(isSpecsRecord ? createReqVO.getWorth() : splitWorth.add(createReqVO.getWorth()));
        }
        if (CollectionUtil.isNotEmpty(createReqVO.getSpecsRecordVOList())) {
            orderSplitItemDO.setSpecsRecord(JSONObject.toJSONString(createReqVO.getSpecsRecordVOList()));
        }
        orderSplitItemDO.setBoxGauge(boxGauge);
        orderSplitItemDO.setRemark(createReqVO.getRemark());
        if (TransportTypeShortEnum.SEA_CONTAINER.getValue().equals(orderSplitDO.getTransportId())
                || TransportTypeShortEnum.MARINE_CONTAINER.getValue().equals(orderSplitDO.getTransportId())) {
            // 空运拆单需要更新订单可能的新成交单价数据、收费模式、价格、货币、计量单位
            if (Objects.nonNull(createReqVO.getOneSeaFreight())) {
                orderSplitItemDO.setOneSeaFreight(createReqVO.getOneSeaFreight());
            }
            if (Objects.nonNull(createReqVO.getOneClearanceFreight())) {
                orderSplitItemDO.setOneClearanceFreight(createReqVO.getOneClearanceFreight());
            }
        }
        this.saveOrUpdate(orderSplitItemDO);

        if (createReqVO.getShipmentSplit()) {//master子order的item要减少,且要保持一致，因为每次拆单都是从主拆单拿出，所以只需要保持拆单数据与原主拆单项数据一致即可
            this.updateMasterSplitItem(quantityRequired, splitMaster.getId(), orderSplitMasterItemDO, orderSplitItemDO,
                    (orderSplitItemDO.getNum() - splitNum), (orderSplitItemDO.getQuantity() - splitQuantity),
                    orderSplitItemDO.getWeight().subtract(splitWeight),
                    orderSplitItemDO.getVolume().subtract(splitVolume),
                    orderSplitItemDO.getChargeWeight().subtract(splitChargeWeight),
                    orderSplitItemDO.getChargeVolume().subtract(splitChargeVolume),
                    orderSplitItemDO.getChargeQuantity().subtract(splitChargeQuantity));
            // 获取所有子拆单的货值
            BigDecimal sonSplitTotalWorth = splitItemMapper.getSonSplitTotalWorth(orderSplitDO.getParentOrderId());
            // 更新主拆单的货值
            this.updateMasterSplitItemWorth(orderSplitMasterItemDOList, totalWorth.subtract(sonSplitTotalWorth));
            // 在放入成功后，校验拆单项与原单的强一致性
            orderSplitCheckService.splitConsistencyCheck(sourceOrderItemDo, orderItemId, allNum, Objects.isNull(quantity) ? 0 : quantity, weight, volume, chargeWeight, chargeVolume, chargeQuantity);
        }
        if (orderSplitDO.getTransportId() == 3) {
            // 对该空运拆单品名进行实时计价
            splitOrderCalculation(orderDO, orderSplitDO);
        }
        // 返回
        return true;
    }

    private void splitOrderCalculation(OrderDO orderDO, OrderSplitDO orderSplitDO) {
        List<OrderSplitItemDO> orderSplitItemDOList = splitItemMapper.selectList(new LambdaQueryWrapper<OrderSplitItemDO>()
                .eq(OrderSplitItemDO::getOrderSplitId, orderSplitDO.getId()));
        List<ProdConditionParam> prodConditionParamList = orderSplitItemDOList.stream().map(it -> {
            OrderItemDO orderItemDO = orderItemMapper.selectById(it.getOrderItemId());
            ProdConditionParam param = new ProdConditionParam();
            param.setItemId(it.getId());
            param.setIsPriced(false);
            param.setProdId(it.getProdId());
            param.setProdTitleEn(it.getProdTitleEn());
            param.setProdTitleZh(it.getProdTitleZh());
            param.setProductType(it.getProdType());
            param.setBrandType(it.getFeeType());
            param.setBrand(orderItemDO.getBrand());
            param.setProdAttrIds(orderItemDO.getProdAttrIds());
            WarehouseInInfoVO inInfoVO = orderItemDO.getWarehouseInInfoVO();
            if (StringUtils.isNotBlank(inInfoVO.getUnits())) {
                // 逗号分割后去重转集合参数
                param.setPackages(Arrays.stream(inInfoVO.getUnits().split(StrUtil.COMMA)).distinct().collect(Collectors.toList()));
            } else {
                // 已入仓取入仓包装单位
                param.setPackaging(inInfoVO.getUnit());
            }
            param.setProdAttrIds(orderItemDO.getProdAttrIds());
            param.setBrandType(orderItemDO.getFeeType());
            param.setChargeWeight(it.getChargeWeight());
            param.setChargeVolume(it.getChargeVolume());
            param.setChargeQuantity(it.getChargeQuantity());

            return param;
        }).collect(Collectors.toList());
        prodConditionParamList = calculation.obtainProdLineOnePrice(prodConditionParamList, orderSplitDO.getOrderNo(),
                orderDO.getCustomsType(), orderDO.getCustomerId(), orderSplitDO.getTransportId(), orderDO.getLineId(), orderSplitDO.getChannelId(), true);
        for (ProdConditionParam param : prodConditionParamList) {
            orderSplitItemDOList = orderSplitItemDOList.stream().peek(it -> {
                if (Objects.equals(param.getItemId(), it.getId()) && !it.getSplitCustomPriceType()){
                    // 的非自定义价格的拆单项获取实时定价
                    it.setCharging(param.getCharging());
                    it.setOneSeaFreight(param.getOneFreight());
                    it.setSeaFreightVolume(param.getFreightVolume());
                    it.setSeaFreightCurrency(param.getFreightCurrency());
                    it.setOneClearanceFreight(param.getOneClearanceFee());
                    it.setClearanceFreightVolume(param.getClearanceFeeVolume());
                    it.setClearanceFreightCurrency(param.getClearanceFeeCurrency());
                }
            }).collect(Collectors.toList());
        }
        this.updateBatchById(orderSplitItemDOList);
    }


    /**
     * @param quantityRequired       数量是否必填
     * @param splitMasterId          主拆单ID
     * @param orderSplitMasterItemDO 主拆单项
     * @param orderSplitItemDO       变更的子拆单项
     * @param splitNum               变更箱数
     * @param splitQuantity          变更数量
     * @param splitWeight            变更重量
     * @param splitVolume            变更体积
     * @param splitChargeWeight      变更收费重量
     * @param splitChargeVolume      变更收费体积
     * @param splitChargeQuantity    变更收费数量
     */
    private void updateMasterSplitItem(boolean quantityRequired, Long splitMasterId, OrderSplitItemDO orderSplitMasterItemDO,
                                       OrderSplitItemDO orderSplitItemDO, int splitNum, int splitQuantity, BigDecimal splitWeight,
                                       BigDecimal splitVolume, BigDecimal splitChargeWeight, BigDecimal splitChargeVolume,
                                       BigDecimal splitChargeQuantity) {
        int num = orderSplitMasterItemDO.getNum() - splitNum;
        if (num < 0) {
            throw exception(ORDER_SPLIT_ITEM_NUM_FEW_EXCEPTION, -num);
        } else if (num == 0) {
            // 当整个订单项商品的数量被移除当前订单时, 需要查询当前主订单下是否还有订单项，否则不允许移除
            Long count = splitItemMapper.selectCount(new LambdaQueryWrapper<OrderSplitItemDO>().eq(OrderSplitItemDO::getOrderSplitId, splitMasterId));
            if (count <= 1) {
                throw exception(ORDER_SPLIT_MASTER_ORDER_ITEM_NOT_NULL);
            } else {
                // 当前主订单下不只有一个商品项时，可以将此商品项整体移到另一个子订单中，删除主订单下的当前订单商品项
                splitItemMapper.deleteById(orderSplitMasterItemDO.getId());
            }
        } else {
            String title = I18nMessage.getLang() == 0 ? orderSplitMasterItemDO.getProdTitleZh() : orderSplitMasterItemDO.getProdTitleEn();
            orderSplitMasterItemDO.setNum(num);
            orderSplitMasterItemDO.setQuantity(orderSplitMasterItemDO.getQuantity() - splitQuantity);
            if (quantityRequired) {
                if (Objects.isNull(orderSplitMasterItemDO.getQuantity()) || orderSplitMasterItemDO.getQuantity() <= 0) {
                    throw exception(CALCULATION_UNIT_QUANTITY_NOT_NULL);
                }
            }
            orderSplitMasterItemDO.setChargeQuantity(orderSplitMasterItemDO.getChargeQuantity().subtract(splitChargeQuantity));
            if (quantityRequired) {
                if (Objects.isNull(orderSplitMasterItemDO.getChargeQuantity()) || orderSplitMasterItemDO.getChargeQuantity().compareTo(BigDecimal.ZERO) <= 0) {
                    throw exception(CALCULATION_UNIT_QUANTITY_NOT_NULL);
                }
            }
            // 校验入仓重量
            orderSplitMasterItemDO.setWeight(orderSplitMasterItemDO.getWeight().subtract(splitWeight));
            if (orderSplitMasterItemDO.getWeight().compareTo(BigDecimal.ZERO) == 0) {
                throw exception(ORDER_SPLIT_ITEM_WEIGHT_ERROR, title);
            }
            if (orderSplitMasterItemDO.getWeight().compareTo(BigDecimal.ZERO) < 0) {
                throw exception(ORDER_SPLIT_ITEM_WEIGHT_FEW_EXCEPTION, orderSplitMasterItemDO.getWeight().negate().setScale(2, RoundingMode.HALF_UP));
            }
            // 校验入仓体积
            orderSplitMasterItemDO.setVolume(orderSplitMasterItemDO.getVolume().subtract(splitVolume));
            if (orderSplitMasterItemDO.getVolume().compareTo(BigDecimal.ZERO) == 0) {
                throw exception(ORDER_SPLIT_ITEM_VOLUME_ERROR, title);
            }
            if (orderSplitMasterItemDO.getVolume().compareTo(BigDecimal.ZERO) < 0) {
                throw exception(ORDER_SPLIT_ITEM_VOLUME_FEW_EXCEPTION, orderSplitMasterItemDO.getVolume().negate().setScale(2, RoundingMode.HALF_UP));
            }
            // 校验收费重量
            orderSplitMasterItemDO.setChargeWeight(orderSplitMasterItemDO.getChargeWeight().subtract(splitChargeWeight));
            if (orderSplitMasterItemDO.getChargeWeight().compareTo(BigDecimal.ZERO) == 0) {
                throw exception(ORDER_SPLIT_ITEM_CHARGE_WEIGHT_ERROR, title);
            }
            if (orderSplitMasterItemDO.getChargeWeight().compareTo(BigDecimal.ZERO) < 0) {
                throw exception(ORDER_SPLIT_ITEM_CHARGE_WEIGHT_FEW_EXCEPTION, orderSplitMasterItemDO.getChargeWeight().negate().setScale(2, RoundingMode.HALF_UP));
            }
            // 校验收费体积
            orderSplitMasterItemDO.setChargeVolume(orderSplitMasterItemDO.getChargeVolume().subtract(splitChargeVolume));
            if (orderSplitMasterItemDO.getChargeVolume().compareTo(BigDecimal.ZERO) == 0) {
                throw exception(ORDER_SPLIT_ITEM_CHARGE_VOLUME_ERROR, title);
            }
            if (orderSplitMasterItemDO.getChargeVolume().compareTo(BigDecimal.ZERO) < 0) {
                throw exception(ORDER_SPLIT_ITEM_CHARGE_VOLUME_FEW_EXCEPTION, orderSplitMasterItemDO.getChargeVolume().negate().setScale(2, RoundingMode.HALF_UP));
            }
            // 校验入仓记录值
            if (CollectionUtil.isNotEmpty(orderSplitMasterItemDO.getSpecsRecordVOList()) && CollectionUtil.isNotEmpty(orderSplitItemDO.getSpecsRecordVOList())) {
                List<OrderSpiltItemSpecsRecordVO> masterSpecsRecordVOList = new ArrayList<>();
                for (OrderSpiltItemSpecsRecordVO masterSpecsRecordVO : orderSplitMasterItemDO.getSpecsRecordVOList()) {
                    for (OrderSpiltItemSpecsRecordVO specsRecordVOSplit : orderSplitItemDO.getSpecsRecordVOList()) {
                        // 子拆单记录中可能有原单同一记录的多条数据
                        if (Objects.equals(masterSpecsRecordVO.getWarehouseInId(), specsRecordVOSplit.getWarehouseInId())) {
                            // 当主拆单的入仓记录箱数大于子拆单的入仓记录箱数时，说明主拆单该记录未拆完
                            masterSpecsRecordVO.setNum(masterSpecsRecordVO.getNum() - specsRecordVOSplit.getNum());
                            masterSpecsRecordVO.setQuantity((Objects.isNull(masterSpecsRecordVO.getQuantity()) ? 0 : masterSpecsRecordVO.getQuantity()) - specsRecordVOSplit.getQuantity());
                            masterSpecsRecordVO.setVolume(masterSpecsRecordVO.getVolume().subtract(specsRecordVOSplit.getVolume()));
                            masterSpecsRecordVO.setWeight(masterSpecsRecordVO.getWeight().subtract(specsRecordVOSplit.getWeight()));
                        }
                    }
                    masterSpecsRecordVOList.add(masterSpecsRecordVO);
                }
                // 删除拆完的记录
                masterSpecsRecordVOList = masterSpecsRecordVOList.stream().filter(masterSpecsRecord -> masterSpecsRecord.getNum() > 0).collect(Collectors.toList());
                orderSplitMasterItemDO.setSpecsRecord(JSONObject.toJSONString(masterSpecsRecordVOList));
            }
            splitItemMapper.updateById(orderSplitMasterItemDO);
        }
    }


    /**
     * 出货拆单主拆单整体货值更新
     *
     * @param orderSplitMasterItemDOList 所有主拆单项
     * @param masterSplitWorth           所有主拆单剩余货值
     */
    private void updateMasterSplitItemWorth(List<OrderSplitItemDO> orderSplitMasterItemDOList, BigDecimal masterSplitWorth) {
        for (OrderSplitItemDO splitItemDO : orderSplitMasterItemDOList) {
            if (masterSplitWorth.compareTo(splitItemDO.getWorth()) >= 0) {
                // 剩余货值大于等于该主拆单项货值，那么该主拆单项货值保存不变，剩余货值减去此拆单项货值
                masterSplitWorth = masterSplitWorth.subtract(splitItemDO.getWorth());
            } else {
                // 当剩余货值小于该主拆单项货值时，该拆单项的货值直接更新为剩余货值，并将剩余货值置为0
                splitItemDO.setWorth(masterSplitWorth);
                masterSplitWorth = BigDecimal.ZERO;
            }
        }
        splitItemMapper.updateBatch(orderSplitMasterItemDOList);
    }


    @Override
    public Boolean checkItemVolume(Integer freightVolume, Integer clearanceFreightVolume) {
        if (Objects.isNull(freightVolume) || freightVolume == 0) {
            throw exception(NOT_LOOK_CALCULATION_UNIT);
        }
        boolean flag = false;
        // 获取所有单位
        List<UnitDO> unitDOList = unitService.list();
        Map<Integer, UnitDO> unitDOMap = unitDOList.stream()
                .collect(Collectors.toMap(UnitDO::getId, Function.identity(), (key1, key2) -> key2));
        UnitDO freightUnitDO = unitDOMap.get(freightVolume);
        if (Objects.isNull(freightUnitDO)) {
            throw exception(NOT_LOOK_CALCULATION_UNIT);
        }
        if (freightUnitDO.getFuhao().equals("a")) {
            flag = true;
        }
        if (Objects.nonNull(clearanceFreightVolume) && clearanceFreightVolume > 0) {
            UnitDO clearanceFeeUnitDO = unitDOMap.get(clearanceFreightVolume);
            if (Objects.isNull(clearanceFeeUnitDO)) {
                throw exception(NOT_LOOK_CALCULATION_UNIT);
            }
            if (clearanceFeeUnitDO.getFuhao().equals("a")) {
                flag = true;
            }
        }
        return flag;
    }

    private BigDecimal calcSplitValue(BigDecimal allValue, Integer inNum, Integer allNum) {
        BigDecimal defaultValue = new BigDecimal("0.01");
        if (allValue == null) {
            return defaultValue;
        }
        BigDecimal totalValue = allValue.multiply(BigDecimal.valueOf(inNum));
        if (totalValue.compareTo(BigDecimal.ZERO) == 0) {
            return defaultValue;
        }
        BigDecimal divide = totalValue.divide(BigDecimal.valueOf(allNum), 2, RoundingMode.HALF_UP);
        return divide.compareTo(BigDecimal.ZERO) == 0 ? defaultValue : divide;
    }

    private Integer calcSplitValue(Integer allValue, Integer inNum, Integer allNum) {
        Integer defaultValue = 0;
        if (allValue == null || allValue == 0) {
            return defaultValue;
        }
        BigDecimal totalValue = BigDecimal.valueOf(allValue).multiply(BigDecimal.valueOf(inNum));
        if (totalValue.compareTo(BigDecimal.ZERO) == 0) {
            return defaultValue;
        }
        // 对数量的计算不能四舍五入
        return totalValue.divide(BigDecimal.valueOf(allNum), 0, RoundingMode.DOWN).intValue();
    }


    @Override
    public Boolean updateSplitItem(OrderSplitItemUpdateReqVO updateReqVO) {
        OrderSplitItemDO orderSplitItemDO = splitItemMapper.selectById(updateReqVO.getId());
        if (Objects.isNull(orderSplitItemDO)) {
            throw exception(ORDER_SPLIT_ITEM_NOT_EXISTS);
        }
        Long orderItemId = orderSplitItemDO.getOrderItemId();
        Long orderSplitId = orderSplitItemDO.getOrderSplitId();
        OrderSplitDO orderSplitDO = splitMapper.selectById(orderSplitId);
        if (orderSplitDO == null) {
            throw exception(ORDER_SPLIT_NOT_EXISTS);
        }
        if (updateReqVO.getShipmentSplit()) {
            if (orderSplitDO.getIsMaster()) {
                throw exception(MASTER_SPLIT_ITEM_NOT_UPDATE);
            }
        }

        OrderItemDO sourceOrderItemDo = orderItemMapper.selectById(orderItemId);
        if (sourceOrderItemDo == null) {
            throw exception(ORDER_ITEM_NOT_EXISTS);
        }
        // 判断当前订单是否有审批业务，有则不能进行拆单修改业务
        OrderDO orderDO = orderQueryService.getOrderById(sourceOrderItemDo.getOrderId());
        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);
        }
        WarehouseInInfoVO warehouseInInfoVO = sourceOrderItemDo.getWarehouseInInfoVO();
        if (Objects.isNull(warehouseInInfoVO)) {
            throw exception(SPLIT_ORDER_WAREHOUSE_IN_DATA_EXCEPTION);
        }
        OrderSplitDO splitMaster = null;
        OrderSplitItemDO orderSplitMasterItemDO = null;
        List<OrderSplitItemDO> orderSplitMasterItemDOList = null;
        if (updateReqVO.getShipmentSplit()) {
            splitMaster = splitMapper.selectOne(new LambdaQueryWrapperX<OrderSplitDO>()
                    .eq(OrderSplitDO::getParentOrderId, orderSplitDO.getParentOrderId())
                    .eq(OrderSplitDO::getUsed, false)
                    .eq(OrderSplitDO::getIsMaster, true));
            if (Objects.isNull(splitMaster)) {
                throw exception(ORDER_SPLIT_NOT_EXISTS);
            }
            orderSplitMasterItemDOList = splitItemMapper.selectList(new LambdaQueryWrapperX<OrderSplitItemDO>()
                    .eq(OrderSplitItemDO::getOrderSplitId, splitMaster.getId())
                    .eq(OrderSplitItemDO::getUsed, Boolean.FALSE));
            if (CollectionUtil.isEmpty(orderSplitMasterItemDOList)) {
                throw exception(ORDER_SPLIT_NOT_EXISTS);
            }
            orderSplitMasterItemDO = orderSplitMasterItemDOList.stream().filter(item -> Objects.equals(item.getOrderItemId(), orderItemId)).findFirst().orElse(null);
            if (Objects.isNull(orderSplitMasterItemDO)) {
                // 主拆单商品【{}】已被全部拆出,对此拆单商品数据不能再做修改操作
                throw exception(MASTER_SPLIT_ITEM_NOT_EXISTS, I18nMessage.getLang() == 0 ? orderSplitItemDO.getProdTitleZh() : orderSplitItemDO.getProdTitleEn());
            }
        }
        boolean quantityRequired = warehouseService.quantityRequired(orderDO.getLineId());
        //原单箱数、数量
        int allNum = Objects.isNull(warehouseInInfoVO.getCartonsNum()) ? 0 : warehouseInInfoVO.getCartonsNum();
        int quantity = Objects.isNull(warehouseInInfoVO.getQuantityAll()) ? 0 : warehouseInInfoVO.getQuantityAll();
        if (updateReqVO.getShipmentSplit()) {
            if (allNum <= 0) {
                throw exception(ORDER_SPLIT_ITEM_NOT_REMOVABLE_NUM);
            }
        }
        // TODO 货值需要匹配整个订单的
        CostVO costVO = JSONObject.parseObject(orderDO.getCost(), CostVO.class);
        BigDecimal totalWorth = costVO.getTotalWorth();
        // 原单入仓属性
        BigDecimal weight = warehouseInInfoVO.getWeight();
        BigDecimal volume = warehouseInInfoVO.getVolume();
        String boxGauge = warehouseInInfoVO.getBoxGauge();
        // 原单收费属性
        BigDecimal chargeWeight = sourceOrderItemDo.getChargeWeight();
        BigDecimal chargeVolume = sourceOrderItemDo.getChargeVolume();
        BigDecimal chargeQuantity = sourceOrderItemDo.getChargeQuantity();

        if (CollectionUtil.isNotEmpty(updateReqVO.getSpecsRecordVOList())) {
            boxGauge = updateReqVO.getSpecsRecordVOList().stream().map(OrderSpiltItemSpecsRecordVO::getBoxGauge).findFirst().get();
            updateReqVO.setNum(updateReqVO.getSpecsRecordVOList().stream().map(OrderSpiltItemSpecsRecordVO::getNum).filter(Objects::nonNull).mapToInt(Integer::intValue).sum());
            updateReqVO.setQuantity(updateReqVO.getSpecsRecordVOList().stream().map(OrderSpiltItemSpecsRecordVO::getQuantity).filter(Objects::nonNull).mapToInt(Integer::intValue).sum());
            updateReqVO.setVolume(updateReqVO.getSpecsRecordVOList().stream().map(OrderSpiltItemSpecsRecordVO::getVolume).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
            updateReqVO.setWeight(updateReqVO.getSpecsRecordVOList().stream().map(OrderSpiltItemSpecsRecordVO::getWeight).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
            updateReqVO.setChargeVolume(updateReqVO.getSpecsRecordVOList().stream().map(OrderSpiltItemSpecsRecordVO::getChargeVolume).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
            updateReqVO.setChargeWeight(updateReqVO.getSpecsRecordVOList().stream().map(OrderSpiltItemSpecsRecordVO::getChargeWeight).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
        }
        if (updateReqVO.getShipmentSplit()) {
            //master子order的item要减少,且要保持一致，因为每次拆单都是从主拆单拿出，所以只需要保持拆单数据与原主拆单项数据一致即可
            this.updateMasterSplitItem(quantityRequired, splitMaster.getId(), orderSplitMasterItemDO, orderSplitItemDO,
                    ((Objects.isNull(updateReqVO.getNum()) ? 0 : updateReqVO.getNum()) - orderSplitItemDO.getNum()),
                    ((Objects.isNull(updateReqVO.getQuantity()) ? 0 : updateReqVO.getQuantity()) - orderSplitItemDO.getQuantity()),
                    (Objects.isNull(updateReqVO.getWeight()) ? BigDecimal.ZERO : updateReqVO.getWeight()).subtract(orderSplitItemDO.getWeight()),
                    (Objects.isNull(updateReqVO.getVolume()) ? BigDecimal.ZERO : updateReqVO.getVolume()).subtract(orderSplitItemDO.getVolume()),
                    (Objects.isNull(updateReqVO.getChargeWeight()) ? BigDecimal.ZERO : updateReqVO.getChargeWeight()).subtract(orderSplitItemDO.getChargeWeight()),
                    (Objects.isNull(updateReqVO.getChargeVolume()) ? BigDecimal.ZERO : updateReqVO.getChargeVolume()).subtract(orderSplitItemDO.getChargeVolume()),
                    (Objects.isNull(updateReqVO.getQuantity()) ? BigDecimal.ZERO : new BigDecimal(updateReqVO.getQuantity())).subtract(orderSplitItemDO.getChargeQuantity()));
            // 获取所有子拆单的货值
            BigDecimal sonSplitTotalWorth = splitItemMapper.getSonSplitTotalWorth(orderSplitDO.getParentOrderId());
            // 更新主拆单的货值
            this.updateMasterSplitItemWorth(orderSplitMasterItemDOList, totalWorth.subtract(sonSplitTotalWorth));
        }
        orderSplitItemDO.setBoxGauge(boxGauge);
        if (TransportTypeShortEnum.AIR_FREIGHT_LINE.getValue().equals(orderSplitDO.getTransportId())
                || TransportTypeShortEnum.AIR_SEA_COMBINED_TRANSPORT.getValue().equals(orderSplitDO.getTransportId())) {
            // 空运拆单需要更新订单可能的新成交单价数据、收费模式、价格、货币、计量单位
            if (Objects.nonNull(updateReqVO.getOneSeaFreight()) && updateReqVO.getOneSeaFreight().compareTo(BigDecimal.ZERO) > 0) {
                orderSplitItemDO.setSplitCustomPriceType(true);
                orderSplitItemDO.setOneSeaFreight(updateReqVO.getOneSeaFreight());

            }
            if (orderSplitItemDO.getCharging() == 0) {
                if (Objects.nonNull(updateReqVO.getOneClearanceFreight()) && updateReqVO.getOneClearanceFreight().compareTo(BigDecimal.ZERO) > 0) {
                    orderSplitItemDO.setSplitCustomPriceType(true);
                    orderSplitItemDO.setOneClearanceFreight(updateReqVO.getOneClearanceFreight());
                }
            }
        }
        // 更新当前子拆单项数据,此业务因为是直接更新传参值到数据库, 需要在计算更新完主拆单项后才进行
        if (Objects.nonNull(updateReqVO.getNum()) && updateReqVO.getNum() > 0) {
            orderSplitItemDO.setNum(updateReqVO.getNum());
        }
        if (Objects.nonNull(updateReqVO.getQuantity()) && updateReqVO.getQuantity() > 0) {
            orderSplitItemDO.setQuantity(updateReqVO.getQuantity());
            orderSplitItemDO.setChargeQuantity(new BigDecimal(updateReqVO.getQuantity()));
        }
        if (Objects.nonNull(updateReqVO.getWeight()) && updateReqVO.getWeight().compareTo(BigDecimal.ZERO) > 0) {
            orderSplitItemDO.setWeight(updateReqVO.getWeight());
        }
        if (Objects.nonNull(updateReqVO.getVolume()) && updateReqVO.getVolume().compareTo(BigDecimal.ZERO) > 0) {
            orderSplitItemDO.setVolume(updateReqVO.getVolume());
        }
        if (Objects.nonNull(updateReqVO.getWorth()) && updateReqVO.getWorth().compareTo(BigDecimal.ZERO) > 0) {
            orderSplitItemDO.setWorth(updateReqVO.getWorth());
        }
        if (Objects.nonNull(updateReqVO.getChargeWeight()) && updateReqVO.getChargeWeight().compareTo(BigDecimal.ZERO) > 0) {
            orderSplitItemDO.setChargeWeight(updateReqVO.getChargeWeight());
        }
        if (Objects.nonNull(updateReqVO.getChargeVolume()) && updateReqVO.getChargeVolume().compareTo(BigDecimal.ZERO) > 0) {
            orderSplitItemDO.setChargeVolume(updateReqVO.getChargeVolume());
        }
        if (CollectionUtil.isNotEmpty(updateReqVO.getSpecsRecordVOList())) {
            orderSplitItemDO.setSpecsRecord(JSONObject.toJSONString(updateReqVO.getSpecsRecordVOList()));
        }
        orderSplitItemDO.setBoxGauge(boxGauge);
        if (quantityRequired) {
            if (Objects.isNull(orderSplitItemDO.getQuantity()) || orderSplitItemDO.getQuantity() == 0 || orderSplitItemDO.getQuantity() < 0) {
                throw exception(CALCULATION_UNIT_QUANTITY_NOT_NULL);
            }
        }
        splitItemMapper.updateById(orderSplitItemDO);
        // 在更新成功后，校验拆单项与原单的强一致性
//        this.splitConsistencyCheck(orderItemId, allNum, quantity, weight, volume, worth, chargeWeight, chargeVolume, chargeQuantity);
        // 返回
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteSplitItem(Long id, Boolean shipmentSplit) {
        // 校验存在
        OrderSplitItemDO waitDeleteItem = splitItemMapper.selectById(id);
        if (waitDeleteItem == null) {
            throw exception(ORDER_SPLIT_ITEM_NOT_EXISTS);
        }

        Long orderItemId = waitDeleteItem.getOrderItemId();
        Long orderSplitId = waitDeleteItem.getOrderSplitId();


        OrderSplitDO orderSplitDO = splitMapper.selectById(orderSplitId);
        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());
        }
        // 删除移除的拆单项
        splitItemMapper.deleteById(id);
        if (shipmentSplit) {
            //master子order的item要增加
            OrderSplitDO splitMaster = splitMapper.selectOne(new LambdaQueryWrapperX<OrderSplitDO>()
                    .eq(OrderSplitDO::getParentOrderId, orderSplitDO.getParentOrderId())
                    .eq(OrderSplitDO::getUsed, false)
                    .eq(OrderSplitDO::getIsMaster, true));
            if (splitMaster != null) {
                OrderSplitItemDO masterItem = splitItemMapper.selectOne(new LambdaQueryWrapperX<OrderSplitItemDO>()
                        .eq(OrderSplitItemDO::getOrderSplitId, splitMaster.getId())
                        .eq(OrderSplitItemDO::getUsed, false)
                        .eq(OrderSplitItemDO::getOrderItemId, orderItemId));
                if (masterItem != null) {
                    masterItem.setNum(masterItem.getNum() + waitDeleteItem.getNum());
                    masterItem.setQuantity(masterItem.getQuantity() + waitDeleteItem.getQuantity());
                    masterItem.setWeight(masterItem.getWeight().add(waitDeleteItem.getWeight()));
                    masterItem.setVolume(masterItem.getVolume().add(waitDeleteItem.getVolume()));
                    masterItem.setWorth(masterItem.getWorth().add(waitDeleteItem.getWorth()));
                    masterItem.setChargeQuantity(masterItem.getChargeQuantity().add(waitDeleteItem.getChargeQuantity()));
                    masterItem.setChargeWeight(masterItem.getChargeWeight().add(waitDeleteItem.getChargeWeight()));
                    masterItem.setChargeVolume(masterItem.getChargeVolume().add(waitDeleteItem.getChargeVolume()));
                    splitItemMapper.updateById(masterItem);
                    // 更新主拆单项后删除移除的拆单项
                    splitItemMapper.deleteById(id);
                } else {
                    // 当删除的某个子拆单拆单项在主拆单中不存在时，则整体放回主拆单中
                    // 将需要删除的子拆单项变更到主拆单下
                    waitDeleteItem.setOrderSplitId(splitMaster.getId());
                    splitItemMapper.updateById(waitDeleteItem);
                }
            }
        }

    }

    private void validateSplitItemExists(Long id) {
        if (splitItemMapper.selectById(id) == null) {
            throw exception(ORDER_SPLIT_ITEM_NOT_EXISTS);
        }
    }

    @Override
    public OrderSplitItemDO getSplitItem(Long id) {
        return splitItemMapper.selectById(id);
    }

    @Override
    public List<OrderSplitItemDO> getSplitItemList(Collection<Long> ids) {
        return splitItemMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<OrderSplitItemDO> getSplitItemPage(OrderSplitItemQueryVO query, PageVO page) {
        return splitItemMapper.selectPage(page, query);
    }

    @Override
    public List<OrderSplitItemDO> getSplitItemList(OrderSplitItemQueryVO query) {
        return splitItemMapper.selectList(query);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean batchCreate(OrderSplitItemBatchCreateReqVO createReqVO) {
        List<OrderSplitItemCreateReqVO> itemList = createReqVO.getSplitItemList();
        for (OrderSplitItemCreateReqVO reqVO : itemList) {
            createSplitItem(reqVO);
        }
        return true;
    }
}
