package model import ( "context" "fmt" "git.noahlan.cn/northlan/ntools-go/gorm-zero/gormc" "github.com/pkg/errors" "github.com/zeromicro/go-zero/core/logx" "gorm.io/gorm" "live-service/common/nerr" ) var _ UserIntegralModel = (*customUserIntegralModel)(nil) type ( // UserIntegralModel is an interface to be customized, add more methods here, // and implement the added methods in customUserIntegralModel. UserIntegralModel interface { userIntegralModel Transact(ctx context.Context, tx *gorm.DB, fn func(tx *gorm.DB) error) error InsertTx(ctx context.Context, tx *gorm.DB, data *UserIntegral) error UpdateIntegralTx(ctx context.Context, tx *gorm.DB, userId, addon int64) error FindIntegral(ctx context.Context, tx *gorm.DB, userId int64) (int64, error) // ChangeIntegral 用户积分变动 ChangeIntegral(ctx context.Context, tx *gorm.DB, userId int64, change int64) (int64, error) } customUserIntegralModel struct { *defaultUserIntegralModel } ) // NewUserIntegralModel returns a model for the database table. func NewUserIntegralModel(conn *gorm.DB) UserIntegralModel { return &customUserIntegralModel{ defaultUserIntegralModel: newUserIntegralModel(conn), } } func (m *customUserIntegralModel) Transact(ctx context.Context, tx *gorm.DB, fn func(tx *gorm.DB) error) error { return withTx(ctx, m.conn, tx).Transaction(fn) } func (m *customUserIntegralModel) InsertTx(ctx context.Context, tx *gorm.DB, data *UserIntegral) error { err := withTx(ctx, m.conn, tx).Create(&data).Error return err } func (m *customUserIntegralModel) UpdateIntegralTx(ctx context.Context, tx *gorm.DB, userId, integral int64) error { if integral < 0 { return errors.New("无法将积分更新至负数") } db := withTx(ctx, m.conn, tx) result := db.Table(m.table). Where("`user_id` = ?", userId). Update("`integral`", integral) if result.Error != nil { return result.Error } // TODO 这里得处理一下 if result.RowsAffected == 0 { logx.Statf("更新积分影响行数为0, user_id: %d, integral: %d", userId, integral) return nil } return nil } func (m *customUserIntegralModel) FindIntegral(ctx context.Context, tx *gorm.DB, userId int64) (int64, error) { var resp int64 err := withTx(ctx, m.conn, tx).Table(m.table). Select(fmt.Sprintf("%s.integral", m.table)). Where("`user_id` = ?", userId).Take(&resp).Error switch err { case nil: return resp, nil case gormc.ErrNotFound: return 0, ErrNotFound default: return 0, err } } func (m *customUserIntegralModel) ChangeIntegral(ctx context.Context, tx *gorm.DB, userId int64, change int64) (int64, error) { resp := change err := withTx(ctx, m.conn, tx).Transaction(func(tx *gorm.DB) error { integral, err := m.FindIntegral(ctx, tx, userId) if err != nil { if errors.Is(err, ErrNotFound) { if change < 0 { return nerr.NewWithCode(nerr.UserIntegralNotEnoughError) } // 用户积分记录不存在,进行插入 if err = m.InsertTx(ctx, tx, &UserIntegral{ UserId: userId, Integral: change, }); err != nil { return errors.Wrap(err, "插入用户积分失败") } return nil } else { return errors.Wrap(err, "获取当前用户积分失败") } } if integral+change < 0 { return errors.New("用户积分不足") } if err = m.UpdateIntegralTx(ctx, tx, userId, integral+change); err != nil { return errors.Wrap(err, "更新用户积分失败") } resp = integral + change return nil }) return resp, err }