48e507783e
- 新增 SubscribePromo 响应结构,套餐列表每项追加 promo 字段 - 新增 promo.go 促销候选规则查询与资格评估逻辑 - 重构 authMiddleware 提取 authenticateRequest,新增 OptionalAuthMiddleware - /v1/public/subscribe/list 改为可选鉴权,未登录仅展示 campaign 类型促销 - /node/list、/group/list 保持强制鉴权不变 - 每个规格只返回最高优先级命中的规则,promo_price 为单价,expires_at 为秒级时间戳 - 新增单测覆盖 campaign/new_user 命中、活动窗口判定等场景 Co-authored-by: multica-agent <github@multica.ai>
76 lines
2.3 KiB
Go
76 lines
2.3 KiB
Go
package subscribe
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/perfect-panel/server/internal/model/user"
|
|
)
|
|
|
|
func TestPromoEligibilityEvaluatorMatch(t *testing.T) {
|
|
now := time.Unix(1710000000, 0)
|
|
campaignEnd := now.Add(2 * time.Hour)
|
|
|
|
campaign := subscribePromoCandidate{
|
|
RuleName: "限时活动",
|
|
RuleType: promoRuleTypeCampaign,
|
|
PromoPrice: 99,
|
|
EndTime: &campaignEnd,
|
|
}
|
|
ok, expiresAt, err := (&promoEligibilityEvaluator{}).match(campaign, now)
|
|
if err != nil {
|
|
t.Fatalf("campaign match error: %v", err)
|
|
}
|
|
if !ok {
|
|
t.Fatal("campaign promo should match without login")
|
|
}
|
|
if got, want := unixSeconds(expiresAt), campaignEnd.Unix(); got != want {
|
|
t.Fatalf("campaign expires_at = %d, want %d", got, want)
|
|
}
|
|
|
|
newUser := subscribePromoCandidate{
|
|
RuleName: "新客7天优惠",
|
|
RuleType: promoRuleTypeNewUser,
|
|
PromoPrice: 279,
|
|
Params: `{"window_hours":168}`,
|
|
}
|
|
ok, _, err = (&promoEligibilityEvaluator{}).match(newUser, now)
|
|
if err != nil {
|
|
t.Fatalf("anonymous new_user match error: %v", err)
|
|
}
|
|
if ok {
|
|
t.Fatal("new_user promo should not match without login")
|
|
}
|
|
|
|
userInfo := &user.User{Id: 1, CreatedAt: now.Add(-24 * time.Hour)}
|
|
ok, expiresAt, err = (&promoEligibilityEvaluator{userInfo: userInfo}).match(newUser, now)
|
|
if err != nil {
|
|
t.Fatalf("logged-in new_user match error: %v", err)
|
|
}
|
|
if !ok {
|
|
t.Fatal("new_user promo should match inside window")
|
|
}
|
|
if got, want := unixSeconds(expiresAt), userInfo.CreatedAt.Add(168*time.Hour).Unix(); got != want {
|
|
t.Fatalf("new_user expires_at = %d, want %d", got, want)
|
|
}
|
|
}
|
|
|
|
func TestSubscribePromoCandidateActiveWindow(t *testing.T) {
|
|
now := time.Unix(1710000000, 0)
|
|
start := now.Add(-time.Hour)
|
|
end := now.Add(time.Hour)
|
|
|
|
if !(subscribePromoCandidate{PromoPrice: 1, StartTime: &start, EndTime: &end}).isActive(now) {
|
|
t.Fatal("candidate inside active window should be active")
|
|
}
|
|
if (subscribePromoCandidate{PromoPrice: 0, StartTime: &start, EndTime: &end}).isActive(now) {
|
|
t.Fatal("candidate with zero promo price should not be active")
|
|
}
|
|
if (subscribePromoCandidate{PromoPrice: 1, StartTime: &end}).isActive(now) {
|
|
t.Fatal("candidate before start time should not be active")
|
|
}
|
|
if (subscribePromoCandidate{PromoPrice: 1, EndTime: &start}).isActive(now) {
|
|
t.Fatal("candidate after end time should not be active")
|
|
}
|
|
}
|