2.0 KiB
2.0 KiB
05 库存设计
库存设计是整个 WMS 的核心。
库存模型
不要简单设计 sku + warehouse + quantity,必须建立完整库存模型。
数量维度
| 字段 | 含义 |
|---|---|
| available_qty | 可用数量 |
| reserved_qty | 预占 / 锁定数量 |
| picked_qty | 已拣货数量 |
| hold_qty | 冻结数量 |
| damaged_qty | 残损数量 |
| in_transit_qty | 在途数量 |
位置与属性维度
- 仓库
- 库区
- 库位
- SKU
- 批次
- 库存状态
核心关系
SKU
↓
Warehouse
↓
Zone
↓
Location
↓
Batch
↓
Inventory
库存流水必须是核心数据
必须设计 wms_stock_log,任何库存变化必须能够追溯。例如:
入库 +100
锁定 -20
拣货 -5
出库 -5
盘点 +2
调整 -1
需要能够回答:为什么这个 SKU 的库存从昨天的 100 变成今天的 76?
- 库存余额是结果。
- 库存流水是事实。
不要只修改 inventory.quantity 而不留下完整流水。库存余额更新与流水写入必须在同一事务中完成,流水需记录业务单据类型与单号(如 inbound_no / outbound_no)。
库存并发安全
库存扣减必须考虑并发。
禁止: 先 SELECT → PHP 计算 → UPDATE。这种方式容易产生超卖。
根据实际业务采用:
- 数据库事务
- 行锁(
SELECT ... FOR UPDATE) - 乐观锁(version 字段)
- 原子更新
- Redis 分布式锁(必要时)
原子更新示例:
UPDATE wms_inventory
SET available_qty = available_qty - :qty,
reserved_qty = reserved_qty + :qty
WHERE tenant_code = :tenant_code
AND id = :id
AND available_qty >= :qty;
-- 受影响行数为 0 即库存不足,必须抛出业务异常
必须保证:
available_qty >= 扣减数量- 多个并发请求不能导致负库存或重复扣减
并发验收用例
两个请求同时扣减 8 个库存,而实际只有 10 个库存。必须保证:
- 不会出现
available_qty = -6 - 不能出现两个订单都成功扣减 8