002-voucher-ui-enhancement
功能規格:卡券系統 UI/UX 優化
功能分支: 002-voucher-ui-enhancement
建立日期: 2025-11-30
狀態: 草稿
輸入: 使用者描述:「根據 2025-11-30 會議記錄,針對卡券匯入與帳號綁定系統進行 UI/UX 優化,包含:全名搜尋調整、顧客搜尋顯示生日、卡券表格字體調整、頁籤佈局調整、綁定記錄顯示優化、開卡功能整合、卡券作廢功能、卡券來源欄位、綁定/解綁歷程獨立頁籤等。」
依賴: 此規格為 001-voucher-account-binding 的延續與增強
澄清
Session 2025-11-30
- Q: 「全名」欄位的資料來源? → A: 系統自動從「姓」+「名」組合產生
- Q: 「開卡」功能是什麼? → A: 開卡是既有功能(已有 API 實作),用於設計師手動新增單張卡券
- Q: 卡券拿掉/開錯卡的處理方式? → A: 軟刪除,將卡券標記為「已作廢」
- Q: 卡券 source 欄位的值? → A:
manual(手動開卡)vsimported(批次匯入) - Q: 已移除顧客卡卷(視覺化)的呈現方式? → A: 使用不同 Icon 區分操作類型:🔗(綁定)vs 🔓(解綁)
Grooming Session 2025-11-30
設計決策確認:
全名欄位實作
- 決策:新增
User.full_name實際欄位(String(100), nullable, indexed) - 值:由
last_name+first_name組合產生 - 當姓名都為空時:
full_name允許為 null
- 決策:新增
卡券綁定架構(雙軌系統)
- 匯入卡券(
imported_vouchers):- 匯入後可綁定客戶,使用
bound_customer_id欄位記錄 - 綁定時同步新增
voucher_binding記錄(用於歷程追蹤) - 支援解綁操作(
bound_customer_id設為 NULL)
- 匯入後可綁定客戶,使用
- 手動開卡(
vouchers):- 開卡時直接指定
customer_id,不可變更 - 不透過
voucher_binding記錄綁定關係 - 使用
source欄位區分來源(manual|imported)
- 開卡時直接指定
- 綁定歷程(
voucher_binding):- 只記錄
imported_vouchers的綁定/撤銷歷程 - 欄位:
imported_voucher_id,customer_id,bound_at,revoked_at
- 只記錄
- 匯入卡券(
三種卡券操作定義
- 解綁(Unbind):
- 對象:
imported_vouchers已綁定的卡券 - 操作:
bound_customer_id = NULL,status = 'UNBOUND' - 權限:EMPLOYEE 以上
- UI:✅ 有介面
- 對象:
- 撤銷(Revoke):
- 對象:已綁定的匯入卡券(透過
voucher_binding綁定的) - 操作:
voucher_binding.revoked_at = NOW()+ 軟刪除vouchers及voucher_items - 權限:僅 ADMIN
- UI:❌ 僅 API
- 對象:已綁定的匯入卡券(透過
- 剪卡(Void):
- 對象:手動開卡的
vouchers(未綁定客戶) - 操作:軟刪除
vouchers及voucher_items(is_deleted = TRUE) - 權限:僅 ADMIN
- UI:❌ 僅 API
- 對象:手動開卡的
- 解綁(Unbind):
客戶搜尋功能
- 搜尋範圍:全名 + 電話 + 生日(複合搜尋)
- 效能要求:500ms 內回應,需建立
full_name索引 - 無結果處理:顯示「查無符合的客戶」提示文字
使用者場景與測試 (必填)
使用者故事 1 - 客戶搜尋與顯示優化 (優先級: P1)
設計師在進行卡券綁定時,需要快速且準確地搜尋客戶。系統需新增「全名」欄位(由姓+名自動組合),並使用此全名欄位進行模糊搜尋,取代原本的姓名分開搜尋方式。此外,搜尋結果必須顯示客戶生日資訊,方便設計師確認客戶身份。
優先級理由: 這是設計師日常操作最頻繁的功能,搜尋效率直接影響工作流程。全名搜尋能更準確地匹配客戶,生日顯示能協助確認同名客戶。
獨立測試: 可透過輸入客戶姓名搜尋,驗證系統使用全名欄位進行模糊搜尋,並確認搜尋結果中顯示客戶生日。
驗收場景:
- Given 系統中有客戶資料(姓:王、名:小明、生日:03/15),When 系統計算全名欄位,Then 全名欄位值為「王小明」
- Given 設計師在客戶搜尋輸入「王小」,When 執行搜尋,Then 系統使用全名、電話、生日欄位進行複合模糊搜尋,返回所有符合條件的客戶,回應時間應在 500ms 內
- Given 搜尋結果 Modal 顯示客戶清單,When 設計師檢視清單內容,Then 每位客戶的資訊必須包含:全名、電話、生日(MMDD格式)
- Given 系統中有兩位客戶全名都是「王小明」但生日不同(0315 和 0720),When 搜尋結果顯示,Then 設計師可透過生日欄位區分兩位客戶
- Given 設計師搜尋「不存在的客戶」,When 搜尋完成,Then 系統顯示「查無符合的客戶」提示文字
使用者故事 2 - 綁定/解綁歷程獨立頁籤 (優先級: P1)
設計師需要查看匯入卡券的綁定與撤銷歷程記錄(透過 voucher_binding 記錄的操作),以追蹤操作歷史和責任歸屬。系統需提供獨立的「綁定/解綁歷程」頁籤,顯示完整的操作記錄,並使用視覺化 Icon 區分不同操作類型。歷程支援依操作類型和時間區間篩選,預設顯示最近一週的記錄。
優先級理由: 操作歷程是追蹤和稽核的重要依據,獨立頁籤能讓設計師快速找到所需資訊,Icon 區分能提升可讀性。篩選功能能快速定位特定時間段的操作。
獨立測試: 可透過切換至歷程頁籤,驗證系統顯示所有綁定/撤銷記錄,並確認 Icon 正確區分操作類型,篩選功能正常運作。
驗收場景:
- Given 設計師進入卡券管理介面,When 檢視頁籤列表,Then 系統顯示獨立的「綁定/解綁歷程」頁籤
- Given 設計師點擊「綁定/解綁歷程」頁籤,When 頁面載入完成,Then 系統顯示歷程記錄表格,包含欄位:操作設計師、卡券 ID、操作類型、顧客名稱(全名)、操作時間,預設顯示最近一週的記錄
- Given 歷程記錄中有一筆綁定操作(
revoked_at IS NULL),When 顯示該筆記錄,Then 操作類型欄位顯示 🔗 Icon 並標示「綁定」 - Given 歷程記錄中有一筆撤銷操作(
revoked_at IS NOT NULL),When 顯示該筆記錄,Then 操作類型欄位顯示 🔓 Icon 並標示「已撤銷」,並顯示撤銷時間 - Given 歷程記錄表格有多筆資料,When 檢視排序,Then 記錄依操作時間倒序排列(最新在最上方)
- Given 設計師使用篩選功能,When 選擇「僅綁定」,Then 系統只顯示
revoked_at IS NULL的記錄 - Given 設計師使用篩選功能,When 選擇「已撤銷」,Then 系統只顯示
revoked_at IS NOT NULL的記錄 - Given 設計師使用時間區間篩選,When 選擇「最近一個月」,Then 系統顯示最近 30 天內的記錄
- Given 歷程記錄超過 20 筆,When 檢視表格,Then 系統提供分頁功能,每頁顯示 20 筆記錄
使用者故事 3 - 開卡功能與紀錄整合 (優先級: P2)
設計師除了批次匯入卡券外,也需要能夠手動開立單張卡券。系統需整合既有的開卡 API,並在卡券資料中新增 source 欄位區分來源(manual 手動開卡 vs imported 批次匯入)。開卡紀錄需與綁定紀錄分開顯示,便於追蹤。
優先級理由: 開卡是既有功能,需確保與新系統整合順暢。來源欄位能幫助追蹤卡券的建立方式,對於資料分析和問題排查很重要。
獨立測試: 可透過手動開卡操作,驗證系統正確記錄卡券來源為 manual,並在紀錄中與匯入卡券區分顯示。
驗收場景:
- Given 設計師透過手動開卡功能建立新卡券,When 卡券建立成功,Then 該卡券的
source欄位值為manual - Given 設計師透過批次匯入建立卡券,When 匯入成功,Then 這些卡券的
source欄位值為imported - Given 卡券列表中有手動開卡和匯入的卡券,When 顯示列表,Then 系統能透過來源欄位區分並標示卡券來源
- Given 設計師手動開卡失敗(例如卡號重複),When 錯誤發生,Then 系統顯示明確錯誤訊息,並將錯誤記錄到系統日誌
使用者故事 4 - 卡券操作功能(解綁/撤銷/剪卡) (優先級: P2)
系統需要提供三種卡券操作功能,分別對應不同的業務場景:
解綁(Unbind):設計師需要解除匯入卡券與客戶的綁定關係,使卡券可重新綁定給其他客戶。此操作透過 UI 執行,權限為 EMPLOYEE 以上。
撤銷(Revoke):管理員需要撤銷錯誤的綁定操作並移除相關卡券記錄。此操作僅透過 API 執行,權限僅限 ADMIN,操作具永久性(軟刪除)。
剪卡(Void):管理員需要作廢手動開錯的卡券。此操作僅透過 API 執行,權限僅限 ADMIN,操作具永久性(軟刪除)。
優先級理由: 這些操作是資料維護的基本需求,能處理人為錯誤。解綁是日常操作,撤銷和剪卡是管理功能,軟刪除確保資料可追溯性,符合稽核需求。
獨立測試: 可分別測試三種操作,驗證權限控制、資料變更正確性,以及軟刪除的卡券不再出現於可用清單中。
驗收場景:
解綁操作
- Given 設計師(EMPLOYEE 角色)檢視一張已綁定客戶的匯入卡券(
imported_vouchers.bound_customer_id不為 NULL),When 點擊「解綁」按鈕,Then 系統彈出確認視窗,顯示卡券資訊和綁定客戶姓名 - Given 解綁確認視窗已開啟,When 設計師點擊「確認解綁」,Then 系統更新
imported_vouchers.bound_customer_id = NULL和status = 'UNBOUND',顯示「解綁成功」訊息 - Given 卡券已解綁,When 設計師再次搜尋該卡券,Then 該卡券顯示為未綁定狀態,可重新綁定給任何客戶(包含原客戶)
撤銷操作(API only)
- Given 管理員(ADMIN 角色)透過 API 呼叫撤銷端點,對象為已綁定的匯入卡券,When API 執行成功,Then 系統更新
voucher_binding.revoked_at = NOW(),並軟刪除相關的vouchers.is_deleted = TRUE和voucher_items.is_deleted = TRUE - Given 卡券綁定已撤銷,When 查詢有效綁定記錄,Then 該記錄不出現(因
revoked_at IS NOT NULL) - Given 非 ADMIN 角色嘗試呼叫撤銷 API,When API 執行,Then 系統返回 403 Forbidden 錯誤
剪卡操作(API only)
- Given 管理員(ADMIN 角色)透過 API 呼叫剪卡端點,對象為未綁定客戶的手動開卡卡券,When API 執行成功,Then 系統軟刪除
vouchers.is_deleted = TRUE和voucher_items.is_deleted = TRUE - Given 卡券已剪卡,When 設計師搜尋卡券,Then 該卡券不出現在可用卡券列表中(因
is_deleted = TRUE) - Given 管理員嘗試剪卡一張已綁定客戶的卡券,When API 執行,Then 系統返回錯誤「此卡券已綁定客戶,無法剪卡」
- Given 非 ADMIN 角色嘗試呼叫剪卡 API,When API 執行,Then 系統返回 403 Forbidden 錯誤
使用者故事 5 - 介面佈局與視覺優化 (優先級: P3)
為提升使用者體驗,系統需調整頁籤順序(共 4 個頁籤:卡券綁定 → 卡券管理 → 綁定/解綁歷程 → 卡券匯入)、將綁定按鈕放置於 footer 區域、以及將卡券表格字體從 14px 增大到 16px 以提升可讀性。
優先級理由: 這是視覺優化,不影響核心功能但能提升使用體驗。相對於功能性需求,優先級較低。
獨立測試: 可透過檢視介面佈局,驗證頁籤順序、按鈕位置和字體大小符合設計要求。
驗收場景:
- Given 設計師進入卡券管理介面,When 檢視頁籤順序,Then 頁籤依序為:1) 卡券綁定、2) 卡券管理、3) 綁定/解綁歷程、4) 卡券匯入(最右邊)
- Given 設計師在卡券綁定頁面,When 檢視頁面佈局,Then「確認綁定」按鈕位於頁面 footer 區域(固定於底部)
- Given 設計師搜尋卡券後,When 檢視卡券表格,Then 表格字體大小為 16px(原為 14px),提升可讀性
- Given 綁定記錄列表顯示,When 檢視記錄內容,Then 顯示完整的顧客全名(非 ID)、綁定時間、操作設計師
邊界案例
- 全名為空: 當客戶只有姓或只有名時,全名欄位應正確處理(僅顯示有值的部分);當姓名都為空時,
full_name為 null - 同名同生日: 若存在全名和生日都相同的客戶,搜尋結果應顯示其他可區分資訊(如電話末四碼)
- 解綁後重新綁定: 匯入卡券解綁後,可重新綁定給任何客戶(包含原客戶),無限制
- 軟刪除後的卡券: 已執行撤銷或剪卡的卡券(
is_deleted = TRUE),在所有查詢中應被過濾,不出現在任何可用清單中 - 歷程記錄分頁: 歷程記錄每頁固定顯示 20 筆,超過時自動分頁
- Icon 顯示異常: 當作業系統不支援 emoji 時,應有文字替代方案(「綁定」/「已撤銷」)
- 撤銷永久性: 已撤銷的綁定記錄和已剪卡的卡券無法恢復,操作具永久性
需求 (必填)
功能需求
客戶全名欄位與搜尋
- FR-001: 系統必須在
User資料表新增full_name欄位(String(100), nullable, indexed),值由last_name+first_name組合產生。新增使用者或更新姓名時,系統應自動同步更新full_name欄位。當姓名都為空時,full_name允許為 null。 - FR-002: 客戶搜尋功能必須支援複合搜尋,同時對
full_name、phone、birthday欄位進行模糊查詢,回應時間應在 500ms 內 - FR-003: 客戶搜尋結果 Modal 必須顯示客戶生日資訊(MMDD 格式)
- FR-004: 客戶搜尋無結果時,系統必須顯示「查無符合的客戶」提示文字
卡券表格與佈局
- FR-005: 卡券搜尋結果表格字體大小必須為 16px(原為 14px)
- FR-006: 頁籤順序必須為:1) 卡券綁定、2) 卡券管理、3) 綁定/解綁歷程、4) 卡券匯入(最右邊)
- FR-007: 綁定卡券的「確認綁定」按鈕必須放置於頁面 footer 區域
綁定記錄顯示
- FR-008: 綁定記錄必須顯示顧客全名(非 ID 或部分姓名)
- FR-009: 綁定記錄必須顯示綁定時間(完整日期時間格式)
- FR-010: 綁定記錄必須顯示操作設計師姓名
開卡功能整合
- FR-011: 系統必須整合既有開卡 API,支援設計師手動新增單張卡券
- FR-012:
vouchers表必須新增source欄位(ENUM:manual|imported),區分卡券來源 - FR-013: 手動開卡的卡券
source為manual;從imported_vouchers轉入的卡券source為imported - FR-014: 開卡紀錄失敗時,系統必須將錯誤記錄到系統日誌
卡券操作功能
解綁(Unbind)
- FR-015: 系統必須提供解綁功能(有 UI),允許 EMPLOYEE 以上角色解除
imported_vouchers與客戶的綁定 - FR-016: 解綁操作必須彈出確認視窗,顯示卡券資訊和綁定客戶姓名
- FR-017: 解綁執行時,系統必須更新
imported_vouchers.bound_customer_id = NULL和status = 'UNBOUND' - FR-018: 解綁後的卡券可重新綁定給任何客戶(包含原客戶),無限制
撤銷(Revoke)
- FR-019: 系統必須提供撤銷 API(無 UI),僅 ADMIN 角色可執行
- FR-020: 撤銷操作對象為已透過
voucher_binding綁定的匯入卡券 - FR-021: 撤銷執行時,系統必須:1) 更新
voucher_binding.revoked_at = NOW(),2) 軟刪除vouchers.is_deleted = TRUE,3) 軟刪除所有相關voucher_items.is_deleted = TRUE - FR-022: 撤銷操作具永久性,無法恢復
- FR-023: 非 ADMIN 角色呼叫撤銷 API 時,系統必須返回 403 Forbidden 錯誤
剪卡(Void)
- FR-024: 系統必須提供剪卡 API(無 UI),僅 ADMIN 角色可執行
- FR-025: 剪卡操作對象為手動開卡的
vouchers(未綁定客戶) - FR-026: 剪卡執行時,系統必須:1) 軟刪除
vouchers.is_deleted = TRUE,2) 軟刪除所有相關voucher_items.is_deleted = TRUE - FR-027: 剪卡操作具永久性,無法恢復
- FR-028: 嘗試剪卡已綁定客戶的卡券時,系統必須返回錯誤「此卡券已綁定客戶,無法剪卡」
- FR-029: 非 ADMIN 角色呼叫剪卡 API 時,系統必須返回 403 Forbidden 錯誤
綁定/解綁歷程頁籤
- FR-030: 系統必須提供獨立的「綁定/解綁歷程」頁籤,只顯示
voucher_binding表的記錄(匯入卡券的綁定/撤銷歷程) - FR-031: 歷程記錄必須包含欄位:操作設計師(Employee.name)、卡券 ID、操作類型、顧客名稱(全名)、操作時間
- FR-032: 操作類型必須使用 Icon 視覺化區分:🔗(綁定,
revoked_at IS NULL)、🔓(已撤銷,revoked_at IS NOT NULL) - FR-033: 歷程記錄必須依操作時間倒序排列(最新在最上方)
- FR-034: 已撤銷的綁定記錄必須顯示撤銷時間(
revoked_at) - FR-035: 歷程頁籤必須支援篩選功能:1) 操作類型(全部/僅綁定/已撤銷),2) 時間區間(最近一週/最近一個月/最近三個月/自訂區間),預設顯示最近一週
- FR-036: 歷程記錄必須提供分頁功能,每頁固定顯示 20 筆
關鍵實體
User(使用者/客戶):
- 新增
full_name欄位(String(100), nullable, indexed),由last_name+first_name自動組合
- 新增
ImportedVoucher(匯入卡券):
- 匯入的待綁定卡券清單
- 關鍵欄位:
bound_customer_id(nullable, 綁定的客戶)、status(UNBOUND | BOUND) - 支援解綁操作:設定
bound_customer_id = NULL
Voucher(正式卡券):
- 手動開卡的卡券記錄(開卡時直接指定客戶)
- 新增欄位:
source(ENUM:manual|imported)、customer_id、is_deleted(軟刪除) - 不透過
voucher_binding記錄綁定關係
VoucherItem(卡券項目):
- 卡券的詳細項目(次數、金額等)
- 新增欄位:
is_deleted(軟刪除,跟隨voucher一起作廢)
VoucherBinding(綁定歷程):
- 只記錄
imported_vouchers的綁定/撤銷歷程 - 關鍵欄位:
imported_voucher_id(foreign key)、customer_id、bound_at、revoked_at(nullable, 撤銷時間)、operator_id、operator_role
- 只記錄
成功標準 (必填)
可衡量成果
- SC-001: 設計師使用全名搜尋客戶的成功率達到 95% 以上(首次搜尋即找到目標客戶)
- SC-002: 客戶搜尋結果顯示生日後,同名客戶的選擇錯誤率降低 80%
- SC-003: 設計師能在 5 秒內透過歷程頁籤找到特定卡券的綁定記錄
- SC-004: 卡券作廢操作在 3 步驟內完成(點擊作廢 → 確認 → 完成)
- SC-005: 新頁籤佈局(匯入置右、綁定按鈕在 footer)在使用者測試中獲得 80% 正面評價
- SC-006: 卡券表格字體調整後,設計師閱讀卡券資訊的時間縮短 20%
假設
- 既有開卡 API 已正常運作,本規格僅需整合而非重新開發
- 客戶資料已有
first_name和last_name欄位,系統可據此計算full_name - 系統日誌機制已存在,可直接寫入開卡失敗記錄
- 使用者裝置支援 emoji 顯示(作為 Icon 主要方案)
- 此規格變更與 001-voucher-account-binding 的既有功能相容
VoucherBinding表已存在operator_id和operator_role欄位,可複用記錄操作者- 資料庫支援為
User.full_name欄位建立索引,以達成 500ms 搜尋效能要求 - 綁定/解綁歷程記錄永久保留,無保留期限限制
- 手動開卡功能(
vouchers表)在開卡時就指定客戶,不需要額外的綁定操作 - 系統已有角色權限控制機制(EMPLOYEE, ADMIN, OWNER),可用於操作權限管理
範圍界定
包含在此功能內
- 客戶全名欄位新增與複合搜尋邏輯(全名+電話+生日)
- 客戶搜尋結果顯示生日與無結果提示
- 客戶搜尋效能優化(500ms 內,建立索引)
- 卡券表格字體調整(14px → 16px)
- 頁籤順序調整(4 個頁籤:綁定 → 管理 → 歷程 → 匯入)
- 綁定按鈕位置調整(移至 footer)
- 綁定記錄顯示欄位擴充
- 開卡功能整合與來源欄位(source: manual | imported)
- 三種卡券操作功能:
- 解綁(有 UI,EMPLOYEE 以上)
- 撤銷(API only,ADMIN)
- 剪卡(API only,ADMIN)
- 綁定/解綁歷程獨立頁籤(只顯示 voucher_binding 記錄)
- 歷程篩選功能(操作類型 + 時間區間)
- 歷程分頁功能(每頁 20 筆)
- 操作類型 Icon 視覺化
不包含在此功能內
- 開卡 API 的重新開發(使用既有 API)
- 卡券硬刪除功能(僅支援軟刪除)
- 已撤銷綁定的恢復功能
- 已剪卡卡券的恢復功能
- 客戶
first_name、last_name欄位的新增(假設已存在) - 歷程記錄的匯出功能
- 多語系支援
imported_vouchers的解綁歷程記錄(只記錄透過 voucher_binding 的操作)- 手動開卡(
vouchers)的綁定/解綁功能(開卡時就指定客戶,不可變更)
Change Log
v0.3.0 - Phase 2 Grooming 完成 (2025-12-07)
架構重大調整:
- 確認雙軌卡券綁定系統:
imported_vouchers使用bound_customer_id直接綁定,同步記錄到voucher_bindingvouchers使用customer_id直接綁定,開卡時指定,不透過voucher_binding
- 釐清三種卡券操作:
- 解綁(Unbind):UI 操作,EMPLOYEE 權限,針對
imported_vouchers - 撤銷(Revoke):API 操作,ADMIN 權限,撤銷
voucher_binding並軟刪除vouchers - 剪卡(Void):API 操作,ADMIN 權限,軟刪除手動開卡的
vouchers
- 解綁(Unbind):UI 操作,EMPLOYEE 權限,針對
- 確認歷程頁籤只顯示
voucher_binding的記錄(匯入卡券的綁定/撤銷歷程)
功能需求大幅擴充:
- FR-001~004: 補充搜尋效能要求(500ms)和無結果提示
- FR-005~007: 明確字體大小(16px)和完整頁籤順序
- FR-012~014: 新增
vouchers.source欄位定義 - FR-015~029: 新增三種卡券操作的完整需求(解綁/撤銷/剪卡)
- FR-030~036: 新增歷程篩選功能(操作類型 + 時間區間)和分頁功能
User Story 重寫:
- US2: 補充篩選功能(操作類型 + 時間區間,預設一週)和分頁規格(每頁 20 筆)
- US4: 從單一「作廢功能」重寫為三種操作(解綁/撤銷/剪卡),明確權限和 UI/API 區分
- US5: 補充具體規格(字體 16px、4 個頁籤順序)
關鍵實體修訂:
ImportedVoucher: 新增bound_customer_id和status欄位說明Voucher: 新增source,customer_id,is_deleted欄位VoucherItem: 新增is_deleted欄位VoucherBinding: 明確只記錄imported_vouchers的綁定,欄位包含imported_voucher_id
假設新增:
- 資料庫索引支援(達成 500ms 搜尋效能)
- 歷程記錄永久保留
- 角色權限控制機制已存在
邊界案例更新:
- 補充解綁後重新綁定規則
- 補充撤銷和剪卡的永久性說明
- 更新歷程分頁規格
v0.2.0 - Grooming Session (2025-11-30)
設計決策:
- 確認
full_name為User表的實際欄位,非計算欄位 - 確認撤銷狀態使用
VoucherBinding.revoked_at欄位記錄 - 確認客戶搜尋支援全名+電話+生日複合搜尋
- 確認開卡功能已實作綁定客戶流程
功能需求修訂:
- FR-001: 明確
full_name欄位規格(String(100), nullable, indexed) - FR-002: 擴展為複合搜尋(全名+電話+生日)
- FR-014~018: 從「卡券作廢」調整為「綁定撤銷」概念
- FR-020: 新增撤銷狀態欄位顯示
- FR-023: 新增已撤銷記錄的視覺標記需求
關鍵實體修訂:
- 移除「作廢記錄 (Void Record)」實體
- 新增
VoucherBinding.revoked_at欄位說明 - 更新
User.full_name欄位說明
v0.1.0 - Initial Draft (2025-11-30)
- 初始規格草稿建立