我在给一家年GMV超5亿的母婴电商企业做供应链诊断时,发现一个让人后背发凉的现象:ERP系统里显示的“可用库存”是3200件,运营团队据此策划了一场满减活动,活动上线2小时就卖了2800单。但仓库实际能发出的货只有1800件,剩下的1400单凭空消失了。当天晚上,客服团队被退款和差评淹没,补货计划被全部打乱,供应商被紧急催单,但补的货7天后才到,而那批“可用库存”在系统里早已归零,却在另一个报表模块里显示还有1400件被“锁定”。这不是偶然,这是库存口径不统一的标准症状。
核心结论很清楚:大多数电商企业的库存断货与积压,根本原因是系统内部对“可用”“在途”“锁定”三类库存的判断规则没有达成一致,导致自动补货算法、促销决策、财务核销全部跑偏。 本文将从实战视角,拆解这三个口径的本质、常见误区,以及如何用一套可落地的计算规则把它们统一起来。
那家母婴企业使用的是某知名电商ERP,库存管理模块默认的逻辑很简单:可用库存 = 总入库 – 总出库。听起来没毛病,但问题出在“锁定”这个中间态。
活动前一周,采购部下了两批在途订单:一批是A供应商的5000件纸尿裤,预计3天后到仓;另一批是B供应商的3000件湿巾,预计5天后到仓。仓管员在系统里把这两批都录入了“在途库存”。同时,运营部为即将到来的大促做了预售活动,有800个订单已经生成了预占库存(锁定)。此外,还有一批200件的退货正在质检区,系统标记为“退货锁定”。
活动当天,运营打开ERP看板:可用库存 = 总库存3200(物理实有) – 0(锁定?),显示3200。实际上,系统“锁定”字段只包含了那些被“正式出库单”占用的库存,而预售占用的800件和退货锁定的200件并没有被纳入锁定计算。那部分库存被当成了“可用”。结果就是,3200件物理库存里,有1000件已经被隐性占用,真正可卖的只有2200件。但系统反馈的是3200,运营按3200做了活动。
活动开始2小时,真实成交2800单。系统自动扣减后,可用库存变为400。但仓库捡货时发现,有800个预售订单的商品已经被预售占了,却因为系统口径问题,这些商品被再次售卖。最后实际能发出的只有1800单,剩余1000单不得不退款。
这次事故的直接损失:客诉成本2.7万元,额外加急物流成本1.2万元,品牌口碑损伤更是难以计算。 但最核心的问题不在于运营决策失误,而在于ERP的库存口径定义有漏洞,它没有把全部锁定类型减掉。

从技术层面看,库存口径混乱的根源在于“时间差”和“状态域划分不清晰”。
时间差产生的原因: 一个订单从“加入购物车”到“支付完成”再到“仓库发货”,中间有多个时间节点。购物车占用库存、未支付订单占用库存、已支付订单占用库存、出库单占用库存、快递签收冲减库存,每个节点触发不同的库存动作。如果系统没有在这些节点上统一维护一个“库存状态域”,就会导致不同模块对同一批次库存的判断不一致。
状态域划分不清晰: 很多电商ERP在设计初期只用了“总库存”和“锁定库存”两个字段,但“锁定”这个词过于笼统。它至少应该涵盖:
当系统只用“锁定库存=已支付订单出库扣减”的逻辑时,其他类型的占用就会变成“隐形库存”,导致可用库存虚高。这就是库存三叉戟的根源:三类库存(可用、在途、锁定)的定义域在系统底层就没有对齐,业务层自然无法一致。
大多数运营人员理解的“可用库存”就是“仓库里能卖的货”。但在系统层面,可用库存必须是一个经过全面排除后的结果。
核心公式(通用结构化表达):
系统可用库存 = 物理实有库存 – 全部不可售占用量
全部不可售占用量 = 订单锁定(未支付) + 订单锁定(已支付未出库) + 调拨锁定(调出方) + 退货锁定(质检中) + 其他锁定(赠品预留、内部领用等)
很多ERP的“库存查询”页面只扣除了一部分锁定,这是最大的误区。正确做法是:每次计算可用库存时,必须遍历所有消耗库存但尚未完成最终出库的环节。
| 锁定类型 | 狭义处理(仅扣已支付) | 广义处理(全部扣减) | 风险 |
|---|---|---|---|
| 未支付订单 | 不扣减 | 扣减(30分钟释放) | 若不计入,超卖风险高 |
| 已支付未发货 | 扣减 | 扣减 | 正常 |
| 内部调拨中 | 不扣减 | 扣减(调出方) | 若不扣减,调出方库存虚高 |
| 退货质检 | 不扣减 | 扣减 | 若不扣减,库存虚高且次品可能流出 |
| 赠品预留 | 不扣减 | 扣减 | 促销时可用库存虚高 |
专业判断: 我见过不少企业因为“未支付订单不扣库存”的设计,导致大促期间超卖率飙升。标准做法应该是:未支付订单一旦生成,立即锁库,并设置TTL(生存时间),超时自动释放回可用池。这个逻辑必须在ERP底层写死,不能依赖人工。
在途库存是采购已下单、供应商已发货但尚未入仓的库存。它本质上是“预期供应”,但能否作为“可用库存”来计算,取决于它的到达时间与需求时间的关系。
常见误区: 有些ERP把在途库存直接加在可用库存旁边,运营一看“总可用(含在途)”数字很大,就敢做大促。但实际上,如果这批发货延误,就会直接断货。
正确决策逻辑:
在途部分是否算入可用 = f(预计到货时间, 当前库存消耗速率, 安全库存周期)
如果 (预计到货时间 – 当前时间) ≤ (安全库存天数 / 2) 且 供应商历史准点率 ≥ 90%:
算入可用(但需标记为“可预支”)
否则:
不算入可用,仅作为计划参考。
这里的关键变量是供应商置信度。我一般建议企业建立供应商到货率档案。对于新供应商或历史准点率低的供应商,在途库存无论多久都只作展示,不纳入任何自动补货计算。
| 处理方式 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| 全部不算可用 | 供应不稳定、运输风险高 | 绝对安全,不会超卖 | 可能低估库存,过度补货导致积压 |
| 全部算入可用 | 供应商稳定、运输可控 | 最大化利用预期库存,减少补货频次 | 一旦延误,立即断货风险高 |
| 按置信度部分算入 | 大部分企业通用 | 平衡风险和效率 | 需要维护供应商准时率数据,稍复杂 |
我的建议: 先按保守模式(全部不算)跑一个月,观察实际到货时间和误差,再逐步切换到置信度模式。至少留出一个完整补货周期的观察。

锁定库存是库存管理的“暗物质”,它占着位置,但不出现在常规报表里。很多企业根本不知道自己到底有多少库存被锁定、锁在哪里、锁了多久。
锁定库存必须细分:
专业判断: 我发现很多企业的ERP只提供了“释放锁定”的按钮,但没有详细的锁定明细报表。这就像只看到银行账户余额,但看不到每笔冻结资金的状态。一个健康的库存系统,必须每天出具《锁定库存分布表》:
锁定类型 数量 平均锁定时长 超时时长占比
订单锁定 1245 18分钟 3%
调拨锁定 340 6小时 12%
退货锁定 89 4小时 5%
其他 57 8小时 20%
当“其他锁定”或“超时占比”过高时,就是口径出现问题或流程淤积的信号。锁定库存不能只有一个总数,必须有明细、有时效、有告警。

库存口径统一的根基在数据模型。我推荐采用“多状态域”的设计,而不是用单一字段存储状态。
反例(常见错误设计):
CREATE TABLE inventory (
sku_id VARCHAR(32),
warehouse_id VARCHAR(16),
total_quantity INT,
locked_quantity INT,
available_quantity INT
);
这种设计的问题是:locked_quantity 无法细分为不同类型,可用库存需要应用层去减,而且容易遗漏某些锁定。实际使用中,工程师可能只减了部分订单锁定。
推荐设计(基于状态域):
CREATE TABLE inventory_state (
sku_id VARCHAR(32),
warehouse_id VARCHAR(16),
state_realm VARCHAR(32), — 'available', 'in_transit', 'locked'
state_detail VARCHAR(32), — 细分:'order_unpaid', 'order_paid', 'transfer_out', 'return_qc', 'prepay'
quantity INT,
expire_at DATETIME, — 锁定过期时间(用于自动释放)
created_at DATETIME,
PRIMARY KEY (sku_id, warehouse_id, state_realm, state_detail)
);
这样,可用库存 = 查询 state_realm='available' 的总和;在途入库后,从 in_transit 转为 available;锁定状态由 state_detail 细分。 每种状态单独记录,互不干扰。应用层只需要聚合查询,不需要做复杂的减法逻辑。
这种设计虽然增加了记录数,但完全避免了口径歧义。任何一次库存变化都能精确追溯到来源。在数据库层面可以保证数据一致性,比应用层做加减法稳定得多。
即便数据库设计完美,数据同步环节也可能引入口径误差。常见问题有:
| 场景 | 同步方式 | 频率 | 冲突策略 |
|---|---|---|---|
| 订单锁定/解锁 | 实时(API触发) | 每次操作 | 悲观锁(数据库行锁) |
| 在途库存更新 | 定时批量 | 每15分钟 | 增量对比,差异告警 |
| 退货质检状态变更 | 事件触发 | 每次状态变化 | 乐观锁(版本号) |
| 库存全量对账 | 定时批量 | 每日凌晨 | 以WMS为准,差异自动生成调账单 |
经验: 我遇到过的严重超卖事故,几乎都发生在“批量同步”的窗口期内。所以我的原则是:涉及真实可售数量变化的操作(订单锁定、库存扣减),必须走实时同步,不能依赖定时任务。 对于在途和统计类数据,才可以用批量方式。
很多企业设置专人每天看库存报表,但人的反应速度永远跟不上系统变化。我们需要一套量化的指标体系,自动告警当口径出现异常时。
IF (可用库存准确率 IF (某锁定类型时长 > 其设定超时阈值的150% for 3次) THEN 通知对应流程负责人
IF (在途逾期率 > 10% for 1 week) THEN 自动调低该供应商在途置信度,减少自动补货
这些规则最好内嵌在BI工具或ERP的告警模块中。我见过有些企业用零代码BI平台(如简道云/九数云)搭建库存健康仪表盘,把规则写在数据集中,每天自动发送告警到钉钉或飞书。核心是让系统自动捕捉异常,而不是等人发现问题。


统一库存口径并不是一刀切的事。不同发展阶段的企业,投入和侧重点不同。

电商库存的可用、在途、锁定,本质是同一批货物在不同业务阶段的不同身份。身份定义不清晰,就会导致决策冲突。
我的核心观点: 口径统一不是IT部门的一次开发任务,而是数据治理的基础习惯。它要求企业:
如果你现在还在被“可用库存虚高”导致超卖、被“在途库存不可控”导致断货,请对照本文的公式和模型,检查你的库存状态字段是否覆盖了所有锁定类型。如果没有,从今天开始改变,哪怕先从锁定细分报表开始。
下一步行动清单:
库存口径统一了,自动补货才是真正的补货,而不是“盲人摸象”。


读者评论
作为一个电商运营,文章里的案例让我后背发凉,因为我也踩过类似的坑,系统显示可用3200实际只能发1800,那1000单的投诉和加班补发至今难忘。锁定库存的细分太重要了,尤其是未支付订单和退货质检的隐形占用,不统一口径就是定时炸弹。
作为供应链从业者,我非常赞同在途库存按供应商置信度分场景处理的观点。现实里供应商延迟太常见,全部计入风险大,全部不计又会低估库存导致补货过慢。建立准时率档案是基础,但很多公司嫌麻烦就一刀切,结果就是断货或积压。文章提供了清晰的决策逻辑。
从技术角度看,文章推荐的多状态域数据设计很优雅,但中小电商的ERP通常改不动底层。现实折中方案可以是增加锁定明细表和定时任务来扫描超期锁定,至少让问题暴露出来。库存口径问题往往是业务和开发对“锁定”理解不一致导致的,沟通成本很高。
库存管理不光是数据问题,更是流程问题。文中对锁定库存超时率的细分给我很大启发,我们公司以前只关注总锁定量,从不看每个锁定类型的平均时长,结果滞留在退货质检的库存常常被忘记释放。有了明细报表和告警,才能真正让库存流动起来。