From 055d28f8700111eb0d37cbee498358def7d1202c Mon Sep 17 00:00:00 2001 From: lafetz Date: Thu, 10 Apr 2025 04:22:16 +0300 Subject: [PATCH] start working on admin and cashier --- internal/domain/user.go | 11 +++ internal/repository/user.go | 6 +- internal/services/authentication/impl.go | 14 ++-- internal/services/user/direct.go | 49 ++++++++++++ internal/services/user/port.go | 3 +- internal/web_server/handlers/auth_handler.go | 2 + internal/web_server/handlers/cashier.go | 80 ++++++++++++++++++++ 7 files changed, 157 insertions(+), 8 deletions(-) create mode 100644 internal/services/user/direct.go create mode 100644 internal/web_server/handlers/cashier.go diff --git a/internal/domain/user.go b/internal/domain/user.go index b4d2fa4..7151eb9 100644 --- a/internal/domain/user.go +++ b/internal/domain/user.go @@ -26,6 +26,8 @@ type User struct { // SuspendedAt time.Time Suspended bool + // + BranchID int64 } type RegisterUserReq struct { FirstName string @@ -39,6 +41,15 @@ type RegisterUserReq struct { // OtpMedium OtpMedium } +type CreateUserReq struct { + BranchID int64 + FirstName string + LastName string + Email string + PhoneNumber string + Password string + Role string +} type ResetPasswordReq struct { Email string PhoneNumber string diff --git a/internal/repository/user.go b/internal/repository/user.go index 98814f0..c3aeacd 100644 --- a/internal/repository/user.go +++ b/internal/repository/user.go @@ -8,6 +8,7 @@ import ( dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain" + "github.com/SamuelTariku/FortuneBet-Backend/internal/services/user" "github.com/jackc/pgx/v5/pgtype" ) @@ -82,7 +83,7 @@ func (s *Store) GetUserByID(ctx context.Context, id int64) (domain.User, error) Suspended: user.Suspended, }, nil } -func (s *Store) GetAllUsers(ctx context.Context) ([]domain.User, error) { +func (s *Store) GetAllUsers(ctx context.Context, filter user.Filter) ([]domain.User, error) { users, err := s.queries.GetAllUsers(ctx) if err != nil { return nil, err @@ -233,3 +234,6 @@ func (s *Store) UpdatePassword(ctx context.Context, identifier string, password } return nil } +func (s *Store) CreateUserWithoutOtp(ctx context.Context, user domain.CreateUserReq) (domain.User, error) { + return domain.User{}, nil +} diff --git a/internal/services/authentication/impl.go b/internal/services/authentication/impl.go index ea8de4d..58eb044 100644 --- a/internal/services/authentication/impl.go +++ b/internal/services/authentication/impl.go @@ -19,9 +19,10 @@ var ( ) type LoginSuccess struct { - UserId int64 - Role domain.Role - RfToken string + UserId int64 + Role domain.Role + RfToken string + BranchId int64 } func (s *Service) Login(ctx context.Context, email, phone string, password string) (LoginSuccess, error) { @@ -48,9 +49,10 @@ func (s *Service) Login(ctx context.Context, email, phone string, password strin return LoginSuccess{}, err } return LoginSuccess{ - UserId: user.ID, - Role: user.Role, - RfToken: refreshToken, + UserId: user.ID, + Role: user.Role, + RfToken: refreshToken, + BranchId: user.BranchID, }, nil } diff --git a/internal/services/user/direct.go b/internal/services/user/direct.go new file mode 100644 index 0000000..a0f61b9 --- /dev/null +++ b/internal/services/user/direct.go @@ -0,0 +1,49 @@ +package user + +import ( + "context" + + "github.com/SamuelTariku/FortuneBet-Backend/internal/domain" +) + +func (s *Service) CreateUser(ctx context.Context, User domain.CreateUserReq, createrUserId int64, branchId int64) (domain.User, error) { + // Create User + creator, err := s.userStore.GetUserByID(ctx, createrUserId) + if err != nil { + return domain.User{}, err + } + if creator.Role != domain.RoleAdmin { + User.BranchID = creator.BranchID + User.Role = string(domain.RoleCashier) + } else { + User.BranchID = branchId + User.Role = string(domain.RoleBranchManager) + } + + return s.userStore.CreateUserWithoutOtp(ctx, User) +} + +func (s *Service) DeleteUser(ctx context.Context, id int64) error { + // Delete User + return s.userStore.DeleteUser(ctx, id) +} + +type Filter struct { + Role string + BranchId int64 + Page int + PageSize int +} +type ValidRole struct { + Value domain.Role + Valid bool +} +type ValidBranchId struct { + Value int64 + Valid bool +} + +func (s *Service) GetAllUsers(ctx context.Context, filter Filter) ([]domain.User, error) { + // Get all Users + return s.userStore.GetAllUsers(ctx, filter) +} diff --git a/internal/services/user/port.go b/internal/services/user/port.go index bcfdd5a..7d4c5e3 100644 --- a/internal/services/user/port.go +++ b/internal/services/user/port.go @@ -8,8 +8,9 @@ import ( type UserStore interface { CreateUser(ctx context.Context, user domain.User, usedOtpId int64) (domain.User, error) + CreateUserWithoutOtp(ctx context.Context, user domain.CreateUserReq) (domain.User, error) GetUserByID(ctx context.Context, id int64) (domain.User, error) - GetAllUsers(ctx context.Context) ([]domain.User, error) + GetAllUsers(ctx context.Context, filter Filter) ([]domain.User, error) UpdateUser(ctx context.Context, user domain.UpdateUserReq) error DeleteUser(ctx context.Context, id int64) error CheckPhoneEmailExist(ctx context.Context, phoneNum, email string) (bool, bool, error) diff --git a/internal/web_server/handlers/auth_handler.go b/internal/web_server/handlers/auth_handler.go index 0022827..8731159 100644 --- a/internal/web_server/handlers/auth_handler.go +++ b/internal/web_server/handlers/auth_handler.go @@ -20,6 +20,7 @@ type loginCustomerReq struct { type loginCustomerRes struct { AccessToken string `json:"access_token"` RefreshToken string `json:"refresh_token"` + Role string `json:"role"` } // LoginCustomer godoc @@ -69,6 +70,7 @@ func LoginCustomer( res := loginCustomerRes{ AccessToken: accessToken, RefreshToken: successRes.RfToken, + Role: string(successRes.Role), } return response.WriteJSON(c, fiber.StatusOK, "Login successful", res, nil) } diff --git a/internal/web_server/handlers/cashier.go b/internal/web_server/handlers/cashier.go new file mode 100644 index 0000000..f63b40e --- /dev/null +++ b/internal/web_server/handlers/cashier.go @@ -0,0 +1,80 @@ +package handlers + +import ( + "log/slog" + + "github.com/SamuelTariku/FortuneBet-Backend/internal/domain" + "github.com/SamuelTariku/FortuneBet-Backend/internal/services/user" + "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response" + customvalidator "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/validator" + "github.com/gofiber/fiber/v2" +) + +type CreateCashierReq struct { + FirstName string `json:"first_name" example:"John"` + LastName string `json:"last_name" example:"Doe"` + Email string `json:"email" example:"john.doe@example.com"` + PhoneNumber string `json:"phone_number" example:"1234567890"` + Password string `json:"password" example:"password123"` +} + +func CreateCashier(logger *slog.Logger, userSvc *user.Service, validator *customvalidator.CustomValidator) fiber.Handler { + return func(c *fiber.Ctx) error { + userId := c.Locals("user_id").(int64) + + var req CreateCashierReq + if err := c.BodyParser(&req); err != nil { + logger.Error("RegisterUser failed", "error", err) + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ + "error": "Invalid request", + }) + } + valErrs, ok := validator.Validate(c, req) + if !ok { + response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil) + return nil + } + user := domain.CreateUserReq{ + FirstName: req.FirstName, + LastName: req.LastName, + Email: req.Email, + PhoneNumber: req.PhoneNumber, + Password: req.Password, + Role: string(domain.RoleCashier), + } + _, err := userSvc.CreateUser(c.Context(), user, userId, 0) + if err != nil { + logger.Error("CreateCashier failed", "error", err) + response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to create cashier", nil, nil) + return nil + } + response.WriteJSON(c, fiber.StatusOK, "Cashier created successfully", nil, nil) + return nil + } + +} +func GetAllCashiers(logger *slog.Logger, userSvc *user.Service, validator *customvalidator.CustomValidator) fiber.Handler { + return func(c *fiber.Ctx) error { + + filter := user.Filter{ + Role: string(domain.RoleCashier), + BranchId: int64(c.QueryInt("branch_id")), + Page: c.QueryInt("page", 1), + PageSize: c.QueryInt("page_size", 10), + } + valErrs, ok := validator.Validate(c, filter) + if !ok { + response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil) + return nil + } + cashiers, err := userSvc.GetAllUsers(c.Context(), filter) + if err != nil { + logger.Error("GetAllCashiers failed", "error", err) + response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get cashiers", nil, nil) + return nil + } + response.WriteJSON(c, fiber.StatusOK, "Cashiers retrieved successfully", cashiers, nil) + return nil + } + +}