From b1da15e8dbc15460d7fe05abcd27cc6d79d3eeac Mon Sep 17 00:00:00 2001 From: NorthLan <6995syu@163.com> Date: Thu, 26 May 2022 21:09:20 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E7=94=A8=E6=88=B7=E5=BC=B9=E5=B8=81?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E6=A8=A1=E5=9E=8B.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/user_center/model/user_coin_model.go | 85 ++++++++++++++++++ app/user_center/model/user_coin_model_gen.go | 90 ++++++++++++++++++++ 2 files changed, 175 insertions(+) create mode 100644 app/user_center/model/user_coin_model.go create mode 100644 app/user_center/model/user_coin_model_gen.go diff --git a/app/user_center/model/user_coin_model.go b/app/user_center/model/user_coin_model.go new file mode 100644 index 0000000..e72a141 --- /dev/null +++ b/app/user_center/model/user_coin_model.go @@ -0,0 +1,85 @@ +package model + +import ( + "context" + "git.noahlan.cn/northlan/ntools-go/gorm-zero/gormx" + "github.com/pkg/errors" + "gorm.io/gorm" + "gorm.io/plugin/optimisticlock" + "live-service/common/nerr" +) + +var _ UserCoinModel = (*customUserCoinModel)(nil) + +type ( + // UserCoinModel is an interface to be customized, add more methods here, + // and implement the added methods in customUserCoinModel. + UserCoinModel interface { + userCoinModel + UpdateCoin(ctx context.Context, tx *gorm.DB, integral *UserCoin) error + // ChangeCoin 用户弹币变动 + ChangeCoin(ctx context.Context, tx *gorm.DB, userId int64, change int64) (int64, error) + } + + customUserCoinModel struct { + *defaultUserCoinModel + } +) + +// NewUserCoinModel returns a model for the database table. +func NewUserCoinModel(conn *gorm.DB) UserCoinModel { + return &customUserCoinModel{ + defaultUserCoinModel: newUserCoinModel(conn), + } +} + +func (m *customUserCoinModel) UpdateCoin(ctx context.Context, tx *gorm.DB, coin *UserCoin) error { + if coin.Coin < 0 { + return errors.New("无法将弹币更新至负数") + } + db := gormx.WithTx(ctx, m.DB, tx) + + result := db.Model(&coin).Updates(&UserCoin{Coin: coin.Coin, Version: optimisticlock.Version{Int64: 1}}) + return gormx.WrapUpdateErr(result.Error, result.RowsAffected) +} + +func (m *customUserCoinModel) ChangeCoin(ctx context.Context, tx *gorm.DB, userId int64, change int64) (int64, error) { + resp := change + err := gormx.WithRetry(VersionRetryCount, func() error { + return m.Transact(tx, func(tx *gorm.DB) error { + data, err := m.FindOne(ctx, tx, userId) + if err != nil { + if errors.Is(err, ErrNotFound) { + if change < 0 { + return nerr.NewError(nerr.UserCoinNotEnoughErr, "用户弹币不足") + } + // 用户积分记录不存在,进行插入 + if err = m.Insert(ctx, tx, &UserCoin{ + UserId: userId, + Coin: change, + }); err != nil { + return nerr.NewError(nerr.NewUserCoinErr, "新建用户弹币记录失败") + } + return nil + } else { + return nerr.NewError(nerr.GetUserCoinErr, "获取当前用户弹币失败") + } + } + if data.Coin+change < 0 { + return nerr.NewError(nerr.UserCoinNotEnoughErr, "用户弹币不足") + } + data.Coin += change + if err = m.UpdateCoin(ctx, tx, data); err != nil { + if errors.Is(err, gormx.ErrRowsAffectedZero) { + return err + } + return nerr.NewError(nerr.UpdateUserCoinErr, "更新用户弹币失败") + } + resp = data.Coin + return nil + }) + }, func(err error) bool { + return errors.Is(err, gormx.ErrRowsAffectedZero) + }) + return resp, err +} diff --git a/app/user_center/model/user_coin_model_gen.go b/app/user_center/model/user_coin_model_gen.go new file mode 100644 index 0000000..5b7fec8 --- /dev/null +++ b/app/user_center/model/user_coin_model_gen.go @@ -0,0 +1,90 @@ +// Code generated by goctl. DO NOT EDIT! + +package model + +import ( + "context" + "gorm.io/plugin/optimisticlock" + "strings" + "time" + + "git.noahlan.cn/northlan/ntools-go/gorm-zero/gormx" + "github.com/zeromicro/go-zero/core/stores/builder" + "github.com/zeromicro/go-zero/core/stringx" + "gorm.io/gorm" +) + +var ( + userCoinFieldNames = builder.RawFieldNames(&UserCoin{}) + userCoinRows = strings.Join(userCoinFieldNames, ",") + userCoinRowsExpectAutoSet = strings.Join(stringx.Remove(userCoinFieldNames, "`create_time`", "`update_time`"), ",") + userCoinRowsWithPlaceHolder = strings.Join(stringx.Remove(userCoinFieldNames, "`user_id`", "`create_time`", "`update_time`"), "=?,") + "=?" +) + +type ( + userCoinModel interface { + gormx.TxModel + Insert(ctx context.Context, tx *gorm.DB, data *UserCoin) error + FindOne(ctx context.Context, tx *gorm.DB, userId int64) (*UserCoin, error) + Update(ctx context.Context, tx *gorm.DB, data *UserCoin) error + Delete(ctx context.Context, tx *gorm.DB, userId int64) error + } + + defaultUserCoinModel struct { + gormx.GormConn + table string + } + + UserCoin struct { + UserId int64 `gorm:"column:user_id;primaryKey"` // 用户ID + Coin int64 `gorm:"column:coin"` // 弹币 1:100 + Version optimisticlock.Version `gorm:"column:version"` // 乐观锁 + CreateTime time.Time `gorm:"column:create_time;default:null"` // 创建时间 + UpdateTime time.Time `gorm:"column:update_time;default:null"` // 更新时间 + } +) + +var UserCoinTableName = "`user_coin`" + +func newUserCoinModel(conn *gorm.DB) *defaultUserCoinModel { + return &defaultUserCoinModel{ + GormConn: gormx.NewConn(conn), + table: UserCoinTableName, + } +} + +func (m *defaultUserCoinModel) Insert(ctx context.Context, tx *gorm.DB, data *UserCoin) error { + err := gormx.WithTx(ctx, m.DB, tx).Create(&data).Error + return err +} + +func (m *defaultUserCoinModel) FindOne(ctx context.Context, tx *gorm.DB, userId int64) (*UserCoin, error) { + var resp UserCoin + err := gormx.WithTx(ctx, m.DB, tx).Model(&UserCoin{}).Where("`user_id` = ?", userId).Take(&resp).Error + result, err := gormx.WrapSelectResult(err, &resp) + if err != nil { + return nil, err + } + return result.(*UserCoin), nil +} + +func (m *defaultUserCoinModel) Update(ctx context.Context, tx *gorm.DB, data *UserCoin) error { + + result := gormx.WithTx(ctx, m.DB, tx).Save(data) + return gormx.WrapUpdateErr(result.Error, result.RowsAffected) + +} + +func (m *defaultUserCoinModel) Delete(ctx context.Context, tx *gorm.DB, userId int64) error { + err := gormx.WithTx(ctx, m.DB, tx).Delete(&UserCoin{}, userId).Error + + return err +} + +func (m *defaultUserCoinModel) tableName() string { + return m.table +} + +func (UserCoin) TableName() string { + return UserCoinTableName +}