iT邦幫忙

2025 iThome 鐵人賽

DAY 21
0
自我挑戰組

我獨自開發 - Supabase 打造全端應用系列 第 21

第二十ㄧ關 - 來企排隊:資料庫與 API 文件規劃

  • 分享至 

  • xImage
  •  

封面

以下會規劃系統的資料庫架構與 API 設計,涵蓋使用者管理、商家管理、預約系統、即時訊息以及通知功能。

「來企排隊」(LaiQiPaiDui):取自台語「來這裡排隊」的諧音。

「企」是企鵝的企,靈感來自企鵝會有類似排隊行為,因為牠們在軟軟的雪地裡走路,大家都當開路先鵝的話,會耗費太多體力,因此牠們演化出排隊省力的方法,固定在同一個路線,就會都是踩過的路。
而且在下水時,牠們也會排隊,若同時跳下水,會造成水花四濺之外,也有可能互相撞擊,影響其他同伴,因此牠們會一隻接一隻的跳下去。

資料表

1. users - 使用者

管理所有使用者的基本資料和個人化設定。

  • id (UUID, PK): 使用者的唯一識別碼,採用 UUID 確保全域唯一性
  • email (VARCHAR): 電子郵件地址,作為登入憑證
  • name (VARCHAR): 使用者的顯示名稱
  • avatar_url (TEXT): 頭像圖片的儲存位置
  • address (TEXT): 使用者地址,方便計算距離和推薦附近服務
  • notification_settings (JSONB): 通知偏好設定,支援彈性的個人化配置
  • created_at (TIMESTAMP): 帳號建立時間
  • updated_at (TIMESTAMP): 最後更新時間

2. stores - 服務提供者

記錄所有提供預約服務的商家或個人資訊。

  • id (UUID, PK): 商家的唯一識別碼
  • owner_id (UUID, FK): 商家擁有者,關聯到 users 表
  • name (VARCHAR): 商家或服務的名稱
  • description (TEXT): 詳細的服務描述
  • avatar_url (TEXT): 商家的品牌圖片或 Logo
  • address (TEXT): 服務地點
  • contact_email (VARCHAR): 客戶聯絡信箱
  • is_active (BOOLEAN): 控制是否開放預約的開關
  • created_at (TIMESTAMP): 商家註冊時間
  • updated_at (TIMESTAMP): 資訊最後更新時間

3. bookings - 預約系統

預約表是整個排隊系統的心臟,記錄每一筆預約的完整生命週期,從建立到完成的所有狀態變化。

  • id (UUID, PK): 預約的唯一識別碼
  • store_id (UUID, FK): 關聯的商家,建立預約與服務提供者的連結
  • user_id (UUID, FK): 預約的使用者
  • queue_number (INTEGER): 排隊號碼,系統自動分配
  • status (ENUM): 預約狀態,包含 waiting(等待中)、serving(服務中)、completed(已完成)、cancelled(已取消)
  • notes (TEXT): 使用者的特殊需求或備註
  • created_at (TIMESTAMP): 預約建立時間
  • completed_at (TIMESTAMP): 服務完成時間

4. messages - 訊息

訊息表支援使用者與商家之間的一對一即時通訊。

  • id (UUID, PK): 訊息的唯一識別碼
  • booking_id (UUID, FK): 關聯的預約,確保訊息與特定預約綁定
  • sender_id (UUID, FK): 訊息發送者
  • content (TEXT): 訊息內容
  • is_read (BOOLEAN): 已讀狀態,支援訊息狀態追蹤
  • created_at (TIMESTAMP): 訊息發送時間

5. notifications - 通知

通知表管理系統中所有的通知訊息,確保使用者能及時收到重要的狀態更新。

  • id (UUID, PK): 通知的唯一識別碼
  • user_id (UUID, FK): 通知接收者
  • type (ENUM): 通知類型,包含 booking_created(預約建立)、booking_cancelled(預約取消)、queue_updated(排隊更新)、message_received(收到訊息)
  • title (VARCHAR): 通知標題
  • content (TEXT): 通知詳細內容
  • is_read (BOOLEAN): 是否已讀
  • created_at (TIMESTAMP): 通知產生時間

API 設計

依照資料庫設計 RESTful API 來提供前端所需的各種功能。

認證系統

身份驗證的認證流程。

使用者註冊

功能說明: 讓新使用者能夠快速建立帳號。

  • API 路由: POST /auth/register
  • 請求參數:
    {
      "email": "user@example.com",
      "password": "securePassword123",
      "name": "張小明"
    }
    
  • 成功回應:
    {
      "user": {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "email": "user@example.com",
        "name": "張小明"
      },
      "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
    }
    
  • 狀態代碼: 201 Created (成功建立)
  • 錯誤處理: 400 Bad Request (信箱已存在), 422 Unprocessable Entity (格式錯誤)

使用者登入

功能說明: 驗證使用者身份,提供存取權杖進行後續操作。

  • API 路由: POST /auth/login
  • 請求參數:
    {
      "email": "user@example.com",
      "password": "securePassword123"
    }
    
  • 成功回應:
    {
      "user": {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "email": "user@example.com",
        "name": "張小明"
      },
      "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
    }
    
  • 狀態代碼: 200 OK (登入成功)
  • 錯誤處理: 401 Unauthorized (帳密錯誤), 404 Not Found (使用者不存在)

使用者管理

使用者管理模組提供個人資料管理功能。

取得個人資料

功能說明: 查看自己的個人資料,包含基本資訊和偏好設定。

  • API 路由: GET /users/profile
  • 認證要求: Bearer Token (登入後取得)
  • 成功回應:
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "email": "user@example.com",
      "name": "張小明",
      "avatar_url": "https://storage.example.com/avatars/user123.jpg",
      "address": "台北市信義區信義路五段7號",
      "notification_settings": {
        "email_notifications": true,
        "push_notifications": true,
        "sms_notifications": false
      }
    }
    
  • 狀態代碼: 200 OK (成功取得)
  • 錯誤處理: 401 Unauthorized (未登入或 Token 無效)

更新個人資料

功能說明: 允許使用者修改個人資訊,包含姓名、頭像、地址和通知偏好。

  • API 路由: PUT /users/profile
  • 請求參數:
    {
      "name": "張大明",
      "avatar_url": "https://storage.example.com/avatars/new-avatar.jpg",
      "address": "台北市大安區敦化南路二段216號",
      "notification_settings": {
        "email_notifications": true,
        "push_notifications": false,
        "sms_notifications": true
      }
    }
    
  • 成功回應:
    {
      "message": "個人資料更新成功",
      "updated_at": "2024-01-15T10:30:00Z"
    }
    
  • 狀態代碼: 200 OK (更新成功)
  • 錯誤處理: 401 Unauthorized (未登入), 422 Unprocessable Entity (資料格式錯誤)

商家管理

讓服務提供者能夠建立和管理自己的商家資訊。

取得商家列表

功能說明: 提供所有開放預約的商家清單。

  • API 路由: GET /stores
  • 查詢參數:
    {
      "page": 1,
      "limit": 20,
      "search": "咖啡"
    }
    
  • 成功回應:
    {
      "stores": [
        {
          "id": "550e8400-e29b-41d4-a716-446655440001",
          "name": "星巴克信義店",
          "avatar_url": "https://storage.example.com/stores/starbucks.jpg",
          "address": "台北市信義區信義路五段7號",
          "contact_email": "xinyi@starbucks.com.tw",
          "current_queue_count": 8
        },
        {
          "id": "550e8400-e29b-41d4-a716-446655440002",
          "name": "路易莎咖啡",
          "avatar_url": "https://storage.example.com/stores/louisa.jpg",
          "address": "台北市大安區敦化南路二段216號",
          "contact_email": "daan@louisacoffee.com.tw",
          "current_queue_count": 3
        }
      ],
      "total": 25,
      "page": 1,
      "total_pages": 2
    }
    
  • 狀態代碼: 200 OK (成功取得)
  • 錯誤處理: 400 Bad Request (參數格式錯誤)

建立商家

功能說明: 讓使用者建立自己的服務商家。

  • API 路由: POST /stores
  • 請求參數:
    {
      "name": "阿明理髮店",
      "description": "專業理髮服務,20年經驗,提供洗剪吹造型服務",
      "avatar_url": "https://storage.example.com/stores/barber-shop.jpg",
      "address": "台北市中山區中山北路二段48號",
      "contact_email": "ming.barber@example.com"
    }
    
  • 成功回應:
    {
      "id": "550e8400-e29b-41d4-a716-446655440003",
      "name": "阿明理髮店",
      "message": "商家建立成功,開始接受預約!",
      "created_at": "2024-01-15T10:30:00Z"
    }
    
  • 狀態代碼: 201 Created (建立成功)
  • 錯誤處理: 401 Unauthorized (未登入), 422 Unprocessable Entity (資料格式錯誤)

預約管理

預約管理是來企排隊最重要的功能,從建立預約到服務完成的全程。

建立預約

功能說明: 系統會自動分配排隊號碼並估算等待時間。

  • API 路由: POST /bookings
  • 請求參數:
    {
      "store_id": "550e8400-e29b-41d4-a716-446655440001",
      "notes": "希望能安排靠窗的位置,謝謝!"
    }
    
  • 成功回應:
    {
      "id": "550e8400-e29b-41d4-a716-446655440010",
      "queue_number": 15,
      "estimated_wait_time": 45,
      "message": "預約成功!您是第15號,預估等待時間45分鐘"
    }
    
  • 狀態代碼: 201 Created (預約建立成功)
  • 錯誤處理: 401 Unauthorized (未登入), 404 Not Found (商家不存在), 409 Conflict (重複預約同一商家)

查看我的預約

功能說明: 讓使用者查看自己的所有預約記錄。

  • API 路由: GET /bookings/my-bookings
  • 查詢參數:
    {
      "status": "waiting",
      "page": 1,
      "limit": 10
    }
    
  • 成功回應:
    {
      "bookings": [
        {
          "id": "550e8400-e29b-41d4-a716-446655440010",
          "store": {
            "name": "星巴克信義店",
            "avatar_url": "https://storage.example.com/stores/starbucks.jpg",
            "contact_email": "xinyi@starbucks.com.tw"
          },
          "queue_number": 15,
          "status": "waiting",
          "notes": "希望能安排靠窗的位置,謝謝!",
          "created_at": "2024-01-15T09:30:00Z"
        }
      ],
      "total": 3,
      "current_page": 1
    }
    
  • 狀態代碼: 200 OK (成功取得)
  • 錯誤處理: 401 Unauthorized (未登入)

查看收到的預約 (商家端)

功能說明: 讓商家查看所有預約自己服務的客戶列表。

  • API 路由: GET /bookings/received-bookings
  • 查詢參數:
    {
      "store_id": "550e8400-e29b-41d4-a716-446655440001",
      "status": "waiting",
      "page": 1,
      "limit": 20
    }
    
  • 成功回應:
    {
      "bookings": [
        {
          "id": "550e8400-e29b-41d4-a716-446655440010",
          "user": {
            "name": "張小明",
            "avatar_url": "https://storage.example.com/avatars/user123.jpg",
            "email": "user@example.com"
          },
          "queue_number": 15,
          "status": "waiting",
          "notes": "希望能安排靠窗的位置,謝謝!",
          "created_at": "2024-01-15T09:30:00Z"
        }
      ],
      "total": 8,
      "current_page": 1
    }
    
  • 狀態代碼: 200 OK (成功取得)
  • 錯誤處理: 401 Unauthorized (未登入), 403 Forbidden (非商家擁有者)

更新預約

功能說明: 讓商家能夠更新客戶預約的服務狀態,從等待中到服務中再到完成。

  • API 路由: PUT /bookings/{booking_id}/status
  • 請求參數:
    {
      "status": "serving"
    }
    
  • 成功回應:
    {
      "message": "預約狀態已更新為服務中",
      "updated_at": "2024-01-15T10:15:00Z"
    }
    
  • 狀態代碼: 200 OK (更新成功)
  • 錯誤處理: 401 Unauthorized (未登入), 403 Forbidden (非商家擁有者), 404 Not Found (預約不存在)

取消預約

功能說明: 讓使用者能夠取消自己的預約,釋放排隊位置給其他人。

  • API 路由: DELETE /bookings/{booking_id}
  • 成功回應:
    {
      "message": "預約已成功取消",
      "cancelled_at": "2024-01-15T10:00:00Z"
    }
    
  • 狀態代碼: 200 OK (取消成功)
  • 錯誤處理: 401 Unauthorized (未登入), 403 Forbidden (非預約擁有者), 404 Not Found (預約不存在)

聊天系統

聊天系統讓使用者與商家能夠就預約細節進行即時溝通。

取得聊天列表

功能說明: 顯示使用者所有的聊天室。

  • API 路由: GET /chats
  • 成功回應:
    {
      "chats": [
        {
          "booking_id": "550e8400-e29b-41d4-a716-446655440010",
          "store": {
            "name": "星巴克信義店",
            "avatar_url": "https://storage.example.com/stores/starbucks.jpg"
          },
          "last_message": {
            "content": "您的位置準備好了,請前來取餐!",
            "created_at": "2024-01-15T10:20:00Z"
          },
          "unread_count": 1
        }
      ]
    }
    
  • 狀態代碼: 200 OK (成功取得)
  • 錯誤處理: 401 Unauthorized (未登入)

取得聊天訊息

功能說明: 顯示特定預約的完整聊天記錄。

  • API 路由: GET /chats/{booking_id}/messages
  • 查詢參數:
    {
      "page": 1,
      "limit": 50
    }
    
  • 成功回應:
    {
      "messages": [
        {
          "id": "550e8400-e29b-41d4-a716-446655440020",
          "sender": {
            "id": "550e8400-e29b-41d4-a716-446655440000",
            "name": "張小明",
            "avatar_url": "https://storage.example.com/avatars/user123.jpg"
          },
          "content": "請問還需要等多久呢?",
          "is_read": true,
          "created_at": "2024-01-15T10:15:00Z"
        },
        {
          "id": "550e8400-e29b-41d4-a716-446655440021",
          "sender": {
            "id": "550e8400-e29b-41d4-a716-446655440005",
            "name": "星巴克信義店",
            "avatar_url": "https://storage.example.com/stores/starbucks.jpg"
          },
          "content": "大約還需要5分鐘,謝謝您的耐心等候!",
          "is_read": false,
          "created_at": "2024-01-15T10:18:00Z"
        }
      ]
    }
    
  • 狀態代碼: 200 OK (成功取得)
  • 錯誤處理: 401 Unauthorized (未登入), 403 Forbidden (非預約相關人員)

發送訊息

功能說明: 在聊天室中發送訊息。

  • API 路由: POST /chats/{booking_id}/messages
  • 請求參數:
    {
      "content": "謝謝!我馬上過去取餐"
    }
    
  • 成功回應:
    {
      "id": "550e8400-e29b-41d4-a716-446655440022",
      "message": "訊息發送成功",
      "sent_at": "2024-01-15T10:22:00Z"
    }
    
  • 狀態代碼: 201 Created (訊息發送成功)
  • 錯誤處理: 401 Unauthorized (未登入), 403 Forbidden (非預約相關人員), 422 Unprocessable Entity (訊息內容錯誤)

通知系統

確保使用者不會錯過狀態更新,提供多種類型的通知服務。

取得通知列表

功能說明: 顯示使用者的所有通知。

  • API 路由: GET /notifications
  • 查詢參數:
    {
      "is_read": false,
      "page": 1,
      "limit": 20
    }
    
  • 成功回應:
    {
      "notifications": [
        {
          "id": "550e8400-e29b-41d4-a716-446655440030",
          "type": "queue_updated",
          "title": "排隊進度更新",
          "content": "您在星巴克信義店的排隊號碼已前進到第3位!",
          "is_read": false,
          "created_at": "2024-01-15T10:25:00Z"
        },
        {
          "id": "550e8400-e29b-41d4-a716-446655440031",
          "type": "message_received",
          "title": "收到新訊息",
          "content": "星巴克信義店向您發送了一則訊息",
          "is_read": false,
          "created_at": "2024-01-15T10:18:00Z"
        }
      ],
      "unread_count": 2
    }
    
  • 狀態代碼: 200 OK (成功取得)
  • 錯誤處理: 401 Unauthorized (未登入)

標記通知已讀

功能說明: 將特定通知標記為已讀,幫助使用者管理通知狀態。

  • API 路由: PUT /notifications/{notification_id}/read
  • 成功回應:
    {
      "message": "通知已標記為已讀",
      "read_at": "2024-01-15T10:30:00Z"
    }
    
  • 狀態代碼: 200 OK (標記成功)
  • 錯誤處理: 401 Unauthorized (未登入), 404 Not Found (通知不存在)

檔案管理

支援頭像上傳和圖片處理。

上傳頭像

功能說明: 讓使用者和商家能夠上傳個人或品牌頭像。

  • API 路由: POST /upload/avatar
  • 請求格式:
    Content-Type: multipart/form-data
    file: image file (支援 JPG, PNG, WebP,最大 5MB)
    
  • 成功回應:
    {
      "avatar_url": "https://storage.example.com/avatars/user123-new.jpg",
      "message": "頭像上傳成功",
      "uploaded_at": "2024-01-15T10:35:00Z"
    }
    
  • 狀態代碼: 200 OK (上傳成功)
  • 錯誤處理: 401 Unauthorized (未登入), 400 Bad Request (檔案格式不支援), 413 Payload Too Large (檔案過大)

即時功能架構

採用 WebSocket 技術實現即時資料同步,讓使用者能夠即時收到各種狀態更新。

排隊狀態即時更新

功能說明: 當有人預約或取消時,所有相關使用者都會即時收到排隊人數的更新。

  • 事件名稱: queue_updated
  • 觸發時機: 新預約建立、預約取消、預約完成
  • 推送資料:
    {
      "store_id": "550e8400-e29b-41d4-a716-446655440001",
      "current_queue_count": 12,
      "your_position": 8,
      "estimated_wait_time": 35,
      "updated_at": "2024-01-15T10:40:00Z"
    }
    

即時訊息推送

功能說明: 聊天訊息的即時推送。

  • 事件名稱: new_message
  • 觸發時機: 收到新的聊天訊息
  • 推送資料:
    {
      "booking_id": "550e8400-e29b-41d4-a716-446655440010",
      "message": {
        "id": "550e8400-e29b-41d4-a716-446655440022",
        "sender_id": "550e8400-e29b-41d4-a716-446655440005",
        "sender_name": "星巴克信義店",
        "content": "您的餐點準備好了,請前來取餐!",
        "created_at": "2024-01-15T10:45:00Z"
      }
    }
    

預約狀態變更通知

功能說明: 當預約狀態發生變化時,即時通知相關的使用者和商家。

  • 事件名稱: booking_status_changed
  • 觸發時機: 預約狀態從等待中變為服務中,或從服務中變為已完成
  • 推送資料:
    {
      "booking_id": "550e8400-e29b-41d4-a716-446655440010",
      "old_status": "waiting",
      "new_status": "serving",
      "message": "您的服務即將開始,請準備前往現場!",
      "updated_at": "2024-01-15T10:50:00Z"
    }
    

小結

後端架構設計,從資料庫設計到 API 介面,再到即時通訊功能,接下來會開始實際開發,實作前端介面來展示這些功能。

... to be continued

有任何想討論歡迎留言,或需要指正的地方請鞭大力一點,歡迎訂閱、按讚加分享,分享給想要提升開發效率的朋友


上一篇
第二十關 - 來企排隊:網頁地圖/流程圖/時序圖/設計稿
下一篇
第二十二關 - 來企排隊:Supabase 快速建立信箱註冊與登入
系列文
我獨自開發 - Supabase 打造全端應用22
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言