package handlers import ( "net/http" "github.com/gin-gonic/gin" "github.com/oklog/ulid/v2" "github.com/timetracker/backend/internal/api/utils" dto "github.com/timetracker/backend/internal/dtos" "github.com/timetracker/backend/internal/models" ) // CompanyHandler handles company-related API endpoints type CompanyHandler struct{} // NewCompanyHandler creates a new CompanyHandler func NewCompanyHandler() *CompanyHandler { return &CompanyHandler{} } // GetCompanies handles GET /companies // // @Summary Get all companies // @Description Get a list of all companies // @Tags companies // @Accept json // @Produce json // @Security BearerAuth // @Success 200 {object} utils.Response{data=[]dto.CompanyDto} // @Failure 401 {object} utils.Response{error=utils.ErrorInfo} // @Failure 500 {object} utils.Response{error=utils.ErrorInfo} // @Router /companies [get] func (h *CompanyHandler) GetCompanies(c *gin.Context) { // Get companies from the database companies, err := models.GetAllCompanies(c.Request.Context()) if err != nil { utils.InternalErrorResponse(c, "Error retrieving companies: "+err.Error()) return } // Convert to DTOs companyDTOs := make([]dto.CompanyDto, len(companies)) for i, company := range companies { companyDTOs[i] = convertCompanyToDTO(&company) } utils.SuccessResponse(c, http.StatusOK, companyDTOs) } // GetCompanyByID handles GET /companies/:id // // @Summary Get company by ID // @Description Get a company by its ID // @Tags companies // @Accept json // @Produce json // @Security BearerAuth // @Param id path string true "Company ID" // @Success 200 {object} utils.Response{data=dto.CompanyDto} // @Failure 400 {object} utils.Response{error=utils.ErrorInfo} // @Failure 401 {object} utils.Response{error=utils.ErrorInfo} // @Failure 404 {object} utils.Response{error=utils.ErrorInfo} // @Failure 500 {object} utils.Response{error=utils.ErrorInfo} // @Router /companies/{id} [get] func (h *CompanyHandler) GetCompanyByID(c *gin.Context) { // Parse ID from URL idStr := c.Param("id") id, err := ulid.Parse(idStr) if err != nil { utils.BadRequestResponse(c, "Invalid company ID format") return } // Get company from the database company, err := models.GetCompanyByID(c.Request.Context(), models.FromULID(id)) if err != nil { utils.InternalErrorResponse(c, "Error retrieving company: "+err.Error()) return } if company == nil { utils.NotFoundResponse(c, "Company not found") return } // Convert to DTO companyDTO := convertCompanyToDTO(company) utils.SuccessResponse(c, http.StatusOK, companyDTO) } // CreateCompany handles POST /companies // // @Summary Create a new company // @Description Create a new company // @Tags companies // @Accept json // @Produce json // @Security BearerAuth // @Param company body dto.CompanyCreateDto true "Company data" // @Success 201 {object} utils.Response{data=dto.CompanyDto} // @Failure 400 {object} utils.Response{error=utils.ErrorInfo} // @Failure 401 {object} utils.Response{error=utils.ErrorInfo} // @Failure 500 {object} utils.Response{error=utils.ErrorInfo} // @Router /companies [post] func (h *CompanyHandler) CreateCompany(c *gin.Context) { // Parse request body var companyCreateDTO dto.CompanyCreateDto if err := c.ShouldBindJSON(&companyCreateDTO); err != nil { utils.BadRequestResponse(c, "Invalid request body: "+err.Error()) return } // Convert DTO to model companyCreate := convertCreateCompanyDTOToModel(companyCreateDTO) // Create company in the database company, err := models.CreateCompany(c.Request.Context(), companyCreate) if err != nil { utils.InternalErrorResponse(c, "Error creating company: "+err.Error()) return } // Convert to DTO companyDTO := convertCompanyToDTO(company) utils.SuccessResponse(c, http.StatusCreated, companyDTO) } // UpdateCompany handles PUT /companies/:id // // @Summary Update a company // @Description Update an existing company // @Tags companies // @Accept json // @Produce json // @Security BearerAuth // @Param id path string true "Company ID" // @Param company body dto.CompanyUpdateDto true "Company data" // @Success 200 {object} utils.Response{data=dto.CompanyDto} // @Failure 400 {object} utils.Response{error=utils.ErrorInfo} // @Failure 401 {object} utils.Response{error=utils.ErrorInfo} // @Failure 404 {object} utils.Response{error=utils.ErrorInfo} // @Failure 500 {object} utils.Response{error=utils.ErrorInfo} // @Router /companies/{id} [put] func (h *CompanyHandler) UpdateCompany(c *gin.Context) { // Parse ID from URL idStr := c.Param("id") id, err := ulid.Parse(idStr) if err != nil { utils.BadRequestResponse(c, "Invalid company ID format") return } // Parse request body var companyUpdateDTO dto.CompanyUpdateDto if err := c.ShouldBindJSON(&companyUpdateDTO); err != nil { utils.BadRequestResponse(c, "Invalid request body: "+err.Error()) return } // Set ID from URL companyUpdateDTO.ID = id.String() // Convert DTO to model companyUpdate := convertUpdateCompanyDTOToModel(companyUpdateDTO) // Update company in the database company, err := models.UpdateCompany(c.Request.Context(), companyUpdate) if err != nil { utils.InternalErrorResponse(c, "Error updating company: "+err.Error()) return } if company == nil { utils.NotFoundResponse(c, "Company not found") return } // Convert to DTO companyDTO := convertCompanyToDTO(company) utils.SuccessResponse(c, http.StatusOK, companyDTO) } // DeleteCompany handles DELETE /companies/:id // // @Summary Delete a company // @Description Delete a company by its ID // @Tags companies // @Accept json // @Produce json // @Security BearerAuth // @Param id path string true "Company ID" // @Success 204 {object} utils.Response // @Failure 400 {object} utils.Response{error=utils.ErrorInfo} // @Failure 401 {object} utils.Response{error=utils.ErrorInfo} // @Failure 500 {object} utils.Response{error=utils.ErrorInfo} // @Router /companies/{id} [delete] func (h *CompanyHandler) DeleteCompany(c *gin.Context) { // Parse ID from URL idStr := c.Param("id") id, err := ulid.Parse(idStr) if err != nil { utils.BadRequestResponse(c, "Invalid company ID format") return } // Delete company from the database err = models.DeleteCompany(c.Request.Context(), models.FromULID(id)) if err != nil { utils.InternalErrorResponse(c, "Error deleting company: "+err.Error()) return } utils.SuccessResponse(c, http.StatusNoContent, nil) } // Helper functions for DTO conversion func convertCompanyToDTO(company *models.Company) dto.CompanyDto { return dto.CompanyDto{ ID: company.ID.String(), CreatedAt: company.CreatedAt, UpdatedAt: company.UpdatedAt, Name: company.Name, } } func convertCreateCompanyDTOToModel(dto dto.CompanyCreateDto) models.CompanyCreate { return models.CompanyCreate{ Name: dto.Name, } } func convertUpdateCompanyDTOToModel(dto dto.CompanyUpdateDto) models.CompanyUpdate { id, _ := ulid.Parse(dto.ID) update := models.CompanyUpdate{ ID: models.FromULID(id), } if dto.Name != nil { update.Name = dto.Name } return update }