Feature #1422
是由 陳國瑋 於 28 天 前更新
## 背景
Branch Admin 的 `/dashboard` 目前是空白頁。既有 `DashboardStatsCard` 只有硬編碼假資料且未掛載;現有 `GET /api/connector/dashboard` 只能提供 Connector 總數、Available、Charging、Faulted、公用與私人數量,尚不足以支援案場營運判斷。
本需求建立所有案場共用的 Backend Admin 營運 Dashboard;A17 僅為第一個驗證與導入案場。API、WebSocket、UI、freshness policy 與資料模型不得硬編碼 A17,並須以 `buildingId` 明確隔離案場資料。
> Mockup 內所有數字均為假資料。A17 production baseline 必須在實作前以 read-only query 驗證,不得將 mock 數字作為驗收基準。
## 多案場適用原則
- Dashboard 功能適用所有案場,A17 僅作為首個 rollout/baseline 驗證站點。
- REST、WebSocket ticket、URL 與 event envelope 明確使用 `buildingId`。
- Backend 必須驗證使用者對 building 的存取權;切換 building 不得混用舊案場 snapshot。
- Freshness/stale cutoff 由 Backend 依資料來源統一管理,不由 FE 或 A17-specific code 決定。
- A17 Phase 0 的數據只用於驗證通用方案的公式、效能及預設值,不能成為其他案場的固定規則。
## 產品目標
讓 Site Admin、Operations、Finance 與 Engineer 在 10 秒內回答:
- 案場現在是否正常?
- 哪些 Charge Point 離線、哪些 Connector 故障?
- 目前充電工作階段與總負載是否接近契約容量?
- 輪充/離峰隊列是否阻塞或等待過久?
- 今日使用量與最近一期結算流程是否有待處理項目?
- Dashboard 資料是否仍然新鮮、可被信任?
Dashboard V1 以唯讀總覽與 deep link 為主,不在首頁直接執行 Remote Start/Stop、Reset、Modbus 或 Engineer command。
## 完整需求文件
建立 Issue 後將附上:
- `a17-ems-dashboard-requirements.pdf`:17 頁完整需求說明書
- Repository source:`documents/dashboard-mockup/a17-dashboard-requirements.md`
- UI mockup:`documents/dashboard-mockup/a17-operations-dashboard.html`
## V1 Scope
- Needs Attention severity-first 告警列與 deep link
- Charge Point OCPP connection 與 runtime 摘要
- Connector 完整狀態統計與即時狀態 grid
- Active sessions、目前功率、近 24 小時負載
- Charge Group total/occupied/reserved/available slots
- Queue waiting/blocked/最久等待時間摘要(唯讀資訊)
- 今日用電與近 30 日 kWh/sessions 趨勢
- 結算流程區塊沿用 attachment #1110 四步驟面板;假數字改接正式 API,資料期間由 Backend 依最近結算資料回傳(BIL-DEC-001/002,詳見 #1460)
- Loading、Empty、Error、Stale、Partial、403 等 UI states
- Desktop/Tablet/Mobile responsive
- SS3A Dashboard function/API 權限
## V1 Scope Boundary
- Dashboard 是唯讀營運資訊頁,只查詢、彙整及呈現既有系統狀態。
- Queue 顯示既有 source、status、priority、statusReason、waitingSince/waiting duration;`BLOCKED` 沿用既有狀態呈現。
- V1 不新增 Queue SLA、等待逾時判定、門檻 override、Queue 設定頁或 Rotation scheduler-health 規則。
- Connector preview 固定 Cards,完整清單 Drawer 採單一 responsive list;不提供 Grid/Table toggle 或顯示偏好保存。
- Dashboard 開發不得改變 queue lifecycle、priority、slot allocation、rotation dispatch、OCPP command 或任何充電作業邏輯。
- 若未來確有 SLA/scheduler monitoring 需求,須另案確認;本次不先建立實作 ticket。
## 開發工作拆分
### Backend / API
- [ ] 新增 typed `GET /api/dashboard/overview`
- [ ] 建立 `DashboardController`、`DashboardService`、alerts 與各區塊 DTO
- [ ] 聚合 CP connection/runtime、Connector 狀態、active transaction
- [ ] 建立 latest power query、W/kW normalization 與 stale cutoff
- [ ] 依既有 SlotCalculator 語意產生 Charge Group capacity summary
- [ ] 統計既有 queue waiting/blocked/statusReason/waiting duration;不得新增 Queue SLA、timeout 或狀態轉換規則
- [ ] 依 #1461 USG-DEC-001/002/003/004/005 USG-DEC-001/002/003/004 建立固定最近 30 個案場日曆日(含今天)的 kWh/Sessions usage trend;有效充電量只讀取符合條件的 COMPLETED energy_consumed,Sessions 只計算 COMPLETED 且正電量交易,兩者依 building timezone 的交易開始日歸屬且跨日不拆分;異常 Completed 回傳排除筆數並標示 PARTIAL;不提供 7/90 日、自訂範圍或時間使用率 日或自訂範圍
- [ ] 依 #1460 BIL-DEC-001/002 建立四步驟結算流程的 read-only aggregation/DTO,並回傳 periodYear/periodMonth/timezone;不得執行帳務 mutation 或改變既有月結排程
- [ ] 支援 COMPLETE/PARTIAL/STALE 與 sourceStatuses
- [ ] 新增 SS3A function/API mapping
- [ ] 補 OpenAPI `@Schema`、method/DTO 欄位註解與測試
- [ ] 在 A17 資料量下完成 EXPLAIN 與 P95 驗證
### Frontend
- [ ] 重新實作 `react/branch/app/(dashboard)/dashboard/page.tsx`
- [ ] OpenAPI refresh 與 React Query overview hook
- [ ] Header、AttentionStrip、KPI、LiveLoad、ChargeGroup、ConnectorGrid
- [ ] Connector preview 固定 Cards;完整清單 Drawer 單一 responsive list(不實作 Grid/Table toggle)
- [ ] Connector detail drawer 與既有管理頁/Engineer Tools deep link
- [ ] 依 #1461 實作固定 30 日 UsageTrend(kWh/Sessions,依案場 timezone,不提供 range selector),以及 attachment #1110 四步驟結算流程面板;月份只格式化 Backend 回傳期間,四列維持純資訊,footer 提供「查看帳單」與「查看請款/發票」既有 route 導覽
- [ ] Loading/Empty/Error/Stale/Partial/Unauthorized states
- [ ] Healthy/Critical/Partial/Stale/Empty/Large 六組 fixture
- [ ] 四組 responsive breakpoint 與 keyboard/accessibility 驗證
- [ ] Production API error 不得 fallback 到 fixture
### Database / Performance
- [ ] 取得 A17 table row count、狀態分布、MeterValue 24h volume 與 query plan
- [ ] 優先採 read-only aggregate,不先建立 Dashboard snapshot table
- [ ] 只有在 A17 EXPLAIN 證明必要時,才提出普通 index
- [ ] 不新增 UNIQUE/FOREIGN KEY/CHECK/cascade constraint
### QA / Release
- [ ] Backend repository/service/security/contract tests
- [ ] FE fixture、RWD、keyboard、unknown enum、null/0/large value tests
- [ ] A17 staging E2E:offline、faulted、active transaction、stale meter、blocked queue、billing、partial data、403
- [ ] 上線採 controlled release,觀察 24 小時 error rate、partial rate、query latency
## 核心狀態規則
1. `ChargePoint.ocppConnectionStatus`、Charge Point runtime、Connector runtime、rotation queue 必須分層顯示,不得合併成單一在線/離線。
2. Heartbeat/BootNotification 只能證明連線存活,不能把 FAULTED/CHARGING 覆寫為 AVAILABLE。
3. Connector runtime primary owner 是 StatusNotification。
4. `currentTransactionId` 或 ACTIVE transaction 存在時,離線告警需標記可能仍在離線充電/待 reconciliation。
5. 即時數值不存在時回 `null`,不可用 0 表示未知。
6. Status code 供 FE 邏輯使用;中文 label 僅供顯示,未知 code 不得 fallback 成 AVAILABLE。
## Acceptance Criteria
- [ ] 使用者 10 秒內可指出離線、故障、隊列阻塞或帳務異常
- [ ] 所有告警與關鍵數字都有可用 deep link
- [ ] Overview API 在 A17 資料量下 P95 < 1.5 秒
- [ ] Header 顯示 `generatedAt`;各資料源有 `updatedAt` 與 freshness
- [ ] 任一子查詢失敗時,其餘區塊仍顯示並標記 PARTIAL
- [ ] Stale 資料不可被顯示為正常,也不可納入需要即時性的總功率
- [ ] 未授權使用者直接呼叫 API 得到 403
- [ ] 狀態不可只靠顏色;keyboard focus、status message 與文字對比符合 WCAG 2.2 AA 基本要求
- [ ] 390/768/1024/1440 px 不出現頁面級水平捲軸
- [ ] Production build 不包含 API error → fixture fallback
## A17 Phase 0 Gate
實作前必須用 read-only query 確認:
- CP ONLINE/OFFLINE/UNKNOWN 與 runtime 分布
- Connector status/area/type 分布
- Active transaction 數與最長持續時間
- 各 Charge Group contract/allocated/reserved/queue
- MeterValue 24 小時筆數、峰值與 latest lag
- 近 30 日 transaction/kWh/日分布
- 最近結算資料期間的 Billing/Invoice 狀態分布
- 各 aggregate query 的 EXPLAIN
## E2E Test Impact
**Classification:Add**
此需求新增 user-visible Dashboard、typed API、SS3A permission 與多來源營運聚合,需在實作階段新增長期 E2E Catalog cases:
- P0 / Standard、Major、A17 release:Dashboard overview 權限、PARTIAL、stale safety
- P1 / Standard、Major、A17 release:OCPP offline、Connector faulted、active transaction、queue blocked、billing block、responsive
- P2 / Major、A17 release:large data、unknown enum、performance baseline
實作 ticket 的階段 2 必須依 `maintain-ems-e2e-catalog` skill 確認正式 Case ID 與 release pack。
## Definition of Done
- [ ] Product 確認 KPI 字典、範圍與待決策事項
- [ ] A17 baseline 完成且未推翻公式/效能方案
- [ ] Backend API、OpenAPI、SS3A mapping 與測試完成
- [ ] FE 各區塊、states、RWD、accessibility、deep link 完成
- [ ] A17 staging E2E 與 P95 通過
- [ ] E2E Catalog 與 `ai/02-backend-services.md`、`ai/03-database.md`、`ai/04-frontend.md` 更新
- [ ] 發布後完成 24 小時監看
## 待決策
- Dashboard V1 是否固定單站,或 API 先支援 `buildingId`
- 契約容量利用率分母如何依 A17 電力拓撲避免重複計算
- Queue waiting 僅顯示持續時間,V1 不設定 warning/timeout 門檻(已確認)
- 30 日充電用量固定最近 30 個案場日曆日(含今天),保留 kWh/Sessions 切換,不提供 7/90 日或自訂範圍(USG-DEC-001,已確認;詳見 #1461)
- 有效充電量只加總 COMPLETED 的既有最終 energy_consumed;ACTIVE 不估算,異常 Completed 排除並標示 PARTIAL(USG-DEC-002,已確認)
- Usage 每日 kWh/Sessions 依 building timezone 的交易開始日歸屬,跨日不拆 MeterValue(USG-DEC-003,已確認)
- 充電 Sessions 只計算 COMPLETED 且 energy_consumed > 0 的交易;0 Wh 與 ACTIVE 不計入(USG-DEC-004,已確認)
- V1 移除時間使用率及其 Backend denominator/threshold;替代摘要另行確認(USG-DEC-005,已確認)
- 首頁帳務區塊沿用 attachment #1110 四步驟「結算流程」;不改成 Billing Summary(BIL-DEC-001,已確認)
- 結算流程期間由 Backend 依最近結算資料回傳;Frontend 不依日曆月份推算(BIL-DEC-002,已確認)
- 結算四列維持純資訊;footer 分別導向既有 /bill/list 與 /invoice/list,不新增頁面或 drill-down API(BIL-DEC-003,已確認)
- Dashboard function 授權哪些既有 role
- V1 refresh 60 秒是否足夠
返回