- 将文档从代码审计任务转换为端到端业务回归测试链路 - 重新组织文档结构为链路总览、示例数据基线和详细步骤 - 添加完整的业务场景清单涵盖WMS/MES/工位终端三大系统 - 定义统一的测试数据包括产品型号、物料清单、工位派工等 - 提供详细的步骤断言和数量等式验证方法 - 建立贯穿全链路的数据流向和状态变更追踪体系
212 lines
20 KiB
Markdown
212 lines
20 KiB
Markdown
# 库存查询重构 + 来料检验修复 · 最优方案(评审稿)
|
||
|
||
> 范围:WMS 库存查询页重构、WMS↔MES 数据交换定调、MES 排产支撑视图、来料检验三问题修复。
|
||
> 原则:一次做干净,不打补丁、不留旧口径;改 schema 走 ent 重生成 + db.go applyColumnPatches 幂等 DDL;改前端必须 npm run build + go build 重编 exe。
|
||
|
||
---
|
||
|
||
## 0. 数据交换方式(架构定调,先解决"谁拉谁、看什么")
|
||
|
||
### 现状(实读代码)
|
||
- WMS 库存页 onMounted → `GET /api/stock/producible` → WMS `mesclient.FetchProducible` → MES `/api/internal/producible` → MES `ComputeProducible`(读 BOM + 反向拉 WMS `/api/internal/stock/check` 可用量)→ 算「可生产套数 + 未来5天需求」→ 回 WMS 落 `producible_snapshot` + `material_demand` 两张快照表。
|
||
- 问题:**可生产套数是 MES 视角,却显示在 WMS 库存页**;一次拉取把两种诉求混在一起;WMS 侧无分页全量展示所有成品。
|
||
|
||
### 真源与方向(定调)
|
||
| 数据 | 真源 | 谁缺 | 交换方向 |
|
||
|---|---|---|---|
|
||
| 库存可用量(合格可用) | WMS | MES 缺 | MES 拉 WMS `/api/internal/stock/check`(已有 `StockAvailable`) |
|
||
| BOM 单台用量 + 日排产 | MES | WMS 缺 | WMS 拉 MES「物料排产需求量」 |
|
||
|
||
**核心:每个系统只拉自己缺的原始数据,各自算各自视角的结论,不再互相代算对方的展示指标。**
|
||
|
||
- **WMS 视角 = 缺料补货**:WMS 用「MES 排产需求量」对比「本地可用库存」→ 缺什么料、缺多少、该进什么料。
|
||
- **MES 视角 = 排产支撑**:MES 用「WMS 可用库存」对比「日排产需求速率」→ 可生产套数 + 还能支撑到哪天/多少天。
|
||
|
||
### 落地动作
|
||
1. **可生产套数从 WMS 移除**,迁到 MES 新视图(见 §A2)。
|
||
2. WMS 保留 `material_demand`(`ledgerState` 备料四态预警仍用 future5Qty),但**喂数改为专职拉「排产需求」**;删除 `producible_snapshot` 表 + `queryProducibleHandler` + `FetchProducible` 的 items 分支(彻底清理旧库旧代码)。
|
||
3. MES 侧 `ComputeProducible` 复用,新增 MES 用户态接口 + 前端页(见 §A2)。
|
||
|
||
---
|
||
|
||
## A. 库存查询重构
|
||
|
||
### A1. 三 Tab 维度归位(根治"质量状态被当拆行维度")
|
||
|
||
现状三 Tab:物料汇总 / 库存明细(物料×区域×质量拆行) / 区域汇总(区域×质量×类型拆行)。
|
||
问题:`aggregateStock` 分组键含 `QualityStatus`、`buildZoneSummary` 分组键含 `quality+type`,导致**同一物料/区域被质量、类型拆成多行**,用户误以为重复。
|
||
|
||
**方案:每个 Tab 只负责一个主维度,质量/类型降为"列"或"标签",不做拆行维度。**
|
||
|
||
| Tab(新) | 主维度(一行=一个) | 质量怎么放 | 类型怎么放 |
|
||
|---|---|---|---|
|
||
| 物料汇总 | 物料编码 | 合格/未检/不合格 **三列数量**(现状已是列,保留) | 管理粒度列(结构件/电气件/其他) |
|
||
| 库位明细(原"库存明细"改名) | 物料 × 库位(区域/货架/层/位置) × 批次/SN | 质量作**列**(每行一个质量状态标签),**不进分组键** | 管理粒度列 |
|
||
| 区域汇总 | 区域编码(一区域一行) | 合格/未检/不合格 **三列数量** | 结构件/电气件/其他 **三列数量** |
|
||
|
||
改动要点:
|
||
- `aggregateStock`([stock.go:227-258](file:///d:/hardman/bj_power/bj_power_wms/internal/handler/stock.go#L227-L258))分组键 `stockKey` **去掉 QualityStatus**,改为 `物料+区域+货架+层+位置+管理粒度`;质量分布改成聚合列(合格/未检/不合格数量)。
|
||
- `buildZoneSummary`([stock.go:685-778](file:///d:/hardman/bj_power/bj_power_wms/internal/handler/stock.go#L685-L778))**一区域一行**:数量、可用量、锁定量、质量三列、类型三列;**去掉"区域创建时间"**,保留"最近入库时间"(可改"最近变动时间")。
|
||
- 前端 [Inventory.vue](file:///d:/hardman/bj_power/bj_power_wms/frontend/src/pages/Inventory.vue) 三张表列头按上表重排。
|
||
|
||
### A2. 可生产数量 → 迁出 WMS,MES 新建「排产支撑」视图
|
||
|
||
**WMS 侧(删)**
|
||
- 删 [Inventory.vue:272-299](file:///d:/hardman/bj_power/bj_power_wms/frontend/src/pages/Inventory.vue#L272-L299) 可生产数量卡片 + `loadProducible`。
|
||
- 删 `producible.go` `queryProducibleHandler`、routes 的 `/api/stock/producible`、`producible_snapshot` schema + ent 文件、db.go 相关 DDL。
|
||
|
||
**MES 侧(新增"排产支撑"页)**
|
||
- 后端:新增用户态接口 `GET /api/v1/production/producible-support`,复用 `ComputeProducible`,返回每个成品:可生产套数、短板物料、**支撑天数/支撑到哪天**。
|
||
- **支撑天数算法(最优:按日排产逐日消耗)**:取 WMS 可用量 avail,按 `daily_plan` 从今天起逐日扣减当日需求(台数×单台用量),直到某物料不足 → 支撑天数 = 能满产的完整天数;并给出"最先告罄的短板物料"。简化兜底:`floor(avail / 日均需求)`。
|
||
- 前端:MES 新增菜单/路由 `排产支撑`([router/index.js](file:///d:/hardman/bj_power/bj_power_mes/frontend/src/router/index.js) + MainLayout 菜单 + 新 `ProducibleSupport.vue`),成品分页展示(**分页/懒加载,解决"内存炸弹"**:只算启用成品、按需分页,不再全量无分页)。
|
||
|
||
### A3. WMS 新建「缺料补货」视图(WMS 最该知道:该进什么料)
|
||
|
||
- 数据来源:WMS 拉 MES「排产需求量」(按物料,可带日期窗口,如未来5天/逐日);对比 WMS 本地可用库存(合格可用,口径同出库门禁 `QStatusPass`)。
|
||
- 输出每物料一行:排产需求量、当前可用量、**缺口量(=需求-可用,>0 才列)**、安全库存、建议采购量、告罄日(结合逐日需求)。
|
||
- 与现有 `shortageHandler`([stock.go:1074](file:///d:/hardman/bj_power/bj_power_wms/internal/handler/stock.go#L1074) 仅按安全库存)区分:**安全库存缺货**(常规补货)vs **排产缺料**(按订单需求)两者并列,缺料补货视图以"排产缺料"为主、安全库存为辅。
|
||
- 前端:库存页新增 Tab「缺料补货」或独立菜单;复用/扩展 `material_demand` 表存拉取到的排产需求。
|
||
- 交换实现:`mesclient` 新增 `FetchMaterialDemand(ctx)` → MES `/api/internal/material-demand`(由 `computeFuture5Demand` 逻辑扩展为可传日期窗口/逐日)。
|
||
|
||
### A4. 库位明细加"库位筛选"(区域→货架→层→位置 联动)
|
||
|
||
- 现状 [Inventory.vue:319-339](file:///d:/hardman/bj_power/bj_power_wms/frontend/src/pages/Inventory.vue#L319-L339) 明细只有"区域"筛选。
|
||
- 方案:复用区域维护/入库页的四级联动下拉(`/zone/picker` 按 level+zoneCode+shelfNo 逐级取),明细查询参数增加 `shelfNo/layerNo/positionNo`;`aggregateStock` 增加对应 where(inventory 已有 `shelf_no/layer_no/position_no` 列,直接过滤,无需 join)。
|
||
|
||
### A5. 质量维度:独立"不合格品"视图 + 快捷筛选
|
||
|
||
- 现状找不合格品要在明细里逐列翻。
|
||
- 方案:库位明细/物料汇总提供"质量状态"快捷筛选(未检/合格/不合格);另加「不合格品」快捷入口(预设 quality=不合格 的明细视图),一屏定位"不合格在哪(物料/库位/批次/SN)"。
|
||
|
||
### A6. 细节清理
|
||
|
||
- **导出按钮统一命名"导出Excel"**(现状"导出物料汇总"/"导出"/"导出区域汇总"三种)。
|
||
- **"最近入库单"字段**:一个批次可能多次入库,"最近一单"误导 → 明细下钻里保留逐条入库单,汇总行去掉或改"首次入库时间"。
|
||
- 区域汇总去掉"区域创建时间"列(与库存无关)。
|
||
|
||
---
|
||
|
||
## B. 来料检验修复(三问题,按已确认决策)
|
||
|
||
### B1. 目标类型加"其他" + 按入库类型筛选(问题1,决策:两者都要)
|
||
|
||
**事实**:`item_type=4`(辅料/工装/试验设备,即"其他入库")建档时被**强制 manage_mode=1**([material.go:96-98](file:///d:/hardman/bj_power/bj_power_wms/internal/handler/material.go#L96-L98)),现混在"批次(结构件)"里,无法单独识别/筛选。inventory 表**无 item_type 列**(在 material 表)、**无 inbound_type 列**(在 inbound_order 表)。
|
||
|
||
**方案**
|
||
- 目标类型 radio 增第三项:**批次(结构件) / SN(电气件) / 其他(辅料·工装·试验设备)**。
|
||
- 拾取器/待检清单支持两类过滤:
|
||
- **按品类=其他**:过滤 `item_type=4`。因 inventory 无该列,走 **join material**(`materialCodesByItemType(4)` 取编码集,再 `MaterialCodeIn`);与现有 `materialCodesBySpec` 同套路。
|
||
- **按入库类型**:过滤 inbound_order.inbound_type(purchase/semi/finished/return/other),走 **join inbound_order by inbound_no**;待检清单接口支持 `inboundType` 参数。
|
||
- `aggregateStock`/`/stock/query` 增加 `itemType` 过滤参数(join material)。`resolveInspectionTarget` 无需改(其他类是 manage_mode=1,按 batchNo 已能命中)。
|
||
|
||
### B2. 新增"待检清单"视图(问题2,决策:新增视图)
|
||
|
||
- 来料检验页新增 Tab「待检清单」:列出 `quality_status=未检` 的库存行,可按 物料/入库类型/目标类型(结构件·电气件·其他) 筛选,分页。
|
||
- 每行带勾选 + "送检"按钮 → 勾选项带入录入表单"已选清单";检验提交后质量状态翻转,自动移出待检清单。
|
||
- 后端:新增 `GET /api/inspection/pending`(或复用 `/stock/query?qualityStatus=未检` + itemType/inboundType 过滤),返回未检库存行(含物料、库位、批次/SN、数量、入库类型)。
|
||
|
||
### B3. 逐个判定 + 不合格数(问题3,决策:逐个判定+不合格数)
|
||
|
||
**现状缺陷**
|
||
- 一次提交只能给所有选中编号**同一结论**,不能一屏内这个判合格、那个判不合格。
|
||
- `batch-flip` 多选时把**相同的 inspectQty/passQty 写进每条记录**([inspection.go:239-240](file:///d:/hardman/bj_power/bj_power_wms/internal/handler/inspection.go#L239-L240)),每对象数量失真。
|
||
- InspectionRecord **无独立"不合格数"字段**,只有 inspect_qty/pass_qty。
|
||
|
||
**数据模型**
|
||
- `InspectionRecord` 增字段 `reject_qty`(不合格数,默认0)。schema 改 + ent 重生成(WMS:`go run -tags entgenerate ./tools/generate.go`)+ db.go `applyColumnPatches` 幂等加列 `ALTER TABLE inspection_records ADD COLUMN IF NOT EXISTS reject_qty ...`。
|
||
- 校验口径:`检验数 = 合格数 + 不合格数`;`reject_qty = inspect_qty - pass_qty`(提交时后端复核,不信任前端)。
|
||
|
||
**录入交互(逐个判定)**
|
||
- **电气件(SN) / 其他**:已选清单每行一个"结论"单选(合格/不合格),一屏内逐个判定;每行独立写 inspect_qty=1、pass_qty=1/0、reject_qty=0/1。
|
||
- **结构件(批次)**:每行填 检验数/合格数,不合格数自动=差;判不合格选处置(部分入库 PARTIAL 拆 合格数入库 + 差额 NG 隔离,逻辑已存在于 `disposeInspectionHandler`)。
|
||
- 后端:`batch-flip` 改造为**逐对象结果**提交 —— body `items:[{targetId,status,inspectQty,passQty,rejectQty,disposalType,returnTrackingNo,...}]`,每条按自身数量写记录、按自身处置翻状态(修复"所有记录同数量"bug)。保留一次事务原子提交。
|
||
|
||
**列表/导出**
|
||
- 检验记录列表 + xlsx 导出([inspection.go:419](file:///d:/hardman/bj_power/bj_power_wms/internal/handler/inspection.go#L419) headers)增加"不合格数"列。
|
||
- 记录页明确展示:对象(批次/SN)、结论、检验数/合格数/不合格数、处置方式,做到"哪个 SN 不合格、对应哪条记录"一目了然(每 SN 一条记录,本就可追溯;配合逐个判定后完全对齐)。
|
||
|
||
### B4. 结构件 vs 电气件不合格的口径(在帮助文档写清)
|
||
- **结构件(批次)**:一行 qty=N,判不合格=整批隔离;"N 里坏 M 个"用**部分入库**填合格数 N-M,系统拆 (N-M)合格 + M不合格(-NG 批次)。
|
||
- **电气件(SN)/其他**:逐个判定,每个 SN/件一条记录、一行库存,选中判不合格即隔离该件,无需拆分。
|
||
- 更新 `helpInspection`([help.js](file:///d:/hardman/bj_power/bj_power_wms/frontend/src/help.js))说明两者差异与不合格数口径。
|
||
|
||
---
|
||
|
||
## C. 施工顺序与构建(避免遗漏)
|
||
|
||
1. **schema 改**:InspectionRecord 加 `reject_qty`;删 `producible_snapshot`。→ WMS ent 重生成(`go run -tags entgenerate ./tools/generate.go`,注意删残留 per-entity 文件含 where.go)+ db.go applyColumnPatches 幂等 DDL(加 reject_qty;producible_snapshot 旧表按需 DROP)。
|
||
2. **WMS 后端**:stock.go 三 Tab 维度归位 + 库位/itemType 筛选 + 缺料补货 + 删 producible;inspection.go 逐个判定 + pending + reject_qty;mesclient 加 FetchMaterialDemand;routes 增删。
|
||
3. **MES 后端**:`/api/internal/material-demand`(供 WMS 拉);`/api/v1/production/producible-support`(供 MES 前端,含支撑天数)。
|
||
4. **WMS 前端**:Inventory.vue 三 Tab 重构 + 缺料补货 + 库位筛选 + 不合格视图 + 导出改名;Inspection.vue 目标类型加"其他" + 待检清单 Tab + 逐个判定交互。
|
||
5. **MES 前端**:新增 ProducibleSupport.vue + 路由 + 菜单。
|
||
6. **构建**:
|
||
- WMS 前端 `cd d:\hardman\bj_power\bj_power_wms\frontend; npm run build` → `cd d:\hardman\bj_power\bj_power_wms; go build -o bj_power_wms.exe .`
|
||
- MES 前端 `cd d:\hardman\bj_power\bj_power_mes\frontend; npm run build` → `cd d:\hardman\bj_power\bj_power_mes; go build -o bj_power_mes.exe .`
|
||
- PowerShell 用 `;` 不用 `&&`。
|
||
|
||
## D. 口径已定案(采纳评审建议,本轮按此实现)
|
||
1. **支撑天数**:逐日排产消耗为主 —— 有排产的日期按 `daily_plan` 当日需求逐日扣减 WMS 可用量;**排产只排了 N 天、第 N+1 天起无排产时,用「最近3天平均日需求」外推兜底**,直到某物料告罄。输出"支撑天数 + 支撑到哪天 + 最先告罄短板物料"。
|
||
2. **缺料补货分两列,不合并**(合并会掩盖两种性质不同的缺料):
|
||
- 列A「安全库存补货量」= 安全库存 − 可用量(常规补货,>0 才列)
|
||
- 列B「排产缺料量」= 排产需求 − 可用量(订单驱动紧急补料,>0 才列)
|
||
- 「在途量」当前**无数据源**,列留空显示"—",不纳入计算(不臆造)。
|
||
3. **待检清单 = 独立 Tab**(量大需分页/筛选,不内嵌录入页)。
|
||
|
||
---
|
||
|
||
## E. 对 deepseek 复核意见的逐条核实(结合实际代码)
|
||
|
||
> deepseek 不看代码,以下逐条核实:采纳 / 已实现无需改 / 与你的原则冲突需纠正。
|
||
|
||
| deepseek 意见 | 核实结论 | 处理 |
|
||
|---|---|---|
|
||
| 补充1 归属字段要改造 | **已实现**:Inspection.vue 归属默认"其他"、命名"工单编号/科技项目号/其他"、归属编号手动输入不联动 MES | 无需改造;但见 §E1 归属应从入库单带入 |
|
||
| 补充2 待检清单按入库单分组 | 合理,契合你"来料检验根据入库管理检查"的原意 | **采纳**:见 §E2 |
|
||
| 补充3 录入页按入库单驱动、勾选带入 | 合理,是 B2 的强化 | **采纳**:见 §E2 |
|
||
| 补充4 scan_record 孤儿表 | 属 **MES 侧报工记录**改造,不在本轮(WMS 库存+来料检验)范围 | 标注排除,见 §E4 |
|
||
| 补充5 帮助文档同步更新 | 成立,原方案只提了 helpInspection | **采纳**:见 §E5 |
|
||
| D1/D2/D3 建议 | 均合理 | 已定案,见 §D |
|
||
| 注意1 join material 性能 | 方案已是"先查 material 取 item_type=4 编码集,再 IN 查 inventory",非逐行 join | **强调落实**:见 §E6 |
|
||
| 注意2 reject_qty 历史回填 | 成立 | **采纳**:见 §E7 迁移回填 |
|
||
| 注意3 batch-flip 接口兼容、加版本号/留旧接口 | **与你"不兼容妥协、不留旧代码"原则冲突**;且实测 `/inspection/batch-flip` 全仓仅 Inspection.vue 一个调用方 | **纠正**:干净改 body 结构 + 同步改唯一前端调用方,**不加版本、不留旧接口**,见 §E8 |
|
||
|
||
### E1. 归属从入库单自动带入(补充1 的正确落点)
|
||
来料检按入库单驱动,而入库单已存 `ownership_type/ownership_no`([inbound.go:164-165](file:///d:/hardman/bj_power/bj_power_wms/internal/handler/inbound.go#L164-L165))。待检清单勾选带入录入页时,**归属类型/归属编号一并从入库单带入**(可手改),检验记录归属与入库单归属保持一致,避免二次手抄。录入页归属字段本身无需改(已符合决策)。
|
||
|
||
### E2. 待检清单:按入库单分组 + 勾选带入录入页(补充2+3)
|
||
- 待检清单 Tab **以入库单为主行**(一张入库单一行:入库单号、入库类型、物料、数量、未检批次数/SN数、归属、入库时间),**展开看该单下的批次/SN 明细**(quality_status=未检 的行)。
|
||
- 勾选(整单或单条批次/SN)→「送检」带入录入页"已选清单",并自动回填 物料/归属/入库类型/检测单号等字段;**用户在录入页只需逐个判结论 + 填检验数/合格数**,实现"按入库单驱动、闭环"。
|
||
- 后端 `GET /api/inspection/pending` 返回按 inbound_no 分组的未检库存(join inbound_order 取 inbound_type/归属)。
|
||
|
||
### E3. 死接口清理(本轮新发现)
|
||
`/api/inspection/create`(`createInspectionHandler`)**前端无任何调用方**(录入只走 batch-flip)。按"彻底清理旧代码"原则,本轮改造 batch-flip 时**一并删除 createInspectionHandler + 其路由**,避免两个语义重叠的检验写入口并存。(实施前再全仓 grep 确认无内部/MES 调用。)
|
||
|
||
### E4. 范围排除声明(补充4)
|
||
**报工记录改造(MES 侧 scan_record 孤儿表、/scan/report、/scan/records、报工 Tab 改查 workpiece_process)不在本轮范围**,需单独一轮处理。本轮仅 WMS 库存查询重构 + WMS 来料检验修复 + 配套的 MES 排产支撑视图/物料需求接口。
|
||
|
||
### E5. 帮助文档同步(补充5)
|
||
界面改动同步更新帮助文档,避免用户看不懂:
|
||
- `helpInventory`:三 Tab 新维度解释(质量/类型降为列、库位明细四级库位、区域汇总一区域一行)。
|
||
- 新增「缺料补货」帮助:两列缺料口径、数据来源(拉 MES 排产需求 vs 本地可用)。
|
||
- 新增 MES「排产支撑」帮助:可生产套数/支撑天数算法口径。
|
||
- `helpInspection`:目标类型加"其他"、待检清单用法、逐个判定、不合格数口径、结构件 vs 电气件不合格差异(B4)。
|
||
|
||
### E6. itemType/inboundType 过滤走"子查询 IN"而非逐行 join(注意1)
|
||
`item_type=4`(其他入库物料):先 `material.Query().Where(ItemTypeEQ(4))` 取编码集(量小),再 `inventory.MaterialCodeIn(codes...)`;与现有 `materialCodesBySpec` 同套路,**不做逐行 join**,避免大数据量下变慢。按入库类型同理:先由 inbound_order 取符合 inbound_type 的 inbound_no 集,再 `inventory.InboundNoIn(...)`。
|
||
|
||
### E7. reject_qty 历史数据回填(注意2)
|
||
db.go applyColumnPatches 加列后,**回填历史行**:`UPDATE inspection_records SET reject_qty = inspect_qty - pass_qty WHERE reject_qty = 0 AND inspect_qty > pass_qty`(幂等,只补差异>0 的旧行),保证历史记录"不合格数"列不空白、口径一致。
|
||
|
||
### E8. batch-flip 干净改造,不做兼容(注意3 纠正)
|
||
实测 `/inspection/batch-flip` 全仓仅 [Inspection.vue:145](file:///d:/hardman/bj_power/bj_power_wms/frontend/src/pages/Inspection.vue#L145) 一个调用方。body 由 `{targetIds:[],status,inspectQty,passQty,...}` 改为**逐对象结果** `{items:[{targetId,status,inspectQty,passQty,rejectQty,disposalType,returnTrackingNo,ownershipType,ownershipNo,...}]}`,**同步改唯一前端调用方**;不加版本号、不留旧接口(符合"不兼容妥协、彻底清理"原则)。
|
||
|
||
---
|
||
|
||
## F. 决策已定案(2026-09-21 用户拍板,本方案定稿)
|
||
1. **缺料补货入口** = 库存页新增 Tab「缺料补货」,与物料汇总/库位明细/区域汇总并列。
|
||
2. **拉取时机** = 打开页面实时拉一次(同现状 producible 口径),**不做定时同步**,保持 WMS/MES 两系统无定时耦合。
|
||
3. **死接口 `/api/inspection/create`(createInspectionHandler)= 删除**(连同其路由;实施前再全仓 grep 确认无内部/MES 调用)。
|
||
4. **待检清单分组粒度** = 按入库单为主行、展开看该单下批次/SN 明细(见 §E2)。
|
||
|
||
> 方案至此定稿,无遗留待决项。实施严格按 §C 顺序:schema→ent 重生成→db.go 幂等 DDL(含 §E7 回填)→WMS 后端→MES 后端→WMS 前端→MES 前端→帮助文档(§E5)→两侧 npm build + go build。改前端必须重编 exe(go:embed)。
|