feat: add customer list, modify pagination utils
This commit is contained in:
@@ -4,10 +4,12 @@ import (
|
||||
"strconv"
|
||||
|
||||
"git.ma-al.com/goc_daniel/b2b/app/delivery/middleware/perms"
|
||||
"git.ma-al.com/goc_daniel/b2b/app/model"
|
||||
"git.ma-al.com/goc_daniel/b2b/app/service/customerService"
|
||||
"git.ma-al.com/goc_daniel/b2b/app/utils/i18n"
|
||||
"git.ma-al.com/goc_daniel/b2b/app/utils/localeExtractor"
|
||||
"git.ma-al.com/goc_daniel/b2b/app/utils/nullable"
|
||||
"git.ma-al.com/goc_daniel/b2b/app/utils/query/query_params"
|
||||
"git.ma-al.com/goc_daniel/b2b/app/utils/response"
|
||||
"git.ma-al.com/goc_daniel/b2b/app/utils/responseErrors"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
@@ -28,7 +30,7 @@ func CustomerHandlerRoutes(r fiber.Router) fiber.Router {
|
||||
handler := NewCustomerHandler()
|
||||
|
||||
r.Get("", handler.customerData)
|
||||
// r.Get("/list", handler.listCustomers)
|
||||
r.Get("/list", handler.listCustomers)
|
||||
return r
|
||||
}
|
||||
|
||||
@@ -67,41 +69,28 @@ func (h *customerHandler) customerData(fc fiber.Ctx) error {
|
||||
return fc.JSON(response.Make(&customer, 0, i18n.T_(fc, response.Message_OK)))
|
||||
}
|
||||
|
||||
// func (h *customerHandler) listCustomers(fc fiber.Ctx) error {
|
||||
// var customerId uint
|
||||
// customerIdStr := fc.Query("id")
|
||||
// if customerIdStr != "" {
|
||||
func (h *customerHandler) listCustomers(fc fiber.Ctx) error {
|
||||
p, filt, err := query_params.ParseFilters[model.Customer](fc, columnMappingListProducts)
|
||||
if err != nil {
|
||||
return fc.Status(responseErrors.GetErrorStatus(err)).
|
||||
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(fc, err)))
|
||||
}
|
||||
|
||||
// user, ok := localeExtractor.GetCustomer(fc)
|
||||
// if !ok || user == nil {
|
||||
// return fc.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)).
|
||||
// JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(fc, responseErrors.ErrBadAttribute)))
|
||||
// }
|
||||
// id, err := strconv.ParseUint(customerIdStr, 10, 64)
|
||||
// if err != nil {
|
||||
// return fiber.ErrBadRequest
|
||||
// }
|
||||
user, ok := localeExtractor.GetCustomer(fc)
|
||||
if !ok || user == nil {
|
||||
return fc.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)).
|
||||
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(fc, responseErrors.ErrBadAttribute)))
|
||||
}
|
||||
if !user.HasPermission(perms.UserReadAny) {
|
||||
return fc.Status(fiber.StatusForbidden).
|
||||
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(fc, responseErrors.ErrForbidden)))
|
||||
}
|
||||
|
||||
// if user.UserID != uint(id) && !user.HasPermission(perms.UserReadAny) {
|
||||
// return fc.Status(fiber.StatusForbidden).
|
||||
// JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(fc, responseErrors.ErrForbidden)))
|
||||
// }
|
||||
customer, err := h.service.Find(user.LangID, p, filt)
|
||||
if err != nil {
|
||||
return fc.Status(responseErrors.GetErrorStatus(err)).
|
||||
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(fc, err)))
|
||||
}
|
||||
|
||||
// customerId = uint(id)
|
||||
// } else {
|
||||
// id, ok := fc.Locals("userID").(uint)
|
||||
// if !ok {
|
||||
// return fc.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)).
|
||||
// JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(fc, responseErrors.ErrBadAttribute)))
|
||||
// }
|
||||
// customerId = id
|
||||
// }
|
||||
|
||||
// customer, err := h.service.GetById(customerId)
|
||||
// if err != nil {
|
||||
// return fc.Status(responseErrors.GetErrorStatus(err)).
|
||||
// JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(fc, err)))
|
||||
// }
|
||||
|
||||
// return fc.JSON(response.Make(&customer, 0, i18n.T_(fc, response.Message_OK)))
|
||||
// }
|
||||
return fc.JSON(response.Make(&customer, 0, i18n.T_(fc, response.Message_OK)))
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ type Customer struct {
|
||||
FirstName string `gorm:"size:100" json:"first_name"`
|
||||
LastName string `gorm:"size:100" json:"last_name"`
|
||||
RoleID uint `gorm:"column:role_id;not null;default:1" json:"-"`
|
||||
Role Role `gorm:"foreignKey:RoleID" json:"role"`
|
||||
Role *Role `gorm:"foreignKey:RoleID" json:"role,omitempty"`
|
||||
Provider AuthProvider `gorm:"type:varchar(20);default:'local'" json:"provider"`
|
||||
ProviderID string `gorm:"size:255" json:"provider_id,omitempty"` // ID from OAuth provider
|
||||
AvatarURL string `gorm:"size:500" json:"avatar_url,omitempty"`
|
||||
|
||||
@@ -3,10 +3,13 @@ package customerRepo
|
||||
import (
|
||||
"git.ma-al.com/goc_daniel/b2b/app/db"
|
||||
"git.ma-al.com/goc_daniel/b2b/app/model"
|
||||
"git.ma-al.com/goc_daniel/b2b/app/utils/query/filters"
|
||||
"git.ma-al.com/goc_daniel/b2b/app/utils/query/find"
|
||||
)
|
||||
|
||||
type UICustomerRepo interface {
|
||||
Get(id uint) (*model.Customer, error)
|
||||
Find(langId uint, p find.Paging, filt *filters.FiltersList) (*find.Found[model.Customer], error)
|
||||
}
|
||||
|
||||
type CustomerRepo struct{}
|
||||
@@ -25,3 +28,12 @@ func (repo *CustomerRepo) Get(id uint) (*model.Customer, error) {
|
||||
|
||||
return &customer, err
|
||||
}
|
||||
|
||||
func (repo *CustomerRepo) Find(langId uint, p find.Paging, filt *filters.FiltersList) (*find.Found[model.Customer], error) {
|
||||
found, err := find.Paginate[model.Customer](langId, p, db.DB.
|
||||
Model(&model.Customer{}).
|
||||
Scopes(filt.All()...),
|
||||
)
|
||||
|
||||
return &found, err
|
||||
}
|
||||
|
||||
@@ -153,7 +153,6 @@ func (s *AuthService) Register(req *model.RegisterRequest) error {
|
||||
Password: string(hashedPassword),
|
||||
FirstName: req.FirstName,
|
||||
LastName: req.LastName,
|
||||
Role: model.Role{},
|
||||
Provider: model.ProviderLocal,
|
||||
IsActive: false,
|
||||
EmailVerified: false,
|
||||
|
||||
@@ -150,7 +150,6 @@ func (s *AuthService) findOrCreateGoogleUser(info *view.GoogleUserInfo) (*model.
|
||||
Provider: model.ProviderGoogle,
|
||||
ProviderID: info.ID,
|
||||
AvatarURL: info.Picture,
|
||||
Role: model.Role{},
|
||||
IsActive: true,
|
||||
EmailVerified: true,
|
||||
LangID: 2, // default is english
|
||||
|
||||
@@ -3,6 +3,8 @@ package customerService
|
||||
import (
|
||||
"git.ma-al.com/goc_daniel/b2b/app/model"
|
||||
"git.ma-al.com/goc_daniel/b2b/app/repos/customerRepo"
|
||||
"git.ma-al.com/goc_daniel/b2b/app/utils/query/filters"
|
||||
"git.ma-al.com/goc_daniel/b2b/app/utils/query/find"
|
||||
)
|
||||
|
||||
type CustomerService struct {
|
||||
@@ -18,3 +20,7 @@ func New() *CustomerService {
|
||||
func (s *CustomerService) GetById(id uint) (*model.Customer, error) {
|
||||
return s.repo.Get(id)
|
||||
}
|
||||
|
||||
func (s *CustomerService) Find(langId uint, p find.Paging, filt *filters.FiltersList) (*find.Found[model.Customer], error) {
|
||||
return s.repo.Find(langId, p, filt)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package find
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
@@ -28,18 +27,13 @@ type Found[T any] struct {
|
||||
Spec map[string]interface{} `json:"spec,omitempty"`
|
||||
}
|
||||
|
||||
// Wraps given query adding limit, offset clauses and SQL_CALC_FOUND_ROWS to it
|
||||
// and running SELECT FOUND_ROWS() afterwards to fetch the total number
|
||||
// (ignoring LIMIT) of results. The final results are wrapped into the
|
||||
// [find.Found] type.
|
||||
func Paginate[T any](langID uint, paging Paging, stmt *gorm.DB) (Found[T], error) {
|
||||
var items []T
|
||||
var count uint64
|
||||
var count int64
|
||||
|
||||
// stmt.Debug()
|
||||
stmt.Count(&count)
|
||||
|
||||
err := stmt.
|
||||
Clauses(SqlCalcFound()).
|
||||
Offset(paging.Offset()).
|
||||
Limit(paging.Limit()).
|
||||
Find(&items).
|
||||
@@ -48,14 +42,6 @@ func Paginate[T any](langID uint, paging Paging, stmt *gorm.DB) (Found[T], error
|
||||
return Found[T]{}, err
|
||||
}
|
||||
|
||||
countInterface, ok := stmt.Get(FOUND_ROWS_CTX_KEY)
|
||||
if !ok {
|
||||
return Found[T]{}, errors.New(FOUND_ROWS_CTX_KEY + " value was not found in the gorm db context")
|
||||
}
|
||||
if count, ok = countInterface.(uint64); !ok {
|
||||
return Found[T]{}, errors.New("failed to cast value under " + FOUND_ROWS_CTX_KEY + " to uint64")
|
||||
}
|
||||
|
||||
columnsSpec := GetColumnsSpec[T](langID)
|
||||
|
||||
return Found[T]{
|
||||
|
||||
15
bruno/api_v1/customer/Customer list.yml
Normal file
15
bruno/api_v1/customer/Customer list.yml
Normal file
@@ -0,0 +1,15 @@
|
||||
info:
|
||||
name: Customer list
|
||||
type: http
|
||||
seq: 3
|
||||
|
||||
http:
|
||||
method: GET
|
||||
url: "{{bas_url}}/restricted/customer/list"
|
||||
auth: inherit
|
||||
|
||||
settings:
|
||||
encodeUrl: true
|
||||
timeout: 0
|
||||
followRedirects: true
|
||||
maxRedirects: 5
|
||||
Reference in New Issue
Block a user