package payment import ( "context" "fmt" "hkdj-web-server/pub/common/log" "hkdj-web-server/pub/common/srvdef" "hkdj-web-server/pub/common/utils" "hkdj-web-server/pub/models/cointransmod" "hkdj-web-server/pub/models/usermod" "hkdj-web-server/pub/mongos" "go.mongodb.org/mongo-driver/bson" ) // WriteCoinTransOpt 写流水所需参数 type WriteCoinTransOpt struct { UserId int64 UserName string // 可为空,自动查询 FlowDir cointransmod.FlowDir // FlowIn / FlowOut TranType cointransmod.TranType // 交易类型 Amount int64 // 本次交易金币数(正整数) OrderNo string // 关联订单号(可为空) RelatedId int64 // 关联内容ID(可为空) Remark string // 备注 } // WriteCoinTrans 写一条金币流水记录 // balanceBefore 和 balanceAfter 从用户当前余额自动推算: // - 若传入 balanceAfter(>= 0),直接使用; // - 否则查库获取用户当前余额作为 balanceAfter,再反推 balanceBefore。 func WriteCoinTrans(ctx context.Context, opt WriteCoinTransOpt, balanceAfter int64) *srvdef.SrvErr { userName := opt.UserName if userName == "" { if u, _ := usermod.FindOneUser(ctx, bson.M{usermod.FN.User.Id: opt.UserId}); u != nil { userName = u.NickName } } var balanceBefore int64 if opt.FlowDir == cointransmod.FlowIn { balanceBefore = balanceAfter - opt.Amount } else { balanceBefore = balanceAfter + opt.Amount } if balanceBefore < 0 { balanceBefore = 0 } remark := opt.Remark if remark == "" { remark = opt.TranType.Desc() } doc := &cointransmod.CoinTrans{ Id: mongos.Lid.CoinTrans.Get(), UserId: opt.UserId, UserName: userName, FlowDir: opt.FlowDir, TranType: opt.TranType, Amount: opt.Amount, BalanceBefore: balanceBefore, BalanceAfter: balanceAfter, OrderNo: opt.OrderNo, RelatedId: opt.RelatedId, Remark: remark, CreatedAt: utils.Now(), } if serr := cointransmod.InsertOneCoinTrans(ctx, doc); serr != nil { log.Error("WriteCoinTrans InsertOneCoinTrans failed", log.Any("userId", opt.UserId), log.Any("tranType", opt.TranType), log.E(serr)) return serr } return nil } // WriteCoinTransByUser 查询用户当前余额后自动写流水(适合已更新余额后调用) func WriteCoinTransByUser(ctx context.Context, opt WriteCoinTransOpt) *srvdef.SrvErr { u, serr := usermod.FindOneUser(ctx, bson.M{usermod.FN.User.Id: opt.UserId}) if serr != nil || u == nil { return srvdef.New(srvdef.ErrNoData, "用户不存在", "") } if opt.UserName == "" { opt.UserName = u.NickName } return WriteCoinTrans(ctx, opt, u.Recharge) } // CoinTransRemark 生成标准备注 func CoinTransRemark(tranType cointransmod.TranType, extra string) string { name := tranType.Desc() if extra != "" { return fmt.Sprintf("%s:%s", name, extra) } return name }