电商库存模型:占用、可用、在途、冻结的划分与落地

电商库存模型:占用、可用、在途、冻结的划分与落地

电商供应链里,库存不只是一串数字,而是多种「状态」的组合。把实物、占用、可用、在途、冻结五类拆清楚,并显式刻画它们之间的流转,才能避免超卖、少卖和对账困难。本文先说划分,再画流转,最后落库与一致性要点。


一、五类库存的定义与关系

单 SKU、单仓库为维度,可抽象出五类数量(均为非负整数):

类型 含义 典型来源
实物库存 仓内实际可盘点的数量 采购入库、销售出库、调拨、盘点
占用库存 已成交未出库(订单已下单未发货) 销售下单、预售确认
可用库存 可被新订单占用的数量 由公式算得,不单独持久
在途库存 已采购未入库 采购单下发、在途入库
冻结库存 被活动/调拨预占,尚未转成占用或出库 秒杀预占、仓间调拨预占

数量关系(核心公式):

1
可用库存 = 实物库存 - 占用库存 - 冻结库存

注意:在途不参与「可售」计算,只有入库后才变成实物,再通过可用被售卖;占用冻结都是从「可用」里扣出来的,只是业务含义不同(前者是已卖,后者是预占)。


二、库存状态的流转(核心)

下面用「谁触发 → 哪些数量增减」的方式描述流转,便于对照落库与事件。

2.1 采购链路

1
2
3
4
flowchart LR
A[采购下单] -->|在途 +N| B[在途]
B --> C[采购入库]
C -->|在途 -N,实物 +N| D[实物]
  • 采购单确认:只在「在途」上 +N,不动实物与可用。
  • 入库单完成:在途 -N,实物 +N;可用因公式自动增加(占用、冻结不变时)。

2.2 销售链路(正常下单 → 发货)

1
2
3
4
flowchart LR
A[下单占库存] -->|可用 -N,占用 +N| B[占用]
B --> C[发货出库]
C -->|占用 -N,实物 -N| D((出库完成))
  • 下单:先扣可用(等价于占用增加),占用 +N;实物暂时不变,等出库再减。
  • 出库:占用 -N、实物 -N;取消则只做「占用 -N」,可用通过公式回升。

2.3 订单取消

1
2
3
flowchart LR
A[订单取消] -->|占用 -N| B[占用释放]
B -->|可用 +N(公式)| C[可用]

只减占用,不碰实物;可用随公式恢复。

2.4 促销/秒杀预占(活动未开始)

1
2
3
4
5
flowchart TB
A[活动预占] -->|可用 -N,冻结 +N| B[冻结]
B --> C{后续操作}
C -->|活动开始/用户下单<br/>冻结 -N,占用 +N| D[占用]
C -->|活动取消/释放<br/>冻结 -N,可用 +N| E[可用]
  • 预占:把「可售」从可用挪到冻结,避免被普通订单卖光。
  • 开卖:冻结减、占用加,进入正常销售链路。
  • 取消/过期:只减冻结,可用通过公式恢复。

2.5 仓间调拨

1
2
3
4
5
6
7
8
9
10
11
flowchart TB
subgraph 调出仓
A1[调拨单创建/预占] -->|可用 -N,冻结 +N| A2[冻结]
A2 --> A3[调拨出库]
A3 -->|冻结 -N,实物 -N| A4((出库))
end
subgraph 调入仓
B1[在途] --> B2[调拨入库]
B2 -->|在途 -N,实物 +N| B3[实物]
end
A4 -.-> B1

调出仓:先冻结再出库,避免调拨与销售抢同一批可用;调入仓可按「在途」建模(在途 +N 在调拨发运时,在途 -N、实物 +N 在入库时)。

2.6 流转总览(概念图)

1
2
3
4
5
6
7
8
9
10
11
12
13
flowchart LR
subgraph 入库
PO[采购下单] -->|在途 +N| IT[在途]
IT -->|采购入库| PH[实物]
end
subgraph 销售与预占
PH -->|下单占库| OC[占用]
OC -->|发货出库| OUT1((出库))
AV[可用] -->|活动预占| FR[冻结]
FR -->|活动开始| OC
OC -->|取消订单| AV
FR -->|释放| AV
end

三、落地要点

3.1 表与字段设计(示意)

  • 库存主表(按 仓库 + SKU):physical_qtyoccupied_qtyfrozen_qtyin_transit_qty
  • 可用不落库,查询时算:available_qty = physical_qty - occupied_qty - frozen_qty
  • 约束available_qty 计算结果 ≥ 0;扣减可用时等价为「占用+」或「冻结+」,并做乐观锁或行锁,防止超卖。

3.2 扣减顺序与事务

  • 下单占库存:在事务内「可用检查 → 占用+」或「实物 - 占用 - 冻结 ≥ 需求」后 occupied_qty += N
  • 出库:同一事务内「占用-」「实物-」;取消订单只「占用-」。
  • 预占、释放、在途增减同理,保证一次业务操作内,涉及的多列增减原子完成

3.3 流水与可追溯

每次数量变动落库存流水表:仓库、SKU、变动类型(占用+/-、冻结+/-、实物+/-、在途+/-)、变动量、单据号(订单号/采购单号/调拨单号等)、前后快照。便于对账、排查超卖和做审计。

3.4 与 DDD / 事件结合

  • 聚合根:以「仓库+SKU」为库存聚合根,变更通过领域方法(如 reserve()confirmOutbound())完成,内部维护五类数量。
  • 跨上下文:出库完成可发「库存已扣减」领域事件,驱动订单侧更新发货状态;事件 payload 带单据号与数量,便于幂等与对账。

四、小结

  • 五类:实物(仓内实有)、占用(已卖未发)、可用(公式)、在途(已采未入)、冻结(预占未用)。
  • 关系:可用 = 实物 - 占用 - 冻结;在途独立,入库后才参与实物与可用。
  • 流转:采购动在途与实物;销售动可用↔占用与实物;活动/调拨动可用↔冻结,再转占用或实物。
  • 落地:主表存四类数量、可用计算得出;事务内原子增减;流水表记录每次变动;领域内封装变更并可选发事件,保证一致与可追溯。

把「划分 + 流转」在设计与代码里显式化,是库存准确、可解释、易扩展的基础。