package services import ( "context" "quyun/v2/app/requests" "quyun/v2/database/models" "github.com/pkg/errors" "github.com/samber/lo" "go.ipao.vip/gen" ) // @provider type users struct{} // List returns a paginated list of users func (m *users) List( ctx context.Context, pagination *requests.Pagination, conds ...gen.Condition, ) (*requests.Pager, error) { pagination.Format() _, query := models.UserQuery.QueryContext(ctx) items, cnt, err := query.Where(conds...).FindByPage(int(pagination.Offset()), int(pagination.Limit)) if err != nil { return nil, errors.Wrap(err, "query users error") } return &requests.Pager{ Items: items, Total: cnt, Pagination: *pagination, }, nil } // PostList returns a paginated list of posts for a user func (m *users) PostList( ctx context.Context, userId int64, pagination *requests.Pagination, conds ...gen.Condition, ) (*requests.Pager, error) { pagination.Format() // stmt := SELECT(tbl.AllColumns). // FROM(tbl. // RIGHT_JOIN( // tblUserPosts, // tblUserPosts.PostID.EQ(tbl.ID), // ), // ). // WHERE(CondTrue(cond...)). // 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 return nil, nil } // GetUsersMapByIDs func (m *users) GetUsersMapByIDs(ctx context.Context, ids []int64) (map[int64]*models.User, error) { if len(ids) == 0 { return nil, nil } tbl, query := models.UserQuery.QueryContext(ctx) items, err := query.Where(tbl.ID.In(ids...)).Find() if err != nil { return nil, errors.Wrapf(err, "failed to get users by ids:%v", ids) } return lo.KeyBy(items, func(item *models.User) int64 { return item.ID }), nil } // BatchCheckHasBought checks if the user has bought the given post IDs func (m *users) BatchCheckHasBought(ctx context.Context, userId int64, postIDs []int64) (map[int64]bool, error) { tbl, query := models.UserPostQuery.QueryContext(ctx) userPosts, err := query. Where( tbl.UserID.Eq(userId), tbl.PostID.In(postIDs...), ). Find() if err != nil { return nil, errors.Wrapf(err, "check user has bought failed, user_id: %d, post_ids: %+v", userId, postIDs) } result := make(map[int64]bool) for _, postID := range postIDs { result[postID] = false } 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, query := models.UserPostQuery.QueryContext(ctx) cnt, err := query. Where( tbl.UserID.Eq(userID), tbl.PostID.Eq(postID), ). Count() if err != nil { return false, errors.Wrap(err, "failed to check user bought") } return cnt > 0, nil } // SetUsername func (m *users) SetUsername(ctx context.Context, userID int64, username string) error { tbl, query := models.UserQuery.QueryContext(ctx) _, err := query. Where( tbl.ID.Eq(userID), ). Update(tbl.Username, username) if err != nil { return err } return nil } // BuyPosts func (m *users) BuyPosts(ctx context.Context, userID, postID, price int64) error { model := &models.UserPost{UserID: userID, PostID: postID, Price: price} return model.Create(ctx) } // RevokePosts func (m *users) RevokeUserPosts(ctx context.Context, userID, postID int64) error { tbl, query := models.UserPostQuery.QueryContext(ctx) _, err := query.Where( tbl.UserID.Eq(userID), tbl.PostID.Eq(postID), ).Delete() return err } // FindByID func (m *users) FindByID(ctx context.Context, userID int64) (*models.User, error) { tbl, query := models.UserQuery.QueryContext(ctx) user, err := query.Where(tbl.ID.Eq(userID)).First() if err != nil { return nil, errors.Wrapf(err, "find by id failed, id: %d", userID) } return user, nil } // SetBalance func (m *users) SetBalance(ctx context.Context, userID, balance int64) error { tbl, query := models.UserQuery.QueryContext(ctx) _, err := query.Where(tbl.ID.Eq(userID)).Update(tbl.Balance, balance) return err } // AddBalance adds the given amount to the user's balance func (m *users) AddBalance(ctx context.Context, userID, amount int64) error { tbl, query := models.UserQuery.QueryContext(ctx) _, err := query.Where(tbl.ID.Eq(userID)).Inc(tbl.Balance, amount) return err } // Desc desc the given amount to the user's balance func (m *users) DescBalance(ctx context.Context, userID, amount int64) error { user, err := m.FindByID(ctx, userID) if err != nil { return err } if user.Balance < amount { return errors.New("balance not enough") } tbl, query := models.UserQuery.QueryContext(ctx) _, err = query.Where(tbl.ID.Eq(userID)).Inc(tbl.Balance, -amount) return err } // Count func (m *users) Count(ctx context.Context, conds ...gen.Condition) (int64, error) { _, query := models.UserQuery.QueryContext(ctx) if len(conds) > 0 { query = query.Where(conds...) } return query.Count() }