Bug #1403
是由 陳國瑋 於 約 21 小時 前更新
## 問題
Ken 環境對 背景:Ken 環境已部署 #1398 Backend/HQ。2026-08-02 15:54 後,LIFF 對 CP001-001 執行 `START_CHARGING` 時,Branch 已建立 operation、送出 `RemoteStartTransaction`,但 HQ 實際回給 LIFF `409`,導致 FE 正確顯示「操作未成功」。FE 對 HTTP 200/202 與 WebSocket operationResult 的處理已符合 contract,不需修改。 按「開始充電」後彈出「操作未成功」。
## 已確認證據
查 log 結果:
- 2026-08-02 15:54:48,HQ access log 顯示 HQ 已收到 `POST /api/connector/commands` 回 `409`。 /api/connector/commands`。
- Branch DB 已 dispatch `START_CHARGING`,建立 operation `539` 已建立,CP 後續回 `Accepted`。 `logId=539`。
- Ken DB transaction isolation 為 `REPEATABLE-READ`。 CP 已收到 `RemoteStartTransaction` 並回 `Accepted`。
- `ConnectorCommandService` 先以 `hasActive()` 建立 transaction snapshot;`RemoteOperationPersistenceService` 再以 `REQUIRES_NEW` commit operation;outer transaction 隨後重新查 `getActiveOperation()` 時看不到新 row,誤丟 `START_OPERATION_MISSING`。 CP 隨後送出 `StatusNotification: PREPARING`。
- STOP Branch DB 顯示 CP001-001 進入 `PREPARING`,operation 狀態為 `ACCEPTED`,尚未收到 `StartTransaction` 是因為 CP 還在等待車端電流,不是 command 存在相同重新查詢模式,也需一併修正。 失敗。
## 修正方向
保留 dispatch 前 `REQUIRES_NEW` 持久化。由 charging orchestration 直接回傳本次建立的 operation reference,`ConnectorCommandService` 使用該 reference 建立 問題:FE 目前疑似仍用舊 response contract 判斷成功,例如只認 `isSuccess === true` 或未將 HTTP `202 Accepted` response,不再重新查詢 connector 最新 active operation。 視為成功,導致 backend 已成功 accepted 的非同步 command 被顯示成「操作未成功」。
## 驗收
- START/STOP dispatch 成功後皆回 `202`,包含正確 `operationId`、`operationStatus` 與 `activeOperation`。 FE 要做:
- 不受 MySQL `REPEATABLE-READ` snapshot 影響。 1. `POST /api/connector/commands` 回 `200 OK` 或 `202 Accepted` 都應視為 command request 成功。
- 真正 dispatch/設備拒絕仍依既有錯誤 contract 回應。 2. 成功 body 使用 `ConnectorCommandResponse`,欄位包含 `action`、`operationId`、`operationStatus`、`enableOffPeak`、`driverState`、`activeOperation`。
- FE 無須修改。 3. `START_CHARGING` / `STOP_CHARGING` 回 `202 Accepted` 時,不要等 `StartTransaction` / `StopTransaction` 才算 API 成功;畫面應立即依 response 或後續 WebSocket 的 `driverState` 更新,例如顯示 `PREPARING / 準備中`。
4. 只有 HTTP `403` / `409` 或 request exception 才顯示失敗 modal;`403` / `409` body 使用 `ConnectorCommandErrorResponse.message` 與最新 `driverState` 修正畫面。
返回