UGOMK 操作手冊
11 章 / 共 72

票券管理

點數系統

每位會員的點數可以透過:

  • 消費自動累積(依「點數參數」的「金額換點數比例」)
  • 管理員手動加點
  • 活動贈點
  • 推薦獎勵

「會員 → 點數紀錄」會顯示所有點數異動。

會員端「集點記錄」頁面

會員從 LIFF 進「會員中心 → 集點記錄」,會看到每一筆點數異動。每筆記錄包含:

  • 左側圓形圖示:依異動類型顯示對應圖示
  • 中文類別標籤:例如「客服贈點」「消費回饋」「兌換票券」「推薦獎勵」
  • 入帳 / 使用 badge:綠色 badge = 點數增加,橘色 badge = 點數扣除
  • 異動說明:依類別自動帶出對應描述(例如「POS 消費:訂單 #...」「兌換票券:滿千折百」)
  • 時間:年/月/日 時:分
  • 點數變化:右側 +N 點 / -N 點,綠色加分、紅色扣分

集點記錄頁面截圖製作中

目前支援的 15 種異動類別

類別代碼中文標籤觸發時機
manual_add客服贈點管理員後台手動加點
manual_deduct客服扣點管理員後台手動扣點
purchase消費回饋POS / 手動消費登記
refund退款扣回訂單退款回收點數。扣回的點數以會員實際扣得到的餘額為準,不會扣成負數——會員若已把當初賺到的點數用掉一部分,退款只會扣到剩下的餘額,扣不足的差額不會倒扣;扣不足時這筆記錄的說明會多一句「(原 N 點,餘額不足實扣 M)」方便對帳
exchange兌換票券點數商城兌換
invoice_reward發票回饋上傳發票通過審核
invoice_reward_revoke回饋撤回鑑賞期二驗失敗撤回
lottery_reward抽獎中獎抽獎活動中獎
referral推薦獎勵推薦新會員達標
dispatch_reward派案酬金派案模組完成案件
beauty_service預約完成美業預約完成
micro_page活動加點微網頁觸發加點
marketing行銷活動行銷自動化贈點
transfer_in收到紅包領取點數紅包 / 過期退回
transfer_out送出紅包建立點數紅包扣點
提示:如果未來新增類別代碼,前端會 fallback 成「點數異動」不會炸。

票券管理

「內容管理 → 票券管理」可建立票券,建立時可設定:

  • 票券名稱
  • 類型:折扣券 / 現金券 / 禮品券(共 3 種)
  • 金額或折數(依類型不同意義不同)
  • 最低消費金額(選填)
  • 庫存(留空=不限)
  • 生效日期 / 到期日期
  • 允許會員轉贈這張票券預設關閉,要開放才逐張開啟,見下方「票券轉贈設定」)
  • 優惠券圖片(2026-06-17 改為拖曳上傳;2026-06-25 起強制必填):可直接拖檔或點選圖片上傳到 R2,建議 1200×600(2:1 寬幅)。會員收到票券推播時 Flex 卡 hero 區會用這張圖。新建 / 編輯票券時必須上傳 banner 或商品圖至少一張,後端 POST / PUT 會 reject 兩者皆空的請求

票券列表頁可依「類型」「狀態(啟用中 / 已停用 / 已過期)」篩選。

狀態欄一律顯示中文:無論是票券範本(啟用中 / 已暫停 / 未啟用 / 草稿 / 已發佈 / 已撤銷 / 已取消)、會員票券(未使用 / 已使用 / 已核銷 / 已過期 / 轉贈中 / 贈送相關)或 records 事件(已發放 / 處理中),列表 / 詳情 / 記錄頁全走同一份 mapping(lib/voucher-status.ts)—— 後端 enum 內部值 (active / unused / used 等) 保持不變,只有顯示層自動翻中文。老闆 / 客戶不會再在截圖看到 active / unused 生英文。

進入單張票券詳情頁,可執行:發放給特定會員核銷編輯

自動發券時推 LINE Flex 通知(2026-06-17 新加)

行銷劇本 / 抽獎 / 入會禮等發券動作(issue_voucher)會員都會自動收到一張 LINE Flex 圖卡通知

  • 含商品圖(如上有設)、票券名、類型、面額、有效期、收券人姓名
  • 底部按鈕「查看我的票券」導向會員 LIFF /vouchers
  • 樣式可在「內容管理 → 系統圖卡 → 票券發放通知卡」自訂(變數含 voucher_name / type_label / value_label / image_url / expires_label 等)
  • 沒綁 LINE 的會員照樣發券(DB 寫入 member_vouchers),只是不會收推播

為什麼客戶說沒收到票券?

最常見原因:voucher 沒上傳 banner 圖 → 自動走純文字版 fallback bubble,視覺平淡客戶誤判滑過以為沒收到。

2026-06-25 起新建 / 編輯票券強制圖片必填,舊資料若未補圖會在列表標紅;新建 / 編輯時若 banner 與商品圖都空白,後端會回 400 拒絕儲存。

修法(系統已內建三段 fallback,但前兩段強烈建議都做):

  1. 每張 voucher 上傳 2:1 橫式 banner(1200×600)— 首選,可做活動專屬視覺(現為必填
  2. 在「系統設定 → 票券預設圖」設一張統一品牌 banner — 任何未上傳 banner 的 voucher 自動套用(救援用)
  3. 兩者皆無 → 走純文字 bubble(safety net,仍可送達但體驗弱;新資料已不會發生此情況)

Admin 警示

  • 票券列表「票券名稱」欄位旁若無 banner / 商品圖 → 顯示 缺圖,無法發送 紅色 chip
  • 列表頁頂部會出現整列紅色提示橫條:「本頁有 N 張票券缺圖無法發送,請優先補圖」
  • 每張缺圖 row 右側都有「補圖」紅色按鈕,點擊直接跳該 voucher 編輯頁並自動開啟編輯 modal

票券圖片必填規則(2026-06-25 上線)

規則banner_image_urlimage_url 至少一個欄位有值。

欄位用途建議規格
banner_image_urlLINE Flex 2:1 主圖(hero)1200×600 橫式
image_url商品圖(banner 沒設時 fallback)1:1 或方形皆可

驗證點

  • 後端 POST /api/vouchers:兩者皆空回 400「請至少上傳一張票券圖片(banner 或商品圖),建議 2:1 橫式 1200×600」
  • 後端 PUT /api/vouchers/:id:若本次 PUT 涉及這兩個欄位,結算後仍兩者皆空回 400「請至少保留一張票券圖片(banner 或商品圖)」(不涉及這兩個欄位的部分更新不會擋)
  • 前端新建 / 編輯 form:submit 前 inline error「請至少上傳一張票券圖片」
  • 既有舊資料:GET / list 不擋,但列表紅 chip + 紅橫條提示,「補圖」按鈕一鍵跳編輯

Flex 發送 fallback 順序voucher-flex-push.ts):banner_image_urlimage_url → 租戶預設圖 → 純文字 bubble

票券預設圖在哪設?

路徑:後台左側 系統設定 → 頁面內第 3 張卡片「票券預設圖(2:1 1200×600)

規格

  • 比例 2:1 橫式,建議 1200×600
  • 檔案 3MB 以內
  • PNG / JPG 皆可,以品牌橫式 KV 圖為佳

何時被使用:當某張 voucher 的 banner_image_urlimage_url 都為空 → 推送 LINE Flex 時自動以本預設圖填入 hero。

寫入位置settings 表 key=voucher_default_banner_url(jsonb),api 端 voucher-flex-push.ts 三段 fallback 第二層讀此 key。

票券轉贈設定(2026-08-16 新增)

逐張票券決定「這張券能不能被會員轉贈給 LINE 好友」。

設定位置

  • 新建票券頁 → 「允許會員轉贈這張票券」開關
  • 單張票券詳情頁 → 「轉贈設定」卡片(切換後立即儲存,不需再按儲存)

預設值關閉(不可轉贈)新建票券一律預設不開放轉贈,要讓客人能把券送給朋友,必須逐張自己開啟

為什麼預設關閉:票券等於有金額的資產,開放轉贈後就可能流到非本人手上。少開放只要開啟一下即可補上;多開放則券已經轉手出去,事後追不回來。

關閉時:會員票券夾(LIFF「我的票券」)該張票券不會出現「轉贈給朋友」按鈕。已經送出、對方尚未領取的禮物不受影響,仍照原本 24 小時規則走。

只有這一層開關

轉贈只由每張票券自己的設定決定,沒有全店總開關,也不需要先到其他頁面啟用。在票券新建頁或票券詳情頁開啟後立即生效。

2026-08-16 之前的說明曾提到「參數設定 → 商家設定 → 啟用轉贈功能」這顆全店總開關。該開關實際上從未生效(開或關都不影響會員能否轉贈),已一併移除,請以本節為準。

轉贈時朋友收到的卡片(2026-08-16 改版)

會員按「轉贈給朋友」時,LINE 會跳選好友視窗、送出一張「票券禮物分享卡」,對方點「立即領取」開 LIFF 領取頁。

  • 圖片改成 2:1 橫式(原本是 1:1 正方形),與「票券發放通知卡」一致,同一張票券圖不用再準備兩種比例
  • 圖片取用順序:banner 圖 → 商品圖,與發券通知卡同一套規則(在此之前這張卡根本沒去撈 banner 圖,所以只會顯示商品圖)
  • 版型可在 內容管理 → 系統圖卡 → 票券禮物分享卡 自訂
  • 未領取的禮物24 小時後自動退回原持有者

票券進階設定(2026-06-30 新增 4 欄位)

新建 / 編輯票券 modal 內新增以下欄位:

1. 禮品券(type = gift)不需設金額

票券類型新增 「禮品券」 選項。選了禮品券:

  • 金額欄位 disabled(不會傳 value
  • 適用情境:免費贈品(如「免費咖啡」「免費小菜」「贈品兌換券」),不對應金額
  • LIFF 票券詳情頁顯示「贈品」徽章,沒有面額或折數
  • POS 核銷時不會影響訂單金額(純記錄已兌換)
資料層:vouchers.value 已 DROP NOT NULL(boot-migration F45 backfill),type='gift' 時 value 可為 null;其他類型仍要求 value > 0

2. 使用說明(usage_terms,最多 2000 字)

textarea 欄位,填了之後:

  • 顯示在會員 LIFF 票券詳情頁的「使用說明」區塊
  • 範例文案:「本券限本店使用 / 一桌限用一張 / 不可與其他優惠合併使用 / 不可折抵現金 / 過期作廢」
  • 後端限制 2000 字以內,超過會 reject

3. 領券後 N 天可使用(valid_after_days,0–365)

  • 預設 0:發券當下立即可用
  • 設 N:發券當下計算 valid_from = NOW() + N days,會員 LIFF 在此日期前看到票券但顯示「N 天後可使用」無法核銷
  • 適用情境

- 新會員禮券要等 7 天驗證期後才可用 - 預售活動:發券當下不可用,活動開跑日才開放

  • 由 PostgreSQL BEFORE INSERT trigger 自動算 valid_from,caller 不用算

4. 領券後 N 天失效(valid_for_days,1–3650)

  • 預設 null:吃 voucher 主檔的 expires_at 為到期日
  • 設 N:發券當下計算 expires_at = valid_from + N days,覆寫主檔 expires_at
  • 適用情境

- 限時優惠:「領券後 7 天內用完」 - 滾動式發放:不想設固定到期日,每位會員從領到當下算 N 天

  • 後端限制 1-3650(10 年內)
注意:valid_after_days + valid_for_days 兩欄位 BEFORE INSERT trigger 在 member_vouchers 表上自動計算 valid_from / expires_at,發券的 7+ 個 caller(手動發、行銷劇本、抽獎、推薦獎勵、購買、兌換、轉贈)全部不需改 code 自動受惠。

5. 票券狀態 inline toggle(票券管理列表)

票券列表 狀態 欄位可直接點 cell 切換啟用 / 暫停,無需開編輯 modal:

狀態DataTable 顯示行為
active啟用中可被發放 / 兌換 / 行銷劇本派送
paused已暫停列表仍可見 / 已發出的票券不受影響 / 不再被新發送

點擊 cell → PUT /api/vouchers/:id/toggle-status → toast「票券已暫停 / 票券已恢復啟用」

提示:暫停不等於刪除:要永久移除請走 刪除 按鈕(會 cascade 刪除已發出的 member_vouchers,僅 tenant_admin 可執行)。

6. 每日領取限制 + 額滿推送文字(2026-07-02 新增)

新建 / 編輯票券 modal 內新增「每日領取限制」藍色卡片,兩個上限可個別設或同時設:

欄位意義範圍
每人每日限領張數同一會員每天最多可領這張票券幾張0-999,0 或不填 = 不限
全店每日發放上限這張票券每天全店最多發放幾張(含系統贈送)0-9999,0 或不填 = 不限

3 條設計原則(拍板規則)

  1. 系統贈送也算配額 — 新會員禮 / MGM 推薦獎勵 / 行銷劇本派券 / admin 手動發放全部算入當日配額。不會因為「是系統送的」就跳過上限。
  2. admin 撤銷後不退還配額 — 撤銷票券不會把當天的名額退回去(防 exploit:撤銷再重領)。
  3. 時間邊界用租戶時區 00:00 — 從「系統設定 → 時區」讀取(預設 Asia/Taipei),00:00 重置當日計數。不用 UTC,也不吃 POS「營業日」設定。

觸發時機

  • 全店上限先檢查(滿了個人一定也拿不到)
  • 檢查順序:全店 → 個人;任一 hit 就拒絕發券

額滿時的行為分流

情境系統動作
會員 LIFF 自主兌換按鈕顯示 disabled + 進度小字「今日 X/Y」;詳情 modal 顯示提示
會員點兌換按鈕(僥倖點到)回 429 錯誤 + toast「本券今日領取名額已滿,請明日再試」
Admin 手動發放回 429 給 admin,會員端推任何訊息(避免困擾)
系統贈送(MGM / 自動行銷 / 週期任務)該張 voucher 不發,改推「額滿推送文字」給會員(見下)

額滿推送文字(limit_reached_message,最多 500 字)

「每日領取限制」卡片下方新增 textarea,供 admin 自訂系統贈送 hit 上限時推給會員的文字:

  • 不填 → 走系統 default:「本券今日領取已達上限,明日再試」
  • 有填 → 推 admin 設的文字。範例:

- 「今日領取已達上限,明天早上 8:00 重置,歡迎明日再來」 - 「本活動今日名額已滿,請追蹤下週三新一波開放時間」 - 「感謝支持!本券今日份已發完,明日 00:00 重新開放」

提示只在系統贈送情境下推(MGM 推薦、行銷自動化派券、週期任務贈送):這些流程原本會推一張 voucher Flex 圖卡,hit 上限後改推此文字讓會員知道今日名額已滿。會員 LIFF 自主兌換 hit 上限時不會推此文字(會員在 UI 上已看到 disabled 提示)。

未加好友的會員:文字進 pending_push 佇列,未來加好友時 webhook follow 事件補推(同 voucher Flex fallback 邏輯)。

會員 LIFF 點數商城顯示(Phase 2)

會員從 LIFF 進「會員中心 → 點數商城」,票券卡片會依當日配額動態顯示:

狀態卡片按鈕卡片下方
可領正常「兌換」按鈕
個人已達上限灰色 disabled 按鈕「今日 X/Y」(粉紅小字,顯示已領 / 上限)
全店已達上限灰色 disabled 按鈕「今日 X/Y」

點卡片開詳情 modal:footer 顯示醒目提示 + admin 設的「額滿推送文字」(若有),並顯示「今日已領取 N / M 張」。會員能一眼看懂「不是壞掉,是名額滿了」。

資料層:vouchers 加 3 個新欄位 daily_claim_limit_per_member / daily_claim_limit_total / limit_reached_message(boot-migration F48 / F49 自動 backfill)。LIFF list endpoint 每張 voucher 預查 evaluateClaimEligibilitycan_claim / limit_used_today / limit_total / limit_reason 給前端渲染。

核銷後自動觸發行銷劇本(voucher_redeemed trigger)

票券核銷成功後系統自動 fireTrigger('voucher_redeemed'),可在 會員管理 → 自動行銷劇本 建一條規則攔截:

  • trigger_typevoucher_redeemed
  • config 可選 voucher_id:填了則只該張票券核銷會觸發;不填 = 任何票券核銷都觸發
  • action:可串點數、推 LINE、發另一張票券、改標籤等任何 ma_rules 支援的動作
  • dedup:每張 member_voucher 終生 fire 一次(即使重複核銷不會多觸發)
不是 voucher 主檔欄位 — 走 ma_rules 規則設定。完整 trigger 規格見 自動行銷規則

點數商城(兌換票券)

點數商城(會員可用點數兌換的票券)由 points_cost > 0 的票券自動上架到 LIFF「點數商城」。

設定入口內容管理 → 兌換票券(與「票券管理」分離,本頁聚焦純發放票券;兌換票券完整設定見 兌換票券 說明書)。

2026-06-26 起列表分流:「票券管理」列表只顯示 redeemable=false 的純發放票券(後台手動贈送 / 行銷劇本派發 / 購買);積分兌換券(points_cost > 0)統一到「兌換票券」頁管理,兩處不會互相混入。