Files
wms-saas/docs/database/40-inventory.md
T
2026-09-30 11:11:54 +08:00

10 KiB
Raw Blame History

库存余额、批次、流水、调整、盘点

约定见 00-conventions.md。数量桶的业务含义见 01-er-overview.md 与 05-inventory.md。Phase 1 锁定,Phase 7、8 写迁移。

冻结、锁定不单独建单据表。冻结是可用与 hold_qty 的对转;订单锁定是可用与 reserved_qty 的对转,锁定对象记在 wms_outbound_allocation 和流水的 biz_no 上。

wms_batch 批次

用途:批次属性。不管理批次的库存使用 batch_no = '',不写本表。

字段 类型 可空 默认 说明
id BIGINT UNSIGNED N AUTO_INCREMENT 内部主键
tenant_code VARCHAR(32) N 租户编码
customer_code VARCHAR(64) N 货主
sku_code VARCHAR(64) N SKU 编码
batch_no VARCHAR(64) N 批次号,禁止空字符串
supplier_code VARCHAR(64) Y 供应商
mfg_date DATE Y 生产日期
expiry_date DATE Y 失效日期
created_at TIMESTAMP Y
updated_at TIMESTAMP Y

索引:

名称 类型 字段 支撑的查询
uk_tenant_customer_sku_batch UNIQUE (tenant_code, customer_code, sku_code, batch_no) 定位批次
idx_tenant_sku_expiry INDEX (tenant_code, sku_code, expiry_date) 临期查询

关联:wms_inventory.batch_no。首次收货写入,之后只允许补空缺的日期,不改已有批次号。

并发 / 审计:无软删除。属性变更写 wms_operation_log。

wms_inventory 库存余额

用途:某一货主、仓库、库位、SKU、批次上的数量结果。余额是结果,不是事实。

字段 类型 可空 默认 说明
id BIGINT UNSIGNED N AUTO_INCREMENT 内部主键
tenant_code VARCHAR(32) N 租户编码
customer_code VARCHAR(64) N 货主
warehouse_code VARCHAR(32) N 仓库编码
location_code VARCHAR(64) N '' 库位;在途为空字符串
sku_code VARCHAR(64) N SKU 编码
batch_no VARCHAR(64) N '' 批次;无批次为空字符串
available_qty DECIMAL(16,4) N 0 可用
reserved_qty DECIMAL(16,4) N 0 预占
picked_qty DECIMAL(16,4) N 0 已拣
hold_qty DECIMAL(16,4) N 0 冻结
damaged_qty DECIMAL(16,4) N 0 残损
in_transit_qty DECIMAL(16,4) N 0 在途
version INT UNSIGNED N 0 乐观锁,随数量更新递增
created_at TIMESTAMP Y
updated_at TIMESTAMP Y

索引:

名称 类型 字段 支撑的查询
uk_inventory_grain UNIQUE (tenant_code, customer_code, warehouse_code, location_code, sku_code, batch_no) 定位余额行
idx_tenant_wh_sku INDEX (tenant_code, warehouse_code, sku_code) 仓库内某 SKU 库存
idx_tenant_customer_sku INDEX (tenant_code, customer_code, sku_code) 货主下某 SKU 库存

关联:维度对应仓库、库位、SKU、批次。在途行的 location_code 不引用 wms_location。

并发 / 审计:

  • 禁止先查出数量再在 PHP 里相减后回写。
  • 扣减使用单条条件更新,例如可用转预占:
UPDATE wms_inventory
SET available_qty = available_qty - :qty,
    reserved_qty = reserved_qty + :qty,
    version = version + 1
WHERE tenant_code = :tenant_code
  AND id = :id
  AND available_qty >= :qty;
  • 受影响行数为 0:库存不足或版本冲突,抛业务异常,整单事务回滚。
  • 同一事务插入对应的 wms_stock_log。
  • 各数量桶不得为负。不软删除;数量全为 0 的行保留,避免并发下反复插入同一粒度。

wms_stock_log 库存流水

用途:库存变化的事实。任何余额变化都要有流水。只追加。

一次业务动作若改变多个数量桶或多行余额,每个桶一行,共用同一个 movement_no。

字段 类型 可空 默认 说明
id BIGINT UNSIGNED N AUTO_INCREMENT 内部主键
tenant_code VARCHAR(32) N 租户编码
movement_no VARCHAR(64) N 同一次动作的组号
customer_code VARCHAR(64) N 货主
warehouse_code VARCHAR(32) N 仓库
location_code VARCHAR(64) N '' 库位
sku_code VARCHAR(64) N SKU
batch_no VARCHAR(64) N '' 批次
qty_bucket VARCHAR(32) N available、reserved、picked、hold、damaged、in_transit
qty_before DECIMAL(16,4) N 该桶变更前
qty_delta DECIMAL(16,4) N 有符号变化量
qty_after DECIMAL(16,4) N 该桶变更后
biz_type VARCHAR(32) N 业务类型
biz_no VARCHAR(64) N 业务单号
biz_line_no INT UNSIGNED Y 单据行号
operator_user_code VARCHAR(64) Y 操作人
request_id VARCHAR(64) Y 请求标识
created_at TIMESTAMP Y 发生时间
updated_at TIMESTAMP Y 行创建后不更新

索引:

名称 类型 字段 支撑的查询
idx_tenant_sku_created INDEX (tenant_code, sku_code, created_at) 某 SKU 的库存为何变化
idx_tenant_biz INDEX (tenant_code, biz_type, biz_no) 某单据的流水
idx_tenant_movement INDEX (tenant_code, movement_no) 同一次动作的各行

biz_type:inbound_confirm、inbound_receive、inbound_putaway、reserve、release、pick、ship、hold、unhold、damage、transfer、adjust、stocktake。

关联:biz_no 指向入库单、出库单、调整单或盘点单。

并发 / 审计:禁止更新和删除。qty_after = qty_before + qty_delta,且 qty_after 等于同一事务中余额桶的新值。

wms_stock_adjust 库存调整单

用途:人工调整的单据头。确认时才改余额并写流水。

字段 类型 可空 默认 说明
id BIGINT UNSIGNED N AUTO_INCREMENT 内部主键
tenant_code VARCHAR(32) N 租户编码
adjust_no VARCHAR(64) N 调整单号
warehouse_code VARCHAR(32) N 仓库
customer_code VARCHAR(64) N 货主
status VARCHAR(32) N draft 状态
reason VARCHAR(500) N 原因
version INT UNSIGNED N 0 乐观锁
created_at TIMESTAMP Y
updated_at TIMESTAMP Y

索引:

名称 类型 字段 支撑的查询
uk_tenant_adjust_no UNIQUE (tenant_code, adjust_no) 按单号查找
idx_tenant_status_created INDEX (tenant_code, status, created_at) 列表

状态:draft → confirmed,draft → cancelled。confirmed、cancelled 为终态。

确认时按明细对指定数量桶做原子增减,biz_type = adjust。减少时受影响行数为 0 则整单回滚。状态变更写 wms_status_log。不软删除。

wms_stock_adjust_line 调整明细

用途:调整单的一行,只改一个数量桶。

字段 类型 可空 默认 说明
id BIGINT UNSIGNED N AUTO_INCREMENT 内部主键
tenant_code VARCHAR(32) N 租户编码
adjust_no VARCHAR(64) N 调整单号
line_no INT UNSIGNED N 行号,单内从 1 递增
location_code VARCHAR(64) N '' 库位
sku_code VARCHAR(64) N SKU
batch_no VARCHAR(64) N '' 批次
qty_bucket VARCHAR(32) N 数量桶
qty_delta DECIMAL(16,4) N 有符号数量,禁止 0
created_at TIMESTAMP Y
updated_at TIMESTAMP Y

索引:

名称 类型 字段 支撑的查询
uk_tenant_adjust_line UNIQUE (tenant_code, adjust_no, line_no) 定位明细

关联:头表 wms_stock_adjust。确认后明细不再修改。

wms_stocktake 盘点单

用途:盘点单据头。确认时把账面与实盘的差额写成流水,biz_type = stocktake。

字段 类型 可空 默认 说明
id BIGINT UNSIGNED N AUTO_INCREMENT 内部主键
tenant_code VARCHAR(32) N 租户编码
stocktake_no VARCHAR(64) N 盘点单号
warehouse_code VARCHAR(32) N 仓库
status VARCHAR(32) N draft 状态
version INT UNSIGNED N 0 乐观锁
created_at TIMESTAMP Y
updated_at TIMESTAMP Y

索引:

名称 类型 字段 支撑的查询
uk_tenant_stocktake_no UNIQUE (tenant_code, stocktake_no) 按单号查找
idx_tenant_status_created INDEX (tenant_code, status, created_at) 列表

状态:draft → counting → confirmed,draft 或 counting 可到 cancelled。confirmed、cancelled 为终态。

盘点期间不锁死全仓。确认时按当时账面重算差额;若并发导致目标桶不足,确认失败并回滚。不软删除。

wms_stocktake_line 盘点明细

用途:一个库位、SKU、批次、数量桶上的账面与实盘。

字段 类型 可空 默认 说明
id BIGINT UNSIGNED N AUTO_INCREMENT 内部主键
tenant_code VARCHAR(32) N 租户编码
stocktake_no VARCHAR(64) N 盘点单号
line_no INT UNSIGNED N 行号
customer_code VARCHAR(64) N 货主
location_code VARCHAR(64) N 库位
sku_code VARCHAR(64) N SKU
batch_no VARCHAR(64) N '' 批次
qty_bucket VARCHAR(32) N available 盘点的数量桶
system_qty DECIMAL(16,4) N 生成明细时的账面
counted_qty DECIMAL(16,4) Y 实盘,未盘为空
created_at TIMESTAMP Y
updated_at TIMESTAMP Y

索引:

名称 类型 字段 支撑的查询
uk_tenant_stocktake_line UNIQUE (tenant_code, stocktake_no, line_no) 定位明细
idx_tenant_stocktake_loc INDEX (tenant_code, stocktake_no, location_code) 按库位录入

关联:头表 wms_stocktake。确认时差额为 counted_qty - 当前账面,不以生成时的 system_qty 作为扣减依据。system_qty 只说明生成时刻的账面。