← 回看板
spec

001-voucher-account-binding

功能規格:卡券匯入與帳號綁定系統

功能分支: 001-voucher-account-binding 建立日期: 2025-11-14 狀態: 草稿 輸入: 使用者描述:「我希望有一個匯入卡卷的功能,將客戶的卡卷資料匯入系統中幫助我後續進行綁定帳號。我希望有一個帳號綁定系統,能夠將既有的美髮卡卷資料與真實的註冊客戶進行綁定...」

澄清

Session 2025-11-12

  • Q: 卡券資料欄位是否需要補充? → A: 需要添加「頭皮」至服務大類(洗髮/剪髮/燙髮/染髮/護髮/頭皮),並新增欄位:子類別(細項)、每次使用金額、剩餘次數
  • Q: 驗收場景4(卡券編號重複檢查)是否需要? → A: 不需要,已移除
  • Q: 卡券與客戶的綁定關係為何? → A: 同張卡券只能綁定一個客戶,但客戶可重複綁定多張卡券。已綁定的卡券在搜尋結果中顯示「已綁定」且不可選取
  • Q: 解綁流程是否需要判斷卡券使用狀態? → A: 不需要判斷,解綁就是直接解綁,釋出卡券使其可被重新綁定

Session 2025-11-17 (1)

  • Q: 卡券搜尋姓名是否需要精確比對? → A: 使用模糊搜尋,因為姓名可能有錯字或空格
  • Q: 綁定卡券是否一次只能綁定一張? → A: 支援 checkbox 複選多張卡券,最後按「確認綁定」,跳出防呆視窗顯示被選取的卡券列表做二次確認
  • Q: 服務類別名稱是否需要更新? → A: 更新為「洗髮/剪髮/燙髮/染髮/護髮/頭皮」(統一使用完整名稱)

Session 2025-11-17 (2) - 需求變更

變更背景: 根據實際使用情境優化流程,簡化操作並提升設計師自主性

變更內容:

  1. 使用者故事 1 - 匯入流程簡化:

    • 移除匯入結果報告產生功能,改為失敗時將錯誤記錄到系統日誌(log)
    • 採用「全有或全無」原則:若單一檔案中任何一筆資料匯入失敗,則整個檔案的匯入視為失敗,已匯入資料必須回滾
    • 目的:減少等待時間,確保資料一致性
  2. 使用者故事 2 - 第 10 點客戶搜尋功能:

    • 原:提供卡券編號輸入框進行精確搜尋
    • 改:提供手動搜尋生日(MMDD)和姓名而非卡券編號,使用模糊匹配
    • 目的:更符合實際使用場景,設計師通常透過客戶資訊搜尋卡券
  3. 使用者故事 3 - 設計師自主解綁:

    • 原:解綁需人工處理,提示設計師聯絡系統管理員
    • 改:設計師可自主解綁,點擊解綁後彈出確認視窗,從下拉選單(dropdown)選擇設計師姓名確認身份,確認後記錄解綁紀錄,卡券被釋出可重新綁定
    • 重要細節:未選擇下拉選單時,「確認解綁」按鈕為 disabled 狀態(無需顯示錯誤訊息)
    • 目的:提升設計師自主性,減少對管理員的依賴,同時透過下拉選單確認身份確保操作可追溯

使用者場景與測試 (必填)

使用者故事 1 - 簡化卡券匯入流程 (優先級: P1)

設計師需要將既有客戶的實體卡券資料批次匯入系統,以便後續進行帳號綁定作業。當匯入成功時,系統直接顯示成功訊息;當匯入失敗時,系統不產出匯入結果報告,而是將錯誤詳情記錄在系統日誌(log)中。重要變更:若單一檔案中有任何一筆資料匯入失敗,則整個檔案的匯入操作視為失敗,已匯入的資料必須回滾,不允許部分成功。

優先級理由: 這是整個綁定流程的基礎。沒有匯入卡券資料,就無法進行後續的帳號綁定作業。簡化的流程減少等待時間,並確保資料一致性(全有或全無原則)。

獨立測試: 可透過上傳包含有效和無效資料的檔案,驗證系統拒絕整個匯入並在日誌中記錄錯誤,而不產生報告檔案。

驗收場景:

  1. Given 設計師準備好包含100筆完全有效的卡券資料檔案,When 設計師上傳檔案並執行匯入,Then 系統成功匯入所有100筆資料,顯示「匯入成功:100筆」訊息,不產生任何報告檔案
  2. Given 匯入檔案中包含99筆有效資料和1筆無效資料(第50列剩餘次數為負數),When 匯入執行,Then 系統拒絕整個匯入、顯示「匯入失敗」訊息、將詳細錯誤資訊(檔案名稱、第50列:剩餘次數不得為負數)記錄在系統日誌中、且不匯入任何一筆資料(包含99筆有效資料)
  3. Given 匯入檔案格式錯誤(如缺少必填欄位「服務大類」),When 匯入開始驗證,Then 系統立即拒絕匯入、顯示「檔案格式錯誤」訊息、將錯誤詳情記錄在日誌中
  4. Given 匯入過程中發生系統錯誤(如資料庫連線中斷),When 匯入中止,Then 系統回滾所有已匯入的資料、顯示「匯入失敗」訊息、將錯誤堆疊記錄在系統日誌中

使用者故事 2 - 客戶搜尋與卡券綁定 (優先級: P2)

設計師需要在同一頁面中完成客戶搜尋和卡券綁定的完整流程。首先透過電話號碼、生日(MMDD格式)或姓名搜尋已註冊客戶,支援多條件組合搜尋(例如生日+姓名)。搜尋結果以 Modal 顯示,點擊客戶選項後直接選定並返回主畫面。選定客戶後,系統自動使用該客戶的姓名和生日搜尋卡券,設計師也可額外輸入卡券編號進行搜尋。

優先級理由: 這是完整綁定流程的核心功能,將客戶搜尋與卡券綁定整合在同一頁面,簡化操作流程。依賴故事1(卡券匯入)和客戶註冊系統(已存在)。

獨立測試: 可透過輸入客戶搜尋條件、選定客戶、自動搜尋卡券、選擇卡券並執行綁定,驗證系統能正確完成整個流程,並記錄完整的操作歷程。

驗收場景:

客戶搜尋部分:

  1. Given 設計師進入綁定頁面,When 檢視客戶搜尋區塊,Then 系統顯示三個輸入框(電話、生日、姓名),各自的 placeholder 顯示格式範例(「例如:0912345678」、「例如:0315」、「例如:王小明」)
  2. Given 系統中有客戶「王小明」(電話0912345678、生日3/15),When 設計師輸入電話「0912345678」並點擊搜尋,Then 系統彈出 Modal 顯示「王小明」的客戶資訊
  3. Given 系統中有3位客戶生日都是3月15日,其中一位叫「王小明」,When 設計師同時輸入生日「0315」和姓名「王小明」搜尋,Then 系統僅顯示符合兩個條件的客戶「王小明」
  4. Given 搜尋結果 Modal 顯示5位符合條件的客戶,When 設計師點擊其中一位客戶「王小明」,Then Modal 關閉,主畫面顯示已選定客戶「王小明」的資訊,並自動觸發卡券搜尋
  5. Given 設計師輸入不存在的電話號碼,When 搜尋執行,Then 系統在 Modal 中顯示「查無符合條件的客戶」
  6. Given 設計師輸入生日「0229」(閏年2月29日),When 搜尋執行,Then 系統正確處理並返回符合條件的客戶(若有)

卡券搜尋與綁定部分: 7. Given 設計師已選定客戶「王小明」(生日3/15),When 選定完成後,Then 系統自動使用模糊搜尋「王小明」的姓名和生日「0315」搜尋卡券,並顯示搜尋結果 8. Given 匯入的卡券姓名為「王 小明」(含空格)或「王小名」(錯字),When 設計師選定客戶「王小明」並自動搜尋卡券,Then 系統使用模糊搜尋,成功返回這些卡券 9. Given 自動搜尋顯示5張「王小明」的卡券(3張未綁定、2張已綁定),When 顯示搜尋結果,Then 系統將未綁定卡券排在前面且顯示 checkbox 可複選,已綁定卡券標示「已綁定」且不可選取,同一狀態內依大類(洗髮/剪髮/燙髮/染髮/護髮/頭皮理療)→子類別→建立日期排序 10. Given 設計師想手動搜尋特定客戶的卡券,When 設計師在卡券搜尋區塊輸入生日「0315」和姓名「王小明」並搜尋,Then 系統顯示所有姓名包含「王小明」且生日為3月15日的卡券清單(包含服務大類、子類別、剩餘次數、每次使用金額、綁定狀態) 11. Given 搜尋結果中有3張未綁定卡券,When 設計師勾選 checkbox 選擇其中2張卡券(「V2024001234」、「V2024001235」)並點擊「確認綁定」,Then 系統跳出防呆視窗顯示「即將綁定以下卡券到客戶王小明:V2024001234(剪髮-層次剪)、V2024001235(染髮-全染)。是否確認?」 12. Given 防呆視窗顯示待綁定卡券列表,When 設計師點擊「確認」,Then 系統批次執行綁定,記錄每張卡券的綁定資訊(設計師ID、客戶ID、卡券編號、綁定時間),並顯示「成功綁定2張卡券」訊息 13. Given 防呆視窗顯示待綁定卡券列表,When 設計師點擊「取消」,Then 視窗關閉,不執行任何綁定操作,選取狀態保持 14. Given 卡券「V2024001234」已綁定到客戶「王小明」,When 設計師再次搜尋卡券,Then 該卡券顯示為「已綁定」狀態且不可選取(同張卡券只能綁定一個客戶) 15. Given 客戶「王小明」已綁定卡券「V2024001234」,When 設計師搜尋並選擇另一張未綁定卡券「V2024001236」綁定到「王小明」,Then 系統允許綁定,客戶可重複綁定多張卡券 16. Given 設計師點擊「確認綁定」按鈕後,因網路延遲又點擊一次,When 兩次請求送達後端,Then 系統透過冪等性設計(卡券編號+客戶ID唯一鍵)確保只綁定一次,重複的請求返回「已綁定」狀態 17. Given 設計師嘗試綁定卡券時系統發生錯誤(例如資料庫連線失敗),When 綁定失敗,Then 系統顯示錯誤訊息「綁定失敗,請稍後再試」,並不記錄綁定操作


使用者故事 3 - 設計師自主解綁卡券 (優先級: P3)

設計師需要能夠自行解綁已綁定給客戶的卡券,而不需要透過管理員協助。重要變更:當設計師決定解綁卡券時,系統顯示確認視窗,讓設計師從下拉選單(dropdown)中選擇自己的姓名以確認身份,確認後系統會記錄解綁操作(包含操作者和時間),並將卡券釋出回可用狀態,可被重新綁定到其他客戶。

優先級理由: 這是便利性功能,能減少對管理員的依賴並提升設計師自主性。但相較於核心業務流程(P1 匯入、P2 綁定),這是最不緊急的功能。

獨立測試: 可透過設計師對已綁定的卡券點擊「解綁」按鈕,在確認視窗中從下拉選單選擇自己的姓名並確認,驗證卡券狀態變更為「未綁定」且系統記錄了解綁操作歷史。

驗收場景:

  1. Given 設計師檢視客戶「王小明」已綁定的卡券列表,When 點擊卡券「V2024001234」的「解綁」按鈕,Then 系統彈出確認視窗,顯示卡券資訊(編號、服務類型)、當前綁定的客戶姓名「王小明」、一個下拉選單列出所有設計師姓名、以及「確認解綁」按鈕(初始狀態為 disabled)
  2. Given 確認視窗已開啟且「確認解綁」按鈕為 disabled,When 設計師從下拉選單選擇自己的姓名「李設計師」,Then 「確認解綁」按鈕變為可點擊狀態
  3. Given 設計師已從下拉選單選擇姓名「李設計師」,When 點擊「確認解綁」,Then 系統執行解綁操作、關閉確認視窗、顯示「解綁成功」訊息、卡券狀態從「已綁定」變更為「未綁定」、並在解綁歷史記錄中新增一筆記錄(包含解綁時間、操作者姓名「李設計師」、原綁定客戶「王小明」、卡券編號)
  4. Given 確認視窗已開啟,When 設計師點擊「取消」或關閉視窗,Then 系統不執行解綁操作,卡券維持原綁定狀態
  5. Given 設計師正在解綁卡券的過程中發生系統錯誤,When 解綁操作失敗,Then 系統顯示錯誤訊息、卡券維持原綁定狀態、不新增解綁記錄、將錯誤記錄在系統日誌中
  6. Given 卡券「V2024001234」已成功解綁,When 設計師搜尋該卡券,Then 該卡券顯示為「未綁定」狀態,可被重新選擇綁定到其他客戶

邊界案例

  • 匯入檔案格式錯誤: 當匯入檔案為非預期格式(例如PDF、圖片)時,系統應拒絕匯入並顯示「僅支援CSV或Excel格式」
  • 匯入檔案超大: 當匯入檔案超過10,000筆資料時,系統應分批處理或提示設計師分割檔案
  • 電話號碼格式多樣: 客戶電話可能為09開頭手機、02開頭市話、含國碼+886等格式,系統需正規化後搜尋
  • 生日輸入錯誤: 設計師輸入無效生日(例如1332、0230非閏年),系統應提示「生日格式錯誤,請輸入MMDD四碼(例如0315)」
  • 剩餘次數或金額異常: 匯入時若剩餘次數為負數或每次使用金額為負數/零,應在錯誤報告中標示並拒絕匯入該筆資料
  • 同名客戶過多: 當搜尋「王小明」返回超過50位客戶時,系統應提供分頁或建議設計師使用更精確的條件(電話、生日)
  • 綁定狀態不一致: 若卡券已綁定但客戶狀態顯示未綁定(資料異常),系統應標示警告並阻止綁定操作
  • 併發綁定衝突: 兩位設計師同時嘗試將同一卡券綁定到不同客戶,系統應使用鎖機制確保只有一個綁定成功,另一個返回錯誤

需求 (必填)

功能需求

卡券匯入功能

  • FR-001: 系統必須支援CSV或Excel格式的卡券資料批次匯入
  • FR-002: 匯入的卡券資料必須包含:卡券編號、客戶姓名、服務類型(大類:洗髮/剪髮/燙髮/染髮/護髮/頭皮,子類別:細項服務名稱)、每次使用金額、剩餘次數、生日、建立日期
  • FR-003: 系統必須在匯入過程中驗證每筆資料的必填欄位(卡券編號、姓名、服務類型、每次使用金額、剩餘次數)及格式正確性(卡券編號格式、生日MMDD格式、剩餘次數需為非負整數、每次使用金額需為正數)
  • FR-004: 系統必須採用「全有或全無」(all-or-nothing)原則:若檔案中任何一筆資料匯入失敗,則整個檔案的所有資料都不得被匯入,已匯入的資料必須回滾
  • FR-005: 系統不得產出任何形式的匯入結果報告檔案(無論成功或失敗)
  • FR-006: 系統必須在匯入成功時顯示簡單的「匯入成功:N筆」訊息
  • FR-007: 系統必須在匯入失敗時,將完整錯誤資訊記錄在系統日誌中,包含:失敗時間、檔案名稱、具體錯誤原因、錯誤資料的行號和內容,並向使用者顯示簡要錯誤訊息

客戶搜尋與卡券綁定功能(整合在同一頁面)

客戶搜尋:

  • FR-008: 系統必須在同一頁面提供客戶搜尋和卡券綁定功能,包含三個客戶搜尋輸入框:電話號碼、生日(MMDD四碼)、姓名
  • FR-009: 各輸入框必須在 placeholder 顯示格式範例(「例如:0912345678」、「例如:0315」、「例如:王小明」)
  • FR-010: 系統必須支援多條件組合搜尋(例如:生日+姓名、電話+姓名),搜尋時使用 AND 邏輯(所有條件都符合)
  • FR-011: 搜尋結果必須以 Modal 顯示,包含符合條件的客戶清單
  • FR-012: 客戶清單中的每個選項必須支援點擊直接選定,無需額外按鈕確認
  • FR-013: 選定客戶後,Modal 必須關閉,主畫面顯示已選定客戶的詳細資訊(姓名、電話、生日)
  • FR-014: 電話號碼搜尋時,系統必須正規化電話格式後進行比對(支援09手機、02市話、+886國碼等格式)
  • FR-015: 當搜尋無結果時,系統必須在 Modal 中顯示「查無符合條件的客戶」

卡券自動搜尋與手動搜尋:

  • FR-016: 設計師選定客戶後,系統必須自動使用該客戶的姓名和生日進行模糊搜尋匯入的卡券資料,容錯處理姓名中的空格和錯字
  • FR-017: 系統必須額外提供手動搜尋輸入框,支援設計師手動輸入生日(MMDD格式)和姓名進行卡券搜尋,使用模糊匹配
  • FR-018: 卡券搜尋結果必須顯示:服務大類、子類別、剩餘次數、每次使用金額、綁定狀態
  • FR-019: 卡券搜尋結果必須依以下規則排序:未綁定卡券排在前面且顯示 checkbox 可複選、已綁定卡券排在後面且標示「已綁定」不可選取、同狀態內先依服務大類別(洗髮/剪髮/燙髮/染髮/護髮/頭皮)、再依子類別、最後依建立日期

卡券綁定執行 (支援多選):

  • FR-020: 系統必須在未綁定卡券列表中提供 checkbox,支援設計師複選多張卡券
  • FR-021: 設計師勾選卡券後點擊「確認綁定」,系統必須跳出防呆視窗,顯示待綁定卡券列表(卡券編號、服務大類、子類別)並詢問「是否確認綁定到客戶XXX?」
  • FR-022: 防呆視窗必須提供「確認」和「取消」按鈕,點擊「取消」時關閉視窗不執行綁定
  • FR-023: 點擊「確認」後,系統必須批次執行綁定操作,記錄每張卡券的綁定資訊(操作設計師ID、客戶ID、卡券編號、綁定時間戳記)
  • FR-024: 系統必須實作冪等性設計,確保重複綁定請求(例如網路延遲導致重複點擊)只執行一次綁定,使用「卡券編號+客戶ID」作為唯一鍵
  • FR-025: 系統必須允許一位客戶綁定多張卡券(客戶可重複綁定),但同張卡券只能綁定到一位客戶
  • FR-026: 綁定成功後,系統必須將卡券標記為「已綁定」,已綁定的卡券在搜尋結果中顯示為不可選取狀態,並拒絕將該卡券再次綁定到其他客戶
  • FR-027: 批次綁定完成後,系統必須顯示成功訊息「成功綁定N張卡券」並更新卡券列表的綁定狀態

綁定記錄與設計師自主解綁

  • FR-028: 系統必須記錄所有綁定操作,包含:操作類型(綁定/解綁)、操作時間、操作者姓名(設計師)、客戶ID、卡券編號
  • FR-029: 設計師查看客戶綁定歷程時,系統必須顯示該客戶的所有綁定/解綁記錄,依時間倒序排列
  • FR-030: 當設計師點擊「解綁」按鈕時,系統必須彈出確認視窗,顯示:卡券編號、服務類型、當前綁定的客戶姓名、設計師姓名下拉選單、「確認解綁」按鈕(初始為 disabled 狀態)、「取消」按鈕
  • FR-031: 下拉選單必須列出所有系統中的設計師姓名,供操作者選擇
  • FR-032: 「確認解綁」按鈕必須在設計師從下拉選單選擇姓名後才變為可點擊狀態(enabled)
  • FR-033: 設計師點擊「確認解綁」後,系統必須執行以下操作:(1)將卡券狀態從「已綁定」變更為「未綁定」;(2)清除卡券與客戶的綁定關係;(3)新增解綁歷史記錄(包含解綁時間、操作者姓名、原綁定客戶、卡券編號)
  • FR-034: 設計師點擊「取消」或關閉確認視窗時,系統不得執行任何解綁操作,卡券保持原綁定狀態
  • FR-035: 系統必須在解綁操作完成後,顯示「解綁成功」訊息,並更新介面上的卡券綁定狀態

關鍵實體

  • 卡券 (Voucher): 代表美髮沙龍的服務卡券,包含卡券編號(唯一識別碼)、客戶姓名、服務類型(大類:洗髮/剪髮/燙髮/染髮/護髮/頭皮、子類別:細項服務名稱)、每次使用金額、剩餘次數、生日、建立日期、綁定狀態(未綁定/已綁定到客戶X)
  • 註冊客戶 (Registered Customer): 代表已在系統註冊的客戶帳號,包含客戶ID、姓名、電話號碼、生日、綁定狀態(未綁定/已綁定)、綁定的卡券清單
  • 綁定記錄 (Binding Record): 記錄卡券與客戶帳號的綁定歷程,包含操作類型(綁定/解綁)、操作時間、操作者ID及角色(設計師/管理員)、客戶ID、卡券編號
  • 設計師 (Designer): 執行卡券匯入、客戶搜尋、綁定操作的使用者,擁有查看綁定記錄的權限,但無解綁權限
  • 匯入批次 (Import Batch): 記錄每次匯入操作的元資料,包含匯入時間、操作設計師、總筆數、成功筆數、失敗筆數、錯誤報告檔案路徑

成功標準 (必填)

可衡量成果

  • SC-001: 設計師完成100筆卡券資料匯入操作的平均時間減少60%(從需要等待報告產生到立即得知結果)
  • SC-002: 卡券匯入失敗時,技術人員能在2分鐘內從系統日誌中找到完整錯誤資訊並定位問題
  • SC-003: 客戶搜尋結果在1秒內返回(資料庫包含10,000位註冊客戶的情況下)
  • SC-004: 卡券綁定操作在2秒內完成,並正確記錄綁定資訊
  • SC-005: 90%的設計師能在首次使用時,不需額外指導即可完成「搜尋客戶→搜尋卡券→綁定」完整流程
  • SC-006: 系統能處理併發綁定請求而不產生資料不一致(100個併發綁定請求測試通過)
  • SC-007: 所有資料操作(匯入、綁定、解綁)的原子性達到100%,無任何部分成功部分失敗的情況發生
  • SC-008: 設計師完成單次卡券解綁操作的時間縮短至30秒以內(從點擊解綁到完成確認)
  • SC-009: 設計師自主解綁卡券的比例達到90%以上,減少對管理員協助的依賴

假設

  • 系統已存在客戶註冊功能,客戶資料(姓名、電話、生日)已正確儲存
  • 匯入的卡券資料格式由沙龍方提供,且遵循固定的欄位結構(卡券編號、姓名、服務類型、生日等)
  • 卡券編號為唯一識別碼,不會跨沙龍重複
  • 服務類型的大類別固定為「洗髮、剪髮、燙髮、染髮、護髮、頭皮」六種,子類別由沙龍方定義
  • 卡券姓名搜尋使用模糊比對,容錯處理空格和錯字(例如「王 小明」或「王小名」都能匹配到「王小明」)
  • 設計師可一次綁定多張卡券到同一客戶,系統提供防呆確認機制
  • 電話號碼搜尋時,系統假設客戶註冊時已正規化電話格式儲存(例如統一轉為09或+886格式)
  • 生日格式統一為MMDD四碼(月份兩碼+日期兩碼),不包含年份
  • 設計師擁有匯入、搜尋、綁定、解綁的完整權限,可自主完成所有卡券管理操作
  • 解綁操作需要設計師從下拉選單選擇自己的姓名以確認身份,提供操作追蹤和責任歸屬
  • 綁定和解綁操作都會完整記錄操作者資訊,確保可追溯性
  • 匯入檔案的大小限制為10,000筆或10MB(以系統效能限制為準)

範圍界定

包含在此功能內

  • 卡券資料的批次匯入(CSV/Excel格式),採用全有或全無原則
  • 匯入資料的格式驗證,失敗時記錄到系統日誌而非產生報告檔案
  • 客戶搜尋功能(電話號碼、生日MMDD、姓名)
  • 卡券搜尋功能(姓名、生日MMDD),支援模糊匹配
  • 卡券綁定到客戶帳號的操作與記錄,支援多選批次綁定
  • 綁定歷程的查詢與顯示
  • 設計師自主解綁功能,透過確認視窗和下拉選單選擇姓名
  • 解綁操作的完整記錄與追蹤
  • 冪等性設計防止重複綁定

不包含在此功能內

  • 客戶註冊功能(已存在於系統中)
  • 卡券的核銷、使用、過期管理(屬於其他功能模組)
  • 設計師權限管理與身份驗證(假設已由現有系統處理)
  • 卡券服務類型的新增、修改、刪除管理(假設由系統管理員在後台維護)
  • 匯入檔案的自動格式轉換(設計師需確保上傳檔案為CSV或Excel格式)
  • 客戶資料的修改或刪除(屬於客戶管理模組)
  • 匯入結果報告的產生或下載功能(已移除)