跳至主要内容

US-202: 訂單狀態流轉

User Story

作為 店員/管理者 我想要 能夠變更訂單狀態並追蹤狀態流轉歷史 以便 掌握訂單進度並確保訂單按流程推進


驗收標準 (Acceptance Criteria)

Scenario 1: 確認訂單(待確認 → 已確認)

  • Given 我是已登入的店員
  • And 系統中有一筆「待確認」狀態的訂單 ABC-20251101-0001
  • And 我已檢查訂單資訊無誤
  • When 我在訂單詳情頁點擊「確認訂單」按鈕
  • Then 系統應將訂單狀態變更為「已確認」
  • And 系統應記錄狀態變更日誌(操作者、時間、狀態變更)
  • And 系統應發送通知給客戶(「您的訂單已確認」)
  • And 我應看到「訂單已確認」的成功訊息
  • And 訂單應出現在「待分配設計師」列表中

Scenario 2: 分配設計師後自動流轉(已確認 → 設計中)

  • Given 我是已登入的管理者
  • And 系統中有一筆「已確認」狀態的訂單 ABC-20251101-0002
  • When 我將訂單分配給設計師「王小花」
  • Then 系統應自動將訂單狀態變更為「設計中」
  • And 系統應記錄「分配設計師」操作日誌
  • And 系統應發送通知給設計師「王小花」
  • And 訂單應出現在設計師「王小花」的工作列表中

Scenario 3: 設計完成(設計中 → 待出貨)

  • Given 我是已登入的設計師「王小花」
  • And 我的工作列表中有一筆「設計中」狀態的訂單 ABC-20251101-0002
  • And 我已完成商品設計
  • When 我上傳作品照片(至少 1 張)
  • And 我點擊「標記為完成」按鈕
  • Then 系統應將訂單狀態變更為「待出貨」
  • And 系統應記錄作品照片上傳與完成時間
  • And 系統應發送通知給管理者與送貨員(「訂單已完成設計」)
  • And 訂單應出現在「待分配送貨員」列表中

Scenario 4: 配送中(待出貨 → 配送中)

  • Given 我是已登入的送貨員「李配送」
  • And 系統中有一筆「待出貨」狀態的訂單 ABC-20251101-0003
  • When 我從「待出貨」列表中接單
  • And 我點擊「開始配送」按鈕
  • Then 系統應將訂單狀態變更為「配送中」
  • And 系統應記錄配送開始時間與送貨員資訊
  • And 系統應發送通知給客戶(「訂單配送中,預計 {時段} 送達」)
  • And 訂單應出現在我的「配送中」列表

Scenario 5: 簽收完成(配送中 → 已簽收)

  • Given 我是已登入的送貨員「李配送」
  • And 我的「配送中」列表中有一筆訂單 ABC-20251101-0003
  • And 客戶已簽收商品
  • When 我上傳簽收照片(至少 1 張)
  • And 我點擊「確認簽收」按鈕
  • Then 系統應將訂單狀態變更為「已簽收」
  • And 系統應記錄簽收時間與照片
  • And 系統應發送通知給客戶(「訂單已簽收,查看簽收照片」)
  • And 系統應檢查支付狀態,若已支付則自動變更為「已完成」

Scenario 6: 訂單完成(已簽收 → 已完成)

  • Given 系統中有一筆「已簽收」狀態的訂單 ABC-20251101-0003
  • And 訂單支付狀態為「已支付」
  • When 系統定期檢查訂單狀態(每 5 分鐘)
  • Then 系統應自動將訂單狀態變更為「已完成」
  • And 系統應記錄完成時間
  • And 訂單應移至「已完成」列表

Scenario 7: 無效狀態流轉(錯誤場景)

  • Given 我是已登入的店員
  • And 系統中有一筆「設計中」狀態的訂單 ABC-20251101-0004
  • When 我嘗試將訂單狀態變更為「待確認」(逆向流轉)
  • Then 系統應拒絕此操作並顯示錯誤訊息「無效的狀態流轉」
  • And 訂單狀態應保持為「設計中」

Scenario 8: 查看狀態流轉歷史

  • Given 我是已登入的管理者
  • And 系統中有一筆訂單 ABC-20251101-0001
  • When 我在訂單詳情頁查看「狀態歷史」區塊
  • Then 系統應顯示所有狀態變更記錄
  • And 每筆記錄應包含:
    • 變更時間(精確到秒)
    • 原狀態 → 新狀態
    • 操作者姓名與角色
    • 操作說明(如「分配給設計師王小花」)

業務規則 (Business Rules)

  1. 狀態流轉規則(僅允許單向流轉)

    待確認 → 已確認 → 設計中 → 待出貨 → 配送中 → 已簽收 → 已完成
    • 禁止逆向流轉(如「設計中」→「已確認」)
    • 例外:任何狀態都可流轉至「已取消」(US-208 處理)
  2. 自動狀態流轉

    • 已確認 → 設計中: 當分配設計師時自動流轉
    • 待出貨 → 配送中: 當送貨員接單時自動流轉
    • 已簽收 → 已完成: 當支付狀態為「已支付」時自動流轉(系統定期檢查)
  3. 手動狀態流轉

    • 待確認 → 已確認: 店員/管理者手動確認
    • 設計中 → 待出貨: 設計師上傳作品照片並標記完成
    • 配送中 → 已簽收: 送貨員上傳簽收照片並確認
  4. 狀態流轉前置條件

    • 設計中 → 待出貨: 必須上傳至少 1 張作品照片
    • 配送中 → 已簽收: 必須上傳至少 1 張簽收照片
    • 已簽收 → 已完成: 必須支付狀態為「已支付」
  5. 狀態歷史記錄

    • 每次狀態變更都需記錄審計日誌
    • 日誌包含:操作者、時間戳、原狀態、新狀態、操作說明
    • 日誌不可修改或刪除
  6. 通知規則

    • 每次狀態變更都應觸發相應的通知(整合 Epic 0 通知系統)
    • 通知對象根據狀態不同而異(客戶、設計師、送貨員、管理者)
  7. 多租戶隔離

    • 狀態流轉操作僅能針對當前租戶的訂單
    • 員工選擇列表(設計師、送貨員)僅顯示當前租戶的員工

UI/UX 需求 (UI/UX Requirements)

訂單詳情頁 - 狀態流轉區塊

佈局

  • 狀態進度條: 顯示訂單當前處於哪個階段(視覺化流程圖)
    • 已完成的階段: 綠色勾選
    • 當前階段: 藍色高亮
    • 未完成階段: 灰色
  • 操作按鈕區: 根據當前狀態與用戶角色動態顯示可執行操作
  • 狀態歷史時間軸: 折疊式區塊,顯示所有狀態變更記錄

互動行為

1. 狀態進度條

[✓] 待確認 → [✓] 已確認 → [●] 設計中 → [ ] 待出貨 → [ ] 配送中 → [ ] 已簽收 → [ ] 已完成
  • 點擊每個階段顯示該階段的操作記錄

2. 操作按鈕(根據狀態動態顯示)

當前狀態可見按鈕(根據角色)操作結果
待確認「確認訂單」(店員+)→ 已確認
已確認「分配設計師」(管理者+)→ 設計中
設計中「上傳作品照片」(設計師+)上傳照片
設計中「標記為完成」(設計師+)→ 待出貨
待出貨「分配送貨員」(管理者+)分配送貨員
待出貨「開始配送」(送貨員+)→ 配送中
配送中「上傳簽收照片」(送貨員+)上傳照片
配送中「確認簽收」(送貨員+)→ 已簽收

3. 狀態歷史時間軸

  • 預設折疊,點擊「查看狀態歷史」展開
  • 顯示格式:
    ● 2025-11-01 14:30:25  設計中 → 待出貨
    操作者: 王小花 (設計師)
    說明: 上傳作品照片並標記完成

    ● 2025-11-01 10:15:00 已確認 → 設計中
    操作者: 系統自動
    說明: 分配給設計師王小花

    ● 2025-11-01 09:30:00 待確認 → 已確認
    操作者: 張店員 (店員)
    說明: 手動確認訂單

錯誤訊息

  • 無效狀態流轉: 「無法執行此操作,當前狀態不允許此流轉」
  • 缺少前置條件: 「請先上傳作品照片後再標記為完成」
  • 權限不足: 「您沒有權限執行此操作」

成功反饋

  • 狀態變更成功: Toast 通知「訂單狀態已更新為 {新狀態}」
  • 通知發送成功: Toast 通知「已發送通知給 {通知對象}」

技術規格 (Technical Specifications)

API 端點

1. 變更訂單狀態

  • 端點: PUT /api/v1/orders/{orderId}/status
  • 權限要求: 根據目標狀態不同而異(見業務規則)
  • 多租戶隔離: 自動檢查 tenantId

請求 Payload

interface UpdateOrderStatusRequest {
newStatus: OrderStatus; // 目標狀態(必填)
reason?: string; // 操作原因(可選,某些流轉需要)
assignedTo?: string; // 分配對象 ID(分配設計師/送貨員時必填)
photoUrls?: string[]; // 照片 URL(上傳作品/簽收照片時必填)
}

enum OrderStatus {
PENDING_CONFIRMATION = 'pending_confirmation',
CONFIRMED = 'confirmed',
IN_PRODUCTION = 'in_production',
READY_FOR_DELIVERY = 'ready_for_delivery',
OUT_FOR_DELIVERY = 'out_for_delivery',
DELIVERED = 'delivered',
COMPLETED = 'completed',
CANCELLED = 'cancelled',
DELIVERY_FAILED = 'delivery_failed'
}

響應範例

{
"orderId": "ABC-20251101-0001",
"oldStatus": "pending_confirmation",
"newStatus": "confirmed",
"updatedAt": "2025-11-01T09:30:00Z",
"updatedBy": {
"userId": "user-001",
"userName": "張店員",
"role": "ROLE_SALES"
},
"message": "訂單狀態已更新為「已確認」"
}

2. 查看狀態歷史

  • 端點: GET /api/v1/orders/{orderId}/status-history
  • 權限要求: ROLE_STAFF 或更高
  • 多租戶隔離: 自動檢查 tenantId

響應範例

{
"orderId": "ABC-20251101-0001",
"history": [
{
"id": "history-001",
"timestamp": "2025-11-01T14:30:25Z",
"oldStatus": "in_production",
"newStatus": "ready_for_delivery",
"operator": {
"userId": "user-002",
"userName": "王小花",
"role": "ROLE_FLORIST"
},
"description": "上傳作品照片並標記完成",
"metadata": {
"photoCount": 3
}
},
{
"id": "history-002",
"timestamp": "2025-11-01T10:15:00Z",
"oldStatus": "confirmed",
"newStatus": "in_production",
"operator": {
"userId": "system",
"userName": "系統自動",
"role": "system"
},
"description": "分配給設計師王小花",
"metadata": {
"assignedTo": "user-002"
}
}
]
}

數據模型

OrderStatusHistory Entity

interface OrderStatusHistory {
id: string; // 歷史記錄 ID
orderId: string; // 訂單 ID(外鍵)
tenantId: string; // 租戶 ID
oldStatus: OrderStatus; // 原狀態
newStatus: OrderStatus; // 新狀態
timestamp: Date; // 變更時間
operatorId: string; // 操作者 ID
operatorName: string; // 操作者姓名(冗餘,方便查詢)
operatorRole: UserRole; // 操作者角色
description: string; // 操作描述
metadata?: Record<string, any>; // 額外資訊(如照片數量、分配對象)
createdAt: Date;
}

前端組件

  • 使用框架組件:

    • @appfuse/appfuse-webButton 組件(操作按鈕)
    • @appfuse/appfuse-webTimeline 組件(狀態歷史,若有)
    • @appfuse/appfuse-webBadge 組件(狀態標籤)
    • @appfuse/appfuse-webProgressSteps 組件(狀態進度條,若有)
  • 自定義組件:

    • OrderStatusFlow - 位於 src/applets/order-applet/components/OrderStatusFlow.tsx
    • OrderStatusHistory - 狀態歷史時間軸
    • StatusProgressBar - 狀態進度條

狀態流轉驗證邏輯

// 狀態流轉規則映射表
const STATUS_TRANSITIONS: Record<OrderStatus, OrderStatus[]> = {
[OrderStatus.PENDING_CONFIRMATION]: [OrderStatus.CONFIRMED, OrderStatus.CANCELLED],
[OrderStatus.CONFIRMED]: [OrderStatus.IN_PRODUCTION, OrderStatus.CANCELLED],
[OrderStatus.IN_PRODUCTION]: [OrderStatus.READY_FOR_DELIVERY, OrderStatus.CANCELLED],
[OrderStatus.READY_FOR_DELIVERY]: [OrderStatus.OUT_FOR_DELIVERY, OrderStatus.CANCELLED],
[OrderStatus.OUT_FOR_DELIVERY]: [OrderStatus.DELIVERED, OrderStatus.DELIVERY_FAILED, OrderStatus.CANCELLED],
[OrderStatus.DELIVERED]: [OrderStatus.COMPLETED],
[OrderStatus.COMPLETED]: [],
[OrderStatus.CANCELLED]: [],
[OrderStatus.DELIVERY_FAILED]: [OrderStatus.OUT_FOR_DELIVERY, OrderStatus.CANCELLED]
};

// 驗證狀態流轉是否合法
function isValidTransition(currentStatus: OrderStatus, targetStatus: OrderStatus): boolean {
const allowedTransitions = STATUS_TRANSITIONS[currentStatus] || [];
return allowedTransitions.includes(targetStatus);
}

SBE 場景 (Specification by Example)

詳細的測試場景與範例數據:


估算 (Estimation)

  • Story Points: 5 點
  • 預估工時: 2-3 天
  • 複雜度: 中等

工作拆分

  1. 後端開發 (1-1.5 天)

    • 實作 PUT /api/v1/orders/{orderId}/status API
    • 狀態流轉驗證邏輯
    • 狀態歷史記錄(OrderStatusHistory Entity)
    • GET 狀態歷史 API
    • 自動狀態流轉邏輯(系統定期檢查)
    • 通知觸發邏輯(整合 Epic 0)
  2. 前端開發 (1-1.5 天)

    • 創建 OrderStatusFlow 組件
    • 狀態進度條實作
    • 操作按鈕動態顯示邏輯
    • 狀態歷史時間軸組件
    • 權限控制(根據角色顯示按鈕)
  3. 整合與測試 (0.5 天)

    • 整合測試(API + UI)
    • E2E 測試(完整狀態流轉流程)
    • Mock API 更新

依賴 (Dependencies)

前置條件

  • US-201: 創建訂單 - 需要訂單資料
  • Epic 0: 通知系統 - 狀態變更通知
  • Epic 0: 審計日誌 - 記錄狀態變更

並行開發

  • 可與 US-203(搜尋與過濾訂單)並行開發

外部依賴

  • 通知系統 API(發送狀態變更通知)
  • 員工管理 API(獲取設計師與送貨員列表)

測試策略 (Testing Strategy)

單元測試

  • 測試狀態流轉驗證邏輯(isValidTransition
  • 測試自動狀態流轉邏輯(已簽收 → 已完成)
  • 測試狀態歷史記錄生成

整合測試

  • 測試 PUT /api/v1/orders/{orderId}/status API 端點
  • 測試狀態歷史記錄查詢 API
  • 測試通知觸發邏輯
  • 測試多租戶隔離(不同租戶的訂單狀態獨立)

E2E 測試

  • 測試完整的訂單狀態流轉流程(待確認 → 已完成)
  • 測試無效狀態流轉(錯誤場景)
  • 測試權限控制(不同角色的操作權限)

手動測試

  • 測試狀態進度條視覺化
  • 測試操作按鈕動態顯示
  • 測試狀態歷史時間軸展開/折疊

完成定義 (Definition of Done)

  • 後端 API 實作完成並通過單元測試
  • 前端 UI 實作完成並符合設計規範
  • 狀態流轉驗證邏輯實作完成
  • 狀態歷史記錄功能實作完成
  • 整合測試通過(API + UI)
  • E2E 測試通過(至少涵蓋完整流轉與錯誤場景)
  • 單元測試覆蓋率 > 80%
  • Code Review 通過
  • API 文檔已更新(訂單 API 規格
  • Mock API 已更新(支援狀態流轉)
  • 通知功能驗證通過
  • 審計日誌記錄驗證通過
  • 多租戶隔離驗證通過
  • 產品經理驗收通過

備註 (Notes)

設計決策

為何禁止逆向流轉?

  • 確保訂單流程的單向性與可追溯性
  • 防止人為錯誤(如不小心將「已簽收」改回「設計中」)
  • 若需要修正錯誤,應使用「取消訂單」並重新創建

為何需要狀態歷史?

  • 滿足審計需求(追溯訂單處理過程)
  • 幫助排查問題(如「為何訂單卡在設計中?」)
  • 提升透明度(客戶可查看訂單進度)

未來優化

  • 支援 WebSocket 即時推送狀態變更(目前使用輪詢)
  • 支援狀態流轉通知偏好設定(客戶可選擇接收哪些通知)
  • 支援批量狀態流轉(如批量確認訂單)
  • 支援狀態流轉規則自定義(不同租戶可自定義流程)

最後更新: 2025-12-20