生产部门当前仅有耗材目录表(biz_consumable)和试剂目录表(biz_reagent),管理编码、名称、规格、标准用量等基础信息,无库存管理。市场部门和质检部门已有完整的库存管理体系,采用「主表含库存字段 + 变动记录表」的双表模式。
现有耗材/试剂被 10 张下游关联表(耗材包、工艺、工艺路线、生产任务步骤)引用,但全部使用快照复制(denormalized code/name),无 FK 依赖,对主表加字段零影响。
biz_material(含 stock_qty)+ biz_material_stock_log(变动记录,rk/ck,正数)biz_qc_material(含 stock_qty)+ biz_qc_material_usage(变动记录,in/use,正负数,含 task_complete 自动扣减 + revert 回退)生产任务步骤的耗材/试剂保存入口:
PUT /production-tasks/{task_id}/steps/{step_id}/reagents → replace_step_reagents()PUT /production-tasks/{task_id}/steps/{step_id}/consumables → replace_step_consumables()这两个函数使用"软删旧 + 插入新"模式,需在此处加入 diff 结算逻辑。
Goals:
Non-Goals:
选择:ALTER TABLE biz_consumable / biz_reagent 新增 stock_qty、warning_qty、status 字段。
理由:
替代方案:新建 biz_consumable_stock 表,通过 consumable_id 关联。放弃原因:多一层间接、需维护目录-库存同步、与已有模式不一致。
选择:新建 biz_consumable_stock_log 和 biz_reagent_stock_log,参照 biz_material_stock_log 结构。
理由:
biz_qc_material_usage 的 source_type 模式:manual_in / manual_out / step_save关键设计:参照质检物料采用正负数表示方向(入库正、出库负),同时保留 change_type 字段(in/use)。
选择:全量回退 + 重算模式(参照质检物料的 revert + deduct 模式)。
算法:
理由:
替代方案:逐项 diff(旧用量 - 新用量 = 差额)。放弃原因:需处理编码变更(物料A改成物料B)、处理删除、新增等复杂场景,容易出 bug。全量回退更简单且已验证。
选择:
理由:
选择:在 replace_step_reagents() 和 replace_step_consumables() 函数中,在 soft delete 旧记录之后、insert 新记录之前,执行库存 diff 结算。
调用链:
API: PUT /production-tasks/{task_id}/steps/{step_id}/consumables
→ replace_step_consumables(db, step_id, tenant_no, user_id, items)
→ 1. 查出步骤信息(step_id → task_id, task_no)
→ 2. 调用 diff_settle_step_consumables(db, step_id, task_id, task_no, tenant_no, user_id)
→ revert step 的所有 step_save 变动记录(回退库存)
→ 3. soft delete 旧步骤耗材子记录
→ 4. insert 新步骤耗材子记录
→ 5. 调用 deduct_step_consumables(db, step_id, task_id, task_no, tenant_no, user_id, new_items)
→ 按 actual_usage 扣减库存,生成 step_save 变动记录
→ 6. commit
影响:任务执行保存步骤时,若耗材/试剂库存不足,保存会失败。 缓解:提供清晰的错误提示("物料「XX」库存不足,当前库存 N,需使用 M"),让用户先去入库。同时前端可在步骤编辑时显示当前库存量供参考。
影响:步骤保存时 actual_usage 字段可能为空字符串或非数字。 缓解:diff 结算时跳过 actual_usage 为空或无法转为正数的条目,仅处理有效数据。
影响:多个步骤同时保存涉及同一耗材/试剂。
缓解:使用 with_for_update() 行锁,与质检物料一致。
选择全量回退,牺牲少量性能换取代码简洁性和正确性保证。步骤保存频率低,性能影响可忽略。