Initial commit
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
package cointransmod
|
||||
|
||||
type TagCoinTrans struct {
|
||||
Id string
|
||||
UserId string
|
||||
UserName string
|
||||
FlowDir string
|
||||
TranType string
|
||||
Amount string
|
||||
BalanceBefore string
|
||||
BalanceAfter string
|
||||
OrderNo string
|
||||
RelatedId string
|
||||
Remark string
|
||||
CreatedAt string
|
||||
}
|
||||
|
||||
var FN struct {
|
||||
CoinTrans TagCoinTrans
|
||||
}
|
||||
var TN struct {
|
||||
CoinTrans string
|
||||
}
|
||||
|
||||
func init() {
|
||||
FN.CoinTrans.Id = "_id"
|
||||
FN.CoinTrans.UserId = "userId"
|
||||
FN.CoinTrans.UserName = "userName"
|
||||
FN.CoinTrans.FlowDir = "flowDir"
|
||||
FN.CoinTrans.TranType = "tranType"
|
||||
FN.CoinTrans.Amount = "amount"
|
||||
FN.CoinTrans.BalanceBefore = "balanceBefore"
|
||||
FN.CoinTrans.BalanceAfter = "balanceAfter"
|
||||
FN.CoinTrans.OrderNo = "orderNo"
|
||||
FN.CoinTrans.RelatedId = "relatedId"
|
||||
FN.CoinTrans.Remark = "remark"
|
||||
FN.CoinTrans.CreatedAt = "createdAt"
|
||||
|
||||
TN.CoinTrans = "coin_trans"
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package cointransmod
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"videoweb/pub/common/log"
|
||||
"videoweb/pub/common/srvdef"
|
||||
"videoweb/pub/mongos"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
var coll *mongos.Collection
|
||||
|
||||
func Init(ctx context.Context) {
|
||||
coll = mongos.Shop.Coll(TN.CoinTrans)
|
||||
initIndex(ctx)
|
||||
}
|
||||
|
||||
func initIndex(ctx context.Context) {
|
||||
indexes := []mongo.IndexModel{
|
||||
// 按用户+时间倒序查流水(最常用)
|
||||
{Keys: bson.D{
|
||||
{Key: FN.CoinTrans.UserId, Value: 1},
|
||||
{Key: FN.CoinTrans.CreatedAt, Value: -1},
|
||||
}},
|
||||
// 按交易类型筛选
|
||||
{Keys: bson.D{{Key: FN.CoinTrans.TranType, Value: 1}}},
|
||||
// 按订单号查(幂等校验)
|
||||
{Keys: bson.D{{Key: FN.CoinTrans.OrderNo, Value: 1}}},
|
||||
}
|
||||
if _, err := coll.CreateIndex(ctx, indexes); err != nil {
|
||||
panic(fmt.Sprintf("(cointransmod:initIndex) Create Index failed! err:%+v:", err))
|
||||
}
|
||||
}
|
||||
|
||||
// InsertOneCoinTrans 写入一条流水记录
|
||||
func InsertOneCoinTrans(ctx context.Context, doc *CoinTrans) *srvdef.SrvErr {
|
||||
if _, err := coll.InsertOne(ctx, doc); err != nil {
|
||||
log.Error("cointransmod:InsertOneCoinTrans failed", log.Any("doc", doc), log.E(err))
|
||||
return srvdef.New(srvdef.ErrDbInsertError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FindManyCoinTrans 分页查询流水列表
|
||||
func FindManyCoinTrans(ctx context.Context, filter bson.M, opts ...*options.FindOptions) (CoinTransList, *srvdef.SrvErr) {
|
||||
var data CoinTransList
|
||||
if err := coll.Find(ctx, &data, filter, opts...); err != nil {
|
||||
log.Warn("cointransmod:FindManyCoinTrans failed", log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// CountCoinTrans 统计流水条数
|
||||
func CountCoinTrans(ctx context.Context, filter bson.M) (int64, *srvdef.SrvErr) {
|
||||
count, err := coll.Count(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("cointransmod:CountCoinTrans failed", log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// StatSyncConsumeList 按 ID 游标增量拉取金币消费流水(统计中心)
|
||||
func StatSyncConsumeList(ctx context.Context, startId int64, size int64) (CoinTransList, error) {
|
||||
opt := (&options.FindOptions{}).SetLimit(size).SetSort(bson.D{{Key: FN.CoinTrans.Id, Value: 1}})
|
||||
filter := bson.M{
|
||||
FN.CoinTrans.Id: bson.M{"$gt": startId},
|
||||
FN.CoinTrans.FlowDir: FlowOut,
|
||||
}
|
||||
list := CoinTransList{}
|
||||
if err := coll.Find(ctx, &list, filter, opt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return list, nil
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package cointransmod
|
||||
|
||||
import "time"
|
||||
|
||||
// FlowDir 收支方向
|
||||
type FlowDir int8
|
||||
|
||||
const (
|
||||
FlowIn FlowDir = 1 // 收入(充值、赠送)
|
||||
FlowOut FlowDir = -1 // 支出(消费、解锁)
|
||||
)
|
||||
|
||||
func (f FlowDir) Desc() string {
|
||||
if f == FlowIn {
|
||||
return "收入"
|
||||
}
|
||||
return "支出"
|
||||
}
|
||||
|
||||
// TranType 交易类型
|
||||
type TranType int32
|
||||
|
||||
const (
|
||||
TranTypeCoinRecharge TranType = 1 // 金币充值(购买金币)
|
||||
TranTypeVipGiftCoin TranType = 2 // 购买会员赠送金币
|
||||
TranTypeDarkAlley TranType = 3 // 历史遗留交易类型(已下线)
|
||||
TranTypeVideoUnlock TranType = 4 // 视频解锁
|
||||
TranTypeAdminAdjust TranType = 5 // 管理员手动调整
|
||||
)
|
||||
|
||||
var TranTypeNameMap = map[TranType]string{
|
||||
TranTypeCoinRecharge: "金币充值",
|
||||
TranTypeVipGiftCoin: "会员赠送",
|
||||
TranTypeDarkAlley: "历史交易",
|
||||
TranTypeVideoUnlock: "视频解锁",
|
||||
TranTypeAdminAdjust: "管理员调整",
|
||||
}
|
||||
|
||||
func (t TranType) Desc() string {
|
||||
if name, ok := TranTypeNameMap[t]; ok {
|
||||
return name
|
||||
}
|
||||
return "未知"
|
||||
}
|
||||
|
||||
// @table: coin_trans
|
||||
type CoinTrans struct {
|
||||
Id int64 `json:"id" bson:"_id"` // 唯一ID
|
||||
UserId int64 `json:"userId" bson:"userId"` // 用户ID
|
||||
UserName string `json:"userName" bson:"userName"` // 用户昵称(快照)
|
||||
FlowDir FlowDir `json:"flowDir" bson:"flowDir"` // 收支方向:1收入 -1支出
|
||||
TranType TranType `json:"tranType" bson:"tranType"` // 交易类型
|
||||
Amount int64 `json:"amount" bson:"amount"` // 本次交易金币数(正整数)
|
||||
BalanceBefore int64 `json:"balanceBefore" bson:"balanceBefore"` // 交易前余额
|
||||
BalanceAfter int64 `json:"balanceAfter" bson:"balanceAfter"` // 交易后余额
|
||||
OrderNo string `json:"orderNo" bson:"orderNo"` // 关联订单号(可为空)
|
||||
RelatedId int64 `json:"relatedId" bson:"relatedId"` // 关联内容ID(视频等,可为空)
|
||||
Remark string `json:"remark" bson:"remark"` // 备注描述
|
||||
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` // 交易时间
|
||||
}
|
||||
|
||||
type CoinTransList []*CoinTrans
|
||||
Reference in New Issue
Block a user