iT邦幫忙

2025 iThome 鐵人賽

DAY 27
0
Vue.js

打造銷售系統30天修練 - 全集中・Vue之呼吸系列 第 27

Day 27:[Systemの呼吸・肆之型] 訂單流程 - 狀態機與流程設計

  • 分享至 

  • xImage
  •  

在 Day 25、Day26 的文章中,我們深入探討了 POS 系統中商品管理的前端 CRUD 介面設計,並借鑒了 CustomerManagement.vue 的實作模式,規劃了如何透過組件化和 Pinia Store 來高效管理商品資料。商品是零售系統的基石,而將商品轉化為實際銷售的,正是「訂單流程」。

訂單流程是任何商業系統的核心動脈,它不僅僅是簡單的資料記錄,更涉及一系列複雜的狀態變遷、業務邏輯判斷以及多方協同作業。

從顧客下單、付款、商家處理、出貨到最終完成,每個環節都可能產生不同的狀態和事件。如果沒有一個清晰、嚴謹的設計,訂單流程很容易變得混亂且難以維護。

今天,我們將引入一個強大的設計工具:「狀態機 (State Machine)」,來幫助我們理解和設計銷售系統的訂單流程。

透過狀態機,我們能夠將複雜的訂單生命週期清晰地模型化,確保狀態轉換的正確性,並為前端介面和後端邏輯的協同工作奠定堅實的基礎。

訂單流程的挑戰與複雜性

一個典型的訂單流程可能包含以下挑戰:

  • 多樣的狀態:訂單可能處於「待付款」、「已付款」、「處理中」、「已出貨」、「已完成」、「已取消」、「退款中」等多種狀態。
  • 嚴格的轉換規則:並非所有狀態之間都可以任意轉換。例如,「已出貨」的訂單不能直接回到「待付款」狀態。
  • 多種觸發事件:狀態的轉換由不同的事件觸發,例如「顧客付款成功」、「管理員確認訂單」、「物流更新出貨狀態」、「顧客申請取消」等。
  • 異常與錯誤處理:付款失敗、庫存不足、物流異常、顧客退貨等情況都需要有明確的處理流程和狀態變更。
  • 多角色互動:顧客、商家管理員、倉儲人員、物流人員等不同角色,對訂單狀態的影響和可操作性各不相同。

這些複雜性使得傳統的條件判斷 (if-else) 難以維護,且容易出錯。這正是狀態機大顯身手的地方。

狀態機 (State Machine) 簡介

狀態機是一種數學模型,用於描述一個系統在不同時間點所處的「狀態 (State)」,以及在接收到特定「事件 (Event)」時,如何從一個狀態「轉換 (Transition)」到另一個狀態。

一個狀態機由以下三個核心元素組成:

  1. 狀態 (State):系統在某一時刻的狀況。例如:訂單的「待付款」、「已付款」。
  2. 事件 (Event):觸發狀態變化的外部或內部動作。例如:「付款成功」、「取消訂單」。
  3. 轉換 (Transition):從一個狀態到另一個狀態的過程,由特定事件觸發,並可能伴隨執行某些動作。

狀態機的優點

  • 清晰的邏輯:將複雜的業務邏輯模型化為簡單的狀態和轉換,易於理解和溝通。
  • 減少錯誤:強制定義所有可能的狀態和轉換路徑,避免了非法狀態或轉換的發生。
  • 易於擴展:當業務需求變化時,只需添加新的狀態、事件或轉換規則,而不會影響現有邏輯。
  • 可視化:狀態圖 (State Diagram) 能夠直觀地展示系統的行為,有助於團隊成員理解。

訂單核心狀態與轉換設計

現在,讓我們為 POS 系統的訂單流程設計一個簡化的狀態機。

1. 定義核心狀態

我們首先定義訂單可能經歷的核心狀態:

  • PENDING_PAYMENT (待付款):訂單已建立,等待顧客付款。
  • PAID (已付款):顧客已成功付款。
  • PROCESSING (處理中):商家已確認訂單,準備出貨。
  • SHIPPED (已出貨):商品已交由物流運送。
  • COMPLETED (已完成):顧客已收到商品,訂單流程結束。
  • CANCELLED (已取消):訂單在付款前或付款後被取消。
  • REFUND_REQUESTED (退款申請中):顧客申請退款。
  • REFUNDED (已退款):退款已處理完成。

2. 定義事件

接下來,我們定義觸發狀態轉換的事件:

  • PAYMENT_SUCCESS (付款成功)
  • PAYMENT_FAILED (付款失敗)
  • CANCEL_ORDER (取消訂單)
  • CONFIRM_ORDER (商家確認訂單)
  • SHIP_ORDER (商家出貨)
  • DELIVER_ORDER (物流送達)
  • REQUEST_REFUND (顧客申請退款)
  • PROCESS_REFUND (商家處理退款)
  • ORDER_TIMEOUT (訂單超時未付款)

3. 設計狀態轉換規則 (State Transition Diagram)

以下是訂單狀態機的簡化轉換規則示意:

graph TD
    A[Start] --> B(PENDING_PAYMENT)

    B -- PAYMENT_SUCCESS --> C(PAID)
    B -- CANCEL_ORDER --> G(CANCELLED)
    B -- ORDER_TIMEOUT --> G

    C -- CONFIRM_ORDER --> D(PROCESSING)
    C -- CANCEL_ORDER --> G
    C -- REQUEST_REFUND --> H(REFUND_REQUESTED)

    D -- SHIP_ORDER --> E(SHIPPED)
    D -- CANCEL_ORDER --> G

    E -- DELIVER_ORDER --> F(COMPLETED)
    E -- REQUEST_REFUND --> H

    F -- REQUEST_REFUND --> H

    H -- PROCESS_REFUND --> I(REFUNDED)
    H -- CANCEL_REFUND --> C(PAID)  // 商家拒絕退款,回到已付款

    G -- End --> J[End]
    I -- End --> J
    F -- End --> J
  • PENDING_PAYMENT
    • 收到 PAYMENT_SUCCESS 事件 -> 轉換到 PAID
    • 收到 CANCEL_ORDER 事件或 ORDER_TIMEOUT 事件 -> 轉換到 CANCELLED
  • PAID
    • 收到 CONFIRM_ORDER 事件 -> 轉換到 PROCESSING
    • 收到 CANCEL_ORDER 事件 -> 轉換到 CANCELLED (可能需要退款流程)。
    • 收到 REQUEST_REFUND 事件 -> 轉換到 REFUND_REQUESTED
  • PROCESSING
    • 收到 SHIP_ORDER 事件 -> 轉換到 SHIPPED
    • 收到 CANCEL_ORDER 事件 -> 轉換到 CANCELLED (可能需要退款流程)。
  • SHIPPED
    • 收到 DELIVER_ORDER 事件 -> 轉換到 COMPLETED
    • 收到 REQUEST_REFUND 事件 -> 轉換到 REFUND_REQUESTED
  • COMPLETED
    • 收到 REQUEST_REFUND 事件 -> 轉換到 REFUND_REQUESTED
  • REFUND_REQUESTED
    • 收到 PROCESS_REFUND 事件 -> 轉換到 REFUNDED
    • 收到 CANCEL_REFUND 事件 (商家拒絕退款) -> 轉換回 PAID (或 COMPLETED,視業務邏輯而定)。
  • CANCELLEDREFUNDED 通常是終止狀態,不能再進行轉換。

前端與後端如何協同實作狀態機

狀態機的設計理念在前後端協同開發中尤為重要:

  • 後端 (Backend)

    • 後端服務是訂單狀態的唯一權威來源。所有狀態轉換的邏輯、業務規則驗證(例如庫存檢查、權限驗證)都應在後端實現。
    • 後端接收前端發送的「事件」,根據當前訂單狀態和事件,判斷是否允許轉換,並執行相應的業務邏輯(例如扣除庫存、生成物流單),然後更新資料庫中的訂單狀態。
    • 後端可以利用專門的狀態機庫(如 Python 的 transitions,Java 的 Spring State Machine)來實現狀態機邏輯。
  • 前端 (Frontend) - 狀態的呈現與事件的發送

    • 前端不直接修改訂單狀態,而是根據後端返回的訂單「狀態」,動態地呈現不同的介面元素和可操作按鈕。
    • 當使用者執行某個操作時(例如點擊「去付款」、「取消訂單」),前端會向後端發送一個「事件」請求。
    • 例如:
      • 如果訂單狀態是 PENDING_PAYMENT,前端顯示「去付款」按鈕。點擊後發送 PAYMENT_SUCCESS 事件給後端。
      • 如果訂單狀態是 PAID,前端顯示「取消訂單」按鈕。點擊後發送 CANCEL_ORDER 事件給後端。
    • 透過 Pinia Store 管理訂單列表和單一訂單的狀態,並在後端響應後更新這些狀態。

Vue.js 中的應用考量

在 Vue.js 專案中,我們可以這樣應用狀態機的概念:

  • Pinia Store (stores/order.js)
    • 管理訂單列表 (orders) 和單一訂單詳情 (currentOrder) 的狀態。
    • 封裝與後端訂單 API 互動的邏輯,例如 fetchOrders(), fetchOrderById(id), sendOrderEvent(orderId, eventType, payload)
    • 當後端返回新的訂單狀態時,更新 Store 中的資料。
  • 組件化
    • OrderList.vue:展示訂單列表,根據訂單狀態顯示不同的標籤或顏色。
    • OrderDetail.vue:訂單詳情頁面,這是狀態機邏輯在前端最集中的體現。
      • 根據 currentOrder.status 動態渲染不同的操作按鈕(例如「去付款」、「確認收貨」、「申請退款」)。
      • 這些按鈕點擊後,呼叫 orderStore.sendOrderEvent(orderId, 'EVENT_TYPE'),將事件發送給後端。
  • 權限控制
    • 前端介面也需要根據登入使用者的角色(顧客、管理員)來判斷哪些操作按鈕可以顯示,哪些事件可以發送。例如,只有管理員才能觸發 CONFIRM_ORDERSHIP_ORDER 事件。

總結

今天,我們深入探討了 POS 系統中訂單流程的複雜性,並引入了「狀態機」這一強大工具來進行設計。透過明確定義訂單的狀態、事件和轉換規則,我們能夠構建出一個清晰、健壯且易於維護的訂單管理系統。前端負責根據狀態呈現介面和發送事件,後端則作為狀態機的權威,負責處理所有狀態轉換的業務邏輯。

這種設計模式不僅提升了系統的穩定性,也使得未來業務邏輯的擴展變得更加容易。

明日,Day 28:[Systemの呼吸・伍之型] 儀表板 - 數據視覺化與圖表。心を燃やせ 🔥!


上一篇
Day 26(下):[Systemの呼吸・參之型] 客戶資料管理— CRUD 的前端實作
下一篇
Day 28:[Systemの呼吸・伍之型] 儀表板 - 數據視覺化與圖表
系列文
打造銷售系統30天修練 - 全集中・Vue之呼吸29
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言