package user import ( "bindbox-game/internal/repository/mysql/model" "context" "fmt" "time" "go.uber.org/zap" ) // GrantGamePass 发放游戏次数卡(购买) func (s *service) GrantGamePass(ctx context.Context, userID int64, packageID int64, count int32, orderNo string) error { s.logger.Info("GrantGamePass: 开始发放次数卡", zap.Int64("user_id", userID), zap.Int64("package_id", packageID), zap.Int32("count", count), zap.String("order_no", orderNo)) if count <= 0 { count = 1 } // 1. 获取套餐信息 pkg, err := s.readDB.GamePassPackages.WithContext(ctx). Where(s.readDB.GamePassPackages.ID.Eq(packageID)). First() if err != nil { return fmt.Errorf("package not found: %w", err) } totalPasses := pkg.PassCount * count // 2. 构造次数卡记录 now := time.Now() pass := &model.UserGamePasses{ UserID: userID, ActivityID: pkg.ActivityID, Remaining: totalPasses, TotalGranted: totalPasses, TotalUsed: 0, Source: "purchase", Remark: fmt.Sprintf("订单:%s|套餐:%s|数量:%d", orderNo, pkg.Name, count), CreatedAt: now, UpdatedAt: now, } if pkg.ValidDays > 0 { pass.ExpiredAt = now.Add(time.Duration(pkg.ValidDays) * 24 * time.Hour) } // 3. 写入数据库 q := s.writeDB.UserGamePasses.WithContext(ctx) if pass.ExpiredAt.IsZero() { q = q.Omit(s.writeDB.UserGamePasses.ExpiredAt) } if err := q.Create(pass); err != nil { s.logger.Error("GrantGamePass: 写入数据库失败", zap.Error(err)) return fmt.Errorf("failed to create user game pass: %w", err) } s.logger.Info("GrantGamePass: 发放成功", zap.Int64("pass_id", pass.ID)) return nil }