拆分场景分析:多仓库库存拆分、多供应商拆分、预售与现货拆分、跨境与国内拆分

订单拆分,说白了就是「一个订单怎么分给多个地方发货」。

我做了这么多年电商系统,发现很多团队一上来就写拆分逻辑,结果上线就崩。为什么?因为场景没想清楚。今天咱们就把四个最常见的拆分场景掰开揉碎讲明白。

1. 多仓库库存拆分

这是最基础的拆分场景。用户下单买了5件商品,但A仓只有3件,B仓有2件。怎么办?拆!

核心逻辑:按库存可用量,把订单行拆到不同仓库。

我在项目中遇到过一个问题:库存数据是实时变动的,拆分时查到的库存,执行时可能已经被别的订单占用了。所以一定要加「预占库存」的步骤。

关键点:拆分前先锁定库存,避免超卖。

举个例子:

// 伪代码:多仓库库存拆分
function splitByWarehouse(order, warehouseStockMap) {
    let splits = [];
    for (let item of order.items) {
        let remainingQty = item.qty;
        for (let [warehouse, stock] of Object.entries(warehouseStockMap)) {
            if (remainingQty <= 0) break;
            let allocateQty = Math.min(remainingQty, stock.available);
            if (allocateQty > 0) {
                splits.push({
                    warehouse: warehouse,
                    sku: item.sku,
                    qty: allocateQty
                });
                remainingQty -= allocateQty;
            }
        }
        if (remainingQty > 0) {
            // 库存不足,走缺货处理
            throw new Error('库存不足');
        }
    }
    return splits;
}

我的习惯:拆分时不要只按仓库维度,还要考虑「物流时效」。比如A仓虽然库存多,但距离用户远,运费高。我一般会加一个「仓库优先级」配置,优先拆给离用户近的仓库。

2. 多供应商拆分

这个场景在平台型电商里特别常见。一个订单里,商品A是京东自营的,商品B是第三方卖家A的,商品C是第三方卖家B的。每个供应商各自发货。

嗯,这里要注意:供应商拆分和仓库拆分是两回事。供应商拆分是按「货主」维度切分,仓库拆分是按「物理位置」切分。

核心逻辑:按供应商ID分组,每个供应商生成一个子订单。

我曾经踩过一个坑:供应商A和供应商B都卖同一款商品,但价格不同。用户下单时选了供应商A的商品,但拆分时系统把商品分给了供应商B。结果用户投诉说「我明明买的A家的,怎么发来的是B家的?」

避坑指南:多供应商拆分时,必须保留用户选择的供应商信息。不能因为库存充足就随意切换供应商。

拆分后的数据结构大概是这样:

子订单ID 供应商ID 商品SKU 数量 金额
SO-001 VENDOR_A SKU-1001 2 200.00
SO-002 VENDOR_B SKU-1002 1 150.00

3. 预售与现货拆分

这个场景在双11、618大促时特别常见。用户一个订单里,既有预售商品(付定金,等尾款),又有现货商品(直接发货)。

你想想看,如果系统不拆分,那现货商品也得等预售商品一起发货。用户肯定骂娘:「我买的现货怎么不给我发?」

核心逻辑:按「发货时间」维度拆分。预售商品走预售流程,现货商品立即发货。

我建议这样设计:

  1. 订单创建时,标记每个商品行的「发货类型」:预售 or 现货
  2. 拆分时,按发货类型分组
  3. 预售子订单进入「等待尾款」状态,现货子订单进入「待发货」状态

关键点:预售和现货拆分后,运费怎么算?我一般会按子订单独立计算运费,而不是按原订单总金额算。否则用户会觉得「我付了两次运费」。

举个例子:

// 预售与现货拆分逻辑
function splitPreSaleAndSpot(order) {
    let preSaleItems = [];
    let spotItems = [];
    
    for (let item of order.items) {
        if (item.isPreSale) {
            preSaleItems.push(item);
        } else {
            spotItems.push(item);
        }
    }
    
    let subOrders = [];
    if (preSaleItems.length > 0) {
        subOrders.push({
            type: 'PRE_SALE',
            items: preSaleItems,
            status: 'WAITING_PAYMENT'
        });
    }
    if (spotItems.length > 0) {
        subOrders.push({
            type: 'SPOT',
            items: spotItems,
            status: 'PENDING_SHIP'
        });
    }
    return subOrders;
}

4. 跨境与国内拆分

这个场景相对复杂。跨境商品涉及海关清关、税费计算、国际物流,和国内商品完全是两套流程。

我记得有一次,用户买了一件国内现货和一件跨境直邮商品。系统没拆分,结果国内商品跟着跨境商品走了国际物流,用户等了两周才收到国内商品。投诉电话打爆了。

核心逻辑:按「物流模式」维度拆分。国内走国内物流,跨境走跨境物流。

拆分时还要考虑:

  • 税费:跨境商品需要计算关税、增值税,国内商品不需要
  • 清关信息:跨境商品需要用户提供身份证信息
  • 物流时效:跨境物流通常7-15天,国内物流1-3天

避坑指南:跨境和国内拆分后,支付环节也要分开。跨境商品可能需要单独支付税费,不能和国内商品合并支付。否则海关那边过不去。

我一般会这样设计拆分规则:

商品类型 物流模式 拆分策略 备注
国内现货 国内快递 按仓库拆分 优先就近发货
跨境直邮 国际快递 按供应商拆分 需要清关信息
跨境保税 保税仓发货 按保税仓拆分 需要身份证信息

核心知识体系

下面这张图,是我总结的四种拆分场景的核心逻辑。你看一眼就能明白它们之间的关系。

订单拆分场景核心逻辑 原始订单 多仓库库存拆分 按库存可用量切分 多供应商拆分 按供应商ID分组 预售与现货拆分 按发货时间切分 跨境与国内拆分 按物流模式切分 多个子订单 四种拆分场景可能叠加出现 例如:跨境商品同时涉及多仓库和多供应商 💡 实际项目中,建议先按「物流模式」拆分,再按「供应商」拆分,最后按「仓库」拆分

这四种场景在实际项目中往往是叠加出现的。比如一个跨境商品,可能同时涉及多仓库和多供应商。我的建议是:先按物流模式拆,再按供应商拆,最后按仓库拆。这个顺序能最大程度减少拆分后的合并成本。

我的经验:拆分逻辑不要写死。我一般会设计一个「拆分规则引擎」,把拆分策略做成可配置的。这样业务变了,改配置就行,不用改代码。

好了,这四种场景你理解了吗?其实核心就一句话:找到那个「必须分开」的维度,然后按它切分。


公众号:蓝海资料掘金营,微信deep3321