- 将文档从代码审计任务转换为端到端业务回归测试链路 - 重新组织文档结构为链路总览、示例数据基线和详细步骤 - 添加完整的业务场景清单涵盖WMS/MES/工位终端三大系统 - 定义统一的测试数据包括产品型号、物料清单、工位派工等 - 提供详细的步骤断言和数量等式验证方法 - 建立贯穿全链路的数据流向和状态变更追踪体系
20 KiB
库存查询重构 + 来料检验修复 · 最优方案(评审稿)
范围:WMS 库存查询页重构、WMS↔MES 数据交换定调、MES 排产支撑视图、来料检验三问题修复。 原则:一次做干净,不打补丁、不留旧口径;改 schema 走 ent 重生成 + db.go applyColumnPatches 幂等 DDL;改前端必须 npm run build + go build 重编 exe。
0. 数据交换方式(架构定调,先解决"谁拉谁、看什么")
现状(实读代码)
- WMS 库存页 onMounted →
GET /api/stock/producible→ WMSmesclient.FetchProducible→ MES/api/internal/producible→ MESComputeProducible(读 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 可用库存」对比「日排产需求速率」→ 可生产套数 + 还能支撑到哪天/多少天。
落地动作
- 可生产套数从 WMS 移除,迁到 MES 新视图(见 §A2)。
- WMS 保留
material_demand(ledgerState备料四态预警仍用 future5Qty),但喂数改为专职拉「排产需求」;删除producible_snapshot表 +queryProducibleHandler+FetchProducible的 items 分支(彻底清理旧库旧代码)。 - MES 侧
ComputeProducible复用,新增 MES 用户态接口 + 前端页(见 §A2)。
A. 库存查询重构
A1. 三 Tab 维度归位(根治"质量状态被当拆行维度")
现状三 Tab:物料汇总 / 库存明细(物料×区域×质量拆行) / 区域汇总(区域×质量×类型拆行)。
问题:aggregateStock 分组键含 QualityStatus、buildZoneSummary 分组键含 quality+type,导致同一物料/区域被质量、类型拆成多行,用户误以为重复。
方案:每个 Tab 只负责一个主维度,质量/类型降为"列"或"标签",不做拆行维度。
| Tab(新) | 主维度(一行=一个) | 质量怎么放 | 类型怎么放 |
|---|---|---|---|
| 物料汇总 | 物料编码 | 合格/未检/不合格 三列数量(现状已是列,保留) | 管理粒度列(结构件/电气件/其他) |
| 库位明细(原"库存明细"改名) | 物料 × 库位(区域/货架/层/位置) × 批次/SN | 质量作列(每行一个质量状态标签),不进分组键 | 管理粒度列 |
| 区域汇总 | 区域编码(一区域一行) | 合格/未检/不合格 三列数量 | 结构件/电气件/其他 三列数量 |
改动要点:
aggregateStock(stock.go:227-258)分组键stockKey去掉 QualityStatus,改为物料+区域+货架+层+位置+管理粒度;质量分布改成聚合列(合格/未检/不合格数量)。buildZoneSummary(stock.go:685-778)一区域一行:数量、可用量、锁定量、质量三列、类型三列;去掉"区域创建时间",保留"最近入库时间"(可改"最近变动时间")。- 前端 Inventory.vue 三张表列头按上表重排。
A2. 可生产数量 → 迁出 WMS,MES 新建「排产支撑」视图
WMS 侧(删)
- 删 Inventory.vue:272-299 可生产数量卡片 +
loadProducible。 - 删
producible.goqueryProducibleHandler、routes 的/api/stock/producible、producible_snapshotschema + ent 文件、db.go 相关 DDL。
MES 侧(新增"排产支撑"页)
- 后端:新增用户态接口
GET /api/v1/production/producible-support,复用ComputeProducible,返回每个成品:可生产套数、短板物料、支撑天数/支撑到哪天。 - 支撑天数算法(最优:按日排产逐日消耗):取 WMS 可用量 avail,按
daily_plan从今天起逐日扣减当日需求(台数×单台用量),直到某物料不足 → 支撑天数 = 能满产的完整天数;并给出"最先告罄的短板物料"。简化兜底:floor(avail / 日均需求)。 - 前端:MES 新增菜单/路由
排产支撑(router/index.js + MainLayout 菜单 + 新ProducibleSupport.vue),成品分页展示(分页/懒加载,解决"内存炸弹":只算启用成品、按需分页,不再全量无分页)。
A3. WMS 新建「缺料补货」视图(WMS 最该知道:该进什么料)
- 数据来源:WMS 拉 MES「排产需求量」(按物料,可带日期窗口,如未来5天/逐日);对比 WMS 本地可用库存(合格可用,口径同出库门禁
QStatusPass)。 - 输出每物料一行:排产需求量、当前可用量、缺口量(=需求-可用,>0 才列)、安全库存、建议采购量、告罄日(结合逐日需求)。
- 与现有
shortageHandler(stock.go:1074 仅按安全库存)区分:安全库存缺货(常规补货)vs 排产缺料(按订单需求)两者并列,缺料补货视图以"排产缺料"为主、安全库存为辅。 - 前端:库存页新增 Tab「缺料补货」或独立菜单;复用/扩展
material_demand表存拉取到的排产需求。 - 交换实现:
mesclient新增FetchMaterialDemand(ctx)→ MES/api/internal/material-demand(由computeFuture5Demand逻辑扩展为可传日期窗口/逐日)。
A4. 库位明细加"库位筛选"(区域→货架→层→位置 联动)
- 现状 Inventory.vue:319-339 明细只有"区域"筛选。
- 方案:复用区域维护/入库页的四级联动下拉(
/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),现混在"批次(结构件)"里,无法单独识别/筛选。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),每对象数量失真。- InspectionRecord 无独立"不合格数"字段,只有 inspect_qty/pass_qty。
数据模型
InspectionRecord增字段reject_qty(不合格数,默认0)。schema 改 + ent 重生成(WMS:go run -tags entgenerate ./tools/generate.go)+ db.goapplyColumnPatches幂等加列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改造为逐对象结果提交 —— bodyitems:[{targetId,status,inspectQty,passQty,rejectQty,disposalType,returnTrackingNo,...}],每条按自身数量写记录、按自身处置翻状态(修复"所有记录同数量"bug)。保留一次事务原子提交。
列表/导出
- 检验记录列表 + xlsx 导出(inspection.go:419 headers)增加"不合格数"列。
- 记录页明确展示:对象(批次/SN)、结论、检验数/合格数/不合格数、处置方式,做到"哪个 SN 不合格、对应哪条记录"一目了然(每 SN 一条记录,本就可追溯;配合逐个判定后完全对齐)。
B4. 结构件 vs 电气件不合格的口径(在帮助文档写清)
- 结构件(批次):一行 qty=N,判不合格=整批隔离;"N 里坏 M 个"用部分入库填合格数 N-M,系统拆 (N-M)合格 + M不合格(-NG 批次)。
- 电气件(SN)/其他:逐个判定,每个 SN/件一条记录、一行库存,选中判不合格即隔离该件,无需拆分。
- 更新
helpInspection(help.js)说明两者差异与不合格数口径。
C. 施工顺序与构建(避免遗漏)
- 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)。 - WMS 后端:stock.go 三 Tab 维度归位 + 库位/itemType 筛选 + 缺料补货 + 删 producible;inspection.go 逐个判定 + pending + reject_qty;mesclient 加 FetchMaterialDemand;routes 增删。
- MES 后端:
/api/internal/material-demand(供 WMS 拉);/api/v1/production/producible-support(供 MES 前端,含支撑天数)。 - WMS 前端:Inventory.vue 三 Tab 重构 + 缺料补货 + 库位筛选 + 不合格视图 + 导出改名;Inspection.vue 目标类型加"其他" + 待检清单 Tab + 逐个判定交互。
- MES 前端:新增 ProducibleSupport.vue + 路由 + 菜单。
- 构建:
- 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 用
;不用&&。
- WMS 前端
D. 口径已定案(采纳评审建议,本轮按此实现)
- 支撑天数:逐日排产消耗为主 —— 有排产的日期按
daily_plan当日需求逐日扣减 WMS 可用量;排产只排了 N 天、第 N+1 天起无排产时,用「最近3天平均日需求」外推兜底,直到某物料告罄。输出"支撑天数 + 支撑到哪天 + 最先告罄短板物料"。 - 缺料补货分两列,不合并(合并会掩盖两种性质不同的缺料):
- 列A「安全库存补货量」= 安全库存 − 可用量(常规补货,>0 才列)
- 列B「排产缺料量」= 排产需求 − 可用量(订单驱动紧急补料,>0 才列)
- 「在途量」当前无数据源,列留空显示"—",不纳入计算(不臆造)。
- 待检清单 = 独立 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)。待检清单勾选带入录入页时,归属类型/归属编号一并从入库单带入(可手改),检验记录归属与入库单归属保持一致,避免二次手抄。录入页归属字段本身无需改(已符合决策)。
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 一个调用方。body 由 {targetIds:[],status,inspectQty,passQty,...} 改为逐对象结果 {items:[{targetId,status,inspectQty,passQty,rejectQty,disposalType,returnTrackingNo,ownershipType,ownershipNo,...}]},同步改唯一前端调用方;不加版本号、不留旧接口(符合"不兼容妥协、彻底清理"原则)。
F. 决策已定案(2026-09-21 用户拍板,本方案定稿)
- 缺料补货入口 = 库存页新增 Tab「缺料补货」,与物料汇总/库位明细/区域汇总并列。
- 拉取时机 = 打开页面实时拉一次(同现状 producible 口径),不做定时同步,保持 WMS/MES 两系统无定时耦合。
- 死接口
/api/inspection/create(createInspectionHandler)= 删除(连同其路由;实施前再全仓 grep 确认无内部/MES 调用)。 - 待检清单分组粒度 = 按入库单为主行、展开看该单下批次/SN 明细(见 §E2)。
方案至此定稿,无遗留待决项。实施严格按 §C 顺序:schema→ent 重生成→db.go 幂等 DDL(含 §E7 回填)→WMS 后端→MES 后端→WMS 前端→MES 前端→帮助文档(§E5)→两侧 npm build + go build。改前端必须重编 exe(go:embed)。