Joy Loyalty · Membership · Plan V2 · SB-12028 / MR !4396
App Joy Subscription đã chuyển từ API product-based (V1) sang plan-based (V2). Joy Loyalty tích hợp với Joy Subscription để gán VIP tier cho người subscribe — nên phải migrate tích hợp theo để tính năng tiếp tục chạy: hỗ trợ nhiều sản phẩm/plan, đồng bộ admin UX với app JS mới, và đồng bộ dữ liệu chủ động khi merchant xoá plan. Kèm sửa lỗi xử lý webhook tồn tại sẵn.
Joy Subscription nâng cấp API, Joy Loyalty phải migrate tích hợp theo — nếu không, người subscribe trên plan kiểu mới sẽ không được gán VIP tier.
Joy Subscription đổi mô hình dữ liệu. Trước đây một subscription chỉ gắn 1 sản phẩm (product-based, V1). API mới (plan-based, V2) cho phép nhiều sản phẩm trong cùng một plan. Joy Loyalty đang gọi API cũ — không theo kịp mô hình mới sẽ hỏng tích hợp.
Admin chuyển sang app Joy Subscription. Bản mới merchant tạo/sửa/xoá plan ngay trong app Joy Subscription (UI giàu hơn). Hệ quả: merchant xoá plan bên đó thường xuyên hơn → cách Joy dọn dữ liệu cũ (chỉ dọn khi mở trang) không bắt kịp → cần đồng bộ chủ động qua webhook.
Lỗi webhook có sẵn (ảnh hưởng cả bản cũ). Khi khách subscribe/huỷ, Joy Subscription bắn webhook sang Joy để gán/gỡ tier. Phát hiện: cửa sổ kích hoạt (Activation window) bị bỏ qua hoàn toàn — plan hết hạn vẫn promote, plan chưa tới ngày cũng promote luôn. Ngoài ra mọi thay đổi tier qua webhook không ghi activity log → CS/admin không truy được lịch sử.
Migrate tích hợp sang API plan-based + admin V2 đồng bộ với app JS + đồng bộ dữ liệu chủ động + sửa lỗi webhook.
Đổi tích hợp Joy ↔ Joy Subscription sang API plan-based (hỗ trợ nhiều sản phẩm/plan). Màn admin V2 trong Joy: chọn nhiều sản phẩm, cấu hình từng frequency (tier · ưu tiên · cửa sổ ngày · auto-tag · giảm giá), preview storefront real-time, widget settings gương từ app JS. Router tự tách shop V1 ↔ V2 — không phá bản cũ.
Sửa cửa sổ kích hoạt (đọc ngày từ chính dữ liệu Joy, không phụ thuộc payload), ghi activity log mỗi lần đổi tier (kèm tên plan + contract), và xoá sạch dữ liệu loyalty khi Joy Subscription xoá plan (cascade delete) — thay cho cơ chế dọn-khi-mở-trang vốn không kịp với admin flow mới.
Luồng A — Merchant tạo/sửa plan trong Joy admin
Luồng B — Khách subscribe / huỷ → tier tự đổi
Màn sửa frequency: form bên trái, preview storefront real-time bên phải, nút chuyển nhanh giữa các frequency ở góc trên.
Test backend webhook trên dev shop dopd-joy-dev.myshopify.com (Firebase emulator → staging Firestore). Phase N chạy trên 3 khách hàng thật, kiểm tra cả dữ liệu Firestore lẫn activity feed UI.
| Khách | Kịch bản | Kết quả render thật |
|---|---|---|
| C1 — dopdtestrefund@ | Subscribe plan có tier Silver | VIP Tier → Silver; activity: "User joined a membership plan — tier moved from Bronze to Silver"; tag c1-vip được gắn |
| C2 — maint@ | Huỷ subscription (đang ở Subscriber) | VIP Tier → Bronze (fallback); activity: "Membership ended — tier moved from Subscriber to Bronze"; tag được gỡ |
| C3 — dopd@ | Đổi từ plan Silver (ưu tiên thấp) sang plan Subscriber (ưu tiên cao) | VIP Tier → Subscriber; activity: "User joined a membership plan — tier moved from Silver to Subscriber" |
Tổng cộng 61 kịch bản backend webhook PASS (Phase A–O), 0 fail — phủ middleware, dispatch, lọc plan, validation, ưu tiên, đổi tier, gắn/gỡ tag, xoá plan.
membership của khách bị reset (intentional) — lịch sử tra qua activity feed (tab "VIP tier changes"), không qua hồ sơ khách.