← 回作品列表

晶片商 A 議題追蹤平台

Chip Vendor A Issue Tracker

把供應商週期性回報的 issue 從 Outlook / Excel 手動流程,工程化為可查詢、可篩選、可維護的內部 web 平台,串成 Outlook → Excel → 正規化 → MySQL upsert → 看板的 ETL 連續體。

data-platform ETLMySQLFlaskDataTablesVault 原始碼:私有

問題現場

每隔一段時間,晶片供應商就用 Email 夾一份 Excel,回報一批 issue。原本就是有人收信、開 Excel、自己比對——這樣其實沒什麼不對,直到你想查點東西。

痛點很具體:沒有單一可查詢的來源。要查「某顆晶片的某類問題現在什麼狀態」得翻信箱、翻多份 Excel;要做趨勢、要篩選、要長期維護幾乎不可能;換人接手就得重新熟悉一遍別人的 Excel 排版習慣。

最小技術背景

  • ETL:把資料從來源抽出來(Extract)、整理成統一格式(Transform)、再存進資料庫(Load)。
  • upsert:寫入資料庫時,「有就更新、沒有就新增」,用一個 key 判斷是否同一筆,藉此天然去重。
  • DataTables:前端表格元件,提供搜尋、排序、分頁。
  • filter text / display text:同一欄可以有「畫面顯示的字」和「拿來篩選比對的字」兩種用途——把它們分開,才不會互相污染。

系統架構與資料流

flowchart LR
  OUT["Outlook 信件"] --> EX["Excel 附件"]
  EX --> ETL["ETL|抽取 + 正規化"]
  ETL --> UP["MySQL upsert|以 key 去重"]
  UP --> WEB["Flask + DataTables 看板"]
  WEB --> USER["可查詢 / 篩選 / 維護"]

關鍵設計決策(含取捨)

決策選了什麼否決的替代為什麼
流程模型串成一條 ETL 連續體,每站職責分明每次手動處理一份 Excel否決:查不了、累積不起來、也沒法長期維護
篩選語意顯示文字與篩選文字分離直接拿顯示字去篩否決:畫面要顯示的字、跟拿來比對的字,會互相污染
比對方式精準比對(exact match)子字串比對(contains)否決:篩 Open 會把 Open - Pending 一起撈出來
設定管理ETL 與 Web 共用同一份 DB 連線設定兩邊各抄一份否決:兩份設定遲早各走各的,難維護

代表性技術證據

顯示與篩選分離(pseudo-code,示意)

row = {
    "status_display": "Open - Pending",   # 畫面上看到的那個字
    "status_filter":  "Open - Pending",   # 拿來篩選比對的,跟顯示的分開存
}

def matches(row, query):
    return row["status_filter"] == query  # 整個對起來才算,不是用 contains 比子字串
# 所以篩 "Open",不會把 "Open - Pending" 一起撈進來

ETL 去重(pseudo-code,示意)

# 拿 (來源, issue_id) 當 key,重跑只會更新,不會多長出重複列
db.upsert("issues", key=["source", "issue_id"], row=normalized)

踩過的坑

欄位內容
症狀篩選 Open,結果跑出一堆 Open - Pending
初判(猜錯)第一個念頭是匯入的資料髒了
驗證檢查篩選邏輯,發現用的是子字串比對
根因filter 用 contains,前綴相同就誤命中
修法改成精準比對,並把顯示文字與篩選文字分離
預防加入「前綴相同的相似狀態」測試案例(Open vs Open - Pending

驗證方式

  • 去重:ETL 連跑兩次,資料庫列數不增加(upsert key 生效)。
  • 篩選:對相似前綴狀態做測試,確認精準比對不誤命中。
  • 設定:ETL 與 Web 取得的 DB 連線來自同一份設定(無第二份可漂移)。
  • 驗收標準:同一批 Email/Excel 重匯不產生重複;篩選結果與預期一致。

可複製 SOP:把週期性報表流程工程化

適用情境:定期以 Email / Excel 收到、需要長期查詢與維護的資料。

不適用情境:一次性、用完即丟的資料,不值得建 ETL。

前置條件

  • 找出每筆資料的唯一 key(去重與 upsert 都靠它)。
  • 一份共用的連線 / 設定來源,避免各模組各抄。

步驟

  1. 拆連續體:把「收信 → 抽附件 → 正規化 → 入庫 → 看板」每一站到底負責什麼,先一站一站講清楚。
  2. 正規化:把每個人各自的 Excel 排版習慣,收斂成同一組欄位。
  3. upsert 入庫:用 key 去重,讓你重跑幾次都安全。
  4. 分離顯示與篩選:畫面要顯示的字、跟拿來比對的字,各存一份。
  5. 精準比對:篩選一律用 exact match,別用 contains。

停損點

  • 重跑會長出重複列 → 停,先確認 key 與 upsert。
  • 篩選誤命中 → 停,檢查是不是又用了子字串比對。

驗收標準

  • 重匯不重複;篩選不誤命中;設定只有一份來源。

回滾:以「重跑零重複 + 篩選測試全綠」的版本為還原點。

可複製到:任何「定期收 Excel、要變成可查詢平台」的內部資料流。

決策回放(三個月後回讀用)

  • 背景:供應商週期性 issue 散在信箱與 Excel,需可查詢、可維護。
  • 限制:不可外流真實 issue 內容、供應商名與內部 DB 主機;沿用既有 Vault 取得 DB 機密。
  • 考慮過但放棄:每次都手動整理 Excel——被「累積不起來、難維護」否決。
  • 證據:upsert 去重、顯示/篩選分離、相似前綴篩選測試。
  • 未解:要不要跟晶片商 B 的 tracker 併成同一個資料平台家族。

作者備註: 這種案子最容易栽在小地方——不是架構,是「篩選到底拿哪個字去比」這種細節。Open 命中 Open - Pending 看起來很蠢,但真的會發生。