docs/00-overview.md

This commit is contained in:
Yangxt
2026-09-29 13:08:21 +08:00
parent c30f7e2e7b
commit cb9b7a4bd4
20 changed files with 1383 additions and 0 deletions
+101
View File
@@ -0,0 +1,101 @@
# 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