248 lines
7.0 KiB
Go

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(), 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(), 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: id,
}
if dto.Name != nil {
update.Name = dto.Name
}
return update
}