From 8ee14eaa29cc8bb980022d8829526d360006a00b Mon Sep 17 00:00:00 2001 From: sky121113 Date: Wed, 11 Mar 2026 17:37:05 +0800 Subject: [PATCH] =?UTF-8?q?[DOCS]=20=E6=96=B0=E5=A2=9E=E4=B8=A6=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=20Phase=201=20=E6=A0=B8=E5=BF=83=E6=A9=9F=E5=8F=B0?= =?UTF-8?q?=E9=80=9A=E8=A8=8A=20API=20=E6=8A=80=E8=A1=93=E8=A6=8F=E7=AF=84?= =?UTF-8?q?=E6=96=87=E4=BB=B6=20(B010~B710)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/api_analysis.md | 474 +++++++++++++++++++++++++++ docs/architecture_plan.md | 627 ++++++++++++++++++++++++++++++++++++ docs/b010_technical_spec.md | 89 +++++ docs/b017_technical_spec.md | 65 ++++ docs/b055_technical_spec.md | 55 ++++ docs/b220_technical_spec.md | 51 +++ docs/b600_technical_spec.md | 52 +++ docs/b601_technical_spec.md | 49 +++ docs/b602_technical_spec.md | 50 +++ docs/b650_technical_spec.md | 46 +++ docs/b710_technical_spec.md | 49 +++ docs/rbac_architecture.md | 55 ++++ 12 files changed, 1662 insertions(+) create mode 100644 docs/api_analysis.md create mode 100644 docs/architecture_plan.md create mode 100644 docs/b010_technical_spec.md create mode 100644 docs/b017_technical_spec.md create mode 100644 docs/b055_technical_spec.md create mode 100644 docs/b220_technical_spec.md create mode 100644 docs/b600_technical_spec.md create mode 100644 docs/b601_technical_spec.md create mode 100644 docs/b602_technical_spec.md create mode 100644 docs/b650_technical_spec.md create mode 100644 docs/b710_technical_spec.md create mode 100644 docs/rbac_architecture.md diff --git a/docs/api_analysis.md b/docs/api_analysis.md new file mode 100644 index 0000000..3add800 --- /dev/null +++ b/docs/api_analysis.md @@ -0,0 +1,474 @@ +# Star Cloud API 分析與資料庫結構整理 + +> 基於 `docs/API/` 中 12 個 PDF 文件的完整分析,整理出 API 端點清單、資料流向及推導出的資料庫結構。 + +--- + +## 一、API 端點總覽 + +| 代碼 | 名稱 | URL | Method | 說明 | +|------|------|-----|--------|------| +| B010 | 機台狀態上傳 & 指令撈回 | `/api/app/machine/status/{workid}` | POST | 機台定期心跳上報(狀態、溫度、門禁、版本),並撈回遠端指令。詳見 [b010_technical_spec.md](file:///home/mama/projects/star-cloud/docs/b010_technical_spec.md) | +| B017 | 遠端改庫存 | `/api/app/machine/reload_msg/{workid}` | POST | 機台撈取最新貨道庫存數量。詳見 [b017_technical_spec.md](file:///home/mama/projects/star-cloud/docs/b017_technical_spec.md) | +| B055 | 遠端出貨(取得指令) | `/api/app/machine/dispense/{workid}` | POST | 機台撈取遠端出貨指令列表。詳見 [b055_technical_spec.md](file:///home/mama/projects/star-cloud/docs/b055_technical_spec.md) | +| B055 | 遠端出貨(狀態回傳) | `/api/app/machine/dispense/{workid}` | PUT | 機台回報出貨結果(成功/失敗)及剩餘庫存。詳見 [b055_technical_spec.md](file:///home/mama/projects/star-cloud/docs/b055_technical_spec.md) | +| B220 | 零錢機庫存變動回傳 | `/api/app/coin/inventory/B220` | POST | 零錢機各面額庫存回傳(1/5/10/50/100/500/1000 元)。詳見 [b220_technical_spec.md](file:///home/mama/projects/star-cloud/docs/b220_technical_spec.md) | +| B600 | 消費金流回傳 | `/api/app/B600` | POST | 消費交易核心 API — 記錄金流類型、金額、商品、發票、會員等。詳見 [b600_technical_spec.md](file:///home/mama/projects/star-cloud/docs/b600_technical_spec.md) | +| B601 | 發票資訊回傳 | `/api/app/B601` | POST | 開立發票後回傳發票號碼、日期、隨機碼等。詳見 [b601_technical_spec.md](file:///home/mama/projects/star-cloud/docs/b601_technical_spec.md) | +| B602 | 出貨回傳 | `/api/app/B602` | POST | 出貨結果回傳(商品、貨道、金額、庫存、會員條碼等)。詳見 [b602_technical_spec.md](file:///home/mama/projects/star-cloud/docs/b602_technical_spec.md) | +| B650 | 驗證會員 | `/api/app/B650` | POST | 會員驗證(點數折抵、優惠券、取貨碼、線上訂單線下取貨等)。詳見 [b650_technical_spec.md](file:///home/mama/projects/star-cloud/docs/b650_technical_spec.md) | +| B710 | 計時器狀態回傳 | `/api/app/B710` | POST | 計時型機台的貨道使用狀態與倒數秒數回傳。詳見 [b710_technical_spec.md](file:///home/mama/projects/star-cloud/docs/b710_technical_spec.md) | + +--- + +## 二、API 詳細分析 + +### 2.1 B010 — 機台狀態上傳 & 指令撈回 + +**用途**:機台定期向 Cloud 回報自身狀態,Cloud 透過 response 中的 `status` 碼下發遠端指令。 + +**Request 欄位**: + +| 欄位 | 說明 | +|------|------| +| `key` | API 金鑰 (`KahnEwjhfDBHUYS7`) | +| `machine` | 機台序號 | +| `door` | 門禁狀態(非必填) | +| `temperature` | 溫度 | +| `M_Stus` | 機台型號(非必填) | +| `M_Stus2` | 當前頁面狀態碼 | +| `M_Ver` | 當前軟體版本 | + +**頁面狀態碼 (M_Stus2)**: +- `0`: 離線, `1`: 主頁面, `2`: 販賣頁, `3`: 管理頁, `4`: 補貨頁, `5`: 教學頁 +- `6`: 購買中, `7`: 鎖定頁, `60`: 出貨成功, `61`: 貨道測試, `62`: 付款選擇 +- `63`: 等待付款, `64`: 出貨, `65`: 收據簽單, `66`: 通行碼, `67`: 取貨碼 +- `68`: 訊息顯示, `69`: 取消購買, `610`: 購買結束, `611`: 來店禮, `612`: 出貨失敗 + +**遠端指令碼 (Response status)**: +- `49`: reload B017 (重新載入庫存), `50`: reload B005, `51`: reboot (重啟) +- `60`: reboot card machine, `61`: checkout, `70`: unlock, `71`: lock +- `72`: sellCode reload B023, `75`: exp reload B026, `79`: read B050 +- `81`: sync timer status (B710), `85`: reload B055 (遠端出貨) + +--- + +### 2.2 B600 — 消費金流回傳(核心交易 API) + +**用途**:記錄每筆消費交易的完整資訊,為最核心的銷售數據 API。 + +**Request 欄位**: + +| 欄位 | 參數名 | 說明 | 類型 | +|------|--------|------|------| +| req1 | key | API 金鑰 | String | +| req2 | machine | 機台編號 | String | +| req3 | payment_type | 金流類型代碼 | String | +| req4 | payment_request | 金流送出 data | String | +| req5 | payment_response | 金流回傳 data | String | +| req6 | product_id | 商品 ID | String | +| req7 | amount | 消費金額 | String | +| req8 | invoice_info | 發票歸戶資訊(統編-電話) | String | +| req9 | order_no | APP 定義訂單編號 | String | +| req10 | member_barcode | 掃會員得到的條碼 | String | +| req11 | machine_time | 機台時間 | String | +| req12 | status | 金流狀態 (0: 失敗, 1: 成功, 2: 50 結帳) | String | +| req13 | change_amount | 找零金額 | String | +| req14 | points_used | 使用的點數 | String | +| req15 | reserved | 系統保留 | String | +| req16 | items | 商品明細 `[{pid, amount, num}]` | JsonArray | + +**金流類型 (req3) 完整對照**: + +| 代碼 | 說明 | +|------|------| +| 1 | 信用卡 | +| 2 | 悠遊卡/一卡通 | +| 3 | 掃碼支付 | +| 4 | 手機支付 | +| 5 | 通行碼 | +| 6 | 取貨碼 | +| 7 | 來店禮 | +| 8 | 問卷 | +| 9 | 零錢 | +| 21-25 | 線下付款 + (1/2/3/4/9) | +| 30-34 | TapPay (Line/街口/悠遊付/Pi/全盈+) | +| 40 | 會員驗證取貨商品 | +| 41 | 線上訂單線下結帳 | +| 50-54 | 線下付款 + TapPay 系列 | +| 60 | 點數/優惠券全額折抵 | +| 61-64, 69 | 會員 + (1/2/3/4/9) | +| 70 | 官方 LinePay | +| 90-94 | 會員 + TapPay 系列 | +| 101-109 | 大豐環保點數 + 消費 | +| 110-114, 120 | 大豐環保 + TapPay/LinePay | + +--- + +### 2.3 B650 — 驗證會員 + +**驗證類型 (req6)**: + +| req6 | 說明 | Response 特殊欄位 | +|------|------|--------------------| +| 0 | 有點擊商品的驗證 | `userToken`, `amount`, `point`, `respondMSG` | +| 1 | 會員純驗證 | 基本驗證回應 | +| 2 | 會員兌換商品列表 | `productList[{pId, pName, token, validityPeriod, num}]` | +| 3 | 線上訂單線下結帳 | `orderUrl`, `orderNumber`, `orderAmount` | +| 4 | 會員贈品 | — | + +**Response 狀態碼**: +- `100`: 成功 — 無可用點數 +- `101`: 成功 — 全額折抵(點數或優惠券) +- `102`: 成功 — 部分折抵 +- `103`: 取貨碼驗證成功 +- `104`: 線上訂單驗證成功 +- `21`: Key Error, `22`: Time Error, `23`: User Token Error +- `25`: 會員平台錯誤, `30`: 會員正在其他機台使用中 +- `35`: 無效優惠券, `40`: 已兌換過, `41`: 無效訂單, `42`: 取貨碼錯誤 + +--- + +## 三、資料庫結構推導 + +根據以上 API 的欄位分析,以下是系統需要的**完整資料庫結構**: + +### 🟢 已存在的資料表(比對現有 migration) + +| 資料表 | 說明 | 對應 API | +|--------|------|----------| +| `users` | 後台管理員 | — | +| `machines` | 機台基本資料 | B010, B017, B055, B220, B600, B602 | +| `machine_logs` | 機台日誌 | B010 | +| `app_configs` | APP 設定 | — | +| `members` | 會員資料 | B650 | +| `social_accounts` | 社群帳號 | B650 | +| `member_wallets` | 會員錢包 | B650 | +| `wallet_transactions` | 錢包交易 | B600, B650 | +| `member_points` | 點數帳戶 | B650 | +| `point_transactions` | 點數異動 | B650, B600 | +| `point_rules` | 點數規則 | B650 | +| `membership_tiers` | 會員等級 | — | +| `member_memberships` | 會員等級紀錄 | — | +| `gift_definitions` | 禮品定義 | — | +| `member_gifts` | 禮品發放 | — | +| `deposit_bonus_rules` | 儲值回饋規則 | — | + +### 🔴 需新增的資料表 + +以下是從 API 欄位推導出**目前資料庫中缺少**,但系統運作所必需的資料表: + +--- + +#### 1. `products` — 商品資料 + +> 來源:B600 (req6, req16), B602 (req5), B650 (productList), B710 (pid) + +``` +products +├── id BIGINT PK +├── name VARCHAR 商品名稱 +├── price DECIMAL(10,2) 售價 +├── cost DECIMAL(10,2) 成本(選填) +├── category_id BIGINT FK 分類(選填) +├── image VARCHAR 商品圖片 URL +├── barcode VARCHAR 商品條碼 +├── description TEXT 商品描述 +├── is_active BOOLEAN 是否上架 +├── created_at TIMESTAMP +└── updated_at TIMESTAMP +``` + +--- + +#### 2. `machine_slots` — 機台貨道 + +> 來源:B017 (tid, num), B055 (res2), B602 (req6, req9), B710 (cid) + +``` +machine_slots +├── id BIGINT PK +├── machine_id BIGINT FK → machines +├── slot_no VARCHAR 貨道編號 (tid/cid) +├── product_id BIGINT FK → products(可空) +├── stock INT 當前庫存數量 +├── max_stock INT 最大容量 +├── is_active BOOLEAN 是否啟用 +├── created_at TIMESTAMP +└── updated_at TIMESTAMP +``` + +--- + +#### 3. `orders` — 訂單(消費紀錄主表) + +> 來源:B600 (核心), B601, B602 + +``` +orders +├── id BIGINT PK +├── order_no VARCHAR UNIQUE APP 定義訂單編號 (req9) +├── machine_id BIGINT FK → machines (req2) +├── member_id BIGINT FK → members(可空) +├── payment_type TINYINT 金流類型代碼 (req3) +├── total_amount DECIMAL(10,2) 消費金額 (req7) +├── change_amount DECIMAL(10,2) 找零金額 (req13) +├── points_used INT 使用的點數 (req14) +├── discount_amount DECIMAL(10,2) 折扣前金額 (req15) +├── payment_status TINYINT 金流狀態 (req12: 0失敗/1成功/2:50結帳) +├── payment_request TEXT 金流送出 data (req4) +├── payment_response TEXT 金流回傳 data (req5) +├── member_barcode VARCHAR 會員條碼 (req10) +├── invoice_info VARCHAR 發票歸戶資訊 (req8) +├── machine_time DATETIME 機台時間 (req11) +├── flow_id VARCHAR Cloud 回傳的金流 ID (B600 response message) +├── created_at TIMESTAMP +└── updated_at TIMESTAMP +``` + +--- + +#### 4. `order_items` — 訂單明細 + +> 來源:B600 (req16: `[{pid, amount, num}]`) + +``` +order_items +├── id BIGINT PK +├── order_id BIGINT FK → orders +├── product_id BIGINT FK → products (pid) +├── quantity INT 數量 (num) +├── unit_price DECIMAL(10,2) 單價 (amount) +├── subtotal DECIMAL(10,2) 小計 +├── created_at TIMESTAMP +└── updated_at TIMESTAMP +``` + +--- + +#### 5. `invoices` — 發票紀錄 + +> 來源:B601 + +``` +invoices +├── id BIGINT PK +├── order_id BIGINT FK → orders(透過 flow_id 關聯) +├── flow_id VARCHAR B600 回傳的金流 ID (req3) +├── machine_id BIGINT FK → machines (req2) +├── rtn_code VARCHAR 發票回傳碼 (req4) +├── rtn_msg VARCHAR 發票回傳訊息 (req5) +├── invoice_no VARCHAR 發票號碼 (req6) +├── invoice_date DATE 發票日期 (req7) +├── random_number VARCHAR 隨機碼 (req8) +├── love_code VARCHAR 愛心碼 (req9) +├── business_tax_id VARCHAR 公司統編 (新增) +├── carrier_id VARCHAR 載具編號 (新增) +├── carrier_type VARCHAR 載具類型 (新增) +├── status TINYINT 發票狀態 (1:有效, 0:作廢) +├── created_at TIMESTAMP +└── updated_at TIMESTAMP +``` + +--- + +#### 6. `dispense_records` — 出貨紀錄 + +> 來源:B602, B055 + +``` +dispense_records +├── id BIGINT PK +├── order_id BIGINT FK → orders(透過 flow_id 關聯) +├── flow_id VARCHAR 金流 ID (req3) +├── machine_id BIGINT FK → machines (req2) +├── product_id BIGINT FK → products (req5) +├── slot_no VARCHAR 貨道編號 (req6) +├── amount DECIMAL(10,2) 消費金額 (req7) +├── remaining_stock INT 貨道剩餘庫存 (req9) +├── member_barcode VARCHAR 會員條碼 (req10) +├── machine_time DATETIME 機台時間 (req11) +├── coupon_order_no VARCHAR 商品券訂單編號 (req12) +├── dispense_status TINYINT 出貨狀態 (req13: 0成功/1失敗) +├── original_price DECIMAL(10,2) 折扣前金額 (req15) +├── points_used INT 使用的點數 (req16) +├── created_at TIMESTAMP +└── updated_at TIMESTAMP +``` + +--- + +#### 7. `remote_dispense_commands` — 遠端出貨指令 + +> 來源:B055 + +``` +remote_dispense_commands +├── id BIGINT PK +├── machine_id BIGINT FK → machines +├── command_id VARCHAR 執行命令 ID (res1) +├── slot_no VARCHAR 貨道 ID (res2) +├── status TINYINT 狀態 (0: 待執行, 1: 出貨成功, 2: 出貨失敗) +├── remaining_stock INT 出貨後剩餘庫存 +├── created_at TIMESTAMP +└── updated_at TIMESTAMP +``` + +--- + +#### 8. `coin_inventory_logs` — 零錢機庫存紀錄 + +> 來源:B220 + +``` +coin_inventory_logs +├── id BIGINT PK +├── machine_id BIGINT FK → machines +├── value_1 INT 1 元庫存 +├── value_5 INT 5 元庫存 +├── value_10 INT 10 元庫存 +├── value_50 INT 50 元庫存 +├── value_100 INT 100 元庫存 +├── value_500 INT 500 元庫存 +├── value_1000 INT 1000 元庫存 +├── account VARCHAR 操作人帳號 (0=消費者) +├── created_at TIMESTAMP +└── updated_at TIMESTAMP +``` + +--- + +#### 9. `timer_statuses` — 計時器狀態 + +> 來源:B710 + +``` +timer_statuses +├── id BIGINT PK +├── machine_id BIGINT FK → machines +├── slot_no VARCHAR 貨道 ID (cid) +├── product_id BIGINT FK → products (pid, 0=未設定) +├── status TINYINT 狀態 (0: 未啟用, 1: 使用中, 2: 異常) +├── remaining_seconds INT 剩餘秒數 (num) +├── created_at TIMESTAMP +└── updated_at TIMESTAMP +``` + +--- + +#### 10. `payment_types` — 金流類型參照表(建議) + +> 來源:B600 req3 的龐大對照表 + +``` +payment_types +├── id BIGINT PK +├── code INT UNIQUE 金流類型代碼 +├── name VARCHAR 名稱(中文) +├── category VARCHAR 分類(信用卡/電子票證/行動支付/TapPay/會員/環保點數...) +├── is_active BOOLEAN 是否啟用 +├── created_at TIMESTAMP +└── updated_at TIMESTAMP +``` + +--- + +## 四、ER 關係圖 + +```mermaid +erDiagram + machines ||--o{ machine_slots : "擁有" + machines ||--o{ machine_logs : "產生" + machines ||--o{ orders : "交易於" + machines ||--o{ coin_inventory_logs : "零錢記錄" + machines ||--o{ timer_statuses : "計時器" + machines ||--o{ remote_dispense_commands : "遠端指令" + + products ||--o{ machine_slots : "放置於" + products ||--o{ order_items : "被購買" + products ||--o{ timer_statuses : "計時商品" + + orders ||--o{ order_items : "包含" + orders ||--o| invoices : "開立" + orders ||--o{ dispense_records : "出貨" + orders }o--o| members : "消費者" + orders }o--|| payment_types : "付款方式" + + members ||--o{ social_accounts : "社群綁定" + members ||--o| member_wallets : "錢包" + members ||--o| member_points : "點數" + members ||--o{ member_memberships : "會員等級" + members ||--o{ member_gifts : "禮品" + + member_wallets ||--o{ wallet_transactions : "異動" + member_points ||--o{ point_transactions : "異動" + membership_tiers ||--o{ member_memberships : "對應等級" + gift_definitions ||--o{ member_gifts : "對應禮品" +``` + +--- + +## 五、API 資料流向圖 + +``` +┌─────────────┐ +│ 機台 (APP) │ +└──────┬──────┘ + │ + ├── B010 ──► 心跳上報 ──► machine_logs(狀態/溫度/版本) + │ ◄── 返回遠端指令碼 + │ + ├── B017 ──► 撈取庫存 ──► machine_slots(最新貨道數量) + │ + ├── B055 ──► 撈取出貨指令 ──► remote_dispense_commands + │ PUT ──► 回報出貨結果 ──► 更新 command status + 庫存 + │ + ├── B220 ──► 零錢機庫存 ──► coin_inventory_logs + │ + ├── B600 ──► 消費金流 ──► orders + order_items(核心交易) + │ ◄── 返回金流 ID (flow_id) + │ + ├── B601 ──► 發票回傳 ──► invoices(關聯 flow_id) + │ + ├── B602 ──► 出貨回傳 ──► dispense_records(關聯 flow_id) + │ + ├── B650 ──► 驗證會員 ──► members + member_points + │ ◄── 點數折抵/優惠券/取貨碼/線上訂單 + │ + └── B710 ──► 計時器狀態 ──► timer_statuses +``` + +--- + +## 六、重要觀察與建議 + +### 6.1 API 金鑰 +- 所有 API 使用同一把硬編碼金鑰 `KahnEwjhfDBHUYS7` +- **建議**:遷移到 Star Cloud 後改為每台機台獨立的 API Token,使用 Laravel Sanctum 管理 + +### 6.2 資料一致性 +- B600(金流)→ B601(發票)→ B602(出貨)三支 API 透過 `flow_id` 串聯 +- 建議資料庫設計中以 `orders.flow_id` 作為三者的關聯基準 + +### 6.3 高頻 API +- **B010** 為最高頻率 API(每台機台數秒呼叫一次),必須走 **Redis Queue 異步寫入** +- B220(零錢機庫存)與 B710(計時器)也屬於高頻回報,建議異步處理 + +### 6.4 新舊版差異 +- B220 和 B600/B602 各有兩個版本的 PDF(新舊版),新版增加了更多面額(500/1000 元)和 TapPay 金流類型 +- 建議以**較新版本 (帶日期後綴的)** 為準進行開發 + +### 6.5 `machines` 表建議補充欄位 + +根據 B010 API,`machines` 表應包含: + +| 欄位 | 說明 | 來源 | +|------|------|------| +| `serial_no` | 機台序號 | B010 machine | +| `model` | 機台型號 | B010 M_Stus | +| `current_status` | 當前頁面狀態碼 | B010 M_Stus2 | +| `current_version` | 當前軟體版本 | B010 M_Ver | +| `temperature` | 最新溫度 | B010 temperature | +| `door_status` | 門禁狀態 | B010 door | +| `last_heartbeat_at` | 最後心跳時間 | B010 呼叫時間 | +| `is_online` | 是否在線 | 由心跳超時判斷 | diff --git a/docs/architecture_plan.md b/docs/architecture_plan.md new file mode 100644 index 0000000..88f9247 --- /dev/null +++ b/docs/architecture_plan.md @@ -0,0 +1,627 @@ +# Star Cloud — 智能販賣機管理平台技術架構規劃 + +> **目標**:為上千至上萬台智能販賣機建構集中式管理後台,承接所有機台透過 API 回寫的資料,並提供完整的營運管理介面。 + +--- + +## 一、系統架構全景 + +``` + ┌──────────────────────────────────────────────┐ + │ Star Cloud 管理後台 │ + │ (Laravel 12 + Blade + Tailwind) │ + │ ┌──────────┐ ┌──────────┐ ┌───────────┐ │ + │ │ 儀表板 │ │ 機台管理 │ │ 銷售分析 │ │ + │ │ Dashboard │ │ Machines │ │ Analytics │ │ + │ └──────────┘ └──────────┘ └───────────┘ │ + │ ┌──────────┐ ┌──────────┐ ┌───────────┐ │ + │ │ 倉庫管理 │ │ 會員系統 │ │ 遠端操控 │ │ + │ │Warehouses │ │ Members │ │ Remote │ │ + │ └──────────┘ └──────────┘ └───────────┘ │ + └──────────┬───────────────┬───────────────────┘ + │ Web Routes │ + │ (Blade SSR) │ + ┌──────────┴───────────────┴───────────────────┐ + │ Laravel Application │ + │ │ + │ Controllers → Services → Models → MySQL │ + │ │ + └──────┬────────────────────┬──────────────────┘ + │ │ + ┌──────────┴────┐ ┌───────┴───────┐ + │ API Routes │ │ Redis Queue │ + │ /api/v1/app │ │ (異步處理) │ + └──────┬────────┘ └───────┬───────┘ + │ │ + ┌──────┴────────┐ ┌───────┴───────┐ + │ API Controller│──────►│ Jobs │ + │ (驗證 + 分派) │ dispatch│ (Worker 執行) │ + └───────────────┘ └───────┬───────┘ + ▲ │ + ┌────────────────┤ ▼ + │ │ ┌──────────────┐ + ┌─────┴─────┐ ┌────┴─────┐ │ Services │ + │ 販賣機 #1 │ │販賣機 #N │ │ (業務邏輯) │ + │ B010 │ │ B600 │ └──────┬───────┘ + │ B600 │ │ B602 │ │ + │ B602 │ │ ... │ ▼ + └────────────┘ └──────────┘ ┌──────────────┐ + │ MySQL │ + │ (持久化) │ + └──────────────┘ +``` + +--- + +## 二、技術棧確認 + +| 層級 | 技術 | 說明 | +|------|------|------| +| **後端框架** | PHP 8.5 / Laravel 12 | 單體架構,Blade SSR | +| **資料庫** | MySQL 8.0 | 資料持久化 | +| **快取/隊列** | Redis | B010 心跳、B600 金流等高頻 API 必須異步 | +| **前端視圖** | Blade + Tailwind CSS + Preline UI | 極簡奢華風 | +| **前端互動** | Alpine.js | 輕量 DOM 互動 | +| **建置工具** | Vite | 前端資源編譯 | +| **開發環境** | Laravel Sail (Docker) | 本地開發 | +| **IoT 通訊** | Redis Queue + Jobs | 異步寫入,避免 API 直連 DB | +| **認證** | Laravel Sanctum | 後台用 Session,API 用 Token | + +--- + +## 三、多租戶與權限架構 (Multi-Tenant RBAC) + +為支援系統管理員(內部營運)與租戶(客戶公司及子帳號)的雙層管理模式,平台採用以下三層級權限隔離架構: + +### 3.1 租戶隔離層 (Tenant Isolation) +* **核心機制**:導入 `companies` 資料表作為租戶實體,所有歸屬於客戶的資源(`users`, `machines` 等)均需綁定 `company_id`。 +* **身份判定**: + * **系統管理員 (內部)**:`company_id = null`,具備跨租戶檢視與管理機台、設定全局參數的最高權限。 + * **客戶端帳號 (租戶)**:`company_id` 有值,所有查詢(透過 Eloquent Global Scopes 或 Middleware)自動注入 `where('company_id', $user->company_id)`,達成資料物理隔離。 + +### 3.2 角色與權限層 (Roles & Permissions) +* 採用 `spatie/laravel-permission` 套件並進行多租戶改造。 +* **多租戶角色 (Tenant-Aware Roles)**:擴充 `roles` 表,加入 `company_id` 欄位。 + * **系統預設角色** (`company_id = null`):如 Super Admin, System Support。 + * **客戶自建角色** (`company_id = N`):如客戶建立的「分區維修員」、「會計」,確保客戶只能看見與分配屬於自己公司的角色給員工。 +* **權限 (Permissions)**:定義系統最小操作單位(如 `machine.view`, `user.create`),供角色綁定。 + +### 3.3 流程控制與防禦 (Flow Control) +* **介面隔離**:依據身份動態隱藏/顯示系統級選單(例如「全站設定」、「合約管理」等多租戶不可見的功能)。 +* **越權防禦**:客戶創建子帳號時,後端必定強制攔截並覆寫 `user->company_id = Auth::user()->company_id`,確保子帳號牢牢綁在自己的公司名下。同時限制其只能撈與分配自己公司名下的 Role。 + +--- + +## 四、資料庫完整設計 + +### 4.1 資料表總覽 + +分為 **6 大領域**,共 **28 張表**: + +```mermaid +graph LR + subgraph 系統管理 + A1[users] --> A2[sessions] + A1 --> A3[personal_access_tokens] + A4[failed_jobs] + end + + subgraph 機台領域 + B1[machines] --> B2[machine_slots] + B1 --> B3[machine_logs] + B1 --> B4[coin_inventories] + B1 --> B5[timer_statuses] + B1 --> B6[remote_commands] + B1 --> B7[machine_heartbeats] + end + + subgraph 商品領域 + C1[products] + C2[product_categories] + end + + subgraph 交易領域 + D1[orders] --> D2[order_items] + D1 --> D3[invoices] + D1 --> D4[dispense_records] + D5[payment_types] + end + + subgraph 會員領域 + E1[members] --> E2[social_accounts] + E1 --> E3[member_wallets] + E3 --> E4[wallet_transactions] + E1 --> E5[member_points] + E5 --> E6[point_transactions] + E7[point_rules] + E8[deposit_bonus_rules] + E1 --> E9[membership_tiers] + E1 --> E10[member_memberships] + E1 --> E11[gift_definitions] + E1 --> E12[member_gifts] + end + + subgraph APP設定 + F1[app_configs] + end +``` + +### 4.2 需新增的資料表(Migration 設計) + +> 以下為 API 分析後推導出的缺失表,搭配各 API 欄位產生對應。 + +--- + +#### 👑 多租戶與權限基礎表 (RBAC & Tenant) + +##### 🆕 `companies` — 租戶/客戶主表 +所有客戶端的資料邊界,用來實現資料物理隔離。 + +| 欄位 | 類型 | 說明 | +|------|------|------| +| `id` | BIGINT PK | — | +| `name` | VARCHAR(255) | 公司/組織名稱 | +| `tax_id` | VARCHAR(20) NULL | 統一編號 | +| `contact_name` | VARCHAR(100) NULL | 聯絡人姓名 | +| `contact_phone` | VARCHAR(50) NULL | 聯絡電話 | +| `status` | TINYINT DEFAULT 1 | 狀態 (1:啟用, 0:停用) | +| `valid_until` | DATE NULL | 合約使用期限 | +| `timestamps` | — | — | +| `deleted_at` | TIMESTAMP NULL | 軟刪除 (SoftDeletes) | + +##### 🟡 `users` 表 — 需擴充欄位 +將 Laravel 預設的使用者表與租戶綁定。 + +| 新增欄位 | 類型 | 說明 | +|----------|------|------| +| `company_id` | BIGINT FK NULL | → `companies` (NULL 代表系統管理員) | +| `status` | TINYINT DEFAULT 1 | 帳號狀態 (1:啟用, 0:停用) | + +##### 🟡 `roles` 表 (Spatie 權限擴充) +Spatie 預設的 roles 表必須加上多租戶設計,確保留戶只能管理自己的角色。 + +| 新增/調整欄位 | 類型 | 說明 | +|----------|------|------| +| `company_id` | BIGINT FK NULL | → `companies` (NULL 代表系統全域角色) | +| **UNIQUE** | `(name, guard_name, company_id)` | 原套件無 `company_id`,需修改為複合唯一鍵 | + +--- + +#### 🟡 `machines` 表 — 需擴充欄位 + +現有 `machines` 表僅有基礎欄位,需為 B010 API 補充: + +| 新增欄位 | 類型 | 說明 | 來源 API | +|----------|------|------|----------| +| `serial_no` | `VARCHAR UNIQUE` | 機台序號(API 用此識別) | B010 `machine` | +| `model` | `VARCHAR` | 機台型號 | B010 `M_Stus` | +| `current_page` | `TINYINT` | 當前頁面狀態碼 | B010 `M_Stus2` | +| `door_status` | `VARCHAR` | 門禁狀態 | B010 `door` | +| `is_online` | `BOOLEAN` | 是否在線(心跳超時判斷) | 計算欄位 | +| `api_token` | `VARCHAR` | 機台專屬 API Token | 取代硬編碼 key | + +--- + +#### 🆕 `products` — 商品資料 + +| 欄位 | 類型 | 說明 | +|------|------|------| +| `id` | BIGINT PK | — | +| `name` | VARCHAR(255) | 商品名稱 (預設語系) | +| `name_dictionary_key` | VARCHAR(100) NULL | 多語系字典鍵值 (對應 translations 表) | +| `sku` | VARCHAR(100) UNIQUE | 商品編號 | +| `price` | DECIMAL(10,2) | 售價 | +| `cost` | DECIMAL(10,2) NULL | 成本 | +| `category_id` | BIGINT FK NULL | → product_categories | +| `image` | VARCHAR NULL | 圖片 URL | +| `barcode` | VARCHAR NULL | 條碼 | +| `is_timer_product` | BOOLEAN | 是否為計時型商品 | +| `is_active` | BOOLEAN | 是否上架 | +| `timestamps` | — | — | + +--- + +#### 🌐 多語系支援表 (i18n) + +為了支援後台介面與 APP 端顯示的多語系內容(如商品名稱、分類名稱、系統提示),統一採用字典表架構。 + +##### 🆕 `translations` — 多語系字典表 + +| 欄位 | 類型 | 說明 | +|------|------|------| +| `id` | BIGINT PK | — | +| `group` | VARCHAR(50) | 分組 (例如: `product`, `category`, `system`) | +| `key` | VARCHAR(100) | 字典鍵值 (例如: `prod_name_001`) | +| `locale` | VARCHAR(10) | 語系代碼 (例如: `zh_TW`, `en_US`, `ja_JP`) | +| `value` | TEXT | 翻譯內容 | +| `timestamps` | — | — | +| **UNIQUE** | `(group, key, locale)` | 確保同一組鍵值在同一語系下唯一 | + +> **多語系實作策略**: +> 1. **靜態文案**:後台介面的靜態文字直接使用 Laravel 內建的 `lang/` 目錄 (JSON 或 PHP 陣列)。 +> 2. **動態資料**:資料庫內容(如商品名稱 `products.name`)保留預設語系供後台快速搜尋。同時新增 `name_dictionary_key`。當對接外部 APP 或前台需要多語系時,透過 API 關聯 `translations` 表,回傳當前語系對應的 `value`。 + +--- + +#### 🆕 `machine_slots` — 機台貨道 + +| 欄位 | 類型 | 說明 | 來源 | +|------|------|------|------| +| `id` | BIGINT PK | — | — | +| `machine_id` | BIGINT FK | → machines | B017, B055, B710 | +| `slot_no` | VARCHAR(20) | 貨道編號 | B017 `tid`, B710 `cid` | +| `product_id` | BIGINT FK NULL | → products | B710 `pid` | +| `stock` | INT DEFAULT 0 | 當前庫存 | B017 `num` | +| `max_stock` | INT DEFAULT 0 | 最大容量 | — | +| `is_active` | BOOLEAN | 是否啟用 | — | +| `timestamps` | — | — | — | +| **UNIQUE** | `(machine_id, slot_no)` | 複合唯一鍵 | — | + +--- + +#### 🆕 `orders` — 訂單主表 + +| 欄位 | 類型 | 說明 | 來源 | +|------|------|------|------| +| `id` | BIGINT PK | — | — | +| `flow_id` | VARCHAR UNIQUE | Cloud 金流 ID | B600 response | +| `order_no` | VARCHAR | APP 訂單號 | B600 `req9` | +| `machine_id` | BIGINT FK | → machines | B600 `req2` | +| `member_id` | BIGINT FK NULL | → members | B650 關聯 | +| `payment_type` | SMALLINT | 金流類型碼 | B600 `req3` | +| `total_amount` | DECIMAL(10,2) | 消費金額 | B600 `req7` | +| `change_amount` | DECIMAL(10,2) | 找零 | B600 `req13` | +| `points_used` | INT DEFAULT 0 | 使用點數 | B600 `req14` | +| `original_amount` | DECIMAL(10,2) NULL | 折扣前金額 | B602 `req15` | +| `payment_status` | TINYINT | 0:失敗/1:成功 | B600 `req12` | +| `payment_request` | TEXT NULL | 金流送出 data | B600 `req4` | +| `payment_response` | TEXT NULL | 金流回傳 data | B600 `req5` | +| `member_barcode` | VARCHAR NULL | 會員條碼 | B600 `req10` | +| `invoice_info` | VARCHAR NULL | 發票歸戶 | B600 `req8` | +| `machine_time` | DATETIME NULL | 機台時間 | B600 `req11` | +| `timestamps` | — | — | — | +| **INDEX** | `(machine_id, created_at)` | 查詢最佳化 | — | +| **INDEX** | `(payment_type)` | 金流類型篩選 | — | + +--- + +#### 🆕 `order_items` — 訂單明細 + +| 欄位 | 類型 | 說明 | 來源 | +|------|------|------|------| +| `id` | BIGINT PK | — | — | +| `order_id` | BIGINT FK | → orders | — | +| `product_id` | BIGINT FK | → products | B600 `req16.pid` | +| `quantity` | INT | 數量 | B600 `req16.num` | +| `unit_price` | DECIMAL(10,2) | 單價 | B600 `req16.amount` | +| `subtotal` | DECIMAL(10,2) | 小計 | 計算 | +| `timestamps` | — | — | — | + +--- + +#### 🆕 `invoices` — 發票紀錄 + +| 欄位 | 類型 | 說明 | 來源 | +|------|------|------|------| +| `id` | BIGINT PK | — | — | +| `order_id` | BIGINT FK | → orders(via flow_id) | — | +| `flow_id` | VARCHAR | 金流 ID | B601 `req3` | +| `machine_id` | BIGINT FK | → machines | B601 `req2` | +| `rtn_code` | VARCHAR NULL | 回傳碼 | B601 `req4` | +| `rtn_msg` | VARCHAR NULL | 回傳訊息 | B601 `req5` | +| `invoice_no` | VARCHAR NULL | 發票號碼 | B601 `req6` | +| `invoice_date` | DATE NULL | 發票日期 | B601 `req7` | +| `random_number` | VARCHAR NULL | 隨機碼 | B601 `req8` | +| `love_code` | VARCHAR NULL | 愛心碼 | B601 `req9` | +| `timestamps` | — | — | — | + +--- + +#### 🆕 `dispense_records` — 出貨紀錄 + +| 欄位 | 類型 | 說明 | 來源 | +|------|------|------|------| +| `id` | BIGINT PK | — | — | +| `order_id` | BIGINT FK NULL | → orders | — | +| `flow_id` | VARCHAR NULL | 金流 ID | B602 `req3` | +| `machine_id` | BIGINT FK | → machines | B602 `req2` | +| `product_id` | VARCHAR | 商品 ID | B602 `req5` | +| `slot_no` | VARCHAR | 貨道編號 | B602 `req6` | +| `amount` | DECIMAL(10,2) | 消費金額 | B602 `req7` | +| `remaining_stock` | INT NULL | 剩餘庫存 | B602 `req9` | +| `dispense_status` | TINYINT | 0:成功/1:失敗 | B602 `req13` | +| `member_barcode` | VARCHAR NULL | 會員條碼 | B602 `req10` | +| `machine_time` | DATETIME NULL | 機台時間 | B602 `req11` | +| `points_used` | INT DEFAULT 0 | 使用點數 | B602 `req16` | +| `timestamps` | — | — | — | + +--- + +#### 🆕 `remote_commands` — 遠端指令佇列 + +| 欄位 | 類型 | 說明 | 來源 | +|------|------|------|------| +| `id` | BIGINT PK | — | — | +| `machine_id` | BIGINT FK | → machines | — | +| `command_type` | VARCHAR(20) | 指令類型 | B010 response status | +| `status` | ENUM | pending/sent/success/failed | — | +| `payload` | JSON NULL | 指令附加資料 | — | +| `executed_at` | TIMESTAMP NULL | 執行時間 | — | +| `timestamps` | — | — | — | + +> 對應 B010 遠端指令(reboot, lock, unlock, checkout, dispense 等)以及 B055 遠端出貨。 + +--- + +#### 🆕 `coin_inventories` — 零錢機庫存 + +| 欄位 | 類型 | 說明 | 來源 | +|------|------|------|------| +| `id` | BIGINT PK | — | — | +| `machine_id` | BIGINT FK | → machines | B220 `machine` | +| `value_1` | INT DEFAULT 0 | 1 元 | B220 | +| `value_5` | INT DEFAULT 0 | 5 元 | B220 | +| `value_10` | INT DEFAULT 0 | 10 元 | B220 | +| `value_50` | INT DEFAULT 0 | 50 元 | B220 | +| `value_100` | INT DEFAULT 0 | 100 元 | B220 | +| `value_500` | INT DEFAULT 0 | 500 元 | B220 | +| `value_1000` | INT DEFAULT 0 | 1000 元 | B220 | +| `operator` | VARCHAR NULL | 操作人 (0=消費者) | B220 `account` | +| `timestamps` | — | — | — | + +--- + +#### 🆕 `timer_statuses` — 計時器狀態 + +| 欄位 | 類型 | 說明 | 來源 | +|------|------|------|------| +| `id` | BIGINT PK | — | — | +| `machine_id` | BIGINT FK | → machines | B710 `req2` | +| `slot_no` | VARCHAR | 貨道 ID | B710 `cid` | +| `product_id` | BIGINT FK NULL | → products (0=未設定) | B710 `pid` | +| `status` | TINYINT | 0:未啟用/1:使用中/2:異常 | B710 `status` | +| `remaining_seconds` | INT | 剩餘秒數 | B710 `num` | +| `timestamps` | — | — | — | + +--- + +#### 🆕 `payment_types` — 金流類型參照 + +| 欄位 | 類型 | 說明 | +|------|------|------| +| `id` | BIGINT PK | — | +| `code` | SMALLINT UNIQUE | 金流代碼 (1,2,3...120) | +| `name` | VARCHAR | 中文名稱 | +| `category` | VARCHAR | 大分類 | +| `is_active` | BOOLEAN | 是否啟用 | +| `timestamps` | — | — | + +--- + +## 五、IoT API 路由設計 + +### 5.1 路由結構 + +```php +// routes/api.php +Route::prefix('v1/app')->middleware(['throttle:iot'])->group(function () { + + // B010 - 機台狀態上傳 & 指令撈回 + Route::post('/machine/status', [MachineStatusController::class, 'heartbeat']); + + // B017 - 遠端撈庫存 + Route::post('/machine/reload', [MachineStockController::class, 'reload']); + + // B055 - 遠端出貨 + Route::post('/machine/dispense', [DispenseController::class, 'getCommands']); + Route::put('/machine/dispense', [DispenseController::class, 'updateStatus']); + + // B220 - 零錢機庫存 + Route::post('/coin/inventory', [CoinInventoryController::class, 'store']); + + // B600 - 消費金流 + Route::post('/transaction', [TransactionController::class, 'store']); + + // B601 - 發票回傳 + Route::post('/invoice', [InvoiceController::class, 'store']); + + // B602 - 出貨回傳 + Route::post('/dispense-record', [DispenseRecordController::class, 'store']); + + // B650 - 驗證會員 + Route::post('/member/verify', [MemberVerifyController::class, 'verify']); + + // B710 - 計時器狀態 + Route::post('/timer/status', [TimerStatusController::class, 'sync']); +}); +``` + +### 5.2 處理管線 + +> [!IMPORTANT] +> 遵循 IoT 通訊技能規範:**嚴禁** API Controller 直接寫入 DB。 + +| API | 處理方式 | 原因 | +|-----|----------|------| +| B010 | **異步** (Redis Queue) | 最高頻,每台數秒一次 | +| B017 | **同步** (直接回應) | 低頻,需即時回傳庫存數據 | +| B055 GET | **同步** | 需即時回傳指令列表 | +| B055 PUT | **異步** | 出貨結果可背景處理 | +| B220 | **異步** | 庫存變動日誌可背景寫入 | +| B600 | **異步** | 高頻交易,核心數據 | +| B601 | **異步** | 發票資訊可背景寫入 | +| B602 | **異步** | 出貨紀錄可背景寫入 | +| B650 | **同步** | 需即時回傳驗證結果與折抵金額 | +| B710 | **異步** | 計時器狀態批量更新 | + +--- + +## 六、後台模組 ↔ 資料表對應 + +| 後台模組(web.php) | 對應資料表 | 資料來源 API | +|---------------------|-----------|-------------| +| 1. 儀表板 Dashboard | orders, machines, dispense_records | 統計彙整 | +| 2. 會員管理 Members | members, social_accounts, member_wallets... | B650 | +| 3. 機台管理 Machines | machines, machine_logs, machine_slots | B010, B017 | +| 4. APP 管理 App | app_configs, timer_statuses | B710 | +| 5. 倉庫管理 Warehouses | products, machine_slots | B017, B602 | +| 6. 銷售管理 Sales | orders, order_items, dispense_records | B600, B602 | +| 7. 分析管理 Analysis | orders, dispense_records, coin_inventories | 全部 | +| 8. 稽核管理 Audit | orders, dispense_records | B600, B602 | +| 9. 資料設定 DataConfig | products, payment_types, users | — | +| 10. 遠端管理 Remote | remote_commands | B010, B055 | +| 11. Line 管理 | members (Line 綁定) | — | +| 12. 預約系統 Reservation | (未來擴充) | — | +| 13. 特殊權限 SpecialPerm | machines, app_configs | — | +| 14. 權限設定 Permission | users, roles | — | + +--- + +## 七、效能預估與應對 + +### 10,000 台機台的流量預估 + +| API | 頻率 | 每秒請求量 (QPS) | 每日資料量 | +|-----|------|-----------------|-----------| +| B010 心跳 | 每 5 秒/台 | **~2,000** | ~173M 筆 | +| B600 金流 | 每筆交易 | ~10-50 | ~50K-200K 筆 | +| B602 出貨 | 每筆交易 | ~10-50 | ~50K-200K 筆 | +| B710 計時器 | 每 10 秒/台 | ~1,000 | ~86M 筆 | + +### 應對策略 + +| 策略 | 實作方式 | +|------|----------| +| **Redis Queue 異步寫入** | 所有高頻 API 進 Queue,Worker 批量寫入 | +| **心跳資料瘦身** | B010 不逐筆寫 DB,僅更新 `machines` 表的即時欄位 + 異常時寫 log | +| **資料分區** | `orders` 和 `dispense_records` 按月份分區 | +| **索引策略** | 所有查詢欄位建立適當 INDEX(machine_id + created_at 複合索引) | +| **速率限制** | 單台機台 60 req/min,全站 100,000 req/min | +| **快取** | 機台列表、商品列表等低變動資料用 Redis Cache | + +--- + +## 八、實作路線圖與預估時程 + +> **總結報告**:為確保開發品質與應對突發狀況,本專案預計總開發時程擴展為 **16 - 18 週**。以 1 人天 = 8 小時純開發時間計算,預估總投入約 **80 - 90 個工作天**。 + +### 🗓️ 專案開發甘特圖 (自動排除週末) + +```mermaid +gantt + title Star Cloud 實作時程規劃 + dateFormat YYYY-MM-DD + excludes weekends + + section 第一階段 MVP + Phase 1 基礎設施與資料表 :active, p1, 2026-03-11, 14d + Phase 2 IoT API 與異步管線 :p2, after p1, 24d + Phase 3 後台 MVP 頁面整合 :p3, after p2, 18d + + section 第二階段 進階 + Phase 4 進階功能與報表分析 :p4, after p3, 30d +``` + +### 📅 詳細時程對照表 + +| 階段 (Phase) | 關鍵任務摘要 | 預估天數 | 預計工作日期 | 狀態 | +| :--- | :--- | :---: | :---: | :---: | +| **Phase 1** | 基礎架構、28張表設計、資料遷移基礎 | 14 工作天 | 03/11 ~ 03/30 | 準備啟動 | +| **Phase 2** | B010~B710 核心 API、Redis 異步 Job、Service | 24 工作天 | 03/31 ~ 05/01 | 規劃中 | +| **Phase 3** | 儀表板、機台/銷售/遠端管理 MVP 介面 | 18 工作天 | 05/04 ~ 05/27 | 規劃中 | +| **Phase 4** | 數據分析統計圖表、補貨演算法、自動對帳模組 | 30 工作天 | 05/28 ~ 07/08 | 規劃中 | + +--- + +### 🔵 第一階段:MVP 營運核心 (最優先上線) +**目標**:確保機台金流與指令能穩定連通,完成基礎營運管理功能。 + +#### Phase 1:基礎設施與核心資料表 (預計: 14 工作天) +- [ ] 擴充 `machines` 表(serial_no, model 等欄位) +- [ ] 建立 多租戶與權限基礎表 (`companies`, `spatie/laravel-permission` 相關表) +- [ ] 將 `company_id` 欄位加入 `users`, `machines`, `roles` 等核心表 +- [ ] 建立 `translations` 多語系字典表,並擴充 `products` 語系關聯 +- [ ] 新增 `products` + `product_categories` 表 +- [ ] 新增 `machine_slots` 表 +- [ ] 新增 `orders` + `order_items` 表 +- [ ] 新增 `invoices` + `dispense_records` 表 +- [ ] 新增 `remote_commands` 表 (遠端管理與對接用) +- [ ] 新增 `payment_types` 表 + Seeder + +#### Phase 2:核心營運 IoT API 與異步管線 (預計: 24 工作天) +- [ ] 實作 **B010** API (心跳上報 + 狀態更新 + 遠端管理) +- [ ] 實作 **B017 / B055** API (遠端改庫存/出貨) +- [ ] 實作 **B600 / B601 / B602** API (金流/發票/出貨紀錄) +- [ ] 實作 **B650** API (會員驗證 + 點數折抵) +- [ ] 建立上述對應的 **Redis Queue Job + Service** 異步處理邏輯 + +#### Phase 3:後台 MVP 頁面整合 (預計: 18 工作天) +- [ ] **多租戶權限與身份切換機制 (Middleware & Views)** +- [ ] 儀表板 Dashboard:即時數據看板 (營收、機台數,依據租戶隔離資料) +- [ ] 機台管理 Machines:連線狀態、貨道庫存、指令操作 UI +- [ ] 銷售管理 Sales:訂單列表、出貨/發票追蹤 +- [ ] 系統基礎設定:帳號與權限設定 (RBAC UI)、商品建檔、金流代碼設定、**多語系字典維護介面** + +--- + +### 🟢 第二階段:進階營運與智慧分析 (持續優化) +**目標**:強化報表分析能力與自動化稽核。 + +#### Phase 4:進階功能與報表分析模組 (預計: 30 工作天) +- [ ] **分析管理 Analysis**:趨勢圖、商品熱銷分析、機台產能報表 +- [ ] **倉庫管理 Warehouses**:補貨建議、入/出庫流程優化 +- [ ] **擴充支持**:B220 (零錢機) + B710 (計時器) 支援 +- [ ] **自動化稽核 Audit**:對帳機制、異常提醒 +- [ ] **行銷模組**:Line 聯動、預約系統、UI 動態設定 + + +--- + +## 九、目錄結構建議 + +``` +app/ +├── Http/Controllers/ +│ ├── Admin/ ← 後台管理(已存在 14 模組) +│ └── Api/V1/ +│ ├── App/ ← 機台 IoT API(新增) +│ │ ├── MachineStatusController.php (B010) +│ │ ├── MachineStockController.php (B017) +│ │ ├── DispenseController.php (B055) +│ │ ├── CoinInventoryController.php (B220) +│ │ ├── TransactionController.php (B600) +│ │ ├── InvoiceController.php (B601) +│ │ ├── DispenseRecordController.php (B602) +│ │ ├── MemberVerifyController.php (B650) +│ │ └── TimerStatusController.php (B710) +│ ├── MemberController.php ← 會員 API(已存在) +│ └── MachineController.php ← 機台日誌(已存在) +├── Jobs/ +│ └── Machine/ ← IoT 異步任務(新增) +│ ├── ProcessHeartbeat.php +│ ├── ProcessTransaction.php +│ ├── ProcessDispenseRecord.php +│ ├── ProcessInvoice.php +│ ├── ProcessCoinInventory.php +│ └── ProcessTimerStatus.php +├── Services/ +│ └── Machine/ ← 業務邏輯(新增) +│ ├── HeartbeatService.php +│ ├── TransactionService.php +│ ├── DispenseService.php +│ └── MemberVerifyService.php +└── Models/ + ├── Machine/ ← 已存在 + │ ├── Machine.php + │ └── MachineLog.php + ├── Transaction/ ← 新增 + │ ├── Order.php + │ ├── OrderItem.php + │ ├── Invoice.php + │ ├── DispenseRecord.php + │ └── PaymentType.php + ├── Product/ ← 新增 + │ ├── Product.php + │ └── ProductCategory.php + └── Member/ ← 已存在 +``` diff --git a/docs/b010_technical_spec.md b/docs/b010_technical_spec.md new file mode 100644 index 0000000..5d4796c --- /dev/null +++ b/docs/b010_technical_spec.md @@ -0,0 +1,89 @@ +# B010 API (機台心跳與指令) 技術規範與執行指南 + +本文件整合了 B010 API 的業務邏輯討論與技術執行分析,作為 Star Cloud 實作機台通訊核心的指導準則。 + +--- + +## 1. 業務邏輯與指令下發 (Command Flow) + +### 1.1 指令下發機制 +B010 是 Cloud 向機台下達遠端指令(如:開鎖、重啟、改庫存)的唯一通道。 +* **指令隊列**:指令需先寫入 `remote_commands` 表,狀態標記為 `pending`。 +* **撈取邏輯**:當機台定期呼叫 B010 時,後端 Service 會查詢該機台是否有等待執行的指令。 +* **回應處理**:若有指令,則在 Response 的 `status` 欄位回傳對應的指令碼(如 51:重啟, 70:開鎖)。 +* **優先順序**:當同時有多個指令待執行時,需按緊急程度(如:重啟 > 開鎖 > 載入配置)定義優先順序回傳。 + +### 1.2 執行回饋 (Feedback Loop) +* **確認機制**:機台收到指令後,必須確保執行結果能回報至雲端。 +* **判定方案**: + * **被動判定**:若機台在其後的 B010 心跳中回報狀態正常(如:軟體版本更新成功、頁面碼正確),即視為成功。 + * **主動判定**:對於關鍵指令(如遠端出貨),機台需另外呼叫狀態更新 API (如 B055 PUT) 回報結果。 + +--- + +## 2. 執行面挑戰:高併發與效能 (Performance) + +### 2.1 寫入瓶頸分析 +* **數據規模**:10,000 台機台,每 5 秒一個心跳,全站 QPS 約 2,000。 +* **DB 壓力**:直接同步寫入 MySQL `machines` 與 `machine_logs` 將導致磁碟 I/O 鎖定。 + +### 2.2 解決策略 (Redis 緩衝) +* **即時狀態流動**: + * **最後在線時間**、**溫度**、**門禁狀態**、**頁面碼** 等動態數據優先存入 **Redis**。 + * **批量更新 (Lazy Update)**:每 1~5 分鐘由後台任務將 Redis 數據批量寫回 MySQL `machines` 表。 +* **日誌優化**: + * 正常的心跳資料不逐筆寫入 `machine_logs`。 + * 僅在**狀態變更**(如:門被打開、溫度過高、軟體報錯)時,才觸發資料庫日誌記錄。 + +--- + +## 3. 資料庫結構擴充 (Schema Gap) + +必須對原有的 `machines` 表進行欄位擴充,以承載 B010 的回傳值: + +| 新增欄位 | 類型 | 說明 | +|----------|------|------| +| `serial_no` | VARCHAR(50) UNIQUE | 機台序號 (API `machine`) | +| `model` | VARCHAR(50) | 機台型號 (API `M_Stus`) | +| `current_page` | TINYINT | 當前頁面代碼 (API `M_Stus2`) | +| `door_status` | VARCHAR(10) | 門禁狀態 (`open`/`closed`) | +| `api_token` | VARCHAR(100) | 獨立安全憑證 (取代共用 Key) | + +--- + +## 4. 安全性與驗證策略 (Security) + +* **API Key 遷移**:從目前全系統硬編碼的共用 Key,逐步遷移至每台機台專屬的 `api_token`。 +* **實裝方式**: + * 後台管理介面新增「核發機台 Token」功能。 + * 建立專屬 `IotAuthMiddleware`,驗證請求中的 Token 與 `machines` 表是否匹配。 + +--- + +## 5. 離線與告警機制 (Heartbeat Logic) + +* **在線判定**:心跳超時(建議超過 60 秒)即在 UI 將機台顯示為「離線」。 +* **自動維護**:排程 Job 定期掃描 `machines.last_heartbeat_at`,對長期失聯的機台發出系統告警。 + +--- + +## 6. 待確認事項 (To-be-confirmed) + +### 6.1 指令下發與回應 (Command Flow) +1. **指令優先順序**:當後台同時有多個指令待執行 (如:改庫存 + 重啟) 時,應如何定義優先權? +2. **執行狀態回饋**:機台收到心跳指令後的執行結果確認,應採「被動判定」(機台下次心跳狀態正確則視為成功) 還是「主動回報」(機台另呼叫 API)? + +### 6.2 效能與日誌策略 (Performance & Logs) +3. **Redis 更新頻率**:即時狀態從 Redis 批量同步至 MySQL 的建議時間間隔 (目前暫估 1~5 分鐘)。 +4. **心跳日誌級別**:是否確認「正常心跳」不寫入資料庫日誌,僅記錄「異常/變更」事件? + +### 6.3 在線/離線判定 (Presence) +5. **離線超時定義**:預計多久未收心跳判定為離線?(建議 30~60 秒)。 +6. **斷線告警機制**:機台斷線時,是否需即時產出系統警示或推播給相關人員? + +### 6.4 安全性驗證 (Auth) +7. **Token 傳遞方式**:將 API Key 遷移至專屬 Token 時,機台端是否能配合在 Header (`Authorization: Bearer `) 帶入,或必須保留在 JSON Payload 中? + +### 6.5 欄位細節 (Field Details) +8. **URL {workid} 定義**:URL 中的 `{workid}` 應對應為 `serial_no` (機台序號) 還是資料庫自增 `id`? +9. **M_Stus2 告警觸發**:20 多種頁面狀態碼中,哪些特定的錯誤代碼需要在管理後台觸發即時紅字警示? diff --git a/docs/b017_technical_spec.md b/docs/b017_technical_spec.md new file mode 100644 index 0000000..dc96454 --- /dev/null +++ b/docs/b017_technical_spec.md @@ -0,0 +1,65 @@ +# B017 API (遠端改庫存) 技術規範與執行指南 + +本文件記錄 B017 API 的業務邏輯與技術執行細節,用於指導後端管理系統遠端調整機台庫存的實作。 + +--- + +## 1. 業務情境與觸發機制 (Trigger) + +### 1.1 觸發流程 +1. **管理行為**:管理員在後台管理介面手動修改特定機台的貨道庫存數量。 +2. **指令預備**:後端系統記錄異動請求,並在該機台的 B010 (心跳) 回應中,將 `status` 設為 `49` (reload B017)。 +3. **機台拉取**:機台收到心跳回應中的 `49` 代碼後,主動呼叫 B017 API (`/api/app/machine/reload_msg/{workid}`)。 +4. **數據同步**:機台獲取最新庫存數據並更新本地狀態。 + +### 1.2 更新範圍 +* **全量更新 (Full Sync)**:B017 API 回傳該機台**所有貨道**的最新庫存數量,而非僅回傳變動部分。這有助於機台軟體進行「最終狀態一致性」的自我校正。 + +--- + +## 2. 資料一致性與日誌 (Consistency & Audit) + +### 2.1 更新確認機制 +* **隱式成功 (Implicit Success)**:機台更新本地庫存後不需要回傳明確的 B017 確認 API。 +* **驗證方式**:系統將以機台下次呼叫 B010 回報的狀態或機台後續的正常銷售紀錄,視為前次更新成功。 + +### 2.2 管理員異動日誌 (Audit Log) +* **強制要求**:每次後台發起遠端改庫存操作,必須記錄於 `activity_logs` 或特定的 `stock_adjustment_logs`。 +* *紀錄內容*:管理者 ID、執行時間、機台 ID、調整前後的貨道庫存對照。 + +### 2.3 庫存衝突處理 +* *情境*:若雲端下發庫存更新時,機台現場同時發生實體銷售。 +* *處理原則*:**詳見下方待確認事項**。 + +--- + +## 3. 執行面優化 (Execution Strategy) + +### 3.1 Redis 緩衝與效能 +* **快取策略**:機台的貨道結構與庫存數據應快取於 Redis 中。當管理員調整庫存時,同步更新 Redis 與 MySQL。 +* **讀取優化**:B017 API 應直接從 Redis 讀取數據回傳給機台,以降低 MySQL 的查詢壓力。 + +--- + +## 4. 欄位定義與對照 + +| 欄位名稱 | 資料庫對應 | 說明 | +|----------|------------|------| +| `workid` | `machines.serial_no` | 機台識別序號 | +| `channelid` | `machine_slots.slot_no` | 貨道編號 | +| `stock` | `machine_slots.stock` | 該貨道的當前可用庫存 | + +--- + +## 5. 開發建議 +* 建立一個專屬的 `StockService` 來處理 Redis 與 DB 的同步,以及異動日誌的寫入。 +* 在 `B010` 的回應邏輯中,檢查 `remote_commands` 是否有 pending 的庫存異動指令,以動態切換 `status: 49`。 + +--- + +## 6. 待確認事項 (To-be-confirmed) + +1. **庫存衝突優先權**:當「雲端改庫存」與「現場實體銷售」同時發生時,最終庫存應以何者為準?(待主管確認)。 +2. **API 欄位對照**: + * `workid` 是否嚴格對應 `serial_no`? + * `channelid` 是否對標 `slot_no`? diff --git a/docs/b055_technical_spec.md b/docs/b055_technical_spec.md new file mode 100644 index 0000000..8c4eaf2 --- /dev/null +++ b/docs/b055_technical_spec.md @@ -0,0 +1,55 @@ +# B055 API (遠端出貨) 技術規範與執行指南 + +本文件定義 B055 API 的技術實作規範,用於處理從雲端發起的機台遠端出貨指令及其結果回饋。 + +--- + +## 1. 業務流程與通訊機制 + +### 1.1 指令下發流程 +1. **指令生成**:Cloud 後端(管理者或系統觸發)在 `remote_dispense_commands` 表中建立一筆狀態為 `0` (待執行) 的指令。 +2. **心跳通知**:在該機台的 B010 回應中,將 `status` 設為 `85` (reload B055)。 +3. **機台撈取 (POST)**:機台呼叫 B055 POST API (`/api/app/machine/dispense/{workid}`) 取得詳細出貨參數(貨道 ID、指令 ID)。 +4. **執行與回報 (PUT)**:機台嘗試出貨後,呼叫 B055 PUT API 回報出貨結果及剩餘庫存。 + +### 1.2 數據關聯 (Data Linking) +* **出貨紀錄整合**:遠端出貨成功後,系統必須在 `dispense_records` 表中同步存入一筆紀錄,並將 `source` 標記為 `remote`(或對應識別),確保後台報表包含所有實體出貨數據。 + +--- + +## 2. 資料庫結構:`remote_dispense_commands` + +| 欄位 | 說明 | 備註 | +|------|------|------| +| `command_id` | 執行命令 ID | 用於追蹤單次指令 | +| `slot_no` | 貨道 ID | 指派機台出貨的通道 | +| `status` | 執行狀態 | 0:待執行, 1:成功, 2:失敗 | +| `remaining_stock` | 剩餘庫存 | 由機台回報 | + +--- + +## 3. 執行面優化 (Execution Strategy) + +* **Redis 隊列**:由於遠端出貨屬於高優先權操作,待執行指令應快取於 Redis 中,以確保機台呼叫 POST 時能即時回應。 +* **異步處理**:機台 PUT 回報結果後,系統透過隊列更新 DB 狀態,並根據結果觸發後續邏輯(如扣除庫存、異動日誌)。 + +--- + +## 4. 待確認事項 (To-be-confirmed) + +### 4.1 業務情境 (Scenario) +1. **指令發起來源**:確認指令是由後台管理員手動測試發起,還是串接外部線上購買系統產出的取貨指令? + +### 4.2 失敗處理機制 (Failure Handling) +2. **自動退款/告警**:若機台 PUT 回報出貨失敗,雲端是否需要自動發起退款(針對線上訂單)或發送維修告警通知? + +### 4.3 指令效期與防重 (TTL & Idempotency) +3. **指令效期**:如果指令發出後機台失聯,該指令應在多久後失效 (TTL)? +4. **防重複機制**:如何嚴格確保同一個 `command_id` 不會被重複執行兩次? + +### 4.4 安全性與權限 (Security) +5. **指令簽名**:除了 `api_token`,發送出貨指令是否需要額外的加密簽名驗證以防偽造? +6. **權限限制**:是否限制僅特定高級管理員可發起此類高風險指令? + +### 4.5 欄位定義 +7. **URL {workid}**:確認是否對標 `serial_no`。 diff --git a/docs/b220_technical_spec.md b/docs/b220_technical_spec.md new file mode 100644 index 0000000..be3a239 --- /dev/null +++ b/docs/b220_technical_spec.md @@ -0,0 +1,51 @@ +# B220 API (零錢機庫存變動) 技術規範與執行指南 + +本文件定義 B220 API 的技術實作規範,用於監控機台內的硬幣與鈔票庫存數量,並提供補幣紀錄與找零水位告警功能。 + +--- + +## 1. 業務情境與數據特性 + +### 1.1 數據採集 +* **回報內容**:機台定期回報各面額(1, 5, 10, 50, 100, 500, 1000 元)的**當前累積總量 (Total Amount)**。 +* **操作識別**: + * `account = 0`:消費者交易引起的庫存變動。 + * `account != 0`:管理員或補貨員進行手動補幣或清空錢箱的操作。 + +### 1.2 報表與對帳 +* **零錢庫存分析**:系統必須保留所有變動紀錄,以提供後台「分析報表 > 零錢庫存分析」選單顯示歷史庫存走勢與補幣紀錄。 + +--- + +## 2. 執行面優化與告警 (Execution & Alerts) + +### 2.1 高頻數據處理 (待確認頻率) +* **快取策略**:機台各面額的最新總量應快取於 Redis 或更新至 `machines` 表的擴充欄位,供後台儀表板即時監看。 +* **寫入過濾**:為節省儲存空間,建議僅在資料數值有實際變動時才寫入 `coin_inventory_logs`。 + +### 2.2 找零不足告警 (Low Inventory Warning) +* **機制**:當特定面額(如 5 元、10 元硬幣)低於預設的水位閾值時,系統應: + * 在管理後台儀表板顯示紅字告警。 + * (選配)發送推播或系統通知給補貨人員。 + +--- + +## 3. 資料庫結構:`coin_inventory_logs` + +| 欄位 | 說明 | 備註 | +|------|------|------| +| `machine_id` | 機台關聯 ID | | +| `value_x` | 各面額數量 | 包含 1, 5, 10, 50, 100, 500, 1000 | +| `account` | 操作人識別 | 0 為消費者,其餘為管理員 | +| `created_at` | 紀錄時間 | | + +--- + +## 4. 待確認事項 (To-be-confirmed) + +### 4.1 系統效能與頻率 +1. **回報頻率**:確認機台呼叫 B220 的頻率(是每次交易後即時回報,還是定時回報?)。 + +### 4.2 告警配置 +2. **水位閾值**:各面額的最低告警水位數值(如 5 元低於多少枚觸發告警)。 +3. **通知方式**:觸發告警時的具體通知管道。 diff --git a/docs/b600_technical_spec.md b/docs/b600_technical_spec.md new file mode 100644 index 0000000..a47dc90 --- /dev/null +++ b/docs/b600_technical_spec.md @@ -0,0 +1,52 @@ +# B600 API (消費金流回傳) 技術規範與執行指南 + +本文件定義 B600 API 的技術實作規範,這是系統處理金流交易、訂單生成與跨 API 關聯的核心。 + +--- + +## 1. 交易生命週期與 `flow_id` 串聯 + +為確保一筆交易數據的完整性,系統採用 `flow_id` 串聯三個連續上報的 API: + +1. **B600 (金流上報)**: + * 機台於支付成功後即時呼叫。 + * 雲端收到後產出專屬的 `flow_id` 並回傳給機台。 +2. **B601 (發票上報)**: + * 機台開立發票後,攜帶 B600 取得的 `flow_id` 呼叫。 + * 系統根據 `flow_id` 將發票資訊與 `orders` 表關聯。 +3. **B602 (出貨上報)**: + * 機台實體出貨後,攜帶 `flow_id` 呼叫。 + * 系統根據 `flow_id` 更新訂單的出貨狀態。 + +--- + +## 2. 金流類型與標準化 + +### 2.1 類型定義 +根據 B600 PDF 文件規範 (Req3),系統優先採用以下預定義類型進行處理與對帳。 + +### 2.2 防重複上報 (Idempotency) +為防止網路不穩導致機台重複呼叫 B600,系統必須使用機台產生的 `order_no (tid)` 結合 `machine_id` 作為唯一鍵值校驗。 + +--- + +## 3. 執行面優化:異步隊列 (Async Queue) + +在高併發環境下,為確保機台端不因等待資料庫寫入而時耗,B600 採以下流程: + +1. **即時回應**:API 接收請求後,將原始 JSON 派發至 **Redis Queue**。 +2. **背景處理**:由 `ProcessTransaction` 任務異步執行: + * 建立 `orders` 與 `order_items`。 + * 計算並異動會員點數/優惠券。 + * 同步更新儀表板統計數據。 +3. **異步回傳**:機台呼叫 API 後會收到 `202 Accepted`,`flow_id` 則透過回應檔同步回傳。 + +--- + +## 4. 待確認事項 (To-be-confirmed) + +### 4.1 數據完整性稽核 +1. **自動對帳**:是否需要定期自動比對「B600 收取金額」與「B602 實際出貨金額」,並將差異標記為異常訂單? + +### 4.2 失敗補償邏輯 +2. **出貨失敗處理**:若 B602 回報「出貨失敗」,系統是否需觸發自動退款程序(限線上支付)或發送補發通知? diff --git a/docs/b601_technical_spec.md b/docs/b601_technical_spec.md new file mode 100644 index 0000000..2462e1b --- /dev/null +++ b/docs/b601_technical_spec.md @@ -0,0 +1,49 @@ +# B601 API (發票資訊回傳) 技術規範與執行指南 + +本文件定義 B601 API 的技術實作規範,用於紀錄每筆訂單對應的電子發票資訊。 + +--- + +## 1. 業務流程與角色定義 + +### 1.1 系統角色 +* **機台端**:負責與電子發票系統對接、開立發票,並於取得發票號碼後將資訊回傳至雲端。 +* **雲端 (Star Cloud)**:僅負責**紀錄 (Logging)** 發票資訊,不涉及上傳傳財政部平台或寄送中獎通知。 + +### 1.2 串聯機制 +* **關聯 ID**:必須攜帶 B600 取得的 `flow_id`,以便將發票資訊正確掛載至對應的 `orders`。 + +--- + +## 2. 資料庫結構:`invoices` + +為符合台灣發票規範,除了原始 PDF 欄位外,本系統將擴充相關稅務欄位: + +| 欄位 | 說明 | 備註 | +|------|------|------| +| `order_id` | 訂單關聯 ID | 透過 `flow_id` 對應 | +| `invoice_no` | 發票號碼 | 例:AB-12345678 | +| `invoice_date` | 發票日期 | | +| `random_number` | 隨機碼 | 4 位數 | +| `love_code` | 愛心碼 | 捐贈碼 | +| `business_tax_id` | **公司統編** | 8 位數 | +| `carrier_id` | **載具編號** | 手機條碼或自然人憑證 | +| `carrier_type` | **載具類型** | | +| `status` | **發票狀態** | 1:有效, 0:作廢 | + +--- + +## 3. 發票作廢機制 (Invoice Voiding) + +* **需求確認**:當交易發生退款或特定失敗情境時,機台端需具備回報「發票作廢」的能力。 +* **API 實作**: + * **方法一**:呼叫 B601 POST 時帶入 `status = 0`。 + * **方法二**:新增 `/api/app/B601/void` 專屬端點(待後續細化)。 + +--- + +## 4. 待確認事項 (To-be-confirmed) + +### 4.1 邏輯關聯與超時 +1. **發票缺失標記**:若收到 B600 (金流) 但在預設時間內(如 5 分鐘)未收到 B601,後台是否應將該訂單標記為「發票缺失」以供巡檢。 +2. **重試機制**:機台端在 B601 呼叫失敗時的緩存與重傳策略。 diff --git a/docs/b602_technical_spec.md b/docs/b602_technical_spec.md new file mode 100644 index 0000000..a1b47be --- /dev/null +++ b/docs/b602_technical_spec.md @@ -0,0 +1,50 @@ +# B602 API (出貨回傳) 技術規範與執行指南 + +本文件定義 B602 API 的技術實作規範,用於紀錄機台實體出貨結果,並作為訂單完結與庫存校準的依據。 + +--- + +## 1. 業務邏輯與交易完結 + +### 1.1 串聯機制 +* **關聯 ID**:必須攜帶 B600 取得的 `flow_id`,以確保出貨紀錄正確鏈結至對應的 `orders`。 + +### 1.2 多品項交易處理 (Multi-item Orders) +* **一對多關係**:系統支持一筆訂單(同一個 `flow_id`)對應多筆 `dispense_records`。 +* **上報方式**:機台每完成一個貨道之出貨即呼叫一次 B602。雲端後端將自動彙整所有關聯之出貨紀錄以計算該訂單之總體狀態。 + +--- + +## 2. 庫存一致性機制 (Stock Consistency) + +為確保雲端與機台端的物理庫存同步,系統採以下策略: + +1. **強制信任機制**:系統將「強制信任」機台在 B602 中回報的 `remaining_stock` (絕對值),並直接更新資料庫中的貨道庫存。 +2. **異常監控**:若機台回報的庫存與系統計算的預期值(原值 - 1)不符時,系統應於後台標記該次出貨為「庫存異動異常」,供管理員檢查是否發生卡貨或漏貨。 + +--- + +## 3. 資料庫結構:`dispense_records` + +| 欄位 | 說明 | 備註 | +|------|------|------| +| `order_id` | 訂單 ID | 透過 `flow_id` 關聯 | +| `product_id` | 商品 ID | 出貨之商品 | +| `slot_no` | 貨道編號 | 出貨之貨道 | +| `dispense_status` | 出貨狀態 | 0: 成功, 1: 失敗 | +| `remaining_stock` | 剩餘庫存 | 機台回報之絕對值 | +| `source` | 來源標記 | `local` (B602), `remote` (B055) | + +--- + +## 4. 待確認事項 (To-be-confirmed) + +### 4.1 訂單完結判斷 +1. **超時標記**:若雲端收到 B600 但遲遲未收到 B602,預設在多久後應將訂單標記為「出貨超時」? +2. **狀態遷移**:出貨失敗 (`status=1`) 時,訂單的最終顯示文字與處理流程。 + +### 4.2 營收與點數處理 +3. **出貨失敗補償**:若 B602 回報失敗: + * 行動支付是否自動觸發退款? + * 是否自動退回該次交易所扣除之會員點數與優惠券? +4. **現金交易失敗**:出貨失敗且為現金交易時,是否應產出待維護工單或通知補貨員。 diff --git a/docs/b650_technical_spec.md b/docs/b650_technical_spec.md new file mode 100644 index 0000000..79c1bb7 --- /dev/null +++ b/docs/b650_technical_spec.md @@ -0,0 +1,46 @@ +# B650 API (會員/點數/取貨碼驗證) 技術規範與執行指南 + +本文件定義 B650 API 的技術實作規範,用於處理會員驗證、點數折抵、優惠券兌換、取貨碼驗證以及線上訂單線下結帳等多元功能。 + +--- + +## 1. 業務功能與驗證類型 (req6) + +根據 API 請求中的 `req6` 欄位,B650 提供以下驗證模式: + +| req6 | 說明 | 核心流程 | +|------|------|----------| +| `0` | 點擊商品驗證 | 驗證會員資格與點數餘額 | +| `1` | 會員純驗證 | 僅確認會員身份是否有效 | +| `2` | 會員兌換商品清單 | 撈取該會員可使用的兌換券或贈品清單 | +| `3` | 線上訂單線下結帳 | 驗證取貨碼或訂單編號 | +| `4` | 會員贈品 | 處理行銷活動贈品領取 | + +--- + +## 2. 執行面機制 (Execution Strategy) + +* **高可用性請求**:由於會員驗證通常發生在交易前夕,API 必須具備極速響應能力,建議與第三方系統(若有)採用高效能通訊協議。 +* **Response 狀態碼校驗**:系統必須嚴格遵守 PDF 定義的狀態碼(如 `101` 全額折抵, `104` 線上訂單驗證成功, `30` 會員使用中等)進行前端反饋。 + +--- + +## 3. 待確認事項 (To-be-confirmed) + +以下議題目前皆列為**待確認**,將於 Phase 2 或後續討論中釐清: + +### 3.1 會員系統架構 (Architecture) +1. **資料主體**:Star Cloud 是直接管理會員資料庫,還是僅作為轉發請求至第三方 CRM 的代理伺服器? + +### 3.2 安全與防雙重消費 (Security) +2. **鎖定機制**:是否需要在 Redis 實作「會員操作 Session」,防止同一帳號在多台機台同時扣點 (狀態碼 30)? +3. **Token 時效**:回傳之 `userToken` 的有效期與刷新機制。 + +### 3.3 線上/線下整合流程 +4. **訂單轉換**:驗證取貨碼成功後,雲端是否應自動產出對應的銷售紀錄單? + +### 3.4 扣點邏輯 +5. **預扣 vs 實扣**:點數與優惠券應於 B650 驗證時預先鎖定,還是待 B602 出貨成功後才正式扣除? + +### 3.5 界面展示需求 +6. **商品資訊**:當 `req6 = 2` 時,回傳的產品清單是否需要包含圖片或詳細描述供機台屏幕顯示? diff --git a/docs/b710_technical_spec.md b/docs/b710_technical_spec.md new file mode 100644 index 0000000..2ce4898 --- /dev/null +++ b/docs/b710_technical_spec.md @@ -0,0 +1,49 @@ +# B710 API (計時器狀態回傳) 技術規範與執行指南 + +本文件定義 B710 API 的技術實作規範,用於處理計時型設備(如洗衣服務、按摩服務)的剩餘時間監測與狀態回報。 + +--- + +## 1. 業務流程與資料流 + +### 1.1 狀態回報 +* **回報內容**:機台定期回報特定貨道 (product/timer) 的 `remaining_seconds` (剩餘秒數) 與目前狀態。 +* **資料用途**: + * **即時監控**:供管理後台儀表板顯示設備的使用進度。 + * **稼動分析**:紀錄設備的總租用時數與閒置率。 + +--- + +## 2. 執行面機制 (Execution Strategy) + +* **異步處理**:由於計時狀態可能高頻回報,系統應優先將數據更新至 **Redis 快取**,以確保前端查詢的高效能與資料庫的負擔平衡。 + +--- + +## 3. 資料庫結構:`timer_statuses` + +| 欄位 | 說明 | 備註 | +|------|------|------| +| `machine_id` | 機台 ID | | +| `product_id` | 產品/服務 ID | | +| `remaining_seconds` | 剩餘秒數 | | +| `status` | 運行狀態 | 1:運行中, 0:停止 | + +--- + +## 4. 待確認事項 (To-be-confirmed) + +以下議題目前皆列為**待確認**,將於後續開發階段釐清: + +### 4.1 回報頻率與快取 +1. **更新頻率**:確認機台呼叫 B710 的精確頻率,以及資料庫寫入的節流策略(例如:僅在關鍵變動或每分鐘寫入一次)。 + +### 4.2 遠端通知與異常 +2. **結束通知**:倒數結束時,雲端是否需主動對對消費者發送推播或系統訊息? +3. **斷線判定**:針對長期未回報的計時器,雲端應自動判定為結束還是異常? + +### 4.3 復歸機制 +4. **斷電補償**:機台意外斷電重啟後,是否需向雲端 B010 撈回最後的剩餘秒數以恢復服務? + +### 4.4 報表需求 +5. **稼動分析**:後台是否需要針對此數據計算「設備利用率」等績效指標。 diff --git a/docs/rbac_architecture.md b/docs/rbac_architecture.md new file mode 100644 index 0000000..e6d20de --- /dev/null +++ b/docs/rbac_architecture.md @@ -0,0 +1,55 @@ +# Star Cloud 多租戶與權限架構 (Multi-Tenant RBAC) 實作規劃 + +## 1. 架構目標 +為了支援 Star Cloud 系統具備 B2B SaaS 的多租戶特性,讓「系統管理員(內部營運)」與「租戶(客戶公司)」能在同一套後台中共存。各租戶能自行建立子帳號並分配權限,且資料彼此絕對隔離。 + +將導入基於 `companies` 的租戶隔離,並結合 `spatie/laravel-permission` 實作多租戶的角色權限控制。 + +--- + +## 2. 核心實作架構 + +### 2.1 租戶隔離層 (Tenant Isolation) +建立實體的租戶邊界,確保每個客戶在物理與邏輯上只能存取自己的資料。 +* **變更**:新增 `companies` 表(公司名稱、統編、狀態等)。 +* **綁定**:在 `users`, `machines`, 等核心資源表中加上 `company_id`。 +* **身份判定**: + * `company_id = null`:系統預設管理員(內部工程師 / 營運人員),具備跨公司存取能力。 + * `company_id = N`:客戶端帳號(租戶)。 + +### 2.2 角色與權限層 (Roles & Permissions) +利用 `spatie/laravel-permission` 結合多租戶。 +* **全域權限 (Permissions)**:定義系統所有的最小操作單位(如 `machine.view`, `user.create`),所有租戶共用權限定義。 +* **多租戶角色 (Tenant-Aware Roles)**:原本套件的 `roles` 表必須擴充加上 `company_id` 欄位。 + * 系統預設角色 (`company_id = null`):如 Super Admin。 + * 客戶自建角色 (`company_id = N`):如客戶自定義的「台北區維修員」,只能分配給統一個 `company_id` 的使用者。 + +### 2.3 流程控制與防禦 (Flow Control) +* **自動過濾 (Global Scopes)**:寫一個 Trait `TenantScoped`,當非內部人員登入時,自動幫 Eloquent Model 的所有查詢加上 `where('company_id', auth()->user()->company_id)`。 +* **越權防禦 (Create User)**:租戶在後台建立「新子帳號」時,API Controller 必須在背景強制 `NewUser->company_id = Auth::user()->company_id`。 +* **角色分配防禦**:客戶分配角色給員工時,只能撈取並指定 `company_id` 與自己相同的 Role。 + +--- + +## 3. 實作步驟 (對應 Phase 1 與 Phase 3) + +### 步驟 1:資料庫結構 (Migrations) +1. 建立 `create_companies_table` migration。 +2. 建立 `add_company_id_to_users_table` migration。 +3. 調整 `machines` 及其他資源表,加入 `company_id` 欄位與外鍵。 +4. 安裝並發布 `spatie/laravel-permission` migrations,並接續寫一個 migration 為 `roles` 和 `permissions` 調整結構 (加入 `company_id` 至 `roles`)。 + +### 步驟 2:Eloquent Models 與 Scopes 修改 +1. 建立 `Company` Model (`App\Models\System\Company`)。 +2. 修改 `User` Model (`App\Models\Member\User`),加入 `company()` 關聯與 Helper methods (`isSystemAdmin()`, `isTenant()`)。 +3. 建立 `TenantScoped` Trait,包含 Laravel Global Scope 邏輯。套用至 `Machine` 等需要隔離的 Model。 + +### 步驟 3:後端流程與介面防禦 (Middleware & Controllers) +1. 建立 `CheckTenantAccess` Middleware 進行基礎的路由存取權限卡控。 +2. 在後台的「帳號與權限」模組中,實作過濾邏輯: + * 撈取使用者、角色列表時帶入 `company_id`。 + * 創建或修改時強制綁定 `Auth::user()->company_id`。 + +### 步驟 4:前端 Blade 呈現切換 +1. 使用 Blade 的 `@if(auth()->user()->isSystemAdmin())` 在 Sidebar 中隱藏或顯示「全站管理」、「合約設定」等專屬區塊。 +2. 確保一般租戶登入時,左側選單僅顯示其有權限存取的「機台管理」、「我的專屬會員」、「所屬帳號設定」等區塊。