Files
zkxw/openspec/changes/production-material-inventory/specs/production-step-stock-deduction/spec.md
T
2026-05-23 12:51:22 +08:00

4.3 KiB

ADDED Requirements

Requirement: Step save auto stock deduction

系统 SHALL 在生产任务步骤保存耗材/试剂时,根据 actual_usage 字段自动扣减对应耗材/试剂的库存。变动记录的 source_type SHALL 为 step_save。

Scenario: First save with actual usage

  • WHEN 用户首次保存步骤,耗材A 的 actual_usage=2,耗材B 的 actual_usage=3
  • THEN 耗材A 库存扣减 2,耗材B 库存扣减 3,生成 2 条变动记录 source_type=step_save

Scenario: Save with empty actual_usage

  • WHEN 用户保存步骤,某耗材的 actual_usage 为空或为 0
  • THEN 该耗材不扣减库存,不生成变动记录

Scenario: Save with non-numeric actual_usage

  • WHEN 用户保存步骤,某耗材的 actual_usage 为非数字字符串
  • THEN 系统跳过该条目,仅处理 actual_usage 为有效正数的条目

Requirement: Step save diff settlement via full revert and re-deduct

系统 SHALL 采用全量回退+重算模式处理步骤保存的库存变动:

  1. 查出该步骤此前所有 source_type=step_save 的变动记录
  2. 按变动记录逐条回退库存(加回扣减量),软删变动记录
  3. 遍历新的步骤耗材/试剂列表,按 actual_usage 扣减库存,生成新变动记录

Scenario: Modify usage upward

  • WHEN 步骤首次保存耗材A actual_usage=2,第二次保存改为 actual_usage=3
  • THEN 回退 2(库存+2),重新扣减 3(库存-3),净效果库存-1

Scenario: Modify usage downward

  • WHEN 步骤首次保存耗材A actual_usage=5,第二次保存改为 actual_usage=2
  • THEN 回退 5(库存+5),重新扣减 2(库存-2),净效果库存+3

Scenario: Remove material from step

  • WHEN 步骤首次保存耗材A actual_usage=3 和耗材B actual_usage=2,第二次保存仅保留耗材B actual_usage=2
  • THEN 回退耗材A 的 3 和耗材B 的 2,重新扣减耗材B 的 2。净效果:耗材A 库存+3,耗材B 不变

Scenario: Add new material to step

  • WHEN 步骤首次保存耗材A actual_usage=2,第二次保存新增耗材C actual_usage=4
  • THEN 回退耗材A 的 2,重新扣减耗材A 的 2 和耗材C 的 4。净效果:耗材A 不变,耗材C 库存-4

Requirement: Step save stock deduction uses row-level locking

diff 结算过程中 SHALL 使用 with_for_update() 行锁锁定涉及的耗材/试剂行。

Scenario: Concurrent step saves on same material

  • WHEN 两个步骤同时保存,都涉及耗材A
  • THEN 行锁保证串行执行,库存变动正确

Requirement: Step save stock deduction in same transaction

diff 结算 SHALL 在步骤耗材/试剂保存的同一数据库事务中执行。库存扣减失败时,步骤保存也回滚。

Scenario: Stock insufficient during step save

  • WHEN 用户保存步骤,耗材A actual_usage=10,但库存仅 3
  • THEN 整个步骤保存回滚,提示"物料「耗材A」库存不足,当前库存 3,需使用 10"

Requirement: Stock deduction traceability

每条 step_save 类型的变动记录 SHALL 包含以下溯源字段:

  • step_id — 生产任务步骤 ID
  • task_id — 生产任务 ID
  • task_no — 生产任务编号快照

Scenario: Stock log shows task info

  • WHEN 步骤保存触发库存扣减
  • THEN 变动记录包含 step_id、task_id、task_no,可追溯至具体任务和步骤

Requirement: Deduction hooks in replace_step_reagents and replace_step_consumables

库存 diff 结算 SHALL 在 replace_step_reagents() 和 replace_step_consumables() 函数中执行,调用时机为软删旧子记录之后、插入新子记录之前。

Scenario: replace_step_consumables triggers deduction

  • WHEN API PUT /production-tasks/{task_id}/steps/{step_id}/consumables 被调用
  • THEN 系统在替换步骤耗材的同时执行库存 diff 结算

Requirement: Skip deduction for materials not in catalog

如果步骤中的耗材编码或试剂编码在 biz_consumable / biz_reagent 中不存在(可能是手工录入的自定义物料),SHALL 跳过该条目的库存扣减,不报错。

Scenario: Custom material code in step

  • WHEN 步骤保存包含一个 consumable_code 不在 biz_consumable 表中的条目
  • THEN 系统跳过该条目的库存扣减,其他正常条目正常扣减