Appearance
Type Deep Dive — Statistics Notification And History
1. History Tabs Không Dùng Nguồn Riêng
1.1 Shake History
ShakeHistory.tsx query gamification_claim_logs với filter:
gamification_id = current campaigngift_config.type = gf_own_gift_configsender_id is null
Nghĩa là tab này cố ý loại bỏ gifting giữa bạn bè và chỉ giữ own-gift runtime.
1.2 Gift History
GiftHistory.tsx cũng query gamification_claim_logs, nhưng filter:
gamification_id = current campaigngifted_from = gifted_from_friend
Nghĩa là tab này là lens riêng cho quà được tặng qua bạn bè.
2. Statistics Read Models
2.1 List cards
List campaign đọc relationship statistics từ view gamification_statistics.
View này tính:
total_gift_quantityclaimed_gift_countclaimed_percentageparticipant_count
Nhưng loại trừ gift_type_greeting khỏi total/claimed count (1766950000000_add_gamification_statistics_view/up.sql).
2.2 Detail statistics
Tab Statistics dùng 3 functions:
get_gamification_campaign_summaryget_gamification_spins_by_timeget_gamification_gift_distribution
FE build args từ:
campaign_id- date range
- optional branch IDs
view_mode = daily/hourlycho line chart (Statistics.tsx:71-122)
3. Notification Config Engine
gamification_notification_config là bảng riêng tách khỏi campaign core, có:
reference_typereference_template_id/_stringmanual_templatesend_configstop_configpriority
Remote relationships nối sang source notification cho:
notification_templatezns_templatesms_template
FE form hiện có cả:
- push,
- sms,
- zns,
- zns + sms fallback (
CampaignCreateUpdate.tsx:1315-1410)
4. Notification Dispatch Runtime
SendGamificationNotification(...):
- load all
gamification_notification_configtheogamification_id, - parse template + sendConfig + stopConfig,
- filter config theo
conditionType, - enrich thêm campaign/customer data nếu template cần,
- tính
sendAftertheo pending type / offset, - ghi notification logs và dispatch qua push/SMS/ZNS paths (
gamification_notification.go:111-260).
Điểm đáng chú ý:
- nếu config không có
NotiSendingConditionType, code fallback sangGamificationNotificationCondition, - pending types
days_before,hours_before,minutes_beforecầnGameEndTime, - gửi notification không chỉ là synchronous send; có cả scheduling semantics qua
sendAfter.
5. Scheduler Boundary
end_expired_gamification là cron boundary duy nhất tôi thấy ở package này:
- tìm campaign
publishedquá hạn, - update sang
ended, - trả count campaign bị đóng.
Nếu notification stop conditions dựa trên game ended, cron này chính là source của event trạng thái thật chứ không phải FE action.
6. FE/DB Drift Liên Quan History Và Noti
Một drift đáng chú ý:
- FE constants file khai báo notification/stop condition IDs kiểu
on_start,end_date,manual, - DB master data thực tế dùng
gf_noti_*vàgf_stop_*.
Hiện runtime options đang lấy từ GetGamificationMasterData, nên form có thể vẫn chạy đúng. Nhưng bất kỳ validator/helper nào dùng constants file sẽ có nguy cơ sai ngầm.
7. QA Focus
- So sánh
ShakeHistory,GiftHistoryvàstatisticstrên cùng campaign để xác minh filter semantics. - Campaign chỉ có blessing gifts để kiểm tra dashboard claimed percentage và total gift quantity.
- Notification config push/SMS/ZNS với cùng condition để kiểm tra filter theo
conditionType. - Pending type
days_before/hours_before/minutes_befoređể kiểm trasendAfter. - Campaign end bằng action thủ công và bằng scheduler để kiểm tra stop behavior của noti/history.
8. Rủi ro / Findings kỹ thuật
| ID | Mức | Finding |
|---|---|---|
| SN-F01 | P1 | gamification_statistics loại trừ blessing khỏi total/claimed metrics, nên stakeholder rất dễ hiểu sai “tổng quà” nếu không biết rule này. |
| SN-F02 | P1 | History tabs cùng đọc claim_logs nhưng filter rất khác; chỉ test một tab sẽ không đủ coverage cho runtime log semantics. |
| SN-F03 | P2 | Notification runtime phụ thuộc JSON config khá linh hoạt (manual_template, send_config, stop_config), nên sai cấu hình có thể chỉ lộ khi dispatch thật. |