From 6dcee0bc4b0ffbceeec25f08d67bff25c1fac861 Mon Sep 17 00:00:00 2001 From: "n.nakhostin" Date: Sat, 20 Sep 2025 10:32:21 +0330 Subject: [PATCH] Refactor Customer Entity and Forms to Use 'Companies' Field - Updated the Customer entity to replace 'CompanyIDs' with 'Companies' for improved clarity and consistency. - Modified CreateCustomerForm and UpdateCustomerForm to reflect the change from 'CompanyIDs' to 'Companies', ensuring proper validation and structured responses. - Adjusted service methods to handle the new 'Companies' field, including registration and company assignment logic, enhancing the overall data model and API usability. --- internal/customer/entity.go | 2 +- internal/customer/form.go | 38 +++++++++--------- internal/customer/service.go | 78 ++++++++++++++++++------------------ 3 files changed, 58 insertions(+), 60 deletions(-) diff --git a/internal/customer/entity.go b/internal/customer/entity.go index 37aeb02..6b6d3c7 100644 --- a/internal/customer/entity.go +++ b/internal/customer/entity.go @@ -44,7 +44,7 @@ type Customer struct { Type CustomerType `bson:"type"` Role CustomerRole `bson:"role"` Phone *string `bson:"phone"` - CompanyIDs []string `bson:"company_ids"` + Companies []string `bson:"companies"` DeviceToken []string `bson:"device_token"` LastLoginAt *int64 `bson:"last_login_at"` UpdatedAt int64 `bson:"updated_at"` diff --git a/internal/customer/form.go b/internal/customer/form.go index f072887..de42288 100644 --- a/internal/customer/form.go +++ b/internal/customer/form.go @@ -4,26 +4,26 @@ import "tm/pkg/response" // CreateCustomerForm represents the form for creating a new customer type CreateCustomerForm struct { - FullName *string `json:"full_name,omitempty" valid:"optional,length(2|100)" example:"User"` - Type string `json:"type" valid:"required,in(individual|company|government)" example:"individual"` - Role string `json:"role" valid:"required,in(admin|analyst)" example:"analyst"` - CompanyIDs []string `json:"company_ids,omitempty" valid:"optional"` - Username string `json:"username" valid:"required,alphanum,length(3|30)" example:"user"` - Email string `json:"email" valid:"required,email" example:"user@opplens.com"` - Password string `json:"password" valid:"required,length(8|128)" example:"User!1234"` - Phone *string `json:"phone,omitempty" valid:"optional,length(10|20)" example:"+1234567890"` + FullName *string `json:"full_name,omitempty" valid:"optional,length(2|100)" example:"User"` + Type string `json:"type" valid:"required,in(individual|company|government)" example:"individual"` + Role string `json:"role" valid:"required,in(admin|analyst)" example:"analyst"` + Companies []string `json:"companies,omitempty" valid:"optional"` + Username string `json:"username" valid:"required,alphanum,length(3|30)" example:"user"` + Email string `json:"email" valid:"required,email" example:"user@opplens.com"` + Password string `json:"password" valid:"required,length(8|128)" example:"User!1234"` + Phone *string `json:"phone,omitempty" valid:"optional,length(10|20)" example:"+1234567890"` } // UpdateCustomerForm represents the form for updating a customer type UpdateCustomerForm struct { - FullName *string `json:"full_name,omitempty" valid:"optional,length(2|100)" example:"User"` - Type string `json:"type" valid:"required,in(individual|company|government)" example:"individual"` - Role string `json:"role" valid:"required,in(admin|analyst)" example:"analyst"` - CompanyIDs []string `json:"company_ids,omitempty" valid:"optional"` - Username string `json:"username" valid:"required,alphanum,length(3|30)" example:"user"` - Email string `json:"email" valid:"required,email" example:"user@opplens.com"` - Password string `json:"password" valid:"required,length(8|128)" example:"User!1234"` - Phone *string `json:"phone,omitempty" valid:"optional,length(10|20)" example:"+1234567890"` + FullName *string `json:"full_name,omitempty" valid:"optional,length(2|100)" example:"User"` + Type string `json:"type" valid:"required,in(individual|company|government)" example:"individual"` + Role string `json:"role" valid:"required,in(admin|analyst)" example:"analyst"` + Companies []string `json:"companies,omitempty" valid:"optional"` + Username string `json:"username" valid:"required,alphanum,length(3|30)" example:"user"` + Email string `json:"email" valid:"required,email" example:"user@opplens.com"` + Password string `json:"password" valid:"required,length(8|128)" example:"User!1234"` + Phone *string `json:"phone,omitempty" valid:"optional,length(10|20)" example:"+1234567890"` } // CustomerStatusForm represents the form for suspending a customer @@ -56,7 +56,6 @@ type CustomerResponse struct { Type string `json:"type"` Role string `json:"role"` Phone *string `json:"phone"` - CompanyIDs []string `json:"company_ids"` UpdatedAt int64 `json:"updated_at"` CreatedAt int64 `json:"created_at"` LastLoginAt *int64 `json:"last_login_at"` @@ -74,7 +73,6 @@ func (c *Customer) ToResponse(companies []*CompanySummary) *CustomerResponse { Status: string(c.Status), Role: string(c.Role), Phone: c.Phone, - CompanyIDs: c.CompanyIDs, UpdatedAt: c.UpdatedAt, CreatedAt: c.CreatedAt, LastLoginAt: c.LastLoginAt, @@ -117,11 +115,11 @@ type AuthResponse struct { } type AssignCompaniesForm struct { - CompanyIDs []string `json:"company_ids" valid:"required"` + Companies []string `json:"companies" valid:"required"` } type RemoveCompaniesForm struct { - CompanyIDs []string `json:"company_ids" valid:"required"` + Companies []string `json:"companies" valid:"required"` } // RequestResetPasswordForm represents the form for requesting password reset diff --git a/internal/customer/service.go b/internal/customer/service.go index dc77816..0109ab1 100644 --- a/internal/customer/service.go +++ b/internal/customer/service.go @@ -79,9 +79,9 @@ func (s *customerService) Register(ctx context.Context, form *CreateCustomerForm } // Verify that all company IDs exist - var companyIDs []string - if len(form.CompanyIDs) > 0 { - for _, companyID := range form.CompanyIDs { + var Companies []string + if len(form.Companies) > 0 { + for _, companyID := range form.Companies { _, err := s.companyService.GetByID(ctx, companyID) if err != nil { s.logger.Error("Invalid company ID provided", map[string]interface{}{ @@ -91,7 +91,7 @@ func (s *customerService) Register(ctx context.Context, form *CreateCustomerForm return nil, errors.New("invalid company ID: " + companyID) } } - companyIDs = form.CompanyIDs + Companies = form.Companies } // Hash password @@ -105,15 +105,15 @@ func (s *customerService) Register(ctx context.Context, form *CreateCustomerForm // Create customer customer := &Customer{ - Type: CustomerType(form.Type), - Role: CustomerRole(form.Role), - Status: CustomerStatusActive, - CompanyIDs: companyIDs, - FullName: form.FullName, - Username: form.Username, - Email: form.Email, - Password: string(hashedPassword), - Phone: form.Phone, + Type: CustomerType(form.Type), + Role: CustomerRole(form.Role), + Status: CustomerStatusActive, + Companies: Companies, + FullName: form.FullName, + Username: form.Username, + Email: form.Email, + Password: string(hashedPassword), + Phone: form.Phone, } // Save to database @@ -131,7 +131,7 @@ func (s *customerService) Register(ctx context.Context, form *CreateCustomerForm "customer_id": customer.ID, "email": customer.Email, "type": customer.Type, - "company_ids": companyIDs, + "company_ids": Companies, }) go s.notification.SendEmail(ctx, customer.Email, fmt.Sprintf("Welcome to Tender Management\nUsername: %s\nPassword: %s", customer.Username, form.Password), customer.ID.Hex()) @@ -151,7 +151,7 @@ func (s *customerService) GetByID(ctx context.Context, id string) (*CustomerResp } var companies []*CompanySummary - if len(customer.CompanyIDs) > 0 { + if len(customer.Companies) > 0 { companies, err = s.loadCompaniesForCustomer(ctx, customer) if err != nil { s.logger.Error("Failed to load companies for customer", map[string]interface{}{ @@ -229,10 +229,10 @@ func (s *customerService) Update(ctx context.Context, id string, form *UpdateCus } // Handle company assignments - if len(form.CompanyIDs) > 0 { + if len(form.Companies) > 0 { // Verify that all company IDs exist - var validCompanyIDs []string - for _, companyID := range form.CompanyIDs { + var validCompanies []string + for _, companyID := range form.Companies { _, err := s.companyService.GetByID(ctx, companyID) if err != nil { s.logger.Error("Invalid company ID provided in update", map[string]interface{}{ @@ -241,9 +241,9 @@ func (s *customerService) Update(ctx context.Context, id string, form *UpdateCus }) return nil, errors.New("invalid company ID: " + companyID) } - validCompanyIDs = append(validCompanyIDs, companyID) + validCompanies = append(validCompanies, companyID) } - customer.CompanyIDs = validCompanyIDs + customer.Companies = validCompanies } if form.FullName != nil { @@ -337,7 +337,7 @@ func (s *customerService) UpdateStatus(ctx context.Context, id string, form *Upd } // AssignCompanies assigns companies to a customer -func (s *customerService) AssignCompanies(ctx context.Context, customerID string, companyIDs []string) error { +func (s *customerService) AssignCompanies(ctx context.Context, customerID string, Companies []string) error { // Get customer to check if exists customer, err := s.repository.GetByID(ctx, customerID) if err != nil { @@ -345,8 +345,8 @@ func (s *customerService) AssignCompanies(ctx context.Context, customerID string } // Verify companies exist and update customer's company IDs - var validCompanyIDs []string - for _, companyID := range companyIDs { + var validCompanies []string + for _, companyID := range Companies { _, err = s.companyService.GetByID(ctx, companyID) if err != nil { s.logger.Error("Company not found during assignment", map[string]interface{}{ @@ -356,11 +356,11 @@ func (s *customerService) AssignCompanies(ctx context.Context, customerID string }) continue // Skip invalid company IDs } - validCompanyIDs = append(validCompanyIDs, companyID) + validCompanies = append(validCompanies, companyID) } // Update customer's company IDs - customer.CompanyIDs = append(customer.CompanyIDs, validCompanyIDs...) + customer.Companies = append(customer.Companies, validCompanies...) customer.UpdatedAt = time.Now().Unix() err = s.repository.Update(ctx, customer) @@ -374,14 +374,14 @@ func (s *customerService) AssignCompanies(ctx context.Context, customerID string s.logger.Info("Companies assigned to customer successfully", map[string]interface{}{ "customer_id": customerID, - "company_ids": validCompanyIDs, + "company_ids": validCompanies, }) return nil } // RemoveCompaniesFromCustomer removes companies from a customer -func (s *customerService) RemoveCompanies(ctx context.Context, customerID string, companyIDs []string) error { +func (s *customerService) RemoveCompanies(ctx context.Context, customerID string, Companies []string) error { // Get customer to check if exists customer, err := s.repository.GetByID(ctx, customerID) if err != nil { @@ -389,22 +389,22 @@ func (s *customerService) RemoveCompanies(ctx context.Context, customerID string } // Remove company IDs from customer's list - var updatedCompanyIDs []string - for _, existingID := range customer.CompanyIDs { + var updatedCompanies []string + for _, existingID := range customer.Companies { shouldRemove := false - for _, removeID := range companyIDs { + for _, removeID := range Companies { if existingID == removeID { shouldRemove = true break } } if !shouldRemove { - updatedCompanyIDs = append(updatedCompanyIDs, existingID) + updatedCompanies = append(updatedCompanies, existingID) } } // Update customer's company IDs - customer.CompanyIDs = updatedCompanyIDs + customer.Companies = updatedCompanies customer.UpdatedAt = time.Now().Unix() err = s.repository.Update(ctx, customer) @@ -418,7 +418,7 @@ func (s *customerService) RemoveCompanies(ctx context.Context, customerID string s.logger.Info("Companies removed from customer successfully", map[string]interface{}{ "customer_id": customerID, - "company_ids": companyIDs, + "company_ids": Companies, }) return nil @@ -512,8 +512,8 @@ func (s *customerService) Login(ctx context.Context, form *LoginForm) (*AuthResp // Generate JWT tokens using authorization service companyID := "" - if len(customer.CompanyIDs) > 0 { - companyID = customer.CompanyIDs[0] // Use first company ID for JWT token + if len(customer.Companies) > 0 { + companyID = customer.Companies[0] // Use first company ID for JWT token } tokenPair, err := s.authService.GenerateTokenPair( @@ -1038,17 +1038,17 @@ func (s *customerService) isValidPassword(password string) bool { // loadCompaniesForCustomer loads company summaries for a customer func (s *customerService) loadCompaniesForCustomer(ctx context.Context, customer *Customer) ([]*CompanySummary, error) { - if len(customer.CompanyIDs) == 0 { + if len(customer.Companies) == 0 { return []*CompanySummary{}, nil } // Load companies in batch using the new GetCompaniesByIDs method - companies, err := s.companyService.GetByIDs(ctx, customer.CompanyIDs) + companies, err := s.companyService.GetByIDs(ctx, customer.Companies) if err != nil { s.logger.Error("Failed to load companies for customer", map[string]interface{}{ "error": err.Error(), "customer_id": customer.ID, - "company_ids": customer.CompanyIDs, + "company_ids": customer.Companies, }) return []*CompanySummary{}, err } @@ -1064,7 +1064,7 @@ func (s *customerService) loadCompaniesForCustomer(ctx context.Context, customer s.logger.Info("Companies loaded for customer", map[string]interface{}{ "customer_id": customer.ID, - "requested_count": len(customer.CompanyIDs), + "requested_count": len(customer.Companies), "loaded_count": len(companySummaries), })