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 }