Yimaru-BackEnd/internal/web_server/handlers/company_handler.go
2025-07-22 17:39:53 +03:00

421 lines
13 KiB
Go

package handlers
import (
"fmt"
"strconv"
"time"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
"github.com/gofiber/fiber/v2"
"go.uber.org/zap"
)
// CreateCompany godoc
// @Summary Create a company
// @Description Creates a company
// @Tags company
// @Accept json
// @Produce json
// @Param createCompany body domain.CreateCompanyReq true "Creates company"
// @Success 200 {object} domain.CompanyRes
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/company [post]
func (h *Handler) CreateCompany(c *fiber.Ctx) error {
var req domain.CreateCompanyReq
if err := c.BodyParser(&req); err != nil {
h.mongoLoggerSvc.Info("CreateCompanyReq 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)
}
h.mongoLoggerSvc.Info("Failed to validate create company",
zap.String("errMsg", errMsg),
zap.Int("status_code", fiber.StatusBadRequest),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, errMsg)
}
user, err := h.userSvc.GetUserByID(c.Context(), req.AdminID)
if err != nil {
h.mongoLoggerSvc.Error("Error fetching user",
zap.Int("admin_id", int(req.AdminID)),
zap.Int("status_code", fiber.StatusInternalServerError),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
}
// Create Company Wallet
newWallet, err := h.walletSvc.CreateWallet(c.Context(), domain.CreateWallet{
IsWithdraw: false,
IsBettable: true,
IsTransferable: true,
UserID: req.AdminID,
})
if err != nil {
h.mongoLoggerSvc.Error("Create Company Wallet failed",
zap.Int64("admin", req.AdminID),
zap.Int("status_code", fiber.StatusInternalServerError),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
}
company, err := h.companySvc.CreateCompany(c.Context(), domain.CreateCompany{
Name: req.Name,
AdminID: user.ID,
WalletID: newWallet.ID,
DeductedPercentage: req.DeductedPercentage,
})
if err != nil {
h.mongoLoggerSvc.Error("CreateCompanyReq failed to create company",
zap.Int64("userID", user.ID),
zap.String("name", req.Name),
zap.String("Name", req.Name),
zap.Int("status_code", fiber.StatusInternalServerError),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
}
err = h.userSvc.UpdateUserCompany(c.Context(), user.ID, company.ID)
if err != nil {
h.mongoLoggerSvc.Error("Failed to update user company",
zap.Int64("userID", user.ID),
zap.Int64("companyID", company.ID),
zap.Int("status_code", fiber.StatusInternalServerError),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
}
res := domain.ConvertCompany(company)
return response.WriteJSON(c, fiber.StatusCreated, "Company Created", res, nil)
}
// GetAllCompanies godoc
// @Summary Gets all companies
// @Description Gets all companies
// @Tags company
// @Accept json
// @Produce json
// @Success 200 {array} domain.GetCompanyRes
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/company [get]
func (h *Handler) GetAllCompanies(c *fiber.Ctx) error {
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("created_after", 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,
}
}
companies, err := h.companySvc.GetAllCompanies(c.Context(), domain.CompanyFilter{
Query: searchString,
CreatedBefore: createdBefore,
CreatedAfter: createdAfter,
})
if err != nil {
h.mongoLoggerSvc.Error("Failed to get companies",
zap.Int("status_code", fiber.StatusInternalServerError),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
}
var result []domain.GetCompanyRes = make([]domain.GetCompanyRes, 0, len(companies))
for _, company := range companies {
result = append(result, domain.ConvertGetCompany(company))
}
return response.WriteJSON(c, fiber.StatusOK, "All Companies retrieved", result, nil)
}
// GetCompanyByID godoc
// @Summary Gets company by id
// @Description Gets a single company by id
// @Tags company
// @Accept json
// @Produce json
// @Param id path int true "Company ID"
// @Success 200 {object} domain.GetCompanyRes
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/company/{id} [get]
func (h *Handler) GetCompanyByID(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")
}
company, err := h.companySvc.GetCompanyByID(c.Context(), id)
if err != nil {
h.mongoLoggerSvc.Error("Failed to get company by ID",
zap.Int64("companyID", id),
zap.Int("status_code", fiber.StatusInternalServerError),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
}
res := domain.ConvertGetCompany(company)
return response.WriteJSON(c, fiber.StatusOK, "Company retrieved successfully", res, nil)
}
// GetCompanyForAdmin godoc
// @Summary Gets company by id
// @Description Gets a single company by id
// @Tags company
// @Accept json
// @Produce json
// @Success 200 {object} domain.GetCompanyRes
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/admin-company [get]
func (h *Handler) GetCompanyForAdmin(c *fiber.Ctx) error {
companyID := c.Locals("company_id").(domain.ValidInt64)
if !companyID.Valid {
h.mongoLoggerSvc.Error("Invalid company ID",
zap.Int("status_code", fiber.StatusInternalServerError),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, "Invalid company ID")
}
company, err := h.companySvc.GetCompanyByID(c.Context(), companyID.Value)
if err != nil {
h.mongoLoggerSvc.Error("Failed to get company by ID",
zap.Int64("companyID", companyID.Value),
zap.Int("status_code", fiber.StatusInternalServerError),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
}
res := domain.ConvertGetCompany(company)
return response.WriteJSON(c, fiber.StatusOK, "Company retrieved successfully", res, nil)
}
// GetAllCompanies godoc
// @Summary Gets all companies
// @Description Gets all companies
// @Tags company
// @Accept json
// @Produce json
// @Success 200 {array} domain.CompanyRes
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/search/company [get]
func (h *Handler) SearchCompany(c *fiber.Ctx) error {
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")
}
companies, err := h.companySvc.SearchCompanyByName(c.Context(), searchQuery)
if err != nil {
h.mongoLoggerSvc.Info("Failed to get companies",
zap.String("search query", searchQuery),
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
}
var result []domain.GetCompanyRes = make([]domain.GetCompanyRes, 0, len(companies))
for _, company := range companies {
result = append(result, domain.ConvertGetCompany(company))
}
return response.WriteJSON(c, fiber.StatusOK, "All Companies retrieved", result, nil)
}
// UpdateCompany godoc
// @Summary Updates a company
// @Description Updates a company
// @Tags company
// @Accept json
// @Produce json
// @Param id path int true "Company ID"
// @Param updateCompany body domain.UpdateCompanyReq true "Update Company"
// @Success 200 {object} domain.CompanyRes
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/company/{id} [put]
func (h *Handler) UpdateCompany(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")
}
var req domain.UpdateCompanyReq
if err := c.BodyParser(&req); err != nil {
h.mongoLoggerSvc.Info("UpdateCompanyReq failed",
zap.String("companyID", companyID),
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("UpdateCompanyReq failed to validate",
zap.String("companyID", companyID),
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusBadRequest, errMsg)
}
company, err := h.companySvc.UpdateCompany(c.Context(), domain.ConvertUpdateCompanyReq(req))
if err != nil {
h.mongoLoggerSvc.Error("Failed to update company",
zap.Int64("companyID", id),
zap.Int("status_code", fiber.StatusInternalServerError),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
}
res := domain.ConvertCompany(company)
return response.WriteJSON(c, fiber.StatusOK, "Company Updated", res, nil)
}
// DeleteCompany godoc
// @Summary Delete the company
// @Description Delete the company
// @Tags company
// @Accept json
// @Produce json
// @Param id path int true "Company ID""
// @Success 200 {object} response.APIResponse
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /api/v1/company/{id} [delete]
func (h *Handler) DeleteCompany(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")
}
err = h.companySvc.DeleteCompany(c.Context(), id)
if err != nil {
h.mongoLoggerSvc.Info("Failed to delete by ID",
zap.Int64("Company ID", id),
zap.Int("status_code", fiber.StatusBadRequest),
zap.Error(err),
zap.Time("timestamp", time.Now()),
)
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
}
return response.WriteJSON(c, fiber.StatusOK, "Company removed successfully", nil, nil)
}