Files
zkxw/openspec/changes/production-material-inventory/design.md
T
2026-05-23 12:51:22 +08:00

132 lines
6.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## Context
生产部门当前仅有耗材目录表(`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
**Goals:**
- 为耗材和试剂增加库存管理能力(库存量、预警量、出入库操作)
- 支持手动单个/批量入库出库,参照质检物料模式
- 支持生产任务步骤保存时按 actual_usage 自动 diff 结算库存
- 变动记录在耗材/试剂页面内以子弹窗和 Tab 形式展示
**Non-Goals:**
- 不新建独立菜单页面(变动记录嵌入现有页面)
- 不修改现有耗材/试剂目录字段(只加库存字段)
- 不修改下游 10 张关联表
- 不实现仓库/库位管理(单库存维度)
- 不实现库存预警通知(仅记录 warning_qty 字段)
- 不统一耗材/试剂为统一物料表(保持两个独立目录)
## Decisions
### Decision 1: 在现有目录表上加库存字段,不新建库存主表
**选择**:ALTER TABLE `biz_consumable` / `biz_reagent` 新增 `stock_qty`、`warning_qty`、`status` 字段。
**理由**:
- 下游 10 张关联表全是快照复制,加字段零影响
- 与市场/质检物料的「主表含库存字段」模式一致
- 避免引入目录表→库存表的间接层和数据同步问题
- 改动最小:复用现有 CRUD/API/前端,只需扩展
**替代方案**:新建 `biz_consumable_stock` 表,通过 consumable_id 关联。放弃原因:多一层间接、需维护目录-库存同步、与已有模式不一致。
### Decision 2: 新建独立的变动记录表
**选择**:新建 `biz_consumable_stock_log` 和 `biz_reagent_stock_log`,参照 `biz_material_stock_log` 结构。
**理由**:
- 变动记录是独立的关注点,不应混在目录表中
- 需要快照字段(code/name)和 before/after 库存
- 需要溯源字段(source_type、step_id、task_id、task_no)
- 参照 `biz_qc_material_usage` 的 source_type 模式:manual_in / manual_out / step_save
**关键设计**:参照质检物料采用正负数表示方向(入库正、出库负),同时保留 `change_type` 字段(in/use)。
### Decision 3: 步骤保存 diff 结算算法
**选择**:全量回退 + 重算模式(参照质检物料的 revert + deduct 模式)。
**算法**:
1. 查出该步骤当前所有 source_type=step_save 的变动记录
2. 按变动记录逐条回退库存(加回扣减量),软删变动记录
3. 遍历新的步骤耗材/试剂列表,按 actual_usage 扣减库存,生成新变动记录
4. 整体在同一事务中
**理由**:
- 步骤保存频率不高,全量回退+重算简单可靠
- 避免复杂的逐项 diff 计算(需处理编码变更等边界情况)
- 与质检物料 deduct_for_task() 模式一致,代码可复用
**替代方案**:逐项 diff(旧用量 - 新用量 = 差额)。放弃原因:需处理编码变更(物料A改成物料B)、处理删除、新增等复杂场景,容易出 bug。全量回退更简单且已验证。
### Decision 4: 变动记录子弹窗 + Tab 双入口
**选择**:
- 每行操作列「变动记录」按钮 → Dialog 弹窗,按 material_id 筛选
- 页面顶部 Tab「全部变动记录」→ Tab 切换视图,展示所有物料的汇总记录
**理由**:
- 不新增菜单位,保持生产管理菜单简洁
- 行按钮满足"看某个物料历史"的快速需求
- Tab 视图满足"看所有变动流水"的审计需求
### Decision 5: 挂钩点在 replace_step_reagents/consumables
**选择**:在 `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
```
## Risks / Trade-offs
### Risk: 步骤保存时库存不足
**影响**:任务执行保存步骤时,若耗材/试剂库存不足,保存会失败。
**缓解**:提供清晰的错误提示("物料「XX」库存不足,当前库存 N,需使用 M"),让用户先去入库。同时前端可在步骤编辑时显示当前库存量供参考。
### Risk: actual_usage 为空或非数字
**影响**:步骤保存时 actual_usage 字段可能为空字符串或非数字。
**缓解**:diff 结算时跳过 actual_usage 为空或无法转为正数的条目,仅处理有效数据。
### Risk: 并发保存同一物料库存
**影响**:多个步骤同时保存涉及同一耗材/试剂。
**缓解**:使用 `with_for_update()` 行锁,与质检物料一致。
### Trade-off: 全量回退 vs 逐项 diff
**选择**全量回退,牺牲少量性能换取代码简洁性和正确性保证。步骤保存频率低,性能影响可忽略。
## Migration Plan
1. **数据库迁移**:ALTER TABLE 加字段(有默认值) + CREATE TABLE 建变动记录表
2. **后端部署**:模型 → CRUD → API 顺序部署
3. **前端部署**:扩展现有页面
4. **无需数据迁移**:现有耗材/试剂的 stock_qty 默认为 0,warning_qty 默认为 0,status 默认为 '1'
5. **回滚方案**:ALTER TABLE 删除新增字段,DROP TABLE 变动记录表,回滚代码