跳至主要内容

訂單 API

概述

訂單 API 提供訂單的完整生命週期管理,包括創建、查詢、搜尋、過濾、狀態流轉和歷史記錄。支援多租戶隔離和角色權限控制。


端點列表

方法路徑說明權限
GET/api/v1/orders列出訂單(支援搜尋、過濾、分頁)ROLE_SALES 或更高
GET/api/v1/orders/:id獲取單一訂單詳情ROLE_SALES 或更高
POST/api/v1/orders創建訂單ROLE_SALES 或更高
PATCH/api/v1/orders/:id部分更新訂單ROLE_SALES 或更高
PUT/api/v1/orders/:id更新訂單(完整替換)⚠️ 已棄用ROLE_SALES 或更高
DELETE/api/v1/orders/:id刪除訂單ROLE_OWNER
PATCH/api/v1/orders/:id/status更新訂單狀態根據狀態流轉規則
GET/api/v1/orders/:id/status-history獲取訂單狀態歷史ROLE_SALES 或更高

端點詳細規格

GET /api/v1/orders

描述: 列出訂單,支援搜尋、過濾、分頁和排序

權限: ROLE_SALES 或更高

Query Parameters:

參數類型必填說明預設值
searchstringNo搜尋關鍵字(訂單編號、客戶姓名、電話、地址)-
statusstring[]No訂單狀態過濾(可多選)-
deliveryDateFromstringNo配送日期起始(YYYY-MM-DD)-
deliveryDateTostringNo配送日期結束(YYYY-MM-DD)-
amountMinnumberNo最低金額-
amountMaxnumberNo最高金額-
assignedFloriststringNo分配的設計師 ID-
assignedDeliverystringNo分配的送貨員 ID-
pageintegerNo頁碼(從 1 開始)1
limitintegerNo每頁數量(10, 20, 50, 100)20
sortBystringNo排序欄位(createdAt, deliveryDate, amount)createdAt
sortOrderstringNo排序順序(asc, desc)desc

請求範例:

GET /api/v1/orders?search=李&status=PENDING&status=CONFIRMED&page=1&limit=20
Authorization: Bearer {access_token}

響應範例 (200 OK):

Headers:

X-Total-Count: 45
X-Page: 1
X-Per-Page: 20
Link: </api/v1/orders?page=2&limit=20>; rel="next", </api/v1/orders?page=3&limit=20>; rel="last"

Body:

[
{
"id": "order-001",
"orderNumber": "ABC-20251104-0001",
"customerId": "cust-123",
"customerName": "李大華",
"customerPhone": "0912-345-678",
"status": "PENDING",
"statusLabel": "待確認",
"deliveryAddress": "台北市信義區信義路五段 7 號",
"deliveryDate": "2025-11-05",
"deliveryTimeSlot": "morning",
"totalAmount": 2520,
"createdAt": "2025-11-04T10:30:00Z",
"updatedAt": "2025-11-04T10:30:00Z"
}
]

錯誤響應:

狀態碼錯誤碼說明
401AUTH_TOKEN_INVALIDToken 無效或過期
403FORBIDDEN權限不足

GET /api/v1/orders/:id

描述: 獲取單一訂單的完整詳情

權限: ROLE_SALES 或更高

路徑參數:

參數類型說明
idstring訂單 ID

請求範例:

GET /api/v1/orders/order-001
Authorization: Bearer {access_token}

響應範例 (200 OK):

{
"id": "order-001",
"orderNumber": "ABC-20251104-0001",
"tenantId": "tenant-abc",
"customerId": "cust-123",
"customerName": "李大華",
"customerPhone": "0912-345-678",
"status": "PENDING",
"statusLabel": "待確認",
"items": [
{
"productId": "prod-001",
"productName": "玫瑰花束(12 朵)",
"quantity": 2,
"price": 1200,
"subtotal": 2400,
"notes": "不要包含百合"
}
],
"deliveryAddress": "台北市信義區信義路五段 7 號",
"deliveryPhone": "0912-345-678",
"deliveryDate": "2025-11-05",
"deliveryTimeSlot": "morning",
"deliveryTimeSlotLabel": "上午 (09:00-12:00)",
"recipientName": "張三",
"recipientPhone": "0987-654-321",
"cardMessage": "生日快樂!",
"specialRequirements": "",
"internalNotes": "",
"subtotal": 2400,
"taxAmount": 120,
"totalAmount": 2520,
"assignedFlorist": null,
"assignedDelivery": null,
"createdAt": "2025-11-04T10:30:00Z",
"updatedAt": "2025-11-04T10:30:00Z",
"createdBy": "user-001"
}

錯誤響應:

狀態碼錯誤碼說明
404ORDER_NOT_FOUND訂單不存在
403FORBIDDEN權限不足(跨租戶訪問)

POST /api/v1/orders

描述: 創建新訂單

權限: ROLE_SALES 或更高

請求 Body:

{
"customerId": "cust-123",
"items": [
{
"productId": "prod-001",
"quantity": 2,
"price": 1200,
"notes": "不要包含百合"
}
],
"deliveryAddress": "台北市信義區信義路五段 7 號",
"deliveryPhone": "0912-345-678",
"deliveryDate": "2025-11-05",
"deliveryTimeSlot": "morning",
"recipientName": "張三",
"recipientPhone": "0987-654-321",
"cardMessage": "生日快樂!",
"specialRequirements": "",
"internalNotes": ""
}

欄位說明:

欄位類型必填說明驗證規則
customerIdstringYes客戶 ID-
itemsarrayYes商品項目至少 1 個
items[].productIdstringYes商品 ID-
items[].quantityintegerYes數量≥ 1
items[].pricenumberYes單價≥ 0
items[].notesstringNo備註-
deliveryAddressstringYes配送地址-
deliveryPhonestringYes聯絡電話-
deliveryDatestringYes配送日期(YYYY-MM-DD)≥ 今天,非店休日
deliveryTimeSlotstringYes配送時段(morning, afternoon, evening)-
recipientNamestringNo收件人姓名-
recipientPhonestringNo收件人電話-
cardMessagestringNo卡片訊息-
specialRequirementsstringNo特殊需求-
internalNotesstringNo內部備註-

響應範例 (201 Created):

{
"id": "order-001",
"orderNumber": "ABC-20251104-0001",
"status": "PENDING",
"totalAmount": 2520,
"createdAt": "2025-11-04T10:30:00Z"
}

錯誤響應:

狀態碼錯誤碼說明
400VALIDATION_ERROR驗證失敗(缺少必填欄位、日期無效等)
400DELIVERY_DATE_INVALID配送日期早於今天
400DELIVERY_DATE_CLOSED配送日期為店休日

錯誤響應範例 (400):

{
"message": "配送日期不能早於今天",
"error": "DELIVERY_DATE_INVALID",
"field": "deliveryDate",
"timestamp": "2025-11-04T10:30:00Z"
}

PATCH /api/v1/orders/:id

描述: 部分更新訂單(僅更新提供的欄位)

根據 ADR-008 表單部分更新策略,建議使用此端點進行訂單編輯。

權限: ROLE_SALES 或更高

路徑參數:

參數類型說明
idstring訂單 ID

請求 Body: 僅包含需要更新的欄位

{
"deliveryAddress": "新地址",
"deliveryDate": "2025-12-30"
}

可更新欄位:

欄位類型說明
customerIdstring客戶 ID
itemsarray商品項目(整體替換)
deliveryAddressstring配送地址
deliveryPhonestring聯絡電話
deliveryDatestring配送日期(YYYY-MM-DD)
deliveryTimeSlotstring配送時段
recipientNamestring收件人姓名
recipientPhonestring收件人電話
cardMessagestring卡片訊息
specialRequirementsstring特殊需求
internalNotesstring內部備註
productionPhotosstring[]作品照片 URL
deliveryPhotosstring[]簽收照片 URL

請求範例:

PATCH /api/v1/orders/order-001
Authorization: Bearer {access_token}
Content-Type: application/json

{
"deliveryDate": "2025-12-30",
"paymentMethod": "cash"
}

響應範例 (200 OK):

{
"id": "order-001",
"orderNumber": "ABC-20251104-0001",
"status": "PENDING",
"deliveryDate": "2025-12-30",
"updatedAt": "2025-12-21T10:30:00Z"
}

錯誤響應:

狀態碼錯誤碼說明
404ORDER_NOT_FOUND訂單不存在
403FORBIDDEN權限不足
400VALIDATION_ERROR驗證失敗

PUT /api/v1/orders/:id

⚠️ 已棄用: 請使用 PATCH /api/v1/orders/:id 進行部分更新

描述: 更新訂單資訊(完整替換)

權限: ROLE_SALES 或更高

路徑參數:

參數類型說明
idstring訂單 ID

請求 Body: 部分欄位更新(與 POST 相同結構,但所有欄位可選)

響應範例 (200 OK):

{
"id": "order-001",
"message": "訂單已更新"
}

錯誤響應:

狀態碼錯誤碼說明
404ORDER_NOT_FOUND訂單不存在
403FORBIDDEN權限不足

DELETE /api/v1/orders/:id

描述: 刪除訂單(軟刪除)

權限: ROLE_OWNER(僅店主)

路徑參數:

參數類型說明
idstring訂單 ID

響應範例 (200 OK):

{
"message": "訂單已刪除"
}

錯誤響應:

狀態碼錯誤碼說明
404ORDER_NOT_FOUND訂單不存在
403FORBIDDEN權限不足(非店主)

PATCH /api/v1/orders/:id/status

描述: 更新訂單狀態(部分更新,支援狀態流轉驗證)

權限: 根據狀態流轉規則(見下方)

路徑參數:

參數類型說明
idstring訂單 ID

請求 Body:

{
"newStatus": "CONFIRMED",
"notes": "訂單已確認",
"photoUrls": []
}

欄位說明:

欄位類型必填說明
newStatusstringYes新狀態(見下方狀態對照表)
notesstringNo狀態變更備註
photoUrlsstring[]條件必填照片 URL 陣列(特定狀態流轉必填)

狀態值對照表:

狀態值說明中文標籤
pending_confirmation待確認待確認
confirmed已確認已確認
in_production設計中設計中
ready_for_delivery待出貨待出貨
out_for_delivery配送中配送中
delivered已簽收已簽收
completed已完成已完成
cancelled已取消已取消
delivery_failed配送失敗配送失敗

照片上傳要求:

特定狀態流轉需要上傳照片:

狀態流轉照片類型最少數量說明
in_productionready_for_deliveryproduction1作品照片
out_for_deliverydelivereddelivery1簽收照片

請求範例(含照片):

{
"newStatus": "ready_for_delivery",
"notes": "設計完成",
"photoUrls": [
"https://cdn.example.com/photos/order-001/design-1.jpg",
"https://cdn.example.com/photos/order-001/design-2.jpg"
]
}

響應範例 (200 OK):

{
"orderId": "order-001",
"oldStatus": "in_production",
"newStatus": "ready_for_delivery",
"updatedAt": "2025-12-02T16:30:00Z",
"updatedBy": {
"userId": "user-002",
"userName": "王小花",
"role": "ROLE_FLORIST"
},
"message": "訂單狀態已更新為「待出貨」",
"photoCount": 2
}

錯誤響應:

狀態碼錯誤碼說明
400INVALID_STATUS_TRANSITION無效的狀態流轉(如逆向流轉)
400PHOTO_REQUIRED此狀態流轉需要上傳照片
403FORBIDDEN權限不足(角色無法執行此狀態變更)
404ORDER_NOT_FOUND訂單不存在

狀態流轉規則:

pending_confirmation → confirmed (店員確認)
confirmed → in_production (設計師開始設計)
in_production → ready_for_delivery (設計師完成,需照片)
ready_for_delivery → out_for_delivery (配送員開始配送)
out_for_delivery → delivered (配送員簽收,需照片)
delivered → completed (系統自動,支付完成後)
任何狀態 → cancelled (管理者取消)
out_for_delivery → delivery_failed (配送失敗)

權限對應:

狀態流轉所需角色工作台路徑需要照片
pending_confirmationconfirmedROLE_SALES/sales
confirmedin_productionROLE_FLORIST/design
in_productionready_for_deliveryROLE_FLORIST/design
ready_for_deliveryout_for_deliveryROLE_DELIVERY/delivery
out_for_deliverydeliveredROLE_DELIVERY/delivery
deliveredcompletedsystem-
任何 → cancelledROLE_OWNER-

GET /api/v1/orders/:id/status-history

描述: 獲取訂單的狀態流轉歷史

權限: ROLE_SALES 或更高

路徑參數:

參數類型說明
idstring訂單 ID

請求範例:

GET /api/v1/orders/order-001/status-history
Authorization: Bearer {access_token}

響應範例 (200 OK):

{
"orderId": "order-001",
"orderNumber": "ABC-20251104-0001",
"history": [
{
"id": "history-001",
"fromStatus": "PENDING",
"toStatus": "CONFIRMED",
"fromStatusLabel": "待確認",
"toStatusLabel": "已確認",
"changedBy": "user-001",
"changedByName": "王小明",
"changedByRole": "ROLE_SALES",
"notes": "訂單已確認",
"timestamp": "2025-11-04T11:00:00Z"
},
{
"id": "history-002",
"fromStatus": "CONFIRMED",
"toStatus": "DESIGNING",
"fromStatusLabel": "已確認",
"toStatusLabel": "設計中",
"changedBy": "user-002",
"changedByName": "李設計",
"changedByRole": "ROLE_FLORIST",
"notes": "開始設計",
"timestamp": "2025-11-04T14:00:00Z"
}
]
}

錯誤響應:

狀態碼錯誤碼說明
404ORDER_NOT_FOUND訂單不存在
403FORBIDDEN權限不足

業務規則

訂單編號生成規則

  • 格式: {租戶代碼}-{YYYYMMDD}-{序號}
  • 範例: ABC-20251104-0001
  • 序號: 每天從 0001 開始遞增

價格計算

  • 小計: Σ(商品單價 × 數量)
  • 稅額: 小計 × 5%
  • 總計: 小計 + 稅額

配送日期驗證

  • 配送日期不能早於今天
  • 配送日期不能為店休日(由系統配置)

多租戶隔離

  • 所有訂單自動附加 tenantId(從 JWT Token 提取)
  • 查詢自動過濾為當前租戶的訂單
  • 跨租戶訪問返回 404 Not Found(而非 403

相關 User Stories

核心流程

角色工作台


最後更新: 2025-12-21