start working on admin and cashier

This commit is contained in:
lafetz 2025-04-10 04:22:16 +03:00
parent 7dd6221f74
commit 055d28f870
7 changed files with 157 additions and 8 deletions

View File

@ -26,6 +26,8 @@ type User struct {
// //
SuspendedAt time.Time SuspendedAt time.Time
Suspended bool Suspended bool
//
BranchID int64
} }
type RegisterUserReq struct { type RegisterUserReq struct {
FirstName string FirstName string
@ -39,6 +41,15 @@ type RegisterUserReq struct {
// //
OtpMedium OtpMedium OtpMedium OtpMedium
} }
type CreateUserReq struct {
BranchID int64
FirstName string
LastName string
Email string
PhoneNumber string
Password string
Role string
}
type ResetPasswordReq struct { type ResetPasswordReq struct {
Email string Email string
PhoneNumber string PhoneNumber string

View File

@ -8,6 +8,7 @@ import (
dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db" dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/user"
"github.com/jackc/pgx/v5/pgtype" "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, Suspended: user.Suspended,
}, nil }, 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) users, err := s.queries.GetAllUsers(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
@ -233,3 +234,6 @@ func (s *Store) UpdatePassword(ctx context.Context, identifier string, password
} }
return nil return nil
} }
func (s *Store) CreateUserWithoutOtp(ctx context.Context, user domain.CreateUserReq) (domain.User, error) {
return domain.User{}, nil
}

View File

@ -19,9 +19,10 @@ var (
) )
type LoginSuccess struct { type LoginSuccess struct {
UserId int64 UserId int64
Role domain.Role Role domain.Role
RfToken string RfToken string
BranchId int64
} }
func (s *Service) Login(ctx context.Context, email, phone string, password string) (LoginSuccess, error) { 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{}, err
} }
return LoginSuccess{ return LoginSuccess{
UserId: user.ID, UserId: user.ID,
Role: user.Role, Role: user.Role,
RfToken: refreshToken, RfToken: refreshToken,
BranchId: user.BranchID,
}, nil }, nil
} }

View File

@ -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)
}

View File

@ -8,8 +8,9 @@ import (
type UserStore interface { type UserStore interface {
CreateUser(ctx context.Context, user domain.User, usedOtpId int64) (domain.User, error) 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) 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 UpdateUser(ctx context.Context, user domain.UpdateUserReq) error
DeleteUser(ctx context.Context, id int64) error DeleteUser(ctx context.Context, id int64) error
CheckPhoneEmailExist(ctx context.Context, phoneNum, email string) (bool, bool, error) CheckPhoneEmailExist(ctx context.Context, phoneNum, email string) (bool, bool, error)

View File

@ -20,6 +20,7 @@ type loginCustomerReq struct {
type loginCustomerRes struct { type loginCustomerRes struct {
AccessToken string `json:"access_token"` AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"` RefreshToken string `json:"refresh_token"`
Role string `json:"role"`
} }
// LoginCustomer godoc // LoginCustomer godoc
@ -69,6 +70,7 @@ func LoginCustomer(
res := loginCustomerRes{ res := loginCustomerRes{
AccessToken: accessToken, AccessToken: accessToken,
RefreshToken: successRes.RfToken, RefreshToken: successRes.RfToken,
Role: string(successRes.Role),
} }
return response.WriteJSON(c, fiber.StatusOK, "Login successful", res, nil) return response.WriteJSON(c, fiber.StatusOK, "Login successful", res, nil)
} }

View File

@ -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
}
}