@@ -0,0 +1,378 @@
|
||||
package activityser
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"91porn-server/app/appg"
|
||||
"91porn-server/common/db"
|
||||
"91porn-server/common/log"
|
||||
"91porn-server/models/v/backpackmod"
|
||||
"91porn-server/models/v/txnmod"
|
||||
"91porn-server/models/v/usermod"
|
||||
"91porn-server/models/v/videocoupon"
|
||||
"91porn-server/models/v/walletmod"
|
||||
)
|
||||
|
||||
// RewardType 奖励类型
|
||||
type RewardType int
|
||||
|
||||
const (
|
||||
RewardGold RewardType = 1 // 金币
|
||||
RewardVIP RewardType = 2 // 会员卡(VIP天数)
|
||||
RewardGoldBonusCoupon RewardType = 3 // 金币加赠券
|
||||
RewardGoldVideoCoupon RewardType = 4 // 金币观影券
|
||||
RewardAiChangeFaceFree RewardType = 5 // AI视频换脸免费次数
|
||||
RewardAiUndressFree RewardType = 6 // AI脱衣免费次数
|
||||
RewardIntegral RewardType = 7 // 积分
|
||||
RewardPhysical RewardType = 8 // 实物奖品
|
||||
)
|
||||
|
||||
// AddressInfo 收货地址信息
|
||||
type AddressInfo struct {
|
||||
Name string `json:"name"`
|
||||
Phone string `json:"phone"`
|
||||
Address string `json:"address"`
|
||||
}
|
||||
|
||||
// RewardReq 发奖请求
|
||||
type RewardReq struct {
|
||||
RequestId string `json:"requestId"`
|
||||
UserId string `json:"userId" binding:"required"`
|
||||
RewardType RewardType `json:"rewardType" binding:"required"`
|
||||
Amount int64 `json:"amount" binding:"required"`
|
||||
CouponValue int64 `json:"couponValue"`
|
||||
Duration int `json:"duration"`
|
||||
ActivityId string `json:"activityId"`
|
||||
RewardName string `json:"rewardName"`
|
||||
Remark string `json:"remark"`
|
||||
Address *AddressInfo `json:"address"`
|
||||
}
|
||||
|
||||
// RewardItem 批量发奖中的单个奖品
|
||||
type RewardItem struct {
|
||||
RequestId string `json:"requestId"`
|
||||
RewardType RewardType `json:"rewardType"`
|
||||
Amount int64 `json:"amount"`
|
||||
CouponValue int64 `json:"couponValue"`
|
||||
Duration int `json:"duration"`
|
||||
RewardName string `json:"rewardName"`
|
||||
Address *AddressInfo `json:"address"`
|
||||
}
|
||||
|
||||
// BatchRewardReq 批量发奖请求
|
||||
type BatchRewardReq struct {
|
||||
UserId string `json:"userId" binding:"required"`
|
||||
ActivityId string `json:"activityId"`
|
||||
Remark string `json:"remark"`
|
||||
Rewards []RewardItem `json:"rewards" binding:"required"`
|
||||
}
|
||||
|
||||
// GrantBatchReward 批量发放活动奖励
|
||||
func GrantBatchReward(ctx context.Context, req *BatchRewardReq) error {
|
||||
if len(req.Rewards) == 0 {
|
||||
return nil
|
||||
}
|
||||
uid, err := strconv.ParseUint(req.UserId, 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid userId: %s", req.UserId)
|
||||
}
|
||||
u, err := usermod.FindUserByUID(uid)
|
||||
if err != nil {
|
||||
return fmt.Errorf("查询用户异常: %w", err)
|
||||
}
|
||||
if u == nil {
|
||||
return fmt.Errorf("用户不存在: %s", req.UserId)
|
||||
}
|
||||
return appg.VideoDB.Trans(func(t *db.MongoTool) error {
|
||||
for _, item := range req.Rewards {
|
||||
single := &RewardReq{
|
||||
RequestId: item.RequestId,
|
||||
UserId: req.UserId,
|
||||
RewardType: item.RewardType,
|
||||
Amount: item.Amount,
|
||||
CouponValue: item.CouponValue,
|
||||
Duration: item.Duration,
|
||||
ActivityId: req.ActivityId,
|
||||
RewardName: item.RewardName,
|
||||
Remark: req.Remark,
|
||||
Address: item.Address,
|
||||
}
|
||||
if err := grantRewardTx(ctx, t, uid, u, single); err != nil {
|
||||
log.ErrorX(ctx, "批量发奖-单项失败已跳过",
|
||||
log.Any("uid", req.UserId),
|
||||
log.Any("requestId", item.RequestId),
|
||||
log.Any("rewardType", item.RewardType),
|
||||
log.E(err))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// GrantReward 发放活动奖励(单个)
|
||||
func GrantReward(ctx context.Context, req *RewardReq) error {
|
||||
uid, err := strconv.ParseUint(req.UserId, 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid userId: %s", req.UserId)
|
||||
}
|
||||
u, err := usermod.FindUserByUID(uid)
|
||||
if err != nil {
|
||||
return fmt.Errorf("查询用户异常: %w", err)
|
||||
}
|
||||
if u == nil {
|
||||
return fmt.Errorf("用户不存在: %s", req.UserId)
|
||||
}
|
||||
|
||||
return appg.VideoDB.Trans(func(t *db.MongoTool) error {
|
||||
return grantRewardTx(ctx, t, uid, u, req)
|
||||
})
|
||||
}
|
||||
|
||||
func grantRewardTx(ctx context.Context, t *db.MongoTool, uid uint64, u *usermod.User, req *RewardReq) error {
|
||||
desc := req.Remark
|
||||
|
||||
switch req.RewardType {
|
||||
case RewardGold:
|
||||
return grantGoldTx(ctx, t, uid, u, req, desc)
|
||||
case RewardVIP:
|
||||
return grantVIPTx(ctx, t, uid, u, req, desc)
|
||||
case RewardGoldBonusCoupon:
|
||||
return grantGoldBonusCouponTx(ctx, t, uid, u, req, desc)
|
||||
case RewardGoldVideoCoupon:
|
||||
return grantGoldVideoCouponTx(ctx, t, uid, u, req, desc)
|
||||
case RewardAiChangeFaceFree:
|
||||
return grantAiChangeFaceFreeTx(ctx, t, uid, u, req, desc)
|
||||
case RewardAiUndressFree:
|
||||
return grantAiUndressFreeTx(ctx, t, uid, u, req, desc)
|
||||
case RewardIntegral:
|
||||
return grantIntegralTx(ctx, t, uid, u, req, desc)
|
||||
case RewardPhysical:
|
||||
return grantPhysicalTx(ctx, t, uid, u, req, desc)
|
||||
default:
|
||||
return fmt.Errorf("不支持的奖励类型: %d", req.RewardType)
|
||||
}
|
||||
}
|
||||
|
||||
func grantGoldTx(ctx context.Context, t *db.MongoTool, uid uint64, u *usermod.User, req *RewardReq, desc string) error {
|
||||
amount := req.Amount
|
||||
creditPlan := walletmod.CreditPlan{Amount: &amount}
|
||||
|
||||
w, err := walletmod.Credit(t, creditPlan, uid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.InfoX(ctx, "活动发放-发放金币", log.Any("uid", uid), log.Any("amount", amount), log.Any("activityId", req.ActivityId))
|
||||
return txnmod.InsertTransactionLog(t, &txnmod.TransactionLog{
|
||||
UID: uid,
|
||||
Amount: amount,
|
||||
ActualAmount: float64(amount),
|
||||
TranType: txnmod.ActivityRewardGold.Key(),
|
||||
TranTypeInt: int64(txnmod.ActivityRewardGold),
|
||||
Desc: fmt.Sprintf("%s-发放%d金币", desc, amount),
|
||||
SysType: u.SysType,
|
||||
RealAmount: w.RealAmount(),
|
||||
UniqueOrder: req.RequestId,
|
||||
})
|
||||
}
|
||||
|
||||
func grantVIPTx(ctx context.Context, t *db.MongoTool, uid uint64, u *usermod.User, req *RewardReq, desc string) error {
|
||||
days := int(req.Amount)
|
||||
if days <= 0 {
|
||||
return errors.New("VIP天数必须大于0")
|
||||
}
|
||||
|
||||
var expire time.Time
|
||||
if u.VipExpireDate.After(time.Now()) {
|
||||
expire = u.VipExpireDate.AddDate(0, 0, days)
|
||||
} else {
|
||||
expire = time.Now().AddDate(0, 0, days)
|
||||
}
|
||||
|
||||
vipLevel := 1
|
||||
if u.VipLevel > vipLevel {
|
||||
vipLevel = u.VipLevel
|
||||
}
|
||||
|
||||
sel := usermod.UserSelector{
|
||||
VipExpireDate: &expire,
|
||||
VipLevel: &vipLevel,
|
||||
}
|
||||
if err := usermod.UpdateVIP(t, uid, u.VipExpireDate, sel); err != nil {
|
||||
return err
|
||||
}
|
||||
log.InfoX(ctx, "活动发放-发放VIP", log.Any("uid", uid), log.Any("days", days), log.Any("activityId", req.ActivityId))
|
||||
return txnmod.InsertTransactionLog(t, &txnmod.TransactionLog{
|
||||
UID: uid,
|
||||
TranType: txnmod.ActivityRewardVIP.Key(),
|
||||
TranTypeInt: int64(txnmod.ActivityRewardVIP),
|
||||
Desc: fmt.Sprintf("%s-发放VIP%d天", desc, days),
|
||||
SysType: u.SysType,
|
||||
UniqueOrder: req.RequestId,
|
||||
})
|
||||
}
|
||||
|
||||
func grantGoldBonusCouponTx(ctx context.Context, t *db.MongoTool, uid uint64, u *usermod.User, req *RewardReq, desc string) error {
|
||||
if req.CouponValue <= 0 {
|
||||
return errors.New("券额度(couponValue)必须大于0")
|
||||
}
|
||||
|
||||
if err := txnmod.InsertTransactionLog(t, &txnmod.TransactionLog{
|
||||
UID: uid,
|
||||
Amount: req.Amount,
|
||||
TranType: txnmod.ActivityRewardGoldBonusCoupon.Key(),
|
||||
TranTypeInt: int64(txnmod.ActivityRewardGoldBonusCoupon),
|
||||
Desc: fmt.Sprintf("%s-发放金币加赠券%d张", desc, req.Amount),
|
||||
SysType: u.SysType,
|
||||
UniqueOrder: req.RequestId,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
expiredAt := now.AddDate(0, 0, 30)
|
||||
for i := int64(0); i < req.Amount; i++ {
|
||||
item := backpackmod.Backpack{
|
||||
UID: uid,
|
||||
GoodsType: backpackmod.GoldBonusCoupon,
|
||||
GoodsValue: req.CouponValue,
|
||||
GoodsOrigin: desc,
|
||||
Status: backpackmod.Unused,
|
||||
ExpiredTime: expiredAt,
|
||||
CreateTime: now,
|
||||
}
|
||||
if err := backpackmod.AddGoods(t, uid, item); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
log.InfoX(ctx, "活动发放-发放金币加赠券", log.Any("uid", uid), log.Any("couponValue", req.CouponValue), log.Any("amount", req.Amount))
|
||||
return nil
|
||||
}
|
||||
|
||||
func grantGoldVideoCouponTx(ctx context.Context, t *db.MongoTool, uid uint64, u *usermod.User, req *RewardReq, desc string) error {
|
||||
if req.CouponValue <= 0 {
|
||||
return errors.New("券额度(couponValue)必须大于0")
|
||||
}
|
||||
|
||||
if err := txnmod.InsertTransactionLog(t, &txnmod.TransactionLog{
|
||||
UID: uid,
|
||||
Amount: req.Amount,
|
||||
TranType: txnmod.ActivityRewardGoldVideoCoupon.Key(),
|
||||
TranTypeInt: int64(txnmod.ActivityRewardGoldVideoCoupon),
|
||||
Desc: fmt.Sprintf("%s-发放金币观影券%d张", desc, req.Amount),
|
||||
SysType: u.SysType,
|
||||
UniqueOrder: req.RequestId,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
coupons := make([]videocoupon.UserGoldVideoCoupon, 0, req.Amount)
|
||||
for i := int64(0); i < req.Amount; i++ {
|
||||
coupons = append(coupons, videocoupon.UserGoldVideoCoupon{
|
||||
UID: uid,
|
||||
Num: int(req.CouponValue),
|
||||
Used: false,
|
||||
Source: videocoupon.GoldVideoCouponSource(desc),
|
||||
})
|
||||
}
|
||||
if err := videocoupon.InsertManyTrans(t, coupons); err != nil {
|
||||
return err
|
||||
}
|
||||
log.InfoX(ctx, "活动发放-发放金币观影券", log.Any("uid", uid), log.Any("couponValue", req.CouponValue), log.Any("amount", req.Amount))
|
||||
return nil
|
||||
}
|
||||
|
||||
func grantAiChangeFaceFreeTx(ctx context.Context, t *db.MongoTool, uid uint64, u *usermod.User, req *RewardReq, desc string) error {
|
||||
if err := txnmod.InsertTransactionLog(t, &txnmod.TransactionLog{
|
||||
UID: uid,
|
||||
Amount: req.Amount,
|
||||
TranType: txnmod.ActivityRewardAiChangeFaceFree.Key(),
|
||||
TranTypeInt: int64(txnmod.ActivityRewardAiChangeFaceFree),
|
||||
Desc: fmt.Sprintf("%s-发放AI换脸免费%d次", desc, req.Amount),
|
||||
SysType: u.SysType,
|
||||
UniqueOrder: req.RequestId,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
permanent := time.Date(2099, 12, 31, 23, 59, 59, 0, time.Local)
|
||||
item := backpackmod.Backpack{
|
||||
UID: uid,
|
||||
GoodsType: backpackmod.AiChangeFaceDiscount,
|
||||
GoodsValue: req.Amount,
|
||||
GoodsOrigin: desc,
|
||||
Status: backpackmod.Unused,
|
||||
ExpiredTime: permanent,
|
||||
CreateTime: now,
|
||||
}
|
||||
if err := backpackmod.AddGoods(t, uid, item); err != nil {
|
||||
return err
|
||||
}
|
||||
log.InfoX(ctx, "活动发放-发放AI换脸免费次数", log.Any("uid", uid), log.Any("times", req.Amount))
|
||||
return nil
|
||||
}
|
||||
|
||||
func grantIntegralTx(ctx context.Context, t *db.MongoTool, uid uint64, u *usermod.User, req *RewardReq, desc string) error {
|
||||
integral := req.Amount
|
||||
|
||||
_, err := walletmod.CreditIntegral(t, integral, uid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.InfoX(ctx, "活动发放-发放积分", log.Any("uid", uid), log.Any("integral", integral), log.Any("activityId", req.ActivityId))
|
||||
return txnmod.InsertTransactionLog(t, &txnmod.TransactionLog{
|
||||
UID: uid,
|
||||
Amount: integral,
|
||||
TranType: txnmod.ActivityRewardIntegral.Key(),
|
||||
TranTypeInt: int64(txnmod.ActivityRewardIntegral),
|
||||
Desc: fmt.Sprintf("%s-发放%d积分", desc, integral),
|
||||
SysType: u.SysType,
|
||||
UniqueOrder: req.RequestId,
|
||||
})
|
||||
}
|
||||
|
||||
func grantAiUndressFreeTx(ctx context.Context, t *db.MongoTool, uid uint64, u *usermod.User, req *RewardReq, desc string) error {
|
||||
times := req.Amount
|
||||
creditPlan := walletmod.CreditPlan{AiUndressFreeTimes: ×}
|
||||
|
||||
_, err := walletmod.Credit(t, creditPlan, uid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.InfoX(ctx, "活动发放-发放AI脱衣免费次数", log.Any("uid", uid), log.Any("times", times), log.Any("activityId", req.ActivityId))
|
||||
return txnmod.InsertTransactionLog(t, &txnmod.TransactionLog{
|
||||
UID: uid,
|
||||
Amount: times,
|
||||
TranType: txnmod.ActivityRewardAiUndressFree.Key(),
|
||||
TranTypeInt: int64(txnmod.ActivityRewardAiUndressFree),
|
||||
Desc: fmt.Sprintf("%s-发放AI脱衣免费%d次", desc, times),
|
||||
SysType: u.SysType,
|
||||
UniqueOrder: req.RequestId,
|
||||
})
|
||||
}
|
||||
|
||||
func grantPhysicalTx(ctx context.Context, t *db.MongoTool, uid uint64, u *usermod.User, req *RewardReq, desc string) error {
|
||||
addrDesc := ""
|
||||
if req.Address != nil {
|
||||
addrDesc = fmt.Sprintf("【 收件人:%s 手机:%s 地址:%s】", req.Address.Name, req.Address.Phone, req.Address.Address)
|
||||
}
|
||||
rewardName := req.RewardName
|
||||
if rewardName == "" {
|
||||
rewardName = "实物奖品"
|
||||
}
|
||||
|
||||
log.InfoX(ctx, "活动发放-发放实物奖品", log.Any("uid", uid), log.Any("rewardName", rewardName), log.Any("activityId", req.ActivityId), log.Any("address", addrDesc))
|
||||
return txnmod.InsertTransactionLog(t, &txnmod.TransactionLog{
|
||||
UID: uid,
|
||||
Amount: req.Amount,
|
||||
TranType: txnmod.ActivityRewardPhysical.Key(),
|
||||
TranTypeInt: int64(txnmod.ActivityRewardPhysical),
|
||||
Desc: fmt.Sprintf("%s-发放%s%s", desc, rewardName, addrDesc),
|
||||
SysType: u.SysType,
|
||||
UniqueOrder: req.RequestId,
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user