# DDDream Admin API 文件

這份文件詳細說明了 DDDream 套件中所有後台 Admin API 端點，包括請求參數、驗證規則和回應格式。

## 目錄

- [認證系統](#認證系統)
- [權限管理](#權限管理)
- [儀表板](#儀表板)
- [訂單管理](#訂單管理)
- [業績抽成管理](#業績抽成管理)
- [包套方案訂單管理](#包套方案訂單管理)
- [訂單項目管理](#訂單項目管理)
- [儲值金訂單管理](#儲值金訂單管理)
- [會員管理](#會員管理)
- [服務管理](#服務管理)
- [商家管理](#商家管理)
- [排程管理](#排程管理)
- [排程詳情管理](#排程詳情管理)
- [數據分析](#數據分析)
- [金流管理](#金流管理)
- [系統管理](#系統管理)
- [混合式標籤管理](#混合式標籤管理)
- [優惠券管理](#優惠券管理)
- [推播管理](#推播管理)

---

## 認證系統

### POST `/api/admin/merchant/user/login`
後台使用者登入

**中介層:** 無 (登入端點)

**請求參數:**
```json
{
  "email": "email|required",
  "password": "string|required"
}
```

**回應範例:**
```json
{
  "status": "success",
  "code": 200,
  "message": "Merchant admin user login success",
  "data": {
    "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
    "user": {
      "id": "user-uuid",
      "name": "管理員",
      "email": "admin@petsalon.com",
      "merchant": {
        "id": "merchant-uuid",
        "name": "寵物美容店",
        "alias": "pet-salon",
        "state": 1,
        "subscriptionState": "active"
      }
    }
  }
}
```

### GET `/api/admin/merchant/user/logout`
後台使用者登出

**中介層:** 無 (登出端點)

**回應範例:**
```json
{
  "status": "success",
  "code": 200,
  "message": "Merchant admin user logout success",
  "data": null
}
```

### POST `/api/password/email`
發送重設密碼連結

**中介層:** 無 (密碼重設功能)

### GET `/api/password/reset/{token}`
驗證重設密碼 Token

**中介層:** 無 (密碼重設功能)

### POST `/api/password/reset`
重設密碼

**中介層:** 無 (密碼重設功能)

---

## 權限管理

### GET `/api/admin/merchant/user/access`
取得商家使用者權限

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- ⏰ 檢查商家訂閱是否過期
- 👤 驗證管理員權限

### GET `/api/admin/merchant/user/tour`
取得使用者首次教學狀態

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- ⏰ 檢查商家訂閱是否過期
- 👤 驗證管理員權限

---

## 儀表板

### GET `/api/admin/dashboard/orders`
取得訂單統計

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 限制只能查看自己商家的訂單統計
- ⏰ 確保商家訂閱有效
- 📊 管理員權限查看營運數據

**回應範例:**
```json
{
  "status": "success",
  "code": 200,
  "message": "Dashboard admin orders success",
  "data": {
    "today": {
      "orders": 15,
      "revenue": 12500,
      "newMembers": 3
    },
    "thisWeek": {
      "orders": 89,
      "revenue": 67800,
      "newMembers": 12
    },
    "thisMonth": {
      "orders": 342,
      "revenue": 256700,
      "newMembers": 45
    },
    "recentOrders": [
      {
        "id": "order-uuid",
        "displayId": "20240115001",
        "memberName": "王小明",
        "productName": "基礎美容",
        "total": 800,
        "status": 1,
        "createdAt": "2024-01-15T09:00:00Z"
      }
    ]
  }
}
```

### POST `/api/admin/dashboard/ranking`
取得排行榜數據

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 限制只能查看自己商家的排行數據
- ⏰ 確保商家訂閱有效

**回應範例:**
```json
{
  "status": "success",
  "code": 200,
  "message": "Dashboard admin ranking success",
  "data": {
    "topServices": [
      {
        "serviceName": "基礎美容",
        "orderCount": 156,
        "revenue": 124800
      },
      {
        "serviceName": "精緻造型",
        "orderCount": 89,
        "revenue": 133500
      }
    ],
    "topMembers": [
      {
        "memberName": "王小明",
        "orderCount": 25,
        "totalSpent": 18750
      },
      {
        "memberName": "李小華",
        "orderCount": 22,
        "totalSpent": 16500
      }
    ],
    "topStaff": [
      {
        "staffName": "美容師小王",
        "orderCount": 78,
        "revenue": 62400
      }
    ]
  }
}
```
- 🏆 管理員權限查看績效排名

**請求參數:**
```json
{
  "startDate": "date|required",
  "endDate": "date|required",
  "type": "string|required|in:service,staff,revenue"
}
```

### GET `/api/admin/dashboard/smsInfo`
取得簡訊資訊統計

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 查看商家簡訊使用情況
- ⏰ 確保商家訂閱有效
- 📱 簡訊額度和使用統計

---

## 訂單管理

### POST `/api/admin/order/container/search`
搜尋訂單容器

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 限制只能查看自己商家的訂單
- ⏰ 確保商家訂閱有效
- 📋 管理員權限查看訂單列表

**請求參數:**
```json
{
  "page": "integer|nullable",
  "limit": "integer|nullable",
  "startDate": "date|nullable",
  "endDate": "date|nullable",
  "status": "array|nullable",
  "search": "string|nullable",
  "paymentStatus": "string|nullable|in:PAID,UNPAID",
  "paymentMethod": "string|nullable"
}
```

**回應範例:**
```json
{
  "status": "success",
  "code": 200,
  "message": "Order container admin search success",
  "data": {
    "items": [
      {
        "uuid": "order-container-uuid",
        "displayId": "20240115001",
        "memberName": "王小明",
        "memberPhone": "0912345678",
        "total": 800,
        "paymentMethod": "Credit",
        "paymentStatus": "PAID",
        "paidAt": "2024-01-15T10:30:00Z",
        "createdAt": "2024-01-15T09:00:00Z",
        "orders": [
          {
            "id": "order-uuid",
            "productName": "基礎美容",
            "status": 1,
            "date": "2024-01-15",
            "time": "09:00",
            "total": 800,
            "pet": {
              "name": "小白",
              "breed": "貴賓犬"
            }
          }
        ]
      }
    ],
    "pagination": {
      "current_page": 1,
      "last_page": 5,
      "per_page": 20,
      "total": 95
    }
  }
}
```

### POST `/api/admin/order/container/store`
建立/更新訂單容器

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- ⏰ 檢查商家訂閱狀態
- ➕ 建立或修改訂單容器

### GET `/api/admin/order/container/{uuid}`
取得特定訂單容器

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 限制只能查看自己商家的訂單
- 🔍 查看訂單容器詳細資訊

**回應範例:**
```json
{
  "uuid": "order-container-uuid",
  "displayId": "20240115001",
  "isTemp": false,
  "memberName": "王小明",
  "memberPhone": "+886-0912345678",
  "memberEmail": "member@example.com",
  "total": 800,
  "paymentMethod": "Credit",
  "paymentStatus": "PAID",
  "paymentExpiredDate": "2024-01-15T12:00:00Z",
  "paidAt": "2024-01-15T10:30:00Z",
  "createdAt": "2024-01-15T09:00:00Z",
  "orders": [
    {
      "id": "order-uuid",
      "parentId": null,
      "memberId": "member-uuid",
      "status": 1,
      "groupSize": 1,
      "usedSize": 1,
      "source": "web",
      "productId": "product-uuid",
      "productName": "基礎美容",
      "productType": "cosmetic",
      "date": "2024-01-15",
      "time": "09:00",
      "serviceTime": 90,
      "endDate": "2024-01-15T10:30:00Z",
      "priceTotal": 800,
      "priceBase": 800,
      "point": 0,
      "fullName": "王小明",
      "gender": "male",
      "phoneCode": "+886",
      "phoneNumber": "0912345678",
      "email": "member@example.com",
      "pet": {
        "id": "pet-uuid",
        "name": "小白",
        "breed": "貴賓犬",
        "gender": "male",
        "birthday": "2020-01-01",
        "categoryTitle": "小型犬",
        "sizeTitle": "3kg以下"
      },
      "scheduleItem": {
        "id": "schedule-item-uuid",
        "name": "美容師小王"
      },
      "helper": {
        "id": "helper-uuid",
        "name": "助理小李"
      }
    }
  ]
}
```

### POST `/api/admin/order/container/{uuid}/sendLink`
發送訂單付款連結

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 📧 發送付款連結給客戶

### POST `/api/admin/order/store`
建立/更新訂單

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- ⏰ 檢查商家訂閱狀態
- 📝 建立或修改訂單資訊

**請求參數 (主要欄位):**
```json
{
  "id": "string|nullable",
  "type": "string|required_without:id|in:cosmetic,deposit,daycare,goods",
  "parentId": "string|nullable|size:15",
  "productId": "uuid|nullable",
  "scheduleItemId": "uuid|nullable",
  "helperId": "uuid|nullable",
  "startDate": "datetime|nullable|format:Y-m-d H:i",
  "memberId": "uuid|nullable",
  "paymentMethod": "string|nullable|in:Free,Cash,Prepaid,Vacc,Credit,StoreCredit,Atm,Deposit,StoreLinePay,Installment",
  "groupSize": "integer|required_without:id",
  "params": "array|required_without:id",
  "status": "integer|required_with:id|in:0,1,2,3,4,5,6",
  "fullName": "string|nullable",
  "phoneCode": "string|nullable|regex:/^\\+[0-9]+$/",
  "phoneNumber": "string|nullable",
  "email": "email|nullable",
  "total": "numeric|required_without:id|gte:0"
}
```

### POST `/api/admin/order/search`
搜尋訂單

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 限制只能查看自己商家的訂單
- 🔍 支援多種搜尋條件

### POST `/api/admin/order/remove`
刪除訂單

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 🗑️ 刪除指定訂單

### POST `/api/admin/order/changeTime`
修改訂單時間

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- ⏰ 修改預約時間

### POST `/api/admin/order/assignHelper`
指派服務人員

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 👷 指派或更換服務人員

### POST `/api/admin/order/searchHelpers`
搜尋可用服務人員

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 查看商家的服務人員
- 👷 檢查人員可用時段

### POST `/api/admin/order/{order_id}/refund`
訂單退款

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 💰 處理訂單退款

### POST `/api/admin/order/export/simple`
匯出訂單 (簡易版)

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 限制只能匯出自己商家的訂單
- 📊 匯出 Excel 或 CSV 格式

### GET `/api/admin/order/{order_id}`
取得特定訂單

**中介層:** `hasMerchant`, `expired`, `admin`, `isStaff`
- 🏢 驗證商家管理員身份
- ⏰ 檢查商家訂閱狀態
- 👤 驗證管理員權限
- 👷 員工身份驗證，排班人員只能查看自己的訂單

### POST `/api/admin/order/{order_id}/cancel`
取消訂單

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- ❌ 取消指定訂單

### GET `/api/admin/order/{id}/shortUrl`
取得訂單短網址

**路徑參數 `id`**：一般訂單為 displayId；住宿訂單（HotelOrder）或預付訂單（PrepaidOrder）為 UUID（36 字元）。UUID 時優先解析為住宿訂單，找不到再解析為預付訂單。

**回應**：`data`（string）為訂單短網址本體。訂單狀態須為 UNPAID、PAID、CHECKIN／CHECK_IN、CHECKEDIN、NOSHOW／NO_SHOW、COMPLETE／CHECK_OUT（住宿訂單另支援 PENDING）；已取消訂單無法取得短網址。

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 🔐 權限需具備 `getLink`
- 🔗 產生訂單分享連結

---

## 業績抽成管理

### POST `/api/admin/commission/store`
新增業績抽成

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 💰 設定員工業績抽成

### POST `/api/admin/commission/remove`
刪除業績抽成

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 🗑️ 移除業績抽成設定

---

## 包套方案訂單管理

### POST `/api/admin/prepaid/order/store`
建立/更新包套方案訂單

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 📦 建立或修改包套方案訂單

### POST `/api/admin/prepaid/order/search`
搜尋包套方案訂單

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 限制只能查看自己商家的包套訂單
- 🔍 支援多種搜尋條件

### GET `/api/admin/prepaid/order/{order_uuid}`
取得特定包套方案訂單

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 限制只能查看自己商家的包套訂單
- 🔍 查看包套訂單詳情

### POST `/api/admin/prepaid/order/{order_id}/sendLink`
發送包套方案訂單付款連結

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 📧 發送付款連結給客戶

### POST `/api/admin/prepaid/order/{order_uuid}/cancel`
取消包套方案訂單

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- ❌ 取消指定的包套訂單

### POST `/api/admin/prepaid/order/export/simple`
匯出包套方案訂單 (簡易版)

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 限制只能匯出自己商家的包套訂單
- 📊 匯出 Excel 或 CSV 格式

---

## 訂單項目管理

### POST `/api/admin/order/item/modify`
修改訂單項目

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- ✏️ 修改訂單中的項目

---

## 儲值金訂單管理

### POST `/api/admin/deposit/order/search`
搜尋儲值金訂單

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 限制只能查看自己商家的儲值訂單
- 💳 儲值金訂單列表

### POST `/api/admin/deposit/order/export`
匯出儲值金訂單

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 限制只能匯出自己商家的儲值訂單
- 📊 匯出儲值金訂單資料

### GET `/api/admin/deposit/order/{id}`
取得特定儲值金訂單

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 限制只能查看自己商家的儲值訂單
- 💰 查看儲值金訂單詳情

---

## 會員管理

### POST `/api/admin/merchant/member/search`
搜尋會員

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 限制只能查看自己商家的會員
- 🔍 支援多種搜尋條件

**請求參數:**
```json
{
  "page": "integer|nullable",
  "limit": "integer|nullable",
  "search": "string|nullable",
  "levelId": "integer|nullable",
  "tagId": "integer|nullable",
  "registrationStartDate": "date|nullable",
  "registrationEndDate": "date|nullable",
  "lastVisitStartDate": "date|nullable", 
  "lastVisitEndDate": "date|nullable",
  "status": "string|nullable|in:active,blocked"
}
```

**回應範例:**
```json
{
  "status": "success",
  "code": 200,
  "message": "Merchant member admin search success",
  "data": {
    "items": [
      {
        "id": "member-uuid",
        "fullName": "王小明",
        "phoneCode": "+886",
        "phoneNumber": "0912345678",
        "email": "member@example.com",
        "gender": "male",
        "birthday": "1990-01-01",
        "lineUserId": "line_user_123",
        "level": {
          "id": "level-uuid",
          "title": "VIP會員",
          "discount": 10,
          "bonusDiscount": 5
        },
        "depositBalance": 1500.00,
        "bonusBalance": 200.00,
        "totalSpent": 15000.00,
        "totalOrders": 25,
        "lastVisit": "2024-01-10T14:30:00Z",
        "joinDate": "2023-01-15T10:30:00Z",
        "status": "active",
        "tags": [
          {
            "id": "tag-uuid",
            "title": "VIP客戶"
          }
        ]
      }
    ],
    "pagination": {
      "current_page": 1,
      "last_page": 3,
      "per_page": 20,
      "total": 58
    }
  }
}
```

### POST `/api/admin/merchant/member/searchByPhone`
依電話號碼搜尋會員

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 📱 快速查找會員
- ➕ 支援新增會員功能（當會員不存在時）

**請求參數:**
```json
{
  "phoneCode": "string|required|regex:/^\\+[0-9]+$/",
  "phoneNumber": "string|required"
}
```

**回應範例（找到會員）:**
```json
{
  "status": "success",
  "code": 200,
  "message": "MerchantMemberAdminGetItemSuccess",
  "data": {
    "id": "member-uuid",
    "phoneCode": "+886",
    "phoneNumber": "0912345678",
    "email": "member@example.com",
    "fullName": "王小明",
    "gender": "male",
    "ordersCounts": 25,
    "noshowOrdersCounts": 2,
    "prepaidCounts": 3,
    "ordersTotal": 15000.00,
    "depositInfo": {
      "solution1": {
        "allUseDepositTotal": 500,
        "allRealPayTotal": 2000,
        "canWithdrawTotal": 1500
      },
      "solution2": {
        "reduceDepositTotal": {
          "point": 2000,
          "bonus": 0
        },
        "allUseDepositTotal": {
          "point": 500,
          "bonus": 0
        },
        "canWithdrawTotal": {
          "point": 1500,
          "bonus": null
        }
      }
    },
    "storeInvoiceSetting": 1,
    "availablePrepaidOrders": [],
    "pets": [],
    "lineId": "line_user_123",
    "isMember": 1,
    "tags": [
      {
        "id": "tag-uuid",
        "title": "VIP客戶"
      }
    ],
    "billingInfo": {
      "name": "王小明",
      "phoneCode": "+886",
      "phoneNumber": "0912345678",
      "email": "member@example.com"
    },
    "shippingInfo": {
      "name": "王小明",
      "phoneCode": "+886",
      "phoneNumber": "0912345678",
      "address": "台北市大安區復興南路一段123號"
    },
    "taxType": "PERSONAL",
    "taxId": null,
    "CarrierType": null,
    "CarrierNum": null,
    "LoveCode": null,
    "extraInfos": {},
    "level": {
      "id": "level-uuid",
      "title": "VIP會員",
      "startedAt": "2024-01-15T10:30:00Z",
      "expiredAt": null,
      "logs": [],
      "reason": null,
      "discount": 10,
      "servicePrices": [],
      "prepaids": [],
      "deposits": [],
      "default": 0
    },
    "block": {
      "isBlock": 0,
      "createdAt": null,
      "blockReason": null
    },
    "memberPrivateComments": [],
    "orderContainers": [],
    "lineInfo": {
      "isBindLineNotify": false,
      "id": null,
      "lineNotifyBindAt": null,
      "lineNotifyName": "LINE Notify"
    }
  }
}
```

**回應範例（找不到會員）:**
```json
{
  "status": "error",
  "code": 404,
  "message": "MerchantMemberAdminMemberNotFound",
  "data": null
}
```

### POST `/api/admin/merchant/member/changePhone`
修改會員電話號碼

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 📱 更新會員聯絡資訊

### POST `/api/admin/merchant/member/store`
建立/更新會員

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 👤 建立或修改會員資料

**請求參數:**
```json
{
  "id": "uuid|nullable",
  "phoneCode": "string|required_without:id",
  "phoneNumber": "string|required_without:id",
  "email": "email|nullable",
  "fullName": "string|nullable",
  "gender": "string|nullable|in:male,female",
  "lineId": "string|nullable",
  "tagIds": "array|nullable",
  "tagIds.*": "integer|required",
  "extraInfos": "array|nullable",
  "billingInfo": {
    "name": "string|nullable",
    "phone": "string|nullable",
    "email": "email|nullable",
    "postcode": "string|nullable|alpha_num",
    "city": "string|nullable",
    "district": "string|nullable",
    "address": "string|nullable"
  },
  "shippingInfo": [
    {
      "name": "string|nullable",
      "phone": "string|nullable",
      "postcode": "string|nullable|alpha_num",
      "city": "string|nullable",
      "district": "string|nullable",
      "address": "string|nullable"
    }
  ],
  "taxType": "string|nullable|in:B2C,B2B,DONATE",
  "taxId": "string|required_if:taxType,B2B|nullable",
  "CarrierType": "integer|nullable|in:0,1,2",
  "CarrierNum": "string|required_with:CarrierType|nullable",
  "LoveCode": "string|required_if:taxType,DONATE|nullable",
  "saveTaxInfo": "integer|nullable|in:0,1"
}
```

**請求範例（建立新會員）:**
```json
{
  "phoneCode": "+886",
  "phoneNumber": "912345678",
  "email": "member@example.com",
  "fullName": "王小明",
  "gender": "male",
  "lineId": "line123456",
  "tagIds": [1, 2, 3],
  "extraInfos": {},
  "billingInfo": {
    "name": "王小明",
    "phone": "+886-912345678",
    "email": "member@example.com",
    "postcode": "100",
    "city": "台北市",
    "district": "中正區",
    "address": "重慶南路一段122號"
  },
  "shippingInfo": [
    {
      "name": "王小明",
      "phone": "+886-912345678",
      "postcode": "100",
      "city": "台北市",
      "district": "中正區",
      "address": "重慶南路一段122號"
    }
  ],
  "taxType": "B2C",
  "CarrierType": 0,
  "CarrierNum": "/ABC1234",
  "saveTaxInfo": 1
}
```

**請求範例（更新現有會員）:**
```json
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "email": "newemail@example.com",
  "fullName": "王大明",
  "gender": "male",
  "tagIds": [1, 3]
}
```

**回應範例:**
```json
{
  "status": "success",
  "code": 200,
  "message": "MerchantMemberAdminStoreSuccess",
  "data": {
    "id": "member-uuid",
    "phoneCode": "+886",
    "phoneNumber": "912345678",
    "email": "member@example.com",
    "fullName": "王小明",
    "gender": "male",
    "ordersCounts": 25,
    "noshowOrdersCounts": 2,
    "prepaidCounts": 3,
    "ordersTotal": 15000.00,
    "depositInfo": {
      "solution1": {
        "allUseDepositTotal": 500,
        "allRealPayTotal": 2000,
        "canWithdrawTotal": 1500
      },
      "solution2": {
        "reduceDepositTotal": {
          "point": 2000,
          "bonus": 0
        },
        "allUseDepositTotal": {
          "point": 500,
          "bonus": 0
        },
        "canWithdrawTotal": {
          "point": 1500,
          "bonus": null
        }
      }
    },
    "storeInvoiceSetting": 1,
    "availablePrepaidOrders": [],
    "pets": [],
    "lineId": "line123456",
    "isMember": 1,
    "tags": [
      {
        "id": "tag-uuid",
        "title": "VIP客戶"
      }
    ],
    "billingInfo": {
      "name": "王小明",
      "phoneCode": "+886",
      "phoneNumber": "912345678",
      "email": "member@example.com",
      "postcode": "100",
      "city": "台北市",
      "district": "中正區",
      "address": "重慶南路一段122號"
    },
    "shippingInfo": [
      {
        "name": "王小明",
        "phoneCode": "+886",
        "phoneNumber": "912345678",
        "postcode": "100",
        "city": "台北市",
        "district": "中正區",
        "address": "重慶南路一段122號"
      }
    ],
    "taxType": "B2C",
    "taxId": null,
    "CarrierType": 0,
    "CarrierNum": "/ABC1234",
    "LoveCode": null,
    "extraInfos": {},
    "level": {
      "id": "level-uuid",
      "title": "VIP會員",
      "startedAt": "2024-01-15 10:30:00",
      "expiredAt": null,
      "logs": [],
      "reason": null,
      "discount": 10,
      "servicePrices": [],
      "prepaids": [],
      "deposits": [],
      "default": 0
    },
    "block": {
      "isBlock": 0,
      "createdAt": null,
      "blockReason": null
    },
    "memberPrivateComments": [],
    "orderContainers": [],
    "lineInfo": {
      "isBindLineNotify": false,
      "id": null,
      "lineNotifyBindAt": null,
      "lineNotifyName": "LINE Notify"
    }
  }
}
```

**注意事項:**
- 若提供 `id`，則為更新現有會員，此時 `phoneCode` 和 `phoneNumber` 可不填
- 若未提供 `id`，則為建立新會員，此時 `phoneCode` 和 `phoneNumber` 為必填
- `billingInfo` 和 `shippingInfo` 僅小捲尾使用
- `taxType` 為 `B2B` 時，`taxId` 為必填
- `taxType` 為 `DONATE` 時，`LoveCode` 為必填
- `CarrierType` 存在時，`CarrierNum` 為必填
- `CarrierType` 值：`0`（手機條碼）、`1`（自然人）、`2`（ezPay 電子發票載具）

### POST `/api/admin/merchant/member/{id}/block`
封鎖/解封會員

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 🚫 封鎖或解封會員帳號

### GET `/api/admin/merchant/member/{id}`
取得特定會員資訊

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 限制只能查看自己商家的會員
- 👤 查看會員詳細資訊

**路徑參數:**
- `id` (string, required): 會員 UUID

**回應範例:**
```json
{
  "status": "success",
  "code": 200,
  "message": "MerchantMemberAdminGetItemSuccess",
  "data": {
    "id": "member-uuid",
    "phoneCode": "+886",
    "phoneNumber": "0912345678",
    "email": "member@example.com",
    "fullName": "王小明",
    "gender": "male",
    "ordersCounts": 25,
    "noshowOrdersCounts": 2,
    "prepaidCounts": 3,
    "ordersTotal": 15000.00,
    "depositInfo": {
      "solution1": {
        "allUseDepositTotal": 500,
        "allRealPayTotal": 2000,
        "canWithdrawTotal": 1500
      },
      "solution2": {
        "reduceDepositTotal": {
          "point": 2000,
          "bonus": 0
        },
        "allUseDepositTotal": {
          "point": 500,
          "bonus": 0
        },
        "canWithdrawTotal": {
          "point": 1500,
          "bonus": null
        }
      }
    },
    "storeInvoiceSetting": 1,
    "availablePrepaidOrders": [
      {
        "id": "prepaid-order-uuid",
        "displayId": "PP20240115001",
        "title": "基礎美容包套",
        "remainingCount": 5,
        "totalCount": 10,
        "expiredAt": "2024-12-31T23:59:59Z"
      }
    ],
    "pets": [
      {
        "id": "pet-uuid",
        "name": "小白",
        "breed": "貴賓犬",
        "gender": "male",
        "birthday": "2020-01-01",
        "categoryTitle": "小型犬",
        "sizeTitle": "3kg以下"
      }
    ],
    "lineId": "line_user_123",
    "isMember": 1,
    "tags": [
      {
        "id": "tag-uuid",
        "title": "VIP客戶"
      }
    ],
    "billingInfo": {
      "name": "王小明",
      "phoneCode": "+886",
      "phoneNumber": "0912345678",
      "email": "member@example.com"
    },
    "shippingInfo": {
      "name": "王小明",
      "phoneCode": "+886",
      "phoneNumber": "0912345678",
      "address": "台北市大安區復興南路一段123號"
    },
    "taxType": "PERSONAL",
    "taxId": null,
    "CarrierType": null,
    "CarrierNum": null,
    "LoveCode": null,
    "extraInfos": {},
    "level": {
      "id": "level-uuid",
      "title": "VIP會員",
      "startedAt": "2024-01-15T10:30:00Z",
      "expiredAt": null,
      "logs": {
        "data": [
          {
            "id": "log-uuid",
            "levelTitle": "VIP會員",
            "startedAt": "2024-01-15T10:30:00Z",
            "expiredAt": null,
            "reason": "系統自動升級"
          }
        ],
        "current_page": 1,
        "last_page": 1,
        "per_page": 15,
        "total": 1
      },
      "reason": "系統自動升級",
      "discount": 10,
      "servicePrices": [
        {
          "id": "service-price-uuid",
          "discountType": "percentage",
          "discount": 5
        }
      ],
      "prepaids": [],
      "deposits": [],
      "default": 0
    },
    "block": {
      "isBlock": 0,
      "createdAt": null,
      "blockReason": null
    },
    "memberPrivateComments": [
      {
        "id": "comment-uuid",
        "content": "客戶偏好週末預約",
        "createdAt": "2024-01-10T14:30:00Z"
      }
    ],
    "orderContainers": [
      {
        "uuid": "order-container-uuid",
        "displayId": "20240115001",
        "total": 800,
        "paymentStatus": "PAID",
        "createdAt": "2024-01-15T09:00:00Z",
        "orders": []
      }
    ],
    "lineInfo": {
      "isBindLineNotify": true,
      "id": "line-uuid",
      "lineNotifyBindAt": "2024-01-10T10:30:00",
      "lineNotifyName": "LINE Notify"
    }
  }
}
```

### POST `/api/admin/merchant/member/import`
匯入會員資料

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 📊 批量匯入會員資料

### POST `/api/admin/merchant/member/export`
匯出會員資料

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 限制只能匯出自己商家的會員
- 📊 匯出會員清單

### POST `/api/admin/merchant/member/{member_id}/changeLevel`
修改會員等級

**中介層:** `hasMerchant`, `admin`, `expired`
- 🏢 驗證商家管理員身份
- 👤 驗證管理員權限
- ⏰ 檢查商家訂閱狀態
- 📈 調整會員等級

### POST `/api/admin/merchant/member/notification/send`
發送會員通知

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- ⏰ 檢查商家訂閱狀態
- 📧 發送通知給會員（需具備 `sendNotification` 權限）

依指定模式（會員、訂單、預付訂單）發送自訂通知，可選擇 Email、簡訊或兩者。請求以非同步 Job 處理，成功時立即回傳。

**請求參數:**

| 參數名稱 | 類型 | 必填 | 說明 |
|---------|------|------|------|
| `mode` | string | ✅ | 發送模式：`byMember`、`byOrder`、`byPrepaidOrder` |
| `memberIds` | array | ❌ | 會員 ID 陣列（mode 為 `byMember` 時；不傳或空陣列時依搜尋條件篩選） |
| `orderIds` | array | 條件必填 | 訂單 ID 陣列（mode 為 `byOrder` 或 `byPrepaidOrder` 時必填） |
| `templateContent` | string | ✅ | 通知內容（支援 HTML，支援替換字佔位符） |
| `router` | string | ✅ | 發送管道：`email`、`sms`、`all` |
| `subject` | string | 條件必填 | 信件主旨（router 為 `email` 或 `all` 時必填，支援替換字） |
| `sendWhoType` | string | 條件必填 | 訂單通知對象（mode 為 `byOrder` 時必填）：`onlyUser`、`onlyBuyer`、`all` |

**mode 為 `byMember` 且未傳 `memberIds` 時**，可額外傳入搜尋參數篩選會員：`tagIds`、`memberLevelIds`、`block`、`lineNotifyStatus`、`gender`、`birthdayMonth`、`monthsWithoutOrder`、`startDate`、`endDate`、`singleAmount`、`totalAmount`、`serviceIds`、`prepaidGroupOrderingIds`、`page`、`limit`（詳見會員搜尋 API）。

**替換字規則（templateContent / subject）:**

主旨與通知內容支援以下佔位符，發送時會依收件人與訂單／會員資料替換。

**有訂單時**（mode 為 `byOrder` 或 `byPrepaidOrder`）：`{姓名}`、`{店家名稱}`、`{服務類型}`、`{服務項目}`、`{預約時間}`、`{人數}`、`{店家電話}`、`{店家地址}`、`{店家網址}`、`{訂單短網址}`。

**無訂單時**（mode 為 `byMember`）：`{姓名}`、`{店家名稱}`、`{店家電話}`、`{店家地址}`、`{店家網址}`。

**請求範例（依會員發送，使用替換字）:**
```json
{
  "mode": "byMember",
  "memberIds": ["a1b2c3d4-e5f6-7890-abcd-ef1234567890"],
  "templateContent": "<p>親愛的 {姓名}，您好！</p><p>{店家名稱} 有最新優惠，歡迎至 {店家網址} 查看。</p>",
  "router": "email",
  "subject": "{店家名稱} 優惠通知"
}
```

**請求範例（依訂單發送）:**
```json
{
  "mode": "byOrder",
  "orderIds": [101, 102],
  "templateContent": "<p>您的訂單即將入住，請準時報到。預約時間：{預約時間}</p>",
  "router": "all",
  "subject": "入住提醒",
  "sendWhoType": "onlyBuyer"
}
```

**回應範例（成功）:**
```json
{
  "status": "success",
  "code": 200,
  "message": "Custom send notification success",
  "data": null
}
```

**注意:** 實際發送為非同步執行；僅能發送給當前商家底下之會員或訂單。

### POST `/api/admin/merchant/member/forceDelete`
強制刪除會員

**中介層:** `hasMerchant`, `expired`, `SuperAdmin`
- 🏢 驗證商家管理員身份
- ⏰ 檢查商家訂閱是否過期
- 🔑 超級管理員權限 (高危險操作)

### POST `/api/admin/merchant/member/pet/search`
搜尋寵物

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 限制只能查看自己商家的寵物
- 🔍 支援多種搜尋條件

**請求參數:**
```json
{
  "page": "integer|nullable",
  "limit": "integer|nullable",
  "member_id": "uuid|nullable",
  "search": "string|nullable"
}
```

**回應範例:**
```json
{
  "status": "success",
  "code": 200,
  "message": "Pet admin search success",
  "data": [
    {
      "id": 1,
      "memberId": "member-uuid",
      "categoryId": 1,
      "categoryTitle": "小型犬",
      "sizeId": 2,
      "sizeTitle": "小型",
      "name": "小白",
      "birthday": "2020-01-15",
      "avatar": "https://example.com/avatar.jpg",
      "gender": "male",
      "breed": "貴賓犬",
      "phone": "0912345678",
      "serviceComments": [],
      "petComments": [],
      "questions": {},
      "petQuestions": {},
      "is_assessed": false
    }
  ]
}
```

### GET `/api/admin/merchant/member/{member_id}/pet/{pet_id}`
取得特定寵物資訊

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 限制只能查看自己商家的寵物
- 🔍 查看寵物詳細資訊

**回應範例:**
```json
{
  "status": "success",
  "code": 200,
  "message": "Pet admin get item success",
  "data": {
    "id": 1,
    "memberId": "member-uuid",
    "categoryId": 1,
    "categoryTitle": "小型犬",
    "sizeId": 2,
    "sizeTitle": "小型",
    "name": "小白",
    "birthday": "2020-01-15",
    "avatar": "https://example.com/avatar.jpg",
    "gender": "male",
    "breed": "貴賓犬",
    "phone": "0912345678",
    "serviceComments": [],
    "petComments": [],
    "questions": {},
    "petQuestions": {},
    "is_assessed": false
  }
}
```

### POST `/api/admin/merchant/member/pet/store`
建立/更新寵物

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 🛠️ 建立或修改寵物資料

**請求參數:**
```json
{
  "id": "integer|nullable",
  "member_id": "uuid|required",
  "sizeId": "integer|nullable",
  "name": "string|required",
  "state": "integer|nullable",
  "avatar": "string|nullable",
  "gender": "string|nullable",
  "birthday": "date|nullable",
  "breed": "string|nullable",
  "phone": "string|nullable",
  "questions": "object|nullable",
  "petQuestions": "object|nullable",
  "is_assessed": "boolean|nullable"
}
```

**說明:**
- `is_assessed`: 是否已評估。預設為 `false`
- `id`: 如果提供則為更新，否則為新增

**回應範例:**
```json
{
  "status": "success",
  "code": 200,
  "message": "Pet admin create success",
  "data": {
    "id": 1,
    "memberId": "member-uuid",
    "categoryId": 1,
    "categoryTitle": "小型犬",
    "sizeId": 2,
    "sizeTitle": "小型",
    "name": "小白",
    "birthday": "2020-01-15",
    "avatar": "https://example.com/avatar.jpg",
    "gender": "male",
    "breed": "貴賓犬",
    "phone": "0912345678",
    "serviceComments": [],
    "petComments": [],
    "questions": {},
    "petQuestions": {},
    "is_assessed": false
  }
}
```

### POST `/api/admin/merchant/member/pet/remove`
刪除寵物

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 🗑️ 刪除寵物資料

### GET `/api/admin/merchant/member/{member_id}/pets`
取得會員寵物列表 (index)

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 限制只能查看自己商家的寵物
- 📋 回傳精簡欄位 (ID、名稱、分類、頭像、品種、是否需評估、是否已服務)

**路徑參數:**
- `member_id` (uuid, required): 會員 ID

**回應範例:**
```json
{
  "status": "success",
  "code": 200,
  "message": "Pet admin index success",
  "data": [
    {
      "id": 1,
      "name": "小白",
      "category": {
        "id": 1,
        "title": "小型犬",
        "tags": []
      },
      "avatar": "https://example.com/avatar.jpg",
      "breed": "貴賓犬",
      "isEvaluationRequired": true,
      "hasServiced": false
    },
    {
      "id": 2,
      "name": "黑妞",
      "category": {
        "id": 2,
        "title": "中型犬",
        "tags": []
      },
      "avatar": null,
      "breed": "拉布拉多",
      "isEvaluationRequired": false,
      "hasServiced": true
    }
  ]
}
```

**回應欄位說明:**
- `id` (integer): 寵物 ID
- `name` (string): 寵物名稱
- `category` (object|null): 寵物分類物件（對應到 sizeId，即尺寸分類）
  - `id` (integer): 分類 ID
  - `title` (string): 分類名稱
  - `tags` (array): 分類標籤陣列（從 ancestors 取得的 title 列表）
- `avatar` (string|null): 寵物頭像 URL
- `breed` (string|null): 寵物品種
- `isEvaluationRequired` (boolean): 是否需要評估（true = 需評估，false = 不需評估）
- `hasServiced` (boolean): 是否已服務過

### GET `/api/admin/merchant/member/pet/{pet_id}/service-comments`
取得寵物服務備註 (serviceComments)

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 限制只能查看自己商家的備註
- 🔍 依寵物、訂單篩選服務備註

**路徑參數:**
- `pet_id` (integer, required): 寵物 ID

**請求參數:**
```json
{
  "page": "integer|nullable",
  "limit": "integer|nullable",
  "title": "string|nullable",
  "state": "integer|nullable|in:0,1,-2"
}
```

**回應範例:**
```json
{
  "status": "success",
  "code": 200,
  "message": "Comment admin search success",
  "data": {
    "items": [
      {
        "id": "comment-uuid",
        "orderNo": "20240115001-01",
        "memberId": "member-uuid",
        "petId": 12,
        "type": "service",
        "content": "此寵物毛量多，服務時間需加長。",
        "images": [],
        "questions": {},
        "creator": {
          "id": "user-uuid",
          "avatar": "https://example.com/staff.jpg",
          "name": "美容師小王",
          "email": "staff@example.com"
        },
        "createdAt": "2024-01-15T10:30:00Z",
        "updatedAt": "2024-01-15T11:00:00Z"
      }
    ],
    "pagination": {
      "current_page": 1,
      "last_page": 1,
      "per_page": 20,
      "total": 1
    }
  }
}
```

### GET `/api/admin/merchant/member/pet/{pet_id}/pet-comments`
搜尋寵物備註 (petComments)

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 限制只能查看自己商家的備註
- 🔍 依寵物快速取得備註

**路徑參數:**
- `pet_id` (integer, required): 寵物 ID

**請求參數:**
```json
{
  "page": "integer|nullable",
  "limit": "integer|nullable",
  "title": "string|nullable",
  "state": "integer|nullable|in:0,1,-2"
}
```

**回應範例:**
```json
{
  "status": "success",
  "code": 200,
  "message": "Comment admin search success",
  "data": {
    "items": [
      {
        "id": "comment-uuid",
        "orderNo": null,
        "memberId": "member-uuid",
        "petId": 12,
        "type": "pet",
        "content": "怕吹風機，建議先安撫再開始。",
        "images": [],
        "questions": {},
        "creator": {
          "id": "user-uuid",
          "avatar": null,
          "name": "管理員",
          "email": "admin@example.com"
        },
        "createdAt": "2024-01-10T09:30:00Z",
        "updatedAt": "2024-01-10T09:30:00Z"
      }
    ],
    "pagination": {
      "current_page": 1,
      "last_page": 1,
      "per_page": 20,
      "total": 1
    }
  }
}
```

---

## 服務管理

### POST `/api/admin/service/inventory/add`
新增服務庫存

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 📦 管理服務庫存

### POST `/api/admin/service/inventory/history/search`
搜尋庫存異動記錄

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 限制只能查看自己商家的庫存記錄
- 📊 庫存異動歷史

### GET `/api/admin/service/inventory/history/{id}`
取得特定庫存異動記錄

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 🔍 查看庫存異動詳情

### POST `/api/admin/service/store`
建立/更新服務

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 🛠️ 建立或修改服務項目

### POST `/api/admin/service/remove`
刪除服務

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 🗑️ 刪除服務項目

### POST `/api/admin/service/ordering`
調整服務排序

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 🔢 調整服務顯示順序

### POST `/api/admin/service/search`
搜尋服務

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 限制只能查看自己商家的服務
- 🔍 支援多種搜尋條件

### POST `/api/admin/service/importPrices`
匯入服務價格

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 📊 批量匯入價格資料

### GET `/api/admin/service/{id}`
取得特定服務

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 限制只能查看自己商家的服務
- 🔍 查看服務詳細資訊

### POST `/api/admin/service/syncCategories`
同步服務分類

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 🔄 同步服務分類資料

### POST `/api/admin/service/category/search`
搜尋服務分類

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 限制只能查看自己商家的服務分類
- 🔍 支援多種搜尋條件

**回應範例:**
```json
{
  "status": "success",
  "code": 200,
  "message": "Service category admin search success",
  "data": [
    {
      "id": 1,
      "parentId": null,
      "title": "小型犬",
      "alias": "small-dog",
      "state": 1,
      "type": "cosmetic",
      "level": 0,
      "categoryTitle": "小型犬",
      "params": {},
      "require_assessment": true,
      "children": []
    }
  ]
}
```

### POST `/api/admin/service/category/store`
建立/更新服務分類

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 🛠️ 建立或修改服務分類

**請求參數:**
```json
{
  "id": "integer|nullable",
  "title": "string|required",
  "parentId": "integer|nullable",
  "alias": "string|nullable",
  "type": "string|nullable|in:cosmetic,medical,other",
  "state": "integer|required|in:0,1,-2",
  "introtext": "string|nullable",
  "description": "string|nullable",
  "params": "string|nullable",
  "require_assessment": "boolean|nullable"
}
```

**說明:**
- `require_assessment`: 是否需評估。如果為 `null` 或未傳入，預設為 `true`
- `id`: 如果提供則為更新，否則為新增

**回應範例:**
```json
{
  "status": "success",
  "code": 200,
  "message": "Service category admin create success",
  "data": {
    "id": 1,
    "parentId": null,
    "title": "小型犬",
    "alias": "small-dog",
    "state": 1,
    "type": "cosmetic",
    "level": 0,
    "categoryTitle": "小型犬",
    "introtext": null,
    "description": null,
    "params": {},
    "require_assessment": true
  }
}
```

### POST `/api/admin/service/category/remove`
刪除服務分類（舊版 API）

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 🗑️ 刪除服務分類

### DELETE `/api/admin/service/category/{category_id}`
刪除服務分類（軟刪除）

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 🗑️ 軟刪除服務分類（將 state 設為 -1）
- 🔒 只能刪除自己商家的分類

**路徑參數:**
| 參數名稱 | 類型 | 必填 | 說明 | 範例值 |
|---------|------|------|------|--------|
| `category_id` | integer | ✅ | 分類ID | `1` |

**說明:**
- 此 API 使用軟刪除方式，將分類的 `state` 設為 `-1`
- 刪除後分類仍存在於資料庫中，但不會在正常查詢中顯示
- 只能刪除屬於當前商家的分類，嘗試刪除其他商家的分類會拋出異常

**回應範例:**
```json
{
  "status": "SERVICE_CATEGORY_ADMIN_DELETE_SUCCESS",
  "code": 200,
  "message": "Service category admin delete success",
  "data": null
}
```

**錯誤回應範例（分類不存在）:**
```json
{
  "status": "error",
  "code": 404,
  "message": "No query results for model [DaydreamLab\\Dddream\\Models\\Service\\ServiceCategory]",
  "data": null
}
```

**錯誤回應範例（無權限刪除其他商家的分類）:**
```json
{
  "status": "error",
  "code": 404,
  "message": "No query results for model [DaydreamLab\\Dddream\\Models\\Service\\ServiceCategory]",
  "data": null
}
```

### POST `/api/admin/service/category/import`
匯入服務分類

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 📊 批量匯入服務分類資料

---

## 商家管理

### GET `/api/admin/merchant`
取得商家自身資訊

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 取得當前商家資訊
- 👤 管理員權限查看

**回應範例:**
```json
{
  "id": "merchant-uuid",
  "name": "寵物美容店",
  "i18n": "zh-TW",
  "template": "default",
  "alias": "pet-salon",
  "state": 1,
  "logo": "https://example.com/logo.jpg",
  "image": "https://example.com/banner.jpg",
  "images": [
    "https://example.com/image1.jpg",
    "https://example.com/image2.jpg"
  ],
  "mobileImage": "https://example.com/mobile-banner.jpg",
  "mobileImages": [
    "https://example.com/mobile1.jpg"
  ],
  "aboutUsImage": "https://example.com/about.jpg",
  "country": "台灣",
  "city": "台北市",
  "district": "大安區",
  "address": "復興南路一段123號",
  "email": "info@petsalon.com",
  "description": "專業寵物美容服務",
  "website": "https://petsalon.com",
  "phoneCode": "02",
  "phoneNumber": "12345678",
  "fbFanpageId": "123456789",
  "fbFanpageUrl": "https://facebook.com/petsalon",
  "atmAccountName": "寵物美容店",
  "atmBank": "004-台灣銀行",
  "atmAccount": "1234567890123456",
  "lineId": "@petsalon",
  "lineFriendUrl": "https://line.me/R/ti/p/@petsalon",
  "lineBot": {
    "enabled": true,
    "id": "line_channel_123",
    "secret": "line_secret_456",
    "webhook": "https://webhook.example.com/line"
  },
  "creditCard": {
    "enabled": true,
    "merchantId": "merchant_123"
  },
  "cashflowSetting": 1,
  "paymentMethods": ["Credit", "Atm", "Vacc"],
  "subscriptionState": "active",
  "nextChargeDate": "2024-02-01",
  "canUpgrade": 1,
  "ga": "UA-123456789-1",
  "tax": {
    "type": "business",
    "title": "寵物美容店",
    "id": "12345678"
  },
  "plan": {
    "alias": "premium",
    "title": "進階版",
    "price": 2000
  },
  "merchantConfig": {},
  "aboutUs": "我們是專業的寵物美容團隊",
  "aboutUsImages": [],
  "brandConcept": "以愛為出發點",
  "brandConceptImages": [],
  "brandPersist": "堅持品質",
  "brandService": "優質服務",
  "brandMission": "讓每隻寵物都美美的",
  "brandQuality": "最佳品質保證",
  "teamInfo": "專業團隊介紹",
  "awardHistory": "獲獎經歷",
  "invoiceSetting": 1,
  "guest": {
    "allowGuest": false
  }
}
```

### POST `/api/admin/merchant/register`
註冊新商家

**中介層:** `SuperAdmin`, `expired`
- 🔑 純超級管理員權限 (系統級操作)
- ⏰ 檢查系統狀態
- 🏢 建立新商家

### GET `/api/admin/merchant/userGroups`
取得商家使用者群組

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 查看商家使用者群組設定
- 👥 權限群組管理

### POST `/api/admin/merchant/user/search`
搜尋商家使用者

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 限制只能查看自己商家的使用者
- 👤 使用者管理

### POST `/api/admin/merchant/search`
搜尋商家

**中介層:** `SuperAdmin`, `expired`
- 🔑 純超級管理員權限
- 🏢 系統級商家管理

### POST `/api/admin/merchant/store`
更新商家資訊

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- ✏️ 更新商家基本資訊

**請求參數 (主要欄位):**
```json
{
  "name": "string|nullable",
  "logo": "string|nullable",
  "images": "array|nullable",
  "mobileImages": "array|nullable", 
  "country": "string|nullable",
  "city": "string|nullable",
  "district": "string|nullable",
  "address": "string|nullable",
  "website": "url|nullable",
  "phoneCode": "string|nullable|regex:/^\\+[0-9]+$/",
  "phoneNumber": "string|nullable",
  "email": "email|nullable",
  "description": "string|nullable",
  "lineBot": "array|nullable",
  "paymentMethods": "array|nullable"
}
```

### POST `/api/admin/merchant/setting`
取得商家設定

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 取得商家各項設定
- ⚙️ 設定管理

### POST `/api/admin/merchant/setting/store`
儲存商家設定

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- ⚙️ 更新商家設定

### POST `/api/admin/merchant/media/upload`
上傳商家媒體檔案

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 📁 上傳商家相關圖片

### POST `/api/admin/merchant/media/delete`
刪除商家媒體檔案

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 🗑️ 刪除商家媒體檔案

### GET `/api/admin/merchant/config`
取得商家配置

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 取得商家系統配置
- ⚙️ 系統設定查看

---

## 排程管理

### POST `/api/admin/schedule/item/linkUser`
連結使用者到排班項目

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 👤 連結使用者與排班項目

### POST `/api/admin/schedule/item/store`
建立/更新排班項目

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 📅 管理排班項目

### POST `/api/admin/schedule/item/search`
搜尋排班項目

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 限制只能查看自己商家的排班
- 📅 排班項目列表

### POST `/api/admin/schedule/item/search/order`
搜尋排班項目的預約

**中介層:** `hasMerchant`, `expired`, `admin`, `isStaff`
- 🏢 驗證商家管理員身份
- ⏰ 檢查商家訂閱是否過期  
- 👤 驗證管理員權限
- 👷 員工身份驗證，排班人員只能查看自己的預約

### POST `/api/admin/schedule/item/import`
匯入排班項目

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 📊 批量匯入排班資料

### POST `/api/admin/schedule/item/archived`
封存排班項目

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 📦 封存不再使用的排班項目

### POST `/api/admin/schedule/item/{id}`
取得特定排班項目

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 限制只能查看自己商家的排班
- 🔍 查看排班項目詳情

### POST `/api/admin/schedule/calendar/addScheduleItem`
新增排程項目到日曆

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 📅 新增排程到日曆

### POST `/api/admin/schedule/calendar/deleteScheduleItem`
從日曆刪除排程項目

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 🗑️ 從日曆移除排程

### POST `/api/admin/schedule/calendar/{date}`
取得特定日期的排程

**中介層:** `hasMerchant`, `expired`, `admin`, `isStaff`
- 🏢 驗證商家管理員身份
- ⏰ 檢查商家訂閱狀態
- 👤 驗證管理員權限
- 👷 員工身份驗證

### POST `/api/admin/schedule/calendar/search/monthly`
取得月份排程日曆

**中介層:** `hasMerchant`, `expired`, `admin`, `isStaff`
- 🏢 驗證商家管理員身份
- ⏰ 檢查商家訂閱狀態
- 👤 驗證管理員權限
- 👷 員工身份驗證

### POST `/api/admin/schedule/calendar/search/availablePeriod`
檢查排程可移動性

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- ⏰ 檢查時段可用性

---

## 排程詳情管理

### GET `/api/admin/schedule/calendar/detail/{id}`
取得排程詳情

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 限制只能查看自己商家的排程詳情
- 🔍 查看特定排程的詳細資訊

### POST `/api/admin/schedule/calendar/detail/store`
建立/更新排程詳情

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 📝 建立或修改排程詳情

### POST `/api/admin/schedule/calendar/detail/remove`
刪除排程詳情

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 🗑️ 刪除指定排程詳情

---

## 數據分析

### POST `/api/admin/analytic/income`
收入分析

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 限制只能查看自己商家的收入數據
- 📊 收入統計分析

**請求參數:**
```json
{
  "startDate": "date|required",
  "endDate": "date|required", 
  "groupBy": "string|nullable|in:day,week,month",
  "storeId": "uuid|nullable"
}
```

### POST `/api/admin/analytic/sales`
銷售分析

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 限制只能查看自己商家的銷售數據
- 📈 銷售統計分析

**請求參數 `type`（必填）:** `order` | `service` | `prepaid` | `serviceAdd` | `hotel`

- **`order`（預設情境）:** 回傳依訂單類型之區塊（主訂單、加購訂單、包月方案、儲值金等，與商家方案相同）。**「住宿訂單」區塊**與「儲值金」相同為可選：僅當商家方案內含 **hotel** 模組（`merchantPlan.assets` 含 `hotel`）時，才於陣列尾端附加住宿銷售明細。
- **`hotel`:** 僅回傳**住宿訂單**單一區塊，供篩選／僅檢視住宿時使用。

### POST `/api/admin/analytic/coupon`
優惠券分析

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 限制只能查看自己商家的優惠券數據
- 🎫 優惠券使用統計

### POST `/api/admin/analytic/scheduleItem`
排班項目分析

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 限制只能查看自己商家的排班數據
- 👷 排班項目績效分析

---

## 金流管理

### POST `/api/admin/merchant/cashflow/add`
申請金流服務

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 💳 申請金流服務

### POST `/api/merchant/paymentflow/callback`
金流申請回調

**中介層:** 無 (金流系統回調)

### POST `/api/cashflow/modify`
修改金流設定

**中介層:** `SuperAdmin`
- 🔑 純超級管理員權限
- 💳 修改商家金流設定

---

## 系統管理

### POST `/api/admin/merchant/component/{alias}/install`
安裝商家組件

**中介層:** `SuperAdmin`, `expired`
- 🔑 純超級管理員權限 (系統級操作)
- ⏰ 檢查系統狀態

### POST `/api/admin/merchant/module/{alias}/install`
安裝商家模組

**中介層:** `SuperAdmin`, `expired`
- 🔑 純超級管理員權限 (系統級操作)
- ⏰ 檢查系統狀態
- 🔧 安裝系統模組功能

### POST `/api/testEmail`
測試 Email 發送

**中介層:** 無 (測試功能)

### GET `source-chart`
取得來源統計圖表

**中介層:** 無 (公開統計資料)

**說明:** 
- 提供系統來源統計數據
- 用於生成統計圖表
- 不需要認證即可存取

### GET `/api/cancelAuth/{id}`
取消授權

**中介層:** `SuperAdmin`, `expired`
- 🔑 純超級管理員權限
- ❌ 取消系統授權

### POST `/api/queryTradeInfo`
查詢交易資訊

**中介層:** `SuperAdmin`, `expired`
- 🔑 純超級管理員權限
- 💳 查詢金流交易資訊

### POST `/api/smsQuery`
查詢簡訊

**中介層:** `SuperAdmin`, `expired`
- 🔑 純超級管理員權限
- 📱 查詢簡訊發送記錄

### GET `/api/reIssueInvoice/{id}`
重新開立發票

**中介層:** `SuperAdmin`
- 🔑 純超級管理員權限
- 🧾 重新開立發票

### GET `/api/clearMerchant/{merchantAlias}`
清除商家資料

**中介層:** `SuperAdmin`, `expired`
- 🔑 純超級管理員權限 (高危險操作)
- ⚠️ 不可逆的資料清除操作
- 🗑️ 完整移除商家所有相關資料

### GET `/api/closeMerchant/{merchantAlias}`
關閉商家

**中介層:** `SuperAdmin`, `expired`
- 🔑 純超級管理員權限
- 🔒 關閉商家營運

### POST `/api/unbindLineNotify`
解綁 LINE Notify

**中介層:** `SuperAdmin`, `expired`
- 🔑 純超級管理員權限
- 📲 解綁 LINE Notify 服務

### GET `/api/admin/push/refreshEvent`
刷新推播事件

**中介層:** `SuperAdmin`, `expired`
- 🔑 純超級管理員權限
- 🔄 刷新推播事件

### POST `/api/admin/push/systemPost`
系統推播

**中介層:** `SuperAdmin`, `expired`
- 🔑 純超級管理員權限
- 📢 發送系統推播

---

## Admin 中介層說明

### `hasMerchant`
**功能**: 驗證商家管理員權限
- 檢查使用者是否已登入且非會員身份
- 驗證使用者是否擁有商家權限
- **超級管理員特殊處理**:
  - 可指定要管理的商家 ID
  - 無指定商家時 merchant 為 null
- **商家狀態檢查**:
  - 檢查商家是否存在
  - 檢查商家是否已綁定信用卡 (site 來源)
  - 檢查商家訂閱是否過期
- **權限限制**:
  - 未綁卡時只能存取特定 API (商家資訊、方案購買)
  - 訂閱過期時只能存取續約相關 API
- 將商家和使用者資訊注入到請求中
- **失敗回應**: `UserUnauthorized`, `MerchantAdminMerchantInfoIsEmpty`, `MerchantFrontPleaseBindCardFirst`, `MerchantFrontPleaseRenewSubscription`

### `isStaff`
**功能**: 驗證員工身份並處理排班人員
- 檢查使用者是否已登入且非會員身份
- **排班人員特殊處理**:
  - 如果使用者只屬於「排班人員」群組
  - 自動注入該員工的排班項目 ID (`$request['scheduleItemId']`)
  - 用於限制員工只能查看自己的排班和訂單
- **失敗回應**: `UserUnauthorized`

### `SuperAdmin`
**功能**: 驗證超級管理員權限
- 檢查使用者是否已登入且非會員身份
- 驗證使用者 Token 的 `isSuperUser` 標記
- **重要限制**: 確保是純超級管理員身份，不能是模擬商家的狀態
  - `isSuperUser = true` 且 `merchant_id = null`
- 將 merchant 設為 null，user 注入到請求中
- **失敗回應**: `UserUnauthorized`, `UserInsufficientPermission`

### `MerchantObserver`
**功能**: 超級管理員模擬商家身份
- 檢查使用者是否為超級管理員
- **特殊用途**: 允許超級管理員以特定商家身份操作
- 驗證條件: `isSuperUser = true` 且 `merchant_id` 存在
- 載入指定的商家資訊並注入到請求中
- 用於超級管理員需要以商家身份進行操作的場景
- **失敗回應**: `UserUnauthorized`, `UserInsufficientPermission`, `MerchantItemNotExist`

### `CodeScope`
**功能**: 會員一次性代碼驗證
- 驗證 URL 中的特定代碼參數
- 檢查代碼是否存在於 `merchants_members_codes` 表中
- **範圍驗證**: 檢查當前路由是否在代碼允許的範圍內
- 代碼範圍以逗號分隔，支援多個路由路徑
- 將代碼資訊注入到請求中
- **失敗行為**: 重導向到首頁 (`/`)

### `admin`
**功能**: 基礎管理員權限檢查
- 由 Laravel 框架或其他套件提供
- 檢查使用者是否具有管理員權限

### `expired`
**功能**: 檢查商家訂閱狀態
- 驗證商家訂閱是否過期
- 過期時限制 API 存取權限

---

## 混合式標籤管理

### POST `/api/admin/mixtag/store`
建立混合式標籤

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 🏷️ 建立可跨模組使用的標籤

### POST `/api/admin/mixtag/search`
搜尋混合式標籤

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 限制只能查看自己商家的標籤
- 🔍 支援標籤搜尋和篩選

### POST `/api/admin/mixtag/remove`
刪除混合式標籤

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 🗑️ 刪除指定的混合式標籤

### POST `/api/admin/mixtag/apply`
套用混合式標籤

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 🏷️ 將標籤套用到指定項目

---

## 優惠券管理

### GET `/api/admin/coupon`
檢查優惠券代碼可用性

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- ✅ 檢查優惠券代碼是否已存在

### POST `/api/admin/coupon/store`
建立/更新優惠券

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 🎫 建立或修改優惠券

### POST `/api/admin/coupon/remove`
刪除優惠券

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 🗑️ 刪除指定優惠券

### POST `/api/admin/coupon/state`
更新優惠券狀態

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 🔄 啟用或停用優惠券

### POST `/api/admin/coupon/search`
搜尋優惠券

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 限制只能查看自己商家的優惠券
- 🔍 支援多種搜尋條件

### GET `/api/admin/coupon/{id}`
取得特定優惠券

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 限制只能查看自己商家的優惠券
- 🔍 查看優惠券詳細資訊

### GET `/api/admin/coupon/{id}/orders`
取得優惠券使用訂單

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 📋 查看優惠券使用記錄

### POST `/api/admin/coupon/send`
發送優惠券

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 📧 發送優惠券給會員

---

## 推播管理

### GET `/api/admin/push/read/{id}`
標記推播為已讀

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- ✅ 標記推播通知為已讀

### POST `/api/admin/push/search`
搜尋推播通知

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 限制只能查看自己商家的推播通知
- 🔍 推播通知列表

### POST `/api/admin/push/clear`
清除推播通知

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 🗑️ 清除推播通知

### POST `/api/admin/device/register`
註冊推播裝置

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 📱 註冊推播裝置

### POST `/api/admin/device/delete`
刪除推播裝置

**中介層:** `hasMerchant`, `expired`, `admin`
- 🏢 驗證商家管理員身份
- 🗑️ 移除推播裝置

---

## 回應格式

所有 API 回應都遵循統一格式：

### 成功回應
```json
{
  "status": "success",
  "code": 200,
  "message": "操作成功",
  "data": {
    // 回應資料
  }
}
```

### 錯誤回應
```json
{
  "status": "error",
  "code": 400,
  "message": "錯誤訊息",
  "data": {
    "details": {}
  }
}
```

### 分頁回應
```json
{
  "status": "success",
  "code": 200,
  "message": "搜尋成功",
  "data": {
    "items": [],
    "pagination": {
      "current_page": 1,
      "total_pages": 10,
      "total_items": 100,
      "per_page": 10
    }
  }
}
```

---

## 常見錯誤代碼

- `VALIDATION_ERROR`: 驗證錯誤
- `UNAUTHORIZED`: 未授權
- `FORBIDDEN`: 禁止存取
- `UserUnauthorized`: 使用者未授權
- `UserInsufficientPermission`: 使用者權限不足
- `MerchantAdminMerchantInfoIsEmpty`: 商家資訊為空
- `MerchantFrontPleaseBindCardFirst`: 請先綁定信用卡
- `MerchantFrontPleaseRenewSubscription`: 請續約訂閱
- `MerchantItemNotExist`: 商家不存在

---

## Admin 中介層快速參考

| 圖示 | 中介層 | 功能說明 | 使用場景 |
|------|--------|----------|----------|
| 🏢 | `hasMerchant` | 商家管理員權限驗證 | 後台管理功能 |
| ⏰ | `expired` | 商家訂閱狀態檢查 | 防止過期商家使用 |
| 👤 | `admin` | 基礎管理員權限 | 管理功能存取 |
| 👷 | `isStaff` | 員工身份驗證 | 員工專屬功能 |
| 🔑 | `SuperAdmin` | 超級管理員權限 | 系統級管理操作 |
| 🔄 | `MerchantObserver` | 超管模擬商家身份 | 代理商家操作 |
| 🎫 | `CodeScope` | 一次性代碼驗證 | 特殊存取權限 |

### 常用組合快速索引

- **🏢⏰👤** = 標準商家管理
- **🏢⏰👤👷** = 員工操作
- **🔑⏰** = 系統管理
- **🏢⏰🔑** = 高權限商家操作

---

## 版本資訊

- **API 版本**: v1
- **文件類型**: Admin API (後台)
- **最後更新**: 2024年
- **相容性**: Laravel 8+, PHP 7.4+

---

*此文件基於 DDDream 套件的 Admin API 自動生成，如有疑問請聯繫開發團隊。*
