diff --git a/docs/DW_PJ_LOT_V_POWERBI_SQL.txt b/docs/DW_PJ_LOT_V_POWERBI_SQL.txt deleted file mode 100644 index fc8d9cb..0000000 --- a/docs/DW_PJ_LOT_V_POWERBI_SQL.txt +++ /dev/null @@ -1,60 +0,0 @@ -SELECT L.LOTID AS ""Run Card Lot ID"", - L.Workorder AS ""Work Order ID"", - L.Qty AS ""Lot Qty(pcs)"", - L.Qty2 AS ""Lot Qty(Wafer pcs)"", - L.Status AS ""Run Card Status"", - L.HOLDREASONNAME AS ""Hold Reason"", - L.CurrentHoldCount AS ""Hold Count"", - L.Owner AS ""Work Order Owner"", - L.StartDate AS ""Run Card Start Date"", - L.UTS, - L.Product AS ""Product P/N"", - L.Productlinename AS ""Package"", - L.Package_LEF as ""Package(LF)"", - L.PJ_FUNCTION AS ""Product Function"", - L.Pj_Type AS ""Product Type"", - L.BOP, - L.FirstName AS ""Wafer Lot ID"", - L.WAFERNAME AS ""Wafer P/N"", - L.WaferLot ""Wafer Lot ID(Prefix)"", - L.SpecName AS ""Spec"", - L.SPECSEQUENCE AS ""Spec Sequence"", - L.SPECSEQUENCE || '_' || L.SpecName AS ""Spec(Order)"", - L.Workcentername AS ""Work Center"", - L.WorkCenterSequence AS ""Work Center Sequence"", - L.WorkCenter_Group AS ""Work Center(Group)"", - L.WorkCenter_Short AS ""Work Center(Short)"", - L.WorkCenterSequence_Group AS ""Work Center Sequence(Group)"", - L.WorkCenterSequence_Group || '_' || L.WorkCenter_Group AS ""Work Center Group(Order)"", - L.AgeByDays AS ""Age By Days"", - L.Equipments AS ""Equipment ID"", - L.EquipmentCount AS ""Equipment Count"", - L.Workflowname AS ""Work Flow Name"", - L.Datecode AS ""Product Date Code"", - L.LEADFRAMENAME AS ""LF Material Part"", - L.LEADFRAMEOPTION AS ""LF Option ID"", - L.COMNAME AS ""Compound Material Part"", - L.LOCATIONNAME AS ""Run Card Location"", - L.Eventname AS ""NCR ID"", - L.Occurrencedate AS ""NCR-issued Time"", - L.ReleaseTime AS ""Release Time"", - L.ReleaseEmp AS ""Release Employee"", - L.ReleaseReason AS ""Release Comment"", - L.COMMENT_HOLD AS ""Hold Comment"", - L.CONTAINERCOMMENTS AS ""Comment"", - L.COMMENT_DATE AS ""Run Card Comment"", - L.COMMENT_EMP AS ""Run Card Comment Employee"", - L.COMMENT_FUTURE AS ""Future Hold Comment"", - L.HOLDEMP AS ""Hold Employee"", - L.DEPTNAME AS ""Hold Employee Dept"", - L.PJ_PRODUCEREGION AS ""Produce Region"", - L.Prioritycodename AS ""Work Order Priority"", - L.TMTT_R AS ""TMTT Remaining"", - L.wafer_factor AS ""Die Consumption Qty"", - Case When (L.EquipmentCount>0) Then 'RUN' - When (L.CurrentHoldCount>0) Then 'HOLD' - ELSE 'QUENE' End AS ""WIP Status"", - Case When (L.EquipmentCount>0) Then 1 - When (L.CurrentHoldCount>0) Then 3 - ELSE 2 End AS ""WIP Status Sequence"", - sys_date AS ""Data Update Date"" \ No newline at end of file diff --git a/docs/MES_Core_Tables_Analysis_Report.md b/docs/MES_Core_Tables_Analysis_Report.md deleted file mode 100644 index 4c89cf4..0000000 --- a/docs/MES_Core_Tables_Analysis_Report.md +++ /dev/null @@ -1,2334 +0,0 @@ -# MES 核心表詳細分析報告 - -**生成時間**: 2026-01-14(最後更新: 2026-01-29) -**分析範圍**: 19 張 MES 核心表(含 2 張 DWH 即時視圖 + 1 張工站對照視圖) -**資料來源**: MES_Database_Reference.md, DW_MES_LOT_V 實際數據分析, DW_MES_EQUIPMENTSTATUS_WIP_V 實際數據分析, DW_MES_SPEC_WORKCENTER_V 實際數據分析 - ---- - -## 目錄 - -1. [表性質分類總覽](#表性質分類總覽) -2. [即時數據表分析](#即時數據表分析) -3. [現況快照表分析](#現況快照表分析) -4. [歷史累積表分析](#歷史累積表分析) -5. [表間關聯關係圖](#表間關聯關係圖) -6. [關鍵業務場景查詢策略](#關鍵業務場景查詢策略) - ---- - -## 表性質分類總覽 - -### 即時數據表(Real-time Views) -透過 DB Link 從 DWH 取得的即時 WIP / 設備狀態視圖,依來源更新頻率提供 - -| 表名 | 數據量 | 主要用途 | 更新方式 | -|------|--------|---------|---------| -| **DW_MES_LOT_V** | ~9,468 | 即時 WIP 分布(70欄位) | DB Link 即時查詢(依 PJ_LOT_MV 更新頻率) | -| **DW_MES_EQUIPMENTSTATUS_WIP_V** | ~2,631 | 設備資產狀態 + WIP 追蹤(32欄位) | DB Link 即時查詢(真正即時表) | - -### 現況快照表(Snapshot Tables) -存儲當前狀態的數據,數據會被更新或覆蓋 - -| 表名 | 數據量 | 主要用途 | 更新方式 | -|------|--------|---------|---------| -| **DW_MES_WIP** | 79,058,085 | 在制品現況(含歷史累積) | 隨生產流程更新 | -| **DW_MES_RESOURCE** | 91,329 | 資源主檔(設備/工位) | 異動時更新 | -| **DW_MES_CONTAINER** | 5,218,406 | 容器當前狀態 | 隨批次流轉更新 | -| **DW_MES_JOB** | 1,248,622 | 設備維修工單當前狀態 | 維修工單狀態變更時更新 | - -### 歷史累積表(Historical Tables) -只新增不修改,記錄完整的歷史軌跡 - -| 表名 | 數據量 | 主要用途 | 累積方式 | -|------|--------|---------|---------| -| **DW_MES_RESOURCESTATUS** | 65,742,614 | 資源狀態變更歷史 | 狀態變更時新增記錄 | -| **DW_MES_RESOURCESTATUS_SHIFT** | 74,820,134 | 資源班次狀態歷史 | 班次資料匯總新增 | -| **DW_MES_LOTWIPHISTORY** | 53,454,213 | 批次流轉歷史 | 每次移出/移入新增 | -| **DW_MES_LOTWIPDATAHISTORY** | 77,960,216 | 批次數據變更歷史 | 數據採集時新增 | -| **DW_MES_HM_LOTMOVEOUT** | 48,645,692 | 批次移出事件 | 移出操作時新增 | -| **DW_MES_JOBTXNHISTORY** | 9,554,723 | 維修工單交易歷史 | 維修工單狀態變更新增 | -| **DW_MES_LOTREJECTHISTORY** | 15,786,025 | 批次拒絕歷史 | 報廢操作時新增 | -| **DW_MES_LOTMATERIALSHISTORY** | 17,829,931 | 物料消耗歷史 | 物料使用時新增 | -| **DW_MES_HOLDRELEASEHISTORY** | 310,737 | 暫停/釋放歷史 | Hold/Release時新增 | -| **DW_MES_MAINTENANCE** | 52,060,026 | 設備維護歷史 | 維護活動時新增 | - -### 輔助表(Auxiliary Tables) - -| 表名 | 數據量 | 主要用途 | -|------|--------|---------| -| **DW_MES_PARTREQUESTORDER** | 61,396 | 物料請求訂單 | -| **DW_MES_PJ_COMBINEDASSYLOTS** | 1,965,425 | 組合裝配批次 | -| **DW_MES_SPEC_WORKCENTER_V** | 230 | 工站/工序對照視圖 | - ---- - -## 即時數據表分析 - -### DW_MES_LOT_V(即時 WIP 批次視圖)⭐⭐⭐ - -**表性質**: 即時數據視圖(Real-time View) - -**業務定義**: DWH 提供的即時 WIP 視圖,透過 DB Link 從 `PJ_LOT_MV@DWDB_MESDB` 取得,依 PJ_LOT_MV 更新頻率提供。包含完整的批次狀態、工站位置、設備資訊、Hold 原因等 70 個欄位,是 WIP Dashboard 的主要數據源。 - -**數據來源**: `PJ_LOT_MV@DWDB_MESDB`(DB Link 連線) - -**數據量**: 約 9,468 筆(2026-01-29 查詢) - -#### 欄位分類總覽(70 欄位) - -| 分類 | 欄位數 | 說明 | -|------|--------|------| -| 批次識別 | 5 | LOTID, CONTAINERID, WORKORDER, FIRSTNAME, NO | -| 數量相關 | 6 | QTY, QTY2, STARTQTY, STARTQTY2, MOVEINQTY, MOVEINQTY2 | -| 狀態相關 | 4 | STATUS, CURRENTHOLDCOUNT, STARTREASON, OWNER | -| 時間相關 | 7 | STARTDATE, UTS, MOVEINTIMESTAMP, SYS_DATE, AGEBYDAYS, REMAINTIME, OCCURRENCEDATE | -| 工站/流程 | 12 | WORKCENTER*, SPEC*, STEP, WORKFLOWNAME, LOCATIONNAME | -| 產品/封裝 | 8 | PRODUCT, PRODUCTLINENAME, PACKAGE_LEF, MATERIALTYPE, PJ_TYPE, PJ_FUNCTION, BOP | -| Hold 相關 | 8 | HOLDREASONNAME, HOLDEMP, HOLDLOCATION, RELEASETIME, RELEASEEMP, RELEASEREASON, COMMENT_HOLD | -| 設備相關 | 4 | EQUIPMENTNAME, EQUIPMENTS, EQUIPMENTCOUNT, DEPTNAME | -| 物料資訊 | 6 | LEADFRAMENAME, LEADFRAMEOPTION, WAFERNAME, WAFERLOT, COMNAME, DATECODE | -| 備註/其他 | 10 | CONTAINERCOMMENTS, COMMENT_*, PRIORITYCODENAME, JOB*, PB_FUNCTION, TMTT_R, WAFER_FACTOR | - -#### 關鍵時間欄位 - -| 欄位名 | 類型 | 用途 | 說明 | -|--------|------|------|------| -| `SYS_DATE` | TIMESTAMP | 數據更新時間 | 視圖同步時間戳,用於確認數據新鮮度 | -| `STARTDATE` | TIMESTAMP | 批次開始時間 | 批次投產的時間點 | -| `MOVEINTIMESTAMP` | TIMESTAMP | 移入當前工站時間 | 進入當前工序的時間 | -| `UTS` | VARCHAR2 | 預計完成日期 | 格式為 'YYYY/MM/DD' | -| `AGEBYDAYS` | NUMBER | 批次天數 | 從 STARTDATE 到現在的天數(含小數) | -| `REMAINTIME` | NUMBER | 剩餘時間 | 預計完成前的剩餘天數(含小數) | - -#### 關鍵業務欄位詳解 - -##### 批次識別欄位 - -| 欄位名 | 類型 | 說明 | 範例值 | -|--------|------|------|--------| -| `LOTID` | VARCHAR2(40) | 批次號(業務識別碼) | `GA26011704-A00-003` | -| `CONTAINERID` | VARCHAR2(40) | 容器 ID(系統識別碼) | `48810480002ab0b4` | -| `WORKORDER` | VARCHAR2(40) | 工單號 | `GA26011704` | -| `FIRSTNAME` | VARCHAR2(100) | 首片批號 | `PSMS-4473#RFTLD3` | -| `NO` | NUMBER | 序號(查詢結果排序用) | 1, 2, 3... | - -##### 狀態欄位 - -| 欄位名 | 類型 | 說明 | 實際值分布 | -|--------|------|------|-----------| -| `STATUS` | VARCHAR2(20) | 批次狀態 | `ACTIVE`(約 98.7%)、`HOLD`(約 1.3%) | -| `OWNER` | VARCHAR2(40) | 所有者/用途 | `量產`、`重工RW`、`代工`、`點測`、`樣品`、`餘晶`、`工程`、`久存`、`PROD`、`降規` | -| `MATERIALTYPE` | VARCHAR2(40) | 物料類型 | `成品`(約 99%)、`Wafer`(約 1%) | -| `STARTREASON` | VARCHAR2(40) | 開始原因 | `NORMAL`、`RW` 等 | - -##### 數量欄位 - -| 欄位名 | 類型 | 說明 | 數值範圍 | -|--------|------|------|---------| -| `QTY` | NUMBER | 當前數量(主單位) | 1 - 3,000,000+ | -| `QTY2` | NUMBER | 當前數量(輔單位) | 通常為 0 | -| `STARTQTY` | NUMBER | 起始數量 | 通常 ≥ QTY | -| `MOVEINQTY` | NUMBER | 移入數量 | 進站時的數量 | - -##### 工站/流程欄位 - -| 欄位名 | 類型 | 說明 | 範例值 | -|--------|------|------|--------| -| `WORKCENTERNAME` | VARCHAR2(40) | 工作中心名稱 | `成型`、`TMTT`、`電鍍`、`焊接` | -| `WORKCENTER_GROUP` | VARCHAR2(40) | 工作中心群組 | 與 WORKCENTERNAME 相同或分組 | -| `WORKCENTER_SHORT` | VARCHAR2(20) | 工站簡稱 | `Mold`、`TMTT`、`DB`、`WB` | -| `WORKCENTERSEQUENCE` | VARCHAR2(10) | 工站順序 | `130`、`300` 等(數值越大越後段) | -| `SPECNAME` | VARCHAR2(100) | 工序規格名稱 | `成型烘烤`、`PRE TMTT` | -| `STEP` | VARCHAR2(100) | 當前步驟 | 通常與 SPECNAME 相同 | -| `WORKFLOWNAME` | VARCHAR2(100) | 工藝流程名稱 | `PCC_SOT-223`、`UAC_SOD-523` | - -##### 產品/封裝欄位 - -| 欄位名 | 類型 | 說明 | 範例值 | -|--------|------|------|--------| -| `PRODUCT` | VARCHAR2(100) | 產品名稱(完整) | `PJW5P06A_R2_00701` | -| `PRODUCTLINENAME` | VARCHAR2(40) | 產品線/封裝類型 | `SOT-223`、`SOD-523` | -| `PACKAGE_LEF` | VARCHAR2(40) | 封裝型號 | `SOT-223`、`SOD-523` | -| `PJ_TYPE` | VARCHAR2(40) | 產品型號 | `PJW5P06A`、`RB521S30-NC` | -| `PJ_FUNCTION` | VARCHAR2(40) | 產品功能分類 | `MOSFET`、`SKY` | -| `BOP` | VARCHAR2(40) | BOP 代碼 | `PCC15`、`UAC10` | - -##### Hold 相關欄位 - -| 欄位名 | 類型 | 說明 | 範例值 | -|--------|------|------|--------| -| `HOLDREASONNAME` | VARCHAR2(100) | Hold 原因 | `S2品質異常單(PE)`、`特殊需求管控` | -| `CURRENTHOLDCOUNT` | NUMBER | 當前 Hold 次數 | 0 = 非 Hold,≥1 = Hold 中 | -| `HOLDEMP` | VARCHAR2(40) | Hold 操作人員 | 員工姓名 | -| `HOLDLOCATION` | VARCHAR2(40) | Hold 位置 | 通常為 NULL | -| `RELEASETIME` | TIMESTAMP | 預計解除時間 | NULL 表示未設定 | -| `RELEASEEMP` | VARCHAR2(40) | 解除人員 | NULL 表示尚未解除 | -| `RELEASEREASON` | VARCHAR2(200) | 解除原因 | NULL 表示尚未解除 | -| `COMMENT_HOLD` | VARCHAR2(4000) | Hold 備註 | 詳細說明 Hold 原因 | - -##### 設備欄位(重要說明) - -| 欄位名 | 類型 | 說明 | 使用工站 | -|--------|------|------|---------| -| `EQUIPMENTNAME` | VARCHAR2(40) | 設備名稱(單一設備) | TMTT(82%)、切彎腳(69%)、PKG_SAW | -| `EQUIPMENTS` | VARCHAR2(4000) | 設備清單(逗號分隔) | 成型、焊接、電鍍、打印等其他工站 | -| `EQUIPMENTCOUNT` | NUMBER | 設備數量 | 0 表示尚無設備綁定 | - -**⚠️ 重要**: `EQUIPMENTNAME` 與 `EQUIPMENTS` 為**互斥使用**: -- **TMTT、切彎腳、PKG_SAW** 工站使用 `EQUIPMENTNAME`(單一設備) -- **其他工站**(成型、焊接、電鍍、打印等)使用 `EQUIPMENTS`(設備清單) -- 僅約 100 筆同時有兩欄位數據(均為 TMTT 工站) -- **建議查詢**: 使用 `COALESCE(EQUIPMENTNAME, EQUIPMENTS)` 取得統一設備資訊 - -##### 優先度欄位 - -| 欄位名 | 值 | 說明 | -|--------|-----|------| -| `PRIORITYCODENAME` | `1.超特急` | 最高優先度 | -| | `2.特急` | 高優先度 | -| | `3.急件` | 中高優先度(約 3%) | -| | `4.一般` | 一般優先度(約 96%) | - -##### Hold 原因分布(參考數據) - -| HOLDREASONNAME | 說明 | 典型佔比 | -|----------------|------|---------| -| `特殊需求管控` | 特殊製程或客戶要求 | 最常見 | -| `S2品質異常單(PE)` | PE 開立的品質異常 | 常見 | -| `現場品質異常單(PQC)` | PQC 開立的品質異常 | 常見 | -| `自行暫停` | 自主暫停 | 偶爾 | -| `治具不足HOLD` | 治具問題 | 偶爾 | -| 其他 | 換線暫停、生管暫停等 | 少見 | - -#### 查詢策略 - -**1. WIP 即時分布統計(按工站)** -```sql -SELECT - WORKCENTER_GROUP, - WORKCENTER_SHORT, - COUNT(*) as LOT_COUNT, - SUM(QTY) as TOTAL_QTY, - SUM(CASE WHEN STATUS = 'HOLD' THEN 1 ELSE 0 END) as HOLD_LOTS, - SUM(CASE WHEN STATUS = 'HOLD' THEN QTY ELSE 0 END) as HOLD_QTY -FROM DW_MES_LOT_V -WHERE OWNER NOT IN ('DUMMY') -- 排除 DUMMY 批次 -GROUP BY WORKCENTER_GROUP, WORKCENTER_SHORT, WORKCENTERSEQUENCE_GROUP -ORDER BY TO_NUMBER(WORKCENTERSEQUENCE_GROUP); -``` - -**2. WIP 交叉分析(工站 x 封裝)** -```sql -SELECT - WORKCENTER_GROUP, - PRODUCTLINENAME, - COUNT(*) as LOT_COUNT, - SUM(QTY) as TOTAL_QTY -FROM DW_MES_LOT_V -WHERE OWNER NOT IN ('DUMMY') -GROUP BY WORKCENTER_GROUP, PRODUCTLINENAME -ORDER BY WORKCENTER_GROUP, LOT_COUNT DESC; -``` - -**3. Hold 批次清單** -```sql -SELECT - LOTID, - PRODUCT, - WORKCENTERNAME, - SPECNAME, - QTY, - HOLDREASONNAME, - HOLDEMP, - COMMENT_HOLD, - AGEBYDAYS -FROM DW_MES_LOT_V -WHERE STATUS = 'HOLD' -ORDER BY AGEBYDAYS DESC; -``` - -**4. 設備使用查詢(統一處理 EQUIPMENTNAME/EQUIPMENTS)** -```sql -SELECT - LOTID, - WORKCENTERNAME, - COALESCE(EQUIPMENTNAME, EQUIPMENTS) as EQUIPMENT_INFO, - EQUIPMENTCOUNT, - QTY -FROM DW_MES_LOT_V -WHERE COALESCE(EQUIPMENTNAME, EQUIPMENTS) IS NOT NULL -ORDER BY WORKCENTERNAME; -``` - -**5. 批次詳細查詢** -```sql -SELECT - LOTID, - CONTAINERID, - WORKORDER, - PRODUCT, - PJ_TYPE, - PJ_FUNCTION, - PRODUCTLINENAME, - WORKCENTERNAME, - SPECNAME, - STATUS, - QTY, - STARTQTY, - AGEBYDAYS, - REMAINTIME, - UTS, - PRIORITYCODENAME, - OWNER, - COALESCE(EQUIPMENTNAME, EQUIPMENTS) as EQUIPMENT, - SYS_DATE -FROM DW_MES_LOT_V -WHERE LOTID LIKE 'GA26011%' -- 工單篩選 -ORDER BY WORKCENTERSEQUENCE; -``` - -#### 與其他表的關聯 - -| 關聯表 | 關聯欄位 | 用途 | -|--------|---------|------| -| DW_MES_CONTAINER | CONTAINERID | 取得更詳細的容器資訊 | -| DW_MES_LOTWIPHISTORY | CONTAINERID | 查詢批次流轉歷史 | -| DW_MES_HOLDRELEASEHISTORY | CONTAINERID | 查詢 Hold/Release 歷史 | - -#### 重要注意事項 - -⚠️ **資料更新頻率**: 每 5 分鐘從 DWH 同步,查詢時注意 `SYS_DATE` 確認數據新鮮度 - -⚠️ **DUMMY 批次過濾**: 生產報表應排除 `OWNER IN ('DUMMY')` 的測試批次 - -⚠️ **設備欄位選擇**: 使用 `COALESCE(EQUIPMENTNAME, EQUIPMENTS)` 處理不同工站的設備資訊 - -⚠️ **時間欄位**: `UTS` 為 VARCHAR2 格式 'YYYY/MM/DD',需轉換後才能計算 - -⚠️ **無資料庫備註**: 此視圖無 Oracle 欄位備註(ALL_COL_COMMENTS 為空),欄位說明請參考本文件 - ---- - -### DW_MES_EQUIPMENTSTATUS_WIP_V(設備狀態 + WIP 追蹤視圖)⭐⭐ - -**表性質**: 即時數據視圖(Real-time View) - -**業務定義**: DWH 提供設備資產狀態與 WIP 追蹤資料的即時視圖,透過 DB Link 直接查詢 `PJ_EquipmentStatus_WIP_V@DWDB_MESDB`,屬於真正即時表(非同步快照)。整合設備狀態、維修工單與批次 Track-In 及 Wafer/封裝資訊,適合做設備狀態與當前 WIP 關聯分析。 - -**數據來源**: `PJ_EquipmentStatus_WIP_V@DWDB_MESDB`(DB Link 連線) - -**數據量**: 約 2,631 筆(2026-01-29 查詢) - -#### 欄位分類總覽(32 欄位) - -| 分類 | 欄位數 | 說明 | -|------|--------|------| -| 設備/資源識別 | 3 | RESOURCEID, EQUIPMENTID, OBJECTCATEGORY | -| 設備狀態 | 2 | EQUIPMENTASSETSSTATUS, EQUIPMENTASSETSSTATUSREASON | -| 維修工單 | 11 | JOBORDER, JOBMODEL, JOBSTAGE, JOBID, JOBSTATUS, CREATEDATE, CREATEUSERNAME, CREATEUSER, SYMPTOMCODE, CAUSECODE, REPAIRCODE | -| WIP/產品 | 7 | RUNCARDLOTID, "Package", PACKAGE_LF, "Function", TYPE, BOP, SPEC | -| Wafer/材料 | 6 | WAFERLOTID, WAFERPN, WAFERLOTID_PREFIX, LFOPTIONID, WIREDESCRIPTION, WAFERMIL | -| Track-In | 3 | LOTTRACKINQTY_PCS, LOTTRACKINTIME, LOTTRACKINEMPLOYEE | - -#### 關鍵欄位說明 - -#### 欄位清單與說明(32 欄位) - -| 欄位名 | 類型 | 欄位功能說明 | -|--------|------|--------------| -| `RESOURCEID` | CHAR(16) | 資源/設備資源 ID(資源主檔識別碼) | -| `EQUIPMENTID` | VARCHAR2(40) | 設備編號(機台代號) | -| `OBJECTCATEGORY` | VARCHAR2(40) | 類別/製程分類(如 ASSEMBLY) | -| `EQUIPMENTASSETSSTATUS` | VARCHAR2(40) | 設備資產狀態(如 PRD、IDLE) | -| `EQUIPMENTASSETSSTATUSREASON` | VARCHAR2(40) | 設備狀態原因/說明(如 Production RUN) | -| `JOBORDER` | VARCHAR2(40) | 維修工單號 | -| `JOBMODEL` | VARCHAR2(40) | 維修工單機型/型號 | -| `JOBSTAGE` | VARCHAR2(40) | 維修工單階段 | -| `JOBID` | CHAR(16) | 維修工單內部 ID | -| `JOBSTATUS` | VARCHAR2(40) | 維修工單狀態 | -| `CREATEDATE` | DATE | 工單建立時間 | -| `CREATEUSERNAME` | VARCHAR2(40) | 建立者帳號 | -| `CREATEUSER` | VARCHAR2(255) | 建立者姓名/顯示名稱 | -| `SYMPTOMCODE` | VARCHAR2(40) | 維修症狀代碼 | -| `CAUSECODE` | VARCHAR2(40) | 故障原因代碼 | -| `REPAIRCODE` | VARCHAR2(40) | 維修處置代碼 | -| `RUNCARDLOTID` | VARCHAR2(40) | 批次號(Run card lot id) | -| `"Package"` | VARCHAR2(40) | 封裝型號(需雙引號保留大小寫) | -| `PACKAGE_LF` | VARCHAR2(4000) | 封裝/Leadframe 類型或描述 | -| `"Function"` | VARCHAR2(40) | 產品功能分類(需雙引號保留大小寫) | -| `TYPE` | VARCHAR2(40) | 產品型號 | -| `BOP` | VARCHAR2(40) | BOP 代碼 | -| `WAFERLOTID` | VARCHAR2(40) | Wafer Lot 編號 | -| `WAFERPN` | VARCHAR2(40) | Wafer 料號 | -| `WAFERLOTID_PREFIX` | VARCHAR2(160) | Wafer Lot 前綴 | -| `SPEC` | VARCHAR2(40) | 製程/工序規格 | -| `LFOPTIONID` | VARCHAR2(4000) | Leadframe Option | -| `WIREDESCRIPTION` | VARCHAR2(4000) | Wire 描述 | -| `WAFERMIL` | VARCHAR2(3062) | Wafer 規格/厚度 | -| `LOTTRACKINQTY_PCS` | NUMBER | Track-In 數量(PCS) | -| `LOTTRACKINTIME` | DATE | Track-In 時間 | -| `LOTTRACKINEMPLOYEE` | VARCHAR2(255) | Track-In 人員 | - -##### 設備狀態欄位 - -| 欄位名 | 類型 | 說明 | 範例值 | -|--------|------|------|--------| -| `EQUIPMENTASSETSSTATUS` | VARCHAR2(40) | 設備資產狀態 | `PRD` | -| `EQUIPMENTASSETSSTATUSREASON` | VARCHAR2(40) | 狀態原因 | `Production RUN` | -| `OBJECTCATEGORY` | VARCHAR2(40) | 類別/製程分類 | `ASSEMBLY` | - -##### 批次與產品欄位 - -| 欄位名 | 類型 | 說明 | 範例值 | -|--------|------|------|--------| -| `RUNCARDLOTID` | VARCHAR2(40) | 批次號(Run card lot id) | `GA26011480-A00-006` | -| `"Package"` | VARCHAR2(40) | 封裝型號 | `DFN2510-10L` | -| `"Function"` | VARCHAR2(40) | 產品功能分類 | `TVS/ESD` | -| `TYPE` | VARCHAR2(40) | 產品型號 | `PE1605M4AQ` | -| `BOP` | VARCHAR2(40) | BOP 代碼 | `ECA08` | -| `SPEC` | VARCHAR2(40) | 工序規格 | `元件切割` | - -##### Track-In 與 Wafer 欄位 - -| 欄位名 | 類型 | 說明 | -|--------|------|------| -| `LOTTRACKINQTY_PCS` | NUMBER | Track-In 數量(PCS) | -| `LOTTRACKINTIME` | DATE | Track-In 時間 | -| `LOTTRACKINEMPLOYEE` | VARCHAR2(255) | Track-In 人員 | -| `WAFERLOTID` | VARCHAR2(40) | Wafer Lot | -| `WAFERPN` | VARCHAR2(40) | Wafer 料號 | -| `WAFERLOTID_PREFIX` | VARCHAR2(160) | Wafer Lot 前綴 | -| `LFOPTIONID` | VARCHAR2(4000) | Leadframe Option | -| `WIREDESCRIPTION` | VARCHAR2(4000) | Wire 描述 | -| `WAFERMIL` | VARCHAR2(3062) | Wafer 厚度/規格 | - -#### 查詢策略 - -**1. 設備狀態分布** -```sql -SELECT - OBJECTCATEGORY, - EQUIPMENTASSETSSTATUS, - EQUIPMENTASSETSSTATUSREASON, - COUNT(*) as EQUIPMENT_COUNT -FROM DW_MES_EQUIPMENTSTATUS_WIP_V -GROUP BY OBJECTCATEGORY, EQUIPMENTASSETSSTATUS, EQUIPMENTASSETSSTATUSREASON -ORDER BY OBJECTCATEGORY, EQUIPMENT_COUNT DESC; -``` - -**2. 設備對應 WIP 批次(含 Track-In)** -```sql -SELECT - EQUIPMENTID, - RUNCARDLOTID, - "Package" as PACKAGE, - "Function" as FUNCTION, - TYPE, - BOP, - SPEC, - LOTTRACKINQTY_PCS, - LOTTRACKINTIME -FROM DW_MES_EQUIPMENTSTATUS_WIP_V -WHERE RUNCARDLOTID IS NOT NULL -ORDER BY LOTTRACKINTIME DESC; -``` - -**3. 維修工單清單** -```sql -SELECT - EQUIPMENTID, - JOBORDER, - JOBMODEL, - JOBSTAGE, - JOBSTATUS, - CREATEDATE, - SYMPTOMCODE, - CAUSECODE, - REPAIRCODE -FROM DW_MES_EQUIPMENTSTATUS_WIP_V -WHERE JOBORDER IS NOT NULL -ORDER BY CREATEDATE DESC; -``` - -**4. Wafer/材料分布** -```sql -SELECT - WAFERPN, - WAFERLOTID_PREFIX, - COUNT(*) as LOT_COUNT -FROM DW_MES_EQUIPMENTSTATUS_WIP_V -WHERE WAFERPN IS NOT NULL -GROUP BY WAFERPN, WAFERLOTID_PREFIX -ORDER BY LOT_COUNT DESC; -``` - -#### 與其他表的關聯 - -| 關聯表 | 關聯欄位 | 用途 | -|--------|---------|------| -| DW_MES_LOT_V | RUNCARDLOTID ↔ LOTID | 對照批次狀態/工站資訊 | -| DW_MES_WIP | RUNCARDLOTID ↔ CONTAINERNAME | 取得批次現況與工單資訊 | -| DW_MES_RESOURCE | EQUIPMENTID / RESOURCEID | 取得設備主檔/資源資訊 | - -#### 重要注意事項 - -⚠️ **資料更新頻率**: DB Link 即時查詢,查詢時可搭配 `LOTTRACKINTIME` 判斷新鮮度 - -⚠️ **欄位大小寫**: `"Package"`、`"Function"` 為**引用欄位**,查詢需使用雙引號保留大小寫 - -⚠️ **欄位空值**: 維修工單與 Wafer/材料欄位常為 NULL,需依使用情境加條件 - -⚠️ **無資料庫備註**: 此視圖無 Oracle 欄位備註(ALL_COL_COMMENTS 為空),欄位說明請參考本文件 - ---- - -### DW_MES_SPEC_WORKCENTER_V(工站/工序對照視圖)⭐ - -**表性質**: 對照視圖(Mapping View) - -**業務定義**: 由 `MES_SPEC`、`MES_OPERATION`、`MES_WORKCENTER` 組合,提供 SPEC 與工站名稱、分組與排序欄位的對照表。可用於統一工站命名與排序規則,補足報表分群需求。 - -**數據來源**: `MES_SPEC`, `MES_OPERATION`, `MES_WORKCENTER`(DWH 本地表) - -**數據量**: 230 筆(2026-01-29 查詢) - -#### 欄位說明(9 欄位) - -| 欄位名 | 類型 | 說明 | -|--------|------|------| -| `SPEC` | VARCHAR2(40) | SPEC 名稱 | -| `SPECSEQUENCE` | NUMBER | SPEC 順序(PJ_SEQUENCE) | -| `SPEC_ORDER` | VARCHAR2(200) | 排序欄位(SPECSEQUENCE + '_' + SPEC) | -| `WORK_CENTER` | VARCHAR2(100) | 工站名稱 | -| `WORK_CENTER_SEQUENCE` | VARCHAR2(40) | 工站順序碼(取自 WORKCENTER.Description) | -| `WORK_CENTER_GROUP` | VARCHAR2(100) | 工站分組名稱(依規則合併,如焊接/成型/電鍍) | -| `WORKCENTERSEQUENCE_GROUP` | VARCHAR2(40) | 工站群組順序碼(依規則統一) | -| `WORKCENTERGROUP_ORDER` | VARCHAR2(200) | 群組排序欄位(序號 + '_' + 群組名) | -| `WORK_CENTER_SHORT` | VARCHAR2(40) | 工站簡稱(如 DB/WB/Mold) | - -#### 查詢策略 - -**1. SPEC 對應工站分組** -```sql -SELECT - SPEC, - WORK_CENTER, - WORK_CENTER_GROUP, - WORK_CENTER_SHORT, - WORKCENTERSEQUENCE_GROUP -FROM DWH.DW_MES_SPEC_WORKCENTER_V -ORDER BY WORKCENTERSEQUENCE_GROUP, SPEC; -``` - -**2. 與 WIP 視圖對照(補足工站分組)** -```sql -SELECT - l.LOTID, - l.SPECNAME, - l.WORKCENTERNAME, - s.WORK_CENTER_GROUP, - s.WORK_CENTER_SHORT -FROM DWH.DW_MES_LOT_V l -LEFT JOIN DWH.DW_MES_SPEC_WORKCENTER_V s - ON l.SPECNAME = s.SPEC -ORDER BY l.WORKCENTERSEQUENCE_GROUP, l.LOTID; -``` - -#### 重要注意事項 - -⚠️ **分組規則**: `WORK_CENTER_GROUP` 與 `WORKCENTERSEQUENCE_GROUP` 由 CASE 規則產生,若工站命名異動需同步檢查 - ---- - -## 現況快照表分析 - -### 1. DW_MES_WIP(在制品表)⭐⭐⭐ - -**表性質**: 現況快照表(含歷史累積) - -**業務定義**: 存儲在制品(WIP)的現況資料,但實際包含歷史累積,需搭配時間條件(如 `TXNDATE`)限制查詢範圍 - -#### 關鍵時間欄位 - -| 欄位名 | 用途 | 查詢建議 | -|--------|------|---------| -| `MOVEINTIMESTAMP` | 批次移入當前工序的時間 | 計算在站時間 (SYSDATE - MOVEINTIMESTAMP) | -| `ORIGINALSTARTDATE` | 批次原始開始生產日期 | 計算生產週期 (SYSDATE - ORIGINALSTARTDATE) | -| `EXPECTEDENDDATE` | 預計完成日期 | 監控交期風險 | -| `TXNDATE` | 資料最後更新時間 | 數據同步監控用 | -| `HOLDTIME` | 暫停時間 | Hold批次的暫停時間點 | -| `COMMENT_DATE` | 備註更新時間 | 追蹤最後異動時間 | - -#### 關鍵業務欄位 - -**數量相關** -- `QTY` / `QTY2`: 當前數量(主/輔單位) -- `MOVEINQTY` / `MOVEINQTY2`: 移入數量 -- `ORIGINALQTY` / `ORIGINALQTY2`: 原始開始數量 -- `WOQTY`: 工單總數量 - -**狀態與位置** -- `STATUS`: 批次狀態碼(數值) -- `LOCATIONNAME`: 當前所在位置 -- `WORKFLOWSTEPNAME`: 當前工序步驟名稱 -- `WORKCENTERNAME`: 當前工作中心 - -**Hold相關** -- `CURRENTHOLDCOUNT`: 當前Hold數量 -- `HOLDREASONID` / `HOLDREASONNAME`: Hold原因 -- `HOLDLOCATIONNAME`: Hold所在位置 -- `HOLDEMP`: Hold操作人員 -- `HOLDCOMMENT_FUTURE`: Hold備註(FutureHold) - -**產品與工單** -- `CONTAINERNAME`: 批次號(LOT號) -- `MFGORDERNAME`: 工單號 -- `PRODUCTNAME`: 產品名稱 -- `PRODUCTLINENAME`: 產品線 -- `SPECNAME`: 當前站點規格 - -**生產信息** -- `DATECODE`: 生產週期代碼 -- `FIRSTNAME`: 首片批號 -- `WAFERLOT` / `WAFERNAME`: Wafer資訊(3個欄位合併) -- `LEADFRAMENAME` / `LEADFRAMEOPTION`: 框架資訊 -- `CONSUMEFACTOR`: 消耗因子(CF值) - -#### 查詢策略 - -**1. 查詢在站時間過長的批次(停滯分析)** -```sql -SELECT - CONTAINERNAME, - PRODUCTNAME, - WORKFLOWSTEPNAME, - MOVEINTIMESTAMP, - ROUND((SYSDATE - MOVEINTIMESTAMP) * 24, 2) as HOURS_IN_STATION -FROM DW_MES_WIP -WHERE STATUS NOT IN (8, 128) -- 排除已完成或取消 - AND (SYSDATE - MOVEINTIMESTAMP) > 2 -- 在站超過2天 -ORDER BY HOURS_IN_STATION DESC; -``` - -**2. 查詢Hold批次清單** -```sql -SELECT - CONTAINERNAME, - PRODUCTNAME, - HOLDREASONNAME, - HOLDEMP, - HOLDTIME, - HOLDLOCATIONNAME, - CURRENTHOLDCOUNT -FROM DW_MES_WIP -WHERE CURRENTHOLDCOUNT > 0 - AND STATUS NOT IN (8, 128) -ORDER BY HOLDTIME; -``` - -**3. 查詢在制品數量統計(按產品線)** -```sql -SELECT - PRODUCTLINENAME, - COUNT(DISTINCT CONTAINERNAME) as LOT_COUNT, - SUM(QTY) as TOTAL_QTY, - SUM(CASE WHEN CURRENTHOLDCOUNT > 0 THEN 1 ELSE 0 END) as HOLD_LOT_COUNT -FROM DW_MES_WIP -WHERE STATUS NOT IN (8, 128) -GROUP BY PRODUCTLINENAME -ORDER BY LOT_COUNT DESC; -``` - -**4. 工單進度查詢** -```sql -SELECT - MFGORDERNAME, - PRODUCTNAME, - WOQTY as WO_TOTAL_QTY, - COUNT(DISTINCT CONTAINERNAME) as LOT_COUNT, - SUM(QTY) as CURRENT_QTY, - MIN(MOVEINTIMESTAMP) as EARLIEST_MOVEIN, - MAX(MOVEINTIMESTAMP) as LATEST_MOVEIN -FROM DW_MES_WIP -WHERE MFGORDERNAME = 'WO12345' -- 替換為實際工單號 - AND STATUS NOT IN (8, 128) -GROUP BY MFGORDERNAME, PRODUCTNAME, WOQTY; -``` - ---- - -### 2. DW_MES_RESOURCE(資源主表) - -**表性質**: 現況快照表(主檔表) - -**業務定義**: 存儲所有生產資源(設備、工位)的基本信息和配置 - -#### 關鍵時間欄位 - -| 欄位名 | 用途 | -|--------|------| -| `CREATIONDATE` | 資源創建日期 | -| `LASTCHANGEDATE` | 最後修改日期 | - -#### 關鍵業務欄位 - -**基本信息** -- `RESOURCEID` / `RESOURCENAME`: 資源唯一標識與名稱 -- `OBJECTCATEGORY` / `OBJECTTYPE`: 資源分類(設備/工位等) -- `DESCRIPTION`: 資源描述 -- `EQUIPMENTTYPE`: 設備類型 - -**位置與歸屬** -- `LOCATIONID` / `LOCATIONNAME`: 所在位置 -- `WORKCENTERNAME`: 所屬工作中心 -- `RESOURCEFAMILYNAME`: 資源家族 -- `PJ_DEPARTMENT`: 所屬部門 - -**設備狀態與能力** -- `PJ_ASSETSSTATUS`: 資產狀態 -- `MAXLOTS`: 最大批次容量 -- `MAXUNITS`: 最大單元容量 -- `MULTILOTSFLAG`: 是否支持多批次 - -**設備屬性標記(2025-12-17新增)** -- `PJ_ISPRODUCTION`: 是否為生產設備 -- `PJ_ISKEY`: 是否為關鍵設備 -- `PJ_ISMONITOR`: 是否為監控設備 - -**供應商信息** -- `VENDORID` / `VENDORNAME`: 供應商 -- `PJ_ERPVENDORID`: ERP供應商代碼 -- `VENDORMODEL`: 設備型號 -- `VENDORSERIALNUMBER`: 序列號 - -#### 查詢策略 - -**1. 查詢關鍵生產設備清單** -```sql -SELECT - RESOURCENAME, - WORKCENTERNAME, - LOCATIONNAME, - EQUIPMENTTYPE, - VENDORNAME, - VENDORMODEL, - PJ_ASSETSSTATUS -FROM DW_MES_RESOURCE -WHERE PJ_ISPRODUCTION = 1 - AND PJ_ISKEY = 1 - AND OBJECTTYPE = 'Equipment' -ORDER BY WORKCENTERNAME, RESOURCENAME; -``` - -**2. 查詢設備容量信息** -```sql -SELECT - RESOURCENAME, - WORKCENTERNAME, - MAXLOTS, - MAXUNITS, - MULTILOTSFLAG, - LOTCOUNT as CURRENT_LOT_COUNT -FROM DW_MES_RESOURCE -WHERE OBJECTTYPE = 'Equipment' - AND MAXLOTS > 0 -ORDER BY WORKCENTERNAME; -``` - ---- - -### 3. DW_MES_CONTAINER(容器信息表) - -**表性質**: 現況快照表 - -**業務定義**: 存儲生產容器(批次載體)的當前信息和狀態 - -#### 關鍵時間欄位 - -| 欄位名 | 用途 | -|--------|------| -| `LASTMOVEOUTTIMESTAMP` | 最後移出時間 | -| `MOVEINTIMESTAMP` | 最後移入時間 | -| `FACTORYSTARTDATE` | 工廠開始日期 | -| `ORIGINALSTARTDATE` | 原始開始日期 | -| `PLANNEDSTARTDATE` | 計劃開始日期 | -| `LASTACTIVITYDATE` | 最後活動日期 | -| `LASTCOMPLETIONDATE` | 最後完成日期 | -| `ONHOLDDATE` | Hold日期 | -| `EXPIRATIONDATE` | 過期日期 | -| `UTS` | 更新時間戳 | -| `LAST_SYNC_DATE` | 最後同步日期 | - -#### 關鍵業務欄位 - -**容器標識** -- `CONTAINERID` / `CONTAINERNAME`: 容器唯一標識 -- `FIRSTNAME`: 首片資訊 - -**當前狀態** -- `STATUS`: 狀態碼 -- `CURRENTSTATUSID`: 當前狀態ID -- `LOCATIONNAME`: 當前位置 -- `WORKFLOWSTEPNAME`: 當前工序 -- `SPECNAME`: 當前規格 -- `WORKCENTERNAME`: 當前工作中心 - -**數量信息** -- `QTY` / `QTY2`: 當前數量 -- `MOVEINQTY` / `MOVEINQTY2`: 移入數量 -- `ORIGINALQTY` / `ORIGINALQTY2`: 原始數量 -- `FACTORYSTARTQTY`: 工廠開始數量 - -**Hold狀態** -- `CURRENTHOLDCOUNT`: 當前Hold計數 -- `FUTUREHOLDCOUNT`: FutureHold計數 -- `HOLDREASONID` / `HOLDREASONNAME`: Hold原因 -- `HOLDLOCATIONNAME`: Hold位置 -- `HOLDLOCATIONSTARTTIMESTAMP`: Hold開始時間 -- `HOLDLOCATIONDURATION`: Hold持續時間 - -**工單與產品** -- `MFGORDERID` / `MFGORDERNAME`: 工單 -- `PRODUCTID` / `PRODUCTNAME`: 產品 -- `PRODUCTLINENAME`: 產品線 -- `PROCESSSPECID`: 工藝規格 -- `PJ_BOP`: BOP信息 -- `PJ_PRODUCEREGION`: 生產區域 - -**Lead Frame信息** -- `LEADFRAMENAME`: 框架名稱 -- `LEADFRAMEDESC`: 框架描述 -- `LEADFRAMEOPTION`: 框架選項 - -#### 查詢策略 - -**1. 查詢容器完整生命週期** -```sql -SELECT - CONTAINERNAME, - FACTORYSTARTDATE, - FACTORYSTARTQTY, - CURRENTSTATUSID, - QTY, - LASTMOVEOUTTIMESTAMP, - LASTMOVEOUTUSERNAME, - ROUND((SYSDATE - FACTORYSTARTDATE), 2) as DAYS_IN_PRODUCTION -FROM DW_MES_CONTAINER -WHERE CONTAINERNAME = 'LOT123456' -- 替換為實際批號 -ORDER BY LASTMOVEOUTTIMESTAMP DESC; -``` - -**2. 查詢長時間Hold的容器** -```sql -SELECT - CONTAINERNAME, - PRODUCTNAME, - HOLDREASONNAME, - HOLDLOCATIONSTARTTIMESTAMP, - HOLDLOCATIONDURATION, - CURRENTHOLDCOUNT -FROM DW_MES_CONTAINER -WHERE CURRENTHOLDCOUNT > 0 - AND HOLDLOCATIONDURATION > 48 -- Hold超過48小時 -ORDER BY HOLDLOCATIONDURATION DESC; -``` - ---- - -### 4. DW_MES_JOB(工單表) - -**表性質**: 現況快照表 - -**業務定義**: 存儲維修/維護工單的當前狀態信息 - -#### 關鍵時間欄位 - -| 欄位名 | 用途 | -|--------|------| -| `CREATEDATE` | 工單創建日期 | -| `EXPECTEDSTARTDATE` | 預計開始日期 | -| `FIRSTCLOCKONDATE` | 首次簽到日期 | -| `LASTCLOCKOFFDATE` | 最後簽退日期 | -| `COMPLETEDATE` | 完成日期 | -| `CANCELDATE` | 取消日期 | - -#### 關鍵業務欄位 - -**工單基本信息** -- `JOBID`: 工單唯一標識 -- `JOBORDERNAME`: 工單名稱 -- `JOBSTATUS`: 工單狀態 -- `JOBMODELNAME`: 工單模型 -- `STAGENAME`: 階段名稱 -- `STAGESEQUENCE`: 階段順序 - -**資源與容器** -- `RESOURCEID` / `RESOURCENAME`: 關聯資源(設備) -- `CONTAINERIDS` / `CONTAINERNAMES`: 關聯容器(批次) -- `PARTREQUESTORDERNAME`: 物料請求訂單 - -**維修信息** -- `SYMPTOMCODENAME`: 症狀代碼 -- `CAUSECODENAME`: 原因代碼 -- `REPAIRCODENAME`: 維修代碼 -- `PJ_SYMPTOMCODE2NAME`: 症狀代碼2 -- `PJ_CAUSECODE2NAME`: 原因代碼2 -- `PJ_REPAIRCODE2NAME`: 維修代碼2 - -**工單統計** -- `ACKNOWLEDGECOUNT`: 確認計數 -- `ASSIGNCOUNT`: 分配計數 -- `CLOCKONCOUNT`: 簽到計數 -- `ACTIVECLOCKONCOUNT`: 活動簽到計數 -- `ESTIMATEDDURATION`: 預估工時 - -**操作人員** -- `CREATEUSERID` / `CREATE_EMPNAME` / `CREATE_FULLNAME`: 創建人 -- `COMPLETEUSERID` / `COMPLETE_EMPNAME` / `COMPLETE_FULLNAME`: 完成人 -- `CANCELUSERID` / `CANCEL_EMPNAME` / `CANCEL_FULLNAME`: 取消人 - -#### 查詢策略 - -**1. 查詢設備維修工單統計** -```sql -SELECT - RESOURCENAME, - JOBSTATUS, - COUNT(*) as JOB_COUNT, - AVG(COMPLETEDATE - CREATEDATE) as AVG_COMPLETION_DAYS -FROM DW_MES_JOB -WHERE CREATEDATE >= TRUNC(SYSDATE) - 30 -GROUP BY RESOURCENAME, JOBSTATUS -ORDER BY JOB_COUNT DESC; -``` - -**2. 查詢未完成工單清單** -```sql -SELECT - JOBORDERNAME, - RESOURCENAME, - JOBSTATUS, - CREATEDATE, - EXPECTEDSTARTDATE, - SYMPTOMCODENAME, - CREATE_FULLNAME -FROM DW_MES_JOB -WHERE JOBSTATUS NOT IN ('Completed', 'Cancelled') -ORDER BY CREATEDATE; -``` - -**3. 查詢維修原因分析** -```sql -SELECT - SYMPTOMCODENAME, - CAUSECODENAME, - REPAIRCODENAME, - COUNT(*) as OCCURRENCE_COUNT -FROM DW_MES_JOB -WHERE COMPLETEDATE >= TRUNC(SYSDATE) - 90 - AND JOBSTATUS = 'Completed' -GROUP BY SYMPTOMCODENAME, CAUSECODENAME, REPAIRCODENAME -ORDER BY OCCURRENCE_COUNT DESC; -``` - ---- - -## 歷史累積表分析 - -### 5. DW_MES_RESOURCESTATUS(資源狀態表)⭐⭐⭐ - -**表性質**: 歷史累積表(關鍵核心表) - -**業務定義**: 記錄設備狀態的每一次變更,用於計算設備稼動率、停機時間等關鍵指標 - -#### 關鍵時間欄位 - -| 欄位名 | 用途 | 查詢建議 | -|--------|------|---------| -| `OLDLASTSTATUSCHANGEDATE` | 上一個狀態開始時間 | **狀態持續時間計算起點** | -| `LASTSTATUSCHANGEDATE` | 新狀態開始時間 | **狀態持續時間計算終點** | -| `OLDLASTACTIVITYDATE` | 上次活動日期 | 設備最後活動時間 | -| `TXNDATE` | 交易時間 | 資料同步時間(用於ETL) | - -**時間計算公式**: -```sql -狀態持續時間(小時) = (LASTSTATUSCHANGEDATE - OLDLASTSTATUSCHANGEDATE) * 24 -``` - -#### 關鍵業務欄位 - -**狀態變更信息** -- `OLDSTATUSNAME` → `NEWSTATUSNAME`: 狀態變更(從→到) -- `OLDREASONNAME` → `NEWREASONNAME`: 原因變更 -- `OLDAVAILABILITY` → `AVAILABILITY`: 可用性變更 - -**可用性標記(AVAILABILITY)** -- `1`: Productive(生產中) -- `2`: Standby(待機) -- `3`: Non-Scheduled(非排程) -- `4`: Unscheduled Down(非計劃停機) -- `5`: Scheduled Down(計劃停機) - -**資源信息(來自RESOURCE表)** -- `HISTORYID`: 資源ID(關聯RESOURCEID) -- `DESCRIPTION`: 設備描述 -- `RESOURCEFAMILYNAME`: 設備家族 -- `WORKCENTERNAME`: 工作中心 -- `LOCATIONNAME`: 位置 -- `VENDORNAME` / `VENDORMODEL`: 供應商與型號 -- `PJ_ASSETSSTATUS`: 資產狀態 -- `PJ_DEPARTMENT`: 部門 - -**工單關聯** -- `JOBID`: 關聯的維修工單ID - -**特殊標記** -- `SS_ISDOWNVIAPARENT`: 是否因父設備Down而Down -- `UPDATELASTSTATUSCHANGEDATE` / `OLDUPDATELASTSTATUSCHANGEDATE`: 更新標記 - -#### 查詢策略 - -**1. 計算設備稼動率(OEE基礎數據)** -```sql -SELECT - HISTORYID as RESOURCE_ID, - WORKCENTERNAME, - TRUNC(OLDLASTSTATUSCHANGEDATE) as DATE_KEY, - SUM(CASE - WHEN AVAILABILITY = 1 THEN - (LASTSTATUSCHANGEDATE - OLDLASTSTATUSCHANGEDATE) * 24 - ELSE 0 - END) as PRODUCTIVE_HOURS, - SUM(CASE - WHEN AVAILABILITY = 2 THEN - (LASTSTATUSCHANGEDATE - OLDLASTSTATUSCHANGEDATE) * 24 - ELSE 0 - END) as STANDBY_HOURS, - SUM(CASE - WHEN AVAILABILITY = 4 THEN - (LASTSTATUSCHANGEDATE - OLDLASTSTATUSCHANGEDATE) * 24 - ELSE 0 - END) as UNSCHEDULED_DOWN_HOURS, - SUM((LASTSTATUSCHANGEDATE - OLDLASTSTATUSCHANGEDATE) * 24) as TOTAL_HOURS -FROM DW_MES_RESOURCESTATUS -WHERE OLDLASTSTATUSCHANGEDATE >= TRUNC(SYSDATE) - 7 - AND LASTSTATUSCHANGEDATE <= SYSDATE -GROUP BY HISTORYID, WORKCENTERNAME, TRUNC(OLDLASTSTATUSCHANGEDATE) -ORDER BY DATE_KEY DESC, RESOURCE_ID; -``` - -**2. 查詢設備停機記錄(Down Time分析)** -```sql -SELECT - HISTORYID as RESOURCE_ID, - WORKCENTERNAME, - OLDLASTSTATUSCHANGEDATE as DOWN_START, - LASTSTATUSCHANGEDATE as DOWN_END, - ROUND((LASTSTATUSCHANGEDATE - OLDLASTSTATUSCHANGEDATE) * 24, 2) as DOWN_HOURS, - NEWSTATUSNAME, - NEWREASONNAME, - AVAILABILITY -FROM DW_MES_RESOURCESTATUS -WHERE AVAILABILITY IN (4, 5) -- Unscheduled Down / Scheduled Down - AND OLDLASTSTATUSCHANGEDATE >= TRUNC(SYSDATE) - 7 -ORDER BY DOWN_HOURS DESC; -``` - -**3. 查詢設備狀態變更頻率** -```sql -SELECT - HISTORYID as RESOURCE_ID, - WORKCENTERNAME, - COUNT(*) as STATUS_CHANGE_COUNT, - MIN(OLDLASTSTATUSCHANGEDATE) as FIRST_CHANGE, - MAX(LASTSTATUSCHANGEDATE) as LAST_CHANGE -FROM DW_MES_RESOURCESTATUS -WHERE OLDLASTSTATUSCHANGEDATE >= TRUNC(SYSDATE) - 1 -GROUP BY HISTORYID, WORKCENTERNAME -ORDER BY STATUS_CHANGE_COUNT DESC; -``` - -**4. 查詢特定時間段設備時間軸** -```sql -SELECT - OLDLASTSTATUSCHANGEDATE as START_TIME, - LASTSTATUSCHANGEDATE as END_TIME, - OLDSTATUSNAME as FROM_STATUS, - NEWSTATUSNAME as TO_STATUS, - NEWREASONNAME as REASON, - ROUND((LASTSTATUSCHANGEDATE - OLDLASTSTATUSCHANGEDATE) * 24 * 60, 2) as DURATION_MINUTES -FROM DW_MES_RESOURCESTATUS -WHERE HISTORYID = 'RESOURCE_ID_HERE' -- 替換為實際設備ID - AND OLDLASTSTATUSCHANGEDATE >= TO_DATE('2026-01-14 08:00:00', 'YYYY-MM-DD HH24:MI:SS') - AND LASTSTATUSCHANGEDATE <= TO_DATE('2026-01-14 20:00:00', 'YYYY-MM-DD HH24:MI:SS') -ORDER BY OLDLASTSTATUSCHANGEDATE; -``` - -#### 重要注意事項 - -⚠️ **時間範圍必須限制**: 此表有 6500 萬筆資料,查詢時務必加上時間條件 - -⚠️ **狀態持續時間計算**: 使用 `LASTSTATUSCHANGEDATE - OLDLASTSTATUSCHANGEDATE` - -⚠️ **索引使用**: 優先使用 `OLDLASTSTATUSCHANGEDATE` 和 `HISTORYID` 索引 - ---- - -### 6. DW_MES_RESOURCESTATUS_SHIFT(資源狀態班次表)⭐⭐⭐ - -**表性質**: 歷史累積表(彙總表) - -**業務定義**: 按班次彙總資源狀態資料,已計算好時長,是生產報表的首選數據源 - -#### 關鍵時間欄位 - -| 欄位名 | 用途 | -|--------|------| -| `DATADATE` | 資料日期(班次日期) | -| `OLDLASTSTATUSCHANGEDATE` | 狀態開始時間 | -| `LASTSTATUSCHANGEDATE` | 狀態結束時間 | -| `TXNDATE` | 交易時間 | - -#### 關鍵業務欄位 - -**時長計算(已彙總)** -- `HOURS`: **狀態持續時長(小時)** ⭐ 已計算好,直接使用 - -**班次信息** -- `SN`: 班次序號 - -**狀態信息(同RESOURCESTATUS)** -- `OLDSTATUSNAME` / `NEWSTATUSNAME`: 狀態變更 -- `OLDREASONNAME` / `NEWREASONNAME`: 原因 -- `OLDAVAILABILITY` / `AVAILABILITY`: 可用性 - -**資源信息** -- `HISTORYID`: 資源ID -- `WORKCENTERNAME`: 工作中心 -- `RESOURCEFAMILYNAME`: 設備家族 -- `LOCATIONNAME`: 位置 - -**工單關聯** -- `JOBID`: 維修工單ID - -#### 查詢策略 - -**1. 日報表:設備稼動率統計(最佳實踐)** -```sql -SELECT - DATADATE, - HISTORYID as RESOURCE_ID, - WORKCENTERNAME, - SUM(CASE WHEN AVAILABILITY = 1 THEN HOURS ELSE 0 END) as PRODUCTIVE_HOURS, - SUM(CASE WHEN AVAILABILITY = 2 THEN HOURS ELSE 0 END) as STANDBY_HOURS, - SUM(CASE WHEN AVAILABILITY = 4 THEN HOURS ELSE 0 END) as DOWN_HOURS, - SUM(HOURS) as TOTAL_HOURS, - ROUND(SUM(CASE WHEN AVAILABILITY = 1 THEN HOURS ELSE 0 END) / NULLIF(SUM(HOURS), 0) * 100, 2) as UTILIZATION_PCT -FROM DW_MES_RESOURCESTATUS_SHIFT -WHERE DATADATE >= TRUNC(SYSDATE) - 7 -GROUP BY DATADATE, HISTORYID, WORKCENTERNAME -ORDER BY DATADATE DESC, UTILIZATION_PCT DESC; -``` - -**2. 月報表:設備停機時長排名** -```sql -SELECT - HISTORYID as RESOURCE_ID, - WORKCENTERNAME, - NEWREASONNAME as DOWN_REASON, - SUM(HOURS) as TOTAL_DOWN_HOURS, - COUNT(*) as DOWN_COUNT -FROM DW_MES_RESOURCESTATUS_SHIFT -WHERE DATADATE >= TRUNC(ADD_MONTHS(SYSDATE, -1), 'MM') - AND AVAILABILITY IN (4, 5) -- Down狀態 -GROUP BY HISTORYID, WORKCENTERNAME, NEWREASONNAME -ORDER BY TOTAL_DOWN_HOURS DESC; -``` - -**3. 趨勢分析:設備稼動率趨勢(按日)** -```sql -SELECT - DATADATE, - COUNT(DISTINCT HISTORYID) as EQUIPMENT_COUNT, - SUM(CASE WHEN AVAILABILITY = 1 THEN HOURS ELSE 0 END) as TOTAL_PRODUCTIVE_HOURS, - SUM(HOURS) as TOTAL_HOURS, - ROUND(SUM(CASE WHEN AVAILABILITY = 1 THEN HOURS ELSE 0 END) / NULLIF(SUM(HOURS), 0) * 100, 2) as AVG_UTILIZATION_PCT -FROM DW_MES_RESOURCESTATUS_SHIFT -WHERE DATADATE >= TRUNC(SYSDATE) - 30 - AND WORKCENTERNAME = 'WC001' -- 可選:指定工作中心 -GROUP BY DATADATE -ORDER BY DATADATE; -``` - -#### 優勢與使用建議 - -✅ **優勢**: -- 已彙總計算好時長(HOURS欄位),無需自行計算 -- 數據按DATADATE分區,查詢效率高 -- 適合做日報表、月報表 - -✅ **使用建議**: -- 優先使用此表做報表統計,而非RESOURCESTATUS -- 使用DATADATE作為主要時間篩選條件 -- 適合做時間序列分析和趨勢圖表 - ---- - -### 7. DW_MES_LOTWIPHISTORY(批次在制品歷史表)⭐⭐⭐ - -**表性質**: 歷史累積表(核心流程表) - -**業務定義**: 記錄批次在每個工序的完整流轉歷史,包含MoveIn/MoveOut和TrackIn/TrackOut信息 - -#### 關鍵時間欄位 - -| 欄位名 | 用途 | 業務含義 | -|--------|------|---------| -| `MOVEINTIMESTAMP` | 批次移入工序時間 | 批次到達工序的時間 | -| `MOVEOUTTIMESTAMP` | 批次移出工序時間 | 批次離開工序的時間 | -| `TRACKINTIMESTAMP` | 批次上機時間 | 批次開始在設備上加工 | -| `TRACKOUTTIMESTAMP` | 批次下機時間 | 批次完成加工離開設備 | -| `ORIGINALSTARTDATE` | 原始開始日期 | 批次首次開始生產日期 | -| `LAST_UPDATED_DATE` | 最後更新日期 | 記錄更新時間 | -| `LAST_SYNC_DATE` | 最後同步日期 | 資料同步時間 | - -**時間關係**: -``` -MoveIn → TrackIn → TrackOut → MoveOut - ↓ ↓ ↓ ↓ -到達工序 上機加工 完成加工 離開工序 -``` - -#### 關鍵業務欄位 - -**批次標識** -- `WIPLOTHISTORYID`: 歷史記錄唯一ID -- `WIPEQUIPMENTHISTORYID`: 設備歷史關聯ID -- `CONTAINERID` / `FINISHEDRUNCARD`: 批次容器ID與完成品號 -- `PJ_WORKORDER`: 工單號 - -**數量追蹤(4組數量)** -- `MOVEINQTY` / `MOVEINQTY2`: 移入數量(主/輔單位) -- `MOVEOUTQTY` / `MOVEOUTQTY2`: 移出數量 -- `TRACKINQTY` / `TRACKINQTY2`: 上機數量 -- `TRACKOUTQTY` / `TRACKOUTQTY2`: 下機數量 - -**工序與設備** -- `WORKCENTERID` / `WORKCENTERNAME`: 工作中心 -- `SPECID` / `SPECNAME`: 工序規格 -- `EQUIPMENTID` / `EQUIPMENTNAME`: 加工設備 -- `WORKFLOWNAME`: 工藝流程名稱 -- `PROCESSSPECNAME`: 工藝規格 -- `PROCESSTYPENAME`: 工序類型 - -**產品信息** -- `PRODUCTNAME`: 產品名稱 -- `DESCRIPTION`: 產品描述 -- `DATECODE`: 生產週期代碼 -- `PACKAGE_LF`: 封裝Lead Frame信息 - -**Wafer信息** -- `PJ_WAFERID1` / `PJ_WAFERID2` / `PJ_WAFERID3`: Wafer ID - -**人員信息** -- `TRACKINEMPLOYEENAME` / `TRACKINEMPZONE`: 上機人員與區域 -- `TRACKOUTEMPLOYEENAME` / `TRACKOUTEMPZONE`: 下機人員與區域 - -**其他** -- `FLAGNAME`: 標記名稱 -- `CARRIERNAME`: 載具名稱 -- `WIPTRACKINGGROUPKEYID`: WIP追蹤群組Key - -#### 查詢策略 - -**1. 批次完整流轉軌跡查詢** -```sql -SELECT - WIPLOTHISTORYID, - WORKCENTERNAME, - SPECNAME, - EQUIPMENTNAME, - MOVEINTIMESTAMP, - TRACKINTIMESTAMP, - TRACKOUTTIMESTAMP, - MOVEOUTTIMESTAMP, - MOVEINQTY, - MOVEOUTQTY, - ROUND((TRACKOUTTIMESTAMP - TRACKINTIMESTAMP) * 24, 2) as PROCESS_HOURS, - ROUND((MOVEOUTTIMESTAMP - MOVEINTIMESTAMP) * 24, 2) as STATION_HOURS, - TRACKINEMPLOYEENAME, - TRACKOUTEMPLOYEENAME -FROM DW_MES_LOTWIPHISTORY -WHERE CONTAINERID = 'CONTAINER_ID_HERE' -- 或使用 PJ_WORKORDER = 'WO123' -ORDER BY MOVEINTIMESTAMP; -``` - -**2. 工序加工時長分析(Cycle Time)** -```sql -SELECT - WORKCENTERNAME, - SPECNAME, - COUNT(*) as LOT_COUNT, - AVG((TRACKOUTTIMESTAMP - TRACKINTIMESTAMP) * 24) as AVG_PROCESS_HOURS, - MIN((TRACKOUTTIMESTAMP - TRACKINTIMESTAMP) * 24) as MIN_PROCESS_HOURS, - MAX((TRACKOUTTIMESTAMP - TRACKINTIMESTAMP) * 24) as MAX_PROCESS_HOURS, - STDDEV((TRACKOUTTIMESTAMP - TRACKINTIMESTAMP) * 24) as STDDEV_HOURS -FROM DW_MES_LOTWIPHISTORY -WHERE TRACKINTIMESTAMP >= TRUNC(SYSDATE) - 30 - AND TRACKOUTTIMESTAMP IS NOT NULL -GROUP BY WORKCENTERNAME, SPECNAME -ORDER BY AVG_PROCESS_HOURS DESC; -``` - -**3. 設備產出統計(Throughput)** -```sql -SELECT - EQUIPMENTNAME, - WORKCENTERNAME, - TRUNC(TRACKINTIMESTAMP) as WORK_DATE, - COUNT(DISTINCT CONTAINERID) as LOT_COUNT, - SUM(TRACKINQTY) as TOTAL_QTY_IN, - SUM(TRACKOUTQTY) as TOTAL_QTY_OUT, - SUM(TRACKOUTQTY - TRACKINQTY) as QTY_LOSS -FROM DW_MES_LOTWIPHISTORY -WHERE TRACKINTIMESTAMP >= TRUNC(SYSDATE) - 7 - AND EQUIPMENTNAME IS NOT NULL -GROUP BY EQUIPMENTNAME, WORKCENTERNAME, TRUNC(TRACKINTIMESTAMP) -ORDER BY WORK_DATE DESC, TOTAL_QTY_OUT DESC; -``` - -**4. 工序等待時間分析(Queue Time)** -```sql -SELECT - WORKCENTERNAME, - SPECNAME, - COUNT(*) as LOT_COUNT, - AVG((TRACKINTIMESTAMP - MOVEINTIMESTAMP) * 24) as AVG_QUEUE_HOURS, - MAX((TRACKINTIMESTAMP - MOVEINTIMESTAMP) * 24) as MAX_QUEUE_HOURS -FROM DW_MES_LOTWIPHISTORY -WHERE MOVEINTIMESTAMP >= TRUNC(SYSDATE) - 7 - AND TRACKINTIMESTAMP IS NOT NULL -GROUP BY WORKCENTERNAME, SPECNAME -ORDER BY AVG_QUEUE_HOURS DESC; -``` - -**5. 批次數量損耗追蹤** -```sql -SELECT - CONTAINERID, - PJ_WORKORDER, - WORKCENTERNAME, - SPECNAME, - MOVEINQTY, - MOVEOUTQTY, - (MOVEINQTY - MOVEOUTQTY) as QTY_LOSS, - ROUND((MOVEINQTY - MOVEOUTQTY) / NULLIF(MOVEINQTY, 0) * 100, 2) as LOSS_PCT, - MOVEINTIMESTAMP, - MOVEOUTTIMESTAMP -FROM DW_MES_LOTWIPHISTORY -WHERE MOVEINTIMESTAMP >= TRUNC(SYSDATE) - 7 - AND (MOVEINQTY - MOVEOUTQTY) > 0 -- 有損耗 -ORDER BY QTY_LOSS DESC; -``` - -#### 重要注意事項 - -⚠️ **時間範圍必須限制**: 此表有 5300 萬筆資料 - -⚠️ **時間計算**: -- 加工時間 = `TRACKOUTTIMESTAMP - TRACKINTIMESTAMP` -- 在站時間 = `MOVEOUTTIMESTAMP - MOVEINTIMESTAMP` -- 等待時間 = `TRACKINTIMESTAMP - MOVEINTIMESTAMP` - -⚠️ **索引優先使用**: `TRACKINTIMESTAMP`, `MOVEINTIMESTAMP`, `CONTAINERID`, `PJ_WORKORDER` - ---- - -### 8. DW_MES_LOTWIPDATAHISTORY(批次在制品數據歷史表) - -**表性質**: 歷史累積表(數據採集表) - -**業務定義**: 記錄批次在生產過程中採集的所有參數數據(如測試結果、SPC數據等) - -#### 關鍵時間欄位 - -| 欄位名 | 用途 | -|--------|------| -| `TXNTIMESTAMP` | 數據採集時間 | -| `LAST_UPDATED_DATE` | 最後更新日期 | - -#### 關鍵業務欄位 - -**批次與工序** -- `CONTAINERID` / `FINISHEDRUNCARD`: 批次標識 -- `PJ_WORKORDER`: 工單號 -- `WORKCENTERID` / `WORKCENTERNAME`: 工作中心 -- `SPECID` / `SPECNAME`: 工序規格 -- `EQUIPMENTID` / `EQUIPMENTNAME`: 設備 - -**數據內容** -- `WIPDATANAMEID` / `WIPDATANAMENAME`: 數據項名稱 -- `WIPDATAVALUE`: 數據值(最長4000字元) -- `PJ_SPCDATARESULT`: SPC數據結果 - -**關聯信息** -- `WIPLOTHISTORYID`: 關聯LOTWIPHISTORY的ID -- `SERVICENAME`: 服務名稱 -- `PROCESSTYPENAME`: 工序類型 -- `EMPLOYEENAME`: 採集人員 -- `WAFERSCRIBENUMBER`: Wafer刻號 - -#### 查詢策略 - -**1. 查詢批次採集的所有數據** -```sql -SELECT - WIPDATANAMENAME as DATA_NAME, - WIPDATAVALUE as DATA_VALUE, - TXNTIMESTAMP, - WORKCENTERNAME, - SPECNAME, - EQUIPMENTNAME, - EMPLOYEENAME -FROM DW_MES_LOTWIPDATAHISTORY -WHERE CONTAINERID = 'CONTAINER_ID_HERE' -ORDER BY TXNTIMESTAMP, WIPDATANAMENAME; -``` - -**2. 查詢特定參數的歷史趨勢** -```sql -SELECT - CONTAINERID, - TXNTIMESTAMP, - WIPDATAVALUE, - EQUIPMENTNAME, - PJ_SPCDATARESULT -FROM DW_MES_LOTWIPDATAHISTORY -WHERE WIPDATANAMENAME = 'PARAMETER_NAME' -- 如: 'Temperature' - AND TXNTIMESTAMP >= TRUNC(SYSDATE) - 7 -ORDER BY TXNTIMESTAMP; -``` - -**3. SPC異常數據查詢** -```sql -SELECT - CONTAINERID, - PJ_WORKORDER, - WORKCENTERNAME, - SPECNAME, - WIPDATANAMENAME, - WIPDATAVALUE, - PJ_SPCDATARESULT, - TXNTIMESTAMP -FROM DW_MES_LOTWIPDATAHISTORY -WHERE PJ_SPCDATARESULT IN ('Out of Control', 'Warning') -- 根據實際值調整 - AND TXNTIMESTAMP >= TRUNC(SYSDATE) - 7 -ORDER BY TXNTIMESTAMP DESC; -``` - -#### 重要注意事項 - -⚠️ **大數據量表**: 約 7,796 萬筆資料,務必加時間條件 - -⚠️ **與LOTWIPHISTORY關聯**: 通過`WIPLOTHISTORYID`關聯 - -⚠️ **數據值為文字**: `WIPDATAVALUE`是VARCHAR2,數值運算需轉換 - ---- - -### 9. DW_MES_HM_LOTMOVEOUT(批次移出表)⭐⭐ - -**表性質**: 歷史累積表(事件表) - -**業務定義**: 記錄每次批次從工序移出(MoveOut)的事件,是生產流程追蹤的重要數據源 - -#### 關鍵時間欄位 - -| 欄位名 | 用途 | -|--------|------| -| `TXNDATE` | 交易時間(MoveOut時間) | -| `MOVEINTIMESTAMP` | 移入時間 | -| `LASTMOVEOUTTIMESTAMP` | 最後移出時間 | -| `SYSTEMDATE` | 系統時間 | -| `MFGDATE` | 製造日期 | - -#### 關鍵業務欄位 - -**交易信息** -- `HISTORYID` / `HISTORYMAINLINEID`: 歷史記錄ID -- `HISTORYSUMMARYID`: 歷史匯總ID -- `TXNID`: 交易ID -- `TXNTYPE`: 交易類型 - -**批次與容器** -- `CONTAINERID` / `CONTAINERNAME`: 批次容器 -- `CARRIERID` / `CARRIERNAME`: 載具 - -**狀態變更(From → To)** -- `FROMSPECID` / `FROMSPECNAME`: 來源工序 -- `SPECID` / `SPECNAME`: 目標工序 -- `FROMWORKCENTER` / `WORKCENTER`: 工作中心變更 -- `FROMSTATUS` / `STATUS`: 狀態變更 -- `FROMQTY` / `QTY`: 數量變更 -- `FROMQTY2` / `QTY2`: 數量2變更 - -**數量信息** -- `MOVEINQTY` / `MOVEINQTY2`: 移入數量 -- `FROMUOMNAME` / `UOMNAME`: 單位 - -**設備與資源** -- `RESOURCEID` / `RESOURCENAME`: 資源(設備) -- `RESOURCEOBJECTCATEGORY` / `RESOURCEOBJECTTYPE`: 資源類型 -- `RESOURCESTATUSCODEID` / `RESOURCESTATUSREASONID`: 資源狀態 - -**產品與工單** -- `PRODUCTID` / `PRODUCTNAME`: 產品 -- `OWNERID` / `OWNERNAME`: 所有者 -- `WORKFLOWNAME`: 工藝流程 - -**人員信息** -- `EMPLOYEEID` / `EMPLOYEENAME`: 操作人員 -- `USERID` / `USERNAME`: 用戶 -- `USERFULLNAME`: 用戶全名 -- `EMPZONE`: 人員區域 - -**班次與時間** -- `SHIFTNAME`: 班次 -- `COMPUTERNAME`: 電腦名稱 -- `SERVERNAME`: 伺服器名稱 - -**MES CDC信息** -- `CDONAME`: CDO名稱 -- `CDOTXNSEQUENCE`: CDO交易序號 -- `CALLBYCDONAME`: 調用CDO名稱 - -**其他** -- `COMMENTS`: 備註 -- `CONSUMEFACTOR`: 消耗因子 -- `WAFERPRODUCT`: Wafer產品 - -#### 查詢策略 - -**1. 批次流轉記錄查詢** -```sql -SELECT - TXNDATE, - CONTAINERNAME, - FROMSPECNAME as FROM_STEP, - SPECNAME as TO_STEP, - FROMQTY, - QTY, - (FROMQTY - QTY) as QTY_LOSS, - RESOURCENAME, - EMPLOYEENAME, - SHIFTNAME -FROM DW_MES_HM_LOTMOVEOUT -WHERE CONTAINERID = 'CONTAINER_ID_HERE' -ORDER BY TXNDATE; -``` - -**2. 每日產出統計** -```sql -SELECT - TRUNC(TXNDATE) as WORK_DATE, - SPECNAME, - WORKCENTER, - COUNT(DISTINCT CONTAINERID) as LOT_COUNT, - SUM(QTY) as TOTAL_QTY, - COUNT(DISTINCT RESOURCENAME) as EQUIPMENT_COUNT -FROM DW_MES_HM_LOTMOVEOUT -WHERE TXNDATE >= TRUNC(SYSDATE) - 7 -GROUP BY TRUNC(TXNDATE), SPECNAME, WORKCENTER -ORDER BY WORK_DATE DESC, TOTAL_QTY DESC; -``` - -**3. 人員產出績效** -```sql -SELECT - EMPLOYEENAME, - EMPZONE, - COUNT(DISTINCT CONTAINERID) as LOT_COUNT, - SUM(QTY) as TOTAL_OUTPUT, - COUNT(*) as OPERATION_COUNT -FROM DW_MES_HM_LOTMOVEOUT -WHERE TXNDATE >= TRUNC(SYSDATE) - 7 -GROUP BY EMPLOYEENAME, EMPZONE -ORDER BY TOTAL_OUTPUT DESC; -``` - -#### 重要注意事項 - -⚠️ **大數據量**: 約 4,865 萬筆,必須加時間條件 - -⚠️ **與LOTWIPHISTORY差異**: -- HM_LOTMOVEOUT: 只記錄MoveOut事件 -- LOTWIPHISTORY: 記錄完整的MoveIn/TrackIn/TrackOut/MoveOut - ---- - -### 10. 其他歷史表簡要說明 - -#### DW_MES_LOTREJECTHISTORY(批次拒絕歷史表) -- **用途**: 記錄批次報廢、損耗的歷史 -- **關鍵欄位**: - - `REJECTQTY`: 拒絕數量 - - `LOSSREASONNAME`: 損耗原因 - - `REJECTCATEGORYNAME`: 拒絕類別 -- **查詢場景**: 良率分析、損耗原因分析 - -#### DW_MES_LOTMATERIALSHISTORY(批次物料歷史表) -- **用途**: 記錄批次使用物料的歷史 -- **關鍵欄位**: - - `MATERIALPARTNAME`: 物料名稱 - - `MATERIALLOTNAME`: 物料批號 - - `QTYCONSUMED`: 消耗數量 - - `CONSUMEFACTOR`: 消耗因子 -- **查詢場景**: 物料追溯、消耗分析 - -#### DW_MES_HOLDRELEASEHISTORY(暫停/釋放歷史表) -- **用途**: 記錄批次Hold和Release的完整歷史 -- **關鍵欄位**: - - `HOLDTXNDATE` / `RELEASETXNDATE`: Hold/Release時間 - - `HOLDREASONNAME` / `RELEASEREASONNAME`: Hold/Release原因 - - `HOLDEMP` / `RELEASEEMP`: 操作人員 -- **查詢場景**: Hold原因分析、Hold時長統計 - -#### DW_MES_JOBTXNHISTORY(維修工單交易歷史表) -- **用途**: 記錄維修工單的狀態變更歷史 -- **關鍵欄位**: - - `FROMJOBSTATUS` / `JOBSTATUS`: 狀態變更 - - `TXNDATE`: 交易時間 -- **查詢場景**: 維修工單流程追蹤 - -#### DW_MES_MAINTENANCE(維護記錄表) -- **用途**: 記錄設備維護保養的詳細記錄 -- **關鍵欄位**: - - `MAINTENANCEREQNAME`: 維護需求名稱 - - `THRUPUTQTY`: 產出數量 - - `DATAVALUE`: 維護數據值 -- **查詢場景**: 設備保養追蹤、維護計劃執行狀況 - ---- - -## 表間關聯關係圖 - -### 核心實體關係 - -``` -┌─────────────────────────────────────────────────────────────────┐ -│ 核心實體關係圖 │ -└─────────────────────────────────────────────────────────────────┘ - -1. 在制品流轉主線(核心業務流程) - - DW_MES_WIP (現況快照,含歷史累積) - ↓ CONTAINERID - DW_MES_CONTAINER (容器主檔) - ↓ CONTAINERID - DW_MES_LOTWIPHISTORY (流轉歷史) - ↓ WIPLOTHISTORYID - DW_MES_LOTWIPDATAHISTORY (數據採集歷史) - - DW_MES_LOTWIPHISTORY - ↓ CONTAINERID - DW_MES_HM_LOTMOVEOUT (移出事件) - - -2. 資源狀態主線(設備管理) - - DW_MES_RESOURCE (資源主檔) - ↓ RESOURCEID - DW_MES_RESOURCESTATUS (狀態變更歷史) - ↓ HISTORYID (= RESOURCEID) - DW_MES_RESOURCESTATUS_SHIFT (班次彙總) - - -3. 工單維修主線(維修管理) - - DW_MES_JOB (工單現況) - ↓ JOBID - DW_MES_JOBTXNHISTORY (維修工單交易歷史) - - DW_MES_JOB - ↓ RESOURCEID - DW_MES_RESOURCE (關聯設備) - - DW_MES_JOB - ↓ JOBID - DW_MES_PARTREQUESTORDER (物料請求) - - -4. 批次異常處理主線 - - DW_MES_WIP / DW_MES_CONTAINER - ↓ CONTAINERID - DW_MES_HOLDRELEASEHISTORY (Hold/Release歷史) - - DW_MES_LOTWIPHISTORY - ↓ HISTORYMAINLINEID - DW_MES_LOTREJECTHISTORY (拒絕歷史) - - -5. 物料消耗主線 - - DW_MES_LOTWIPHISTORY - ↓ CONTAINERID - DW_MES_LOTMATERIALSHISTORY (物料消耗歷史) - - -6. 設備維護主線 - - DW_MES_RESOURCE - ↓ RESOURCEID - DW_MES_MAINTENANCE (維護記錄) -``` - -### 詳細關聯鍵對照表 - -| 主表 | 關聯表 | 關聯欄位 | 關聯類型 | 說明 | -|------|--------|---------|---------|------| -| **DW_MES_WIP** | DW_MES_CONTAINER | CONTAINERID | 1:1 | 在制品關聯容器 | -| **DW_MES_CONTAINER** | DW_MES_LOTWIPHISTORY | CONTAINERID | 1:N | 容器的流轉歷史 | -| **DW_MES_LOTWIPHISTORY** | DW_MES_LOTWIPDATAHISTORY | WIPLOTHISTORYID | 1:N | 流轉記錄的數據採集 | -| **DW_MES_LOTWIPHISTORY** | DW_MES_HM_LOTMOVEOUT | CONTAINERID + HISTORYMAINLINEID | 1:N | 流轉的移出事件 | -| **DW_MES_LOTWIPHISTORY** | DW_MES_LOTREJECTHISTORY | HISTORYMAINLINEID | 1:N | 流轉的拒絕記錄 | -| **DW_MES_LOTWIPHISTORY** | DW_MES_LOTMATERIALSHISTORY | CONTAINERID | 1:N | 流轉的物料消耗 | -| **DW_MES_WIP** | DW_MES_HOLDRELEASEHISTORY | CONTAINERID | 1:N | 在制品的Hold歷史 | -| **DW_MES_RESOURCE** | DW_MES_RESOURCESTATUS | RESOURCEID = HISTORYID | 1:N | 資源的狀態歷史 | -| **DW_MES_RESOURCE** | DW_MES_RESOURCESTATUS_SHIFT | RESOURCEID = HISTORYID | 1:N | 資源的班次彙總 | -| **DW_MES_RESOURCE** | DW_MES_MAINTENANCE | RESOURCEID | 1:N | 資源的維護記錄 | -| **DW_MES_RESOURCE** | DW_MES_PARTREQUESTORDER | RESOURCEID | 1:N | 資源的維修用料請求 | -| **DW_MES_RESOURCE** | DW_MES_HM_LOTMOVEOUT | RESOURCEID | 1:N | 資源對應的移出事件 | -| **DW_MES_JOB** | DW_MES_JOBTXNHISTORY | JOBID | 1:N | 工單的交易歷史 | -| **DW_MES_JOB** | DW_MES_RESOURCE | RESOURCEID | N:1 | 工單關聯資源 | -| **DW_MES_JOB** | DW_MES_PARTREQUESTORDER | JOBID | 1:N | 工單的物料請求 | -| **DW_MES_CONTAINER** | DW_MES_PJ_COMBINEDASSYLOTS | CONTAINERID | 1:N | 容器的組合裝配 | - -### Reference 備註確認的關聯 - -以下關聯來自 `MES_Database_Reference.md` 的欄位備註(維護人註記): - -| 表 | 欄位 | 備註 | 可推得關聯/用途 | -|------|------|------|----------------| -| **DW_MES_RESOURCESTATUS** | HISTORYID | RESOURCEID | 關聯 `DW_MES_RESOURCE.RESOURCEID` | -| **DW_MES_RESOURCESTATUS_SHIFT** | HISTORYID | RESOURCEID | 關聯 `DW_MES_RESOURCE.RESOURCEID` | -| **DW_MES_JOB** | PARTREQUESTORDERNAME | DW_MES_PARTREQUESTORDER | 可由 `DW_MES_PARTREQUESTORDER` 取得工單請領資訊 | -| **DW_MES_WIP** | RELEASETIME / RELEASEEMP / RELEASEREASON | DW_MES_HOLDRELEASEHISTORY | WIP 的解除資訊來源於 Hold/Release 歷史 | - -### 欄位來源備註(同表內派生) - -以下備註顯示欄位來源於同表關鍵欄位(非跨表),建議查詢時以 ID 欄位為主: - -| 表 | 欄位 | 備註 | -|------|------|------| -| **DW_MES_CONTAINER** | MFGORDERNAME / PJ_BOP / PJ_PRODUCEREGION / PRODUCTBOMBASEID | MFGORDERID | -| **DW_MES_WIP** | STARTREASONNAME / MFGORDERNAME / FIRSTNAME / OWNERNAME / PRIORITYCODENAME / PRODUCTBOMBASEID / PRODUCTNAME / PRODUCTLINENAME / PJ_BOP / PJ_PRODUCEREGION / PJ_TYPE / PJ_FUNCTION | CONTAINERID | -| **DW_MES_WIP** | WOQTY / WOPLANNEDCOMPLETIONDATE | CONTAINERID -> MFGORDERID | - -### 關鍵關聯欄位說明 - -#### CONTAINERID -- 批次/容器的唯一標識(16位元CHAR) -- 貫穿所有與批次相關的表 -- 最重要的關聯欄位 - -#### RESOURCEID / HISTORYID -- RESOURCE表使用 `RESOURCEID` -- RESOURCESTATUS表使用 `HISTORYID`(實際上等於RESOURCEID) -- 關聯時注意欄位名稱差異 - -#### HISTORYMAINLINEID -- 歷史記錄的主線ID -- 用於關聯同一批次在不同歷史表的記錄 - -#### WIPLOTHISTORYID -- LOTWIPHISTORY的主鍵 -- LOTWIPDATAHISTORY用此欄位關聯 - -#### PJ_WORKORDER -- 工單號(業務鍵) -- 部分表使用此欄位追蹤批次 - ---- - -## 關鍵業務場景查詢策略 - -### 場景1: 在制品(WIP)看板 - -**需求**: 顯示當前所有在制品的狀態、位置、停滯時間 - -**推薦表**: `DW_MES_WIP` - -**查詢邏輯**: -```sql -SELECT - CONTAINERNAME, - PRODUCTNAME, - PRODUCTLINENAME, - WORKCENTERNAME, - WORKFLOWSTEPNAME, - QTY, - MOVEINTIMESTAMP, - ROUND((SYSDATE - MOVEINTIMESTAMP) * 24, 2) as HOURS_IN_STATION, - CURRENTHOLDCOUNT, - HOLDREASONNAME, - LOCATIONNAME -FROM DW_MES_WIP -WHERE STATUS NOT IN (8, 128) -- 排除已完成或取消 -ORDER BY HOURS_IN_STATION DESC; -``` - -**效能優化**: -- 使用索引: `TXNDATE`, `CONTAINERNAME` -- 建議增加工作中心或產品線篩選 - ---- - -### 場景2: 設備稼動率(OEE)報表 - -**需求**: 計算每日設備的稼動率、停機時長 - -**推薦表**: `DW_MES_RESOURCESTATUS_SHIFT`(首選,已彙總) - -**查詢邏輯**: -```sql -SELECT - DATADATE, - HISTORYID as RESOURCE_ID, - WORKCENTERNAME, - -- 生產時間 - SUM(CASE WHEN AVAILABILITY = 1 THEN HOURS ELSE 0 END) as PRODUCTIVE_HOURS, - -- 待機時間 - SUM(CASE WHEN AVAILABILITY = 2 THEN HOURS ELSE 0 END) as STANDBY_HOURS, - -- 非計劃停機 - SUM(CASE WHEN AVAILABILITY = 4 THEN HOURS ELSE 0 END) as UNSCHEDULED_DOWN_HOURS, - -- 計劃停機 - SUM(CASE WHEN AVAILABILITY = 5 THEN HOURS ELSE 0 END) as SCHEDULED_DOWN_HOURS, - -- 總時間 - SUM(HOURS) as TOTAL_HOURS, - -- 稼動率 - ROUND(SUM(CASE WHEN AVAILABILITY = 1 THEN HOURS ELSE 0 END) / NULLIF(SUM(HOURS), 0) * 100, 2) as UTILIZATION_PCT -FROM DW_MES_RESOURCESTATUS_SHIFT -WHERE DATADATE >= TRUNC(SYSDATE) - 7 -GROUP BY DATADATE, HISTORYID, WORKCENTERNAME -ORDER BY DATADATE DESC, UTILIZATION_PCT DESC; -``` - -**替代方案**: 若需要更細緻的時間分析,使用 `DW_MES_RESOURCESTATUS` - -**效能優化**: -- 優先使用 `DATADATE` 索引 -- 班次表比狀態表效率高約10倍 - ---- - -### 場景3: 批次生產履歷追溯 - -**需求**: 追溯某批次的完整生產過程(每個工序的時間、設備、人員) - -**推薦表**: `DW_MES_LOTWIPHISTORY` - -**查詢邏輯**: -```sql -SELECT - WIPLOTHISTORYID, - WORKCENTERNAME, - SPECNAME, - EQUIPMENTNAME, - MOVEINTIMESTAMP, - TRACKINTIMESTAMP, - TRACKOUTTIMESTAMP, - MOVEOUTTIMESTAMP, - MOVEINQTY, - MOVEOUTQTY, - (MOVEINQTY - MOVEOUTQTY) as QTY_LOSS, - ROUND((TRACKOUTTIMESTAMP - TRACKINTIMESTAMP) * 24, 2) as PROCESS_HOURS, - ROUND((MOVEOUTTIMESTAMP - MOVEINTIMESTAMP) * 24, 2) as STATION_HOURS, - ROUND((TRACKINTIMESTAMP - MOVEINTIMESTAMP) * 24, 2) as QUEUE_HOURS, - TRACKINEMPLOYEENAME, - TRACKOUTEMPLOYEENAME, - FLAGNAME -FROM DW_MES_LOTWIPHISTORY -WHERE CONTAINERID = 'CONTAINER_ID_HERE' -- 或使用 PJ_WORKORDER -ORDER BY MOVEINTIMESTAMP; -``` - -**擴展查詢**: 加入採集數據 -```sql -SELECT - lwh.SPECNAME, - lwh.EQUIPMENTNAME, - lwh.TRACKINTIMESTAMP, - lwd.WIPDATANAMENAME, - lwd.WIPDATAVALUE, - lwd.PJ_SPCDATARESULT -FROM DW_MES_LOTWIPHISTORY lwh -LEFT JOIN DW_MES_LOTWIPDATAHISTORY lwd - ON lwh.WIPLOTHISTORYID = lwd.WIPLOTHISTORYID -WHERE lwh.CONTAINERID = 'CONTAINER_ID_HERE' -ORDER BY lwh.MOVEINTIMESTAMP, lwd.WIPDATANAMENAME; -``` - ---- - -### 場景4: 工序Cycle Time分析 - -**需求**: 分析各工序的平均加工時間、最大/最小時間 - -**推薦表**: `DW_MES_LOTWIPHISTORY` - -**查詢邏輯**: -```sql -SELECT - WORKCENTERNAME, - SPECNAME, - PROCESSTYPENAME, - COUNT(*) as LOT_COUNT, - -- 加工時間統計 - ROUND(AVG((TRACKOUTTIMESTAMP - TRACKINTIMESTAMP) * 24), 2) as AVG_PROCESS_HOURS, - ROUND(MIN((TRACKOUTTIMESTAMP - TRACKINTIMESTAMP) * 24), 2) as MIN_PROCESS_HOURS, - ROUND(MAX((TRACKOUTTIMESTAMP - TRACKINTIMESTAMP) * 24), 2) as MAX_PROCESS_HOURS, - ROUND(STDDEV((TRACKOUTTIMESTAMP - TRACKINTIMESTAMP) * 24), 2) as STDDEV_HOURS, - -- 在站時間統計 - ROUND(AVG((MOVEOUTTIMESTAMP - MOVEINTIMESTAMP) * 24), 2) as AVG_STATION_HOURS, - -- 等待時間統計 - ROUND(AVG((TRACKINTIMESTAMP - MOVEINTIMESTAMP) * 24), 2) as AVG_QUEUE_HOURS -FROM DW_MES_LOTWIPHISTORY -WHERE TRACKINTIMESTAMP >= TRUNC(SYSDATE) - 30 - AND TRACKOUTTIMESTAMP IS NOT NULL - AND (TRACKOUTTIMESTAMP - TRACKINTIMESTAMP) > 0 -- 排除異常數據 -GROUP BY WORKCENTERNAME, SPECNAME, PROCESSTYPENAME -ORDER BY AVG_PROCESS_HOURS DESC; -``` - -**瓶頸工序識別**: -```sql -SELECT - WORKCENTERNAME, - SPECNAME, - AVG((MOVEOUTTIMESTAMP - MOVEINTIMESTAMP) * 24) as AVG_STATION_HOURS, - COUNT(*) as LOT_COUNT -FROM DW_MES_LOTWIPHISTORY -WHERE MOVEINTIMESTAMP >= TRUNC(SYSDATE) - 7 -GROUP BY WORKCENTERNAME, SPECNAME -HAVING AVG((MOVEOUTTIMESTAMP - MOVEINTIMESTAMP) * 24) > 24 -- 在站超過24小時 -ORDER BY AVG_STATION_HOURS DESC; -``` - ---- - -### 場景5: 設備產出與效率分析 - -**需求**: 統計各設備的產出數量、良率、稼動時間 - -**推薦表**: -- 產出數量: `DW_MES_LOTWIPHISTORY` -- 良率: `DW_MES_LOTREJECTHISTORY` -- 稼動: `DW_MES_RESOURCESTATUS_SHIFT` - -**查詢邏輯(產出)**: -```sql -SELECT - EQUIPMENTNAME, - WORKCENTERNAME, - TRUNC(TRACKINTIMESTAMP) as WORK_DATE, - COUNT(DISTINCT CONTAINERID) as LOT_COUNT, - SUM(TRACKINQTY) as TOTAL_INPUT_QTY, - SUM(TRACKOUTQTY) as TOTAL_OUTPUT_QTY, - SUM(TRACKINQTY - TRACKOUTQTY) as TOTAL_LOSS_QTY, - ROUND((1 - SUM(TRACKINQTY - TRACKOUTQTY) / NULLIF(SUM(TRACKINQTY), 0)) * 100, 2) as YIELD_PCT -FROM DW_MES_LOTWIPHISTORY -WHERE TRACKINTIMESTAMP >= TRUNC(SYSDATE) - 7 - AND EQUIPMENTNAME IS NOT NULL -GROUP BY EQUIPMENTNAME, WORKCENTERNAME, TRUNC(TRACKINTIMESTAMP) -ORDER BY WORK_DATE DESC, TOTAL_OUTPUT_QTY DESC; -``` - -**整合稼動率查詢**: -```sql -SELECT - r.HISTORYID as RESOURCE_ID, - r.WORKCENTERNAME, - r.DATADATE, - -- 稼動數據 - SUM(CASE WHEN r.AVAILABILITY = 1 THEN r.HOURS ELSE 0 END) as PRODUCTIVE_HOURS, - ROUND(SUM(CASE WHEN r.AVAILABILITY = 1 THEN r.HOURS ELSE 0 END) / NULLIF(SUM(r.HOURS), 0) * 100, 2) as UTILIZATION_PCT, - -- 產出數據 - COUNT(DISTINCT w.CONTAINERID) as LOT_COUNT, - SUM(w.TRACKOUTQTY) as TOTAL_OUTPUT_QTY -FROM DW_MES_RESOURCESTATUS_SHIFT r -LEFT JOIN DW_MES_LOTWIPHISTORY w - ON r.HISTORYID = w.EQUIPMENTID - AND TRUNC(w.TRACKINTIMESTAMP) = r.DATADATE -WHERE r.DATADATE >= TRUNC(SYSDATE) - 7 -GROUP BY r.HISTORYID, r.WORKCENTERNAME, r.DATADATE -ORDER BY r.DATADATE DESC, UTILIZATION_PCT DESC; -``` - ---- - -### 場景6: Hold批次分析 - -**需求**: 統計當前Hold批次、Hold原因、Hold時長 - -**推薦表**: -- 當前狀態: `DW_MES_WIP` -- 歷史記錄: `DW_MES_HOLDRELEASEHISTORY` - -**查詢邏輯(當前Hold)**: -```sql -SELECT - CONTAINERNAME, - PRODUCTNAME, - PRODUCTLINENAME, - WORKCENTERNAME, - WORKFLOWSTEPNAME, - HOLDREASONNAME, - HOLDTIME, - ROUND((SYSDATE - HOLDTIME) * 24, 2) as HOLD_HOURS, - HOLDEMP, - HOLDLOCATIONNAME, - CURRENTHOLDCOUNT, - HOLDCOMMENT_FUTURE -FROM DW_MES_WIP -WHERE CURRENTHOLDCOUNT > 0 - AND STATUS NOT IN (8, 128) -ORDER BY HOLD_HOURS DESC; -``` - -**查詢邏輯(Hold歷史分析)**: -```sql -SELECT - HOLDREASONNAME, - COUNT(*) as HOLD_COUNT, - AVG((RELEASETXNDATE - HOLDTXNDATE) * 24) as AVG_HOLD_HOURS, - MAX((RELEASETXNDATE - HOLDTXNDATE) * 24) as MAX_HOLD_HOURS, - SUM(QTY) as TOTAL_HOLD_QTY -FROM DW_MES_HOLDRELEASEHISTORY -WHERE HOLDTXNDATE >= TRUNC(SYSDATE) - 30 - AND RELEASETXNDATE IS NOT NULL -GROUP BY HOLDREASONNAME -ORDER BY HOLD_COUNT DESC; -``` - ---- - -### 場景7: 設備維修工單進度追蹤 - -**需求**: 查詢工單的投入數量、完成數量、在制數量、預計完成時間 - -**推薦表**: `DW_MES_WIP` + `DW_MES_CONTAINER` - -**查詢邏輯**: -```sql -WITH WO_SUMMARY AS ( - SELECT - MFGORDERNAME, - PRODUCTNAME, - MAX(WOQTY) as WO_TOTAL_QTY, - MAX(WOPLANNEDCOMPLETIONDATE) as PLANNED_COMPLETION_DATE, - COUNT(DISTINCT CONTAINERNAME) as LOT_COUNT, - SUM(QTY) as CURRENT_WIP_QTY, - SUM(CASE WHEN CURRENTHOLDCOUNT > 0 THEN QTY ELSE 0 END) as HOLD_QTY, - MIN(MOVEINTIMESTAMP) as FIRST_MOVEIN, - MAX(MOVEINTIMESTAMP) as LAST_MOVEIN - FROM DW_MES_WIP - WHERE STATUS NOT IN (8, 128) - GROUP BY MFGORDERNAME, PRODUCTNAME -) -SELECT - MFGORDERNAME, - PRODUCTNAME, - WO_TOTAL_QTY, - CURRENT_WIP_QTY, - HOLD_QTY, - (WO_TOTAL_QTY - CURRENT_WIP_QTY) as COMPLETED_QTY, - ROUND((CURRENT_WIP_QTY / NULLIF(WO_TOTAL_QTY, 0)) * 100, 2) as WIP_PCT, - ROUND((HOLD_QTY / NULLIF(CURRENT_WIP_QTY, 0)) * 100, 2) as HOLD_PCT, - PLANNED_COMPLETION_DATE, - CASE - WHEN PLANNED_COMPLETION_DATE < SYSDATE THEN 'Overdue' - WHEN PLANNED_COMPLETION_DATE < SYSDATE + 3 THEN 'Critical' - ELSE 'On Track' - END as STATUS, - LOT_COUNT, - FIRST_MOVEIN, - LAST_MOVEIN -FROM WO_SUMMARY -ORDER BY PLANNED_COMPLETION_DATE; -``` - ---- - -### 場景8: 良率分析 - -**需求**: 分析各工序、產品的良率 - -**推薦表**: -- `DW_MES_LOTWIPHISTORY`(產出) -- `DW_MES_LOTREJECTHISTORY`(報廢) - -**查詢邏輯**: -```sql -SELECT - w.WORKCENTERNAME, - w.SPECNAME, - w.PRODUCTNAME, - TRUNC(w.MOVEINTIMESTAMP) as WORK_DATE, - -- 產出統計 - COUNT(DISTINCT w.CONTAINERID) as LOT_COUNT, - SUM(w.MOVEINQTY) as TOTAL_INPUT_QTY, - SUM(w.MOVEOUTQTY) as TOTAL_OUTPUT_QTY, - -- 報廢統計 - SUM(NVL(r.REJECTQTY, 0)) as TOTAL_REJECT_QTY, - -- 良率計算 - ROUND((1 - SUM(NVL(r.REJECTQTY, 0)) / NULLIF(SUM(w.MOVEINQTY), 0)) * 100, 2) as YIELD_PCT -FROM DW_MES_LOTWIPHISTORY w -LEFT JOIN DW_MES_LOTREJECTHISTORY r - ON w.CONTAINERID = r.CONTAINERID - AND w.SPECID = r.SPECID - AND TRUNC(w.MOVEINTIMESTAMP) = TRUNC(r.TXNDATE) -WHERE w.MOVEINTIMESTAMP >= TRUNC(SYSDATE) - 30 -GROUP BY w.WORKCENTERNAME, w.SPECNAME, w.PRODUCTNAME, TRUNC(w.MOVEINTIMESTAMP) -ORDER BY WORK_DATE DESC, YIELD_PCT ASC; -``` - -**報廢原因分析**: -```sql -SELECT - WORKCENTERNAME, - SPECNAME, - LOSSREASONNAME, - REJECTCATEGORYNAME, - COUNT(*) as OCCURRENCE_COUNT, - SUM(REJECTQTY) as TOTAL_REJECT_QTY, - AVG(REJECTQTY) as AVG_REJECT_QTY_PER_LOT -FROM DW_MES_LOTREJECTHISTORY -WHERE TXNDATE >= TRUNC(SYSDATE) - 30 -GROUP BY WORKCENTERNAME, SPECNAME, LOSSREASONNAME, REJECTCATEGORYNAME -ORDER BY TOTAL_REJECT_QTY DESC; -``` - ---- - -## 查詢效能最佳實踐 - -### 1. 大表查詢原則 - -#### 必須加時間範圍的表(>1000萬筆) -- `DW_MES_WIP`: 使用 `TXNDATE` -- `DW_MES_LOTWIPDATAHISTORY`: 使用 `TXNTIMESTAMP` -- `DW_MES_RESOURCESTATUS_SHIFT`: 使用 `DATADATE`(推薦) -- `DW_MES_RESOURCESTATUS`: 使用 `OLDLASTSTATUSCHANGEDATE` -- `DW_MES_LOTWIPHISTORY`: 使用 `TRACKINTIMESTAMP` 或 `MOVEINTIMESTAMP` -- `DW_MES_MAINTENANCE`: 使用 `TXNDATE` -- `DW_MES_HM_LOTMOVEOUT`: 使用 `TXNDATE` -- `DW_MES_LOTMATERIALSHISTORY`: 使用 `TXNDATE` -- `DW_MES_LOTREJECTHISTORY`: 使用 `TXNDATE` - -#### 推薦時間範圍 -```sql --- 日報表 -WHERE DATADATE >= TRUNC(SYSDATE) - 7 - --- 週報表 -WHERE DATADATE >= TRUNC(SYSDATE, 'IW') - 7 - --- 月報表 -WHERE DATADATE >= TRUNC(SYSDATE, 'MM') -``` - -### 2. 索引使用策略 - -#### 優先使用索引欄位 -```sql --- 好的寫法(使用索引) -WHERE TXNDATE >= TRUNC(SYSDATE) - 7 - AND CONTAINERNAME = 'LOT123' - --- 不好的寫法(破壞索引) -WHERE TO_CHAR(TXNDATE, 'YYYY-MM-DD') = '2026-01-14' - OR UPPER(CONTAINERNAME) = 'LOT123' -``` - -#### 各表主要索引 - -| 表名 | 推薦查詢索引 | -|------|------------| -| DW_MES_WIP | `CONTAINERNAME`, `TXNDATE` | -| DW_MES_RESOURCESTATUS_SHIFT | `DATADATE`, `HISTORYID` | -| DW_MES_LOTWIPHISTORY | `TRACKINTIMESTAMP`, `CONTAINERID`, `PJ_WORKORDER` | -| DW_MES_HM_LOTMOVEOUT | `TXNDATE`, `HISTORYID` | - -### 3. JOIN優化 - -#### 推薦JOIN順序 -```sql --- 小表 JOIN 大表 -SELECT ... -FROM DW_MES_RESOURCE r -- 90K rows -INNER JOIN DW_MES_RESOURCESTATUS_SHIFT rs -- 74M rows - ON r.RESOURCEID = rs.HISTORYID -WHERE rs.DATADATE >= TRUNC(SYSDATE) - 7 -- 先過濾大表 -``` - -#### 避免笛卡爾積 -```sql --- 使用 DISTINCT 或 GROUP BY 去重 -SELECT DISTINCT - w.CONTAINERNAME, - r.RESOURCENAME -FROM DW_MES_WIP w -INNER JOIN DW_MES_LOTWIPHISTORY h - ON w.CONTAINERID = h.CONTAINERID -``` - -### 4. 聚合查詢優化 - -#### 使用SHIFT表而非原始表 -```sql --- 推薦:使用班次彙總表 -SELECT DATADATE, SUM(HOURS) -FROM DW_MES_RESOURCESTATUS_SHIFT -WHERE DATADATE >= TRUNC(SYSDATE) - 30 -GROUP BY DATADATE; - --- 不推薦:使用原始狀態表 -SELECT TRUNC(OLDLASTSTATUSCHANGEDATE), - SUM((LASTSTATUSCHANGEDATE - OLDLASTSTATUSCHANGEDATE) * 24) -FROM DW_MES_RESOURCESTATUS -WHERE OLDLASTSTATUSCHANGEDATE >= TRUNC(SYSDATE) - 30 -GROUP BY TRUNC(OLDLASTSTATUSCHANGEDATE); -``` - -### 5. 分頁查詢 - -```sql --- Oracle 12c+ 使用 OFFSET FETCH -SELECT * -FROM ( - SELECT CONTAINERNAME, PRODUCTNAME, MOVEINTIMESTAMP - FROM DW_MES_WIP - WHERE STATUS NOT IN (8, 128) - ORDER BY MOVEINTIMESTAMP DESC -) -OFFSET 0 ROWS FETCH NEXT 100 ROWS ONLY; - --- Oracle 11g 使用 ROWNUM -SELECT * -FROM ( - SELECT ROWNUM as RN, t.* - FROM ( - SELECT CONTAINERNAME, PRODUCTNAME, MOVEINTIMESTAMP - FROM DW_MES_WIP - WHERE STATUS NOT IN (8, 128) - ORDER BY MOVEINTIMESTAMP DESC - ) t - WHERE ROWNUM <= 100 -) -WHERE RN > 0; -``` - ---- - -## 附錄:常用代碼對照表 - -### STATUS 狀態碼 - -| STATUS值 | 含義 | -|---------|------| -| 1 | In Progress(進行中) | -| 2 | On Hold(暫停) | -| 4 | Released(已釋放) | -| 8 | Completed(已完成) | -| 16 | In Queue(排隊中) | -| 32 | Reserved(保留) | -| 64 | In Transit(運輸中) | -| 128 | Cancelled(已取消) | - -### AVAILABILITY 可用性代碼 - -| AVAILABILITY | 含義 | 用途 | -|-------------|------|------| -| 1 | Productive | 生產中(計入稼動時間) | -| 2 | Standby | 待機(不計入稼動) | -| 3 | Non-Scheduled | 非排程時間 | -| 4 | Unscheduled Down | 非計劃停機(故障) | -| 5 | Scheduled Down | 計劃停機(保養) | - -### TXNTYPE 交易類型 - -需根據實際系統定義 - -### OBJECTTYPE 資源類型 - -| OBJECTTYPE | 說明 | -|-----------|------| -| Equipment | 設備 | -| WorkStation | 工作站 | -| Location | 位置 | - ---- - -## 總結與建議 - -### 表選擇決策樹 - -``` -查詢需求分類: - -1. 要查詢"當前狀態" → 使用快照表 - - 在制品現況 → DW_MES_WIP - - 設備基本信息 → DW_MES_RESOURCE - - 容器當前狀態 → DW_MES_CONTAINER - - 設備維修工單當前狀態 → DW_MES_JOB - -2. 要查詢"歷史記錄" → 使用歷史表 - - 批次流轉歷史 → DW_MES_LOTWIPHISTORY - - 設備狀態歷史 → DW_MES_RESOURCESTATUS_SHIFT(推薦)或 RESOURCESTATUS - - 批次移出事件 → DW_MES_HM_LOTMOVEOUT - - 數據採集歷史 → DW_MES_LOTWIPDATAHISTORY - -3. 要做"統計分析" → 優先使用彙總表 - - 設備稼動率 → DW_MES_RESOURCESTATUS_SHIFT(已計算HOURS) - - 產出統計 → DW_MES_LOTWIPHISTORY - - 良率分析 → DW_MES_LOTWIPHISTORY + DW_MES_LOTREJECTHISTORY -``` - -### 開發優先級建議 - -#### 第一階段:基礎報表(必須) -1. 在制品看板(WIP Dashboard) -2. 設備稼動率報表(OEE Report) -3. 設備維修工單進度追蹤(WO Progress) - -#### 第二階段:分析報表(重要) -4. Cycle Time分析 -5. 設備產出分析 -6. Hold批次分析 - -#### 第三階段:深度分析(進階) -7. 良率分析 -8. 瓶頸工序分析 -9. 批次履歷追溯 - -### 效能關鍵注意事項 - -⚠️ **關鍵警告**: -1. 所有大表(>1000萬筆)查詢必須加時間範圍 -2. 優先使用班次彙總表(SHIFT)而非原始表 -3. 避免在索引欄位使用函數 -4. JOIN時先過濾再關聯 -5. 使用EXPLAIN PLAN檢查執行計劃 - ---- - -**文檔版本**: v1.2 -**最後更新**: 2026-01-29 -**更新內容**: DWH 全表掃描更新數據量、補充 DW_MES_SPEC_WORKCENTER_V 工站對照視圖與查詢策略 -**建議更新週期**: 每季度或表結構變更時 - - - - diff --git a/docs/Oracle_Authorized_Objects.md b/docs/Oracle_Authorized_Objects.md index ef7e095..e07998e 100644 --- a/docs/Oracle_Authorized_Objects.md +++ b/docs/Oracle_Authorized_Objects.md @@ -1,15 +1,15 @@ # Oracle 可使用 TABLE/VIEW 清單(DWH) -**產生時間**: 2026-01-29 13:34:22 -**使用者**: (詳見 .env 中的 DB_USER) +**產生時間**: 2026-02-13 17:39:41 +**使用者**: MBU1_R **Schema**: DWH ## 摘要 -- 可使用物件總數: 19 -- TABLE: 16 +- 可使用物件總數: 22 +- TABLE: 19 - VIEW: 3 -- 來源 (去重後物件數): DIRECT 19, PUBLIC 0, ROLE 0, SYSTEM 0 +- 來源 (去重後物件數): DIRECT 22, PUBLIC 0, ROLE 0, SYSTEM 0 ## 物件清單 @@ -33,4 +33,7 @@ | `DWH.DW_MES_RESOURCESTATUS` | TABLE | SELECT | DIRECT | | `DWH.DW_MES_RESOURCESTATUS_SHIFT` | TABLE | SELECT | DIRECT | | `DWH.DW_MES_SPEC_WORKCENTER_V` | VIEW | SELECT | DIRECT | -| `DWH.DW_MES_WIP` | TABLE | SELECT | DIRECT | \ No newline at end of file +| `DWH.DW_MES_WIP` | TABLE | SELECT | DIRECT | +| `DWH.ERP_PJ_WIP_SCRAP_REASONS_EXCLUDE` | TABLE | SELECT | DIRECT | +| `DWH.ERP_WIP_MOVETXN` | TABLE | SELECT | DIRECT | +| `DWH.ERP_WIP_MOVETXN_DETAIL` | TABLE | SELECT | DIRECT | \ No newline at end of file diff --git a/docs/architecture_findings.md b/docs/architecture_findings.md deleted file mode 100644 index e9349dd..0000000 --- a/docs/architecture_findings.md +++ /dev/null @@ -1,936 +0,0 @@ -# MES Dashboard - Architecture Findings - -本文件記錄專案開發過程中確立的架構設計、全局規範與資料處理規則。 - ---- - -## 1. 資料庫連線管理 - -### 連線池統一使用 -所有資料庫操作必須透過 `mes_dashboard.core.database` 模組: - -```python -from mes_dashboard.core.database import read_sql_df, get_engine - -# 讀取資料 (推薦方式) -df = read_sql_df(sql, params) - -# 取得 engine(若需要直接操作) -engine = get_engine() -``` - -### 連線池配置 (位置: `core/database.py`) - -| 參數 | 開發環境 | 生產環境 | 說明 | -|------|---------|---------|------| -| pool_size | 2 | 10 | 基礎連線數 | -| max_overflow | 3 | 20 | 額外連線數 | -| pool_timeout | 30 | 30 | 等待超時 (秒) | -| pool_recycle | 1800 | 1800 | 回收週期 (30分鐘) | -| pool_pre_ping | True | True | 使用前驗證連線 | - -### Keep-Alive 機制 -- 背景執行緒每 5 分鐘執行 `SELECT 1 FROM DUAL` -- 防止 NAT/防火牆斷開閒置連線 -- 啟動: `start_keepalive()`,停止: `stop_keepalive()` - -### 注意事項 -- **禁止**在各 service 中自行建立連線 -- **禁止**直接使用 `oracledb.connect()` -- 連線池由 `database.py` 統一管理,避免連線洩漏 -- 測試環境需在 setUp 中重置:`db._ENGINE = None` - ---- - -## 2. SQL 集中管理 - -### 目錄結構 -所有 SQL 查詢放在 `src/mes_dashboard/sql/` 目錄: - -``` -sql/ -├── loader.py # SQL 檔案載入器 (LRU 快取) -├── builder.py # 參數化查詢構建器 -├── filters.py # 通用篩選條件 -├── dashboard/ # 儀表板 SQL -│ ├── kpi.sql -│ ├── heatmap.sql -│ └── workcenter_cards.sql -├── wip/ # WIP SQL -│ ├── summary.sql -│ └── detail.sql -├── resource/ # 設備 SQL -│ ├── by_status.sql -│ └── detail.sql -├── resource_history/ # 歷史 SQL -└── job_query/ # 維修工單 SQL -``` - -### SQLLoader 使用方式 - -```python -from mes_dashboard.sql.loader import SQLLoader - -# 載入 SQL 檔案 (自動 LRU 快取,最多 100 個) -sql = SQLLoader.load("wip/summary") - -# 結構性參數替換 (用於 SQL 片段) -sql = SQLLoader.load_with_params("dashboard/kpi", - LATEST_STATUS_SUBQUERY="...", - WHERE_CLAUSE="...") - -# 清除快取 -SQLLoader.clear_cache() -``` - -### QueryBuilder 使用方式 - -```python -from mes_dashboard.sql.builder import QueryBuilder - -builder = QueryBuilder() - -# 添加條件 (自動參數化,防 SQL 注入) -builder.add_param_condition("STATUS", "PRD") -builder.add_in_condition("STATUS", ["PRD", "SBY"]) -builder.add_not_in_condition("HOLD_REASON", exclude_list) -builder.add_like_condition("LOTID", user_input, position="both") -builder.add_or_like_conditions(["COL1", "COL2"], [val1, val2]) -builder.add_is_null("COLUMN") -builder.add_is_not_null("COLUMN") -builder.add_condition("FIXED_CONDITION = 1") # 固定條件 - -# 構建 WHERE 子句 -where_clause, params = builder.build_where_only() - -# 替換佔位符並執行 -sql = sql.replace("{{ WHERE_CLAUSE }}", where_clause) -df = read_sql_df(sql, params) -``` - -### 佔位符規範 - -| 類型 | 語法 | 用途 | 安全性 | -|------|------|------|--------| -| 結構性 | `{{ PLACEHOLDER }}` | 靜態 SQL 片段 | 僅限預定義值 | -| 參數 | `:param_name` | 動態用戶輸入 | Oracle bind variables | - -### Oracle IN 子句限制 -Oracle IN 子句上限 1000 個值,需分批處理: - -```python -BATCH_SIZE = 1000 - -# 參考 job_query_service.py 的 _build_resource_filter() -``` - ---- - -## 3. 快取機制 - -### 多層快取架構 - -``` -請求 → 進程級快取 (30 秒 TTL) - → Redis 快取 (可配置 TTL) - → Oracle 資料庫 -``` - -### 全局快取 API -使用 `mes_dashboard.core.cache` 模組: - -```python -from mes_dashboard.core.cache import cache_get, cache_set, make_cache_key - -# 建立快取 key(支援 filters dict) -cache_key = make_cache_key("resource_history_summary", filters={ - 'start_date': start_date, - 'workcenter_groups': sorted(groups) if groups else None, -}) - -# 讀取/寫入快取 -result = cache_get(cache_key) -if result is None: - result = query_data() - cache_set(cache_key, result, ttl=CACHE_TTL_TREND) -``` - -### 快取 TTL 常數 -定義於 `mes_dashboard.config.constants`: - -```python -CACHE_TTL_DEFAULT = 60 # 1 分鐘 -CACHE_TTL_FILTER_OPTIONS = 600 # 10 分鐘 -CACHE_TTL_PIVOT_COLUMNS = 300 # 5 分鐘 -CACHE_TTL_KPI = 60 # 1 分鐘 -CACHE_TTL_TREND = 300 # 5 分鐘 -``` - -### Redis 快取配置 -環境變數: -``` -REDIS_ENABLED=true -REDIS_URL=redis://localhost:6379/0 -REDIS_KEY_PREFIX=mes_wip -``` - -### 專用快取服務 - -| 服務 | 位置 | 用途 | -|------|------|------| -| WIP 快取更新器 | `core/cache_updater.py` | 背景線程自動更新 WIP 數據 | -| 資源快取 | `services/resource_cache.py` | DW_MES_RESOURCE 表快取 (4 小時同步) | -| 設備狀態快取 | `services/realtime_equipment_cache.py` | 設備實時狀態 (5 分鐘同步) | -| Filter 快取 | `services/filter_cache.py` | 篩選選項快取 | - ---- - -## 4. Filter Cache(篩選選項快取) - -### 位置 -`mes_dashboard.services.filter_cache` - -### 用途 -快取全站共用的篩選選項,避免重複查詢資料庫: - -```python -from mes_dashboard.services.filter_cache import ( - get_workcenter_groups, # 取得 workcenter group 列表 - get_workcenter_mapping, # 取得 workcentername → group 對應 - get_workcenters_for_groups, # 根據 group 取得 workcentername 列表 - get_resource_families, # 取得 resource family 列表 -) -``` - -### Workcenter 對應關係 -``` -WORKCENTERNAME (資料庫) → WORKCENTER_GROUP (顯示) -焊接_DB_1 → 焊接_DB -焊接_DB_2 → 焊接_DB -成型_1 → 成型 -``` - -### 資料來源 -- Workcenter Groups: `DW_PJ_LOT_V` (WORKCENTER_GROUP, WORKCENTERSEQUENCE_GROUP) -- Resource Families: `DW_MES_RESOURCE` (RESOURCEFAMILYNAME) - ---- - -## 5. 熔斷器 (Circuit Breaker) - -### 位置 -`mes_dashboard.core.circuit_breaker` - -### 狀態機制 - -``` -CLOSED (正常) - ↓ 失敗達到閾值 -OPEN (故障,拒絕請求) - ↓ 等待 recovery_timeout -HALF_OPEN (測試恢復) - ↓ 成功 → CLOSED / 失敗 → OPEN -``` - -### 配置 (環境變數) - -``` -CIRCUIT_BREAKER_ENABLED=true -CIRCUIT_BREAKER_FAILURE_THRESHOLD=5 # 最少失敗次數 -CIRCUIT_BREAKER_FAILURE_RATE=0.5 # 失敗率閾值 (0.0-1.0) -CIRCUIT_BREAKER_RECOVERY_TIMEOUT=30 # OPEN 狀態等待秒數 -CIRCUIT_BREAKER_WINDOW_SIZE=10 # 滑動窗口大小 -``` - -### 使用方式 -熔斷器已整合在 `read_sql_df()` 中,自動: -- 檢查是否允許請求 -- 記錄成功/失敗 -- 狀態轉移 - -### 狀態查詢 -```python -from mes_dashboard.core.circuit_breaker import get_database_circuit_breaker - -cb = get_database_circuit_breaker() -status = cb.get_status() -# status.state, status.failure_count, status.success_count, status.failure_rate -``` - ---- - -## 6. 統一 API 響應格式 - -### 位置 -`mes_dashboard.core.response` - -### 響應格式 - -```python -# 成功響應 -{ - "success": True, - "data": {...}, - "meta": {"timestamp": "2024-02-04T10:30:45.123456"} -} - -# 錯誤響應 -{ - "success": False, - "error": { - "code": "DB_CONNECTION_FAILED", - "message": "資料庫連線失敗,請稍後再試", - "details": "ORA-12541" # 僅開發模式 - }, - "meta": {"timestamp": "..."} -} -``` - -### 錯誤代碼 - -| 代碼 | HTTP | 說明 | -|------|------|------| -| DB_CONNECTION_FAILED | 503 | 資料庫連線失敗 | -| DB_QUERY_TIMEOUT | 504 | 查詢逾時 | -| DB_QUERY_ERROR | 500 | 查詢執行錯誤 | -| SERVICE_UNAVAILABLE | 503 | 服務不可用 | -| CIRCUIT_BREAKER_OPEN | 503 | 熔斷器開啟 | -| VALIDATION_ERROR | 400 | 驗證失敗 | -| UNAUTHORIZED | 401 | 未授權 | -| FORBIDDEN | 403 | 禁止訪問 | -| NOT_FOUND | 404 | 不存在 | -| TOO_MANY_REQUESTS | 429 | 過多請求 | -| INTERNAL_ERROR | 500 | 內部錯誤 | - -### 便利函數 - -```python -from mes_dashboard.core.response import ( - success_response, - validation_error, # 400 - unauthorized_error, # 401 - forbidden_error, # 403 - not_found_error, # 404 - db_connection_error, # 503 - internal_error, # 500 -) -``` - ---- - -## 7. 認證與授權機制 - -### 認證服務 -位置: `mes_dashboard.services.auth_service` - -#### LDAP 認證 (生產環境) -```python -from mes_dashboard.services.auth_service import authenticate - -user = authenticate(username, password) -# 返回: {username, displayName, mail, department} -``` - -#### 本地認證 (開發環境) -``` -LOCAL_AUTH_ENABLED=true -LOCAL_AUTH_USERNAME=admin -LOCAL_AUTH_PASSWORD=password -``` - -### Session 管理 -```python -# 登入後存入 session -session["admin"] = { - "username": user.get("username"), - "displayName": user.get("displayName"), - "mail": user.get("mail"), - "department": user.get("department"), - "login_time": datetime.now().isoformat() -} - -# Session 配置 -SESSION_COOKIE_SECURE = True # HTTPS only (生產) -SESSION_COOKIE_HTTPONLY = True # 防止 JS 訪問 -SESSION_COOKIE_SAMESITE = 'Lax' # CSRF 防護 -PERMANENT_SESSION_LIFETIME = 28800 # 8 小時 -``` - -### 權限檢查 -位置: `mes_dashboard.core.permissions` - -```python -from mes_dashboard.core.permissions import is_admin_logged_in, admin_required - -# 檢查登入狀態 -if is_admin_logged_in(): - ... - -# 裝飾器保護路由 -@admin_required -def admin_only_view(): - ... -``` - -### 登入速率限制 -- 單 IP 每 5 分鐘最多 5 次嘗試 -- 位置: `routes/auth_routes.py` - ---- - -## 8. 頁面狀態管理 - -### 位置 -- 服務: `mes_dashboard.services.page_registry` -- 數據: `data/page_status.json` - -### 狀態定義 - -| 狀態 | 說明 | -|------|------| -| `released` | 所有用戶可訪問 | -| `dev` | 僅管理員可訪問 | -| `None` | 未註冊,由 Flask 路由控制 | - -### 數據格式 -```json -{ - "pages": [ - {"route": "/wip-overview", "name": "WIP 即時概況", "status": "released"}, - {"route": "/tables", "name": "表格總覽", "status": "dev"} - ], - "api_public": true -} -``` - -### API - -```python -from mes_dashboard.services.page_registry import ( - get_page_status, # 取得頁面狀態 - set_page_status, # 設定頁面狀態 - is_api_public, # API 是否公開 - get_all_pages, # 取得所有頁面 -) -``` - -### 權限檢查 (自動) -在 `app.py` 的 `@app.before_request` 中自動執行: -- dev 頁面 + 非管理員 → 403 - ---- - -## 9. 日誌系統 - -### 雙層日誌架構 - -| 層級 | 目標 | 用途 | -|------|------|------| -| 控制台 (stderr) | Gunicorn 捕獲 | 即時監控 | -| SQLite | 管理員儀表板 | 歷史查詢 | - -### 配置 (環境變數) -``` -LOG_STORE_ENABLED=true -LOG_SQLITE_PATH=logs/admin_logs.sqlite -LOG_SQLITE_RETENTION_DAYS=7 -LOG_SQLITE_MAX_ROWS=100000 -``` - -### 日誌記錄規範 - -```python -import logging -logger = logging.getLogger('mes_dashboard') - -logger.debug("詳細調試資訊") -logger.info("一般操作記錄") -logger.warning("警告但可繼續") -logger.error("錯誤需要關注", exc_info=True) # 包含堆棧 -``` - -### SQLite 日誌查詢 -位置: `mes_dashboard.core.log_store` - -```python -from mes_dashboard.core.log_store import get_log_store - -store = get_log_store() -logs = store.query_logs( - level="ERROR", - limit=100, - offset=0, - search="keyword" -) -``` - ---- - -## 10. 健康檢查 - -### 端點 - -| 端點 | 認證 | 說明 | -|------|------|------| -| `/health` | 無需 | 基本健康檢查 | -| `/health/deep` | 需管理員 | 詳細指標 | - -### 基本檢查項目 -- 資料庫連線 (`SELECT 1 FROM DUAL`) -- Redis 連線 (`PING`) -- 各快取狀態 - -### 詳細檢查項目 (deep) -- 資料庫延遲 (毫秒) -- 連線池狀態 (size, checked_out, overflow) -- 快取新鮮度 -- 熔斷器狀態 -- 查詢性能指標 (P50/P95/P99) - -### 狀態判定 -- `200 OK` (healthy/degraded): DB 正常 -- `503 Unavailable` (unhealthy): DB 故障 - ---- - -## 11. API 路由結構 (Blueprint) - -### Blueprint 列表 - -| Blueprint | URL 前綴 | 檔案 | -|-----------|---------|------| -| wip | `/api/wip` | `wip_routes.py` | -| resource | `/api/resource` | `resource_routes.py` | -| dashboard | `/api/dashboard` | `dashboard_routes.py` | -| excel_query | `/api/excel-query` | `excel_query_routes.py` | -| hold | `/api/hold` | `hold_routes.py` | -| resource_history | `/api/resource-history` | `resource_history_routes.py` | -| job_query | `/api/job-query` | `job_query_routes.py` | -| admin | `/admin` | `admin_routes.py` | -| auth | `/admin` | `auth_routes.py` | -| health | `/` | `health_routes.py` | - -### 路由註冊 -位置: `routes/__init__.py` 的 `register_routes(app)` - ---- - -## 12. 前端全局組件 - -### Toast 通知 -定義於 `static/js/toast.js`,透過 `_base.html` 載入: - -```javascript -// 正確用法 -Toast.info('訊息'); -Toast.success('成功'); -Toast.warning('警告'); -Toast.error('錯誤', { retry: () => loadData() }); - -const id = Toast.loading('載入中...'); -Toast.update(id, { message: '完成!' }); -Toast.dismiss(id); - -// 錯誤用法(不存在) -MESToast.warning('...'); // ❌ 錯誤 -``` - -### 自動消失時間 -- info: 3000ms -- success: 2000ms -- warning: 5000ms -- error: 永久(需手動關閉) -- loading: 永久 - -### MesApi(HTTP 請求) -定義於 `static/js/mes-api.js`: - -```javascript -// GET 請求 -const data = await MesApi.get('/api/wip/summary', { - params: { page: 1 }, - timeout: 60000, - retries: 5, - signal: abortController.signal, - silent: true // 禁用 toast 通知 -}); - -// POST 請求 -const data = await MesApi.post('/api/query_table', { - table_name: 'TABLE_A', - filters: {...} -}); -``` - -### MesApi 特性 -- 自動重試 (3 次,指數退避: 1s, 2s, 4s) -- 自動 Toast 通知 -- 請求 ID 追蹤 -- AbortSignal 支援 -- 4xx 不重試,5xx 重試 - ---- - -## 13. 資料表預篩選規則 - -### 設備類型篩選 -定義於 `mes_dashboard.config.constants.EQUIPMENT_TYPE_FILTER`: - -```sql -((OBJECTCATEGORY = 'ASSEMBLY' AND OBJECTTYPE = 'ASSEMBLY') - OR (OBJECTCATEGORY = 'WAFERSORT' AND OBJECTTYPE = 'WAFERSORT')) -``` - -### 排除條件 -```python -# 排除的地點 -EXCLUDED_LOCATIONS = [ - 'ATEC', 'F區', 'F區焊接站', '報廢', '實驗室', - '山東', '成型站_F區', '焊接F區', '無錫', '熒茂' -] - -# 排除的資產狀態 -EXCLUDED_ASSET_STATUSES = ['Disapproved'] -``` - -### CommonFilters 使用 -位置: `mes_dashboard.sql.filters` - -```python -from mes_dashboard.sql.filters import CommonFilters - -# 添加標準篩選 -CommonFilters.add_location_exclusion(builder, 'r') -CommonFilters.add_asset_status_exclusion(builder, 'r') -CommonFilters.add_wip_base_filters(builder, filters) -CommonFilters.add_equipment_filter(builder, filters) -``` - ---- - -## 14. 資料庫欄位對應 - -### DW_MES_RESOURCE -| 常見錯誤 | 正確欄位名 | -|---------|-----------| -| ASSETSTATUS | PJ_ASSETSSTATUS(雙 S)| -| LOCATION | LOCATIONNAME | -| ISPRODUCTION | PJ_ISPRODUCTION | -| ISKEY | PJ_ISKEY | -| ISMONITOR | PJ_ISMONITOR | - -### DW_MES_RESOURCESTATUS_SHIFT -| 欄位 | 說明 | -|-----|------| -| HISTORYID | 對應 DW_MES_RESOURCE.RESOURCEID | -| TXNDATE | 交易日期 | -| OLDSTATUSNAME | E10 狀態 (PRD, SBY, UDT, SDT, EGT, NST) | -| HOURS | 該狀態時數 | - -### DW_PJ_LOT_V -| 欄位 | 說明 | -|-----|------| -| WORKCENTERNAME | 站點名稱(細分)| -| WORKCENTER_GROUP | 站點群組(顯示用)| -| WORKCENTERSEQUENCE_GROUP | 群組排序 | - ---- - -## 15. E10 狀態定義 - -| 狀態 | 說明 | 計入 OU% | -|-----|------|---------| -| PRD | Production(生產)| 是(分子)| -| SBY | Standby(待機)| 是(分母)| -| UDT | Unscheduled Downtime(非計畫停機)| 是(分母)| -| SDT | Scheduled Downtime(計畫停機)| 是(分母)| -| EGT | Engineering Time(工程時間)| 是(分母)| -| NST | Non-Scheduled Time(非排程時間)| 否 | - -### OU% 計算公式 -``` -OU% = PRD / (PRD + SBY + UDT + SDT + EGT) × 100 -``` - -### 狀態顯示名稱 -```python -STATUS_DISPLAY_NAMES = { - 'PRD': '生產中', - 'SBY': '待機', - 'UDT': '非計畫停機', - 'SDT': '計畫停機', - 'EGT': '工程時間', - 'NST': '未排單', -} -``` - ---- - -## 16. 配置管理 - -### 環境變數 (.env) - -#### 資料庫 -``` -DB_HOST= -DB_PORT=1521 -DB_SERVICE= -DB_USER= -DB_PASSWORD= -DB_POOL_SIZE=5 -DB_MAX_OVERFLOW=10 -``` - -> 實際值請參考 `.env` 或 `.env.example` - -#### Flask -``` -FLASK_ENV=production -FLASK_DEBUG=0 -SECRET_KEY=your_secret_key -SESSION_LIFETIME=28800 -``` - -#### 認證 -``` -LDAP_API_URL= -ADMIN_EMAILS= -LOCAL_AUTH_ENABLED=false -``` - -#### Gunicorn -``` -GUNICORN_BIND=0.0.0.0:8080 -GUNICORN_WORKERS=4 -GUNICORN_THREADS=8 -``` - -#### 快取 -``` -REDIS_ENABLED=true -REDIS_URL=redis://localhost:6379/0 -CACHE_CHECK_INTERVAL=600 -RESOURCE_CACHE_ENABLED=true -RESOURCE_SYNC_INTERVAL=14400 -``` - -#### 熔斷器 -``` -CIRCUIT_BREAKER_ENABLED=true -CIRCUIT_BREAKER_FAILURE_THRESHOLD=5 -CIRCUIT_BREAKER_FAILURE_RATE=0.5 -CIRCUIT_BREAKER_RECOVERY_TIMEOUT=30 -``` - -#### 日誌 -``` -LOG_STORE_ENABLED=true -LOG_SQLITE_PATH=logs/admin_logs.sqlite -LOG_SQLITE_RETENTION_DAYS=7 -``` - -### 環境配置類 -位置: `mes_dashboard.config.settings` - -```python -class DevelopmentConfig(Config): - DEBUG = True - DB_POOL_SIZE = 2 - -class ProductionConfig(Config): - DEBUG = False - DB_POOL_SIZE = 10 - -class TestingConfig(Config): - TESTING = True - DB_POOL_SIZE = 1 -``` - ---- - -## 17. 平行查詢 - -### ThreadPoolExecutor -對於多個獨立查詢,使用平行執行提升效能: - -```python -from concurrent.futures import ThreadPoolExecutor, as_completed - -with ThreadPoolExecutor(max_workers=4) as executor: - futures = { - executor.submit(read_sql_df, kpi_sql): 'kpi', - executor.submit(read_sql_df, trend_sql): 'trend', - executor.submit(read_sql_df, heatmap_sql): 'heatmap', - } - for future in as_completed(futures): - query_name = futures[future] - results[query_name] = future.result() -``` - -### 注意事項 -- Mock 測試時不能使用 `side_effect` 列表(順序不可預測) -- 應使用函式判斷 SQL 內容來回傳對應的 mock 資料 - ---- - -## 18. Oracle SQL 優化 - -### CTE MATERIALIZE Hint -防止 Oracle 優化器將 CTE inline 多次執行: - -```sql -WITH shift_data AS ( - SELECT /*+ MATERIALIZE */ HISTORYID, TXNDATE, OLDSTATUSNAME, HOURS - FROM DW_MES_RESOURCESTATUS_SHIFT - WHERE TXNDATE >= TO_DATE('2024-01-01', 'YYYY-MM-DD') - AND TXNDATE < TO_DATE('2024-01-07', 'YYYY-MM-DD') + 1 -) -SELECT ... -``` - -### 日期範圍查詢 -```sql --- 包含 end_date 當天 -WHERE TXNDATE >= TO_DATE(:start_date, 'YYYY-MM-DD') - AND TXNDATE < TO_DATE(:end_date, 'YYYY-MM-DD') + 1 -``` - -### 慢查詢警告 -- 閾值: 1 秒 (警告),5 秒 (`SLOW_QUERY_THRESHOLD`) -- 自動記錄到日誌 - ---- - -## 19. 前端資料限制 - -### 明細資料上限 -為避免瀏覽器記憶體問題,明細查詢有筆數限制: - -```python -MAX_DETAIL_RECORDS = 5000 - -if total > MAX_DETAIL_RECORDS: - df = df.head(MAX_DETAIL_RECORDS) - truncated = True -``` - -前端顯示警告: -```javascript -if (result.truncated) { - Toast.warning(`資料超過 ${result.max_records} 筆,請使用篩選條件縮小範圍。`); -} -``` - ---- - -## 20. JavaScript 注意事項 - -### Array.reverse() 原地修改 -```javascript -// 錯誤 - 原地修改陣列 -const arr = [1, 2, 3]; -arr.reverse(); // arr 被修改為 [3, 2, 1] - -// 正確 - 建立新陣列 -const reversed = arr.slice().reverse(); // arr 不變 -// 或 -const reversed = [...arr].reverse(); -``` - ---- - -## 21. 測試規範 - -### 測試檔案結構 -``` -tests/ -├── conftest.py # pytest fixtures -├── test_*_service.py # 單元測試(service layer) -├── test_*_routes.py # 整合測試(API endpoints) -├── e2e/ -│ └── test_*_e2e.py # 端對端測試(完整流程) -└── stress/ - └── test_*.py # 壓力測試 -``` - -### 測試前重置 -```python -def setUp(self): - db._ENGINE = None # 重置連線池 - self.app = create_app('testing') -``` - -### 執行測試 -```bash -# 單一模組 -pytest tests/test_resource_history_service.py -v - -# 全部相關測試 -pytest tests/test_resource_history_*.py tests/e2e/test_resource_history_e2e.py -v - -# 覆蓋率報告 -pytest tests/ --cov=mes_dashboard -``` - ---- - -## 22. 錯誤處理模式 - -### 三層錯誤處理 - -```python -# 1. 路由層 - 驗證錯誤 -@bp.route('/api/query') -def query(): - if not request.json.get('table_name'): - return validation_error("table_name 為必填") - -# 2. 服務層 - 業務錯誤 (優雅降級) -def get_wip_summary(filters): - try: - df = query_wip(filters) - if df.empty: - return None - return process_data(df) - except Exception as exc: - logger.error(f"WIP query failed: {exc}") - return None - -# 3. 核心層 - 基礎設施錯誤 -def read_sql_df(sql, params): - if not circuit_breaker.allow_request(): - raise RuntimeError("Circuit breaker open") -``` - -### 全局錯誤處理 -位置: `app.py` 的 `_register_error_handlers()` - -- 401 → `unauthorized_error()` -- 403 → `forbidden_error()` -- 404 → JSON (API) 或 HTML (頁面) -- 500 → `internal_error()` -- Exception → 通用處理 - ---- - -## 參考檔案索引 - -| 功能 | 檔案位置 | -|------|---------| -| SQL 載入 | `src/mes_dashboard/sql/loader.py` | -| 查詢構建 | `src/mes_dashboard/sql/builder.py` | -| 通用篩選 | `src/mes_dashboard/sql/filters.py` | -| 資料庫操作 | `src/mes_dashboard/core/database.py` | -| 快取 | `src/mes_dashboard/core/cache.py` | -| 熔斷器 | `src/mes_dashboard/core/circuit_breaker.py` | -| API 響應 | `src/mes_dashboard/core/response.py` | -| 權限檢查 | `src/mes_dashboard/core/permissions.py` | -| 日誌存儲 | `src/mes_dashboard/core/log_store.py` | -| 配置類 | `src/mes_dashboard/config/settings.py` | -| 常量定義 | `src/mes_dashboard/config/constants.py` | -| 認證服務 | `src/mes_dashboard/services/auth_service.py` | -| 頁面狀態 | `src/mes_dashboard/services/page_registry.py` | -| Filter 快取 | `src/mes_dashboard/services/filter_cache.py` | -| 資源快取 | `src/mes_dashboard/services/resource_cache.py` | -| API 客戶端 | `src/mes_dashboard/static/js/mes-api.js` | -| Toast 系統 | `src/mes_dashboard/static/js/toast.js` | diff --git a/docs/env_sync_report.md b/docs/env_sync_report.md deleted file mode 100644 index acb9285..0000000 --- a/docs/env_sync_report.md +++ /dev/null @@ -1,26 +0,0 @@ -# Environment Sync Report - -- Source: `/home/egg/Project/DashBoard/.env` -- Target: `/home/egg/Project/DashBoard_vite/.env` -- Example Baseline: `.env.example` - -- Keys in source env: 39 -- Keys in vite .env.example: 54 -- Missing keys auto-added to target: 15 - -## Auto-Added Keys -- `DB_POOL_TIMEOUT` -- `DB_POOL_RECYCLE` -- `DB_TCP_CONNECT_TIMEOUT` -- `DB_CONNECT_RETRY_COUNT` -- `DB_CONNECT_RETRY_DELAY` -- `DB_CALL_TIMEOUT_MS` -- `WIP_CACHE_TTL_SECONDS` -- `WATCHDOG_RUNTIME_DIR` -- `WATCHDOG_PID_FILE` -- `WATCHDOG_RESTART_HISTORY_MAX` -- `RESILIENCE_DEGRADED_ALERT_SECONDS` -- `RESILIENCE_POOL_SATURATION_WARNING` -- `RESILIENCE_POOL_SATURATION_CRITICAL` -- `RESILIENCE_RESTART_CHURN_WINDOW_SECONDS` -- `RESILIENCE_RESTART_CHURN_THRESHOLD` diff --git a/docs/env_usage_gap_report.md b/docs/env_usage_gap_report.md deleted file mode 100644 index 85239c6..0000000 --- a/docs/env_usage_gap_report.md +++ /dev/null @@ -1,9 +0,0 @@ -# Environment Usage Gap Report - -- Parsed env keys used in code/tests: 37 -- Keys present in `.env`: 63 -- Missing keys: 2 - -## Missing Keys -- `CONDA_DEFAULT_ENV` -- `PYTEST_CURRENT_TEST` diff --git a/docs/environment_gaps_and_mitigation.md b/docs/environment_gaps_and_mitigation.md deleted file mode 100644 index 2898af5..0000000 --- a/docs/environment_gaps_and_mitigation.md +++ /dev/null @@ -1,34 +0,0 @@ -# Environment-dependent Gaps and Mitigation - -## Oracle-dependent checks - -### Gap -- Service/integration paths that execute Oracle SQL require live DB credentials and network reachability. -- Local CI-like runs may not have Oracle connectivity. -- In this environment, `tests/test_cache_integration.py` has Oracle-dependent fallback failures when cache fixtures are insufficient. - -### Mitigation -- Keep unit tests isolated with mocks for SQL entry points. -- Reserve Oracle-connected tests for gated environments. -- Use `testing` config for app factory tests where possible. - -## Redis-dependent checks - -### Gap -- Redis availability differs across environments. -- Health/caching behavior differs between `L1+L2` and `L1-only degraded` modes. - -### Mitigation -- Expose route-cache telemetry in `/health` and `/health/deep`. -- Keep degraded mode visible and non-fatal where DB remains healthy. -- Validate both modes in unit tests (`tests/test_cache.py`, `tests/test_health_routes.py`). - -## Frontend build availability - -### Gap -- Node/npm may be absent on constrained runtime nodes. - -### Mitigation -- Keep inline script fallback in templates when dist assets are missing. -- Build artifacts in deployment pipeline where Node is available. -- Startup script logs fallback mode explicitly on build failure. diff --git a/docs/frontend_compute_shift_plan.md b/docs/frontend_compute_shift_plan.md deleted file mode 100644 index cb8101f..0000000 --- a/docs/frontend_compute_shift_plan.md +++ /dev/null @@ -1,42 +0,0 @@ -# Frontend Compute Shift Plan - -## Targeted Calculations - -## Resource History (migrated to frontend helpers) -- `ou_pct` -- `availability_pct` -- status percentages: - - `prd_pct` - - `sby_pct` - - `udt_pct` - - `sdt_pct` - - `egt_pct` - - `nst_pct` - -These are now computed by `frontend/src/core/compute.js` via: -- `buildResourceKpiFromHours` -- `calcOuPct` -- `calcAvailabilityPct` -- `calcStatusPct` - -## Parity Rules - -1. Rounding rule -- one decimal place, identical to backend (`round(..., 1)`) - -2. Formula rule -- OU%: `PRD / (PRD + SBY + UDT + SDT + EGT)` -- Availability%: `(PRD + SBY + EGT) / (PRD + SBY + EGT + SDT + UDT + NST)` -- Status%: `status_hours / total_hours` - -3. Zero denominator rule -- all percentages return `0` - -4. Data compatibility rule -- backend keeps existing fields to preserve API compatibility -- frontend recomputes display values from hours for deterministic parity - -## Validation - -- Python backend formula baseline: `mes_dashboard.services.resource_history_service` -- Frontend parity check: `tests/test_frontend_compute_parity.py` diff --git a/docs/hold_history.md b/docs/hold_history.md deleted file mode 100644 index 7701eca..0000000 --- a/docs/hold_history.md +++ /dev/null @@ -1,67 +0,0 @@ -/*PJMES043-Hold歷史紀錄 - 20240716 Peeler 新增匯總紀錄_PJM022024000878 - 20250520 Peeler 加總判斷Future Hold不同站別相同原因只計算第一次Hold_PJM022025000733 -*/ -SELECT TO_NUMBER(BS.TXNDAY) AS TXNDAY1,BS.TXNDAY - ,CASE WHEN :P_QCHOLDPARA = 2 - THEN SUM(CASE WHEN HD.HOLDTXNDAY <= BS.TRANSACTION_DAYS AND (HD.RELEASETXNDAY IS NULL OR BS.TRANSACTION_DAYS < HD.RELEASETXNDAY) AND BS.TRANSACTION_DAYS <= TO_CHAR(SYSDATE , 'YYYY/MM/DD') AND HD.RN_HOLD = 1 THEN QTY - ELSE 0 END) - ELSE SUM(CASE WHEN HD.HOLDTXNDAY <= BS.TRANSACTION_DAYS AND (HD.RELEASETXNDAY IS NULL OR BS.TRANSACTION_DAYS < HD.RELEASETXNDAY) AND BS.TRANSACTION_DAYS <= TO_CHAR(SYSDATE , 'YYYY/MM/DD') AND QCHOLDFLAG = :P_QCHOLDPARA AND HD.RN_HOLD = 1 THEN QTY - ELSE 0 END ) - END AS HOLDQTY - - ,CASE WHEN :P_QCHOLDPARA = 2 - THEN SUM(CASE WHEN HD.HOLDTXNDAY = BS.TRANSACTION_DAYS AND (HD.RELEASETXNDAY IS NULL OR BS.TRANSACTION_DAYS <= HD.RELEASETXNDAY) AND HD.FUTUREHOLD_FLAG = 1 THEN QTY - ELSE 0 END ) - ELSE SUM(CASE WHEN HD.HOLDTXNDAY = BS.TRANSACTION_DAYS AND (HD.RELEASETXNDAY IS NULL OR BS.TRANSACTION_DAYS <= HD.RELEASETXNDAY) AND QCHOLDFLAG = :P_QCHOLDPARA AND HD.FUTUREHOLD_FLAG = 1 THEN QTY - ELSE 0 END ) - END AS NEW_HOLDQTY - - ,CASE WHEN :P_QCHOLDPARA = 2 - THEN SUM(CASE WHEN HD.RELEASETXNDAY = BS.TRANSACTION_DAYS AND HD.RELEASETXNDAY >= HD.HOLDTXNDAY THEN QTY - ELSE 0 END ) - ELSE SUM(CASE WHEN HD.RELEASETXNDAY = BS.TRANSACTION_DAYS AND HD.RELEASETXNDAY >= HD.HOLDTXNDAY AND QCHOLDFLAG = :P_QCHOLDPARA THEN QTY - ELSE 0 END ) - END AS RELEASEQTY - - ,CASE WHEN :P_QCHOLDPARA = 2 - THEN SUM(CASE WHEN HD.HOLDTXNDAY = BS.TRANSACTION_DAYS AND (HD.RELEASETXNDAY IS NULL OR BS.TRANSACTION_DAYS <= HD.RELEASETXNDAY) AND HD.RN_HOLD = 1 AND HD.FUTUREHOLD_FLAG = 0 THEN QTY - ELSE 0 END ) - ELSE SUM(CASE WHEN HD.HOLDTXNDAY = BS.TRANSACTION_DAYS AND (HD.RELEASETXNDAY IS NULL OR BS.TRANSACTION_DAYS <= HD.RELEASETXNDAY) AND QCHOLDFLAG = :P_QCHOLDPARA AND HD.RN_HOLD = 1 AND HD.FUTUREHOLD_FLAG = 0 THEN QTY - ELSE 0 END ) - END AS FUTURE_HOLDQTY - FROM(select TO_CHAR(to_date(:P_TxnDate_S , 'YYYY/MM/DD') + rownum -1,'YYYY') AS TXNYEAR - , TO_CHAR(to_date(:P_TxnDate_S , 'YYYY/MM/DD') + rownum -1,'MM') AS TXNMONTH - , TO_CHAR(to_date(:P_TxnDate_S , 'YYYY/MM/DD') + rownum -1,'DD') AS TXNDAY - , TO_CHAR(to_date(:P_TxnDate_S , 'YYYY/MM/DD') + rownum -1,'YYYY/MM/DD') AS TRANSACTION_DAYS - From dual - CONNECT BY LEVEL <= TO_CHAR(LAST_DAY(to_date(:P_TxnDate_S,'YYYY/MM/DD')),'DD') - )BS, - (SELECT HOLDTXNDAY,RELEASETXNDAY,HOLDTXNDATE,RELEASETXNDATE,CONTAINERID,QTY, QCHOLDFLAG - ,ROW_NUMBER() OVER (PARTITION BY CONTAINERID,HOLDTXNDAY ORDER BY HOLDTXNDATE DESC) AS RN_HOLD--同一張工單當天重複Hold - ,ROW_NUMBER() OVER (PARTITION BY CONTAINERID,RELEASETXNDAY ORDER BY RELEASETXNDATE DESC) AS RN_RELEASE--同一張工單當天重複Release - ,CASE WHEN FUTUREHOLD = 1 AND RN_CONHOLD <> 1 THEN 0 - ELSE 1 END AS FUTUREHOLD_FLAG --FutureHold相同原因第一筆計算1其餘給0 - FROM(SELECT CASE WHEN TO_CHAR(HD.HOLDTXNDATE,'HH24MI')>=0730 - THEN TO_CHAR(HD.HOLDTXNDATE +1 ,'YYYY/MM/DD') - ELSE TO_CHAR(HD.HOLDTXNDATE ,'YYYY/MM/DD') END AS HOLDTXNDAY - ,CASE WHEN TO_CHAR(HD.RELEASETXNDATE,'HH24MI')>=0730 - THEN TO_CHAR(HD.RELEASETXNDATE +1 ,'YYYY/MM/DD') - ELSE TO_CHAR(HD.RELEASETXNDATE ,'YYYY/MM/DD') END AS RELEASETXNDAY - ,HD.HOLDTXNDATE - ,HD.RELEASETXNDATE - ,HD.CONTAINERID - ,HD.QTY - ,CASE WHEN HD.HOLDREASONNAME IN(:P_QCHOLDREASON) THEN 1 - ELSE 0 END AS QCHOLDFLAG - ,CASE WHEN HD.FUTUREHOLDCOMMENTS IS NOT NULL THEN 1 - ELSE 0 END AS FUTUREHOLD - ,ROW_NUMBER() OVER (PARTITION BY HD.CONTAINERID,HD.HOLDREASONID ORDER BY HD.HOLDTXNDATE) AS RN_CONHOLD--同一張工單重複Hold - FROM DW_MES_HOLDRELEASEHISTORY HD - WHERE 1=1 - AND ((HD.HOLDTXNDATE >= TO_DATE(:P_TxnDate_S||' 073000', 'YYYYMMDD HH24MISS')-1) Or :P_TxnDate_S is null OR (HD.RELEASETXNDATE >= TO_DATE(:P_TxnDate_S||' 073000', 'YYYYMMDD HH24MISS')-1) OR (HD.RELEASETXNDATE IS NULL)) - AND ((HD.HOLDTXNDATE <= TO_DATE(:P_TxnDate_E||' 073000', 'YYYYMMDD HH24MISS')) Or :P_TxnDate_E is null OR (HD.RELEASETXNDATE <= TO_DATE(:P_TxnDate_E||' 073000', 'YYYYMMDD HH24MISS')) OR (HD.RELEASETXNDATE IS NULL)) - ) - )HD - WHERE 1=1 -GROUP BY BS.TXNDAY \ No newline at end of file diff --git a/docs/migration/deferred-route-modernization-follow-up/README.md b/docs/migration/deferred-route-modernization-follow-up/README.md deleted file mode 100644 index 3fb0883..0000000 --- a/docs/migration/deferred-route-modernization-follow-up/README.md +++ /dev/null @@ -1,27 +0,0 @@ -# Deferred Route Modernization Follow-up Artifacts - -This directory stores execution artifacts for `deferred-route-modernization-follow-up`. - -## Upstream Reference - -- Phase 1: `docs/migration/full-modernization-architecture-blueprint/` -- Handoff: `docs/migration/full-modernization-architecture-blueprint/deferred_route_handoff.md` - -## Core Governance - -- `route_scope_matrix.json`: frozen in-scope deferred route matrix (promoted from phase 1 deferred). -- `governance_milestones.md`: completion and deprecation milestones for deferred-route phase. -- `exception_registry.json`: approved temporary exceptions with owner and milestone. -- `upstream_linkage.json`: explicit linkage to phase 1 handoff artifacts. -- `scope_boundary_note.md`: clarification that dev routes are eligible for modernization. - -## Pre-Change Confirmation - -- `pre_change_confirmation_template.md`: required fields and template. -- `pre_change_confirmations.json`: recorded per-route confirmations. - -## Rollout Operations - -- `rollout_runbook.md`: phase steps and hold points for deferred-route cutover. -- `rollback_controls.md`: per-route rollback and false-positive gate handling. -- `observability_checkpoints.md`: route/gate/rollback observability contract. diff --git a/docs/migration/deferred-route-modernization-follow-up/exception_registry.json b/docs/migration/deferred-route-modernization-follow-up/exception_registry.json deleted file mode 100644 index 65efa8f..0000000 --- a/docs/migration/deferred-route-modernization-follow-up/exception_registry.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "version": 1, - "change": "deferred-route-modernization-follow-up", - "fields": [ - "id", - "type", - "scope", - "owner", - "introduced_by", - "reason", - "mitigation", - "status", - "milestone", - "tracking_issue" - ], - "entries": [ - { - "id": "style-excel-query-shell-tokens-no-fallback", - "type": "style", - "scope": "/excel-query", - "owner": "frontend-mes-reporting", - "introduced_by": "legacy-template", - "reason": "excel-query uses shell tokens (--portal-brand-start, --portal-brand-end, --portal-shadow-panel) without CSS fallback values; inherited from legacy era before shell token governance", - "mitigation": "add fallback values during content modernization cutover for /excel-query", - "status": "approved-temporary", - "milestone": "2026-03-19", - "tracking_issue": "deferred-route-modernization-follow-up/excel-query-style-hardening" - }, - { - "id": "style-query-tool-shell-tokens-no-fallback", - "type": "style", - "scope": "/query-tool", - "owner": "frontend-mes-reporting", - "introduced_by": "legacy-template", - "reason": "query-tool uses shell tokens (--portal-brand-start, --portal-brand-end, --portal-shadow-panel) without CSS fallback values; inherited from legacy era before shell token governance", - "mitigation": "add fallback values during content modernization cutover for /query-tool", - "status": "approved-temporary", - "milestone": "2026-03-19", - "tracking_issue": "deferred-route-modernization-follow-up/query-tool-style-hardening" - } - ] -} diff --git a/docs/migration/deferred-route-modernization-follow-up/governance_milestones.md b/docs/migration/deferred-route-modernization-follow-up/governance_milestones.md deleted file mode 100644 index 8cebbde..0000000 --- a/docs/migration/deferred-route-modernization-follow-up/governance_milestones.md +++ /dev/null @@ -1,39 +0,0 @@ -# Deferred Route Modernization Governance Milestones - -## Upstream Reference - -- Phase 1: `full-modernization-architecture-blueprint` -- Handoff: `docs/migration/full-modernization-architecture-blueprint/deferred_route_handoff.md` - -## Phase Completion Criteria - -A phase is complete only when all criteria below are true: - -1. Route governance: 100% of in-scope deferred routes in `route_scope_matrix.json` have valid shell contract metadata and ownership with scope promoted to `in-scope`. -2. Style governance: deferred route-local styles do not introduce page-global selectors (`:root`, `body`) unless recorded in exception registry. -3. Quality governance: functional parity, visual checkpoints, accessibility checks, and performance budgets pass at configured gate severity. -4. Content safety governance: page-content parity evidence + manual acceptance sign-off exist for each migrated deferred route. -5. Bug carry-over governance: known-bug replay checks for migrated scope do not reproduce legacy defects. -6. Pre-change confirmation: each deferred route has an approved pre-change confirmation record before implementation begins. - -## Legacy Deprecation Milestones - -- 2026-02-19: deferred route contract CI completeness gate enabled in `warn` mode. -- 2026-02-26: deferred route contract CI completeness gate promoted to `block` mode. -- 2026-03-05: deferred route asset readiness gate promoted to `block` mode. -- 2026-03-12: runtime fallback posture retired for deferred routes in production policy. -- 2026-03-19: unresolved style exceptions past milestone fail modernization review. - -## Route Cutover Sequence - -Routes are cut over one at a time in the following planned order: - -1. `/tables` -2. `/excel-query` -3. `/query-tool` -4. `/mid-section-defect` - -Next route cutover is blocked until current route has: -- Parity pass (golden fixtures + interaction checks) -- Manual acceptance sign-off -- Known-bug replay pass diff --git a/docs/migration/deferred-route-modernization-follow-up/observability_checkpoints.md b/docs/migration/deferred-route-modernization-follow-up/observability_checkpoints.md deleted file mode 100644 index 5db23d1..0000000 --- a/docs/migration/deferred-route-modernization-follow-up/observability_checkpoints.md +++ /dev/null @@ -1,44 +0,0 @@ -# Deferred Route Modernization Observability Checkpoints - -## Route Governance Signals - -1. `navigation_contract_mismatch_total` -- Source: `/api/portal/navigation` diagnostics. -- Alert condition: non-zero for deferred-promoted routes. - -2. `route_contract_missing_metadata_total` -- Source: route governance CI script. -- Alert condition: >0 in block mode for `/tables`, `/excel-query`, `/query-tool`, `/mid-section-defect`. - -## Quality Gate Signals - -1. `quality_gate_failed_total{gate_id}` -- Source: quality gate report. -- Alert condition: any mandatory gate failed for deferred-promoted routes. - -2. `manual_acceptance_pending_routes` -- Source: manual acceptance records. -- Alert condition: cutover attempted with pending sign-off for deferred routes. - -3. `pre_change_confirmation_missing` -- Source: pre-change confirmation records. -- Alert condition: implementation started without recorded confirmation. - -## Fallback and Rollback Signals - -1. `deferred_route_runtime_fallback_served_total` -- Should remain zero after fallback retirement milestone for each route. - -2. `content_cutover_flag_rollbacks_total{route}` -- Track frequency per deferred route. - -3. `legacy_bug_replay_failures_total{route}` -- Any non-zero indicates carry-over risk and blocks sign-off. - -## Cutover Sequence Signals - -1. `deferred_route_cutover_sequence_violation` -- Alert condition: route cutover attempted out of planned sequence. - -2. `deferred_route_signoff_blocked_by_bug_replay` -- Alert condition: sign-off blocked due to reproduced legacy bug. diff --git a/docs/migration/deferred-route-modernization-follow-up/pre_change_confirmation_template.md b/docs/migration/deferred-route-modernization-follow-up/pre_change_confirmation_template.md deleted file mode 100644 index 8b1bcf7..0000000 --- a/docs/migration/deferred-route-modernization-follow-up/pre_change_confirmation_template.md +++ /dev/null @@ -1,35 +0,0 @@ -# Pre-Change Confirmation Template (Deferred Route) - -## Rule - -Before any implementation work begins on a deferred route, a route-scoped pre-change confirmation MUST be recorded and approved. Implementation is BLOCKED until confirmation exists. - -## Required Fields - -1. **Route**: The deferred route path (e.g., `/tables`). -2. **Status Snapshot**: Current route status in page registry (e.g., `dev`, `released`). -3. **Scope Boundary Check**: Confirmation that the route is listed in `route_scope_matrix.json` as in-scope for this change. -4. **Contract Baseline Refs**: References to existing route contracts and content contracts that define expected behavior. -5. **Known-Bug Baseline Ref**: Reference to `known_bug_baseline.json` entry for this route (or confirmation that baseline is initialized). -6. **Rollback Flag Plan**: Planned feature flag key and rollback strategy for this route's cutover. -7. **Owner**: The person/team responsible for this route's modernization. -8. **Date**: Date of confirmation. -9. **Approved By**: Reviewer who approved the pre-change confirmation. - -## Template - -``` -Route: / -Status Snapshot: -Scope Boundary Check: confirmed in route_scope_matrix.json as in-scope -Contract Baseline Refs: - - Route contract: route_contracts.json#/ - - Content contract: route_content_contracts.json#/ -Known-Bug Baseline Ref: known_bug_baseline.json#/ -Rollback Flag Plan: - - Feature flag: modernization_feature_flags.json#/.content_cutover_enabled - - Rollback strategy: fallback_to_legacy_route -Owner: -Date: -Approved By: -``` diff --git a/docs/migration/deferred-route-modernization-follow-up/pre_change_confirmations.json b/docs/migration/deferred-route-modernization-follow-up/pre_change_confirmations.json deleted file mode 100644 index d2a797a..0000000 --- a/docs/migration/deferred-route-modernization-follow-up/pre_change_confirmations.json +++ /dev/null @@ -1,85 +0,0 @@ -{ - "change": "deferred-route-modernization-follow-up", - "rule": "implementation is blocked for a route until its pre-change confirmation is recorded and approved", - "required_fields": [ - "route", - "status_snapshot", - "scope_boundary_check", - "contract_baseline_refs", - "known_bug_baseline_ref", - "rollback_flag_plan", - "owner", - "date", - "approved_by" - ], - "records": [ - { - "route": "/tables", - "status_snapshot": "dev", - "scope_boundary_check": "confirmed in route_scope_matrix.json as in-scope (promoted from deferred)", - "contract_baseline_refs": { - "route_contract": "route_contracts.json#/tables", - "content_contract": "route_content_contracts.json#/tables" - }, - "known_bug_baseline_ref": "known_bug_baseline.json#/tables", - "rollback_flag_plan": { - "feature_flag": "modernization_feature_flags.json#/tables.content_cutover_enabled", - "rollback_strategy": "fallback_to_legacy_route" - }, - "owner": "frontend-mes-reporting", - "date": "2026-02-12", - "approved_by": "deferred-route-modernization-follow-up" - }, - { - "route": "/excel-query", - "status_snapshot": "dev", - "scope_boundary_check": "confirmed in route_scope_matrix.json as in-scope (promoted from deferred)", - "contract_baseline_refs": { - "route_contract": "route_contracts.json#/excel-query", - "content_contract": "route_content_contracts.json#/excel-query" - }, - "known_bug_baseline_ref": "known_bug_baseline.json#/excel-query", - "rollback_flag_plan": { - "feature_flag": "modernization_feature_flags.json#/excel-query.content_cutover_enabled", - "rollback_strategy": "fallback_to_legacy_route" - }, - "owner": "frontend-mes-reporting", - "date": "2026-02-12", - "approved_by": "deferred-route-modernization-follow-up" - }, - { - "route": "/query-tool", - "status_snapshot": "dev", - "scope_boundary_check": "confirmed in route_scope_matrix.json as in-scope (promoted from deferred)", - "contract_baseline_refs": { - "route_contract": "route_contracts.json#/query-tool", - "content_contract": "route_content_contracts.json#/query-tool" - }, - "known_bug_baseline_ref": "known_bug_baseline.json#/query-tool", - "rollback_flag_plan": { - "feature_flag": "modernization_feature_flags.json#/query-tool.content_cutover_enabled", - "rollback_strategy": "fallback_to_legacy_route" - }, - "owner": "frontend-mes-reporting", - "date": "2026-02-12", - "approved_by": "deferred-route-modernization-follow-up" - }, - { - "route": "/mid-section-defect", - "status_snapshot": "dev", - "scope_boundary_check": "confirmed in route_scope_matrix.json as in-scope (promoted from deferred)", - "contract_baseline_refs": { - "route_contract": "route_contracts.json#/mid-section-defect", - "content_contract": "route_content_contracts.json#/mid-section-defect" - }, - "known_bug_baseline_ref": "known_bug_baseline.json#/mid-section-defect", - "rollback_flag_plan": { - "feature_flag": "modernization_feature_flags.json#/mid-section-defect.content_cutover_enabled", - "rollback_strategy": "fallback_to_legacy_route" - }, - "owner": "frontend-mes-reporting", - "date": "2026-02-12", - "approved_by": "deferred-route-modernization-follow-up" - } - ] -} diff --git a/docs/migration/deferred-route-modernization-follow-up/rollback_controls.md b/docs/migration/deferred-route-modernization-follow-up/rollback_controls.md deleted file mode 100644 index 1be9ad3..0000000 --- a/docs/migration/deferred-route-modernization-follow-up/rollback_controls.md +++ /dev/null @@ -1,31 +0,0 @@ -# Deferred Route Modernization Rollback Controls - -## Route-Level Reversion Controls - -- **Content cutover feature flag**: Set `content_cutover_enabled: false` in `data/modernization_feature_flags.json` for the affected route to immediately revert to legacy content path. -- **PORTAL_SPA_ENABLED=false**: Disable shell-first navigation runtime globally (affects all routes). -- **Route-scoped contract fallback**: Mark route contract with fallback strategy and redeploy shell assets. - -## Per-Route Rollback Procedure - -1. Set `content_cutover_enabled: false` for the affected route in `modernization_feature_flags.json`. -2. Restart workers to pick up the flag change. -3. Verify legacy content path is serving correctly. -4. Record rollback in manual acceptance records with reason and timestamp. -5. Investigate root cause before re-enabling cutover. - -## False-Positive Gate Handling - -1. Capture failing gate output and route impact. -2. Confirm whether failure is test flake or product defect. -3. If false-positive and production risk is high: -- Temporarily switch gate severity from `block` to `warn`. -- Record waiver with owner, reason, expiry. -4. Restore `block` mode after corrective action. - -## Required Rollback Evidence - -- Incident timestamp and impacted route. -- Gate IDs that triggered rollback. -- Feature flag state before/after rollback. -- Manual acceptance and known-bug replay references. diff --git a/docs/migration/deferred-route-modernization-follow-up/rollout_runbook.md b/docs/migration/deferred-route-modernization-follow-up/rollout_runbook.md deleted file mode 100644 index 3f71b96..0000000 --- a/docs/migration/deferred-route-modernization-follow-up/rollout_runbook.md +++ /dev/null @@ -1,47 +0,0 @@ -# Deferred Route Modernization Rollout Runbook - -## Upstream Reference - -- Phase 1 runbook: `docs/migration/full-modernization-architecture-blueprint/rollout_runbook.md` - -## Phase Sequence - -1. Governance freeze -- Confirm `route_scope_matrix.json` has deferred routes promoted to in-scope. -- Confirm pre-change confirmations recorded for all 4 routes. -- Confirm exception registry has no unresolved blocking entries. - -2. Route governance enforcement -- Run route contract completeness checks in warn mode. -- Fix all deferred-route metadata gaps. -- Promote route governance checks to block mode. - -3. Per-route content modernization (sequential) -- Enable content cutover flag for first route (`/tables`). -- Execute parity checks and manual acceptance. -- Run known-bug replay checks. -- On pass: sign off and proceed to next route. -- On fail: rollback flag and investigate. - -4. Cutover sequence -- `/tables` -> `/excel-query` -> `/query-tool` -> `/mid-section-defect` -- Next route blocked until current route has approved sign-off. - -5. Asset/gate enforcement -- Validate deferred route asset readiness. -- Run quality gate suite (functional, visual, accessibility, performance). -- Promote gate severity from warn to block per milestones. - -6. Fallback retirement -- Retire runtime fallback for deferred routes after all acceptance gates pass. - -## Hold Points - -- Hold-1: Any deferred route missing contract metadata or pre-change confirmation. -- Hold-2: Any parity failure or known-bug replay failure. -- Hold-3: Any mandatory quality gate failure in block mode. -- Hold-4: Cutover attempted before previous route sign-off complete. - -## Promotion Rule - -Promotion is allowed only when all hold points are clear for the current route in sequence. diff --git a/docs/migration/deferred-route-modernization-follow-up/route_scope_matrix.json b/docs/migration/deferred-route-modernization-follow-up/route_scope_matrix.json deleted file mode 100644 index dfb5837..0000000 --- a/docs/migration/deferred-route-modernization-follow-up/route_scope_matrix.json +++ /dev/null @@ -1,100 +0,0 @@ -{ - "change": "deferred-route-modernization-follow-up", - "upstream_change": "full-modernization-architecture-blueprint", - "generated_at": "2026-02-12T00:00:00Z", - "phase": "phase-2-deferred-route-modernization", - "policy": { - "scope_is_frozen": true, - "out_of_scope_tasks_must_be_rejected": true, - "dev_routes_are_eligible": true, - "released_only_restriction_does_not_apply": true - }, - "in_scope": [ - { - "route": "/tables", - "category": "report", - "canonical_shell_path": "/portal-shell/tables", - "owner": "frontend-mes-reporting", - "visibility_policy": "released_or_admin", - "prior_scope": "deferred", - "prior_change": "full-modernization-architecture-blueprint" - }, - { - "route": "/excel-query", - "category": "report", - "canonical_shell_path": "/portal-shell/excel-query", - "owner": "frontend-mes-reporting", - "visibility_policy": "released_or_admin", - "prior_scope": "deferred", - "prior_change": "full-modernization-architecture-blueprint" - }, - { - "route": "/query-tool", - "category": "report", - "canonical_shell_path": "/portal-shell/query-tool", - "owner": "frontend-mes-reporting", - "visibility_policy": "released_or_admin", - "prior_scope": "deferred", - "prior_change": "full-modernization-architecture-blueprint" - }, - { - "route": "/mid-section-defect", - "category": "report", - "canonical_shell_path": "/portal-shell/mid-section-defect", - "owner": "frontend-mes-reporting", - "visibility_policy": "released_or_admin", - "prior_scope": "deferred", - "prior_change": "full-modernization-architecture-blueprint" - } - ], - "out_of_scope": [ - { - "route": "/wip-overview", - "reason": "completed-in-phase-1" - }, - { - "route": "/wip-detail", - "reason": "completed-in-phase-1" - }, - { - "route": "/hold-overview", - "reason": "completed-in-phase-1" - }, - { - "route": "/hold-detail", - "reason": "completed-in-phase-1" - }, - { - "route": "/hold-history", - "reason": "completed-in-phase-1" - }, - { - "route": "/resource", - "reason": "completed-in-phase-1" - }, - { - "route": "/resource-history", - "reason": "completed-in-phase-1" - }, - { - "route": "/qc-gate", - "reason": "completed-in-phase-1" - }, - { - "route": "/job-query", - "reason": "completed-in-phase-1" - }, - { - "route": "/tmtt-defect", - "reason": "completed-in-phase-1" - }, - { - "route": "/admin/pages", - "reason": "completed-in-phase-1" - }, - { - "route": "/admin/performance", - "reason": "completed-in-phase-1" - } - ] -} diff --git a/docs/migration/deferred-route-modernization-follow-up/scope_boundary_note.md b/docs/migration/deferred-route-modernization-follow-up/scope_boundary_note.md deleted file mode 100644 index 4d69015..0000000 --- a/docs/migration/deferred-route-modernization-follow-up/scope_boundary_note.md +++ /dev/null @@ -1,30 +0,0 @@ -# Scope Boundary Note - -## Change - -`deferred-route-modernization-follow-up` - -## Scope Clarification - -Deferred routes (`/tables`, `/excel-query`, `/query-tool`, `/mid-section-defect`) are **in-scope** for this follow-up change regardless of their current page status (`dev` or `released`). - -The **released-only restriction does not apply** to this change. These routes were intentionally deferred from phase 1 to control blast radius and are now the explicit modernization target. - -## What Is In-Scope - -- `/tables` — currently `dev` in page registry -- `/excel-query` — currently `dev` in page registry -- `/query-tool` — currently `dev` in page registry -- `/mid-section-defect` — currently `dev` in page registry - -## What Is NOT In-Scope - -- Phase-1 routes that are already modernized and governed (10 report + 2 admin routes) -- Routes outside the deferred matrix -- Backend business data semantics beyond compatibility safeguards -- Unrelated admin/report features not in the deferred matrix - -## Policy - -- Phase-1 in-scope routes SHALL NOT be reopened by this change unless explicitly required for shared governance wiring. -- Deferred routes adopt identical governance rigor (contracts, parity, manual acceptance, bug replay) as phase-1 routes. diff --git a/docs/migration/deferred-route-modernization-follow-up/upstream_linkage.json b/docs/migration/deferred-route-modernization-follow-up/upstream_linkage.json deleted file mode 100644 index f826939..0000000 --- a/docs/migration/deferred-route-modernization-follow-up/upstream_linkage.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "change": "deferred-route-modernization-follow-up", - "upstream_change": "full-modernization-architecture-blueprint", - "handoff_artifact": "docs/migration/full-modernization-architecture-blueprint/deferred_route_handoff.md", - "consumed_artifacts": { - "scope_boundary": "docs/migration/full-modernization-architecture-blueprint/route_scope_matrix.json", - "parity_fixtures": "docs/migration/full-modernization-architecture-blueprint/parity_golden_fixtures.json", - "interaction_parity_checks": "docs/migration/full-modernization-architecture-blueprint/interaction_parity_checks.json", - "manual_acceptance_checklist": "docs/migration/full-modernization-architecture-blueprint/page_content_manual_acceptance_checklist.md", - "known_bug_baseline": "docs/migration/full-modernization-architecture-blueprint/known_bug_baseline.json", - "bug_revalidation_records": "docs/migration/full-modernization-architecture-blueprint/bug_revalidation_records.json", - "quality_gate_policy": "docs/migration/full-modernization-architecture-blueprint/quality_gate_policy.json", - "governance_milestones": "docs/migration/full-modernization-architecture-blueprint/governance_milestones.md", - "asset_readiness_manifest": "docs/migration/full-modernization-architecture-blueprint/asset_readiness_manifest.json" - }, - "transfer_rules": [ - "Deferred routes remain excluded from phase-1 blocking criteria", - "Follow-up change MUST promote these routes to in-scope before legacy retirement", - "Equivalent parity/manual-acceptance/bug-revalidation gates must be applied" - ], - "deferred_routes": [ - "/tables", - "/excel-query", - "/query-tool", - "/mid-section-defect" - ] -} diff --git a/docs/migration/full-modernization-architecture-blueprint/README.md b/docs/migration/full-modernization-architecture-blueprint/README.md deleted file mode 100644 index b7b5165..0000000 --- a/docs/migration/full-modernization-architecture-blueprint/README.md +++ /dev/null @@ -1,27 +0,0 @@ -# Full Modernization Architecture Blueprint Artifacts - -This directory stores execution artifacts for `full-modernization-architecture-blueprint`. - -## Core Governance - -- `route_scope_matrix.json`: frozen in-scope/deferred route contract matrix. -- `governance_milestones.md`: completion and deprecation milestones. -- `exception_registry.json`: approved temporary exceptions with owner and milestone. -- Policy artifact runtime cache model: - - `src/mes_dashboard/core/modernization_policy.py` caches `route_scope_matrix.json` and - `asset_readiness_manifest.json` in-process with `lru_cache`. - - Runtime behavior is restart-refresh by default: JSON edits take effect after worker restart. - - Controlled refresh is available through `clear_modernization_policy_cache()` for tests or - explicit maintenance hooks; no automatic file watcher/hot reload is active in production. - -## Content Modernization Safety - -- `page_content_manual_acceptance_checklist.md`: mandatory manual sign-off checklist. -- `known_bug_baseline.json`: route-level known bug baseline and replay blocking policy. - -## Rollout Operations - -- `rollout_runbook.md`: phase steps and hold points. -- `rollback_controls.md`: rollback and false-positive gate handling. -- `observability_checkpoints.md`: route/gate/rollback observability contract. -- `deferred_route_handoff.md`: explicit handoff package to deferred-route follow-up change. diff --git a/docs/migration/full-modernization-architecture-blueprint/asset_readiness_manifest.json b/docs/migration/full-modernization-architecture-blueprint/asset_readiness_manifest.json deleted file mode 100644 index 922cc2e..0000000 --- a/docs/migration/full-modernization-architecture-blueprint/asset_readiness_manifest.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "change": "full-modernization-architecture-blueprint", - "in_scope_required_assets": { - "/portal-shell": ["portal-shell.html", "portal-shell.js", "portal-shell.css", "tailwind.css"], - "/wip-overview": ["wip-overview.html", "wip-overview.js"], - "/wip-detail": ["wip-detail.html", "wip-detail.js"], - "/hold-overview": ["hold-overview.html", "hold-overview.js"], - "/hold-detail": ["hold-detail.html", "hold-detail.js"], - "/hold-history": ["hold-history.html", "hold-history.js"], - "/resource": ["resource-status.html", "resource-status.js"], - "/resource-history": ["resource-history.html", "resource-history.js"], - "/qc-gate": ["qc-gate.html", "qc-gate.js"], - "/job-query": ["job-query.js"], - "/tmtt-defect": ["tmtt-defect.js"], - "/tables": ["tables.html", "tables.js"], - "/excel-query": ["excel-query.js"], - "/query-tool": ["query-tool.js"], - "/mid-section-defect": ["mid-section-defect.html", "mid-section-defect.js"] - }, - "deferred_routes": [] -} diff --git a/docs/migration/full-modernization-architecture-blueprint/bug_revalidation_records.json b/docs/migration/full-modernization-architecture-blueprint/bug_revalidation_records.json deleted file mode 100644 index f5c45eb..0000000 --- a/docs/migration/full-modernization-architecture-blueprint/bug_revalidation_records.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "change": "full-modernization-architecture-blueprint", - "records": [], - "schema": { - "route": "string", - "known_bug_id": "string", - "replay_date": "YYYY-MM-DD", - "result": "pass|fail", - "notes": "string", - "signoff_owner": "string" - } -} diff --git a/docs/migration/full-modernization-architecture-blueprint/canonical_routing_policy.json b/docs/migration/full-modernization-architecture-blueprint/canonical_routing_policy.json deleted file mode 100644 index ae05649..0000000 --- a/docs/migration/full-modernization-architecture-blueprint/canonical_routing_policy.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "change": "full-modernization-architecture-blueprint", - "canonical_policy": { - "applies_when": "PORTAL_SPA_ENABLED=true", - "report_routes": "redirect direct route entry to /portal-shell/", - "admin_routes": "shell target redirects to backend /admin/* while backend keeps auth authority" - }, - "direct_entry_compatibility": { - "query_semantics_must_be_preserved": true, - "redirect_status_code": 302 - }, - "in_scope_report_routes": [ - "/wip-overview", - "/wip-detail", - "/hold-overview", - "/hold-detail", - "/hold-history", - "/resource", - "/resource-history", - "/qc-gate", - "/job-query", - "/tmtt-defect", - "/tables", - "/excel-query", - "/query-tool", - "/mid-section-defect" - ] -} diff --git a/docs/migration/full-modernization-architecture-blueprint/deferred_route_handoff.md b/docs/migration/full-modernization-architecture-blueprint/deferred_route_handoff.md deleted file mode 100644 index a0cc6cd..0000000 --- a/docs/migration/full-modernization-architecture-blueprint/deferred_route_handoff.md +++ /dev/null @@ -1,40 +0,0 @@ -# Deferred Route Handoff (Phase 1 -> Follow-up) - -## Source Change - -- `openspec/changes/full-modernization-architecture-blueprint/` - -## Deferred Routes (Not in Phase 1 Blocking Scope) - -- `/tables` -- `/excel-query` -- `/query-tool` -- `/mid-section-defect` - -## Follow-up Change - -- `openspec/changes/deferred-route-modernization-follow-up/` - -## Handoff Content - -1. Scope boundary contract: -- Source: `docs/migration/full-modernization-architecture-blueprint/route_scope_matrix.json` - -2. Required acceptance model to carry forward: -- Parity fixtures/checks: - - `docs/migration/full-modernization-architecture-blueprint/parity_golden_fixtures.json` - - `docs/migration/full-modernization-architecture-blueprint/interaction_parity_checks.json` -- Manual acceptance + bug replay: - - `docs/migration/full-modernization-architecture-blueprint/page_content_manual_acceptance_checklist.md` - - `docs/migration/full-modernization-architecture-blueprint/known_bug_baseline.json` - - `docs/migration/full-modernization-architecture-blueprint/bug_revalidation_records.json` - -3. Governance policy to carry forward: -- `docs/migration/full-modernization-architecture-blueprint/quality_gate_policy.json` -- `docs/migration/full-modernization-architecture-blueprint/governance_milestones.md` -- `docs/migration/full-modernization-architecture-blueprint/asset_readiness_manifest.json` - -## Transfer Rule - -- Deferred routes remain excluded from phase-1 blocking criteria. -- Follow-up change MUST promote these routes to in-scope and apply equivalent parity/manual-acceptance/bug-revalidation gates before legacy retirement. diff --git a/docs/migration/full-modernization-architecture-blueprint/exception_registry.json b/docs/migration/full-modernization-architecture-blueprint/exception_registry.json deleted file mode 100644 index c010cd0..0000000 --- a/docs/migration/full-modernization-architecture-blueprint/exception_registry.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "version": 1, - "change": "full-modernization-architecture-blueprint", - "fields": [ - "id", - "type", - "scope", - "owner", - "introduced_by", - "reason", - "mitigation", - "status", - "milestone", - "tracking_issue" - ], - "entries": [ - { - "id": "style-admin-pages-inline-css", - "type": "style", - "scope": "/admin/pages", - "owner": "frontend-platform-admin", - "introduced_by": "legacy-template", - "reason": "admin pages remain backend-rendered in this phase", - "mitigation": "enforce shell contract governance while retaining backend auth authority", - "status": "approved-temporary", - "milestone": "2026-03-19", - "tracking_issue": "deferred-route-modernization-follow-up/admin-template-modernization" - }, - { - "id": "style-admin-performance-inline-css", - "type": "style", - "scope": "/admin/performance", - "owner": "frontend-platform-admin", - "introduced_by": "legacy-template", - "reason": "admin performance remains backend-rendered in this phase", - "mitigation": "governed navigation + route-level fallback controls", - "status": "approved-temporary", - "milestone": "2026-03-19", - "tracking_issue": "deferred-route-modernization-follow-up/admin-template-modernization" - }, - { - "id": "style-excel-query-shell-tokens-no-fallback", - "type": "style", - "scope": "/excel-query", - "owner": "frontend-mes-reporting", - "introduced_by": "legacy-template", - "reason": "shell tokens without CSS fallback values; inherited from legacy era", - "mitigation": "add fallback values during content modernization cutover", - "status": "approved-temporary", - "milestone": "2026-03-19", - "tracking_issue": "deferred-route-modernization-follow-up/excel-query-style-hardening" - }, - { - "id": "style-query-tool-shell-tokens-no-fallback", - "type": "style", - "scope": "/query-tool", - "owner": "frontend-mes-reporting", - "introduced_by": "legacy-template", - "reason": "shell tokens without CSS fallback values; inherited from legacy era", - "mitigation": "add fallback values during content modernization cutover", - "status": "approved-temporary", - "milestone": "2026-03-19", - "tracking_issue": "deferred-route-modernization-follow-up/query-tool-style-hardening" - } - ] -} diff --git a/docs/migration/full-modernization-architecture-blueprint/governance_milestones.md b/docs/migration/full-modernization-architecture-blueprint/governance_milestones.md deleted file mode 100644 index a9f2d52..0000000 --- a/docs/migration/full-modernization-architecture-blueprint/governance_milestones.md +++ /dev/null @@ -1,30 +0,0 @@ -# Full Modernization Governance Milestones - -## Phase Completion Criteria - -A phase is complete only when all criteria below are true: - -1. Route governance: 100% of in-scope routes in `route_scope_matrix.json` have valid shell contract metadata and ownership. -2. Style governance: in-scope route-local styles do not introduce page-global selectors (`:root`, `body`) unless recorded in exception registry. -3. Quality governance: functional parity, visual checkpoints, accessibility checks, and performance budgets pass at configured gate severity. -4. Content safety governance: page-content parity evidence + manual acceptance sign-off exist for each migrated in-scope route. -5. Bug carry-over governance: known-bug replay checks for migrated scope do not reproduce legacy defects. - -## Legacy Deprecation Milestones - -- 2026-02-20: route contract CI completeness gate enabled in `warn` mode. -- 2026-02-27: route contract CI completeness gate promoted to `block` mode. -- 2026-03-05: in-scope asset readiness gate promoted to `block` mode. -- 2026-03-12: runtime fallback posture retired for in-scope routes in production policy. -- 2026-03-19: unresolved style exceptions past milestone fail modernization review. - -## Deferred Route Linkage - -Deferred routes are not pass/fail criteria in this phase and are handed over to a follow-up change: - -- `/tables` -- `/excel-query` -- `/query-tool` -- `/mid-section-defect` - -Follow-up change handoff is recorded in `openspec/changes/deferred-route-modernization-follow-up/`. diff --git a/docs/migration/full-modernization-architecture-blueprint/interaction_parity_checks.json b/docs/migration/full-modernization-architecture-blueprint/interaction_parity_checks.json deleted file mode 100644 index 1ed4151..0000000 --- a/docs/migration/full-modernization-architecture-blueprint/interaction_parity_checks.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "change": "full-modernization-architecture-blueprint", - "required_flows": { - "/wip-overview": ["filter_apply", "filter_reset", "status_card_drill"], - "/wip-detail": ["list_detail_continuity", "pagination", "filter_reset"], - "/hold-overview": ["reason_toggle", "matrix_selection", "lot_scope_sync"], - "/hold-detail": ["reason_required_redirect", "distribution_toggle", "lot_scope_sync"], - "/hold-history": ["date_range_query", "pareto_selection", "duration_bucket_selection"], - "/resource": ["status_filter", "workcenter_family_filter", "tooltip_open_close"], - "/resource-history": ["query_submit", "export_csv", "chart_detail_sync"], - "/qc-gate": ["chart_bucket_selection", "table_filter_sync", "filter_clear"], - "/job-query": ["resource_select", "query_submit", "export_csv"], - "/tmtt-defect": ["date_range_query", "chart_filter_link", "detail_sort"], - "/admin/pages": ["drawer_crud", "page_status_update", "admin_visibility"], - "/admin/performance": ["admin_auth_access", "performance_view_load"], - "/tables": ["table_select", "column_filter_apply", "query_submit"], - "/excel-query": ["file_upload", "column_select", "query_execute", "export_csv"], - "/query-tool": ["lot_resolve", "history_load", "association_query", "equipment_period_query", "export_csv"], - "/mid-section-defect": ["date_range_query", "loss_reason_filter", "pareto_chart_drill", "detail_pagination", "export_csv"] - } -} diff --git a/docs/migration/full-modernization-architecture-blueprint/known_bug_baseline.json b/docs/migration/full-modernization-architecture-blueprint/known_bug_baseline.json deleted file mode 100644 index 7788dfe..0000000 --- a/docs/migration/full-modernization-architecture-blueprint/known_bug_baseline.json +++ /dev/null @@ -1,74 +0,0 @@ -{ - "change": "full-modernization-architecture-blueprint", - "scope": "all-governed-routes", - "routes": { - "/wip-overview": { - "baseline_status": "initialized", - "known_bugs": [] - }, - "/wip-detail": { - "baseline_status": "initialized", - "known_bugs": [] - }, - "/hold-overview": { - "baseline_status": "initialized", - "known_bugs": [] - }, - "/hold-detail": { - "baseline_status": "initialized", - "known_bugs": [] - }, - "/hold-history": { - "baseline_status": "initialized", - "known_bugs": [] - }, - "/resource": { - "baseline_status": "initialized", - "known_bugs": [] - }, - "/resource-history": { - "baseline_status": "initialized", - "known_bugs": [] - }, - "/qc-gate": { - "baseline_status": "initialized", - "known_bugs": [] - }, - "/job-query": { - "baseline_status": "initialized", - "known_bugs": [] - }, - "/tmtt-defect": { - "baseline_status": "initialized", - "known_bugs": [] - }, - "/admin/pages": { - "baseline_status": "initialized", - "known_bugs": [] - }, - "/admin/performance": { - "baseline_status": "initialized", - "known_bugs": [] - }, - "/tables": { - "baseline_status": "initialized", - "known_bugs": [] - }, - "/excel-query": { - "baseline_status": "initialized", - "known_bugs": [] - }, - "/query-tool": { - "baseline_status": "initialized", - "known_bugs": [] - }, - "/mid-section-defect": { - "baseline_status": "initialized", - "known_bugs": [] - } - }, - "revalidation_rule": { - "reproduced_legacy_bug_blocks_signoff": true, - "reproduced_legacy_bug_blocks_legacy_retirement": true - } -} diff --git a/docs/migration/full-modernization-architecture-blueprint/manual_acceptance_records.json b/docs/migration/full-modernization-architecture-blueprint/manual_acceptance_records.json deleted file mode 100644 index f74bbde..0000000 --- a/docs/migration/full-modernization-architecture-blueprint/manual_acceptance_records.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "change": "full-modernization-architecture-blueprint", - "records": [], - "rule": "next route cutover is blocked until current route has approved manual sign-off" -} diff --git a/docs/migration/full-modernization-architecture-blueprint/observability_checkpoints.md b/docs/migration/full-modernization-architecture-blueprint/observability_checkpoints.md deleted file mode 100644 index 69c0e72..0000000 --- a/docs/migration/full-modernization-architecture-blueprint/observability_checkpoints.md +++ /dev/null @@ -1,32 +0,0 @@ -# Modernization Observability Checkpoints - -## Route Governance Signals - -1. `navigation_contract_mismatch_total` -- Source: `/api/portal/navigation` diagnostics. -- Alert condition: non-zero for in-scope routes. - -2. `route_contract_missing_metadata_total` -- Source: route governance CI script. -- Alert condition: >0 in block mode. - -## Quality Gate Signals - -1. `quality_gate_failed_total{gate_id}` -- Source: quality gate report. -- Alert condition: any mandatory gate failed. - -2. `manual_acceptance_pending_routes` -- Source: manual acceptance records. -- Alert condition: cutover attempted with pending sign-off. - -## Fallback and Rollback Signals - -1. `in_scope_runtime_fallback_served_total` -- Should remain zero after fallback retirement milestone. - -2. `content_cutover_flag_rollbacks_total` -- Track frequency and route impact. - -3. `legacy_bug_replay_failures_total` -- Any non-zero indicates carry-over risk and blocks sign-off. diff --git a/docs/migration/full-modernization-architecture-blueprint/page_content_manual_acceptance_checklist.md b/docs/migration/full-modernization-architecture-blueprint/page_content_manual_acceptance_checklist.md deleted file mode 100644 index 43dc5e4..0000000 --- a/docs/migration/full-modernization-architecture-blueprint/page_content_manual_acceptance_checklist.md +++ /dev/null @@ -1,28 +0,0 @@ -# Page Content Manual Acceptance Checklist - -## Rule - -- Route cutover proceeds one route at a time. -- Next route cutover is blocked until current route is manually signed off. -- Legacy code retirement is blocked until parity checks and manual sign-off are both complete. - -## Mandatory Checks Per Route - -1. Filter semantics match baseline (apply, reset, URL/query continuity). -2. Chart interactions match baseline (drill/selection/clear behavior). -3. Empty/loading/error/success states are correct and non-overlapping. -4. Table/chart linked interactions remain deterministic. -5. Accessibility: keyboard flow, focus visibility, `aria-*` semantics, reduced-motion behavior. -6. Known-bug replay checks completed (see `known_bug_baseline.json`). -7. No reproduced legacy bug in migrated scope. - -## Sign-Off Template - -- Route: -- Owner: -- Reviewer: -- Date: -- Parity evidence links: -- Known-bug replay result: -- Blocking defects: -- Decision: `approved` | `rework-required` diff --git a/docs/migration/full-modernization-architecture-blueprint/parity_golden_fixtures.json b/docs/migration/full-modernization-architecture-blueprint/parity_golden_fixtures.json deleted file mode 100644 index 670f289..0000000 --- a/docs/migration/full-modernization-architecture-blueprint/parity_golden_fixtures.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "change": "full-modernization-architecture-blueprint", - "fixtures": { - "/wip-overview": ["tests/fixtures/frontend_compute_parity.json"], - "/wip-detail": ["docs/migration/portal-shell-route-view-integration/wave-b-parity-evidence.json"], - "/hold-overview": ["docs/migration/portal-shell-route-view-integration/baseline_interaction_evidence.json"], - "/hold-detail": ["docs/migration/portal-shell-route-view-integration/baseline_interaction_evidence.json"], - "/hold-history": ["docs/migration/portal-shell-route-view-integration/baseline_interaction_evidence.json"], - "/resource": ["docs/migration/portal-shell-route-view-integration/baseline_api_payload_contracts.json"], - "/resource-history": ["docs/migration/portal-shell-route-view-integration/baseline_api_payload_contracts.json"], - "/qc-gate": ["docs/migration/portal-shell-route-view-integration/visual-regression-snapshots.json"], - "/job-query": ["docs/migration/portal-shell-route-view-integration/wave-b-parity-evidence.json"], - "/tmtt-defect": ["docs/migration/portal-shell-route-view-integration/wave-b-parity-evidence.json"], - "/admin/pages": ["tests/test_portal_shell_routes.py"], - "/admin/performance": ["tests/test_performance_integration.py"], - "/tables": ["tests/test_portal_shell_routes.py"], - "/excel-query": ["tests/test_portal_shell_routes.py"], - "/query-tool": ["tests/test_portal_shell_routes.py"], - "/mid-section-defect": ["tests/test_portal_shell_routes.py"] - } -} diff --git a/docs/migration/full-modernization-architecture-blueprint/performance_budgets.json b/docs/migration/full-modernization-architecture-blueprint/performance_budgets.json deleted file mode 100644 index 7767a8d..0000000 --- a/docs/migration/full-modernization-architecture-blueprint/performance_budgets.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "change": "full-modernization-architecture-blueprint", - "targets": { - "shell_navigation_api_avg_ms": 150, - "shell_navigation_api_p95_ms": 350, - "portal_shell_entry_avg_ms": 200, - "portal_shell_entry_p95_ms": 450 - }, - "source_baselines": [ - "docs/migration/portal-no-iframe/performance_baseline_spa.json", - "docs/migration/portal-no-iframe/performance_baseline_legacy.json" - ] -} diff --git a/docs/migration/full-modernization-architecture-blueprint/quality_gate_policy.json b/docs/migration/full-modernization-architecture-blueprint/quality_gate_policy.json deleted file mode 100644 index 49338bc..0000000 --- a/docs/migration/full-modernization-architecture-blueprint/quality_gate_policy.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "change": "full-modernization-architecture-blueprint", - "severity_mode": { - "current": "warn", - "promotion_target": "block", - "promotion_milestone": "2026-02-27" - }, - "gates": [ - {"id": "Q1", "name": "functional-parity", "required": true}, - {"id": "Q2", "name": "visual-regression", "required": true}, - {"id": "Q3", "name": "accessibility-keyboard-aria-motion", "required": true}, - {"id": "Q4", "name": "performance-budget", "required": true}, - {"id": "Q5", "name": "manual-acceptance-and-bug-revalidation", "required": true} - ], - "deferred_routes_excluded": [] -} diff --git a/docs/migration/full-modernization-architecture-blueprint/quality_gate_report.json b/docs/migration/full-modernization-architecture-blueprint/quality_gate_report.json deleted file mode 100644 index c072630..0000000 --- a/docs/migration/full-modernization-architecture-blueprint/quality_gate_report.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "mode": "block", - "errors": [], - "warnings": [ - "/excel-query uses shell tokens without fallback ['--portal-shadow-panel'] in frontend/src/excel-query/style.css with approved exception" - ], - "info": [], - "passed": true -} diff --git a/docs/migration/full-modernization-architecture-blueprint/rollback_controls.md b/docs/migration/full-modernization-architecture-blueprint/rollback_controls.md deleted file mode 100644 index b9539cf..0000000 --- a/docs/migration/full-modernization-architecture-blueprint/rollback_controls.md +++ /dev/null @@ -1,26 +0,0 @@ -# Full Modernization Rollback Controls - -## Route-Level Reversion Controls - -- `PORTAL_SPA_ENABLED=false`: - Disable shell-first navigation runtime globally. -- Route-scoped contract fallback: - Mark route contract with fallback strategy and redeploy shell assets. -- Content cutover feature flag: - Disable route-level modernized content path while keeping shell runtime up. - -## False-Positive Gate Handling - -1. Capture failing gate output and route impact. -2. Confirm whether failure is test flake or product defect. -3. If false-positive and production risk is high: -- Temporarily switch gate severity from `block` to `warn`. -- Record waiver with owner, reason, expiry. -4. Restore `block` mode after corrective action. - -## Required Rollback Evidence - -- Incident timestamp and impacted routes. -- Gate IDs that triggered rollback. -- Route contract state before/after rollback. -- Manual acceptance and known-bug replay references. diff --git a/docs/migration/full-modernization-architecture-blueprint/rollout_runbook.md b/docs/migration/full-modernization-architecture-blueprint/rollout_runbook.md deleted file mode 100644 index eeab681..0000000 --- a/docs/migration/full-modernization-architecture-blueprint/rollout_runbook.md +++ /dev/null @@ -1,33 +0,0 @@ -# Full Modernization Rollout Runbook - -## Phase Sequence - -1. Governance freeze -- Confirm `route_scope_matrix.json` has no pending route-scope changes. -- Confirm exception registry entries include owner + milestone. - -2. Route governance enforcement -- Run route contract completeness checks in warn mode. -- Fix all in-scope metadata gaps. -- Promote route governance checks to block mode. - -3. Style/content hardening -- Apply style isolation checks for in-scope routes. -- Execute parity checks and manual acceptance route-by-route. -- Run known-bug replay checks per route. - -4. Asset/gate enforcement -- Validate in-scope asset readiness. -- Run quality gate suite (functional, visual, accessibility, performance). -- Promote gate severity from warn to block according to policy. - -## Hold Points - -- Hold-1: Any in-scope route missing contract metadata. -- Hold-2: Any unresolved style exception past milestone. -- Hold-3: Any parity failure or known-bug replay failure. -- Hold-4: Any mandatory quality gate failure in block mode. - -## Promotion Rule - -Promotion is allowed only when all hold points are clear and no deferred-route checks were incorrectly included as blockers. diff --git a/docs/migration/full-modernization-architecture-blueprint/route_content_contracts.json b/docs/migration/full-modernization-architecture-blueprint/route_content_contracts.json deleted file mode 100644 index abb3dee..0000000 --- a/docs/migration/full-modernization-architecture-blueprint/route_content_contracts.json +++ /dev/null @@ -1,101 +0,0 @@ -{ - "change": "full-modernization-architecture-blueprint", - "in_scope_routes": { - "/wip-overview": { - "filter_input_semantics": ["workorder", "lotid", "package", "type", "status"], - "query_payload_contract": ["workorder", "lotid", "package", "type", "status"], - "chart_data_shape": ["status_cards", "matrix", "pareto"], - "state_contract": ["loading", "empty", "error", "success"] - }, - "/wip-detail": { - "filter_input_semantics": ["workcenter", "workorder", "lotid", "package", "type", "status", "page"], - "query_payload_contract": ["workcenter", "workorder", "lotid", "package", "type", "status", "page"], - "chart_data_shape": ["summary_cards", "lot_table"], - "state_contract": ["loading", "empty", "error", "success"] - }, - "/hold-overview": { - "filter_input_semantics": ["hold_type", "reason", "workcenter", "package", "age_range", "page"], - "query_payload_contract": ["hold_type", "reason", "workcenter", "package", "age_range", "page"], - "chart_data_shape": ["summary_cards", "matrix", "treemap", "lot_table"], - "state_contract": ["loading", "empty", "error", "success"] - }, - "/hold-detail": { - "filter_input_semantics": ["reason", "workcenter", "package", "age_range", "page"], - "query_payload_contract": ["reason", "workcenter", "package", "age_range", "page"], - "chart_data_shape": ["summary_cards", "distribution", "lot_table"], - "state_contract": ["loading", "empty", "error", "success"] - }, - "/hold-history": { - "filter_input_semantics": ["start_date", "end_date", "hold_type", "record_type", "reason", "duration_range", "page"], - "query_payload_contract": ["start_date", "end_date", "hold_type", "record_type", "reason", "duration_range", "page"], - "chart_data_shape": ["trend", "reason_pareto", "duration", "detail_table"], - "state_contract": ["loading", "empty", "error", "success"] - }, - "/resource": { - "filter_input_semantics": ["workcenter_groups", "families", "resource_ids", "statuses"], - "query_payload_contract": ["workcenter_groups", "families", "resource_ids", "statuses"], - "chart_data_shape": ["summary_cards", "status_matrix", "equipment_grid"], - "state_contract": ["loading", "empty", "error", "success"] - }, - "/resource-history": { - "filter_input_semantics": ["start_date", "end_date", "granularity", "workcenter_groups", "families", "resource_ids", "is_production", "is_key", "is_monitor"], - "query_payload_contract": ["start_date", "end_date", "granularity", "workcenter_groups", "families", "resource_ids", "is_production", "is_key", "is_monitor"], - "chart_data_shape": ["kpi", "trend", "heatmap", "workcenter_comparison", "detail"], - "state_contract": ["loading", "empty", "error", "success"] - }, - "/qc-gate": { - "filter_input_semantics": ["chart_bucket_selection", "table_sort"], - "query_payload_contract": ["summary", "table", "pareto"], - "chart_data_shape": ["station_stack_chart", "linked_lot_table"], - "state_contract": ["loading", "empty", "error", "success"] - }, - "/job-query": { - "filter_input_semantics": ["resource_ids", "start_date", "end_date"], - "query_payload_contract": ["resource_ids", "start_date", "end_date"], - "chart_data_shape": ["job_table", "txn_table"], - "state_contract": ["loading", "empty", "error", "success"] - }, - "/tmtt-defect": { - "filter_input_semantics": ["start_date", "end_date", "sort", "page"], - "query_payload_contract": ["start_date", "end_date"], - "chart_data_shape": ["kpi", "pareto", "trend", "detail_table"], - "state_contract": ["loading", "empty", "error", "success"] - }, - "/admin/pages": { - "filter_input_semantics": ["drawer_crud", "page_status_edit", "order_updates"], - "query_payload_contract": ["drawers", "pages", "status"], - "chart_data_shape": ["n/a"], - "state_contract": ["loading", "empty", "error", "success"] - }, - "/admin/performance": { - "filter_input_semantics": ["date_range", "severity", "search"], - "query_payload_contract": ["performance_summary", "log_stream"], - "chart_data_shape": ["timeline", "status_summary"], - "state_contract": ["loading", "empty", "error", "success"] - }, - "/tables": { - "filter_input_semantics": ["table_category", "table_name", "dynamic_column_filters"], - "query_payload_contract": ["table_name", "limit", "time_field", "filters"], - "chart_data_shape": ["dynamic_data_table"], - "state_contract": ["loading", "empty", "error", "success"] - }, - "/excel-query": { - "filter_input_semantics": ["file_upload", "excel_column", "table_name", "search_column", "query_type", "return_columns", "date_range"], - "query_payload_contract": ["table_name", "search_column", "return_columns", "search_values", "query_type", "date_column", "date_from", "date_to"], - "chart_data_shape": ["result_table", "csv_export"], - "state_contract": ["loading", "empty", "error", "success"] - }, - "/query-tool": { - "filter_input_semantics": ["input_type", "workcenter_groups", "input_values", "association_type", "equipment_ids", "equipment_query_type", "start_date", "end_date"], - "query_payload_contract": ["input_type", "values", "container_id", "workcenter_groups", "type", "equipment_ids", "equipment_names", "start_date", "end_date", "query_type"], - "chart_data_shape": ["resolved_lots_table", "lot_history_table", "association_table", "equipment_table"], - "state_contract": ["loading", "empty", "error", "success"] - }, - "/mid-section-defect": { - "filter_input_semantics": ["start_date", "end_date", "loss_reasons"], - "query_payload_contract": ["start_date", "end_date", "loss_reasons", "page", "page_size"], - "chart_data_shape": ["kpi_cards", "pareto_by_station", "pareto_by_loss_reason", "pareto_by_machine", "pareto_by_tmtt_machine", "pareto_by_workflow", "pareto_by_package", "daily_trend", "detail_table"], - "state_contract": ["loading", "empty", "error", "success"] - } - } -} diff --git a/docs/migration/full-modernization-architecture-blueprint/route_contracts.json b/docs/migration/full-modernization-architecture-blueprint/route_contracts.json deleted file mode 100644 index b53916f..0000000 --- a/docs/migration/full-modernization-architecture-blueprint/route_contracts.json +++ /dev/null @@ -1,166 +0,0 @@ -{ - "change": "full-modernization-architecture-blueprint", - "generated_at": "2026-02-12T00:00:00Z", - "routes": [ - { - "route": "/wip-overview", - "route_id": "wip-overview", - "scope": "in-scope", - "render_mode": "native", - "owner": "frontend-mes-reporting", - "visibility_policy": "released_or_admin", - "canonical_shell_path": "/portal-shell/wip-overview", - "rollback_strategy": "fallback_to_legacy_route" - }, - { - "route": "/wip-detail", - "route_id": "wip-detail", - "scope": "in-scope", - "render_mode": "native", - "owner": "frontend-mes-reporting", - "visibility_policy": "released_or_admin", - "canonical_shell_path": "/portal-shell/wip-detail", - "rollback_strategy": "fallback_to_legacy_route" - }, - { - "route": "/hold-overview", - "route_id": "hold-overview", - "scope": "in-scope", - "render_mode": "native", - "owner": "frontend-mes-reporting", - "visibility_policy": "released_or_admin", - "canonical_shell_path": "/portal-shell/hold-overview", - "rollback_strategy": "fallback_to_legacy_route" - }, - { - "route": "/hold-detail", - "route_id": "hold-detail", - "scope": "in-scope", - "render_mode": "native", - "owner": "frontend-mes-reporting", - "visibility_policy": "released_or_admin", - "canonical_shell_path": "/portal-shell/hold-detail", - "rollback_strategy": "fallback_to_legacy_route" - }, - { - "route": "/hold-history", - "route_id": "hold-history", - "scope": "in-scope", - "render_mode": "native", - "owner": "frontend-mes-reporting", - "visibility_policy": "released_or_admin", - "canonical_shell_path": "/portal-shell/hold-history", - "rollback_strategy": "fallback_to_legacy_route" - }, - { - "route": "/resource", - "route_id": "resource", - "scope": "in-scope", - "render_mode": "native", - "owner": "frontend-mes-reporting", - "visibility_policy": "released_or_admin", - "canonical_shell_path": "/portal-shell/resource", - "rollback_strategy": "fallback_to_legacy_route" - }, - { - "route": "/resource-history", - "route_id": "resource-history", - "scope": "in-scope", - "render_mode": "native", - "owner": "frontend-mes-reporting", - "visibility_policy": "released_or_admin", - "canonical_shell_path": "/portal-shell/resource-history", - "rollback_strategy": "fallback_to_legacy_route" - }, - { - "route": "/qc-gate", - "route_id": "qc-gate", - "scope": "in-scope", - "render_mode": "native", - "owner": "frontend-mes-reporting", - "visibility_policy": "released_or_admin", - "canonical_shell_path": "/portal-shell/qc-gate", - "rollback_strategy": "fallback_to_legacy_route" - }, - { - "route": "/job-query", - "route_id": "job-query", - "scope": "in-scope", - "render_mode": "native", - "owner": "frontend-mes-reporting", - "visibility_policy": "released_or_admin", - "canonical_shell_path": "/portal-shell/job-query", - "rollback_strategy": "fallback_to_legacy_route" - }, - { - "route": "/tmtt-defect", - "route_id": "tmtt-defect", - "scope": "in-scope", - "render_mode": "native", - "owner": "frontend-mes-reporting", - "visibility_policy": "released_or_admin", - "canonical_shell_path": "/portal-shell/tmtt-defect", - "rollback_strategy": "fallback_to_legacy_route" - }, - { - "route": "/admin/pages", - "route_id": "admin-pages", - "scope": "in-scope", - "render_mode": "external", - "owner": "frontend-platform-admin", - "visibility_policy": "admin_only", - "canonical_shell_path": "/portal-shell/admin/pages", - "rollback_strategy": "external_route_reversion" - }, - { - "route": "/admin/performance", - "route_id": "admin-performance", - "scope": "in-scope", - "render_mode": "external", - "owner": "frontend-platform-admin", - "visibility_policy": "admin_only", - "canonical_shell_path": "/portal-shell/admin/performance", - "rollback_strategy": "external_route_reversion" - }, - { - "route": "/tables", - "route_id": "tables", - "scope": "in-scope", - "render_mode": "native", - "owner": "frontend-mes-reporting", - "visibility_policy": "released_or_admin", - "canonical_shell_path": "/portal-shell/tables", - "rollback_strategy": "fallback_to_legacy_route" - }, - { - "route": "/excel-query", - "route_id": "excel-query", - "scope": "in-scope", - "render_mode": "native", - "owner": "frontend-mes-reporting", - "visibility_policy": "released_or_admin", - "canonical_shell_path": "/portal-shell/excel-query", - "rollback_strategy": "fallback_to_legacy_route" - }, - { - "route": "/query-tool", - "route_id": "query-tool", - "scope": "in-scope", - "render_mode": "native", - "owner": "frontend-mes-reporting", - "visibility_policy": "released_or_admin", - "canonical_shell_path": "/portal-shell/query-tool", - "rollback_strategy": "fallback_to_legacy_route" - }, - { - "route": "/mid-section-defect", - "route_id": "mid-section-defect", - "scope": "in-scope", - "render_mode": "native", - "owner": "frontend-mes-reporting", - "visibility_policy": "released_or_admin", - "canonical_shell_path": "/portal-shell/mid-section-defect", - "rollback_strategy": "fallback_to_legacy_route" - } - ] -} diff --git a/docs/migration/full-modernization-architecture-blueprint/route_scope_matrix.json b/docs/migration/full-modernization-architecture-blueprint/route_scope_matrix.json deleted file mode 100644 index 199cae7..0000000 --- a/docs/migration/full-modernization-architecture-blueprint/route_scope_matrix.json +++ /dev/null @@ -1,132 +0,0 @@ -{ - "change": "full-modernization-architecture-blueprint", - "generated_at": "2026-02-12T00:00:00Z", - "phase": "phase-1-shell-and-content-modernization", - "policy": { - "scope_is_frozen": true, - "out_of_scope_tasks_must_be_rejected": true - }, - "in_scope": [ - { - "route": "/wip-overview", - "category": "report", - "canonical_shell_path": "/portal-shell/wip-overview", - "owner": "frontend-mes-reporting", - "visibility_policy": "released_or_admin" - }, - { - "route": "/wip-detail", - "category": "report", - "canonical_shell_path": "/portal-shell/wip-detail", - "owner": "frontend-mes-reporting", - "visibility_policy": "released_or_admin" - }, - { - "route": "/hold-overview", - "category": "report", - "canonical_shell_path": "/portal-shell/hold-overview", - "owner": "frontend-mes-reporting", - "visibility_policy": "released_or_admin" - }, - { - "route": "/hold-detail", - "category": "report", - "canonical_shell_path": "/portal-shell/hold-detail", - "owner": "frontend-mes-reporting", - "visibility_policy": "released_or_admin" - }, - { - "route": "/hold-history", - "category": "report", - "canonical_shell_path": "/portal-shell/hold-history", - "owner": "frontend-mes-reporting", - "visibility_policy": "released_or_admin" - }, - { - "route": "/resource", - "category": "report", - "canonical_shell_path": "/portal-shell/resource", - "owner": "frontend-mes-reporting", - "visibility_policy": "released_or_admin" - }, - { - "route": "/resource-history", - "category": "report", - "canonical_shell_path": "/portal-shell/resource-history", - "owner": "frontend-mes-reporting", - "visibility_policy": "released_or_admin" - }, - { - "route": "/qc-gate", - "category": "report", - "canonical_shell_path": "/portal-shell/qc-gate", - "owner": "frontend-mes-reporting", - "visibility_policy": "released_or_admin" - }, - { - "route": "/job-query", - "category": "report", - "canonical_shell_path": "/portal-shell/job-query", - "owner": "frontend-mes-reporting", - "visibility_policy": "released_or_admin" - }, - { - "route": "/tmtt-defect", - "category": "report", - "canonical_shell_path": "/portal-shell/tmtt-defect", - "owner": "frontend-mes-reporting", - "visibility_policy": "released_or_admin" - }, - { - "route": "/admin/pages", - "category": "admin", - "canonical_shell_path": "/portal-shell/admin/pages", - "owner": "frontend-platform-admin", - "visibility_policy": "admin_only" - }, - { - "route": "/admin/performance", - "category": "admin", - "canonical_shell_path": "/portal-shell/admin/performance", - "owner": "frontend-platform-admin", - "visibility_policy": "admin_only" - }, - { - "route": "/tables", - "category": "report", - "canonical_shell_path": "/portal-shell/tables", - "owner": "frontend-mes-reporting", - "visibility_policy": "released_or_admin", - "promoted_from": "deferred", - "promoted_by": "deferred-route-modernization-follow-up" - }, - { - "route": "/excel-query", - "category": "report", - "canonical_shell_path": "/portal-shell/excel-query", - "owner": "frontend-mes-reporting", - "visibility_policy": "released_or_admin", - "promoted_from": "deferred", - "promoted_by": "deferred-route-modernization-follow-up" - }, - { - "route": "/query-tool", - "category": "report", - "canonical_shell_path": "/portal-shell/query-tool", - "owner": "frontend-mes-reporting", - "visibility_policy": "released_or_admin", - "promoted_from": "deferred", - "promoted_by": "deferred-route-modernization-follow-up" - }, - { - "route": "/mid-section-defect", - "category": "report", - "canonical_shell_path": "/portal-shell/mid-section-defect", - "owner": "frontend-mes-reporting", - "visibility_policy": "released_or_admin", - "promoted_from": "deferred", - "promoted_by": "deferred-route-modernization-follow-up" - } - ], - "deferred": [] -} diff --git a/docs/migration/full-modernization-architecture-blueprint/style_inventory.json b/docs/migration/full-modernization-architecture-blueprint/style_inventory.json deleted file mode 100644 index ae9bc1e..0000000 --- a/docs/migration/full-modernization-architecture-blueprint/style_inventory.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "change": "full-modernization-architecture-blueprint", - "generated_at": "2026-02-12T00:00:00Z", - "in_scope_routes": { - "/wip-overview": {"global_selectors": [], "status": "clean"}, - "/wip-detail": {"global_selectors": [], "status": "clean"}, - "/hold-overview": {"global_selectors": [], "status": "clean"}, - "/hold-detail": {"global_selectors": [], "status": "clean"}, - "/hold-history": {"global_selectors": [], "status": "clean"}, - "/resource": {"global_selectors": [], "status": "clean"}, - "/resource-history": {"global_selectors": [], "status": "clean"}, - "/qc-gate": {"global_selectors": [], "status": "clean-after-refactor"}, - "/job-query": {"global_selectors": [], "status": "clean"}, - "/tmtt-defect": {"global_selectors": [], "status": "clean"}, - "/admin/pages": { - "global_selectors": ["body"], - "status": "exception-registered", - "exception_id": "style-admin-pages-inline-css" - }, - "/admin/performance": { - "global_selectors": ["body"], - "status": "exception-registered", - "exception_id": "style-admin-performance-inline-css" - }, - "/tables": {"global_selectors": [], "status": "pending-audit"}, - "/excel-query": {"global_selectors": [], "status": "pending-audit"}, - "/query-tool": {"global_selectors": [], "status": "pending-audit"}, - "/mid-section-defect": {"global_selectors": [], "status": "pending-audit"} - }, - "shared_layers": { - "frontend/src/styles/tailwind.css": [":root", "body"], - "frontend/src/portal-shell/style.css": [":root", "body"] - } -} diff --git a/docs/migration/portal-no-iframe/archive_readiness.md b/docs/migration/portal-no-iframe/archive_readiness.md deleted file mode 100644 index 6a4fc8b..0000000 --- a/docs/migration/portal-no-iframe/archive_readiness.md +++ /dev/null @@ -1,33 +0,0 @@ -# OpenSpec Archive Readiness (`portal-no-iframe-navigation`) - -## Spec Sync Scope - -Main specs synchronized/updated for this change: - -- `openspec/specs/full-vite-page-modularization/spec.md` -- `openspec/specs/portal-drawer-navigation/spec.md` -- `openspec/specs/vue-vite-page-architecture/spec.md` -- `openspec/specs/migration-gates-and-rollout/spec.md` -- `openspec/specs/spa-shell-navigation/spec.md` (new) -- `openspec/specs/tailwind-design-system/spec.md` (new) -- `openspec/specs/frontend-motion-system/spec.md` (new) -- `openspec/specs/legacy-page-wrapper-strategy/spec.md` (new) - -## Migration Closure Artifacts - -- Rewrite smoke checklist: - - `docs/migration/portal-no-iframe/legacy_rewrite_smoke_checklists.md` -- Rewrite exemplar: - - `docs/migration/portal-no-iframe/tmtt_rewrite_exemplar.md` -- Rewrite playbook: - - `docs/migration/portal-no-iframe/legacy_rewrite_playbook.md` -- Wrapper decommission record: - - `docs/migration/portal-no-iframe/wrapper_decommission_report.md` -- Frame field retirement record: - - `docs/migration/portal-no-iframe/frame_id_tool_src_deprecation_plan.md` - -## Pre-Archive Checklist - -- [x] `openspec validate portal-no-iframe-navigation --strict` passes. -- [x] Build and core migration tests pass on latest branch. -- [x] Task list in `openspec/changes/portal-no-iframe-navigation/tasks.md` is fully checked. diff --git a/docs/migration/portal-no-iframe/baseline_api_payload_contracts.json b/docs/migration/portal-no-iframe/baseline_api_payload_contracts.json deleted file mode 100644 index 42a4774..0000000 --- a/docs/migration/portal-no-iframe/baseline_api_payload_contracts.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "source": "current frontend API consumption contracts", - "apis": { - "/api/wip/overview/summary": { - "required_keys": [ - "dataUpdateDate", - "runLots", - "queueLots", - "holdLots" - ], - "notes": "summary header and cards depend on these fields" - }, - "/api/wip/overview/matrix": { - "required_keys": [ - "workcenters", - "packages", - "matrix", - "workcenter_totals" - ], - "notes": "matrix table rendering contract" - }, - "/api/wip/hold-detail/summary": { - "required_keys": [ - "workcenterCount", - "packageCount", - "lotCount" - ], - "notes": "hold detail summary cards contract" - }, - "/api/resource/history/summary": { - "required_keys": [ - "kpi", - "trend", - "heatmap", - "workcenter_comparison" - ], - "notes": "resource history chart summary contract" - }, - "/api/resource/history/detail": { - "required_keys": [ - "data" - ], - "notes": "detail table contract (plus truncated/max_records metadata when present)" - } - } -} diff --git a/docs/migration/portal-no-iframe/baseline_drawer_contract_validation.json b/docs/migration/portal-no-iframe/baseline_drawer_contract_validation.json deleted file mode 100644 index 177e28b..0000000 --- a/docs/migration/portal-no-iframe/baseline_drawer_contract_validation.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "source": "data/page_status.json", - "errors": [] -} diff --git a/docs/migration/portal-no-iframe/baseline_drawer_visibility.json b/docs/migration/portal-no-iframe/baseline_drawer_visibility.json deleted file mode 100644 index 4a83cbc..0000000 --- a/docs/migration/portal-no-iframe/baseline_drawer_visibility.json +++ /dev/null @@ -1,190 +0,0 @@ -{ - "generated_at": "2026-02-12T02:26:36.887797+00:00", - "source": "data/page_status.json", - "admin": [ - { - "id": "reports", - "name": "即時報表", - "order": 1, - "admin_only": false, - "pages": [ - { - "route": "/wip-overview", - "name": "WIP 即時概況", - "status": "released", - "order": 1 - }, - { - "route": "/hold-overview", - "name": "Hold 即時概況", - "status": "released", - "order": 2 - }, - { - "route": "/resource", - "name": "設備即時概況", - "status": "released", - "order": 4 - }, - { - "route": "/qc-gate", - "name": "QC-GATE 狀態", - "status": "released", - "order": 6 - } - ] - }, - { - "id": "drawer-2", - "name": "歷史報表", - "order": 2, - "admin_only": false, - "pages": [ - { - "route": "/hold-history", - "name": "Hold 歷史績效", - "status": "released", - "order": 3 - }, - { - "route": "/resource-history", - "name": "設備歷史績效", - "status": "released", - "order": 5 - } - ] - }, - { - "id": "drawer", - "name": "查詢工具", - "order": 3, - "admin_only": false, - "pages": [ - { - "route": "/job-query", - "name": "設備維修查詢", - "status": "released", - "order": 3 - } - ] - }, - { - "id": "dev-tools", - "name": "開發工具", - "order": 4, - "admin_only": true, - "pages": [ - { - "route": "/tables", - "name": "表格總覽", - "status": "dev", - "order": 1 - }, - { - "route": "/admin/pages", - "name": "頁面管理", - "status": "dev", - "order": 1 - }, - { - "route": "/excel-query", - "name": "Excel 批次查詢", - "status": "dev", - "order": 2 - }, - { - "route": "/admin/performance", - "name": "效能監控", - "status": "dev", - "order": 2 - }, - { - "route": "/query-tool", - "name": "批次追蹤工具", - "status": "dev", - "order": 4 - }, - { - "route": "/tmtt-defect", - "name": "TMTT印字腳型不良分析", - "status": "dev", - "order": 5 - }, - { - "route": "/mid-section-defect", - "name": "中段製程不良追溯", - "status": "dev", - "order": 6 - } - ] - } - ], - "non_admin": [ - { - "id": "reports", - "name": "即時報表", - "order": 1, - "admin_only": false, - "pages": [ - { - "route": "/wip-overview", - "name": "WIP 即時概況", - "status": "released", - "order": 1 - }, - { - "route": "/hold-overview", - "name": "Hold 即時概況", - "status": "released", - "order": 2 - }, - { - "route": "/resource", - "name": "設備即時概況", - "status": "released", - "order": 4 - }, - { - "route": "/qc-gate", - "name": "QC-GATE 狀態", - "status": "released", - "order": 6 - } - ] - }, - { - "id": "drawer-2", - "name": "歷史報表", - "order": 2, - "admin_only": false, - "pages": [ - { - "route": "/hold-history", - "name": "Hold 歷史績效", - "status": "released", - "order": 3 - }, - { - "route": "/resource-history", - "name": "設備歷史績效", - "status": "released", - "order": 5 - } - ] - }, - { - "id": "drawer", - "name": "查詢工具", - "order": 3, - "admin_only": false, - "pages": [ - { - "route": "/job-query", - "name": "設備維修查詢", - "status": "released", - "order": 3 - } - ] - } - ] -} diff --git a/docs/migration/portal-no-iframe/baseline_route_query_contracts.json b/docs/migration/portal-no-iframe/baseline_route_query_contracts.json deleted file mode 100644 index 220b0ec..0000000 --- a/docs/migration/portal-no-iframe/baseline_route_query_contracts.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "source": "frontend route parsing and current parity matrix", - "routes": { - "/wip-overview": { - "query_keys": [ - "workorder", - "lotid", - "package", - "type", - "status" - ], - "notes": "filters + status URL state must remain compatible" - }, - "/wip-detail": { - "query_keys": [ - "workcenter", - "workorder", - "lotid", - "package", - "type", - "status" - ], - "notes": "workcenter deep-link and back-link query continuity" - }, - "/hold-detail": { - "query_keys": [ - "reason" - ], - "notes": "reason required for normal access flow" - }, - "/resource-history": { - "query_keys": [ - "start_date", - "end_date", - "granularity", - "workcenter_groups", - "families", - "resource_ids", - "is_production", - "is_key", - "is_monitor" - ], - "notes": "query/export params must remain compatible" - } - } -} diff --git a/docs/migration/portal-no-iframe/drawer_governance_contract.md b/docs/migration/portal-no-iframe/drawer_governance_contract.md deleted file mode 100644 index 3d37e25..0000000 --- a/docs/migration/portal-no-iframe/drawer_governance_contract.md +++ /dev/null @@ -1,50 +0,0 @@ -# Drawer Governance Contract (Portal No-Iframe Migration) - -## Scope - -This contract defines drawer behavior that must remain stable during migration. - -## Canonical Responsibilities - -Drawer metadata is responsible for: - -- Information architecture grouping. -- Display order. -- Access visibility (`admin_only`). - -Drawer metadata is not responsible for: - -- Content embedding mode (`iframe`, `toolFrame`). -- Rendering technology selection (Jinja vs SPA route view). - -## Contract Rules - -1. Drawer IDs must be unique and non-empty. -2. Page routes must be unique and non-empty. -3. `page.drawer_id` (when present) must reference an existing drawer. -4. `order` values (when present) must be positive integers. -5. Page status must be one of `released` or `dev`. -6. Visibility outcomes must be deterministic for admin/non-admin users. - -## Deterministic Rendering Order - -Drawers: - -- Primary sort by `order` ascending. -- Secondary sort by `name` ascending. - -Pages in each drawer: - -- Primary sort by `order` ascending. -- Secondary sort by `(name or route)` ascending. - -## Visibility Semantics - -- Non-admin users can view only `released` pages in non-admin-only drawers. -- Admin users can view all drawer-assigned pages according to current page status policy. -- Drawers with zero visible pages are hidden. - -## Validation Artifacts - -- `baseline_drawer_contract_validation.json` -- `baseline_drawer_visibility.json` diff --git a/docs/migration/portal-no-iframe/frame_id_tool_src_deprecation_plan.md b/docs/migration/portal-no-iframe/frame_id_tool_src_deprecation_plan.md deleted file mode 100644 index a8c3787..0000000 --- a/docs/migration/portal-no-iframe/frame_id_tool_src_deprecation_plan.md +++ /dev/null @@ -1,44 +0,0 @@ -# `frame_id` / `tool_src` Deprecation Plan - -## Status - -- Retirement completed in this change. -- Runtime navigation payload generation no longer emits: - - `frame_id` - - `tool_src` - -## Context - -Frame-era fields were used for iframe loading compatibility: - -- `frame_id` -- `tool_src` - -## Policy - -Deprecation is phased and must not break active routes. - -## Phases - -1. **Compatibility phase**: - - Keep fields in payload. - - Ensure new router navigation logic does not rely on these fields. -2. **Dual-run phase**: - - Validate all navigation paths without frame fields. -3. **Retirement readiness**: - - Wrapper-first pages are stable in shell. - - Cutover gates G1~G7 are green in rehearsal. -4. **Removal phase**: - - Remove generation and downstream usage of `frame_id/tool_src`. - - Update related tests and docs. - -## Removal Checkpoints - -- Checkpoint A: drawer parity stable in canary. -- Checkpoint B: legacy wrappers stable with no frame-field dependency. -- Checkpoint C: rollback mechanism verified independent of frame fields. ✓ - -## Risk Controls - -- Keep rollback-safe path via route-level navigation and kill-switch. -- Keep gate coverage for route/drawer/workflow parity after field removal. diff --git a/docs/migration/portal-no-iframe/legacy_rewrite_playbook.md b/docs/migration/portal-no-iframe/legacy_rewrite_playbook.md deleted file mode 100644 index 63dd2cd..0000000 --- a/docs/migration/portal-no-iframe/legacy_rewrite_playbook.md +++ /dev/null @@ -1,40 +0,0 @@ -# Legacy Rewrite Playbook (Batch-2) - -## Target Pages - -This playbook governs rewrite execution for the remaining three legacy pages: - -- `/job-query` -- `/excel-query` -- `/query-tool` - -Rewrite order follows `legacy_rewrite_priority_matrix.md`. - -## Canonical Steps - -1. Preserve route and API contracts first. -2. Move page state and API calls into composables (`useData`). -3. Replace page-local repeated blocks with shared UI components where possible. -4. Keep Tailwind token alignment for new/changed UI. -5. Validate with per-page smoke checklist before/after switch. - -## Required Acceptance (Per Page) - -- Route reachable and functional without shell wrapper. -- Core query workflow succeeds and returns expected result sections. -- Export path remains usable (where applicable). -- No new unhandled runtime error on the primary path. -- Checklist IDs pass: - - `/job-query`: `JOB-SMOKE-01`~`JOB-SMOKE-06` - - `/excel-query`: `EXCEL-SMOKE-01`~`EXCEL-SMOKE-06` - - `/query-tool`: `QTOOL-SMOKE-01`~`QTOOL-SMOKE-06` - -Checklist source: - -- `docs/migration/portal-no-iframe/legacy_rewrite_smoke_checklists.md` - -## Shared Guardrails - -- Do not change backend API signatures in rewrite phase. -- Keep direct-link behavior and query semantics stable. -- If parity fails, rollback to previous stable page artifact before continuing. diff --git a/docs/migration/portal-no-iframe/legacy_rewrite_priority_matrix.md b/docs/migration/portal-no-iframe/legacy_rewrite_priority_matrix.md deleted file mode 100644 index f373053..0000000 --- a/docs/migration/portal-no-iframe/legacy_rewrite_priority_matrix.md +++ /dev/null @@ -1,40 +0,0 @@ -# Legacy Rewrite Priority Matrix - -## Scoring model - -`priority_score = usage(0-5)*0.3 + complexity(0-5)*0.4 + risk(0-5)*0.3` - -- Usage: current observed operational usage + business criticality. -- Complexity: route/API count, frontend LOC, workflow branches. -- Risk: data mutation/export/upload sensitivity and regression blast radius. - -## Measured technical baseline - -| Page | Backend route LOC | Template LOC | Frontend LOC | API surface | -| --- | ---: | ---: | ---: | --- | -| `query-tool` | 509 | 1267 | 3139 | resolve/history/adjacent/associations/equipment/export | -| `excel-query` | 355 | 1181 | 624 | upload/schema/query/export | -| `job-query` | 195 | 995 | 520 | resources/jobs/txn/export | -| `tmtt-defect` | 82 | 271 | 363 | analysis/query + CSV export | - -## Priority scoring - -| Page | Usage | Complexity | Risk | Score | -| --- | ---: | ---: | ---: | ---: | -| `tmtt-defect` | 2 | 1 | 2 | 1.6 | -| `job-query` | 3 | 2 | 3 | 2.6 | -| `excel-query` | 3 | 4 | 4 | 3.7 | -| `query-tool` | 4 | 5 | 5 | 4.7 | - -## Rewrite order decision - -1. `tmtt-defect` (canonical exemplar) -2. `job-query` -3. `excel-query` -4. `query-tool` - -## Rationale - -- Start with lowest-complexity page to establish shared migration playbook. -- Keep high-complexity/high-risk `query-tool` last to maximize reuse from prior rewrites. -- Defer upload-heavy `excel-query` until shared error/retry/upload patterns are stabilized. diff --git a/docs/migration/portal-no-iframe/legacy_rewrite_smoke_checklists.md b/docs/migration/portal-no-iframe/legacy_rewrite_smoke_checklists.md deleted file mode 100644 index e73ace2..0000000 --- a/docs/migration/portal-no-iframe/legacy_rewrite_smoke_checklists.md +++ /dev/null @@ -1,77 +0,0 @@ -# Legacy Rewrite Smoke Checklists (Per-Page) - -本文件是 `7.2 ~ 7.4` 的執行前置與驗收基準。 -每一頁在「重寫前(wrapper baseline)」與「重寫後(rewrite candidate)」都必須執行同一組 smoke。 - -## 0. 執行規則 - -- 必須記錄:執行日期、分支/commit、執行人、環境(DEV/UAT)。 -- 每頁 smoke 通過率要求:`100%`。 -- 任何 P0 smoke 失敗即視為 `No-Go`,不得進入 wrapper 移除。 -- `excel-query`、`query-tool` 為 admin/dev 可見頁,需使用 admin 身份執行。 - -## 1. `tmtt-defect`(Rewrite Exemplar) - -### 前置條件 -- 可取得有效 `start_date/end_date` 測試區間。 -- `/api/tmtt-defect/analysis` 與 `/api/tmtt-defect/export` 可連線。 - -### Smoke Cases -- [ ] `TMTT-SMOKE-01` Route reachable: `/tmtt-defect` 可直接開啟,無白屏/JS error。 -- [ ] `TMTT-SMOKE-02` Required params guard: 缺少日期時,顯示明確錯誤且不崩潰。 -- [ ] `TMTT-SMOKE-03` Query success: 送出合法日期後,KPI/Charts/Detail 皆成功渲染。 -- [ ] `TMTT-SMOKE-04` Drill-down: 點擊 Pareto 圖欄位可套用/清除篩選,明細同步。 -- [ ] `TMTT-SMOKE-05` Table behavior: 明細表格可排序,排序方向切換正確。 -- [ ] `TMTT-SMOKE-06` Export CSV: 匯出成功,response 為 CSV 且檔名包含日期區間。 - -## 2. `job-query` - -### 前置條件 -- `resource` 清單可取得。 -- 至少有一組可查詢日期區間。 - -### Smoke Cases -- [ ] `JOB-SMOKE-01` Route reachable: `/job-query` 可直接開啟。 -- [ ] `JOB-SMOKE-02` Resource loading: `/api/job-query/resources` 回傳清單,UI 可選取。 -- [ ] `JOB-SMOKE-03` Query jobs: 選設備+日期後可查詢成功並顯示結果。 -- [ ] `JOB-SMOKE-04` Txn detail: 由查詢結果可開啟某筆 job 的 txn history。 -- [ ] `JOB-SMOKE-05` Export CSV: 匯出成功且檔案可下載。 -- [ ] `JOB-SMOKE-06` Validation: 缺日期/無設備/超過上限時回傳明確錯誤訊息。 - -## 3. `excel-query`(Admin) - -### 前置條件 -- 準備一份有效 `.xlsx` 測試檔。 -- Admin session 已登入。 - -### Smoke Cases -- [ ] `EXCEL-SMOKE-01` Route/auth: `/excel-query` admin 可進入,非 admin 受保護。 -- [ ] `EXCEL-SMOKE-02` Upload: 上傳有效 Excel 後可解析欄位與預覽。 -- [ ] `EXCEL-SMOKE-03` Column detect: 欄位唯一值與型別偵測可正常運作。 -- [ ] `EXCEL-SMOKE-04` Execute query: 標準查詢與進階查詢都可回傳資料。 -- [ ] `EXCEL-SMOKE-05` Export CSV: 查詢結果可匯出 CSV。 -- [ ] `EXCEL-SMOKE-06` Invalid file guard: 非 `.xls/.xlsx` 檔案被拒絕且回傳可讀錯誤。 - -## 4. `query-tool`(Admin) - -### 前置條件 -- Admin session 已登入。 -- 可用測試 lot/equipment/date range。 - -### Smoke Cases -- [ ] `QTOOL-SMOKE-01` Route reachable: `/query-tool` 可開啟。 -- [ ] `QTOOL-SMOKE-02` Resolve flow: lot_id/serial/work_order 至少一種解析成功。 -- [ ] `QTOOL-SMOKE-03` History flow: lot history 可查詢並顯示。 -- [ ] `QTOOL-SMOKE-04` Adjacent flow: adjacent lots 查詢可回傳。 -- [ ] `QTOOL-SMOKE-05` Associations: materials/rejects/holds/splits/jobs 查詢可用。 -- [ ] `QTOOL-SMOKE-06` Equipment period: status_hours/lots/materials/rejects/jobs 至少各成功一次。 -- [ ] `QTOOL-SMOKE-07` Export CSV: 匯出可下載且欄位合理。 -- [ ] `QTOOL-SMOKE-08` Validation: 缺參數、非法日期範圍會回傳可讀錯誤。 - -## 5. Exit Rule(與 7.4 連動) - -只有在下列條件全成立,才可移除 wrapper: - -- [ ] 四頁 rewrite smoke 全部通過。 -- [ ] 與 `legacy_wrapper_telemetry_contract.md` 對照,error 率在門檻內。 -- [ ] 與 `parity_checklist.md` 的 Route/Workflow/API contract 檢查一致。 diff --git a/docs/migration/portal-no-iframe/legacy_wrapper_exit_criteria.md b/docs/migration/portal-no-iframe/legacy_wrapper_exit_criteria.md deleted file mode 100644 index 58cebc7..0000000 --- a/docs/migration/portal-no-iframe/legacy_wrapper_exit_criteria.md +++ /dev/null @@ -1,21 +0,0 @@ -# Legacy Wrapper Exit Criteria (Rewrite-ready) - -A wrapped page is rewrite-ready only when all criteria are met. - -## Functional readiness - -1. Core workflows are documented with at least one deterministic smoke script per workflow. -2. Route/query contract is frozen and covered by contract tests. -3. Export/upload side effects (if any) are reproducible in test or staging. - -## Technical readiness - -1. Shared UI and composables can cover at least 70% of page scaffolding (filters, cards, table shell, pagination). -2. Required API payload key/type contract is stable for two consecutive releases. -3. Wrapper telemetry shows no unresolved high-severity navigation failures in the last release cycle. - -## Operational readiness - -1. Rollback path for rewritten page is documented and rehearsed. -2. Error budget and success threshold for canary are defined before rewrite starts. -3. Product owner confirms parity acceptance checklist for the target page. diff --git a/docs/migration/portal-no-iframe/legacy_wrapper_telemetry_contract.md b/docs/migration/portal-no-iframe/legacy_wrapper_telemetry_contract.md deleted file mode 100644 index e929647..0000000 --- a/docs/migration/portal-no-iframe/legacy_wrapper_telemetry_contract.md +++ /dev/null @@ -1,40 +0,0 @@ -# Legacy Wrapper Telemetry Contract - -## Status - -- Retired after wrapper decommission. -- `POST /api/portal/wrapper-telemetry` has been removed. -- Reference only for historical migration traceability. - -## Wrapper scope - -- `/job-query` -- `/excel-query` -- `/query-tool` -- `/tmtt-defect` - -## Client events - -- `wrapper_loaded`: wrapper route rendered in shell. -- `launch`: user clicked "進入既有頁面" and navigation handoff started. - -## API endpoint - -- `POST /api/portal/wrapper-telemetry` -- Payload: - - `event_type: string` - - `route: string` (must be one of wrapper scope routes) - - `page_name?: string` - - `drawer_name?: string` - - `duration_ms?: number` - - `ts?: string` - -## Validation - -- Reject unknown routes with `400`. -- Reject missing `event_type` with `400`. - -## Fallback behavior - -- Wrapper UI always provides direct anchor navigation to the legacy route. -- Telemetry failure must not block navigation. diff --git a/docs/migration/portal-no-iframe/motion_baseline_guidelines.md b/docs/migration/portal-no-iframe/motion_baseline_guidelines.md deleted file mode 100644 index 0c23d59..0000000 --- a/docs/migration/portal-no-iframe/motion_baseline_guidelines.md +++ /dev/null @@ -1,20 +0,0 @@ -# Motion Baseline Guidelines (Vue Transition First) - -## Baseline principles - -1. Motion clarifies state change, not decoration. -2. Default to short transitions (180ms - 240ms) with easing. -3. Keep animation on container level (route/panel/filter-chip), avoid animating large table row sets. - -## Standard transitions - -- Route change: `route-fade` (`opacity + translateY`) in portal shell. -- Drawer navigation: hover/active transition on sidebar links. -- Filter apply/remove: `TransitionGroup` chip enter/leave motion. -- Data refresh pulse: panel-level pulse when chart/table refresh is running. - -## Accessibility - -- Respect `prefers-reduced-motion: reduce`. -- All key transitions must have non-animated fallback styles. -- Motion must not block interaction or delay data rendering. diff --git a/docs/migration/portal-no-iframe/motion_gsap_escalation_rule.md b/docs/migration/portal-no-iframe/motion_gsap_escalation_rule.md deleted file mode 100644 index 87327a5..0000000 --- a/docs/migration/portal-no-iframe/motion_gsap_escalation_rule.md +++ /dev/null @@ -1,19 +0,0 @@ -# GSAP Escalation Rule - -## Default - -Use Vue native transitions and CSS transitions for portal migration work. - -## GSAP allowed only when all conditions are true - -1. Interaction cannot be expressed with native Vue/CSS transitions without major maintainability cost. -2. Animation is business-critical (e.g., complex timeline playback or synchronized multi-chart storytelling). -3. Reduced-motion fallback is explicitly implemented. -4. Performance impact is measured on target hardware and meets baseline thresholds. -5. A rollback switch exists to disable advanced animation without breaking functionality. - -## Approval checklist - -- Document the exact scenario and why Vue/CSS is insufficient. -- Add test coverage for degraded/non-animated path. -- Confirm bundle-size impact is acceptable for the target route. diff --git a/docs/migration/portal-no-iframe/pagination_migration_batch1.md b/docs/migration/portal-no-iframe/pagination_migration_batch1.md deleted file mode 100644 index f54a9e7..0000000 --- a/docs/migration/portal-no-iframe/pagination_migration_batch1.md +++ /dev/null @@ -1,27 +0,0 @@ -# Shared Pagination Migration Batch 1 - -## Scope - -Migrated pages/components: - -- `wip-detail/components/LotTable.vue` -- `hold-detail/components/LotTable.vue` -- `hold-overview/components/LotTable.vue` -- `hold-history/components/DetailTable.vue` -- `mid-section-defect/components/DetailTable.vue` - -## Change - -- Replaced direct/inline pagination rendering with shared `PaginationControl`. -- Preserved existing page event contracts (`prev-page`, `next-page`). - -## Visual parity checks - -- Pagination visibility still depends on `totalPages > 1`. -- Prev/Next button enablement remains bounded by page range. -- Page info text format remains unchanged on migrated views. - -## Removed duplicated artifacts - -- Removed local Prev/Next markup and boundary logic from `hold-history/components/DetailTable.vue`. -- Consolidated pagination behavior into shared wrapper for this batch. diff --git a/docs/migration/portal-no-iframe/parity_checklist.md b/docs/migration/portal-no-iframe/parity_checklist.md deleted file mode 100644 index 5a11733..0000000 --- a/docs/migration/portal-no-iframe/parity_checklist.md +++ /dev/null @@ -1,46 +0,0 @@ -# Portal No-Iframe Migration Parity Checklist - -This checklist is the execution companion for `portal-no-iframe-navigation` migration. - -## A. Drawer Visibility Parity - -- [ ] Non-admin visible drawers/routes match `baseline_drawer_visibility.json` exactly. -- [ ] Admin visible drawers/routes match `baseline_drawer_visibility.json` exactly. -- [ ] Empty drawers remain hidden. -- [ ] `admin_only` drawer behavior remains unchanged. - -## B. Route and Query Contract Parity - -- [ ] `/wip-overview` preserves `workorder|lotid|package|type|status` URL semantics. -- [ ] `/wip-detail` preserves `workcenter|workorder|lotid|package|type|status` URL semantics. -- [ ] `/hold-detail` preserves required `reason` semantics and fallback behavior. -- [ ] `/resource-history` preserves date/granularity/group/family/resource/flag query semantics. - -## C. Core Workflow Smoke Paths - -- [ ] Legacy rewrite per-page smoke checklist passes (`legacy_rewrite_smoke_checklists.md`). -- [ ] `/` open portal and switch via drawer navigation. -- [ ] `/wip-overview` apply filters and drill down to `/wip-detail`. -- [ ] `/wip-overview` reason drill-down to `/hold-detail`. -- [ ] `/resource-history` execute query and export path. -- [ ] Legacy rewrite pages (`/job-query`, `/excel-query`, `/query-tool`, `/tmtt-defect`) remain reachable and usable. - -## D. API Payload Contract Parity - -- [ ] `/api/wip/overview/summary` required keys present. -- [ ] `/api/wip/overview/matrix` required keys present. -- [ ] `/api/wip/hold-detail/summary` required keys present. -- [ ] `/api/resource/history/summary` required keys present. -- [ ] `/api/resource/history/detail` required keys present. - -## E. Stability and Performance - -- [ ] No unhandled JS runtime errors on critical E2E paths. -- [ ] Route switch latency remains within agreed threshold. -- [ ] Memory footprint does not regress beyond agreed threshold. - -## F. Cutover Decision - -- [ ] All G1~G7 gates are green. -- [ ] Rollback rehearsal result is recent and valid. -- [ ] Cutover owner and rollback owner are explicitly assigned. diff --git a/docs/migration/portal-no-iframe/performance_baseline_comparison.md b/docs/migration/portal-no-iframe/performance_baseline_comparison.md deleted file mode 100644 index 2da7fac..0000000 --- a/docs/migration/portal-no-iframe/performance_baseline_comparison.md +++ /dev/null @@ -1,21 +0,0 @@ -# Performance Baseline Comparison - -Measured via Flask test client (route latency in ms). - -## Key Entry Routes - -| Surface | Avg (ms) | P95 (ms) | -| --- | ---: | ---: | -| Legacy portal `/` | 1.557 | 0.891 | -| SPA shell `/portal-shell` | 0.239 | 0.263 | - -## Shared API Route - -| Route | Legacy Avg (ms) | SPA Avg (ms) | Delta (ms) | -| --- | ---: | ---: | ---: | -| `/api/portal/navigation` | 0.341 | 0.313 | -0.028 | - -## Notes - -- This baseline is synthetic (test client), used for migration regression gate trend tracking. -- Production browser/network RUM should be captured separately during canary rollout. diff --git a/docs/migration/portal-no-iframe/performance_baseline_legacy.json b/docs/migration/portal-no-iframe/performance_baseline_legacy.json deleted file mode 100644 index f4d6550..0000000 --- a/docs/migration/portal-no-iframe/performance_baseline_legacy.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "portal_spa_enabled": false, - "samples_per_route": 15, - "metrics": [ - { - "route": "/", - "samples": 15, - "avg_ms": 1.557, - "p95_ms": 0.891, - "min_ms": 0.536, - "max_ms": 14.997, - "status_codes": [ - 200 - ] - }, - { - "route": "/api/portal/navigation", - "samples": 15, - "avg_ms": 0.341, - "p95_ms": 0.396, - "min_ms": 0.284, - "max_ms": 0.404, - "status_codes": [ - 200 - ] - }, - { - "route": "/wip-overview", - "samples": 15, - "avg_ms": 0.683, - "p95_ms": 0.925, - "min_ms": 0.422, - "max_ms": 2.633, - "status_codes": [ - 200 - ] - }, - { - "route": "/resource", - "samples": 15, - "avg_ms": 0.413, - "p95_ms": 0.506, - "min_ms": 0.337, - "max_ms": 0.699, - "status_codes": [ - 200 - ] - }, - { - "route": "/qc-gate", - "samples": 15, - "avg_ms": 0.422, - "p95_ms": 0.453, - "min_ms": 0.371, - "max_ms": 0.615, - "status_codes": [ - 200 - ] - } - ] -} \ No newline at end of file diff --git a/docs/migration/portal-no-iframe/performance_baseline_spa.json b/docs/migration/portal-no-iframe/performance_baseline_spa.json deleted file mode 100644 index 3d9d40b..0000000 --- a/docs/migration/portal-no-iframe/performance_baseline_spa.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "portal_spa_enabled": true, - "samples_per_route": 15, - "metrics": [ - { - "route": "/portal-shell", - "samples": 15, - "avg_ms": 0.239, - "p95_ms": 0.263, - "min_ms": 0.169, - "max_ms": 0.708, - "status_codes": [ - 200 - ] - }, - { - "route": "/api/portal/navigation", - "samples": 15, - "avg_ms": 0.313, - "p95_ms": 0.412, - "min_ms": 0.257, - "max_ms": 0.437, - "status_codes": [ - 200 - ] - }, - { - "route": "/job-query", - "samples": 15, - "avg_ms": 0.904, - "p95_ms": 0.786, - "min_ms": 0.33, - "max_ms": 7.345, - "status_codes": [ - 200 - ] - }, - { - "route": "/excel-query", - "samples": 15, - "avg_ms": 0.47, - "p95_ms": 0.448, - "min_ms": 0.324, - "max_ms": 1.951, - "status_codes": [ - 403 - ] - }, - { - "route": "/query-tool", - "samples": 15, - "avg_ms": 0.448, - "p95_ms": 0.802, - "min_ms": 0.32, - "max_ms": 0.849, - "status_codes": [ - 403 - ] - }, - { - "route": "/tmtt-defect", - "samples": 15, - "avg_ms": 0.583, - "p95_ms": 0.585, - "min_ms": 0.323, - "max_ms": 3.455, - "status_codes": [ - 200 - ] - } - ] -} \ No newline at end of file diff --git a/docs/migration/portal-no-iframe/rollback_rehearsal_runbook.md b/docs/migration/portal-no-iframe/rollback_rehearsal_runbook.md deleted file mode 100644 index 15444d0..0000000 --- a/docs/migration/portal-no-iframe/rollback_rehearsal_runbook.md +++ /dev/null @@ -1,51 +0,0 @@ -# Portal No-Iframe Migration Rollback Rehearsal Runbook - -## Objective - -Validate that navigation can be restored to pre-cutover stable behavior within target SLO. - -- Target recovery SLO: <= 15 minutes - -## Trigger Conditions - -Execute rollback when any of the following occur after cutover: - -- P0 route unavailable or broken workflow. -- Drawer visibility parity mismatch. -- Critical API payload contract mismatch causing page failure. -- Severe runtime JS errors on critical user paths. - -## Preconditions - -- Feature-flag/env toggle path for shell cutover is in place. -- Latest baseline snapshots are available under `docs/migration/portal-no-iframe/`. -- On-call owner and rollback owner are assigned. - -## Rehearsal Steps - -1. Enable new navigation mode in staging/canary. -2. Execute parity checklist (`parity_checklist.md`) on critical routes. -3. Force simulated rollback trigger (toggle off new mode). -4. Re-run critical smoke checks: - - portal load - - drawer visibility - - wip overview/detail flow - - resource history query path -5. Record elapsed recovery time and failures. - -## Verification Criteria - -- Toggle change takes effect without manual code rollback. -- Critical routes recover to expected behavior. -- Recovery time is within SLO. -- No residual hard-failure state remains. - -## Post-Rehearsal Record - -- Date: -- Environment: -- Operator: -- Trigger reason: -- Recovery duration: -- Issues found: -- Follow-up actions: diff --git a/docs/migration/portal-no-iframe/rollback_strategy_shell_and_wrappers.md b/docs/migration/portal-no-iframe/rollback_strategy_shell_and_wrappers.md deleted file mode 100644 index 616c8f4..0000000 --- a/docs/migration/portal-no-iframe/rollback_strategy_shell_and_wrappers.md +++ /dev/null @@ -1,28 +0,0 @@ -# Rollback Strategy (Shell / Router / Wrapper) - -## Scope - -- Shell entry failures (`/portal-shell`, route guards, navigation API) -- Legacy route integration failures (`job-query`, `excel-query`, `query-tool`, `tmtt-defect`) - -## Immediate actions - -1. Flip `PORTAL_SPA_ENABLED=false`. -2. Confirm `/` portal route responds and sidebar route links render. -3. Verify core routes (`/wip-overview`, `/resource`, `/qc-gate`) return 2xx. -4. Verify legacy routes (`/job-query`, `/excel-query`, `/query-tool`, `/tmtt-defect`) return 2xx. - -## Validation checkpoints (<=15 minutes) - -- `GET /api/portal/navigation` returns deterministic drawer/page list. -- No spike in 5xx for portal and legacy routes. -- Smoke flows for one P0 page and one legacy page pass. - -## Legacy route fallback - -- If a legacy route fails hard, temporarily hide it from drawer config (`page_status.json`) and announce maintenance route. - -## Post-rollback follow-up - -- Capture failed gate(s), timestamp, and impacted routes. -- Generate incident summary with fix candidate and rehearsal re-entry criteria. diff --git a/docs/migration/portal-no-iframe/rollout_canary_plan.md b/docs/migration/portal-no-iframe/rollout_canary_plan.md deleted file mode 100644 index 6dce6a2..0000000 --- a/docs/migration/portal-no-iframe/rollout_canary_plan.md +++ /dev/null @@ -1,27 +0,0 @@ -# Phased Rollout Plan (Canary) - -## Feature switch - -- Primary switch: `PORTAL_SPA_ENABLED` -- Canary enabled users/groups are routed to `/portal-shell`; others remain on `/` route-based portal. - -## Phases - -1. Phase A (Internal): dev/admin users only, 1 day. -2. Phase B (Canary): 10-20% target users, 2-3 days. -3. Phase C (Broad): 50% users if gates are green for 24h. -4. Phase D (Full): 100% after cutover gates pass. - -## Success thresholds - -- Route availability (P0): >= 99.9% 2xx/3xx. -- Client runtime error rate on critical paths: 0 unhandled exceptions. -- Drawer parity drift: 0 mismatches (admin/non-admin route sets). -- Wrapper launch success (`launch` telemetry): >= 99%. - -## Error thresholds (rollback trigger) - -- P0 route availability < 99.5% in any 30-minute window. -- Any critical workflow smoke failure. -- Drawer parity mismatch count > 0 after deployment. -- Wrapper telemetry error rate >= 2% sustained 30 minutes. diff --git a/docs/migration/portal-no-iframe/shared_component_contracts.md b/docs/migration/portal-no-iframe/shared_component_contracts.md deleted file mode 100644 index bbf23bc..0000000 --- a/docs/migration/portal-no-iframe/shared_component_contracts.md +++ /dev/null @@ -1,50 +0,0 @@ -# Shared UI Component Contracts - -## `PaginationControl` - -File: `frontend/src/shared-ui/components/PaginationControl.vue` - -- Props: - - `page?: number` (legacy compatibility) - - `modelValue?: number` - - `totalPages: number` - - `infoText?: string` - - `visible?: boolean` -- Emits: - - `update:modelValue(number)` - - `change(number)` - - `prev(number)` - - `next(number)` -- Compatibility: - - Supports legacy usage (`:page`, `@prev`, `@next`) for migration-safe replacement. - -## `SectionCard` - -File: `frontend/src/shared-ui/components/SectionCard.vue` - -- Slots: - - `header` - - default body - - `footer` -- Purpose: - - Normalize page section container structure and spacing. - -## `FilterToolbar` - -File: `frontend/src/shared-ui/components/FilterToolbar.vue` - -- Slots: - - default filter controls - - `actions` -- Purpose: - - Shared filter layout shell with consistent spacing and action alignment. - -## `StatusBadge` - -File: `frontend/src/shared-ui/components/StatusBadge.vue` - -- Props: - - `tone: neutral | success | warning | danger` - - `text: string` -- Purpose: - - Replace repeated local badge/status color snippets. diff --git a/docs/migration/portal-no-iframe/shared_composables_contracts.md b/docs/migration/portal-no-iframe/shared_composables_contracts.md deleted file mode 100644 index afa16d1..0000000 --- a/docs/migration/portal-no-iframe/shared_composables_contracts.md +++ /dev/null @@ -1,31 +0,0 @@ -# Shared Composables Contracts - -## `useAutoRefresh` - -File: `frontend/src/shared-composables/useAutoRefresh.js` - -- Current behavior wraps existing `wip-shared` implementation. -- Purpose: single import path for all page modules before deeper implementation merge. - -## `useAutocomplete` - -File: `frontend/src/shared-composables/useAutocomplete.js` - -- Current behavior wraps existing `wip-shared` implementation. -- Purpose: single import path to normalize field/autocomplete interactions. - -## `usePaginationState` - -File: `frontend/src/shared-composables/usePaginationState.js` - -- State: `page`, `perPage`, `total`, `totalPages` -- Derived: `hasPrev`, `hasNext` -- Methods: `setFromPayload`, `reset` - -## `useQueryState` - -File: `frontend/src/shared-composables/useQueryState.js` - -- `readQueryState(keys)` -- `writeQueryState(nextState)` -- Purpose: unify URL query read/write semantics across pages. diff --git a/docs/migration/portal-no-iframe/tailwind_design_tokens.md b/docs/migration/portal-no-iframe/tailwind_design_tokens.md deleted file mode 100644 index 23ebf58..0000000 --- a/docs/migration/portal-no-iframe/tailwind_design_tokens.md +++ /dev/null @@ -1,40 +0,0 @@ -# Tailwind Design Tokens Mapping - -## Goal - -Map existing portal visual language into a stable token set for phased migration. - -## Color tokens - -- `brand.500` / `brand.600` / `brand.700`: primary brand actions and active navigation states. -- `accent.500`: gradient accent endpoint for shell headers. -- `surface.app` / `surface.card` / `surface.muted`: app background, card surfaces, muted blocks. -- `stroke.soft` / `stroke.panel`: border hierarchy. -- `state.success` / `state.warning` / `state.danger` / `state.neutral`: status dots and health states. - -## Typography tokens - -- `fontFamily.sans`: `Noto Sans TC`, `Microsoft JhengHei`, system fallback. - -## Layout tokens - -- `spacing.shell`: outer shell padding. -- `spacing.panel`: panel interior spacing. -- `spacing.nav`: sidebar item horizontal spacing. -- `spacing.block`: vertical rhythm baseline. - -## Radius and elevation tokens - -- `borderRadius.shell`: shell and main card radius. -- `borderRadius.card`: smaller control/card radius. -- `boxShadow.soft`: light containers (sidebar). -- `boxShadow.panel`: content panel container. -- `boxShadow.shell`: header gradient card emphasis. - -## Z-index token - -- `zIndex.popup`: status popup / overlay layer. - -## Migration note - -Tokens are intentionally aligned with current portal values to minimize visual drift during iframe decommission. diff --git a/docs/migration/portal-no-iframe/tailwind_migration_guide.md b/docs/migration/portal-no-iframe/tailwind_migration_guide.md deleted file mode 100644 index 2bb9b03..0000000 --- a/docs/migration/portal-no-iframe/tailwind_migration_guide.md +++ /dev/null @@ -1,33 +0,0 @@ -# Tailwind Migration Guide (Portal No-iframe) - -## Purpose - -Move distributed page CSS toward a token-driven Tailwind system without breaking existing portal behavior. - -## Step-by-step - -1. Keep existing route/page behavior unchanged. -2. Replace repeated layout wrappers with Tailwind utilities first (`grid`, `flex`, spacing, radius, shadows). -3. Replace repeated visual primitives with shared component classes from `@layer components`. -4. Move hard-coded colors/spacing to tokens in `tailwind.config.js` and `tailwind.css`. -5. Remove obsolete page-local CSS only after visual parity is verified. - -## Recommended migration order - -1. Shell and shared navigation blocks -2. Filter bars and KPI card rows -3. Shared table containers and pagination controls -4. Page-specific edge states and empty/error banners - -## Parity checks per batch - -- Drawer visibility and route links stay unchanged. -- Existing URL/query semantics remain compatible. -- No new runtime style conflicts in non-admin/admin views. - -## Do / Don’t - -- Do: prefer composable utility classes and shared Vue components. -- Do: keep style changes scoped to one route family per batch. -- Don’t: introduce new long inline `