專案

一般

配置概況

Feature #1397 » redmine-1397-liff-manual-e2e-test-plan-zh-TW.md

2026-07-31 LIFF 人工 E2E 測試計畫:Ken 環境、公私樁切換、離峰/queue/operation lifecycle、證據與還原步驟 - 陳國瑋, 2026-07-31 10:11

 

Redmine #1397/#1398/#1399 LIFF 人工 E2E 測試計畫

版本:2026-07-31 初版
執行狀態:等待 #1399 Frontend 完成並部署後執行
測試環境:Ken 的 Branch/Charge Point、docker1 HQ staging、#1399 LIFF 測試版
測試起點:所有產品操作都必須從 LIFF Connector 列表或詳細頁開始

1. 目的與通過標準

本計畫驗證 #1397 定義的新版 driverState、semantic actions、RemoteStart/RemoteStop
operation lifecycle、WebSocket initial snapshot,以及私樁長期離峰與排隊行為。API、DB
與 log 只用來佐證 LIFF 操作的真實結果,不可取代 LIFF 畫面與實體充電行為。

整輪測試通過必須同時符合:

  1. 適用的 P0 案例全部通過;Skip 不是 Pass。
  2. LIFF 顯示的狀態、按鈕、modal 與 Backend 真實 operation/transaction 一致。
  3. 實際開始與停止案例必須看到繼電器/電流變化、OCPP transaction 與 DB 收斂。
  4. 公樁與私樁都完成測試;不能只用 API response 推定另一種樁型也正確。
  5. 每個案例都留下時間、Connector ID、畫面、WebSocket/API、Branch/CP log 與 DB 證據。
  6. 測試完成後,兩支 Connector 必須還原成測試前的公私樁、tariff、Charge Group 與離峰設定。

2. Ken 環境基線

2026-07-31 查核到的初始資料如下。正式執行前仍要重查一次,若不同,以當天快照為準。

項目 CP001-001 CP001-002
廠牌 CLOUDLINK CLOUDLINK
Branch status AVAILABLE AVAILABLE
Branch area public public
CP area public public
Charge Group NULL NULL
Connector tariff 未綁定 未綁定
enableOffPeak NULL NULL
active transaction
LIFF 測試使用者關聯 已關聯 已關聯

環境路徑:

層級 環境
LIFF #1399 完成後由 Ryan 提供實際測試 URL/LIFF channel;執行紀錄必須填入版本或 commit
HQ docker1 staging,ems-hq-staging-api,對外由 hq-api.sylksoft.com 提供 API/WebSocket
Branch Ken 主機,ems-branch-api,host port 18081/OCPP 18082
Charge Point Ken 主機,ems-cp-api,實體 Connector 為 CP001-001CP001-002
Branch DB Ken 主機 MySQL container 的 ems_branch

3. 人員、帳號與設備

3.1 必要角色

  • Tester A:Ken 的 LINE/LIFF 測試帳號;必須可進入測試 building,並對 CP001-002
    對應到 Branch user U2601140001。該 Branch user 已有有效 IdTag。
  • Tester B:第二個 LINE/LIFF 帳號,只用於「指定使用者 operationResult」與公/私樁停止授權案例。
    執行前必須在 HQ 建立相同 building binding,Branch 建立另一位有效 IdTag user,並將其關聯到
    私樁 CP001-002。不得共用 Tester A 的 LINE identity。
  • BE observer:觀察 HQ/Branch/CP log、DB 與實體設備;不得代替 Tester 在 API 工具直接發動產品操作。
  • FE observer:確認 LIFF action mapping、modal、WebSocket reconnect 與 operationId 去重。

若 Tester B 尚未準備完成,標記 M1397-014、M1397-015 為 Blocked,不得填 Pass。

3.2 實體設備

  • 一台可正常 AC 充電的測試車,或等效且能產生真實 StartTransaction、MeterValues、StopTransaction 的負載。
  • CP001-001CP001-002 的槍線均可使用。
  • 可觀察 Relay/電流的 CP log 或實體量測方式。
  • 兩支手機;測 targeted result 時兩個 LIFF session 要同時停留在同一 Connector 詳細頁。

4. 測試前安全檢查

先在 Ken 主機進入 MySQL:

sudo docker exec -it mysql mysql -uroot -p ems_branch

密碼只從既有安全設定取得,不可寫入測試報告、截圖或 Redmine。

4.1 留存基線快照

SELECT id, connector_type, status, area, enable_off_peak,
       off_peak_enabled_by_user_id, off_peak_suppressed_window_start,
       off_peak_suppressed_window_end, off_peak_suppression_reason,
       charge_group, current_transaction_id
FROM e_connectors
WHERE id IN ('CP001-001', 'CP001-002');

SELECT id, status, area, current_transaction_id, relay_status
FROM cp_connectors
WHERE id IN ('CP001-001', 'CP001-002');

SELECT id, tariff_id
FROM e_connector_tariff
WHERE id IN ('CP001-001', 'CP001-002');

SELECT connector_id, user_id
FROM e_connector_user
WHERE connector_id IN ('CP001-001', 'CP001-002')
ORDER BY connector_id, user_id;

將查詢結果貼入本次 Test Run report。不要只依本文件的 2026-07-31 基線還原,因為正式測試日的資料可能已改變。

4.2 確認沒有進行中的工作

SELECT transaction_id, connector_id, id_tag, status, start_timestamp
FROM e_transactions
WHERE connector_id IN ('CP001-001', 'CP001-002')
  AND status = 'ACTIVE';

SELECT id, operation_type, source, connector_id, requested_by_user_id,
       operation_status, deadline_at, grace_until
FROM e_remote_transaction_log
WHERE connector_id IN ('CP001-001', 'CP001-002')
  AND operation_status IN ('SENT', 'ACCEPTED');

SELECT id, connector_id, source, requested_by_user_id, charge_group,
       priority, charge_status, status_reason
FROM e_connector_priority
WHERE connector_id IN ('CP001-001', 'CP001-002');

通過條件:ACTIVE transaction、SENT/ACCEPTED operation 與既有 queue 都為空。
若不是空,不得直接刪除 operation 或 transaction;先查明是否仍在供電並正常停止/收斂。

4.3 確認服務與時間

date
sudo docker ps --format '{{.Names}} {{.Status}} {{.Ports}}'
curl -fsS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:18081/api-docs

HQ、Branch、CP、手機時間差不得超過一分鐘,否則 operation deadline 與 log 對帳會混亂。

5. 建立專用測試資料

以下 fixture 讓兩支實體樁切換出三種模式:

模式 CP001-001 CP001-002 用途
PUB public public 公樁 LIFF、Start/Stop、無離峰 switch
PRI-0 public,同 group private,同 group group 總 slot=1,扣除一支 public 後 private slot=0;測 MANUAL/OFF_PEAK QUEUED
PRI-1 public,同 group private,同 group group 總 slot=2,扣除一支 public 後 private slot=1;測私樁實際 Start/Stop/離峰充電

5.1 建立 test-only Charge Group 與 tariffs

只在 4.2 全部為空後執行:

INSERT INTO e_charge_group
    (id, contract_capacity, allocated_power, rotation_cycle_active, reserved_slots)
VALUES
    ('CG_E2E_1397', 7.00, 7.00, 0, 0)
ON DUPLICATE KEY UPDATE
    contract_capacity = VALUES(contract_capacity),
    allocated_power = VALUES(allocated_power),
    rotation_cycle_active = 0,
    reserved_slots = 0;

INSERT INTO e_tariff_table
    (id, mode, name, connector_area, start_date, end_date,
     currency, enabled, version_no, is_template, editable)
VALUES
    ('E2E1397WAIT', 'RLT', 'E2E #1397 非當前離峰', 'private',
     '2026-01-01', '2099-12-31', 'TWD', 1, 1, 0, 1),
    ('E2E1397ACTIVE', 'RLT', 'E2E #1397 全日離峰', 'private',
     '2026-01-01', '2099-12-31', 'TWD', 1, 1, 0, 1)
ON DUPLICATE KEY UPDATE
    enabled = 1,
    connector_area = 'private',
    start_date = '2026-01-01',
    end_date = '2099-12-31';

DELETE FROM e_tariff_time_slot
WHERE tariff_id IN ('E2E1397WAIT', 'E2E1397ACTIVE');

INSERT INTO e_tariff_time_slot
    (id, tariff_id, season_type, day_type, slot_type,
     start_time, end_time, unit_price, sequence_no, cross_day,
     create_time, update_time)
VALUES
    ('E2E1397WAIT01', 'E2E1397WAIT', 'ALL', 'ALL', 'OFF_PEAK',
     '00:00:00', '00:01:00', 1.0000, 1, 0, NOW(), NOW()),
    ('E2E1397ACTIVE01', 'E2E1397ACTIVE', 'ALL', 'ALL', 'OFF_PEAK',
     '00:00:00', '23:59:59', 1.0000, 1, 0, NOW(), NOW());

E2E1397WAIT 用來穩定製造「長期離峰已開啟、目前不在離峰 window」;除非測試剛好在
00:00~00:01 執行。E2E1397ACTIVE 用來讓任何測試時間都處於離峰 window。

5.2 切換 PUB 模式

UPDATE e_connectors
SET area = 'public', enable_off_peak = NULL,
    off_peak_enabled_by_user_id = NULL,
    off_peak_suppressed_window_start = NULL,
    off_peak_suppressed_window_end = NULL,
    off_peak_suppression_reason = NULL,
    charge_group = NULL
WHERE id IN ('CP001-001', 'CP001-002');

UPDATE cp_connectors
SET area = 'public'
WHERE id IN ('CP001-001', 'CP001-002');

DELETE FROM e_connector_priority
WHERE connector_id IN ('CP001-001', 'CP001-002');

變更後關閉舊詳細頁,再由 LIFF 列表重新進入,讓 WebSocket initial snapshot 讀取最新資料。

5.3 切換 PRI-0 模式(private slot=0)

UPDATE e_charge_group
SET contract_capacity = 7.00, allocated_power = 7.00,
    reserved_slots = 0, rotation_cycle_active = 0
WHERE id = 'CG_E2E_1397';

UPDATE e_connectors
SET area = 'public', enable_off_peak = NULL, charge_group = 'CG_E2E_1397'
WHERE id = 'CP001-001';

UPDATE e_connectors
SET area = 'private', enable_off_peak = 0,
    off_peak_enabled_by_user_id = NULL,
    off_peak_suppressed_window_start = NULL,
    off_peak_suppressed_window_end = NULL,
    off_peak_suppression_reason = NULL,
    charge_group = 'CG_E2E_1397'
WHERE id = 'CP001-002';

UPDATE cp_connectors SET area = 'public'  WHERE id = 'CP001-001';
UPDATE cp_connectors SET area = 'private' WHERE id = 'CP001-002';

INSERT INTO e_connector_tariff (id, tariff_id)
VALUES ('CP001-002', 'E2E1397WAIT')
ON DUPLICATE KEY UPDATE tariff_id = VALUES(tariff_id);

DELETE FROM e_connector_priority
WHERE connector_id IN ('CP001-001', 'CP001-002');

此時 floor(7/7)=1,再扣除同 group 的一支 public connector,private 可用 slot 為 0。

5.4 切換 PRI-1 模式(private slot=1)

UPDATE e_charge_group
SET contract_capacity = 14.00, allocated_power = 7.00,
    reserved_slots = 0, rotation_cycle_active = 0
WHERE id = 'CG_E2E_1397';

此時 floor(14/7)=2,扣除一支 public connector 後,剩一個 private slot。

5.5 切換 private tariff

不在離峰 window:

UPDATE e_connector_tariff
SET tariff_id = 'E2E1397WAIT'
WHERE id = 'CP001-002';

強制處於離峰 window:

UPDATE e_connector_tariff
SET tariff_id = 'E2E1397ACTIVE'
WHERE id = 'CP001-002';

每次切換 tariff 後,關閉 Connector 詳細頁,再由 LIFF 列表重新進入。

6. 執行證據規則

每個案例至少記錄:

  • LIFF 操作開始/結束時間與 Tester A/B。
  • Connector ID、當時模式 PUB/PRI-0/PRI-1、車輛是否插槍。
  • 操作前畫面、等待狀態、結果 modal、操作後畫面。
  • command HTTP status/body;涉及非同步操作時記錄 operationId
  • WebSocket initial snapshot 與後續 UPDATED/operationResult 的關鍵欄位。
  • e_remote_transaction_loge_connector_prioritye_transactions 的對應資料。
  • 實際 Relay/電流與 OCPP RemoteStart/StartTransaction/RemoteStop/StopTransaction。

結果只能填 PASSFAILBLOCKEDNOT APPLICABLE。不得把沒有執行寫成 PASS。

7. 公樁案例(PUB)

M1397-001:詳細頁只靠 WebSocket initial snapshot

對應:UI-001、UI-002、UI-010、CHG-025。

  1. 套用 PUB 模式,確認兩樁 AVAILABLE、無 transaction/operation/queue。
  2. Tester A 從 LIFF 充電樁列表進入 CP001-001 詳細頁。
  3. 用 FE debug log/Network 確認只建立 Connector WebSocket;不得另外呼叫 Connector detail REST API。
  4. 確認第一份 snapshot 為目前 Connector 資料,不是舊 cache。

預期:

  • areaType=public、raw status=AVAILABLEdriverState.code=READY
  • title/description 表示可開始充電,主要 action 為 START_CHARGING/「開始充電」。
  • activeOperation=null
  • 公樁不顯示離峰 switch。
  • 列表與詳細頁的狀態一致。

M1397-002:CloudLink 先插槍、尚未按開始

對應:CHG-001、UI-002。

  1. Tester A 先把車插到 CP001-001,不要按 LIFF 開始。
  2. 等待設備狀態穩定後,由 LIFF 列表重新進入詳細頁。
  3. 記錄 raw OCPP status 與 LIFF driverState。

預期:即使設備因插槍回報與待命相關的 raw status,沒有未完成 RemoteStart operation 時,
LIFF 仍顯示 READY/「開始充電」,不得誤顯示「準備中」。

M1397-003:公樁 RemoteStart lifecycle

對應:CHG-001、CHG-020、CHG-029、CHG-032、CHG-034。

  1. 承 M1397-002,Tester A 按「開始充電」。
  2. 若有確認 modal,確認開始。
  3. 按下後立即觀察按鈕、title 與 description,直到開始充電。
  4. 持續至少一個 MeterValues 上傳週期。

預期:

  • command 回 HTTP 202,含新的 operationId
  • LIFF 先進入 PREPARING/「準備中」,不能重複開始。
  • activeOperation.operationId 與 response、DB e_remote_transaction_log.id 相同。
  • 收到 StartTransaction 後轉 CHARGING,主要 action 改為 STOP_CHARGING/「停止充電」。
  • 只有一筆 ACTIVE transaction;Relay 開啟且有合理電流/MeterValues。
  • terminal success operationResult 只顯示一次,不因後續 UPDATED event 重複彈出。

M1397-004:公樁 RemoteStop lifecycle

對應:CHG-001、CHG-020、CHG-029、CHG-032、CHG-034。

  1. 承 M1397-003,由啟動交易的 Tester A 按「停止充電」並確認。
  2. 立即觀察狀態,直到實體停止。

預期:

  • command 回 HTTP 202,取得 STOP operationId
  • LIFF 先進入 FINISHING/「停止中」,Start/Stop 都不可重複執行。
  • 收到 StopTransaction 後,Relay 關閉、transaction 轉 COMPLETED。
  • Connector 回到 READY;停止成功 modal 只顯示一次。

M1397-005:CloudLink PREPARING 取消啟動

對應:CHG-007、CHG-034。

  1. 車輛先不要建立充電需求,從 READY 按「開始充電」。
  2. LIFF 顯示 PREPARING 後,在 StartTransaction 前按「取消啟動」並確認。
  3. 觀察 operation、Relay 與後續 60 秒狀態。

預期:

  • action code 為 CANCEL_START,不是依按鈕文字猜 command。
  • 取消成功後 START operation 為 CANCELLED,LIFF 回 READY
  • 不建立 ACTIVE transaction,設備不應在取消後又自行開始。

若硬體太快產生 StartTransaction,記錄 Blocked,改用未插車且能進入 waiting mode 的方式重測;
不得把已進入 CHARGING 的停止流程算成取消 PREPARING。

M1397-006:WebSocket 中斷時禁止沿用舊 action

對應:UI-010。

  1. 在 READY 詳細頁確認「開始充電」可操作。
  2. 關閉手機網路,或用可控代理只阻斷 Connector WebSocket。
  3. 斷線後立即點原本位置的「開始充電」。
  4. 等待 FE 的一次短暫重連失敗,再恢復網路。

預期:

  • 斷線後舊 driverState.actions 立即不可用,不送出 command。
  • 一次短暫重連仍失敗後,退回列表並顯示連線失敗 modal。
  • 不以 REST detail 或舊 snapshot 留在可操作狀態。
  • 重新進入詳細頁前,DB 不新增 RemoteStart operation。

8. 私樁排隊與離峰案例(PRI-0)

M1397-007:私樁畫面與手動零 slot 排隊

對應:CHG-037、ROT-004、UI-002。

  1. 套用 PRI-0,tariff 使用 E2E1397WAIT,off-peak 保持 OFF。
  2. Tester A 從列表進入 CP001-002
  3. 確認顯示離峰 switch,driverState 為 READY。
  4. 按「開始充電」。

預期:

  • private area 顯示離峰 switch。
  • 因 private slot=0,command 同步回 HTTP 200,不建立 RemoteStart operation。
  • 建立 source=MANUALrequestedByUserId=Tester A Branch user 的 Priority。
  • driverState 轉 QUEUED,主要操作顯示「取消排隊」,action 為 CANCEL_MANUAL_START
  • 點「取消排隊」後只刪除 MANUAL queue,回 READY;不改變 off-peak switch。

M1397-008:開啟長期離峰立即 OFF_PEAK_WAITING

對應:ROT-001、ROT-021。

  1. 確認沒有 MANUAL queue,tariff 使用 E2E1397WAIT
  2. Tester A 將離峰 switch 切成 ON,完成 FE 確認。
  3. API 成功後立即觀察畫面與 DB,不等待 scheduler。

預期:

  • command 為 ENABLE_OFF_PEAK,HTTP 200。
  • enableOffPeak=true,啟用者為 Tester A。
  • driverState 立即為 OFF_PEAK_WAITING;主要操作顯示「取消排隊」。
  • 因目前不在 OFF_PEAK window,e_connector_priority 尚未建立。
  • 「取消排隊」與 switch OFF 都送 DISABLE_OFF_PEAK;成功後回 READY,清除 off-peak actor。

M1397-009:進入離峰 window 後轉 QUEUED

對應:ROT-001、ROT-004、ROT-021。

  1. tariff 改為 E2E1397ACTIVE,保持 PRI-0。
  2. 從 LIFF 將離峰切為 ON。
  3. 先確認立即回 OFF_PEAK_WAITING。
  4. 等待最多 10 分鐘的正常 off-peak scheduler;為縮短人工測試,可由 BE 呼叫既有維運 enqueue endpoint,
    但 Tester 的產品操作仍必須是 LIFF switch ON。
  5. 觀察 WebSocket 更新。

預期:

  • scheduler 建立 source=OFF_PEAK、requester=啟用者的 Priority。
  • driverState 由 OFF_PEAK_WAITING 轉 QUEUED,操作仍是「取消排隊」。
  • private slot=0,不 dispatch RemoteStart,不出現幽靈 PREPARING。
  • 取消後關閉長期離峰並刪除 OFF_PEAK queue;不得刪除其他來源 queue。

9. 私樁實際充電案例(PRI-1)

M1397-010:私樁手動 Start/Stop

對應:CHG-005、CHG-020、CHG-029、CHG-034、ROT-002。

  1. 先將 off-peak 關閉並清空 queue,切換 PRI-1。
  2. Tester A 插槍後從 LIFF 按「開始充電」。
  3. 觀察 READY → PREPARING → CHARGING 與實際供電。
  4. 再按「停止充電」,觀察 CHARGING → FINISHING → READY。

預期與 M1397-003/004 相同,另須確認 private slot 有效、沒有先建立 MANUAL queue,
且整個 transaction 的 area 為 private。

M1397-011:離峰自動開始、停止後抑制本 window

對應:ROT-008、ROT-021、ROT-022、CHG-034。

  1. PRI-1、tariff=E2E1397ACTIVE,車輛插在 CP001-002,off-peak 起始為 OFF。
  2. Tester A 從 LIFF 開啟離峰。
  3. 等待正常 scheduler enqueue/dispatch;必要時 BE 只觸發既有 enqueue 與 rotation tick。
  4. 觀察 OFF_PEAK_WAITING → QUEUED → PREPARING → CHARGING。
  5. CHARGING 時嘗試操作離峰 switch。
  6. 按「停止充電」,閱讀 modal 後確認。
  7. StopTransaction 完成後,至少跨兩次 scheduler cycle 觀察是否重啟。
  8. 再將 off-peak OFF,然後 ON,確認可重新加入本 window。

預期:

  • CHARGING 時 FE 不允許關閉 off-peak switch。
  • 停止 modal 清楚告知:會停止目前充電、本 window 不再自動啟動、長期偏好仍保持。
  • StopTransaction 後 enableOffPeak=true,driverState=OFF_PEAK_WAITING
    reason=USER_CANCELLED_FOR_CURRENT_WINDOW
  • suppression window 持久化;同一 window scheduler 不得重新 dispatch。
  • OFF → ON 明確重設 suppression 後,才可重新 OFF_PEAK_WAITING/QUEUED/dispatch。

M1397-012:離峰 transaction 非使用者停止而結束

對應:CHG-003、ROT-003、ROT-022。

  1. 重新建立一筆離峰 CHARGING transaction。
  2. 不按 LIFF 停止,改用拔槍或讓設備產生真實 StopTransaction。
  3. 觀察 LIFF、DB 與後續 scheduler。

預期:

  • 不猜測滿電或拔槍,不顯示「已充滿」或「槍未正確連接」。
  • enableOffPeak=true,driverState=OFF_PEAK_WAITING
    reason=TRANSACTION_ENDED_FOR_CURRENT_WINDOW
  • 本 window 不再自動開始;下一個獨立 window 才恢復排程。

M1397-013:RemoteStart/RemoteStop timeout 與一次性失敗提示

對應:CHG-009、CHG-018、CHG-032、CHG-034、CHG-035。

RemoteStart:

  1. PRI-1、off-peak OFF,使用不會建立充電需求的狀態,從 LIFF 按開始。
  2. 記錄 operationId,等待 CloudLink 既有 RemoteStart deadline 加 30 秒 reconciliation grace。
  3. 不重複按開始。

預期:PREPARING 期間不盲目重送;最終 timeout result 只顯示一次,手動來源回 READY。
若 grace 後才收到 StartTransaction,實際 transaction 優先轉 CHARGING,但不重播 timeout modal。

RemoteStop:

  1. 在可控制的測試 transaction 中暫時製造 StopTransaction 不回或晚回。
  2. 從 LIFF 按停止,等待 30 秒 deadline。

預期:30 秒內 FINISHING;deadline 時 transaction 仍 ACTIVE 則顯示一次停止失敗並回 CHARGING,
允許新的明確停止。晚到 StopTransaction 仍完成 transaction reconciliation,但不重播舊 modal。

本案例需要 BE/CP observer 可安全製造 timeout;若無法控制,標記 Blocked,不得用單元測試代替。

10. 多使用者與重啟案例

M1397-014:operationResult 只送給發起者

對應:CHG-035。

  1. Tester A、B 同時開啟同一支 private CP001-002 詳細頁。
  2. Tester A 從 LIFF 發起 Start 或 Stop,製造一個 terminal success/failure result。
  3. 同時錄製兩支手機畫面與 WebSocket event。

預期:A、B 都收到共用 driverState UPDATED;只有 A 收到該 operationResult modal。
兩邊都不得看到 browser payload 中暴露另一人的 Branch user identity。

M1397-015:PUBLIC/PRIVATE 停止授權差異

對應:CHG-020、CHG-021、CHG-036。

PUBLIC:

  1. PUB 模式,由 Tester A 啟動 CP001-002
  2. Tester B 開啟同樁並嘗試停止。

預期:B 可看到共用 CHARGING presentation,但 API 回 403
TRANSACTION_OWNED_BY_OTHER_USER;不 dispatch RemoteStop,設備繼續充電。最後由 A 正常停止。

PRIVATE:

  1. PRI-1 模式,確認 A、B 都是目前關聯住戶。
  2. 由 A 啟動 CP001-002,再由 B 停止。

預期:B 可以停止;原 transaction owner 不變,但 operation audit 的 stop requester 為 B。

M1397-016:重啟恢復與 terminal result 不重播

對應:CHG-034、CHG-035、UI-010、REL-004。

  1. 從 LIFF 建立可維持數秒以上的 PREPARING 或 FINISHING,記錄 operationId。
  2. BE observer 依 Ken 環境 SOP 重啟 ems-branch-api
  3. 服務恢復後,Tester 重新連入詳細頁。
  4. 完成該 operation,關閉頁面再重新進入。

預期:

  • 重啟後 initial snapshot 從持久化 operation 還原 PREPARING/FINISHING 與相同 operationId。
  • 重啟不建立第二筆 operation、不重複送 Start/Stop。
  • operation 終結後重新開頁,initial snapshot 不重播 terminal operationResult。
  • 仍生效的問題只由目前 driverState reason/description 表達。

11. 每案 DB/log 對帳

11.1 DB 查詢

SELECT id, operation_type, source, requested_by_user_id, connector_id,
       transaction_id, request_time, accepted_at, deadline_at, grace_until,
       completed_at, status, operation_status, failure_code, remark
FROM e_remote_transaction_log
WHERE connector_id = 'CP001-002'
ORDER BY id DESC
LIMIT 10;

SELECT id, connector_id, source, requested_by_user_id, charge_group,
       priority, start_charging_time, charge_status, status_reason,
       create_time, update_time
FROM e_connector_priority
WHERE connector_id = 'CP001-002'
ORDER BY create_time DESC;

SELECT transaction_id, connector_id, id_tag, start_timestamp, stop_timestamp,
       meter_start, meter_stop, reason, status, energy_consumed
FROM e_transactions
WHERE connector_id = 'CP001-002'
ORDER BY transaction_id DESC
LIMIT 10;

SELECT id, area, enable_off_peak, off_peak_enabled_by_user_id,
       off_peak_suppressed_window_start, off_peak_suppressed_window_end,
       off_peak_suppression_reason, charge_group, current_transaction_id
FROM e_connectors
WHERE id = 'CP001-002';

11.2 log 位置

  • Branch:/opt/ems/ems_branch/api/logs/
  • Charge Point:/opt/ems/ems_cp/api/logs/
  • HQ staging:docker1 的 ems-hq-staging-api container log

每個 operationId 要能串起 LIFF command、HQ、Branch Remote operation、OCPP command 與 transaction。

12. 測後還原

  1. 從 LIFF 正常停止所有 transaction,等兩樁 AVAILABLE、Relay OFF。
  2. 若 private off-peak 仍為 ON,先從 LIFF 切 OFF,確認 queue 清除。
  3. 依 4.1 當天留下的基線還原兩樁;若當天基線仍是 2026-07-31 狀態,可執行:
DELETE FROM e_connector_priority
WHERE connector_id IN ('CP001-001', 'CP001-002');

DELETE FROM e_connector_tariff
WHERE id IN ('CP001-001', 'CP001-002');

UPDATE e_connectors
SET area = 'public', enable_off_peak = NULL,
    off_peak_enabled_by_user_id = NULL,
    off_peak_suppressed_window_start = NULL,
    off_peak_suppressed_window_end = NULL,
    off_peak_suppression_reason = NULL,
    charge_group = NULL
WHERE id IN ('CP001-001', 'CP001-002');

UPDATE cp_connectors
SET area = 'public'
WHERE id IN ('CP001-001', 'CP001-002');

DELETE FROM e_tariff_time_slot
WHERE tariff_id IN ('E2E1397WAIT', 'E2E1397ACTIVE');

DELETE FROM e_tariff_table
WHERE id IN ('E2E1397WAIT', 'E2E1397ACTIVE');

DELETE FROM e_charge_group
WHERE id = 'CG_E2E_1397';
  1. 重跑 4.1、4.2 查詢,確認與基線一致。
  2. 從 LIFF 重新進入兩樁詳細頁,確認皆為 public、READY、不顯示離峰 switch。

不得刪除 e_remote_transaction_loge_transactions 或 OCPP log;它們是本輪 E2E 證據。

13. Test Run 報告要求

正式執行時另建 test_report/YYYYMMDD_NNN_redmine_1397_liff_manual_e2e.md,逐案填:

  • Test case ID/Catalog case ID。
  • 實際前置資料與 fixture mode。
  • LIFF 完整操作步驟。
  • Expected/Actual 畫面與狀態轉換。
  • API status/body、WebSocket event、operationId。
  • DB/log/實體 Relay 與電流證據。
  • PASS/FAIL/BLOCKED 與 defect ticket。
  • 清理與還原結果。

本計畫是待執行步驟,不得預先填寫 PASS。

(5-5/5)