Enhance API documentation and restructure routes for improved clarity
- Updated README.md to include comprehensive Swagger documentation details, highlighting new features and endpoint categories. - Introduced a new router structure to streamline route registration for admin and public endpoints, enhancing maintainability. - Updated health check endpoint documentation to reflect comprehensive server status information. - Enhanced customer and company management routes with improved descriptions and examples in Swagger. - Refactored customer and user handlers to remove obsolete route registrations, aligning with the new router structure. - Improved response handling in customer and user services to utilize string IDs consistently. - Updated validation rules and forms for customer management to support multiple company assignments. - Enhanced logging practices across services to ensure better traceability and error handling.
This commit is contained in:
+350
-24
@@ -5,11 +5,12 @@ import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"tm/internal/company"
|
||||
"tm/pkg/logger"
|
||||
|
||||
"tm/pkg/authorization"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
@@ -18,11 +19,13 @@ type Service interface {
|
||||
// Core customer operations
|
||||
CreateCustomer(ctx context.Context, form *CreateCustomerForm, createdBy *string) (*Customer, error)
|
||||
GetCustomerByID(ctx context.Context, id string) (*Customer, error)
|
||||
GetCustomerByIDWithCompanies(ctx context.Context, id string) (*CustomerResponse, error)
|
||||
UpdateCustomer(ctx context.Context, id string, form *UpdateCustomerForm, updatedBy *string) (*Customer, error)
|
||||
DeleteCustomer(ctx context.Context, id string, deletedBy *string) error
|
||||
|
||||
// Customer listing and search
|
||||
ListCustomers(ctx context.Context, form *ListCustomersForm) (*CustomerListResponse, error)
|
||||
ListCustomersWithCompanies(ctx context.Context, form *ListCustomersForm) (*CustomerListResponse, error)
|
||||
GetCustomersByCompanyID(ctx context.Context, companyID string, limit, offset int) ([]*Customer, int64, error)
|
||||
GetCustomersByType(ctx context.Context, customerType CustomerType, limit, offset int) ([]*Customer, int64, error)
|
||||
GetCustomersByStatus(ctx context.Context, status CustomerStatus, limit, offset int) ([]*Customer, int64, error)
|
||||
@@ -31,6 +34,10 @@ type Service interface {
|
||||
UpdateCustomerStatus(ctx context.Context, id string, form *UpdateCustomerStatusForm, updatedBy *string) error
|
||||
UpdateCustomerVerification(ctx context.Context, id string, form *UpdateCustomerVerificationForm, updatedBy *string) error
|
||||
|
||||
// Company assignments
|
||||
AssignCompaniesToCustomer(ctx context.Context, customerID string, companyIDs []string, updatedBy *string) error
|
||||
RemoveCompaniesFromCustomer(ctx context.Context, customerID string, companyIDs []string, updatedBy *string) error
|
||||
|
||||
// Mobile-specific operations (simplified)
|
||||
CreateCustomerMobile(ctx context.Context, form *CreateCustomerMobileForm, createdBy *string) (*Customer, error)
|
||||
UpdateCustomerMobile(ctx context.Context, id string, form *UpdateCustomerMobileForm, updatedBy *string) (*Customer, error)
|
||||
@@ -44,22 +51,25 @@ type Service interface {
|
||||
Login(ctx context.Context, form *LoginForm) (*AuthResponse, error)
|
||||
RefreshToken(ctx context.Context, refreshToken string) (*AuthResponse, error)
|
||||
GetProfile(ctx context.Context, customerID string) (*Customer, error)
|
||||
GetProfileWithCompanies(ctx context.Context, customerID string) (*CustomerResponse, error)
|
||||
Logout(ctx context.Context, customerID string, accessToken string) error
|
||||
}
|
||||
|
||||
// customerService implements the Service interface
|
||||
type customerService struct {
|
||||
repository Repository
|
||||
logger logger.Logger
|
||||
authService authorization.AuthorizationService
|
||||
repository Repository
|
||||
logger logger.Logger
|
||||
authService authorization.AuthorizationService
|
||||
companyService company.Service
|
||||
}
|
||||
|
||||
// NewCustomerService creates a new customer service
|
||||
func NewCustomerService(repository Repository, logger logger.Logger, authService authorization.AuthorizationService) Service {
|
||||
func NewCustomerService(repository Repository, logger logger.Logger, authService authorization.AuthorizationService, companyService company.Service) Service {
|
||||
return &customerService{
|
||||
repository: repository,
|
||||
logger: logger,
|
||||
authService: authService,
|
||||
repository: repository,
|
||||
logger: logger,
|
||||
authService: authService,
|
||||
companyService: companyService,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,10 +105,21 @@ func (s *customerService) CreateCustomer(ctx context.Context, form *CreateCustom
|
||||
}
|
||||
}
|
||||
|
||||
// Parse company ID if provided
|
||||
var companyID *string
|
||||
if form.CompanyID != nil {
|
||||
companyID = form.CompanyID
|
||||
// Prepare company assignments
|
||||
var companyIDs []string
|
||||
if len(form.CompanyIDs) > 0 {
|
||||
// Verify that all company IDs exist
|
||||
for _, companyID := range form.CompanyIDs {
|
||||
_, err := s.companyService.GetCompanyByID(ctx, companyID)
|
||||
if err != nil {
|
||||
s.logger.Error("Invalid company ID provided", map[string]interface{}{
|
||||
"error": err.Error(),
|
||||
"company_id": companyID,
|
||||
})
|
||||
return nil, errors.New("invalid company ID: " + companyID)
|
||||
}
|
||||
}
|
||||
companyIDs = form.CompanyIDs
|
||||
}
|
||||
|
||||
// Hash password
|
||||
@@ -114,7 +135,7 @@ func (s *customerService) CreateCustomer(ctx context.Context, form *CreateCustom
|
||||
customer := &Customer{
|
||||
Type: CustomerType(form.Type),
|
||||
Status: CustomerStatusPending,
|
||||
CompanyID: companyID,
|
||||
CompanyIDs: companyIDs,
|
||||
FirstName: form.FirstName,
|
||||
LastName: form.LastName,
|
||||
FullName: form.FullName,
|
||||
@@ -155,6 +176,7 @@ func (s *customerService) CreateCustomer(ctx context.Context, form *CreateCustom
|
||||
"customer_id": customer.ID,
|
||||
"email": customer.Email,
|
||||
"type": customer.Type,
|
||||
"company_ids": companyIDs,
|
||||
"created_by": *createdBy,
|
||||
})
|
||||
|
||||
@@ -180,6 +202,38 @@ func (s *customerService) GetCustomerByID(ctx context.Context, id string) (*Cust
|
||||
return customer, nil
|
||||
}
|
||||
|
||||
// GetCustomerByIDWithCompanies retrieves a customer by ID and loads associated companies
|
||||
func (s *customerService) GetCustomerByIDWithCompanies(ctx context.Context, id string) (*CustomerResponse, error) {
|
||||
customer, err := s.repository.GetByID(ctx, id)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get customer by ID with companies", map[string]interface{}{
|
||||
"error": err.Error(),
|
||||
"customer_id": id,
|
||||
})
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Load companies for the customer
|
||||
companies, err := s.loadCompaniesForCustomer(ctx, customer)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to load companies for customer", map[string]interface{}{
|
||||
"error": err.Error(),
|
||||
"customer_id": customer.ID,
|
||||
})
|
||||
// Continue without companies if loading fails
|
||||
companies = []*CompanySummary{}
|
||||
}
|
||||
|
||||
customerResponse := customer.ToResponseWithCompanies(companies)
|
||||
|
||||
s.logger.Info("Customer retrieved with companies successfully", map[string]interface{}{
|
||||
"customer_id": customer.ID,
|
||||
"email": customer.Email,
|
||||
})
|
||||
|
||||
return customerResponse, nil
|
||||
}
|
||||
|
||||
// UpdateCustomer updates a customer
|
||||
func (s *customerService) UpdateCustomer(ctx context.Context, id string, form *UpdateCustomerForm, updatedBy *string) (*Customer, error) {
|
||||
// Get existing customer
|
||||
@@ -233,8 +287,22 @@ func (s *customerService) UpdateCustomer(ctx context.Context, id string, form *U
|
||||
customer.Type = CustomerType(*form.Type)
|
||||
}
|
||||
|
||||
if form.CompanyID != nil {
|
||||
customer.CompanyID = form.CompanyID
|
||||
// Handle company assignments
|
||||
if len(form.CompanyIDs) > 0 {
|
||||
// Verify that all company IDs exist
|
||||
var validCompanyIDs []string
|
||||
for _, companyID := range form.CompanyIDs {
|
||||
_, err := s.companyService.GetCompanyByID(ctx, companyID)
|
||||
if err != nil {
|
||||
s.logger.Error("Invalid company ID provided in update", map[string]interface{}{
|
||||
"error": err.Error(),
|
||||
"company_id": companyID,
|
||||
})
|
||||
return nil, errors.New("invalid company ID: " + companyID)
|
||||
}
|
||||
validCompanyIDs = append(validCompanyIDs, companyID)
|
||||
}
|
||||
customer.CompanyIDs = validCompanyIDs
|
||||
}
|
||||
|
||||
if form.FirstName != nil {
|
||||
@@ -411,6 +479,79 @@ func (s *customerService) ListCustomers(ctx context.Context, form *ListCustomers
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ListCustomersWithCompanies lists customers with search and filters, including companies
|
||||
func (s *customerService) ListCustomersWithCompanies(ctx context.Context, form *ListCustomersForm) (*CustomerListResponse, error) {
|
||||
// Set defaults
|
||||
limit := 20
|
||||
if form.Limit != nil {
|
||||
limit = *form.Limit
|
||||
}
|
||||
|
||||
offset := 0
|
||||
if form.Offset != nil {
|
||||
offset = *form.Offset
|
||||
}
|
||||
|
||||
search := ""
|
||||
if form.Search != nil {
|
||||
search = *form.Search
|
||||
}
|
||||
|
||||
sortBy := "created_at"
|
||||
if form.SortBy != nil {
|
||||
sortBy = *form.SortBy
|
||||
}
|
||||
|
||||
sortOrder := "desc"
|
||||
if form.SortOrder != nil {
|
||||
sortOrder = *form.SortOrder
|
||||
}
|
||||
|
||||
// Parse company ID if provided
|
||||
var companyID *string
|
||||
if form.CompanyID != nil {
|
||||
companyID = form.CompanyID
|
||||
}
|
||||
|
||||
// Get customers
|
||||
customers, err := s.repository.Search(ctx, search, form.Type, form.Status, companyID, form.Industry, form.IsVerified, form.IsCompliant, form.Language, form.Currency, limit, offset, sortBy, sortOrder)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to list customers with companies", map[string]interface{}{
|
||||
"error": err.Error(),
|
||||
})
|
||||
return nil, errors.New("failed to list customers with companies")
|
||||
}
|
||||
|
||||
// Convert to responses
|
||||
var customerResponses []*CustomerResponse
|
||||
for _, customer := range customers {
|
||||
// Load companies for the customer
|
||||
companies, err := s.loadCompaniesForCustomer(ctx, customer)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to load companies for customer in list", map[string]interface{}{
|
||||
"error": err.Error(),
|
||||
"customer_id": customer.ID,
|
||||
})
|
||||
// Continue without companies if loading fails
|
||||
companies = []*CompanySummary{}
|
||||
}
|
||||
customerResponse := customer.ToResponseWithCompanies(companies)
|
||||
customerResponses = append(customerResponses, customerResponse)
|
||||
}
|
||||
|
||||
// TODO: Implement proper count for pagination metadata
|
||||
total := int64(len(customers)) // This should be a separate count query
|
||||
totalPages := (total + int64(limit) - 1) / int64(limit)
|
||||
|
||||
return &CustomerListResponse{
|
||||
Customers: customerResponses,
|
||||
Total: total,
|
||||
Limit: limit,
|
||||
Offset: offset,
|
||||
TotalPages: int(totalPages),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetCustomersByCompanyID retrieves customers by company ID with pagination
|
||||
func (s *customerService) GetCustomersByCompanyID(ctx context.Context, companyID string, limit, offset int) ([]*Customer, int64, error) {
|
||||
customers, err := s.repository.GetByCompanyID(ctx, companyID, limit, offset)
|
||||
@@ -546,6 +687,98 @@ func (s *customerService) UpdateCustomerVerification(ctx context.Context, id str
|
||||
return nil
|
||||
}
|
||||
|
||||
// AssignCompaniesToCustomer assigns companies to a customer
|
||||
func (s *customerService) AssignCompaniesToCustomer(ctx context.Context, customerID string, companyIDs []string, updatedBy *string) error {
|
||||
// Get customer to check if exists
|
||||
customer, err := s.repository.GetByID(ctx, customerID)
|
||||
if err != nil {
|
||||
return errors.New("customer not found")
|
||||
}
|
||||
|
||||
// Verify companies exist and update customer's company IDs
|
||||
var validCompanyIDs []string
|
||||
for _, companyID := range companyIDs {
|
||||
_, err = s.companyService.GetCompanyByID(ctx, companyID)
|
||||
if err != nil {
|
||||
s.logger.Error("Company not found during assignment", map[string]interface{}{
|
||||
"error": err.Error(),
|
||||
"customer_id": customerID,
|
||||
"company_id": companyID,
|
||||
})
|
||||
continue // Skip invalid company IDs
|
||||
}
|
||||
validCompanyIDs = append(validCompanyIDs, companyID)
|
||||
}
|
||||
|
||||
// Update customer's company IDs
|
||||
customer.CompanyIDs = append(customer.CompanyIDs, validCompanyIDs...)
|
||||
customer.UpdatedBy = updatedBy
|
||||
customer.UpdatedAt = time.Now().Unix()
|
||||
|
||||
err = s.repository.Update(ctx, customer)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to update customer with company assignments", map[string]interface{}{
|
||||
"error": err.Error(),
|
||||
"customer_id": customerID,
|
||||
})
|
||||
return errors.New("failed to assign companies to customer")
|
||||
}
|
||||
|
||||
s.logger.Info("Companies assigned to customer successfully", map[string]interface{}{
|
||||
"customer_id": customerID,
|
||||
"company_ids": validCompanyIDs,
|
||||
"updated_by": updatedBy,
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveCompaniesFromCustomer removes companies from a customer
|
||||
func (s *customerService) RemoveCompaniesFromCustomer(ctx context.Context, customerID string, companyIDs []string, updatedBy *string) error {
|
||||
// Get customer to check if exists
|
||||
customer, err := s.repository.GetByID(ctx, customerID)
|
||||
if err != nil {
|
||||
return errors.New("customer not found")
|
||||
}
|
||||
|
||||
// Remove company IDs from customer's list
|
||||
var updatedCompanyIDs []string
|
||||
for _, existingID := range customer.CompanyIDs {
|
||||
shouldRemove := false
|
||||
for _, removeID := range companyIDs {
|
||||
if existingID == removeID {
|
||||
shouldRemove = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !shouldRemove {
|
||||
updatedCompanyIDs = append(updatedCompanyIDs, existingID)
|
||||
}
|
||||
}
|
||||
|
||||
// Update customer's company IDs
|
||||
customer.CompanyIDs = updatedCompanyIDs
|
||||
customer.UpdatedBy = updatedBy
|
||||
customer.UpdatedAt = time.Now().Unix()
|
||||
|
||||
err = s.repository.Update(ctx, customer)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to update customer after removing company assignments", map[string]interface{}{
|
||||
"error": err.Error(),
|
||||
"customer_id": customerID,
|
||||
})
|
||||
return errors.New("failed to remove companies from customer")
|
||||
}
|
||||
|
||||
s.logger.Info("Companies removed from customer successfully", map[string]interface{}{
|
||||
"customer_id": customerID,
|
||||
"company_ids": companyIDs,
|
||||
"updated_by": updatedBy,
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateCustomerMobile creates a new customer via mobile app (simplified)
|
||||
func (s *customerService) CreateCustomerMobile(ctx context.Context, form *CreateCustomerMobileForm, createdBy *string) (*Customer, error) {
|
||||
// Check if email already exists
|
||||
@@ -554,10 +787,28 @@ func (s *customerService) CreateCustomerMobile(ctx context.Context, form *Create
|
||||
return nil, errors.New("customer with this email already exists")
|
||||
}
|
||||
|
||||
// Prepare company assignments
|
||||
var companyIDs []string
|
||||
if len(form.CompanyIDs) > 0 {
|
||||
// Verify that all company IDs exist
|
||||
for _, companyID := range form.CompanyIDs {
|
||||
_, err := s.companyService.GetCompanyByID(ctx, companyID)
|
||||
if err != nil {
|
||||
s.logger.Error("Invalid company ID provided in mobile form", map[string]interface{}{
|
||||
"error": err.Error(),
|
||||
"company_id": companyID,
|
||||
})
|
||||
return nil, errors.New("invalid company ID: " + companyID)
|
||||
}
|
||||
}
|
||||
companyIDs = form.CompanyIDs
|
||||
}
|
||||
|
||||
// Create customer with mobile form
|
||||
customer := &Customer{
|
||||
Type: CustomerType(form.Type),
|
||||
Status: CustomerStatusActive,
|
||||
CompanyIDs: companyIDs,
|
||||
FirstName: form.FirstName,
|
||||
LastName: form.LastName,
|
||||
FullName: form.FullName,
|
||||
@@ -566,7 +817,6 @@ func (s *customerService) CreateCustomerMobile(ctx context.Context, form *Create
|
||||
Password: "", // Will be set after hashing
|
||||
Phone: form.Phone,
|
||||
Mobile: form.Mobile,
|
||||
CompanyID: form.CompanyID,
|
||||
Industry: form.Industry,
|
||||
IsVerified: false,
|
||||
IsCompliant: false,
|
||||
@@ -602,6 +852,7 @@ func (s *customerService) CreateCustomerMobile(ctx context.Context, form *Create
|
||||
"customer_id": customer.ID,
|
||||
"email": customer.Email,
|
||||
"type": customer.Type,
|
||||
"company_ids": companyIDs,
|
||||
"created_by": *createdBy,
|
||||
})
|
||||
|
||||
@@ -637,8 +888,22 @@ func (s *customerService) UpdateCustomerMobile(ctx context.Context, id string, f
|
||||
customer.Mobile = form.Mobile
|
||||
}
|
||||
|
||||
if form.CompanyID != nil {
|
||||
customer.CompanyID = form.CompanyID
|
||||
// Handle company assignments
|
||||
if len(form.CompanyIDs) > 0 {
|
||||
// Verify that all company IDs exist
|
||||
var validCompanyIDs []string
|
||||
for _, companyID := range form.CompanyIDs {
|
||||
_, err := s.companyService.GetCompanyByID(ctx, companyID)
|
||||
if err != nil {
|
||||
s.logger.Error("Invalid company ID provided in mobile update", map[string]interface{}{
|
||||
"error": err.Error(),
|
||||
"company_id": companyID,
|
||||
})
|
||||
return nil, errors.New("invalid company ID: " + companyID)
|
||||
}
|
||||
validCompanyIDs = append(validCompanyIDs, companyID)
|
||||
}
|
||||
customer.CompanyIDs = validCompanyIDs
|
||||
}
|
||||
|
||||
if form.Industry != nil {
|
||||
@@ -661,6 +926,7 @@ func (s *customerService) UpdateCustomerMobile(ctx context.Context, id string, f
|
||||
s.logger.Info("Customer updated via mobile successfully", map[string]interface{}{
|
||||
"customer_id": customer.ID,
|
||||
"email": customer.Email,
|
||||
"company_ids": customer.CompanyIDs,
|
||||
"updated_by": *updatedBy,
|
||||
})
|
||||
|
||||
@@ -783,12 +1049,12 @@ func (s *customerService) Login(ctx context.Context, form *LoginForm) (*AuthResp
|
||||
|
||||
// Generate JWT tokens using authorization service
|
||||
companyID := ""
|
||||
if customer.CompanyID != nil {
|
||||
companyID = *customer.CompanyID
|
||||
if len(customer.CompanyIDs) > 0 {
|
||||
companyID = customer.CompanyIDs[0] // Use first company ID for JWT token
|
||||
}
|
||||
|
||||
tokenPair, err := s.authService.GenerateTokenPair(
|
||||
customer.ID,
|
||||
customer.ID.Hex(),
|
||||
customer.Email,
|
||||
"customer", // Role for customers
|
||||
companyID,
|
||||
@@ -847,7 +1113,7 @@ func (s *customerService) RefreshToken(ctx context.Context, refreshToken string)
|
||||
}
|
||||
|
||||
// Get customer information
|
||||
customerID, err := uuid.Parse(validationResult.Claims.UserID)
|
||||
customerID, err := primitive.ObjectIDFromHex(validationResult.Claims.UserID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to parse customer ID from token", map[string]interface{}{
|
||||
"error": err.Error(),
|
||||
@@ -855,11 +1121,11 @@ func (s *customerService) RefreshToken(ctx context.Context, refreshToken string)
|
||||
return nil, errors.New("invalid token format")
|
||||
}
|
||||
|
||||
customer, err := s.repository.GetByID(ctx, customerID.String())
|
||||
customer, err := s.repository.GetByID(ctx, customerID.Hex())
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get customer for token refresh", map[string]interface{}{
|
||||
"error": err.Error(),
|
||||
"customer_id": customerID.String(),
|
||||
"customer_id": customerID.Hex(),
|
||||
})
|
||||
return nil, errors.New("customer not found")
|
||||
}
|
||||
@@ -905,6 +1171,42 @@ func (s *customerService) GetProfile(ctx context.Context, customerID string) (*C
|
||||
return customer, nil
|
||||
}
|
||||
|
||||
// GetProfileWithCompanies retrieves customer profile information including companies
|
||||
func (s *customerService) GetProfileWithCompanies(ctx context.Context, customerID string) (*CustomerResponse, error) {
|
||||
s.logger.Info("Getting customer profile with companies", map[string]interface{}{
|
||||
"customer_id": customerID,
|
||||
})
|
||||
|
||||
customer, err := s.repository.GetByID(ctx, customerID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get customer profile with companies", map[string]interface{}{
|
||||
"error": err.Error(),
|
||||
"customer_id": customerID,
|
||||
})
|
||||
return nil, errors.New("customer not found")
|
||||
}
|
||||
|
||||
// Load companies for the customer
|
||||
companies, err := s.loadCompaniesForCustomer(ctx, customer)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to load companies for customer profile", map[string]interface{}{
|
||||
"error": err.Error(),
|
||||
"customer_id": customer.ID,
|
||||
})
|
||||
// Continue without companies if loading fails
|
||||
companies = []*CompanySummary{}
|
||||
}
|
||||
|
||||
customerResponse := customer.ToResponseWithCompanies(companies)
|
||||
|
||||
s.logger.Info("Customer profile retrieved with companies successfully", map[string]interface{}{
|
||||
"customer_id": customerID,
|
||||
"customer_type": string(customer.Type),
|
||||
})
|
||||
|
||||
return customerResponse, nil
|
||||
}
|
||||
|
||||
// Logout handles customer logout
|
||||
func (s *customerService) Logout(ctx context.Context, customerID string, accessToken string) error {
|
||||
s.logger.Info("Customer logout", map[string]interface{}{
|
||||
@@ -983,3 +1285,27 @@ func (s *customerService) getDefaultTimezone(timezone *string) string {
|
||||
}
|
||||
return "UTC"
|
||||
}
|
||||
|
||||
// loadCompaniesForCustomer loads company summaries for a customer
|
||||
func (s *customerService) loadCompaniesForCustomer(ctx context.Context, customer *Customer) ([]*CompanySummary, error) {
|
||||
var companies []*CompanySummary
|
||||
|
||||
// Load companies from CompanyIDs
|
||||
for _, companyID := range customer.CompanyIDs {
|
||||
company, err := s.companyService.GetCompanyByID(ctx, companyID)
|
||||
if err != nil {
|
||||
s.logger.Warn("Failed to load company for customer", map[string]interface{}{
|
||||
"error": err.Error(),
|
||||
"customer_id": customer.ID,
|
||||
"company_id": companyID,
|
||||
})
|
||||
continue // Skip companies that can't be loaded
|
||||
}
|
||||
companies = append(companies, &CompanySummary{
|
||||
ID: company.ID.Hex(),
|
||||
Name: company.Name,
|
||||
})
|
||||
}
|
||||
|
||||
return companies, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user