Files
rootandClaude Opus 5 8679200f41 Initial commit
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-15 13:57:10 +08:00

157 lines
4.9 KiB
Go

package activityser
import (
"context"
"fmt"
"strconv"
"91porn-server/app/appg"
"91porn-server/common/db"
"91porn-server/common/log"
"91porn-server/common/stderr"
"91porn-server/models/v/txnmod"
"91porn-server/models/v/usermod"
"91porn-server/models/v/walletmod"
)
// DeductType 扣款类型
type DeductType int
const (
DeductGold DeductType = 1 // 金币
DeductIntegral DeductType = 2 // 积分
DeductLotteryTimes DeductType = 3 // 抽奖免费次数
)
// DeductReq 扣款请求
type DeductReq struct {
UserId string `json:"userId" binding:"required"`
DeductType DeductType `json:"deductType" binding:"required"`
Amount int64 `json:"amount" binding:"required"`
ActivityId string `json:"activityId"`
Remark string `json:"remark"`
}
// Deduct 活动扣款
func Deduct(ctx context.Context, req *DeductReq) (stderr.Code, error) {
uid, err := strconv.ParseUint(req.UserId, 10, 64)
if err != nil {
return stderr.ErrParamError, fmt.Errorf("invalid userId: %s", req.UserId)
}
u, err := usermod.FindUserByUID(uid)
if err != nil {
return stderr.Failure, fmt.Errorf("查询用户异常: %w", err)
}
if u == nil {
return stderr.ErrParamError, fmt.Errorf("用户不存在: %s", req.UserId)
}
if req.Amount <= 0 {
return stderr.ErrParamError, fmt.Errorf("扣款数量必须大于0")
}
w, err := walletmod.GetWallet(uid)
if err != nil {
return stderr.Failure, fmt.Errorf("查询钱包异常: %w", err)
}
if w == nil {
w = &walletmod.Wallet{}
}
desc := req.Remark
switch req.DeductType {
case DeductGold:
if w.Amount < req.Amount {
return stderr.InsufficientGold, fmt.Errorf("金币余额不足,当前%d,需要%d", w.Amount, req.Amount)
}
return deductGold(ctx, uid, u, req, desc)
case DeductIntegral:
if w.Integral < req.Amount {
return stderr.InsufficientPoint, fmt.Errorf("积分余额不足,当前%d,需要%d", w.Integral, req.Amount)
}
return deductIntegral(ctx, uid, u, req, desc)
case DeductLotteryTimes:
if w.LotteryTimes < req.Amount {
return stderr.InsufficientLotteryFreeTimes, fmt.Errorf("抽奖免费次数不足,当前%d,需要%d", w.LotteryTimes, req.Amount)
}
return deductLotteryTimes(ctx, uid, u, req, desc)
default:
return stderr.ErrParamError, fmt.Errorf("不支持的扣款类型: %d", req.DeductType)
}
}
func deductGold(ctx context.Context, uid uint64, u *usermod.User, req *DeductReq, desc string) (stderr.Code, error) {
amount := req.Amount
err := appg.VideoDB.Trans(func(t *db.MongoTool) error {
w, err := walletmod.DebitAmount(t, amount, 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.ActivityDeductGold.Key(),
TranTypeInt: int64(txnmod.ActivityDeductGold),
Desc: fmt.Sprintf("%s-扣除%d金币", desc, amount),
SysType: u.SysType,
RealAmount: w.RealAmount(),
})
})
if err != nil {
return stderr.InsufficientGold, fmt.Errorf("金币余额不足")
}
return stderr.Success, nil
}
func deductIntegral(ctx context.Context, uid uint64, u *usermod.User, req *DeductReq, desc string) (stderr.Code, error) {
integral := req.Amount
err := appg.VideoDB.Trans(func(t *db.MongoTool) error {
_, err := walletmod.DebitIntegral(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,
Integral: -integral,
TranType: txnmod.ActivityDeductIntegral.Key(),
TranTypeInt: int64(txnmod.ActivityDeductIntegral),
Desc: fmt.Sprintf("%s-扣除%d积分", desc, integral),
SysType: u.SysType,
})
})
if err != nil {
return stderr.InsufficientPoint, fmt.Errorf("积分余额不足")
}
return stderr.Success, nil
}
func deductLotteryTimes(ctx context.Context, uid uint64, u *usermod.User, req *DeductReq, desc string) (stderr.Code, error) {
times := req.Amount
err := appg.VideoDB.Trans(func(t *db.MongoTool) error {
_, err := walletmod.DebitLotteryTimes(t, times, uid)
if err != nil {
return err
}
log.InfoX(ctx, "活动扣款-扣除抽奖免费次数", 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.ActivityDeductLotteryTimes.Key(),
TranTypeInt: int64(txnmod.ActivityDeductLotteryTimes),
Desc: fmt.Sprintf("%s-扣除抽奖免费%d次", desc, times),
SysType: u.SysType,
})
})
if err != nil {
return stderr.InsufficientLotteryFreeTimes, fmt.Errorf("抽奖免费次数不足")
}
return stderr.Success, nil
}