feat: update
This commit is contained in:
505
backend/app/model/users.go
Normal file
505
backend/app/model/users.go
Normal file
@@ -0,0 +1,505 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"quyun/app/requests"
|
||||
"quyun/database/conds"
|
||||
"quyun/database/fields"
|
||||
"quyun/database/table"
|
||||
|
||||
. "github.com/go-jet/jet/v2/postgres"
|
||||
"github.com/go-jet/jet/v2/qrm"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/samber/lo"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func (m *Users) log() *log.Entry {
|
||||
return log.WithField("model", "UsersModel")
|
||||
}
|
||||
|
||||
// GetByID
|
||||
func (m *Users) GetByID(ctx context.Context, id int64) (*Users, error) {
|
||||
tbl := table.Users
|
||||
|
||||
stmt := tbl.
|
||||
SELECT(tbl.AllColumns).
|
||||
WHERE(
|
||||
tbl.ID.EQ(Int64(id)),
|
||||
)
|
||||
m.log().Infof("sql: %s", stmt.DebugSql())
|
||||
|
||||
var user Users
|
||||
err := stmt.QueryContext(ctx, db, &user)
|
||||
if err != nil {
|
||||
m.log().Errorf("error querying user by ID: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &user, nil
|
||||
}
|
||||
|
||||
func (m *Users) Own(ctx context.Context, userID, postID int64) error {
|
||||
tbl := table.UserPosts
|
||||
stmt := tbl.INSERT(tbl.MutableColumns).MODEL(&UserPosts{
|
||||
UserID: userID,
|
||||
PostID: postID,
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
})
|
||||
m.log().Infof("sql: %s", stmt.DebugSql())
|
||||
|
||||
if _, err := stmt.ExecContext(ctx, db); err != nil {
|
||||
m.log().Errorf("error inserting user post: %v", err)
|
||||
return err
|
||||
}
|
||||
m.log().Infof("user post inserted successfully: userID=%d, postID=%d", userID, postID)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// BuildConditionWithKey builds the WHERE clause for user queries
|
||||
func (m *Users) BuildConditionWithKey(key *string) BoolExpression {
|
||||
tbl := table.Users
|
||||
|
||||
cond := tbl.DeletedAt.IS_NULL()
|
||||
|
||||
if key == nil || *key == "" {
|
||||
return cond
|
||||
}
|
||||
|
||||
cond = cond.AND(
|
||||
tbl.Username.LIKE(String("%" + *key + "%")),
|
||||
)
|
||||
|
||||
return cond
|
||||
}
|
||||
|
||||
// countByCondition counts users matching the given condition
|
||||
func (m *Users) countByCondition(ctx context.Context, expr BoolExpression) (int64, error) {
|
||||
var cnt struct {
|
||||
Cnt int64
|
||||
}
|
||||
|
||||
tbl := table.Users
|
||||
stmt := SELECT(COUNT(tbl.ID).AS("cnt")).FROM(tbl).WHERE(expr)
|
||||
m.log().Infof("sql: %s", stmt.DebugSql())
|
||||
|
||||
err := stmt.QueryContext(ctx, db, &cnt)
|
||||
if err != nil {
|
||||
m.log().Errorf("error counting users: %v", err)
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return cnt.Cnt, nil
|
||||
}
|
||||
|
||||
// List returns a paginated list of users
|
||||
func (m *Users) List(ctx context.Context, pagination *requests.Pagination, cond BoolExpression) (*requests.Pager, error) {
|
||||
pagination.Format()
|
||||
|
||||
tbl := table.Users
|
||||
stmt := tbl.
|
||||
SELECT(tbl.AllColumns).
|
||||
WHERE(cond).
|
||||
ORDER_BY(tbl.ID.DESC()).
|
||||
LIMIT(pagination.Limit).
|
||||
OFFSET(pagination.Offset)
|
||||
m.log().Infof("sql: %s", stmt.DebugSql())
|
||||
|
||||
var users []Users = make([]Users, 0)
|
||||
err := stmt.QueryContext(ctx, db, &users)
|
||||
if err != nil {
|
||||
m.log().Errorf("error querying users: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
count, err := m.countByCondition(ctx, cond)
|
||||
if err != nil {
|
||||
m.log().Errorf("error getting user count: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &requests.Pager{
|
||||
Items: users,
|
||||
Total: count,
|
||||
Pagination: *pagination,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Create creates a new user
|
||||
func (m *Users) Create(ctx context.Context, userModel *Users) (*Users, error) {
|
||||
userModel.CreatedAt = time.Now()
|
||||
userModel.UpdatedAt = time.Now()
|
||||
|
||||
tbl := table.Users
|
||||
stmt := tbl.INSERT(tbl.MutableColumns).MODEL(userModel).RETURNING(tbl.AllColumns)
|
||||
m.log().Infof("sql: %s", stmt.DebugSql())
|
||||
|
||||
var createdUser Users
|
||||
err := stmt.QueryContext(ctx, db, &createdUser)
|
||||
if err != nil {
|
||||
m.log().Errorf("error creating user: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
return &createdUser, nil
|
||||
}
|
||||
|
||||
// Update updates an existing user
|
||||
func (m *Users) Update(ctx context.Context, id int64, userModel *Users) (*Users, error) {
|
||||
userModel.UpdatedAt = time.Now()
|
||||
|
||||
tbl := table.Users
|
||||
stmt := tbl.
|
||||
UPDATE(
|
||||
tbl.MutableColumns.Except(
|
||||
tbl.Balance,
|
||||
tbl.CreatedAt,
|
||||
tbl.DeletedAt,
|
||||
),
|
||||
).
|
||||
MODEL(userModel).
|
||||
WHERE(tbl.ID.EQ(Int64(id))).
|
||||
RETURNING(tbl.AllColumns)
|
||||
m.log().Infof("sql: %s", stmt.DebugSql())
|
||||
|
||||
var updatedUser Users
|
||||
if err := stmt.QueryContext(ctx, db, &updatedUser); err != nil {
|
||||
m.log().Errorf("error updating user: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
return &updatedUser, nil
|
||||
}
|
||||
|
||||
// DeleteByID soft deletes a user by ID
|
||||
func (m *Users) DeleteByID(ctx context.Context, id int64) error {
|
||||
tbl := table.Users
|
||||
stmt := tbl.
|
||||
UPDATE(tbl.DeletedAt).
|
||||
SET(TimestampT(time.Now())).
|
||||
WHERE(
|
||||
tbl.ID.EQ(Int64(id)),
|
||||
)
|
||||
m.log().Infof("sql: %s", stmt.DebugSql())
|
||||
|
||||
if _, err := stmt.ExecContext(ctx, db); err != nil {
|
||||
m.log().Errorf("error deleting user: %v", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// PostList returns a paginated list of posts for a user
|
||||
func (m *Users) PostList(ctx context.Context, userId int64, pagination *requests.Pagination, conds ...conds.Cond) (*requests.Pager, error) {
|
||||
pagination.Format()
|
||||
|
||||
tblUserPosts := table.UserPosts
|
||||
|
||||
combineConds := tblUserPosts.UserID.EQ(Int64(userId))
|
||||
for _, c := range conds {
|
||||
combineConds = c(combineConds)
|
||||
}
|
||||
|
||||
tbl := table.Posts
|
||||
stmt := SELECT(tbl.AllColumns).
|
||||
FROM(tbl.
|
||||
RIGHT_JOIN(
|
||||
tblUserPosts,
|
||||
tblUserPosts.PostID.EQ(tbl.ID),
|
||||
),
|
||||
).
|
||||
WHERE(combineConds).
|
||||
ORDER_BY(tblUserPosts.ID.DESC()).
|
||||
LIMIT(pagination.Limit).
|
||||
OFFSET(pagination.Offset)
|
||||
m.log().Infof("sql: %s", stmt.DebugSql())
|
||||
|
||||
var posts []Posts
|
||||
err := stmt.QueryContext(ctx, db, &posts)
|
||||
if err != nil {
|
||||
if errors.Is(err, qrm.ErrNoRows) {
|
||||
return &requests.Pager{
|
||||
Items: nil,
|
||||
Total: 0,
|
||||
Pagination: *pagination,
|
||||
}, nil
|
||||
}
|
||||
m.log().Errorf("error querying posts: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// total count
|
||||
var cnt struct {
|
||||
Cnt int64
|
||||
}
|
||||
|
||||
stmtCnt := tblUserPosts.SELECT(COUNT(tblUserPosts.ID).AS("cnt")).WHERE(tblUserPosts.UserID.EQ(Int64(userId)))
|
||||
m.log().Infof("sql: %s", stmtCnt.DebugSql())
|
||||
|
||||
if err := stmtCnt.QueryContext(ctx, db, &cnt); err != nil {
|
||||
m.log().Errorf("error counting users: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &requests.Pager{
|
||||
Items: posts,
|
||||
Total: cnt.Cnt,
|
||||
Pagination: *pagination,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetUserIDByOpenID
|
||||
func (m *Users) GetUserByOpenID(ctx context.Context, openID string) (*Users, error) {
|
||||
tbl := table.Users
|
||||
|
||||
stmt := tbl.
|
||||
SELECT(tbl.AllColumns).
|
||||
WHERE(
|
||||
tbl.OpenID.EQ(String(openID)),
|
||||
)
|
||||
m.log().Infof("sql: %s", stmt.DebugSql())
|
||||
|
||||
var user Users
|
||||
if err := stmt.QueryContext(ctx, db, &user); err != nil {
|
||||
m.log().Errorf("error querying user by OpenID: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &user, nil
|
||||
}
|
||||
|
||||
// GetUserByOpenIDOrCreate
|
||||
func (m *Users) GetUserByOpenIDOrCreate(ctx context.Context, openID string, userModel *Users) (*Users, error) {
|
||||
user, err := m.GetUserByOpenID(ctx, openID)
|
||||
if err != nil {
|
||||
if errors.Is(err, qrm.ErrNoRows) {
|
||||
user, err = m.Create(ctx, userModel)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to create user")
|
||||
}
|
||||
} else {
|
||||
return nil, errors.Wrap(err, "failed to get user")
|
||||
}
|
||||
} else {
|
||||
userModel.OpenID = user.OpenID
|
||||
if !(user.Username == "" || user.Username == "-" || user.Username == "暂未设置昵称") {
|
||||
userModel.Username = user.Username
|
||||
userModel.Avatar = user.Avatar
|
||||
}
|
||||
user, err = m.Update(ctx, user.ID, userModel)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to update user")
|
||||
}
|
||||
}
|
||||
return user, nil
|
||||
}
|
||||
|
||||
// GetUsersMapByIDs
|
||||
func (m *Users) GetUsersMapByIDs(ctx context.Context, ids []int64) (map[int64]Users, error) {
|
||||
if len(ids) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
tbl := table.Users
|
||||
stmt := tbl.
|
||||
SELECT(tbl.AllColumns).
|
||||
WHERE(
|
||||
tbl.ID.IN(lo.Map(ids, func(id int64, _ int) Expression { return Int64(id) })...),
|
||||
)
|
||||
|
||||
m.log().Infof("sql: %s", stmt.DebugSql())
|
||||
|
||||
var users []Users = make([]Users, 0)
|
||||
err := stmt.QueryContext(ctx, db, &users)
|
||||
if err != nil {
|
||||
m.log().Errorf("error querying users: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return lo.SliceToMap(users, func(item Users) (int64, Users) {
|
||||
return item.ID, item
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (m *Users) BatchCheckHasBought(ctx context.Context, userID int64, postIDs []int64) (map[int64]bool, error) {
|
||||
tbl := table.UserPosts
|
||||
stmt := tbl.SELECT(tbl.PostID.AS("post_id")).WHERE(
|
||||
tbl.UserID.EQ(Int64(userID)).AND(
|
||||
tbl.PostID.IN(lo.Map(postIDs, func(id int64, _ int) Expression { return Int64(id) })...),
|
||||
),
|
||||
)
|
||||
|
||||
var userPosts []struct {
|
||||
PostID int64
|
||||
}
|
||||
if err := stmt.QueryContext(ctx, db, &userPosts); err != nil {
|
||||
m.log().Errorf("error querying user posts: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := make(map[int64]bool)
|
||||
for _, post := range userPosts {
|
||||
result[post.PostID] = true
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// HasBought
|
||||
func (m *Users) HasBought(ctx context.Context, userID, postID int64) (bool, error) {
|
||||
tbl := table.UserPosts
|
||||
stmt := tbl.
|
||||
SELECT(tbl.ID).
|
||||
WHERE(
|
||||
tbl.UserID.EQ(Int64(userID)).AND(
|
||||
tbl.PostID.EQ(Int64(postID)),
|
||||
),
|
||||
)
|
||||
|
||||
m.log().Infof("sql: %s", stmt.DebugSql())
|
||||
|
||||
var userPost UserPosts
|
||||
if err := stmt.QueryContext(ctx, db, &userPost); err != nil {
|
||||
if errors.Is(err, qrm.ErrNoRows) {
|
||||
return false, nil
|
||||
}
|
||||
m.log().Errorf("error querying user post: %v", err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
return userPost.ID > 0, nil
|
||||
}
|
||||
|
||||
// Count
|
||||
func (m *Users) Count(ctx context.Context, cond BoolExpression) (int64, error) {
|
||||
tbl := table.Users
|
||||
stmt := tbl.
|
||||
SELECT(COUNT(tbl.ID).AS("cnt")).
|
||||
WHERE(cond)
|
||||
|
||||
m.log().Infof("sql: %s", stmt.DebugSql())
|
||||
|
||||
var cnt struct {
|
||||
Cnt int64
|
||||
}
|
||||
|
||||
if err := stmt.QueryContext(ctx, db, &cnt); err != nil {
|
||||
m.log().Errorf("error counting users: %v", err)
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return cnt.Cnt, nil
|
||||
}
|
||||
|
||||
// UpdateUsername
|
||||
func (m *Users) UpdateUsername(ctx context.Context, id int64, username string) error {
|
||||
tbl := table.Users
|
||||
stmt := tbl.
|
||||
UPDATE(tbl.Username).
|
||||
SET(String(username)).
|
||||
WHERE(
|
||||
tbl.ID.EQ(Int64(id)),
|
||||
)
|
||||
m.log().Infof("sql: %s", stmt.DebugSql())
|
||||
|
||||
if _, err := stmt.ExecContext(ctx, db); err != nil {
|
||||
m.log().Errorf("error updating username: %v", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateUserToken
|
||||
func (m *Users) UpdateUserToken(ctx context.Context, id int64, token fields.UserAuthToken) error {
|
||||
tbl := table.Users
|
||||
stmt := tbl.
|
||||
UPDATE(tbl.AuthToken).
|
||||
SET(fields.ToJson(token)).
|
||||
WHERE(
|
||||
tbl.ID.EQ(Int64(id)),
|
||||
)
|
||||
m.log().Infof("sql: %s", stmt.DebugSql())
|
||||
|
||||
if _, err := stmt.ExecContext(ctx, db); err != nil {
|
||||
m.log().Errorf("error updating user token: %v", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// BuyPosts
|
||||
func (m *Users) BuyPosts(ctx context.Context, userID, postID, price int64) error {
|
||||
tbl := table.UserPosts
|
||||
stmt := tbl.
|
||||
INSERT(tbl.MutableColumns).
|
||||
MODEL(&UserPosts{
|
||||
UserID: userID,
|
||||
PostID: postID,
|
||||
Price: price,
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
})
|
||||
|
||||
m.log().Infof("sql: %s", stmt.DebugSql())
|
||||
|
||||
if _, err := stmt.ExecContext(ctx, db); err != nil {
|
||||
m.log().Errorf("error inserting user post: %v", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Users) RevokePosts(ctx context.Context, userID, postID int64) error {
|
||||
tbl := table.UserPosts
|
||||
stmt := tbl.
|
||||
DELETE().
|
||||
WHERE(
|
||||
tbl.UserID.EQ(Int64(userID)).AND(
|
||||
tbl.PostID.EQ(Int64(postID)),
|
||||
),
|
||||
)
|
||||
m.log().Infof("sql: %s", stmt.DebugSql())
|
||||
|
||||
if _, err := stmt.ExecContext(ctx, db); err != nil {
|
||||
m.log().Errorf("error revoking user post: %v", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetBalance
|
||||
func (m *Users) SetBalance(ctx context.Context, id, balance int64) error {
|
||||
tbl := table.Users
|
||||
stmt := tbl.
|
||||
UPDATE(tbl.Balance).
|
||||
SET(Int64(balance)).
|
||||
WHERE(
|
||||
tbl.ID.EQ(Int64(id)),
|
||||
)
|
||||
m.log().Infof("sql: %s", stmt.DebugSql())
|
||||
|
||||
if _, err := stmt.ExecContext(ctx, db); err != nil {
|
||||
m.log().Errorf("error updating user balance: %v", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddBalance adds the given amount to the user's balance
|
||||
func (m *Users) AddBalance(ctx context.Context, id, amount int64) error {
|
||||
tbl := table.Users
|
||||
stmt := tbl.
|
||||
UPDATE(tbl.Balance).
|
||||
SET(tbl.Balance.ADD(Int64(amount))).
|
||||
WHERE(
|
||||
tbl.ID.EQ(Int64(id)),
|
||||
)
|
||||
m.log().Infof("sql: %s", stmt.DebugSql())
|
||||
|
||||
if _, err := stmt.ExecContext(ctx, db); err != nil {
|
||||
m.log().Errorf("error updating user balance: %v", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user