## Context ### 目标模型(与质检物料库对称) ``` 质检域 生产域(本期目标) ──────── ──────────────── 【质检物料库】 【生产物料库】 biz_qc_material biz_production_material (+ material_type) └ stock_batch └ stock_batch └ usage (流水) └ usage (流水) └ stock_check └ stock_check 【我的物料领用记录】 【我的物料领用记录】 ``` **material_type** 枚举(租户内字典或固定码表): | 值 | 含义 | 原表 | |----|------|------| | `reagent` | 试剂 | biz_reagent | | `consumable` | 耗材 | biz_consumable | ### 为何融合 - 批次、领用、盘点、变动记录 **同一套 CRUD/API/UI**,仅多一个类型维度 - 与 QC「一个物料库」思路一致,降低培训与维护成本 - 试剂/耗材分表导致重复实现(两套 batch、两套 check、两个「我的」菜单) ### 仍与质检分离 - 质检物料用于检测流程;生产物料用于培养/生产步骤 — **权限与菜单不同** - **禁止**合并 `biz_qc_material` 与 `biz_production_material` 为一张表 ## Goals / Non-Goals **Goals:** - 一个【生产物料库】页面 + 一个【我的物料领用记录】菜单 - material_type 区分试剂/耗材;列表/变动/盘点均可按类型筛选 - 批次 + 领用 + 工单登记 + 月末盘点(同 QC) - 迁移 consumable/reagent 历史数据;废弃耗材包 - 生产工单步骤保留试剂/耗材 Tab,共用领用 API **Non-Goals:** - 不合并质检物料库 - 不合并生产步骤子表为单行(`step_reagent` / `step_consumable` 可保留,仅目录统一) - 盘点首版不调账 - 不物理删除 biz_consumable / biz_reagent 表(迁移后只读) ## Decisions ### Decision 1: 统一表命名 `biz_production_material*` **选择**:新建 `production_material` 系列表,结构 **拷贝 QC 表设计** + `material_type` 字段。 **理由**:与 `qc_material.py` 一一对应,后端可复用 CRUD 模式;避免继续维护 consumable/reagent 双份 batch/check。 ### Decision 2: material_type 落点 | 层级 | material_type | |------|----------------| | 物资目录 `biz_production_material` | **必填** | | 批次 / 流水 / 盘点快照 | 冗余快照 `material_type`(便于列表筛选,与 material_code 一并复制) | 编码唯一性:**租户 + material_type + material_code**(允许试剂与耗材编码相同但类型不同)。 ### Decision 3: 菜单与页面 | 旧 | 新 | |----|-----| | 耗材管理、试剂管理 | **【生产物料库】** → 挂在 **【生产基础信息】**(**已确认**;替换原耗材/试剂管理入口,`parent_id=PRB00000000000000000000000000001`) | | 我的耗材领用 + 我的试剂领用 | **【我的物料领用记录】** → 挂在 **【生产管理】**(与「我的生产任务」同级,执行侧查阅) | 页面三 Tab:**批次列表 | 变动记录 | 库存盘点**(复制 `qc-material/index.vue` 结构)。 ### Decision 4: 生产工单步骤 UI **选择**:保留 **试剂 Tab / 耗材 Tab**(工艺步骤已有分列习惯),但: - 领用下拉调用 `GET /production-material-requisition-options?materialType=reagent|consumable` - 保存仍写各自 step 子表 + 统一 `biz_production_material_usage`(step_save) **替代方案**:合并为单「物料」Tab — 放弃,改动工艺对照成本高。 ### Decision 5: 领用与 step_save(同前) 库存仅在 manual_out(按 batch)扣减;step_save 关联 parent_usage_id,不扣 stock_qty。 ### Decision 6: 数据迁移 1. INSERT `biz_production_material` FROM consumable(type=consumable)+ reagent(type=reagent) 2. 期初 batch:对 migrated 且 stock_qty>0 生成 INIT 批次 3. 旧 stock_log 可迁移到 `production_material_usage` 或保留旧表只读(实现时 **新流水只写新表**) 4. 步骤/工艺快照:`reagent_code` / `consumable_code` 通过 **material_type + code** 关联新目录 ### Decision 7: 旧 API 策略 `GET /consumables`、`GET /reagents`:**只读兼容** 1 个版本(内部转查 production_material + type 过滤),POST/PUT/DELETE 返回 410 并提示使用生产物料库。 ### Decision 8: 耗材包 同前:UI/API 下线;原因同批次管理。 ## Risks / Trade-offs | 风险 | 缓解 | |------|------| | 迁移编码冲突(同码异型) | 唯一键含 material_type;冲突则迁移脚本加前缀 | | 范围大(融合+批次+盘点+领用) | tasks 分 Phase;先 library+migration,再 batch,再 requisition,再 check | | 步骤双 Tab 与统一库认知 | UI 文案说明「类型由 Tab 决定,领用记录已过滤」 | ## Open Questions | # | 问题 | 建议 | |---|------|------| | Q1 | 【生产物料库】挂「生产管理」还是「生产基础信息」 | **已确认:生产基础信息** | | Q2 | material_type 是否走数据字典 | **是**,dict_type=`production_material_type` | | Q3 | 旧 consumable/reagent 菜单是否保留隐藏入口 | **否**,直接隐藏,仅保留路由 redirect 可选 |