“仓库已经没货了。”
周四早上的经营会刚开十分钟,仓储负责人就把这句话丢在桌上。采购皱了皱眉,转头看大屏:系统明明显示还有 800 件。运营也急了,昨晚刚做完活动预热,页面上的商品还在卖。
数据分析师阿悦坐在靠门的位置,手里那杯咖啡已经凉了一半。大家等她回答一个听起来很简单的问题:到底有没有货?
她没有立刻查 SQL,而是先问:“这 800 件,是什么时间、哪个仓、什么状态下的库存?”
会议室安静了几秒。报表上的数字当然没说谎,仓库里空着的拣货位也没说谎。麻烦在于,它们说的可能不是同一个时刻。
库存是经营分析里很会骗人的一个词。不是因为谁故意造假,而是它把账面、可售、冻结、在途四种状态挤进了两个字里。再省略时间,800 件和缺货便能同时成立,像两个人各自拿着半张地图争论谁走错了路。

先别争数字,先给库存加上“截至何时”
很多库存看板把商品、仓库、数量放得很醒目,却把数据时间缩在角落,甚至只写“今日”。这对库存来说远远不够。
“今日库存 800”可能是早上八点的快照;仓库说缺货,可能是九点十五分的拣货现场;运营看到的可售量,可能在九点零三分已经被一批订单预留;采购嘴里的在途 600 件,要下午两点才到仓,到了还要质检和上架。
所以库存核对的第一步不是把几个系统的数字抄到一张表里,而是给每个数字补全四件事:
商品 + 地点 + 状态 + 生效时间
少一个维度,都可能在比较不同的东西。
微软 Dynamics 365 的 Inventory Visibility 文档给了一个很直观的例子:销售订单发生软预留后,供应链系统里的实物库存数量可以暂时不变,但可预留数量已经减少。它的 ATP,也就是“可承诺量”,还会结合计划中的入库和出库变化计算。换句话说,账上有货、现在能卖、未来能承诺,本来就不是一个数字。
这不是某个软件特有的脾气。SAP 的产品可用性检查也允许企业决定哪些订单、调拨库存和其他供需元素进入可用量计算。真正的口径因此不在“库存”二字里,而在你们公司到底把哪些状态、单据和时间算了进去。
时间点一:账面过账,回答“系统最后记到了哪一步”
账面库存是系统已经确认并记账的数量。它通常来自收货、上架、移库、拣货、出库、盘点调整等事件。
要核对的不是“当前库存是多少”,而是:
- 这张表最后一次库存事件过账到几点?
- 800 件属于哪个仓、库区、货位和商品批次?
- 仓库动作已经发生,但系统事件还在队列里吗?
- 报表取的是实时事件,还是每小时一次的库存快照?
回到那场会,报表上的 800 件来自 08:00 快照。仓库在 08:35 完成了一批波次拣货,但出库事件要等作业系统回传。九点开会时,账面数字仍停在过去,现场已经往前走了。
这时不要急着给系统扣一顶“库存不准”的帽子。先量出事件延迟:仓库确认时间、库存过账时间、数据入仓时间、报表刷新时间分别是什么。四段时间一摆出来,责任边界通常就没那么神秘了。
时间点二:可售承诺,回答“这一刻还能答应客户多少”
可售库存不是简单的账面库存减一减。它取决于企业如何处理预留、渠道分配、未完成订单、安全库存和超卖规则。
同样是 800 件账面库存,可能有 520 件已经被昨晚订单软预留,200 件留给线下门店,80 件作为安全库存不能放给线上渠道。仓库看线上波次时,自然会说“没货”;集团库存表看总账时,仍然能看到 800。
核对可售时间点,要追问:
- 订单在创建、支付还是审核通过时占用库存?
- 取消订单、支付超时后,预留什么时候释放?
- 渠道配额在哪个系统生效,报表是否已经收到?
- 查询的可售量是“现在可下单”,还是“承诺未来某日可交付”?
可售量是一种承诺,不是一堆静止的箱子。它会随着订单和规则变化。如果分析师把一天结束时的账面库存拿去解释上午活动的缺货,就像拿晚饭后的冰箱照片证明中午还有菜,画面是真的,时间不对。

时间点三:冻结生效,回答“货在这里,为什么不能动”
仓库里看得见的货,也未必能卖。
质量抽检、临期复核、破损待判、召回、盘点锁库、客诉留样,都可能让库存进入冻结状态。最常见的争议不是有没有冻结,而是冻结从什么时候生效、在哪个系统记录、什么时候解除。
有一次类似排查,仓库 08:40 把 280 件商品转入质检区,现场自然不再拣货;库存主系统 09:20 才收到冻结事件,经营看板 10:00 才刷新。一个多小时里,仓库说不能卖,系统说仍有货,两边都能拿出证据。
冻结库存至少要有:冻结原因、冻结数量、冻结生效时间、预计复核时间、解除时间和责任人。报表如果只扣数量,不展示原因,运营看到的只是“货凭空消失”;如果完全不扣,页面又会继续接单。
真正要盯的是冻结事件从现场到报表的传播时间。它决定了缺货是业务状态,还是数据延迟。
时间点四:在途入库,回答“路上的货什么时候才算能用”
采购说“还有 600 件在途”,听起来很让人安心。可是在途库存里至少有三种时间:供应商承诺到达、车辆实际到仓、仓库完成收货上架。
货车停在园区门口,不等于商品已经可售;系统创建了采购单,也不等于货已经出发。微软关于 ATP 的说明把计划入库称为尚未实际可供消费或发运的计划供应,只有实际变化事件提交后,才更新当前库存。这个区分很重要:未来的供应可以支持未来承诺,却不能拿来填今天上午的拣货位。
核对在途时,分析师要把一个“预计到货时间”拆开:
- 供应商发运时间;
- 预计与实际到仓时间;
- 收货确认时间;
- 质检完成与可售上架时间。
如果活动在上午十点开始,而 600 件下午两点到仓、四点上架,今天并不是“有 600 件库存”,而是“最快下午四点可能增加 600 件可售库存”。多写几个字,经营判断会少绕很大一圈。
把 800 件拆成一张状态时间表
阿悦后来没有再问“到底有没有货”。她把现场数字整理成一个简化示例:
| 时间 | 事件 | 账面库存 | 已预留 | 冻结 | 当前可售 | 在途 |
|---|---|---|---|---|---|---|
| 08:00 | 库存快照生成 | 800 | 0 | 0 | 800 | 600 |
| 08:15 | 昨晚订单完成预留 | 800 | 520 | 0 | 280 | 600 |
| 08:40 | 质检冻结生效 | 800 | 520 | 280 | 0 | 600 |
| 09:00 | 经营会查看旧快照 | 800 | 报表未更新 | 报表未更新 | 报表仍显示 800 | 600 |
| 14:00 | 预计到仓 | 视实际收货 | 视订单变化 | 视质检结果 | 尚不能承诺 | 600 |
这张表里的数字只是为了说明核对方法,不是通用库存公式。每家公司如何计算可售,都要看自己的预留、冻结、配额与安全库存规则。
可是它把冲突说清楚了:800 是八点的账面快照;仓库说缺货,是八点四十分之后的可拣状态;600 件在途,是下午的未来供应。大家没有谁看错,只是时间切片没有对齐。

经营会上先问这 3 句话
下次再遇到“仓库说没有,系统说还有”,先别把会议开成责任认定会。三句话通常能省下一轮争吵。
第一问:我们看的是否是同一商品、同一地点?
把 SKU、批次、仓库、库区、货位和渠道范围对齐。全国 800 件,不代表华东前置仓能拣到一件;普通批次有货,也不代表活动指定批次可用。
第二问:这个数量处于什么状态?
明确它是账面、可售、已预留、冻结还是在途。不要把不同状态相加后还叫“库存总量”,也不要只看总量就决定继续投放。
第三问:每个状态分别在几点生效?
写出业务事件时间、系统过账时间、数据入仓时间和报表刷新时间。若差异来自延迟,就讨论延迟门槛和补数;若差异来自口径,就讨论该展示哪个状态。别用修数据的办法解决定义问题。
一张库存报表,至少要让读者看见时间
我更愿意把库存看板做得啰嗦一点。除了数量,至少展示数据截至时间、库存状态、仓库范围和可售计算说明。出现延迟时,明确写“账面截至 08:00,预留截至 08:55,冻结事件待同步”,比一个看起来干净的 800 更诚实。
数据分析的价值,有时不是算出一个更漂亮的数字,而是阻止几个正确的数字在错误的时间相遇。
那场会最后没有立刻加急补货。运营先暂停了活动扩量,仓库确认冻结原因,采购重新给出可上架时间,数据团队则把库存快照和预留事件改成同一张状态时间表。临近中午,280 件质检通过,页面恢复部分可售。
咖啡早就凉透了。阿悦去茶水间换了一杯热水。系统里的 800 还在那里,但大家终于知道,它说的是几点钟的故事。
我叫石头,在数据行业里摸爬滚打了十几年,见过不少库存数字各自正确、放在一起却吵起来的现场。这里写的,就是这些教训——我觉得值得说出来的那部分。
参考资料:Microsoft Dynamics 365 Inventory Visibility reservations · Microsoft Inventory Visibility on-hand change schedules and ATP · SAP Product Availability Check