Yimaru-BackEnd/internal/web_server/handlers/branch_handler.go

1031 lines
32 KiB
Go

package handlers
import (
"fmt"
"strconv"
"strings"
"time"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/authentication"
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
"github.com/gofiber/fiber/v2"
"go.uber.org/zap"
)
// CreateBranch godoc
// @Summary Create a branch
// @Description Creates a branch
// @Tags branch
// @Accept json
// @Produce json
// @Param createBranch body domain.CreateBranchReq true "Creates branch"
// @Success 200 {object} domain.BranchRes
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/branch [post]
func (h *Handler) CreateBranch(c *fiber.Ctx) error {
// Check if user is either branch manager / super main
// role := string(c.Locals("role").(domain.Role))
// if role != string(domain.RoleAdmin) && role != string(domain.RoleSuperAdmin) && role != string(domain.RoleBranchManager) {
// logger.Error("Unauthorized access", "role", role)
// return response.WriteJSON(c, fiber.StatusUnauthorized, "Unauthorized access", nil, nil)
// }
role := c.Locals("role").(domain.Role)
companyID := c.Locals("company_id").(domain.ValidInt64)
var req domain.CreateBranchReq
if err := c.BodyParser(&req); err != nil {
// h.logger.Error("CreateBranchReq failed", "error", err)
h.mongoLoggerSvc.Info("CreateBranchReq failed",
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, "Invalid request")
}
valErrs, ok := h.validator.Validate(c, req)
if !ok {
var errMsg string
for field, msg := range valErrs {
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
}
return fiber.NewError(fiber.StatusBadRequest, errMsg)
}
var IsSelfOwned bool
var checkedCompanyID int64
if role == domain.RoleSuperAdmin {
if req.IsSelfOwned == nil {
h.mongoLoggerSvc.Info("is_self_owned is required for super admin",
zap.Int("status_code", fiber.StatusBadRequest),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, "is_self_owned is required for super admin")
}
if req.CompanyID == nil {
h.mongoLoggerSvc.Info("company_id is required for super admin",
zap.Int("status_code", fiber.StatusBadRequest),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, "company_id is required for super admin")
}
IsSelfOwned = *req.IsSelfOwned
checkedCompanyID = *req.CompanyID
} else {
IsSelfOwned = false
checkedCompanyID = companyID.Value
}
// Create Branch Wallet
newWallet, err := h.walletSvc.CreateWallet(c.Context(), domain.CreateWallet{
IsWithdraw: false,
IsBettable: true,
IsTransferable: true,
UserID: req.BranchManagerID,
})
if err != nil {
h.mongoLoggerSvc.Error("Create Branch Wallet failed",
zap.Int64("branch_manager_id", req.BranchManagerID),
zap.Int("status_code", fiber.StatusInternalServerError),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
}
branch, err := h.branchSvc.CreateBranch(c.Context(), domain.CreateBranch{
Name: req.Name,
Location: req.Location,
WalletID: newWallet.ID,
BranchManagerID: req.BranchManagerID,
CompanyID: checkedCompanyID,
IsSelfOwned: IsSelfOwned,
})
if err != nil {
h.mongoLoggerSvc.Error("Failed to create branch",
zap.Int("status_code", fiber.StatusInternalServerError),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
}
for _, operation := range req.Operations {
err := h.branchSvc.CreateBranchOperation(c.Context(), domain.CreateBranchOperation{
BranchID: branch.ID,
OperationID: operation,
})
if err != nil {
h.mongoLoggerSvc.Error("Failed to create branch operations",
zap.Int64("branchID", branch.ID),
zap.Int64("operation", operation),
zap.Int("status_code", fiber.StatusInternalServerError),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
}
}
res := domain.ConvertBranch(branch)
return response.WriteJSON(c, fiber.StatusCreated, "Branch Created", res, nil)
}
// CreateSupportedOperation godoc
// @Summary Create a supported operation
// @Description Creates a supported operation
// @Tags branch
// @Accept json
// @Produce json
// @Param createSupportedOperation body domain.CreateSupportedOperationReq true "Creates supported operation"
// @Success 200 {object} domain.SupportedOperationRes
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/supportedOperation [post]
func (h *Handler) CreateSupportedOperation(c *fiber.Ctx) error {
var req domain.CreateSupportedOperationReq
if err := c.BodyParser(&req); err != nil {
h.mongoLoggerSvc.Info("Failed to parse CreateSupportedOperationReq",
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, "Invalid request")
}
valErrs, ok := h.validator.Validate(c, req)
if !ok {
var errMsg string
for field, msg := range valErrs {
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
}
h.mongoLoggerSvc.Error("Failed to validate CreateSupportedOperationReq",
zap.Any("request", req),
zap.String("error", errMsg),
zap.Int("status_code", fiber.StatusInternalServerError),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, errMsg)
}
operation, err := h.branchSvc.CreateSupportedOperation(c.Context(), domain.CreateSupportedOperation{
Name: req.Name,
Description: req.Description,
})
if err != nil {
h.mongoLoggerSvc.Error("Failed to create supported operation",
zap.String("name", req.Name),
zap.String("description", req.Description),
zap.Int("status_code", fiber.StatusInternalServerError),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, "Failed to create supported operation")
}
res := domain.SupportedOperationRes{
Name: operation.Name,
Description: operation.Description,
}
return response.WriteJSON(c, fiber.StatusOK, "Operation Created", res, nil)
}
// CreateBranchOperation godoc
// @Summary Create a operation
// @Description Creates a operation
// @Tags branch
// @Accept json
// @Produce json
// @Param createBranchOperation body domain.CreateBranchOperationReq true "Creates operation"
// @Success 200 {object} domain.BranchOperationRes
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/operation [post]
func (h *Handler) CreateBranchOperation(c *fiber.Ctx) error {
var req domain.CreateBranchOperationReq
if err := c.BodyParser(&req); err != nil {
h.logger.Error("CreateBranchOperationReq failed", "error", err)
h.mongoLoggerSvc.Info("Failed to parse CreateBranchOperationReq",
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, "Invalid request")
}
valErrs, ok := h.validator.Validate(c, req)
if !ok {
var errMsg string
for field, msg := range valErrs {
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
}
h.mongoLoggerSvc.Info("Failed to validated CreateBranchOperationReq",
zap.String("errMsg", errMsg),
zap.Int("status_code", fiber.StatusBadRequest),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, errMsg)
}
err := h.branchSvc.CreateBranchOperation(c.Context(), domain.CreateBranchOperation{
BranchID: req.BranchID,
OperationID: req.OperationID,
})
if err != nil {
h.mongoLoggerSvc.Error("Failed to create branch operation",
zap.Int("status_code", fiber.StatusInternalServerError),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
}
return response.WriteJSON(c, fiber.StatusOK, "Branch Operation Created", nil, nil)
}
// GetBranchByID godoc
// @Summary Gets branch by id
// @Description Gets a single branch by id
// @Tags branch
// @Accept json
// @Produce json
// @Param id path int true "Branch ID"
// @Success 200 {object} domain.BranchDetailRes
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/branch/{id} [get]
func (h *Handler) GetBranchByID(c *fiber.Ctx) error {
branchID := c.Params("id")
id, err := strconv.ParseInt(branchID, 10, 64)
if err != nil {
h.mongoLoggerSvc.Info("Invalid branch ID",
zap.String("branch", branchID),
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, "Invalid branch ID")
}
branch, err := h.branchSvc.GetBranchByID(c.Context(), id)
if err != nil {
h.mongoLoggerSvc.Info("Failed to get branch by ID",
zap.Int64("branchID", id),
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
}
res := domain.ConvertBranchDetail(branch)
return response.WriteJSON(c, fiber.StatusOK, "Branch retrieved successfully", res, nil)
}
// GetBranchByManagerID godoc
// @Summary Gets branches by manager id
// @Description Gets a branches by manager id
// @Tags branch
// @Accept json
// @Produce json
// @Param id path int true "User ID"
// @Success 200 {array} domain.BranchDetailRes
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/manager/{id}/branch [get]
func (h *Handler) GetBranchByManagerID(c *fiber.Ctx) error {
// TODO: Restrict any who isn't branch manager or higher
userID := c.Params("id")
id, err := strconv.ParseInt(userID, 10, 64)
if err != nil {
h.mongoLoggerSvc.Info("Invalid user ID",
zap.String("userID", userID),
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, "Invalid user ID")
}
branches, err := h.branchSvc.GetBranchByManagerID(c.Context(), id)
if err != nil {
h.mongoLoggerSvc.Info("Failed to get branches",
zap.String("userID", userID),
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, err.Error())
}
var result []domain.BranchDetailRes = make([]domain.BranchDetailRes, 0, len(branches))
for _, branch := range branches {
result = append(result, domain.ConvertBranchDetail(branch))
}
return response.WriteJSON(c, fiber.StatusOK, "Branches for Branch Manager retrieved", result, nil)
}
// GetBranchByCompanyID godoc
// @Summary Gets branches by company id
// @Description Gets branches by company id
// @Tags branch
// @Accept json
// @Produce json
// @Param id path int true "Company ID"
// @Success 200 {array} domain.BranchDetailRes
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/company/{id}/branch [get]
func (h *Handler) GetBranchByCompanyID(c *fiber.Ctx) error {
companyID := c.Params("id")
id, err := strconv.ParseInt(companyID, 10, 64)
if err != nil {
h.mongoLoggerSvc.Info("Invalid company ID",
zap.String("companyID", companyID),
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, "Invalid company ID")
}
branches, err := h.branchSvc.GetBranchByCompanyID(c.Context(), id)
if err != nil {
h.mongoLoggerSvc.Info("Failed to get branches",
zap.String("companyID", companyID),
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
}
var result []domain.BranchDetailRes = make([]domain.BranchDetailRes, 0, len(branches))
for _, branch := range branches {
result = append(result, domain.ConvertBranchDetail(branch))
}
return response.WriteJSON(c, fiber.StatusOK, "Branches for Company retrieved", result, nil)
}
// GetAllBranches godoc
// @Summary Gets all branches
// @Description Gets all branches
// @Tags branch
// @Accept json
// @Produce json
// @Success 200 {array} domain.BranchDetailRes
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/branch [get]
func (h *Handler) GetAllBranches(c *fiber.Ctx) error {
companyID := c.Locals("company_id").(domain.ValidInt64)
isActiveParam := c.Params("is_active")
isActiveValid := isActiveParam != ""
isActive, err := strconv.ParseBool(isActiveParam)
if isActiveValid && err != nil {
h.mongoLoggerSvc.Info("Invalid is_active param",
zap.String("isActive", isActiveParam),
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, "Invalid is_active param")
}
branchManagerQuery := c.Query("branch_manager_id")
var branchManagerID domain.ValidInt64
if branchManagerQuery != "" {
parseManagerID, err := strconv.ParseInt(branchManagerQuery, 10, 64)
if err != nil {
h.mongoLoggerSvc.Info("Failed to parse branch_manager_id",
zap.String("userID", branchManagerQuery),
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, "Failed to parse branch_manager_id")
}
branchManagerID = domain.ValidInt64{
Value: parseManagerID,
Valid: true,
}
}
searchQuery := c.Query("query")
searchString := domain.ValidString{
Value: searchQuery,
Valid: searchQuery != "",
}
createdBeforeQuery := c.Query("created_before")
var createdBefore domain.ValidTime
if createdBeforeQuery != "" {
createdBeforeParsed, err := time.Parse(time.RFC3339, createdBeforeQuery)
if err != nil {
h.mongoLoggerSvc.Info("invalid created_before format",
zap.String("createdBeforeQuery", createdBeforeQuery),
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, "Invalid created_before format")
}
createdBefore = domain.ValidTime{
Value: createdBeforeParsed,
Valid: true,
}
}
createdAfterQuery := c.Query("created_after")
var createdAfter domain.ValidTime
if createdAfterQuery != "" {
createdAfterParsed, err := time.Parse(time.RFC3339, createdAfterQuery)
if err != nil {
h.mongoLoggerSvc.Info("invalid created_after format",
zap.String("createdAfterQuery", createdAfterQuery),
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, "Invalid created_after format")
}
createdAfter = domain.ValidTime{
Value: createdAfterParsed,
Valid: true,
}
}
branches, err := h.branchSvc.GetAllBranches(c.Context(),
domain.BranchFilter{
CompanyID: companyID,
IsActive: domain.ValidBool{
Value: isActive,
Valid: isActiveValid,
},
BranchManagerID: branchManagerID,
Query: searchString,
CreatedBefore: createdBefore,
CreatedAfter: createdAfter,
})
if err != nil {
h.mongoLoggerSvc.Info("Failed to get branches",
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
}
var result []domain.BranchDetailRes = make([]domain.BranchDetailRes, 0, len(branches))
for _, branch := range branches {
result = append(result, domain.ConvertBranchDetail(branch))
}
return response.WriteJSON(c, fiber.StatusOK, "Branches for Company retrieved", result, nil)
}
// SearchBranch godoc
// @Summary Search branches
// @Description Search branches by name or location
// @Tags branch
// @Accept json
// @Produce json
// @Param q query string true "Search query"
// @Success 200 {array} domain.BranchDetailRes
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/search/branch [get]
func (h *Handler) SearchBranch(c *fiber.Ctx) error {
// Get search query from request
searchQuery := c.Query("q")
if searchQuery == "" {
h.mongoLoggerSvc.Info("Search query is required",
zap.Int("status_code", fiber.StatusBadRequest),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, "Search query is required")
}
// Call the service to search for branches
branches, err := h.branchSvc.SearchBranchByName(c.Context(), searchQuery)
if err != nil {
h.mongoLoggerSvc.Info("Failed to search branches",
zap.String("query", searchQuery),
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
}
// Convert branches to response format
var result []domain.BranchDetailRes
for _, branch := range branches {
result = append(result, domain.ConvertBranchDetail(branch))
}
return response.WriteJSON(c, fiber.StatusOK, "Branches retrieved successfully", result, nil)
}
// GetAllSupportedOperations godoc
// @Summary Gets all supported operations
// @Description Gets all supported operations
// @Tags branch
// @Accept json
// @Produce json
// @Success 200 {array} domain.BranchDetailRes
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/supportedOperation [get]
func (h *Handler) GetAllSupportedOperations(c *fiber.Ctx) error {
operations, err := h.branchSvc.GetAllSupportedOperations(c.Context())
if err != nil {
h.mongoLoggerSvc.Error("Failed to get operations",
zap.Int("status_code", fiber.StatusInternalServerError),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
}
var result []domain.SupportedOperationRes = make([]domain.SupportedOperationRes, 0, len(operations))
for _, operation := range operations {
result = append(result, domain.SupportedOperationRes{
ID: operation.ID,
Name: operation.Name,
Description: operation.Description,
})
}
return response.WriteJSON(c, fiber.StatusOK, "SupportedOperations for Company retrieved", result, nil)
}
// GetBranchOperations godoc
// @Summary Gets branch operations
// @Description Gets branch operations
// @Tags branch
// @Accept json
// @Produce json
// @Param id path int true "Branch ID"
// @Success 200 {array} domain.BranchOperationRes
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/branch/{id}/operation [get]
func (h *Handler) GetBranchOperations(c *fiber.Ctx) error {
branchID := c.Params("id")
id, err := strconv.ParseInt(branchID, 10, 64)
if err != nil {
h.mongoLoggerSvc.Error("Invalid branch ID",
zap.String("branchID", branchID),
zap.Int("status_code", fiber.StatusInternalServerError),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, "Invalid branch ID")
}
operations, err := h.branchSvc.GetBranchOperations(c.Context(), id)
if err != nil {
h.mongoLoggerSvc.Error("Failed to get operation by ID",
zap.Int64("branchID", id),
zap.Int("status_code", fiber.StatusInternalServerError),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
}
var result []domain.BranchOperationRes = make([]domain.BranchOperationRes, 0, len(operations))
for _, branch := range operations {
result = append(result, domain.BranchOperationRes{
Name: branch.OperationName,
Description: branch.OperationDescription,
})
}
return response.WriteJSON(c, fiber.StatusOK, "Branch Operations retrieved successfully", result, nil)
}
// GetBranchCashiers godoc
// @Summary Gets branch cashiers
// @Description Gets branch cashiers
// @Tags branch
// @Accept json
// @Produce json
// @Param id path int true "Branch ID"
// @Success 200 {array} GetCashierRes
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/branch/{id}/cashier [get]
func (h *Handler) GetBranchCashiers(c *fiber.Ctx) error {
branchID := c.Params("id")
id, err := strconv.ParseInt(branchID, 10, 64)
if err != nil {
h.mongoLoggerSvc.Info("Invalid branch ID",
zap.String("branchID", branchID),
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, "Invalid branch ID")
}
cashiers, err := h.userSvc.GetCashiersByBranch(c.Context(), id)
if err != nil {
h.mongoLoggerSvc.Error("Failed to get cashier by branch ID",
zap.Int64("branchID", id),
zap.Int("status_code", fiber.StatusInternalServerError),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
}
var result []GetCashierRes = make([]GetCashierRes, 0, len(cashiers))
for _, cashier := range cashiers {
lastLogin, err := h.authSvc.GetLastLogin(c.Context(), cashier.ID)
if err != nil {
if err == authentication.ErrRefreshTokenNotFound {
lastLogin = &cashier.CreatedAt
} else {
h.mongoLoggerSvc.Error("Failed to get user last login",
zap.Int64("cashier ID", cashier.ID),
zap.Int("status_code", fiber.StatusInternalServerError),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login")
}
}
result = append(result, GetCashierRes{
ID: cashier.ID,
FirstName: cashier.FirstName,
LastName: cashier.LastName,
Email: cashier.Email,
PhoneNumber: cashier.PhoneNumber,
Role: cashier.Role,
EmailVerified: cashier.EmailVerified,
PhoneVerified: cashier.PhoneVerified,
CreatedAt: cashier.CreatedAt,
UpdatedAt: cashier.UpdatedAt,
SuspendedAt: cashier.SuspendedAt,
Suspended: cashier.Suspended,
LastLogin: *lastLogin,
})
}
return response.WriteJSON(c, fiber.StatusOK, "Branch Cashiers retrieved successfully", result, nil)
}
// GetBranchForCashier godoc
// @Summary Gets branch for cahier
// @Description Gets branch for cahier
// @Tags branch
// @Accept json
// @Produce json
// @Param id path int true "Branch ID"
// @Success 200 {object} domain.BranchDetailRes
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/branchCashier [get]
func (h *Handler) GetBranchForCashier(c *fiber.Ctx) error {
cashierID, ok := c.Locals("user_id").(int64)
if !ok {
h.mongoLoggerSvc.Error("Invalid cashier ID in context",
zap.Int64("cashierID", cashierID),
zap.Int("status_code", fiber.StatusInternalServerError),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, "Invalid user_id")
}
role, ok := c.Locals("role").(domain.Role)
if !ok || role != domain.RoleCashier {
h.mongoLoggerSvc.Error("Unauthorized access",
zap.Int64("cashierID", cashierID),
zap.String("role", string(role)),
zap.Int("status_code", fiber.StatusForbidden),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusForbidden, "Unauthorized access")
}
branchID, ok := c.Locals("branch_id").(domain.ValidInt64)
if !ok || !branchID.Valid {
h.mongoLoggerSvc.Info("Invalid branch ID in context",
zap.Int64("cashierID", cashierID),
zap.Int("status_code", fiber.StatusBadRequest),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, "Invalid branch ID")
}
branch, err := h.branchSvc.GetBranchByID(c.Context(), branchID.Value)
if err != nil {
h.mongoLoggerSvc.Error("Failed to get branch by ID",
zap.Int64("branchID", branchID.Value),
zap.Int("status_code", fiber.StatusInternalServerError),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
}
res := domain.ConvertBranchDetail(branch)
return response.WriteJSON(c, fiber.StatusOK, "Branch retrieved successfully", res, nil)
}
// GetBetByBranchID godoc
// @Summary Gets bets by its branch id
// @Description Gets bets by its branch id
// @Tags branch
// @Accept json
// @Produce json
// @Success 200 {array} domain.BetRes
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/branch/{id}/bets [get]
func (h *Handler) GetBetByBranchID(c *fiber.Ctx) error {
branchID := c.Params("id")
id, err := strconv.ParseInt(branchID, 10, 64)
if err != nil {
h.mongoLoggerSvc.Info("Invalid branch ID",
zap.String("branchID", branchID),
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, "Invalid branch ID")
}
bets, err := h.transactionSvc.GetAllShopBet(c.Context(), domain.ShopBetFilter{
BranchID: domain.ValidInt64{
Value: id,
Valid: true,
},
})
if err != nil {
h.mongoLoggerSvc.Error("Failed to get bets",
zap.Int("status_code", fiber.StatusInternalServerError),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
}
var res []domain.ShopBetRes = make([]domain.ShopBetRes, 0, len(bets))
for _, bet := range bets {
res = append(res, domain.ConvertShopBetDetail(bet))
}
return response.WriteJSON(c, fiber.StatusOK, "Branch Bets Retrieved", res, nil)
}
// UpdateBranch godoc
// @Summary Updates a branch
// @Description Updates a branch
// @Tags branch
// @Accept json
// @Produce json
// @Param id path int true "Branch ID"
// @Param updateBranch body domain.CreateBranchReq true "Update Branch"
// @Success 200 {object} domain.BranchRes
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/branch/{id} [put]
func (h *Handler) UpdateBranch(c *fiber.Ctx) error {
branchID := c.Params("id")
id, err := strconv.ParseInt(branchID, 10, 64)
if err != nil {
h.mongoLoggerSvc.Info("Invalid branch ID",
zap.String("branchID", branchID),
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, "Invalid branch ID")
}
var req domain.UpdateBranchReq
if err := c.BodyParser(&req); err != nil {
h.mongoLoggerSvc.Info("Failed to parse CreateBranchReq",
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, "Invalid request")
}
valErrs, ok := h.validator.Validate(c, req)
if !ok {
var errMsg string
for field, msg := range valErrs {
errMsg += fmt.Sprintf("%s: %s; ", field, msg)
}
h.mongoLoggerSvc.Info("Failed to validate UpdateBranchReq",
zap.String("branchID", branchID),
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.String("errMsg", errMsg),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, errMsg)
}
branch, err := h.branchSvc.UpdateBranch(c.Context(), domain.UpdateBranch{
ID: id,
Name: req.Name,
Location: req.Location,
BranchManagerID: req.BranchManagerID,
CompanyID: req.CompanyID,
IsSelfOwned: req.IsSelfOwned,
IsActive: req.IsActive,
})
if err != nil {
h.mongoLoggerSvc.Error("Failed to update branch",
zap.Int64("branchID", id),
zap.Int("status_code", fiber.StatusInternalServerError),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
}
res := domain.ConvertBranch(branch)
return response.WriteJSON(c, fiber.StatusOK, "Branch Updated", res, nil)
}
func (h *Handler) UpdateBranchStatus(c *fiber.Ctx) error {
branchID := c.Params("id")
id, err := strconv.ParseInt(branchID, 10, 64)
if err != nil {
h.mongoLoggerSvc.Info("Invalid branch ID",
zap.String("branchID", branchID),
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, err.Error())
}
var isActive bool
path := strings.Split(strings.Trim(c.Path(), "/"), "/")
if path[len(path)-1] == "set-active" {
isActive = true
} else if path[len(path)-1] == "set-inactive" {
isActive = false
} else {
h.mongoLoggerSvc.Info("Invalid branch status",
zap.Bool("status", isActive),
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, "Invalid branch status")
}
branch, err := h.branchSvc.UpdateBranch(c.Context(), domain.UpdateBranch{
ID: id,
IsActive: &isActive,
})
if err != nil {
h.mongoLoggerSvc.Error("Failed to update branch",
zap.Int64("branchID", id),
zap.Int("status_code", fiber.StatusInternalServerError),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
}
res := domain.ConvertBranch(branch)
return response.WriteJSON(c, fiber.StatusOK, "Branch Updated", res, nil)
}
// DeleteBranch godoc
// @Summary Delete the branch
// @Description Delete the branch
// @Tags branch
// @Accept json
// @Produce json
// @Param id path int true "Branch ID""
// @Success 200 {object} response.APIResponse
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/branch/{id} [delete]
func (h *Handler) DeleteBranch(c *fiber.Ctx) error {
branchID := c.Params("id")
id, err := strconv.ParseInt(branchID, 10, 64)
if err != nil {
h.mongoLoggerSvc.Info("Invalid Branch ID",
zap.String("branchID", branchID),
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, "Invalid Branch ID")
}
err = h.branchSvc.DeleteBranch(c.Context(), id)
if err != nil {
h.mongoLoggerSvc.Error("Failed to delete by ID",
zap.Int64("Branch ID", id),
zap.Int("status_code", fiber.StatusInternalServerError),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
}
return response.WriteJSON(c, fiber.StatusOK, "Branch removed successfully", nil, nil)
}
// DeleteBranchOperation godoc
// @Summary Delete the branch operation
// @Description Delete the branch operation
// @Tags branch
// @Accept json
// @Produce json
// @Param id path int true "Branch ID"
// @Param opID path int true "Branch Operation ID"
// @Success 200 {object} response.APIResponse
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/branch/{id}/operation/{opID} [delete]
func (h *Handler) DeleteBranchOperation(c *fiber.Ctx) error {
branchID := c.Params("id")
opID := c.Params("opID")
id, err := strconv.ParseInt(branchID, 10, 64)
if err != nil {
h.mongoLoggerSvc.Error("Invalid Branch ID",
zap.String("branchID", branchID),
zap.Int("status_code", fiber.StatusInternalServerError),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, "Invalid Branch ID")
}
operationID, err := strconv.ParseInt(opID, 10, 64)
if err != nil {
h.mongoLoggerSvc.Info("Invalid Operation ID",
zap.String("operationID", opID),
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, "Invalid Operation ID")
}
err = h.branchSvc.DeleteBranchOperation(c.Context(), id, operationID)
if err != nil {
h.mongoLoggerSvc.Error("Failed to delete operation",
zap.Int64("Branch ID", id),
zap.Int("status_code", fiber.StatusInternalServerError),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
}
return response.WriteJSON(c, fiber.StatusOK, "Branch Operation removed successfully", nil, nil)
}