ADDED Requirements
Requirement: Consumable inventory fields
系统 SHALL 在 biz_consumable 表上新增以下库存字段:
stock_qty DECIMAL(18,4) NOT NULL DEFAULT 0 — 当前库存量
warning_qty DECIMAL(18,4) NOT NULL DEFAULT 0 — 预警库存量
status CHAR(1) NOT NULL DEFAULT '1' — 启用/停用状态(1=启用,0=停用)
后端 SQLAlchemy Model BizConsumable SHALL 同步新增对应字段。前端列表和表单 SHALL 展示这些字段。
Scenario: Existing consumables have zero stock after migration
- WHEN 数据库迁移完成,已有耗材记录存在
- THEN 所有已有耗材的 stock_qty 为 0,warning_qty 为 0,status 为 '1'
Scenario: Consumable list shows stock info
- WHEN 用户访问耗材管理列表
- THEN 列表显示当前库存量、预警库存量、状态列
Requirement: Manual stock-in for consumable
系统 SHALL 支持对单个耗材进行手动入库操作。入库数量必须大于 0。入库后 stock_qty 增加,同时生成一条变动记录(source_type=manual_in,change_type=in)。
Scenario: Successful stock-in
- WHEN 用户对库存为 10 的耗材入库 5
- THEN 耗材 stock_qty 变为 15,生成变动记录 change_qty=5, stock_after=15, source_type=manual_in
Scenario: Stock-in with disabled consumable
- WHEN 用户对已停用的耗材执行入库
- THEN 系统拒绝并提示"物料「XX」已停用,无法入库"
Requirement: Manual stock-out for consumable
系统 SHALL 支持对单个耗材进行手动出库操作。出库数量必须大于 0,且不能超过当前库存。出库必须填写领用人。出库后 stock_qty 减少,同时生成一条变动记录(source_type=manual_out,change_type=use,change_qty 为负数)。
Scenario: Successful stock-out
- WHEN 用户对库存为 10 的耗材出库 3,领用人为"张三"
- THEN 耗材 stock_qty 变为 7,生成变动记录 change_qty=-3, stock_after=7, source_type=manual_out, receiver=张三
Scenario: Stock-out exceeds inventory
- WHEN 用户对库存为 2 的耗材出库 5
- THEN 系统拒绝并提示"物料「XX」库存不足,当前库存 2,需出库 5"
Scenario: Stock-out without receiver
- WHEN 用户出库时不填写领用人
- THEN 系统拒绝并提示"请选择领用人"
Requirement: Batch stock-in for consumables
系统 SHALL 支持对多个耗材批量入库。所有条目在同一事务内处理,任一条目失败则全部回滚。每条入库记录独立生成变动记录。
Scenario: Successful batch stock-in
- WHEN 用户批量入库 3 种耗材,数量分别为 5、10、2
- THEN 3 种耗材库存分别增加,生成 3 条变动记录,全部在同一事务内
Scenario: Batch stock-in with one invalid item
- WHEN 用户批量入库 3 种耗材,其中一种已停用
- THEN 全部回滚,没有任何耗材库存变化
Requirement: Batch stock-out for consumables
系统 SHALL 支持对多个耗材批量出库。批量出库需统一填写领用人和用途。所有条目在同一事务内处理,任一条目失败则全部回滚。
Scenario: Successful batch stock-out
- WHEN 用户批量出库 3 种耗材,领用人"张三",数量分别为 2、1、3
- THEN 3 种耗材库存分别减少,生成 3 条变动记录(source_type=manual_out)
Scenario: Batch stock-out with insufficient stock
- WHEN 用户批量出库 3 种耗材,其中一种库存不足
- THEN 全部回滚,提示具体哪个物料库存不足
Requirement: Delete protection for stocked consumable
系统 SHALL 禁止删除库存量大于 0 的耗材。
Scenario: Delete consumable with stock
- WHEN 用户尝试删除库存为 5 的耗材
- THEN 系统拒绝并提示"该物料仍有库存,无法删除"
Scenario: Delete consumable with zero stock
- WHEN 用户删除库存为 0 的耗材
- THEN 软删除成功(del_flag=1)
Requirement: Consumable stock-out disabled status check
出库和入库操作 SHALL 检查物料状态,已停用物料不允许出入库。
Scenario: Stock-out with disabled status
- WHEN 用户对 status='0' 的耗材执行出库
- THEN 系统拒绝并提示"物料「XX」已停用,无法出库"
Requirement: Row-level locking for concurrent stock operations
出入库操作 SHALL 使用 with_for_update() 行锁,防止并发操作导致库存数据不一致。
Scenario: Concurrent stock-in
- WHEN 两个用户同时对同一耗材入库
- THEN 行锁保证两次操作串行执行,库存结果正确
Requirement: Consumable stock log table
系统 SHALL 新建 biz_consumable_stock_log 变动记录表,字段参照 biz_material_stock_log 并增加生产溯源字段:
material_id — 耗材 ID
material_code / material_name — 快照字段
change_type — in(入库) / use(使用/出库)
change_qty — 变动数量(入库正数,出库负数)
stock_before — 变动前库存
stock_after — 变动后库存
source_type — manual_in / manual_out / step_save
step_id / task_id / task_no — 步骤溯源字段(step_save 时有值)
receiver / purpose — 领用人/用途(manual_out 时有值)
- 公共字段
Scenario: Stock log created on stock-in
- WHEN 耗材入库 5
- THEN 变动记录 change_type=in, change_qty=5, source_type=manual_in, stock_before=旧库存, stock_after=新库存