bindbox-game/internal/service/user/game_pass_testtool.go
Zuncle 3db52af4b6 feat(activity): 重构福利活动并支持统一奖池
对齐福利活动新库表结构,支持商品、道具卡和优惠券统一建奖、开奖与中奖记录。
同时新增福利活动测试命令行工具,便于模拟消费、参与活动并验证完整开奖链路。
2026-04-29 17:21:11 +08:00

109 lines
2.8 KiB
Go

package user
import (
"context"
"errors"
"fmt"
"strings"
"time"
"bindbox-game/internal/pkg/env"
"bindbox-game/internal/repository/mysql/model"
"gorm.io/gorm"
)
type CreatePaidGamePassOrderForTestInput struct {
UserID int64
PackageID int64
Count int32
Operator string
}
type CreatePaidGamePassOrderForTestOutput struct {
OrderNo string
PackageName string
PackageID int64
Count int32
TotalAmount int64
PaidAt time.Time
UserID int64
ActivityID int64
PassesGranted int32
}
func (s *service) CreatePaidGamePassOrderForTest(ctx context.Context, input CreatePaidGamePassOrderForTestInput) (*CreatePaidGamePassOrderForTestOutput, error) {
if env.Active().IsPro() {
return nil, errors.New("正式环境禁止执行福利测试购买工具")
}
if input.UserID <= 0 {
return nil, errors.New("用户ID无效")
}
if input.PackageID <= 0 {
return nil, errors.New("套餐ID无效")
}
if input.Count <= 0 {
return nil, errors.New("购买次数必须大于0")
}
if input.Count > 999 {
return nil, errors.New("购买次数过大")
}
pkg, err := s.readDB.GamePassPackages.WithContext(ctx).
Where(s.readDB.GamePassPackages.ID.Eq(input.PackageID)).
Where(s.readDB.GamePassPackages.Status.Eq(1)).
First()
if err != nil || pkg == nil {
return nil, errors.New("套餐不存在或已下架")
}
totalPrice := pkg.Price * int64(input.Count)
now := time.Now()
orderNo := fmt.Sprintf("GPTEST%s%04d", now.Format("20060102150405"), now.UnixNano()%10000)
operator := strings.TrimSpace(input.Operator)
if operator == "" {
operator = "cli"
}
remark := fmt.Sprintf("game_pass_package:%s|pkg_id:%d|count:%d|test:welfare_cmd|operator:%s", pkg.Name, pkg.ID, input.Count, operator)
minValidTime := time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC)
err = s.repo.GetDbW().WithContext(ctx).Transaction(func(tx *gorm.DB) error {
order := &model.Orders{
UserID: input.UserID,
OrderNo: orderNo,
SourceType: 4,
TotalAmount: totalPrice,
DiscountAmount: 0,
PointsAmount: 0,
ActualAmount: totalPrice,
Status: 2,
PaidAt: now,
CancelledAt: minValidTime,
IsConsumed: 0,
Remark: remark,
ExtOrderID: "",
CreatedAt: now,
UpdatedAt: now,
}
if err := tx.WithContext(ctx).Create(order).Error; err != nil {
return err
}
return s.GrantGamePass(ctx, input.UserID, pkg.ID, input.Count, orderNo)
})
if err != nil {
return nil, err
}
return &CreatePaidGamePassOrderForTestOutput{
OrderNo: orderNo,
PackageName: pkg.Name,
PackageID: pkg.ID,
Count: input.Count,
TotalAmount: totalPrice,
PaidAt: now,
UserID: input.UserID,
ActivityID: pkg.ActivityID,
PassesGranted: pkg.PassCount * input.Count,
}, nil
}