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:
+47
-41
@@ -5625,6 +5625,17 @@ const docTemplate = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"company.CategoryResponse": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"company.CompanyForm": {
|
"company.CompanyForm": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
@@ -5801,7 +5812,7 @@ const docTemplate = `{
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"tags": {
|
"tags": {
|
||||||
"$ref": "#/definitions/company.CompanyTags"
|
"$ref": "#/definitions/company.CompanyTagsResponse"
|
||||||
},
|
},
|
||||||
"tax_id": {
|
"tax_id": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@@ -5820,46 +5831,6 @@ const docTemplate = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"company.CompanyTags": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"categories": {
|
|
||||||
"description": "Categories",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"certifications": {
|
|
||||||
"description": "Certifications",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"cpv_codes": {
|
|
||||||
"description": "CPV codes (Common Procurement Vocabulary)",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"keywords": {
|
|
||||||
"description": "Keywords for search and matching",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"specializations": {
|
|
||||||
"description": "Specializations",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"company.CompanyTagsForm": {
|
"company.CompanyTagsForm": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
@@ -5910,6 +5881,41 @@ const docTemplate = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"company.CompanyTagsResponse": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"categories": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/company.CategoryResponse"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"certifications": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"cpv_codes": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"keywords": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"specializations": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"company.StatusForm": {
|
"company.StatusForm": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|||||||
+47
-41
@@ -5619,6 +5619,17 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"company.CategoryResponse": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"company.CompanyForm": {
|
"company.CompanyForm": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
@@ -5795,7 +5806,7 @@
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"tags": {
|
"tags": {
|
||||||
"$ref": "#/definitions/company.CompanyTags"
|
"$ref": "#/definitions/company.CompanyTagsResponse"
|
||||||
},
|
},
|
||||||
"tax_id": {
|
"tax_id": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@@ -5814,46 +5825,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"company.CompanyTags": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"categories": {
|
|
||||||
"description": "Categories",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"certifications": {
|
|
||||||
"description": "Certifications",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"cpv_codes": {
|
|
||||||
"description": "CPV codes (Common Procurement Vocabulary)",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"keywords": {
|
|
||||||
"description": "Keywords for search and matching",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"specializations": {
|
|
||||||
"description": "Specializations",
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"company.CompanyTagsForm": {
|
"company.CompanyTagsForm": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
@@ -5904,6 +5875,41 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"company.CompanyTagsResponse": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"categories": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/company.CategoryResponse"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"certifications": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"cpv_codes": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"keywords": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"specializations": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"company.StatusForm": {
|
"company.StatusForm": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|||||||
+31
-29
@@ -54,6 +54,13 @@ definitions:
|
|||||||
example: 123 Main St
|
example: 123 Main St
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
|
company.CategoryResponse:
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: string
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
company.CompanyForm:
|
company.CompanyForm:
|
||||||
properties:
|
properties:
|
||||||
address:
|
address:
|
||||||
@@ -174,7 +181,7 @@ definitions:
|
|||||||
status:
|
status:
|
||||||
type: string
|
type: string
|
||||||
tags:
|
tags:
|
||||||
$ref: '#/definitions/company.CompanyTags'
|
$ref: '#/definitions/company.CompanyTagsResponse'
|
||||||
tax_id:
|
tax_id:
|
||||||
type: string
|
type: string
|
||||||
timezone:
|
timezone:
|
||||||
@@ -186,34 +193,6 @@ definitions:
|
|||||||
website:
|
website:
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
company.CompanyTags:
|
|
||||||
properties:
|
|
||||||
categories:
|
|
||||||
description: Categories
|
|
||||||
items:
|
|
||||||
type: string
|
|
||||||
type: array
|
|
||||||
certifications:
|
|
||||||
description: Certifications
|
|
||||||
items:
|
|
||||||
type: string
|
|
||||||
type: array
|
|
||||||
cpv_codes:
|
|
||||||
description: CPV codes (Common Procurement Vocabulary)
|
|
||||||
items:
|
|
||||||
type: string
|
|
||||||
type: array
|
|
||||||
keywords:
|
|
||||||
description: Keywords for search and matching
|
|
||||||
items:
|
|
||||||
type: string
|
|
||||||
type: array
|
|
||||||
specializations:
|
|
||||||
description: Specializations
|
|
||||||
items:
|
|
||||||
type: string
|
|
||||||
type: array
|
|
||||||
type: object
|
|
||||||
company.CompanyTagsForm:
|
company.CompanyTagsForm:
|
||||||
properties:
|
properties:
|
||||||
categories:
|
categories:
|
||||||
@@ -247,6 +226,29 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
type: array
|
type: array
|
||||||
type: object
|
type: object
|
||||||
|
company.CompanyTagsResponse:
|
||||||
|
properties:
|
||||||
|
categories:
|
||||||
|
items:
|
||||||
|
$ref: '#/definitions/company.CategoryResponse'
|
||||||
|
type: array
|
||||||
|
certifications:
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
|
cpv_codes:
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
|
keywords:
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
|
specializations:
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
|
type: object
|
||||||
company.StatusForm:
|
company.StatusForm:
|
||||||
properties:
|
properties:
|
||||||
reason:
|
reason:
|
||||||
|
|||||||
+1
-1
@@ -137,8 +137,8 @@ func main() {
|
|||||||
|
|
||||||
// Initialize services with repositories
|
// Initialize services with repositories
|
||||||
userService := user.NewUserService(userRepository, logger, userAuthService, userValidator)
|
userService := user.NewUserService(userRepository, logger, userAuthService, userValidator)
|
||||||
companyService := company.NewCompanyService(companyRepository, logger)
|
|
||||||
categoryService := company_category.NewCategoryService(categoryRepository, logger)
|
categoryService := company_category.NewCategoryService(categoryRepository, logger)
|
||||||
|
companyService := company.NewCompanyService(companyRepository, categoryService, logger)
|
||||||
customerService := customer.NewCustomerService(customerRepository, logger, customerAuthService, companyService)
|
customerService := customer.NewCustomerService(customerRepository, logger, customerAuthService, companyService)
|
||||||
tenderService := tender.NewTenderService(tenderRepository, companyService, logger)
|
tenderService := tender.NewTenderService(tenderRepository, companyService, logger)
|
||||||
feedbackService := feedback.NewFeedbackService(feedbackRepo, tenderService, logger)
|
feedbackService := feedback.NewFeedbackService(feedbackRepo, tenderService, logger)
|
||||||
|
|||||||
+54
-28
@@ -98,36 +98,52 @@ type CompanyListResponse struct {
|
|||||||
Meta *response.Meta `json:"-"`
|
Meta *response.Meta `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// CompanyResponse represents the company data sent in API responses
|
// CategoryResponse represents category data for company responses
|
||||||
type CompanyResponse struct {
|
type CategoryResponse struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Type string `json:"type"`
|
|
||||||
Status string `json:"status"`
|
|
||||||
RegistrationNumber string `json:"registration_number"`
|
|
||||||
TaxID string `json:"tax_id"`
|
|
||||||
Industry string `json:"industry"`
|
|
||||||
Description *string `json:"description,omitempty"`
|
|
||||||
Website *string `json:"website,omitempty"`
|
|
||||||
EmployeeCount *int `json:"employee_count,omitempty"`
|
|
||||||
AnnualRevenue *float64 `json:"annual_revenue,omitempty"`
|
|
||||||
FoundedYear *int `json:"founded_year,omitempty"`
|
|
||||||
Address *Address `json:"address,omitempty"`
|
|
||||||
Phone *string `json:"phone,omitempty"`
|
|
||||||
Email *string `json:"email,omitempty"`
|
|
||||||
Tags *CompanyTags `json:"tags,omitempty"`
|
|
||||||
IsVerified bool `json:"is_verified"`
|
|
||||||
IsCompliant bool `json:"is_compliant"`
|
|
||||||
ComplianceNotes *string `json:"compliance_notes,omitempty"`
|
|
||||||
Language string `json:"language"`
|
|
||||||
Currency string `json:"currency"`
|
|
||||||
Timezone string `json:"timezone"`
|
|
||||||
CreatedAt int64 `json:"created_at"`
|
|
||||||
UpdatedAt int64 `json:"updated_at"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CompanyResponse represents the company data sent in API responses
|
||||||
|
type (
|
||||||
|
CompanyResponse struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
RegistrationNumber string `json:"registration_number"`
|
||||||
|
TaxID string `json:"tax_id"`
|
||||||
|
Industry string `json:"industry"`
|
||||||
|
Description *string `json:"description,omitempty"`
|
||||||
|
Website *string `json:"website,omitempty"`
|
||||||
|
EmployeeCount *int `json:"employee_count,omitempty"`
|
||||||
|
AnnualRevenue *float64 `json:"annual_revenue,omitempty"`
|
||||||
|
FoundedYear *int `json:"founded_year,omitempty"`
|
||||||
|
Address *Address `json:"address,omitempty"`
|
||||||
|
Phone *string `json:"phone,omitempty"`
|
||||||
|
Email *string `json:"email,omitempty"`
|
||||||
|
Tags *CompanyTagsResponse `json:"tags,omitempty"`
|
||||||
|
IsVerified bool `json:"is_verified"`
|
||||||
|
IsCompliant bool `json:"is_compliant"`
|
||||||
|
ComplianceNotes *string `json:"compliance_notes,omitempty"`
|
||||||
|
Language string `json:"language"`
|
||||||
|
Currency string `json:"currency"`
|
||||||
|
Timezone string `json:"timezone"`
|
||||||
|
CreatedAt int64 `json:"created_at"`
|
||||||
|
UpdatedAt int64 `json:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
CompanyTagsResponse struct {
|
||||||
|
CPVCodes []string `json:"cpv_codes"`
|
||||||
|
Categories []*CategoryResponse `json:"categories"`
|
||||||
|
Keywords []string `json:"keywords"`
|
||||||
|
Specializations []string `json:"specializations"`
|
||||||
|
Certifications []string `json:"certifications"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
// ToResponse converts Company to CompanyResponse
|
// ToResponse converts Company to CompanyResponse
|
||||||
func (c *Company) ToResponse() *CompanyResponse {
|
func (c *Company) ToResponse(categories []*CategoryResponse) *CompanyResponse {
|
||||||
return &CompanyResponse{
|
return &CompanyResponse{
|
||||||
ID: c.ID.Hex(),
|
ID: c.ID.Hex(),
|
||||||
Name: c.Name,
|
Name: c.Name,
|
||||||
@@ -144,7 +160,7 @@ func (c *Company) ToResponse() *CompanyResponse {
|
|||||||
Address: c.Address,
|
Address: c.Address,
|
||||||
Phone: c.Phone,
|
Phone: c.Phone,
|
||||||
Email: c.Email,
|
Email: c.Email,
|
||||||
Tags: c.Tags,
|
Tags: c.Tags.ToResponse(categories),
|
||||||
IsVerified: c.IsVerified,
|
IsVerified: c.IsVerified,
|
||||||
IsCompliant: c.IsCompliant,
|
IsCompliant: c.IsCompliant,
|
||||||
ComplianceNotes: c.ComplianceNotes,
|
ComplianceNotes: c.ComplianceNotes,
|
||||||
@@ -156,6 +172,16 @@ func (c *Company) ToResponse() *CompanyResponse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *CompanyTags) ToResponse(categories []*CategoryResponse) *CompanyTagsResponse {
|
||||||
|
return &CompanyTagsResponse{
|
||||||
|
CPVCodes: c.CPVCodes,
|
||||||
|
Categories: categories,
|
||||||
|
Keywords: c.Keywords,
|
||||||
|
Specializations: c.Specializations,
|
||||||
|
Certifications: c.Certifications,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// CompanyProfileResponse represents the company profile data sent in API responses
|
// CompanyProfileResponse represents the company profile data sent in API responses
|
||||||
type CompanyProfileResponse struct {
|
type CompanyProfileResponse struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
|
|||||||
@@ -80,6 +80,10 @@ func (h *Handler) Create(c echo.Context) error {
|
|||||||
err.Error() == "company with this tax ID already exists" {
|
err.Error() == "company with this tax ID already exists" {
|
||||||
return response.Conflict(c, err.Error())
|
return response.Conflict(c, err.Error())
|
||||||
}
|
}
|
||||||
|
if err.Error() == "one or more categories are invalid" ||
|
||||||
|
err.Error() == "failed to validate categories" {
|
||||||
|
return response.BadRequest(c, err.Error(), "Invalid category data")
|
||||||
|
}
|
||||||
return response.InternalServerError(c, "Failed to create company")
|
return response.InternalServerError(c, "Failed to create company")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,6 +150,10 @@ func (h *Handler) Update(c echo.Context) error {
|
|||||||
err.Error() == "company with this tax ID already exists" {
|
err.Error() == "company with this tax ID already exists" {
|
||||||
return response.Conflict(c, err.Error())
|
return response.Conflict(c, err.Error())
|
||||||
}
|
}
|
||||||
|
if err.Error() == "one or more categories are invalid" ||
|
||||||
|
err.Error() == "failed to validate categories" {
|
||||||
|
return response.BadRequest(c, err.Error(), "Invalid category data")
|
||||||
|
}
|
||||||
return response.InternalServerError(c, "Failed to update company")
|
return response.InternalServerError(c, "Failed to update company")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+98
-10
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
|
"tm/internal/company_category"
|
||||||
"tm/pkg/logger"
|
"tm/pkg/logger"
|
||||||
"tm/pkg/response"
|
"tm/pkg/response"
|
||||||
)
|
)
|
||||||
@@ -30,20 +31,39 @@ type Service interface {
|
|||||||
|
|
||||||
// companyService implements the Service interface
|
// companyService implements the Service interface
|
||||||
type companyService struct {
|
type companyService struct {
|
||||||
repository Repository
|
repository Repository
|
||||||
logger logger.Logger
|
categoryService company_category.Service
|
||||||
|
logger logger.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCompanyService creates a new company service
|
// 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{
|
return &companyService{
|
||||||
repository: repository,
|
repository: repository,
|
||||||
logger: logger,
|
categoryService: categoryService,
|
||||||
|
logger: logger,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create creates a new company
|
// Create creates a new company
|
||||||
func (s *companyService) Create(ctx context.Context, form *CompanyForm) (*CompanyResponse, error) {
|
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
|
// Check if company name already exists
|
||||||
existingCompany, _ := s.repository.GetByName(ctx, form.Name)
|
existingCompany, _ := s.repository.GetByName(ctx, form.Name)
|
||||||
if existingCompany != nil {
|
if existingCompany != nil {
|
||||||
@@ -103,7 +123,7 @@ func (s *companyService) Create(ctx context.Context, form *CompanyForm) (*Compan
|
|||||||
"type": company.Type,
|
"type": company.Type,
|
||||||
})
|
})
|
||||||
|
|
||||||
return company.ToResponse(), nil
|
return company.ToResponse(nil), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCompanyByID retrieves a company by ID
|
// GetCompanyByID retrieves a company by ID
|
||||||
@@ -122,11 +142,45 @@ func (s *companyService) GetByID(ctx context.Context, id string) (*CompanyRespon
|
|||||||
"name": company.Name,
|
"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
|
// UpdateCompany updates a company
|
||||||
func (s *companyService) Update(ctx context.Context, id string, form *CompanyForm) (*CompanyResponse, error) {
|
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
|
// Get existing company
|
||||||
company, err := s.repository.GetByID(ctx, id)
|
company, err := s.repository.GetByID(ctx, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -236,7 +290,7 @@ func (s *companyService) Update(ctx context.Context, id string, form *CompanyFor
|
|||||||
"name": company.Name,
|
"name": company.Name,
|
||||||
})
|
})
|
||||||
|
|
||||||
return company.ToResponse(), nil
|
return company.ToResponse(nil), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteCompany deletes a company (soft delete)
|
// DeleteCompany deletes a company (soft delete)
|
||||||
@@ -273,7 +327,24 @@ func (s *companyService) SearchCompanies(ctx context.Context, form *SearchForm,
|
|||||||
// Convert to responses
|
// Convert to responses
|
||||||
var companyResponses []*CompanyResponse
|
var companyResponses []*CompanyResponse
|
||||||
for _, company := range companies {
|
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{
|
return &CompanyListResponse{
|
||||||
@@ -291,7 +362,24 @@ func (s *companyService) GetByIDs(ctx context.Context, ids []string) ([]*Company
|
|||||||
|
|
||||||
var companyResponses []*CompanyResponse
|
var companyResponses []*CompanyResponse
|
||||||
for _, company := range companies {
|
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
|
return companyResponses, nil
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"tm/pkg/response"
|
"tm/pkg/response"
|
||||||
|
|
||||||
"go.mongodb.org/mongo-driver/bson"
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Repository defines the interface for category data operations
|
// Repository defines the interface for category data operations
|
||||||
@@ -98,7 +99,16 @@ func (r *categoryRepository) GetByID(ctx context.Context, id string) (*Category,
|
|||||||
|
|
||||||
// GetByIDs retrieves categories by IDs
|
// GetByIDs retrieves categories by IDs
|
||||||
func (r *categoryRepository) GetByIDs(ctx context.Context, ids []string) ([]Category, error) {
|
func (r *categoryRepository) GetByIDs(ctx context.Context, ids []string) ([]Category, error) {
|
||||||
filter := bson.M{"_id": bson.M{"$in": ids}}
|
objectIDs := make([]primitive.ObjectID, len(ids))
|
||||||
|
for i, id := range ids {
|
||||||
|
objectID, err := primitive.ObjectIDFromHex(id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
objectIDs[i] = objectID
|
||||||
|
}
|
||||||
|
|
||||||
|
filter := bson.M{"_id": bson.M{"$in": objectIDs}}
|
||||||
|
|
||||||
paginationBuilder := orm.NewPaginationBuilder().
|
paginationBuilder := orm.NewPaginationBuilder().
|
||||||
Build()
|
Build()
|
||||||
|
|||||||
Reference in New Issue
Block a user