Files
wms-saas/docs/05-inventory.md
T
2026-09-29 13:08:21 +08:00

102 lines
2.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 分布式锁(必要时)
原子更新示例:
```sql
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