graph LR
PAY["Payment Complete (支付完成)"]
EARN["Points Earned (积分累计)"]
TIER["Tier Evaluation (会员等级评估)"]
DISC["Checkout Discount (积分抵扣)"]
PAY -->|"R1 积分累计"| EARN
EARN -->|"R2 等级评估"| TIER
TIER -->|"R3 等级折扣"| DISC
style PAY fill:#1a2332,stroke:#3b82f6,color:#e0e0e0
style EARN fill:#1a2332,stroke:#22c55e,color:#e0e0e0
style TIER fill:#1a2332,stroke:#22c55e,color:#e0e0e0
style DISC fill:#1a2332,stroke:#22c55e,color:#e0e0e0
linkStyle 0 stroke:#22c55e,stroke-width:2px
linkStyle 1 stroke:#22c55e,stroke-width:2px
linkStyle 2 stroke:#22c55e,stroke-width:2px
graph LR
SVCCOMP["Service Complete (服务完成)"]
REVEVAL["Review Evaluate (评价规则评估)"]
REVSMS["Review SMS (评价短信发送)"]
SVCCOMP -->|"R4 触发评价请求"| REVEVAL
REVEVAL -->|"R5 发送评价短信"| REVSMS
style SVCCOMP fill:#1a2332,stroke:#3b82f6,color:#e0e0e0
style REVEVAL fill:#1a2332,stroke:#22c55e,color:#e0e0e0
style REVSMS fill:#1a2332,stroke:#22c55e,color:#e0e0e0
linkStyle 0 stroke:#f59e0b,stroke-width:2px,stroke-dasharray:5
linkStyle 1 stroke:#22c55e,stroke-width:2px
graph LR
REFCODE["Referral Code (推荐码生成)"]
TRACK["Referral Tracking (推荐跟踪)"]
REWARD["Referral Reward (推荐奖励)"]
ACQ["Acquisition (获客入口)"]
REFCODE -->|"R6 推荐码追踪"| TRACK
TRACK -->|"R7 推荐奖励"| REWARD
REFCODE -.->|"R13 跨图: 获客"| ACQ
style REFCODE fill:#1a2332,stroke:#22c55e,color:#e0e0e0
style TRACK fill:#1a2332,stroke:#22c55e,color:#e0e0e0
style REWARD fill:#1a2332,stroke:#22c55e,color:#e0e0e0
style ACQ fill:#0d2818,stroke:#8b5cf6,color:#8b5cf6,stroke-dasharray:5
linkStyle 0 stroke:#22c55e,stroke-width:2px
linkStyle 1 stroke:#22c55e,stroke-width:2px
linkStyle 2 stroke:#ef4444,stroke-width:2px,stroke-dasharray:5
graph LR
GCPURCH["Gift Card Purchase (礼品卡购买)"]
GCGEN["Card Generation (卡号生成)"]
GCDLVR["Delivery (邮件/短信发送)"]
GCCLAIM["Claim (领取)"]
GCUSE["Checkout Deduction (结账抵扣)"]
GCPURCH -->|"R8 生成卡号"| GCGEN
GCGEN -->|"R9 发送通知"| GCDLVR
GCDLVR -->|"R10 领取"| GCCLAIM
GCCLAIM -->|"R11 结账抵扣"| GCUSE
style GCPURCH fill:#1a2332,stroke:#22c55e,color:#e0e0e0
style GCGEN fill:#1a2332,stroke:#22c55e,color:#e0e0e0
style GCDLVR fill:#1a2332,stroke:#22c55e,color:#e0e0e0
style GCCLAIM fill:#1a2332,stroke:#22c55e,color:#e0e0e0
style GCUSE fill:#1a2332,stroke:#22c55e,color:#e0e0e0
linkStyle 0 stroke:#22c55e,stroke-width:2px
linkStyle 1 stroke:#22c55e,stroke-width:2px
linkStyle 2 stroke:#22c55e,stroke-width:2px
linkStyle 3 stroke:#22c55e,stroke-width:2px
graph LR
TEVAL["Tag Evaluation (标签评估)"]
TRIGGER["Trigger Engine (触发引擎)"]
SEND["Send Message (消息发送)"]
BOOK["Booking Page (预约入口)"]
TEVAL -->|"R12a 标签触发"| TRIGGER
TRIGGER -->|"R12b 消息发送"| SEND
SEND -.->|"R12c 跨图: 预约"| BOOK
style TEVAL fill:#1a2332,stroke:#f59e0b,color:#e0e0e0
style TRIGGER fill:#1a2332,stroke:#22c55e,color:#e0e0e0
style SEND fill:#1a2332,stroke:#22c55e,color:#e0e0e0
style BOOK fill:#0d2818,stroke:#8b5cf6,color:#8b5cf6,stroke-dasharray:5
linkStyle 0 stroke:#f59e0b,stroke-width:2px,stroke-dasharray:5
linkStyle 1 stroke:#22c55e,stroke-width:2px
linkStyle 2 stroke:#f59e0b,stroke-width:2px,stroke-dasharray:5
| 状态 | 边 | 涉及模块 | 代码路径 | 备注 |
|---|---|---|---|---|
| ✓ | R1 Payment → Points 累计 | Loyalty |
api/loyalty.js:1892 checkout apply 调用 loyaltyService.earnPoints()services/loyalty/loyaltyService.js:520 onPaymentCompleted() 调用 this.earnPoints()services/loyalty/pointsAccountService.js:132 earnPoints() 写入 points_transactions
|
双路径:checkout-apply 直接调用 + onPaymentCompleted facade。支持 tier multiplier 加成。 |
| ✓ | R2 Points → Tier 评估 | Loyalty |
services/loyalty/membershipService.js:405 recordSpend() 累加 period_spend + lifetime_spendservices/loyalty/membershipService.js:426 异步调用 checkAndUpgrade()services/loyalty/loyaltyService.js:553 onPaymentCompleted() 调用 recordSpend()
|
支付完成后 recordSpend 累加消费额,非阻塞触发 checkAndUpgrade 比较 period_spend vs upgrade_threshold 决定升降级。 |
| ✓ | R3 Tier → Checkout 折扣 | Loyalty |
services/loyalty/membershipService.js:305 calculateMembershipDiscount()services/loyalty/loyaltyService.js:414 processCheckout() 步骤 1 调用此方法
|
processCheckout 在计算最终金额时查询 tier discount_percent 并减免。 |
| ⚠ | R4 Service Complete → Review 请求 | Automation, Agent |
api/appointments.js:2211 status='pending_payment' 时调用 automationEvents.serviceCompleted()services/automation/event-emitter.js:85 serviceCompleted() 触发 trigger engineagents/acquisition/review.agent.js Review Agent 评估 + 发送
|
service_completed 事件通过 automation trigger engine 调度后续消息。Review Agent 是独立的 Inngest agent,通过 checkout 事件触发,不直接挂接在 automation trigger engine 的 service_completed 事件上。两套并行路径,automation rule 和 Review Agent 各自独立。缺乏统一入口编排。 |
| ✓ | R5 Review Evaluate → Send SMS | Agent |
agents/acquisition/tools/review.tools.js:23 evaluateReviewRequest 规则引擎agents/acquisition/tools/review.tools.js:79 sendReviewRequest SMS 发送services/acquisition/review-evaluator.js 规则引擎:tip 阈值、cooldown、weekly cap
|
Review Agent 内部完整:evaluate 判断 shouldSend,通过后 sendReviewRequest 发短信含 Google Review URL。 |
| ✓ | R6 Referral Code → 追踪 | Loyalty |
services/loyalty/referralService.js:35 generateCode() 生成唯一 6 字符码services/loyalty/referralService.js:156 applyCode() 创建 pending referral + 增加 usage_count
|
code 生成 → 新客注册时 applyCode 创建 pending referral 记录。防自引用、防重复引用。 |
| ✓ | R7 Referral → Reward | Loyalty |
services/loyalty/loyaltyService.js:564 onPaymentCompleted() 调用 referral.completeReferral()services/loyalty/referralService.js:234 completeReferral() 判断 multi_reward_enabledservices/loyalty/referralRewardService.js:126 issueRewards() 支持 points / cash_voucher / discount 三种奖励services/loyalty/referralRewardService.js:470 retryPendingRewards() 失败重试 (5min/15min/60min)
|
084-referral-reward-enhancement: 首次支付后自动完成 referral,多类型奖励(积分/现金券/折扣券),含重试机制和通知。 |
| ✓ | R8 Gift Card Purchase → 生成 | Gift Card |
services/loyalty/giftCardService.js:63 purchaseGiftCard()utils/giftCardGenerator.js 生成唯一卡号 + PINservices/giftCard/giftCardService.js 另一套 GiftCardService (023-gift-cards),支持 claim_token / JWT
|
两套 GiftCardService 并存:loyalty/ 下的原始版 (017) 和 giftCard/ 下的增强版 (023)。purchaseGiftCard 原子性写入 gift_cards + gift_card_transactions。 |
| ✓ | R9 Gift Card → 发送通知 | Gift Card, Messaging |
services/loyalty/giftCardDeliveryService.js:20 sendGiftCardEmail() 旧版邮件发送services/giftCard/giftCardNotificationService.js:90 sendGiftCardEmail() 新版含 claim URLservices/giftCard/giftCardNotificationService.js:169 sendGiftCardSMS() 短信含 claim URLservices/giftCard/giftCardDeliveryStateService.js delivery 状态追踪
|
新版 NotificationService 生成 claim URL 并通过 email/SMS/both 发送,记录 delivery events 便于审计。旧版 DeliveryService 直接发卡号+PIN。 |
| ✓ | R10 Gift Card → 领取 | Gift Card, Frontend |
api/gift-cards.js GET /api/gift-cards/claim/verify/:token 验证 tokenapi/gift-cards.js POST /api/gift-cards/claim/:token 执行领取frontend/.../gift-cards/claim/[token]/page.tsx 前端 claim 页面services/giftCard/giftCardService.js JWT claim_token 验证 + 绑定 guest
|
完整 claim 流程:收到通知 → 点击 claim URL → 前端 claim 页面 → verify token → 登录/注册 → POST claim → 绑定到 guest 账户。 |
| ✓ | R11 Gift Card → 结账抵扣 | Loyalty, Payment |
services/loyalty/loyaltyService.js:391 processCheckout() 步骤 3 调用 gift card 验证 + 抵扣services/loyalty/loyaltyService.js:542 onPaymentCompleted() 步骤 3 调用 redeemGiftCard()services/loyalty/giftCardService.js:290 redeemGiftCard() FOR UPDATE 锁卡 + 扣余额api/payment/request-routes.js + api/payment/split-payment-routes.js 支付路由含 gift card 抵扣
|
双路径:processCheckout 预计算抵扣 + onPaymentCompleted 实际执行扣款。redeemGiftCard 使用 FOR UPDATE 行锁防并发。 |
| ⚠ | R12 Tag 评估 → Trigger → 发送 | Tagging, Automation, Messaging |
services/tagging/evaluationService.js:29 evaluateTagDefinition() SQL 规则评估 + 增量更新 guest_tagsservices/automation/trigger-engine.js:29 EVENT_TYPES.TAG_ADDED 事件类型已注册services/automation/event-emitter.js:211 tagAdded() helper 已就绪services/automation/execution-processor.js 调用 MessagingService 发送 email/SMS
|
Tag 评估服务和 automation trigger engine 各自完整,但 evaluationService 在标签变更后未调用 automationEvents.tagAdded()。tag_added 事件触发路径断裂:无代码在标签写入后 emit 事件到 trigger engine。需要在 evaluationService 的 step 5 (添加标签循环) 中加入 automationEvents.tagAdded() 调用。 |
| ⚠ | R12c Recall → Booking Page (跨图) | Automation, Conversion |
services/automation/execution-processor.js 发送 email/SMS 含模板变量模板可包含 booking link 变量 (appointmentInfoUrl 等) |
模板引擎支持注入 booking URL,但具体 recall 类 automation rule 的模板是否配置了正确的预约链接取决于运营配置。代码层面具备能力,但无强制保证。 |
| ✗ | R13 Referral → Acquisition Agent (跨图) | Loyalty, Agent |
services/loyalty/referralService.js 推荐系统独立运作agents/acquisition/ 获客 Agent 组 (SEO, Review, Content) 无 referral 集成
|
Referral 系统和 Acquisition Agent 组完全独立,无交叉引用。Referral 走的是 guest-to-guest 口碑路径(生成码 → 分享 → 新客注册 → 首购奖励),Acquisition Agent 走的是 Local SEO / Review / Content 路径。两者未连接是有意设计还是缺口待确认。 |
| 状态 | 生命周期阶段 | 代码实现 | 备注 |
|---|---|---|---|
| ✓ | 1. Purchase (购买) | loyalty/giftCardService.js:63 purchaseGiftCard + giftCard/giftCardService.js |
生成唯一卡号 + PIN + claim_token,验证金额范围,原子写入 |
| ✓ | 2. Delivery (发送通知) | giftCard/giftCardNotificationService.js email + SMS + delivery state tracking |
含 claim URL,记录 delivery_events 审计 |
| ✓ | 3. Claim (领取) | api/gift-cards.js verify + claim endpointsfrontend/.../gift-cards/claim/[token]/page.tsx |
JWT token 验证,可过期 (claim_expire_days 配置),绑定 guest 账户 |
| ✓ | 4. Redeem (使用) | loyalty/giftCardService.js:290 redeemGiftCard + processCheckout |
FOR UPDATE 行锁,支持部分使用,余额为 0 自动标记 USED |
| ✓ | 5. Reload (充值) | loyalty/giftCardService.js:358 reloadGiftCard |
已用完的卡充值后自动恢复 active 状态 |
| ✓ | 6. Transfer (转让) | loyalty/giftCardService.js:428 transferGiftCard |
更新 recipient + 记录 TRANSFER_OUT 交易 |
| ✓ | 7. Cancel (取消) | loyalty/giftCardService.js:495 cancelGiftCard |
记录 CANCEL 交易,余额归零 |
| ✓ | 8. Expiry 通知 | services/automation/event-emitter.js:194 giftCardExpiring() |
automation trigger engine 支持 GIFT_CARD_EXPIRY 事件触发通知 |
礼品卡生命周期全 8 个阶段均有代码实现,是留存模块中最完整的子系统。
services/tagging/evaluationService.js 在标签变更后(step 5 添加 / step 6 移除)没有调用 automationEvents.tagAdded()。
event-emitter 中 tagAdded() helper 已就绪 (line 211),trigger-engine 中 TAG_ADDED 事件类型已注册 (line 29),但无代码在标签实际变更时触发此事件。
修复方案:在 evaluationService.js 的 step 5 循环中,每次成功添加标签后调用 automationEvents.tagAdded(tenantId, { customerId: guestId, tagId: definitionId })。
services/loyalty/giftCardService.js (017-loyalty-program 原始版) 和 services/giftCard/giftCardService.js (023-gift-cards 增强版) 同时存在。
loyalty 版用于 checkout 抵扣 (redeemGiftCard),giftCard 版用于 claim token / delivery state。referralRewardService 中发放 cash_voucher 奖励调用的是 loyalty 版的 purchaseGiftCard。
风险:两套服务操作同一张 gift_cards 表但逻辑不完全同步 (例如 claim_token 仅 giftCard 版生成)。
service_completed 事件通过 automation trigger engine 调度通用营销消息 (birthday recall, follow-up 等)。Review Agent 是独立的 Inngest agent,通过 checkout 事件单独触发评价短信。
两套系统各自运作,无统一编排层。运营人员配置 automation rule 时不知道 Review Agent 也会发短信,存在重复发送风险。