forked from ebhomengo/niki
EDIT | Add & Use General Pagination Func
This commit is contained in:
parent
bc24bcc686
commit
44bfde3c65
|
|
@ -5,66 +5,103 @@ import (
|
|||
|
||||
"git.gocasts.ir/ebhomengo/niki/domain/wallet/entity"
|
||||
"git.gocasts.ir/ebhomengo/niki/pkg/database/postgres"
|
||||
errmsg "git.gocasts.ir/ebhomengo/niki/pkg/err_msg"
|
||||
richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error"
|
||||
)
|
||||
|
||||
func (db *DB) GetTransactionListByUserID(ctx context.Context, userID uint64, dbPagination postgres.DBPagination) ([]entity.Transaction, int64, error) {
|
||||
const op = richerror.Op("Wallet.repo.GetTransactionListByUserID")
|
||||
|
||||
query := `SELECT * FROM Transactions WHERE user_id = $1 AND transaction_timestamp < $2 ORDER BY transaction_id DESC LIMIT $3`
|
||||
countQuery := "SELECT COUNT(*) FROM transactions WHERE user_id = $1"
|
||||
fetchQuery := `SELECT * FROM Transactions WHERE user_id = $1 ORDER BY created_at DESC LIMIT $2 OFFSET $3`
|
||||
|
||||
stmt, StErr := db.conn.PrepareStatement(ctx, postgres.StatementKeyAWalletGetTransactionHistory, query)
|
||||
countQueryStmt := postgres.StatementKeyAWalletGetTotalCountTransactionHistory
|
||||
fetchQueryStmt := postgres.StatementKeyAWalletGetTransactionHistory
|
||||
|
||||
if StErr != nil {
|
||||
PageOffset := (dbPagination.PageNumber - 1) * dbPagination.PageSize // offset
|
||||
|
||||
return nil, 0, richerror.New(op).WithErr(StErr).WithKind(richerror.KindUnexpected).WithMessage(errmsg.ErrorMsgFailedQuery)
|
||||
PageSize := dbPagination.PageSize //limit
|
||||
|
||||
}
|
||||
|
||||
totalRetrieveRecord := (dbPagination.MaxNextPages-1)*dbPagination.PageSize + 1
|
||||
|
||||
lastTimeStamp := dbPagination.LastTimeStamp
|
||||
|
||||
queryRows, err := stmt.QueryContext(ctx, userID, lastTimeStamp, totalRetrieveRecord)
|
||||
countParams := []any{userID} // $1
|
||||
fetchParams := []any{userID, PageSize, PageOffset} // $1 , $2 , $3
|
||||
//
|
||||
//
|
||||
/////////////////////////// with generic pagination package
|
||||
|
||||
transactionsList, totalItemsCount, err := postgres.PageNumberPagination[entity.Transaction](ctx, countQuery, fetchQuery,
|
||||
db.conn, countQueryStmt, fetchQueryStmt, op,
|
||||
scanTransaction, countParams, fetchParams,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, 0, richerror.New(op).WithErr(StErr).WithKind(richerror.KindUnexpected).WithMessage(errmsg.ErrorMsgFailedQuery)
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
defer queryRows.Close()
|
||||
return transactionsList, totalItemsCount, nil
|
||||
|
||||
var transactions []entity.Transaction
|
||||
/////////////////////////// normal
|
||||
|
||||
var lenCounter int64
|
||||
|
||||
for queryRows.Next() {
|
||||
lenCounter++
|
||||
|
||||
if lenCounter < dbPagination.PageSize+1 {
|
||||
transaction, err := scanTransaction(queryRows)
|
||||
|
||||
if err != nil {
|
||||
return nil, 0, richerror.New(op).WithErr(err).WithKind(richerror.KindUnexpected).WithMessage(errmsg.ErrorMsgCantScanQueryResult)
|
||||
}
|
||||
|
||||
transactions = append(transactions, transaction)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if qErr := queryRows.Err(); qErr != nil {
|
||||
|
||||
return nil, 0, richerror.New(op).WithErr(qErr).WithKind(richerror.KindUnexpected).WithMessage(errmsg.ErrorMsgCantScanQueryResult)
|
||||
}
|
||||
|
||||
return transactions, lenCounter, nil
|
||||
//var totalCount int64
|
||||
//
|
||||
//countStmt, CountStErr := db.conn.PrepareStatement(ctx, countQueryStmt, countQuery)
|
||||
//
|
||||
//if CountStErr != nil {
|
||||
//
|
||||
// return nil, 0, richerror.New(op).WithErr(CountStErr).WithKind(richerror.KindUnexpected).WithMessage(errmsg.ErrorMsgFailedQuery)
|
||||
//
|
||||
//}
|
||||
//countErr := countStmt.QueryRowContext(ctx, userID).Scan(&totalCount)
|
||||
//
|
||||
//if countErr != nil {
|
||||
// return nil, 0, richerror.New(op).WithErr(CountStErr).WithKind(richerror.KindUnexpected).WithMessage(errmsg.ErrorMsgFailedQuery)
|
||||
//
|
||||
//}
|
||||
//
|
||||
////// get records
|
||||
//
|
||||
//stmt, StErr := db.conn.PrepareStatement(ctx, fetchQueryStmt, fetchQuery)
|
||||
//
|
||||
//if StErr != nil {
|
||||
//
|
||||
// return nil, 0, richerror.New(op).WithErr(StErr).WithKind(richerror.KindUnexpected).WithMessage(errmsg.ErrorMsgFailedQuery)
|
||||
//
|
||||
//}
|
||||
//
|
||||
//offset := (dbPagination.PageNumber - 1) * dbPagination.PageSize
|
||||
//
|
||||
//limit := dbPagination.PageSize
|
||||
//
|
||||
//queryRows, qrErr := stmt.QueryContext(ctx, userID, limit, offset)
|
||||
//
|
||||
//if qrErr != nil {
|
||||
// return nil, 0, richerror.New(op).WithErr(qrErr).WithKind(richerror.KindUnexpected).WithMessage(errmsg.ErrorMsgFailedQuery)
|
||||
//}
|
||||
//
|
||||
//defer queryRows.Close()
|
||||
//
|
||||
//var transactions []entity.Transaction
|
||||
//
|
||||
//for queryRows.Next() {
|
||||
//
|
||||
// transaction, err := scanTransaction(queryRows)
|
||||
//
|
||||
// if err != nil {
|
||||
// return nil, 0, richerror.New(op).WithErr(err).WithKind(richerror.KindUnexpected).WithMessage(errmsg.ErrorMsgCantScanQueryResult)
|
||||
// }
|
||||
//
|
||||
// transactions = append(transactions, transaction)
|
||||
//
|
||||
//}
|
||||
//
|
||||
//if qErr := queryRows.Err(); qErr != nil {
|
||||
//
|
||||
// return nil, 0, richerror.New(op).WithErr(qErr).WithKind(richerror.KindUnexpected).WithMessage(errmsg.ErrorMsgCantScanQueryResult)
|
||||
//}
|
||||
//
|
||||
//return transactions, totalCount, nil
|
||||
|
||||
}
|
||||
|
||||
func scanTransaction(scanner postgres.Scanner) (transaction entity.Transaction, err error) {
|
||||
err = scanner.Scan(&transaction.UserID, &transaction.Currency, &transaction.Amount, &transaction.ActionType, &transaction.Timestamp)
|
||||
err = scanner.Scan(&transaction.UserID, &transaction.Currency, &transaction.Amount, &transaction.ActionType, &transaction.Timestamp, &transaction.CreatedAt)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,8 +14,7 @@ type Repository interface {
|
|||
}
|
||||
|
||||
type Config struct {
|
||||
PageSize int64 `koanf:"page_size"`
|
||||
MaxNextPages int64 `koanf:"max_next_pages"`
|
||||
PageSize int64 `koanf:"page_size"`
|
||||
}
|
||||
|
||||
type Service struct {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package service
|
|||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"git.gocasts.ir/ebhomengo/niki/domain/wallet/entity"
|
||||
"git.gocasts.ir/ebhomengo/niki/domain/wallet/param"
|
||||
|
|
@ -12,30 +11,24 @@ import (
|
|||
|
||||
func (s Service) GetUserTransactionHistory(ctx context.Context, request param.TransactionRequest) (param.TransactionResponse, error) {
|
||||
const op = richerror.Op("wallet.service.GetUserTransactionHistory")
|
||||
lastTimeStamp := request.Pagination.LastTimeStamp
|
||||
if lastTimeStamp.IsZero() {
|
||||
lastTimeStamp = time.Now()
|
||||
}
|
||||
|
||||
dbPagination := postgres.DBPagination{
|
||||
LastTimeStamp: lastTimeStamp,
|
||||
PageNumber: request.Pagination.PageNumber,
|
||||
MaxNextPages: s.cfg.MaxNextPages,
|
||||
PageSize: s.cfg.PageSize,
|
||||
PageNumber: request.Pagination.PageNumber,
|
||||
PageSize: s.cfg.PageSize,
|
||||
}
|
||||
|
||||
transactionList, listLen, err := s.repo.GetTransactionListByUserID(ctx, request.UserID, dbPagination)
|
||||
|
||||
showableNextPagesNum := postgres.ComputeNextPages(listLen, s.cfg.PageSize, s.cfg.MaxNextPages)
|
||||
transactionList, totalCount, err := s.repo.GetTransactionListByUserID(ctx, request.UserID, dbPagination)
|
||||
|
||||
if err != nil {
|
||||
return param.TransactionResponse{}, richerror.New(op).WithErr(err)
|
||||
}
|
||||
|
||||
totalPages := (totalCount + s.cfg.PageSize - 1) / s.cfg.PageSize
|
||||
|
||||
paginationInfo := postgres.ResponsePagination{
|
||||
PageNumber: request.Pagination.PageNumber,
|
||||
PageSize: s.cfg.PageSize,
|
||||
ShowableNextPagesNum: showableNextPagesNum,
|
||||
PageNumber: request.Pagination.PageNumber,
|
||||
PageSize: s.cfg.PageSize,
|
||||
TotalPages: totalPages,
|
||||
}
|
||||
|
||||
return param.TransactionResponse{
|
||||
|
|
|
|||
|
|
@ -1,35 +1,85 @@
|
|||
package postgres
|
||||
|
||||
import "time"
|
||||
import (
|
||||
"context"
|
||||
|
||||
errmsg "git.gocasts.ir/ebhomengo/niki/pkg/err_msg"
|
||||
richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error"
|
||||
)
|
||||
|
||||
// page number pagination
|
||||
|
||||
type RequestPagination struct {
|
||||
PageNumber int64 `json:"page_number"`
|
||||
LastTimeStamp time.Time `json:"last_time_stamp"`
|
||||
PageNumber int64 `json:"page_number"`
|
||||
}
|
||||
|
||||
type ResponsePagination struct {
|
||||
PageNumber int64 `json:"page_number"`
|
||||
PageSize int64 `json:"page_size"`
|
||||
ShowableNextPagesNum int64 `json:"showable_next_pages_num"`
|
||||
PageNumber int64 `json:"page_number"`
|
||||
PageSize int64 `json:"page_size"`
|
||||
TotalPages int64 `json:"total_pages"`
|
||||
}
|
||||
|
||||
type DBPagination struct {
|
||||
LastTimeStamp time.Time
|
||||
PageNumber int64
|
||||
MaxNextPages int64
|
||||
PageSize int64
|
||||
PageNumber int64
|
||||
PageSize int64
|
||||
}
|
||||
|
||||
func ComputeNextPages(listLen int64, pageSize int64, maxNextPages int64) int64 {
|
||||
type ScannerFunc[T any] func(scanner Scanner) (T, error)
|
||||
|
||||
pages := float64(listLen) / float64(pageSize)
|
||||
func PageNumberPagination[T any](ctx context.Context, countQuery string, fetchQuery string, conn *DB, countQueryStmt statementKey, fetchQueryStmt statementKey, op richerror.Op, scanner ScannerFunc[T], countParams []any, fetchParams []any) ([]T, int64, error) {
|
||||
|
||||
var totalCount int64
|
||||
|
||||
countStmt, CountStErr := conn.PrepareStatement(ctx, countQueryStmt, countQuery)
|
||||
|
||||
if CountStErr != nil {
|
||||
|
||||
return nil, 0, richerror.New(op).WithErr(CountStErr).WithKind(richerror.KindUnexpected).WithMessage(errmsg.ErrorMsgFailedQuery)
|
||||
|
||||
}
|
||||
countErr := countStmt.QueryRowContext(ctx, countParams...).Scan(&totalCount)
|
||||
|
||||
if countErr != nil {
|
||||
return nil, 0, richerror.New(op).WithErr(countErr).WithKind(richerror.KindUnexpected).WithMessage(errmsg.ErrorMsgFailedQuery)
|
||||
|
||||
for i := maxNextPages - 1; i >= 0; i-- {
|
||||
if pages > float64(i) {
|
||||
return i + 1
|
||||
}
|
||||
}
|
||||
|
||||
return 0
|
||||
//// get records
|
||||
|
||||
stmt, StErr := conn.PrepareStatement(ctx, fetchQueryStmt, fetchQuery)
|
||||
|
||||
if StErr != nil {
|
||||
|
||||
return nil, 0, richerror.New(op).WithErr(StErr).WithKind(richerror.KindUnexpected).WithMessage(errmsg.ErrorMsgFailedQuery)
|
||||
|
||||
}
|
||||
|
||||
queryRows, qrErr := stmt.QueryContext(ctx, fetchParams...)
|
||||
|
||||
if qrErr != nil {
|
||||
return nil, 0, richerror.New(op).WithErr(qrErr).WithKind(richerror.KindUnexpected).WithMessage(errmsg.ErrorMsgFailedQuery)
|
||||
}
|
||||
|
||||
defer queryRows.Close()
|
||||
|
||||
var itemsList []T
|
||||
|
||||
for queryRows.Next() {
|
||||
|
||||
item, err := scanner(queryRows)
|
||||
|
||||
if err != nil {
|
||||
return nil, 0, richerror.New(op).WithErr(err).WithKind(richerror.KindUnexpected).WithMessage(errmsg.ErrorMsgCantScanQueryResult)
|
||||
}
|
||||
|
||||
itemsList = append(itemsList, item)
|
||||
|
||||
}
|
||||
|
||||
if qErr := queryRows.Err(); qErr != nil {
|
||||
|
||||
return nil, 0, richerror.New(op).WithErr(qErr).WithKind(richerror.KindUnexpected).WithMessage(errmsg.ErrorMsgCantScanQueryResult)
|
||||
}
|
||||
|
||||
return itemsList, totalCount, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,9 @@ package postgres
|
|||
type statementKey uint
|
||||
|
||||
const (
|
||||
StatementKeyAWalletGetTransactionHistory statementKey = iota + 1 //wallet
|
||||
StatementKeyWalletInsertTransaction //wallet
|
||||
StatementKeyWalletGetUserWallet //wallet
|
||||
StatementKeyWalletUpsertBalance //wallet
|
||||
StatementKeyAWalletGetTransactionHistory statementKey = iota + 1 //wallet
|
||||
StatementKeyAWalletGetTotalCountTransactionHistory //wallet
|
||||
StatementKeyWalletInsertTransaction //wallet
|
||||
StatementKeyWalletGetUserWallet //wallet
|
||||
StatementKeyWalletUpsertBalance //wallet
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in New Issue