Implement Company Search and Update API Documentation

- Introduced a new search functionality for companies, allowing advanced filtering capabilities including tags, business criteria, and location.
- Updated the API documentation to reflect changes in the search endpoint, enhancing clarity for API consumers.
- Refactored existing company-related API endpoints for consistency, including renaming and restructuring routes.
- Enhanced response structures to return company entities directly, simplifying the response handling in API endpoints.
- Removed unused query parameters and handlers, streamlining the company management functionality.
This commit is contained in:
n.nakhostin
2025-09-08 11:23:15 +03:30
parent 777bbfd714
commit ee830f8c1b
16 changed files with 589 additions and 5338 deletions
+127 -159
View File
@@ -1,72 +1,61 @@
package company
// CreateCompanyForm represents the form for creating a new company
type CreateCompanyForm struct {
Name string `json:"name" valid:"required,length(2|200)"`
Type string `json:"type" valid:"required,in(private|public|government|ngo|startup)"`
RegistrationNumber string `json:"registration_number" valid:"required,length(5|50)"`
TaxID string `json:"tax_id" valid:"required,length(5|50)"`
Industry string `json:"industry" valid:"required,length(2|100)"`
Description *string `json:"description,omitempty" valid:"optional,length(10|1000)"`
Website *string `json:"website,omitempty" valid:"optional,url"`
import "tm/pkg/response"
// Business information
EmployeeCount *int `json:"employee_count,omitempty" valid:"optional,range(1|100000)"`
AnnualRevenue *float64 `json:"annual_revenue,omitempty" valid:"optional,range(0|999999999999)"`
FoundedYear *int `json:"founded_year,omitempty" valid:"optional,range(1800|2100)"`
// CompanyForm represents the form for creating/updating a new company
type (
CompanyForm struct {
Name string `json:"name" valid:"required,length(2|200)"`
Type string `json:"type" valid:"required,in(private|public|government|ngo|startup)"`
RegistrationNumber string `json:"registration_number" valid:"required,length(5|50)"`
TaxID string `json:"tax_id" valid:"required,length(5|50)"`
Industry string `json:"industry" valid:"required,length(2|100)"`
Description *string `json:"description,omitempty" valid:"optional,length(10|1000)"`
Website *string `json:"website,omitempty" valid:"optional,url"`
// Address information
Address *AddressForm `json:"address,omitempty"`
// Business information
EmployeeCount *int `json:"employee_count,omitempty" valid:"optional,range(1|100000)"`
AnnualRevenue *float64 `json:"annual_revenue,omitempty" valid:"optional,range(0|999999999999)"`
FoundedYear *int `json:"founded_year,omitempty" valid:"optional,range(1800|2100)"`
// Contact information
ContactPerson *ContactPersonForm `json:"contact_person,omitempty"`
Phone *string `json:"phone,omitempty" valid:"optional,length(10|20)"`
Email *string `json:"email,omitempty" valid:"optional,email"`
// Address information
Address *AddressForm `json:"address,omitempty"`
// Tags for categorization and search
Tags *CompanyTagsForm `json:"tags,omitempty"`
// Contact information
Phone *string `json:"phone,omitempty" valid:"optional,length(10|20)"`
Email *string `json:"email,omitempty" valid:"optional,email"`
// Settings
Language *string `json:"language,omitempty" valid:"optional,in(en|ar|fr|es|de|zh|ja|ko)"`
Currency *string `json:"currency,omitempty" valid:"optional,in(USD|EUR|GBP|JPY|CAD|AUD|CHF|CNY|INR|BRL)"`
Timezone *string `json:"timezone,omitempty" valid:"optional,length(3|50)"`
}
// Tags for categorization and search
Tags *CompanyTagsForm `json:"tags,omitempty"`
// UpdateCompanyForm represents the form for updating a company
type UpdateCompanyForm struct {
Name *string `json:"name,omitempty" valid:"optional,length(2|200)"`
Type *string `json:"type,omitempty" valid:"optional,in(private|public|government|ngo|startup)"`
RegistrationNumber *string `json:"registration_number,omitempty" valid:"optional,length(5|50)"`
TaxID *string `json:"tax_id,omitempty" valid:"optional,length(5|50)"`
Industry *string `json:"industry,omitempty" valid:"optional,length(2|100)"`
Description *string `json:"description,omitempty" valid:"optional,length(10|1000)"`
Website *string `json:"website,omitempty" valid:"optional,url"`
// Settings
Language *string `json:"language,omitempty" valid:"optional,in(en|ar|fr|es|de|zh|ja|ko)"`
Currency *string `json:"currency,omitempty" valid:"optional,in(USD|EUR|GBP|JPY|CAD|AUD|CHF|CNY|INR|BRL)"`
Timezone *string `json:"timezone,omitempty" valid:"optional,length(3|50)"`
}
// Business information
EmployeeCount *int `json:"employee_count,omitempty" valid:"optional,range(1|100000)"`
AnnualRevenue *float64 `json:"annual_revenue,omitempty" valid:"optional,range(0|999999999999)"`
FoundedYear *int `json:"founded_year,omitempty" valid:"optional,range(1800|2100)"`
// AddressForm represents the form for company address
AddressForm struct {
Street string `json:"street" valid:"required,length(5|200)"`
City string `json:"city" valid:"required,length(2|100)"`
State string `json:"state" valid:"required,length(2|100)"`
PostalCode string `json:"postal_code" valid:"required,length(3|20)"`
Country string `json:"country" valid:"required,length(2|100)"`
}
// Address information
Address *AddressForm `json:"address,omitempty"`
// CompanyTagsForm represents the form for company tags
CompanyTagsForm struct {
CPVCodes []string `json:"cpv_codes,omitempty" valid:"optional"`
Categories []string `json:"categories,omitempty" valid:"optional"`
Keywords []string `json:"keywords,omitempty" valid:"optional"`
Specializations []string `json:"specializations,omitempty" valid:"optional"`
Certifications []string `json:"certifications,omitempty" valid:"optional"`
}
)
// Contact information
ContactPerson *ContactPersonForm `json:"contact_person,omitempty"`
Phone *string `json:"phone,omitempty" valid:"optional,length(10|20)"`
Email *string `json:"email,omitempty" valid:"optional,email"`
// Tags for categorization and search
Tags *CompanyTagsForm `json:"tags,omitempty"`
// Settings
Language *string `json:"language,omitempty" valid:"optional,in(en|ar|fr|es|de|zh|ja|ko)"`
Currency *string `json:"currency,omitempty" valid:"optional,in(USD|EUR|GBP|JPY|CAD|AUD|CHF|CNY|INR|BRL)"`
Timezone *string `json:"timezone,omitempty" valid:"optional,length(3|50)"`
}
// ListCompaniesForm represents the form for listing companies with filters
type ListCompaniesForm struct {
Search *string `query:"search" valid:"optional"`
// SearchForm represents the form for searching companies with filters
type SearchForm struct {
Search *string `query:"q" valid:"optional"`
Type *string `query:"type" valid:"optional,in(private|public|government|ngo|startup)"`
Status *string `query:"status" valid:"optional,in(active|inactive|suspended|pending)"`
Industry *string `query:"industry" valid:"optional"`
@@ -90,122 +79,101 @@ type ListCompaniesForm struct {
SortOrder *string `query:"sort_order" valid:"optional,in(asc|desc)"`
}
// UpdateCompanyStatusForm represents the form for updating company status
type UpdateCompanyStatusForm struct {
Status string `json:"status" valid:"required,in(active|inactive|suspended|pending)"`
// StatusForm represents the form for updating company status
type StatusForm struct {
Status string `json:"status" valid:"required,in(active|inactive|suspended)"`
Reason *string `json:"reason" valid:"optional,length(10|500)"`
}
// UpdateCompanyVerificationForm represents the form for updating company verification status
type UpdateCompanyVerificationForm struct {
// VerificationForm represents the form for updating company verification status
type VerificationForm struct {
IsVerified bool `json:"is_verified"`
IsCompliant bool `json:"is_compliant"`
ComplianceNotes *string `json:"compliance_notes,omitempty" valid:"optional,length(0|1000)"`
}
// UpdateCompanyTagsForm represents the form for updating company tags
type UpdateCompanyTagsForm struct {
Tags *CompanyTagsForm `json:"tags" valid:"required"`
}
// AddTagsForm represents the form for adding tags to a company
type AddTagsForm struct {
CPVCodes []string `json:"cpv_codes,omitempty" valid:"optional"`
Categories []string `json:"categories,omitempty" valid:"optional"`
Keywords []string `json:"keywords,omitempty" valid:"optional"`
Specializations []string `json:"specializations,omitempty" valid:"optional"`
Certifications []string `json:"certifications,omitempty" valid:"optional"`
}
// RemoveTagsForm represents the form for removing tags from a company
type RemoveTagsForm struct {
CPVCodes []string `json:"cpv_codes,omitempty" valid:"optional"`
Categories []string `json:"categories,omitempty" valid:"optional"`
Keywords []string `json:"keywords,omitempty" valid:"optional"`
Specializations []string `json:"specializations,omitempty" valid:"optional"`
Certifications []string `json:"certifications,omitempty" valid:"optional"`
}
// SuspendCompanyForm represents the form for suspending a company
type SuspendCompanyForm struct {
Reason string `json:"reason" valid:"required,length(10|500)"`
}
// AddressForm represents the form for company address
type AddressForm struct {
Street string `json:"street" valid:"required,length(5|200)"`
City string `json:"city" valid:"required,length(2|100)"`
State string `json:"state" valid:"required,length(2|100)"`
PostalCode string `json:"postal_code" valid:"required,length(3|20)"`
Country string `json:"country" valid:"required,length(2|100)"`
}
// ContactPersonForm represents the form for contact person
type ContactPersonForm struct {
FirstName string `json:"first_name" valid:"required,length(2|50)"`
LastName string `json:"last_name" valid:"required,length(2|50)"`
FullName string `json:"full_name" valid:"required,length(2|100)"`
Position string `json:"position" valid:"required,length(2|100)"`
Email string `json:"email" valid:"required,email"`
Phone string `json:"phone" valid:"required,length(10|20)"`
Mobile *string `json:"mobile,omitempty" valid:"optional,length(10|20)"`
IsPrimary bool `json:"is_primary"`
}
// CompanyTagsForm represents the form for company tags
type CompanyTagsForm struct {
CPVCodes []string `json:"cpv_codes,omitempty" valid:"optional"`
Categories []string `json:"categories,omitempty" valid:"optional"`
Keywords []string `json:"keywords,omitempty" valid:"optional"`
Specializations []string `json:"specializations,omitempty" valid:"optional"`
Certifications []string `json:"certifications,omitempty" valid:"optional"`
}
// CompanyListResponse represents the response for listing companies
type CompanyListResponse struct {
Companies []*CompanyResponse `json:"companies"`
Total int64 `json:"total"`
Limit int `json:"limit"`
Offset int `json:"offset"`
TotalPages int `json:"total_pages"`
Companies []*CompanyResponse `json:"companies"`
Meta *response.Meta `json:"-"`
}
// Company search and matching DTOs
type CompanySearchForm struct {
Query *string `query:"q" valid:"optional"`
CPVCodes []string `query:"cpv_codes" valid:"optional"`
Categories []string `query:"categories" valid:"optional"`
Keywords []string `query:"keywords" valid:"optional"`
Specializations []string `query:"specializations" valid:"optional"`
Industry *string `query:"industry" valid:"optional"`
Location *string `query:"location" valid:"optional"`
MinEmployees *int `query:"min_employees" valid:"optional,min(1)"`
MaxEmployees *int `query:"max_employees" valid:"optional,min(1)"`
MinRevenue *float64 `query:"min_revenue" valid:"optional,min(0)"`
MaxRevenue *float64 `query:"max_revenue" valid:"optional,min(0)"`
IsVerified *bool `query:"is_verified" valid:"optional"`
IsCompliant *bool `query:"is_compliant" valid:"optional"`
Limit *int `query:"limit" valid:"optional,range(1|100)"`
Offset *int `query:"offset" valid:"optional,min(0)"`
// 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 *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"`
}
// Company statistics DTOs
type CompanyStatsResponse struct {
TotalCompanies int64 `json:"total_companies"`
ActiveCompanies int64 `json:"active_companies"`
VerifiedCompanies int64 `json:"verified_companies"`
CompaniesByType map[string]int64 `json:"companies_by_type"`
CompaniesByIndustry map[string]int64 `json:"companies_by_industry"`
CompaniesByStatus map[string]int64 `json:"companies_by_status"`
TopCategories []CategoryCount `json:"top_categories"`
TopCPVCodes []CPVCodeCount `json:"top_cpv_codes"`
// ToResponse converts Company to CompanyResponse
func (c *Company) ToResponse() *CompanyResponse {
return &CompanyResponse{
ID: c.ID.Hex(),
Name: c.Name,
Type: string(c.Type),
Status: string(c.Status),
RegistrationNumber: c.RegistrationNumber,
TaxID: c.TaxID,
Industry: c.Industry,
Description: c.Description,
Website: c.Website,
EmployeeCount: c.EmployeeCount,
AnnualRevenue: c.AnnualRevenue,
FoundedYear: c.FoundedYear,
Address: c.Address,
Phone: c.Phone,
Email: c.Email,
Tags: c.Tags,
IsVerified: c.IsVerified,
IsCompliant: c.IsCompliant,
ComplianceNotes: c.ComplianceNotes,
Language: c.Language,
Currency: c.Currency,
Timezone: c.Timezone,
CreatedAt: c.CreatedAt,
UpdatedAt: c.UpdatedAt,
}
}
type CategoryCount struct {
Category string `json:"category"`
Count int64 `json:"count"`
// CompanyProfileResponse represents the company profile data sent in API responses
type CompanyProfileResponse struct {
ID string `json:"id"`
Name string `json:"name"`
RegistrationNumber string `json:"registration_number"`
Industry string `json:"industry"`
FoundedYear *int `json:"founded_year,omitempty"`
CreatedAt int64 `json:"created_at"`
}
type CPVCodeCount struct {
CPVCode string `json:"cpv_code"`
Count int64 `json:"count"`
// ToResponse converts Company to CompanyResponse
func (c *Company) ToProfileResponse() *CompanyProfileResponse {
return &CompanyProfileResponse{
ID: c.ID.Hex(),
Name: c.Name,
RegistrationNumber: c.RegistrationNumber,
Industry: c.Industry,
FoundedYear: c.FoundedYear,
CreatedAt: c.CreatedAt,
}
}