157 lines
4.9 KiB
Go
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
|
|
}
|