拆分场景分析:多仓库库存拆分、多供应商拆分、预售与现货拆分、跨境与国内拆分
订单拆分,说白了就是「一个订单怎么分给多个地方发货」。
我做了这么多年电商系统,发现很多团队一上来就写拆分逻辑,结果上线就崩。为什么?因为场景没想清楚。今天咱们就把四个最常见的拆分场景掰开揉碎讲明白。
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大促时特别常见。用户一个订单里,既有预售商品(付定金,等尾款),又有现货商品(直接发货)。
你想想看,如果系统不拆分,那现货商品也得等预售商品一起发货。用户肯定骂娘:「我买的现货怎么不给我发?」
核心逻辑:按「发货时间」维度拆分。预售商品走预售流程,现货商品立即发货。
我建议这样设计:
- 订单创建时,标记每个商品行的「发货类型」:预售 or 现货
- 拆分时,按发货类型分组
- 预售子订单进入「等待尾款」状态,现货子订单进入「待发货」状态
关键点:预售和现货拆分后,运费怎么算?我一般会按子订单独立计算运费,而不是按原订单总金额算。否则用户会觉得「我付了两次运费」。
举个例子:
// 预售与现货拆分逻辑
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天
避坑指南:跨境和国内拆分后,支付环节也要分开。跨境商品可能需要单独支付税费,不能和国内商品合并支付。否则海关那边过不去。
我一般会这样设计拆分规则:
| 商品类型 | 物流模式 | 拆分策略 | 备注 |
|---|---|---|---|
| 国内现货 | 国内快递 | 按仓库拆分 | 优先就近发货 |
| 跨境直邮 | 国际快递 | 按供应商拆分 | 需要清关信息 |
| 跨境保税 | 保税仓发货 | 按保税仓拆分 | 需要身份证信息 |
核心知识体系
下面这张图,是我总结的四种拆分场景的核心逻辑。你看一眼就能明白它们之间的关系。
这四种场景在实际项目中往往是叠加出现的。比如一个跨境商品,可能同时涉及多仓库和多供应商。我的建议是:先按物流模式拆,再按供应商拆,最后按仓库拆。这个顺序能最大程度减少拆分后的合并成本。
我的经验:拆分逻辑不要写死。我一般会设计一个「拆分规则引擎」,把拆分策略做成可配置的。这样业务变了,改配置就行,不用改代码。
好了,这四种场景你理解了吗?其实核心就一句话:找到那个「必须分开」的维度,然后按它切分。
公众号:蓝海资料掘金营,微信deep3321