修复(#75): 按数量精确匹配套餐列表促销
- loadSubscribePromoMap 返回 map[subscribeID]map[quantity]*SubscribePromo 二级映射 - 候选查询按 subscribe_id、quantity、priority DESC 排序,一次取出所有 quantity 档位 - 下单路径 QueryEligibleRules 将 quantity 条件移至 JOIN,精确匹配 - 永久订阅(expire_time=0)用 CASE WHEN 排序兜底,不再误判为回归促销 - 新增 promoEligibility、model、subscribe promo 单元测试 Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
)
|
||||
|
||||
type PromoResult struct {
|
||||
@@ -148,7 +149,12 @@ func evaluateInactiveUserPromo(
|
||||
err := db.WithContext(ctx).
|
||||
Model(&user.Subscribe{}).
|
||||
Where("user_id = ?", userID).
|
||||
Order("expire_time DESC").
|
||||
Order(clause.OrderBy{
|
||||
Expression: clause.Expr{
|
||||
SQL: "CASE WHEN expire_time = ? THEN 0 ELSE 1 END, expire_time DESC",
|
||||
Vars: []interface{}{time.UnixMilli(0)},
|
||||
},
|
||||
}).
|
||||
Limit(1).
|
||||
Take(&lastSub).Error
|
||||
if err != nil {
|
||||
@@ -158,8 +164,16 @@ func evaluateInactiveUserPromo(
|
||||
return false, time.Time{}, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "query promo inactive user subscription failed")
|
||||
}
|
||||
|
||||
return evaluateInactiveUserExpire(lastSub.ExpireTime, params, now), ruleExpiresAt, nil
|
||||
}
|
||||
|
||||
func evaluateInactiveUserExpire(lastExpire time.Time, params promoRuleParams, now time.Time) bool {
|
||||
if lastExpire.Equal(time.UnixMilli(0)) {
|
||||
return false
|
||||
}
|
||||
|
||||
threshold := now.AddDate(0, -params.InactiveMonths, 0)
|
||||
return lastSub.ExpireTime.Before(threshold) || lastSub.ExpireTime.Equal(threshold), ruleExpiresAt, nil
|
||||
return lastExpire.Before(threshold) || lastExpire.Equal(threshold)
|
||||
}
|
||||
|
||||
func promoRuleExpiresAt(rule *promo.RuleWithPrice) time.Time {
|
||||
|
||||
Reference in New Issue
Block a user