Enhance Company Management with Category Integration and API Documentation Updates

- Updated the Company service to include category validation during creation and updates, ensuring that only valid categories are associated with companies.
- Introduced a new CategoryResponse structure to encapsulate category details in API responses, improving the clarity of the data returned.
- Enhanced the CompanyResponse structure to include category details, providing more comprehensive information in API responses.
- Updated Swagger and YAML documentation to reflect the new category integration, including detailed descriptions and examples for the updated response structures.
- Improved error handling for invalid category data during company creation and updates, enhancing the robustness of the API.
- Refactored existing API handlers to accommodate the new category-related changes, ensuring a seamless user experience across the application.
This commit is contained in:
n.nakhostin
2025-09-08 13:01:45 +03:30
parent 991771ee19
commit 8670b3272d
8 changed files with 297 additions and 151 deletions
+98 -10
View File
@@ -4,6 +4,7 @@ import (
"context"
"errors"
"tm/internal/company_category"
"tm/pkg/logger"
"tm/pkg/response"
)
@@ -30,20 +31,39 @@ type Service interface {
// companyService implements the Service interface
type companyService struct {
repository Repository
logger logger.Logger
repository Repository
categoryService company_category.Service
logger logger.Logger
}
// NewCompanyService creates a new company service
func NewCompanyService(repository Repository, logger logger.Logger) Service {
func NewCompanyService(repository Repository, categoryService company_category.Service, logger logger.Logger) Service {
return &companyService{
repository: repository,
logger: logger,
repository: repository,
categoryService: categoryService,
logger: logger,
}
}
// Create creates a new company
func (s *companyService) Create(ctx context.Context, form *CompanyForm) (*CompanyResponse, error) {
// Validate categories if provided
if form.Tags != nil && len(form.Tags.Categories) > 0 {
validCategories, err := s.categoryService.GetByIDs(ctx, form.Tags.Categories)
if err != nil {
s.logger.Error("Failed to validate categories", map[string]interface{}{
"error": err.Error(),
"categories": form.Tags.Categories,
})
return nil, errors.New("failed to validate categories")
}
// Check if all provided categories exist
if len(validCategories) != len(form.Tags.Categories) {
return nil, errors.New("one or more categories are invalid")
}
}
// Check if company name already exists
existingCompany, _ := s.repository.GetByName(ctx, form.Name)
if existingCompany != nil {
@@ -103,7 +123,7 @@ func (s *companyService) Create(ctx context.Context, form *CompanyForm) (*Compan
"type": company.Type,
})
return company.ToResponse(), nil
return company.ToResponse(nil), nil
}
// GetCompanyByID retrieves a company by ID
@@ -122,11 +142,45 @@ func (s *companyService) GetByID(ctx context.Context, id string) (*CompanyRespon
"name": company.Name,
})
return company.ToResponse(), nil
// Get category details for response
categoryDetails, err := s.categoryService.GetByIDs(ctx, company.Tags.Categories)
if err != nil {
s.logger.Warn("Failed to fetch category details for response", map[string]interface{}{
"error": err.Error(),
"company_id": company.ID,
})
}
var convertedCategories []*CategoryResponse
for _, cat := range categoryDetails {
convertedCategories = append(convertedCategories, &CategoryResponse{
ID: cat.ID,
Name: cat.Name,
})
}
return company.ToResponse(convertedCategories), nil
}
// UpdateCompany updates a company
func (s *companyService) Update(ctx context.Context, id string, form *CompanyForm) (*CompanyResponse, error) {
// Validate categories if provided
if form.Tags != nil && len(form.Tags.Categories) > 0 {
validCategories, err := s.categoryService.GetByIDs(ctx, form.Tags.Categories)
if err != nil {
s.logger.Error("Failed to validate categories", map[string]interface{}{
"error": err.Error(),
"categories": form.Tags.Categories,
})
return nil, errors.New("failed to validate categories")
}
// Check if all provided categories exist
if len(validCategories) != len(form.Tags.Categories) {
return nil, errors.New("one or more categories are invalid")
}
}
// Get existing company
company, err := s.repository.GetByID(ctx, id)
if err != nil {
@@ -236,7 +290,7 @@ func (s *companyService) Update(ctx context.Context, id string, form *CompanyFor
"name": company.Name,
})
return company.ToResponse(), nil
return company.ToResponse(nil), nil
}
// DeleteCompany deletes a company (soft delete)
@@ -273,7 +327,24 @@ func (s *companyService) SearchCompanies(ctx context.Context, form *SearchForm,
// Convert to responses
var companyResponses []*CompanyResponse
for _, company := range companies {
companyResponses = append(companyResponses, company.ToResponse())
// Get category details for response
categoryDetails, err := s.categoryService.GetByIDs(ctx, company.Tags.Categories)
if err != nil {
s.logger.Warn("Failed to fetch category details for response", map[string]interface{}{
"error": err.Error(),
"company_id": company.ID,
})
}
var convertedCategories []*CategoryResponse
for _, cat := range categoryDetails {
convertedCategories = append(convertedCategories, &CategoryResponse{
ID: cat.ID,
Name: cat.Name,
})
}
companyResponses = append(companyResponses, company.ToResponse(convertedCategories))
}
return &CompanyListResponse{
@@ -291,7 +362,24 @@ func (s *companyService) GetByIDs(ctx context.Context, ids []string) ([]*Company
var companyResponses []*CompanyResponse
for _, company := range companies {
companyResponses = append(companyResponses, company.ToResponse())
// Get category details for response
categoryDetails, err := s.categoryService.GetByIDs(ctx, company.Tags.Categories)
if err != nil {
s.logger.Warn("Failed to fetch category details for response", map[string]interface{}{
"error": err.Error(),
"company_id": company.ID,
})
}
var convertedCategories []*CategoryResponse
for _, cat := range categoryDetails {
convertedCategories = append(convertedCategories, &CategoryResponse{
ID: cat.ID,
Name: cat.Name,
})
}
companyResponses = append(companyResponses, company.ToResponse(convertedCategories))
}
return companyResponses, nil