From f5407abbf02907004909b711fc7bf8e4cbba8489 Mon Sep 17 00:00:00 2001 From: "n.nakhostin" Date: Mon, 11 Aug 2025 18:31:15 +0330 Subject: [PATCH] Refactor company domain by removing customer-related fields and methods - Removed OwnerCustomerID from Company entity and CompanyResponse to streamline ownership representation. - Eliminated customer assignment fields from CreateCompanyForm and ListCompaniesForm for clarity. - Updated repository and service methods to remove GetByCustomerID and CountWithCustomer, simplifying the codebase. - Adjusted Search method parameters to exclude hasCustomer filter, enhancing search functionality. - Improved API documentation by removing references to customer assignment in handler comments. --- internal/company/entity.go | 5 --- internal/company/form.go | 26 ++++--------- internal/company/handler.go | 1 - internal/company/repository.go | 69 +++++----------------------------- internal/company/service.go | 29 +++----------- 5 files changed, 23 insertions(+), 107 deletions(-) diff --git a/internal/company/entity.go b/internal/company/entity.go index 64f3433..7cbe899 100644 --- a/internal/company/entity.go +++ b/internal/company/entity.go @@ -65,9 +65,6 @@ type Company struct { Currency string `bson:"currency" json:"currency"` // Default: "USD" Timezone string `bson:"timezone" json:"timezone"` // Default: "UTC" - // Company ownership - which customer owns this company - OwnerCustomerID *string `bson:"owner_customer_id,omitempty" json:"owner_customer_id,omitempty"` - // Audit fields CreatedBy *string `bson:"created_by,omitempty" json:"created_by,omitempty"` UpdatedBy *string `bson:"updated_by,omitempty" json:"updated_by,omitempty"` @@ -167,7 +164,6 @@ type CompanyResponse struct { Language string `json:"language"` Currency string `json:"currency"` Timezone string `json:"timezone"` - OwnerCustomerID *string `json:"owner_customer_id,omitempty"` CreatedAt int64 `json:"created_at"` UpdatedAt int64 `json:"updated_at"` CreatedBy *string `json:"created_by,omitempty"` @@ -200,7 +196,6 @@ func (c *Company) ToResponse() *CompanyResponse { Language: c.Language, Currency: c.Currency, Timezone: c.Timezone, - OwnerCustomerID: c.OwnerCustomerID, CreatedAt: c.CreatedAt, UpdatedAt: c.UpdatedAt, CreatedBy: c.CreatedBy, diff --git a/internal/company/form.go b/internal/company/form.go index a3b95b4..adf424d 100644 --- a/internal/company/form.go +++ b/internal/company/form.go @@ -26,9 +26,6 @@ type CreateCompanyForm struct { // Tags for categorization and search Tags *CompanyTagsForm `json:"tags,omitempty"` - // Customer assignment (for login credentials) - CustomerID *string `json:"customer_id,omitempty" valid:"optional,uuid"` - // 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)"` @@ -81,7 +78,6 @@ type ListCompaniesForm struct { Categories []string `query:"categories" valid:"optional"` Keywords []string `query:"keywords" valid:"optional"` Specializations []string `query:"specializations" valid:"optional"` - HasCustomer *bool `query:"has_customer" valid:"optional"` EmployeeCountMin *int `query:"employee_count_min" valid:"optional,min(1)"` EmployeeCountMax *int `query:"employee_count_max" valid:"optional,min(1)"` AnnualRevenueMin *float64 `query:"annual_revenue_min" valid:"optional,min(0)"` @@ -106,11 +102,6 @@ type UpdateCompanyVerificationForm struct { ComplianceNotes *string `json:"compliance_notes,omitempty" valid:"optional,length(0|1000)"` } -// AssignCustomerForm represents the form for assigning a customer to a company -type AssignCustomerForm struct { - CustomerID string `json:"customer_id" valid:"required,uuid"` -} - // UpdateCompanyTagsForm represents the form for updating company tags type UpdateCompanyTagsForm struct { Tags *CompanyTagsForm `json:"tags" valid:"required"` @@ -199,15 +190,14 @@ type CompanySearchForm struct { // Company statistics DTOs type CompanyStatsResponse struct { - TotalCompanies int64 `json:"total_companies"` - ActiveCompanies int64 `json:"active_companies"` - VerifiedCompanies int64 `json:"verified_companies"` - CompaniesWithCustomer int64 `json:"companies_with_customer"` - 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"` + 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"` } type CategoryCount struct { diff --git a/internal/company/handler.go b/internal/company/handler.go index 2c928ef..0ce3eb8 100644 --- a/internal/company/handler.go +++ b/internal/company/handler.go @@ -183,7 +183,6 @@ func (h *Handler) DeleteCompany(c echo.Context) error { // @Param industry query string false "Filter by industry" // @Param is_verified query boolean false "Filter by verification status" // @Param is_compliant query boolean false "Filter by compliance status" -// @Param has_customer query boolean false "Filter by customer assignment status" // @Param cpv_codes query array false "Filter by CPV codes" // @Param categories query array false "Filter by categories" // @Param keywords query array false "Filter by keywords" diff --git a/internal/company/repository.go b/internal/company/repository.go index 053df69..d22cd3c 100644 --- a/internal/company/repository.go +++ b/internal/company/repository.go @@ -17,17 +17,15 @@ type Repository interface { GetByName(ctx context.Context, name string) (*Company, error) GetByRegistrationNumber(ctx context.Context, registrationNumber string) (*Company, error) GetByTaxID(ctx context.Context, taxID string) (*Company, error) - GetByCustomerID(ctx context.Context, customerID string) (*Company, error) Update(ctx context.Context, company *Company) error Delete(ctx context.Context, id string) error List(ctx context.Context, limit, offset int) ([]*Company, error) - Search(ctx context.Context, search string, companyType *string, status *string, industry *string, isVerified *bool, isCompliant *bool, language *string, currency *string, hasCustomer *bool, cpvCodes []string, categories []string, keywords []string, specializations []string, employeeCountMin *int, employeeCountMax *int, annualRevenueMin *float64, annualRevenueMax *float64, foundedYearMin *int, foundedYearMax *int, limit, offset int, sortBy, sortOrder string) ([]*Company, error) + Search(ctx context.Context, search string, companyType *string, status *string, industry *string, isVerified *bool, isCompliant *bool, language *string, currency *string, cpvCodes []string, categories []string, keywords []string, specializations []string, employeeCountMin *int, employeeCountMax *int, annualRevenueMin *float64, annualRevenueMax *float64, foundedYearMin *int, foundedYearMax *int, limit, offset int, sortBy, sortOrder string) ([]*Company, error) Count(ctx context.Context) (int64, error) CountByType(ctx context.Context, companyType CompanyType) (int64, error) CountByStatus(ctx context.Context, status CompanyStatus) (int64, error) CountByIndustry(ctx context.Context, industry string) (int64, error) CountVerified(ctx context.Context) (int64, error) - CountWithCustomer(ctx context.Context) (int64, error) UpdateStatus(ctx context.Context, id string, status CompanyStatus) error UpdateVerification(ctx context.Context, id string, isVerified, isCompliant bool, complianceNotes *string) error UpdateTags(ctx context.Context, id string, tags *CompanyTags) error @@ -50,7 +48,6 @@ func NewCompanyRepository(mongoManager *mongopkg.ConnectionManager, logger logge *mongopkg.CreateUniqueIndex("name_idx", bson.D{{Key: "name", Value: 1}}), *mongopkg.CreateUniqueIndex("registration_number_idx", bson.D{{Key: "registration_number", Value: 1}}), *mongopkg.CreateUniqueIndex("tax_id_idx", bson.D{{Key: "tax_id", Value: 1}}), - *mongopkg.NewIndex("customer_id_idx", bson.D{{Key: "customer_id", Value: 1}}), *mongopkg.NewIndex("type_idx", bson.D{{Key: "type", Value: 1}}), *mongopkg.NewIndex("status_idx", bson.D{{Key: "status", Value: 1}}), *mongopkg.NewIndex("industry_idx", bson.D{{Key: "industry", Value: 1}}), @@ -187,24 +184,6 @@ func (r *companyRepository) GetByTaxID(ctx context.Context, taxID string) (*Comp return company, nil } -// GetByCustomerID retrieves a company by customer ID -func (r *companyRepository) GetByCustomerID(ctx context.Context, customerID string) (*Company, error) { - filter := bson.M{"customer_id": customerID} - company, err := r.ormRepo.FindOne(ctx, filter) - if err != nil { - if errors.Is(err, mongopkg.ErrDocumentNotFound) { - return nil, errors.New("company not found") - } - r.logger.Error("Failed to get company by customer ID", map[string]interface{}{ - "error": err.Error(), - "customer_id": customerID, - }) - return nil, err - } - - return company, nil -} - // Update updates a company func (r *companyRepository) Update(ctx context.Context, company *Company) error { // Set updated timestamp using Unix timestamp @@ -290,7 +269,7 @@ func (r *companyRepository) List(ctx context.Context, limit, offset int) ([]*Com } // Search retrieves companies with search and filters -func (r *companyRepository) Search(ctx context.Context, search string, companyType *string, status *string, industry *string, isVerified *bool, isCompliant *bool, language *string, currency *string, hasCustomer *bool, cpvCodes []string, categories []string, keywords []string, specializations []string, employeeCountMin *int, employeeCountMax *int, annualRevenueMin *float64, annualRevenueMax *float64, foundedYearMin *int, foundedYearMax *int, limit, offset int, sortBy, sortOrder string) ([]*Company, error) { +func (r *companyRepository) Search(ctx context.Context, search string, companyType *string, status *string, industry *string, isVerified *bool, isCompliant *bool, language *string, currency *string, cpvCodes []string, categories []string, keywords []string, specializations []string, employeeCountMin *int, employeeCountMax *int, annualRevenueMin *float64, annualRevenueMax *float64, foundedYearMin *int, foundedYearMax *int, limit, offset int, sortBy, sortOrder string) ([]*Company, error) { // Build filter filter := bson.M{} @@ -326,14 +305,6 @@ func (r *companyRepository) Search(ctx context.Context, search string, companyTy filter["currency"] = *currency } - if hasCustomer != nil { - if *hasCustomer { - filter["customer_id"] = bson.M{"$ne": nil} - } else { - filter["customer_id"] = nil - } - } - // Tag filters if len(cpvCodes) > 0 { filter["tags.cpv_codes"] = bson.M{"$in": cpvCodes} @@ -507,24 +478,6 @@ func (r *companyRepository) CountVerified(ctx context.Context) (int64, error) { return count, nil } -// CountWithCustomer counts companies with assigned customers -func (r *companyRepository) CountWithCustomer(ctx context.Context) (int64, error) { - filter := bson.M{ - "customer_id": bson.M{"$ne": nil}, - "status": bson.M{"$ne": CompanyStatusInactive}, - } - - count, err := r.ormRepo.Count(ctx, filter) - if err != nil { - r.logger.Error("Failed to count companies with customer", map[string]interface{}{ - "error": err.Error(), - }) - return 0, err - } - - return count, nil -} - // UpdateStatus updates company status func (r *companyRepository) UpdateStatus(ctx context.Context, id string, status CompanyStatus) error { // Get company first @@ -704,20 +657,18 @@ func (r *companyRepository) GetCompanyStats(ctx context.Context) (*CompanyStatsR totalCompanies, _ := r.Count(ctx) activeCompanies, _ := r.CountByStatus(ctx, CompanyStatusActive) verifiedCompanies, _ := r.CountVerified(ctx) - companiesWithCustomer, _ := r.CountWithCustomer(ctx) // For this implementation, we'll return basic stats // In a real implementation, you'd use MongoDB aggregation pipelines stats := &CompanyStatsResponse{ - TotalCompanies: totalCompanies, - ActiveCompanies: activeCompanies, - VerifiedCompanies: verifiedCompanies, - CompaniesWithCustomer: companiesWithCustomer, - CompaniesByType: make(map[string]int64), - CompaniesByIndustry: make(map[string]int64), - CompaniesByStatus: make(map[string]int64), - TopCategories: []CategoryCount{}, - TopCPVCodes: []CPVCodeCount{}, + TotalCompanies: totalCompanies, + ActiveCompanies: activeCompanies, + VerifiedCompanies: verifiedCompanies, + CompaniesByType: make(map[string]int64), + CompaniesByIndustry: make(map[string]int64), + CompaniesByStatus: make(map[string]int64), + TopCategories: []CategoryCount{}, + TopCPVCodes: []CPVCodeCount{}, } return stats, nil diff --git a/internal/company/service.go b/internal/company/service.go index 9b55dac..e38ba39 100644 --- a/internal/company/service.go +++ b/internal/company/service.go @@ -325,7 +325,7 @@ func (s *companyService) ListCompanies(ctx context.Context, form *ListCompaniesF } // Get companies - companies, err := s.repository.Search(ctx, search, form.Type, form.Status, form.Industry, form.IsVerified, form.IsCompliant, form.Language, form.Currency, form.HasCustomer, form.CPVCodes, form.Categories, form.Keywords, form.Specializations, form.EmployeeCountMin, form.EmployeeCountMax, form.AnnualRevenueMin, form.AnnualRevenueMax, form.FoundedYearMin, form.FoundedYearMax, limit, offset, sortBy, sortOrder) + companies, err := s.repository.Search(ctx, search, form.Type, form.Status, form.Industry, form.IsVerified, form.IsCompliant, form.Language, form.Currency, form.CPVCodes, form.Categories, form.Keywords, form.Specializations, form.EmployeeCountMin, form.EmployeeCountMax, form.AnnualRevenueMin, form.AnnualRevenueMax, form.FoundedYearMin, form.FoundedYearMax, limit, offset, sortBy, sortOrder) if err != nil { s.logger.Error("Failed to list companies", map[string]interface{}{ "error": err.Error(), @@ -371,7 +371,7 @@ func (s *companyService) SearchCompanies(ctx context.Context, form *CompanySearc } // Get companies using search - companies, err := s.repository.Search(ctx, query, nil, nil, form.Industry, form.IsVerified, form.IsCompliant, nil, nil, nil, form.CPVCodes, form.Categories, form.Keywords, form.Specializations, form.MinEmployees, form.MaxEmployees, form.MinRevenue, form.MaxRevenue, nil, nil, limit, offset, "created_at", "desc") + companies, err := s.repository.Search(ctx, query, nil, nil, form.Industry, form.IsVerified, form.IsCompliant, nil, nil, form.CPVCodes, form.Categories, form.Keywords, form.Specializations, form.MinEmployees, form.MaxEmployees, form.MinRevenue, form.MaxRevenue, nil, nil, limit, offset, "created_at", "desc") if err != nil { s.logger.Error("Failed to search companies", map[string]interface{}{ "error": err.Error(), @@ -469,25 +469,6 @@ func (s *companyService) UpdateCompanyVerification(ctx context.Context, id strin return nil } -// GetCompanyByCustomerID retrieves a company by customer ID -func (s *companyService) GetCompanyByCustomerID(ctx context.Context, customerID string) (*Company, error) { - company, err := s.repository.GetByCustomerID(ctx, customerID) - if err != nil { - s.logger.Error("Failed to get company by customer ID", map[string]interface{}{ - "error": err.Error(), - "customer_id": customerID, - }) - return nil, err - } - - s.logger.Info("Company retrieved by customer ID successfully", map[string]interface{}{ - "company_id": company.ID, - "customer_id": customerID, - }) - - return company, nil -} - // UpdateCompanyTags updates company tags func (s *companyService) UpdateCompanyTags(ctx context.Context, id string, form *UpdateCompanyTagsForm, updatedBy *string) error { // Get company to check if exists @@ -663,7 +644,7 @@ func (s *companyService) GetCompanyStats(ctx context.Context) (*CompanyStatsResp func (s *companyService) GetCompaniesByType(ctx context.Context, companyType CompanyType, limit, offset int) ([]*Company, int64, error) { // Use search method with type filter typeStr := string(companyType) - companies, err := s.repository.Search(ctx, "", &typeStr, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, limit, offset, "created_at", "desc") + companies, err := s.repository.Search(ctx, "", &typeStr, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, limit, offset, "created_at", "desc") if err != nil { s.logger.Error("Failed to get companies by type", map[string]interface{}{ "error": err.Error(), @@ -689,7 +670,7 @@ func (s *companyService) GetCompaniesByType(ctx context.Context, companyType Com func (s *companyService) GetCompaniesByStatus(ctx context.Context, status CompanyStatus, limit, offset int) ([]*Company, int64, error) { // Use search method with status filter statusStr := string(status) - companies, err := s.repository.Search(ctx, "", nil, &statusStr, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, limit, offset, "created_at", "desc") + companies, err := s.repository.Search(ctx, "", nil, &statusStr, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, limit, offset, "created_at", "desc") if err != nil { s.logger.Error("Failed to get companies by status", map[string]interface{}{ "error": err.Error(), @@ -714,7 +695,7 @@ func (s *companyService) GetCompaniesByStatus(ctx context.Context, status Compan // GetCompaniesByIndustry retrieves companies by industry with pagination func (s *companyService) GetCompaniesByIndustry(ctx context.Context, industry string, limit, offset int) ([]*Company, int64, error) { // Use search method with industry filter - companies, err := s.repository.Search(ctx, "", nil, nil, &industry, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, limit, offset, "created_at", "desc") + companies, err := s.repository.Search(ctx, "", nil, nil, &industry, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, limit, offset, "created_at", "desc") if err != nil { s.logger.Error("Failed to get companies by industry", map[string]interface{}{ "error": err.Error(),