feat(订单): 实现推荐奖励系统支持佣金和赠送天数两种模式
Build docker and publish / build (20.15.1) (push) Failing after 9m13s
Build docker and publish / build (20.15.1) (push) Failing after 9m13s
重构推荐奖励处理逻辑,新增支持根据配置选择佣金奖励或赠送天数奖励 修改Discount相关字段类型为float64以支持小数折扣 添加GiftDays配置项控制赠送天数 新增FindActiveSubscribe方法查询用户有效订阅
This commit is contained in:
@@ -179,8 +179,8 @@ func (l *ActivateOrderLogic) NewPurchase(ctx context.Context, orderInfo *order.O
|
||||
return err
|
||||
}
|
||||
|
||||
// Handle commission in separate goroutine to avoid blocking
|
||||
go l.handleCommission(context.Background(), userInfo, orderInfo)
|
||||
// Handle referral reward in separate goroutine to avoid blocking
|
||||
go l.handleReferralReward(context.Background(), userInfo, orderInfo)
|
||||
|
||||
// Clear cache
|
||||
l.clearServerCache(ctx, sub)
|
||||
@@ -349,10 +349,12 @@ func (l *ActivateOrderLogic) createUserSubscription(ctx context.Context, orderIn
|
||||
return userSub, nil
|
||||
}
|
||||
|
||||
// handleCommission processes referral commission for the referrer if applicable.
|
||||
// handleReferralReward processes referral rewards for the referrer if applicable.
|
||||
// This runs asynchronously to avoid blocking the main order processing flow.
|
||||
func (l *ActivateOrderLogic) handleCommission(ctx context.Context, userInfo *user.User, orderInfo *order.Order) {
|
||||
if !l.shouldProcessCommission(userInfo, orderInfo.IsNew) {
|
||||
// If referral percentage > 0: commission reward
|
||||
// If referral percentage = 0: gift days to both parties
|
||||
func (l *ActivateOrderLogic) handleReferralReward(ctx context.Context, userInfo *user.User, orderInfo *order.Order) {
|
||||
if !l.shouldProcessReferralReward(userInfo, orderInfo.IsNew) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -372,13 +374,25 @@ func (l *ActivateOrderLogic) handleCommission(ctx context.Context, userInfo *use
|
||||
referralPercentage = uint8(l.svc.Config.Invite.ReferralPercentage)
|
||||
}
|
||||
|
||||
// Check if this is commission reward or gift days reward
|
||||
if referralPercentage > 0 {
|
||||
// Commission reward mode
|
||||
l.processCommissionReward(ctx, referer, orderInfo, referralPercentage)
|
||||
} else {
|
||||
// Gift days reward mode
|
||||
l.processGiftDaysReward(ctx, referer, userInfo, orderInfo)
|
||||
}
|
||||
}
|
||||
|
||||
// processCommissionReward handles commission-based rewards
|
||||
func (l *ActivateOrderLogic) processCommissionReward(ctx context.Context, referer *user.User, orderInfo *order.Order, percentage uint8) {
|
||||
// Order commission calculation: (Order Amount - Order Fee) * Referral Percentage
|
||||
amount := l.calculateCommission(orderInfo.Amount-orderInfo.FeeAmount, referralPercentage)
|
||||
amount := l.calculateCommission(orderInfo.Amount-orderInfo.FeeAmount, percentage)
|
||||
|
||||
// Use transaction for commission updates
|
||||
err = l.svc.DB.Transaction(func(tx *gorm.DB) error {
|
||||
err := l.svc.DB.Transaction(func(tx *gorm.DB) error {
|
||||
referer.Commission += amount
|
||||
if err = l.svc.UserModel.Update(ctx, referer, tx); err != nil {
|
||||
if err := l.svc.UserModel.Update(ctx, referer, tx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -420,9 +434,73 @@ func (l *ActivateOrderLogic) handleCommission(ctx context.Context, userInfo *use
|
||||
}
|
||||
}
|
||||
|
||||
// shouldProcessCommission determines if commission should be processed based on
|
||||
// processGiftDaysReward handles gift days rewards for both parties
|
||||
func (l *ActivateOrderLogic) processGiftDaysReward(ctx context.Context, referer *user.User, referee *user.User, orderInfo *order.Order) {
|
||||
giftDays := l.svc.Config.Invite.GiftDays
|
||||
if giftDays <= 0 {
|
||||
giftDays = 3 // Default to 3 days
|
||||
}
|
||||
|
||||
// Get the subscription info to determine the unit time
|
||||
sub, err := l.getSubscribeInfo(ctx, orderInfo.SubscribeId)
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("Get subscribe info failed for gift days",
|
||||
logger.Field("error", err.Error()),
|
||||
logger.Field("subscribe_id", orderInfo.SubscribeId),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
// Grant gift days to both referer and referee
|
||||
l.grantGiftDays(ctx, referer, giftDays, sub.UnitTime, "referer")
|
||||
l.grantGiftDays(ctx, referee, giftDays, sub.UnitTime, "referee")
|
||||
}
|
||||
|
||||
// grantGiftDays grants gift days to a user by extending their subscription
|
||||
func (l *ActivateOrderLogic) grantGiftDays(ctx context.Context, user *user.User, days int64, unitTime string, role string) {
|
||||
// Find user's active subscription
|
||||
userSub, err := l.svc.UserModel.FindActiveSubscribe(ctx, user.Id)
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("Find user active subscription failed for gift days",
|
||||
logger.Field("error", err.Error()),
|
||||
logger.Field("user_id", user.Id),
|
||||
logger.Field("role", role),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
if userSub == nil {
|
||||
logger.WithContext(ctx).Info("User has no active subscription for gift days",
|
||||
logger.Field("user_id", user.Id),
|
||||
logger.Field("role", role),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
// Extend subscription by gift days
|
||||
userSub.ExpireTime = tool.AddTime("day", days, userSub.ExpireTime)
|
||||
|
||||
err = l.svc.UserModel.UpdateSubscribe(ctx, userSub)
|
||||
if err != nil {
|
||||
logger.WithContext(ctx).Error("Update user subscription for gift days failed",
|
||||
logger.Field("error", err.Error()),
|
||||
logger.Field("user_id", user.Id),
|
||||
logger.Field("role", role),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
logger.WithContext(ctx).Info("Gift days granted successfully",
|
||||
logger.Field("user_id", user.Id),
|
||||
logger.Field("role", role),
|
||||
logger.Field("days", days),
|
||||
logger.Field("new_expire_time", userSub.ExpireTime),
|
||||
)
|
||||
}
|
||||
|
||||
// shouldProcessReferralReward determines if referral reward should be processed based on
|
||||
// referrer existence, commission settings, and order type
|
||||
func (l *ActivateOrderLogic) shouldProcessCommission(userInfo *user.User, isFirstPurchase bool) bool {
|
||||
func (l *ActivateOrderLogic) shouldProcessReferralReward(userInfo *user.User, isFirstPurchase bool) bool {
|
||||
if userInfo == nil || userInfo.RefererId == 0 {
|
||||
return false
|
||||
}
|
||||
@@ -504,8 +582,8 @@ func (l *ActivateOrderLogic) Renewal(ctx context.Context, orderInfo *order.Order
|
||||
// Clear cache
|
||||
l.clearServerCache(ctx, sub)
|
||||
|
||||
// Handle commission
|
||||
go l.handleCommission(context.Background(), userInfo, orderInfo)
|
||||
// Handle referral reward
|
||||
go l.handleReferralReward(context.Background(), userInfo, orderInfo)
|
||||
|
||||
// Send notifications
|
||||
l.sendNotifications(ctx, orderInfo, userInfo, sub, userSub, telegram.RenewalNotify)
|
||||
|
||||
Reference in New Issue
Block a user