Files
DashBoard/openspec/changes/archive/2026-03-03-add-material-trace-page/design.md
egg 777751311c
Some checks failed
full-modernization-gates / frontend-route-governance (push) Has been cancelled
full-modernization-gates / backend-modernization-gates (push) Has been cancelled
released-pages-hardening-gates / released-pages-hardening (push) Has been cancelled
feat: add material trace page for bidirectional LOT/material query
Implement full-stack material trace feature enabling forward (LOT/工單 → 原物料)
and reverse (原物料 → LOT) queries with wildcard support, safeguards (memory guard,
IN-clause batching, Oracle slow-query channel), CSV export, and portal-shell integration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 17:32:41 +08:00

5.0 KiB
Raw Blame History

Context

工程師需要查詢 LOT/工單對應的原物料消耗記錄,以及反向從原物料批號追溯使用該批料的所有 LOT。目前原物料資訊只能在 Query Tool 的 LotDetail "原物料" tab 逐筆查看(透過 /api/trace/events?domains=["materials"]),不支援批量輸入或反向查詢。

資料來源 DWH.DW_MES_LOTMATERIALSHISTORY 有 1800 萬筆記錄,已建立四個索引:

  • IDX1: CONTAINERID(正向 LOT 查詢)
  • IDX2: PJ_WORKORDER(正向工單查詢)
  • IDX3: MATERIALPARTNAME(料號,本次不使用)
  • IDX4: MATERIALLOTNAME(反向原物料批號查詢)

站群組WORKCENTER_GROUP對應由 filter_cache.get_workcenter_mapping() 提供,從 DW_MES_SPEC_WORKCENTER_V 載入,每小時刷新。

Goals / Non-Goals

Goals:

  • 提供獨立頁面支援正向LOT ID / 工單 → 原物料)和反向(原物料批號 → LOT雙向查詢
  • 正向查詢支援 LOT ID 和工單兩種輸入模式切換
  • 支援多筆輸入(換行/逗號分隔)
  • 結果含站群組篩選、分頁、CSV 匯出
  • 使用既有 Oracle 索引,查詢效率可控

Non-Goals:

  • 不支援 MATERIALPARTNAME料號反向查詢資料量風險過高同一料號可能數萬筆
  • 不需日期範圍篩選(以 LOT/工單/原物料批號為查詢條件即可)
  • 不做 Redis 快取或 BatchQueryEngine 分片(查詢範圍由輸入筆數控制,非時間範圍)
  • 不做 BOM 對照或原物料品質統計

Decisions

D1: 使用 read_sql_dfpooled connection而非 read_sql_df_slow

決定: 查詢使用 pooled connectionread_sql_df),不走 slow query path。

理由: 此查詢依賴索引命中,預期回應時間 < 5s。不像 reject-history 的全表掃描需要 dedicated connection。正向查詢最多幾千筆結果反向查詢設結果上限 10,000 筆。

替代方案: 使用 read_sql_df_slow為何不採用: 佔用 slow query semaphore 會排擠需要長時間執行的查詢reject-history、resource-history

D2: 正向查詢先解析 LOT ID → CONTAINERID

決定: LOT ID 輸入模式需要先將 CONTAINERNAME 轉換為 CONTAINERID16-char hex因為 LOTMATERIALSHISTORY 的索引是 CONTAINERID。使用 DW_MES_CONTAINER 做 batch lookup。工單模式直接查 PJ_WORKORDER 索引,不需轉換。

理由: 使用者輸入的是可讀的 LOT 名稱(如 GA25060001-A01但資料表索引是 CONTAINERID。直接 JOIN 會讓 optimizer 可能選擇低效計畫。先 batch resolve 再用 IN clause 更可預測。

替代方案: SQL 內直接 JOIN CONTAINER 表。 為何不採用: 對於多筆 LOT 輸入兩步驟resolve + query的執行計畫更穩定且 resolve 結果可重用於顯示。

D3: 站群組篩選在後端 enrichment 而非 SQL WHERE

決定: SQL 查詢不加 WORKCENTERNAME 過濾。查詢結果回來後,後端用 get_workcenter_mapping() 對每列添加 WORKCENTER_GROUP 欄位,前端可做篩選。若使用者選了站群組篩選,後端先 resolve 站群組 → WORKCENTERNAME 清單,再在 SQL 加 AND WORKCENTERNAME IN (...) 過濾。

理由: 如果不篩選使用者能看到所有站點的資料含站群組欄位。如果篩選了SQL 層就縮減結果集,減少傳輸和分頁壓力。

D4: 反向查詢結果數上限 10,000 筆

決定: 反向查詢(原物料批號 → LOT加入 FETCH FIRST 10001 ROWS ONLY 上限。若回傳超過 10,000 筆,前端顯示警告「結果超過上限,請縮小查詢範圍」。

理由: 一批常用原物料可能被上千個 LOT 使用。無上限的反向查詢可能回傳數萬筆,壓垮前端和 Oracle 連線。10,000 筆足以覆蓋絕大多數場景。

D5: 前端頁面結構沿用 Vite multi-page 模式

決定: 新增 frontend/material-trace.html + frontend/src/material-trace/App.vue 作為獨立 Vite entry point。沿用 reject-history 的單檔 App.vue + 子元件模式。

理由: 專案的所有查詢頁面reject-history、hold-history、resource-history都是獨立 Vite entry。統一架構。

D6: 輸入筆數上限

決定: 正向查詢LOT ID / 工單)輸入上限 200 筆,反向查詢(原物料批號)輸入上限 50 筆。

理由: 正向查詢每筆 LOT 平均產生 10-50 筆原物料記錄200 筆 LOT 最多 10,000 筆結果。反向查詢每批原物料可能對應 100-1000 個 LOT50 批已有碰上 10,000 筆上限的風險。

Risks / Trade-offs

  • [低] CONTAINERID resolve 多一次 round-trip — LOT ID 模式需先查 DW_MES_CONTAINER 轉換。→ Container 表有 CONTAINERNAME 索引batch IN query 很快(< 1s
  • [低] 站群組 mapping 可能未涵蓋所有 WORKCENTERNAMEDW_MES_SPEC_WORKCENTER_V 可能缺少新站點。→ 未映射的站點在結果中站群組欄位顯示空值,不影響查詢結果。
  • [中] 反向查詢結果截斷 — 10,000 筆上限可能截斷大量使用的原物料批號結果。→ 前端明確顯示截斷警告,引導使用者縮小範圍。