From 21f8d170fa9e35fb8f42640790df0fccb88c2bc2 Mon Sep 17 00:00:00 2001 From: fernanda-one Date: Thu, 15 Aug 2024 11:01:55 +0700 Subject: [PATCH] feat: customer list --- internal/entity/auth.go | 48 +++++++++++++++++++++++++ internal/entity/user.go | 20 +++++++++++ internal/handlers/http/user/user.go | 54 ++++++++++++++++++++++++++++- internal/handlers/request/user.go | 32 +++++++++++++++++ internal/handlers/response/user.go | 20 +++++++++++ internal/repository/repository.go | 1 + internal/repository/users/user.go | 48 +++++++++++++++++++++++++ internal/services/service.go | 1 + internal/services/users/users.go | 11 ++++++ 9 files changed, 234 insertions(+), 1 deletion(-) diff --git a/internal/entity/auth.go b/internal/entity/auth.go index d70d53a..a36287f 100644 --- a/internal/entity/auth.go +++ b/internal/entity/auth.go @@ -37,6 +37,31 @@ type UserDB struct { ResetPassword bool `gorm:"column:reset_password" json:"reset_password"` } +func (u *UserDB) ToCustomer() *Customer { + if u == nil { + return &Customer{} + } + + userEntity := &Customer{ + ID: u.ID, + Name: u.Name, + Email: u.Email, + PhoneNumber: u.PhoneNumber, + Status: u.Status, + CreatedAt: u.CreatedAt, + UpdatedAt: u.UpdatedAt, + RoleID: role.Role(u.RoleID), + RoleName: u.RoleName, + PartnerID: u.PartnerID, + PartnerName: u.PartnerName, + SiteID: u.SiteID, + SiteName: u.SiteName, + ResetPassword: u.ResetPassword, + } + + return userEntity +} + func (u *UserDB) ToUser() *User { if u == nil { return &User{} @@ -160,3 +185,26 @@ func (o *UserDB) SetDeleted(updatedby int64) { o.UpdatedBy = updatedby o.Status = userstatus.Inactive } + + +type CustomerList []*UserDB + +type CustomerSearch struct { + Search string + Name string + RoleID int64 + PartnerID int64 + SiteID int64 + Limit int + Offset int +} + + +func (b *CustomerList) ToCustomerList() []*Customer { + var users []*Customer + for _, user := range *b { + users = append(users, user.ToCustomer()) + } + return users +} + diff --git a/internal/entity/user.go b/internal/entity/user.go index 01a6935..e2e5412 100644 --- a/internal/entity/user.go +++ b/internal/entity/user.go @@ -29,6 +29,26 @@ type User struct { ResetPassword bool } +type Customer struct { + ID int64 + Name string + Email string + Password string + Status userstatus.UserStatus + NIK string + UserType string + CreatedAt time.Time + UpdatedAt time.Time + RoleID role.Role + PhoneNumber string + RoleName string + PartnerID *int64 + SiteID *int64 + SiteName string + PartnerName string + ResetPassword bool +} + type AuthenticateUser struct { ID int64 Token string diff --git a/internal/handlers/http/user/user.go b/internal/handlers/http/user/user.go index e6b8267..c0c403a 100644 --- a/internal/handlers/http/user/user.go +++ b/internal/handlers/http/user/user.go @@ -25,6 +25,7 @@ func (h *Handler) Route(group *gin.RouterGroup, jwt gin.HandlerFunc) { route.POST("/", jwt, h.Create) route.GET("/list", jwt, h.GetAll) + route.GET("/customer/list", jwt, h.GetAllCustomer) route.GET("/:id", jwt, h.GetByID) route.PUT("/:id", jwt, h.Update) route.DELETE("/:id", jwt, h.Delete) @@ -163,7 +164,8 @@ func (h *Handler) GetAll(c *gin.Context) { ctx := request.GetMyContext(c) var req request.UserParam if err := c.ShouldBindQuery(&req); err != nil { - + response.ErrorWrapper(c, err) + return } users, total, err := h.service.GetAll(ctx, req.ToEntity(ctx)) @@ -179,6 +181,27 @@ func (h *Handler) GetAll(c *gin.Context) { }) } +func (h *Handler) GetAllCustomer(c *gin.Context) { + ctx := request.GetMyContext(c) + var req request.CustomerParam + if err := c.ShouldBindQuery(&req); err != nil { + response.ErrorWrapper(c, err) + return + } + + users, total, err := h.service.GetAllCustomer(ctx, req.ToEntity(ctx)) + if err != nil { + response.ErrorWrapper(c, err) + return + } + + c.JSON(http.StatusOK, response.BaseResponse{ + Success: true, + Status: http.StatusOK, + Data: h.toCustomerResponseList(users, int64(total), req), + }) +} + // GetByID retrieves details of a specific user by ID. // @Summary Get details of a user by ID // @Description Get details of a user based on the provided ID. @@ -289,3 +312,32 @@ func (h *Handler) toUserResponseList(resp []*entity.User, total int64, req reque Offset: req.Offset, } } +func (h *Handler) toCustomerResponse(resp *entity.Customer) response.Customer { + return response.Customer{ + ID: resp.ID, + Name: resp.Name, + Email: resp.Email, + PhoneNumber: resp.PhoneNumber, + Status: string(resp.Status), + RoleID: int64(resp.RoleID), + RoleName: resp.RoleName, + PartnerID: resp.PartnerID, + PartnerName: resp.PartnerName, + CreatedAt: resp.CreatedAt.Format(time.RFC3339), + UpdatedAt: resp.CreatedAt.Format(time.RFC3339), + } +} + +func (h *Handler) toCustomerResponseList(resp []*entity.Customer, total int64, req request.CustomerParam) response.CustomerList { + var users []response.Customer + for _, b := range resp { + users = append(users, h.toCustomerResponse(b)) + } + + return response.CustomerList{ + Users: users, + Total: total, + Limit: req.Limit, + Offset: req.Offset, + } +} diff --git a/internal/handlers/request/user.go b/internal/handlers/request/user.go index 801435c..2e5a3ef 100644 --- a/internal/handlers/request/user.go +++ b/internal/handlers/request/user.go @@ -72,6 +72,38 @@ func (p *UserParam) ToEntity(ctx mycontext.Context) entity.UserSearch { Offset: p.Offset, } } +type CustomerParam struct { + Search string `form:"search" json:"search" example:"admin,branch1"` + Name string `form:"name" json:"name" example:"Admin 1"` + RoleID int64 `form:"role_id" json:"role_id" example:"1"` + PartnerID int64 `form:"partner_id" json:"partner_id" example:"1"` + SiteID int64 `form:"site_id" json:"site_id" example:"1"` + Limit int `form:"limit,default=10" json:"limit" example:"10"` + Offset int `form:"offset,default=0" json:"offset" example:"0"` +} + +func (p *CustomerParam) ToEntity(ctx mycontext.Context) entity.CustomerSearch { + partnerID := p.PartnerID + siteID := p.SiteID + + if !ctx.IsAdmin() { + partnerID = *ctx.GetPartnerID() + } + + if ctx.GetSiteID() != nil { + siteID = *ctx.GetSiteID() + } + + return entity.CustomerSearch{ + Search: p.Search, + Name: p.Name, + RoleID: p.RoleID, + PartnerID: partnerID, + SiteID: siteID, + Limit: p.Limit, + Offset: p.Offset, + } +} type UserRegister struct { Name string `json:"name" validate:"required" binding:"required"` diff --git a/internal/handlers/response/user.go b/internal/handlers/response/user.go index b4c83a7..ec7de67 100644 --- a/internal/handlers/response/user.go +++ b/internal/handlers/response/user.go @@ -21,6 +21,26 @@ type UserList struct { Limit int `json:"limit"` Offset int `json:"offset"` } +type Customer struct { + ID int64 `json:"id"` + Name string `json:"name"` + Email string `json:"email"` + PhoneNumber string `json:"phone_number"` + Status string `json:"status"` + RoleID int64 `json:"role_id"` + RoleName string `json:"role_name"` + PartnerID *int64 `json:"partner_id"` + PartnerName string `json:"partner_name"` + CreatedAt string `json:"created_at,omitempty"` + UpdatedAt string `json:"updated_at,omitempty"` +} + +type CustomerList struct { + Users []Customer `json:"users"` + Total int64 `json:"total"` + Limit int `json:"limit"` + Offset int `json:"offset"` +} type UserRegister struct { ID int64 `json:"id"` diff --git a/internal/repository/repository.go b/internal/repository/repository.go index 6b782ae..8e730b8 100644 --- a/internal/repository/repository.go +++ b/internal/repository/repository.go @@ -105,6 +105,7 @@ type User interface { Create(ctx context.Context, user *entity.UserDB) (*entity.UserDB, error) CreateWithTx(ctx context.Context, tx *gorm.DB, user *entity.UserDB) (*entity.UserDB, error) GetAllUsers(ctx context.Context, req entity.UserSearch) (entity.UserList, int, error) + GetAllCustomer(ctx context.Context, req entity.CustomerSearch) (entity.CustomerList, int, error) GetUserByID(ctx context.Context, id int64) (*entity.UserDB, error) GetUserByEmail(ctx context.Context, email string) (*entity.UserDB, error) UpdateUser(ctx context.Context, user *entity.UserDB) (*entity.UserDB, error) diff --git a/internal/repository/users/user.go b/internal/repository/users/user.go index 8ae8891..88dfce3 100644 --- a/internal/repository/users/user.go +++ b/internal/repository/users/user.go @@ -123,6 +123,54 @@ func (b *UserRepository) GetAllUsers(ctx context.Context, req entity.UserSearch) return users, int(total), nil } +func (b *UserRepository) GetAllCustomer(ctx context.Context, req entity.CustomerSearch) (entity.CustomerList, int, error) { + var users []*entity.UserDB + var total int64 + + query := b.db.Table("users"). + Select("users.id, users.email, users.name, users.phone_number, users.status, users.created_at, users.updated_at, ur.role_id, r.role_name, ur.partner_id, b.name as partner_name"). + Joins("LEFT JOIN user_roles ur ON users.id = ur.user_id"). + Joins("LEFT JOIN roles r ON ur.role_id = r.role_id"). + Joins("LEFT JOIN partners b ON ur.partner_id = b.id"). + Where("users.deleted_at is null"). + Where("users.user_type = ?", "CUSTOMER") + + if req.Search != "" { + query = query.Where("users.name ILIKE ? or users.email ILIKE ? or r.role_name ILIKE ? or b.name ILIKE ? ", "%"+req.Search+"%", "%"+req.Search+"%", "%"+req.Search+"%", "%"+req.Search+"%") + } + + if req.Name != "" { + query = query.Where("users.name ILIKE ?", "%"+req.Name+"%") + } + + if req.RoleID > 0 { + query = query.Where("ur.role_id = ? ", req.RoleID) + } + + if req.PartnerID > 0 { + query = query.Where("ur.partner_id = ? ", req.PartnerID) + } + + if req.SiteID > 0 { + query = query.Where("ur.site_id = ? ", req.SiteID) + } + + // Get the total count without applying the limit and offset. + if err := query.Model(&entity.UserDB{}).Count(&total).Error; err != nil { + logger.ContextLogger(ctx).Error("error when count users", zap.Error(err)) + return nil, 0, err + } + + // Apply pagination. + query = query.Offset(req.Offset).Limit(req.Limit) + + if err := query.Scan(&users).Error; err != nil { + logger.ContextLogger(ctx).Error("error when get all users", zap.Error(err)) + return nil, 0, err + } + + return users, int(total), nil +} func (b *UserRepository) GetUserByID(ctx context.Context, id int64) (*entity.UserDB, error) { var user *entity.UserDB diff --git a/internal/services/service.go b/internal/services/service.go index 619ac31..d9b7eb8 100644 --- a/internal/services/service.go +++ b/internal/services/service.go @@ -80,6 +80,7 @@ type User interface { Create(ctx mycontext.Context, userReq *entity.User) (*entity.User, error) CreateWithTx(ctx mycontext.Context, tx *gorm.DB, userReq *entity.User) (*entity.User, error) GetAll(ctx mycontext.Context, search entity.UserSearch) ([]*entity.User, int, error) + GetAllCustomer(ctx mycontext.Context, search entity.CustomerSearch) ([]*entity.Customer, int, error) Update(ctx mycontext.Context, id int64, userReq *entity.User) (*entity.User, error) UpdateWithTx(ctx mycontext.Context, tx *gorm.DB, req *entity.User) (*entity.User, error) GetByID(ctx mycontext.Context, id int64) (*entity.User, error) diff --git a/internal/services/users/users.go b/internal/services/users/users.go index f8f10a5..33c74f3 100644 --- a/internal/services/users/users.go +++ b/internal/services/users/users.go @@ -86,6 +86,17 @@ func (s *UserService) GetAll(ctx mycontext.Context, search entity.UserSearch) ([ return users.ToUserList(), total, nil } +func (s *UserService) GetAllCustomer(ctx mycontext.Context, search entity.CustomerSearch) ([]*entity.Customer, int, error) { + + users, total, err := s.repo.GetAllCustomer(ctx, search) + if err != nil { + logger.ContextLogger(ctx).Error("error when get all users", zap.Error(err)) + return nil, 0, err + } + + return users.ToCustomerList(), total, nil +} + func (s *UserService) GetByID(ctx mycontext.Context, id int64) (*entity.User, error) { userDB, err := s.repo.GetUserByID(ctx, id) if err != nil {