Remove obsolete customer endpoint and update related documentation

- Deleted the `/admin/v1/customers/{id}/with-companies` endpoint from the API documentation and Swagger files to streamline the API structure.
- Updated the router to remove the corresponding route registration for the deprecated endpoint.
- Enhanced the company repository and service to support batch retrieval of companies by IDs, improving efficiency in data handling.
- Adjusted customer service methods to utilize the new batch retrieval functionality for loading companies associated with customers.
- Improved logging practices to provide better traceability for company retrieval operations.
This commit is contained in:
n.nakhostin
2025-08-11 19:12:31 +03:30
parent a1db2a9790
commit e3ee3d64ce
8 changed files with 100 additions and 219 deletions
-67
View File
@@ -2840,73 +2840,6 @@ const docTemplate = `{
}
}
},
"/admin/v1/customers/{id}/with-companies": {
"get": {
"security": [
{
"BearerAuth": []
}
],
"description": "Retrieve detailed customer information by customer ID including assigned companies",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Admin-Customers"
],
"summary": "Get customer by ID with companies",
"parameters": [
{
"type": "string",
"description": "Customer ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "Customer retrieved successfully",
"schema": {
"allOf": [
{
"$ref": "#/definitions/response.APIResponse"
},
{
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/customer.CustomerResponse"
}
}
}
]
}
},
"400": {
"description": "Bad request - Invalid customer ID",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
},
"404": {
"description": "Not found - Customer not found",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
},
"500": {
"description": "Internal server error",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
}
}
}
},
"/admin/v1/health": {
"get": {
"description": "Get comprehensive server health status including system information, dependencies status, and performance metrics. This endpoint is used for monitoring and load balancer health checks.",
-67
View File
@@ -2834,73 +2834,6 @@
}
}
},
"/admin/v1/customers/{id}/with-companies": {
"get": {
"security": [
{
"BearerAuth": []
}
],
"description": "Retrieve detailed customer information by customer ID including assigned companies",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Admin-Customers"
],
"summary": "Get customer by ID with companies",
"parameters": [
{
"type": "string",
"description": "Customer ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "Customer retrieved successfully",
"schema": {
"allOf": [
{
"$ref": "#/definitions/response.APIResponse"
},
{
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/customer.CustomerResponse"
}
}
}
]
}
},
"400": {
"description": "Bad request - Invalid customer ID",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
},
"404": {
"description": "Not found - Customer not found",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
},
"500": {
"description": "Internal server error",
"schema": {
"$ref": "#/definitions/response.APIResponse"
}
}
}
}
},
"/admin/v1/health": {
"get": {
"description": "Get comprehensive server health status including system information, dependencies status, and performance metrics. This endpoint is used for monitoring and load balancer health checks.",
-41
View File
@@ -2546,47 +2546,6 @@ paths:
summary: Verify customer
tags:
- Admin-Customers
/admin/v1/customers/{id}/with-companies:
get:
consumes:
- application/json
description: Retrieve detailed customer information by customer ID including
assigned companies
parameters:
- description: Customer ID
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: Customer retrieved successfully
schema:
allOf:
- $ref: '#/definitions/response.APIResponse'
- properties:
data:
$ref: '#/definitions/customer.CustomerResponse'
type: object
"400":
description: Bad request - Invalid customer ID
schema:
$ref: '#/definitions/response.APIResponse'
"404":
description: Not found - Customer not found
schema:
$ref: '#/definitions/response.APIResponse'
"500":
description: Internal server error
schema:
$ref: '#/definitions/response.APIResponse'
security:
- BearerAuth: []
summary: Get customer by ID with companies
tags:
- Admin-Customers
/admin/v1/customers/company/{companyId}:
get:
consumes:
-2
View File
@@ -73,9 +73,7 @@ func RegisterAdminRoutes(e *echo.Echo, userHandler *user.Handler, companyHandler
customersGP.Use(userHandler.AuthMiddleware())
customersGP.POST("", customerHandler.CreateCustomer)
customersGP.GET("", customerHandler.ListCustomers)
customersGP.GET("/with-companies", customerHandler.ListCustomersWithCompanies)
customersGP.GET("/:id", customerHandler.GetCustomerByID)
customersGP.GET("/:id/with-companies", customerHandler.GetCustomerByIDWithCompanies)
customersGP.PUT("/:id", customerHandler.UpdateCustomer)
customersGP.DELETE("/:id", customerHandler.DeleteCustomer)
customersGP.PATCH("/:id/status", customerHandler.UpdateCustomerStatus)
+50
View File
@@ -8,6 +8,7 @@ import (
mongopkg "tm/pkg/mongo"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
)
// Repository defines the interface for company data operations
@@ -17,6 +18,7 @@ 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)
GetByIDs(ctx context.Context, ids []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)
@@ -184,6 +186,54 @@ func (r *companyRepository) GetByTaxID(ctx context.Context, taxID string) (*Comp
return company, nil
}
// GetByIDs retrieves multiple companies by their IDs
func (r *companyRepository) GetByIDs(ctx context.Context, ids []string) ([]*Company, error) {
if len(ids) == 0 {
return []*Company{}, nil
}
// Convert string IDs to ObjectIDs for MongoDB query
objectIDs := make([]interface{}, len(ids))
for i, id := range ids {
objectID, err := primitive.ObjectIDFromHex(id)
if err != nil {
r.logger.Warn("Invalid company ID format", map[string]interface{}{
"id": id,
"error": err.Error(),
})
continue
}
objectIDs[i] = objectID
}
if len(objectIDs) == 0 {
return []*Company{}, nil
}
filter := bson.M{"_id": bson.M{"$in": objectIDs}}
companies, err := r.ormRepo.FindMany(ctx, filter, len(ids))
if err != nil {
r.logger.Error("Failed to get companies by IDs", map[string]interface{}{
"error": err.Error(),
"ids": ids,
})
return nil, err
}
// Convert to pointer slice
result := make([]*Company, len(companies))
for i := range companies {
result[i] = &companies[i]
}
r.logger.Info("Retrieved companies by IDs", map[string]interface{}{
"requested_count": len(ids),
"found_count": len(result),
})
return result, nil
}
// Update updates a company
func (r *companyRepository) Update(ctx context.Context, company *Company) error {
// Set updated timestamp using Unix timestamp
+24
View File
@@ -13,6 +13,7 @@ type Service interface {
// Core company operations
CreateCompany(ctx context.Context, form *CreateCompanyForm, createdBy *string) (*Company, error)
GetCompanyByID(ctx context.Context, id string) (*Company, error)
GetCompaniesByIDs(ctx context.Context, ids []string) ([]*Company, error)
UpdateCompany(ctx context.Context, id string, form *UpdateCompanyForm, updatedBy *string) (*Company, error)
DeleteCompany(ctx context.Context, id string, deletedBy *string) error
@@ -144,6 +145,29 @@ func (s *companyService) GetCompanyByID(ctx context.Context, id string) (*Compan
return company, nil
}
// GetCompaniesByIDs retrieves multiple companies by their IDs
func (s *companyService) GetCompaniesByIDs(ctx context.Context, ids []string) ([]*Company, error) {
if len(ids) == 0 {
return []*Company{}, nil
}
companies, err := s.repository.GetByIDs(ctx, ids)
if err != nil {
s.logger.Error("Failed to get companies by IDs", map[string]interface{}{
"error": err.Error(),
"ids": ids,
})
return nil, err
}
s.logger.Info("Companies retrieved successfully", map[string]interface{}{
"requested_count": len(ids),
"found_count": len(companies),
})
return companies, nil
}
// UpdateCompany updates a company
func (s *companyService) UpdateCompany(ctx context.Context, id string, form *UpdateCompanyForm, updatedBy *string) (*Company, error) {
// Get existing company
+1 -28
View File
@@ -84,33 +84,6 @@ func (h *Handler) CreateCustomer(c echo.Context) error {
func (h *Handler) GetCustomerByID(c echo.Context) error {
idStr := c.Param("id")
customer, err := h.service.GetCustomerByID(c.Request().Context(), idStr)
if err != nil {
if err.Error() == "customer not found" {
return response.NotFound(c, "Customer not found")
}
return response.InternalServerError(c, "Failed to get customer")
}
return response.Success(c, customer.ToResponse(), "Customer retrieved successfully")
}
// GetCustomerByIDWithCompanies retrieves a customer by ID with companies (Web Panel)
// @Summary Get customer by ID with companies
// @Description Retrieve detailed customer information by customer ID including assigned companies
// @Tags Admin-Customers
// @Accept json
// @Produce json
// @Param id path string true "Customer ID"
// @Success 200 {object} response.APIResponse{data=CustomerResponse} "Customer retrieved successfully"
// @Failure 400 {object} response.APIResponse "Bad request - Invalid customer ID"
// @Failure 404 {object} response.APIResponse "Not found - Customer not found"
// @Failure 500 {object} response.APIResponse "Internal server error"
// @Security BearerAuth
// @Router /admin/v1/customers/{id}/with-companies [get]
func (h *Handler) GetCustomerByIDWithCompanies(c echo.Context) error {
idStr := c.Param("id")
customer, err := h.service.GetCustomerByIDWithCompanies(c.Request().Context(), idStr)
if err != nil {
if err.Error() == "customer not found" {
@@ -234,7 +207,7 @@ func (h *Handler) ListCustomers(c echo.Context) error {
return response.ValidationError(c, "Invalid request data", err.Error())
}
result, err := h.service.ListCustomers(c.Request().Context(), form)
result, err := h.service.ListCustomersWithCompanies(c.Request().Context(), form)
if err != nil {
return response.InternalServerError(c, "Failed to list customers")
}
+25 -14
View File
@@ -1280,24 +1280,35 @@ func (s *customerService) getDefaultTimezone(timezone *string) string {
// loadCompaniesForCustomer loads company summaries for a customer
func (s *customerService) loadCompaniesForCustomer(ctx context.Context, customer *Customer) ([]*CompanySummary, error) {
var companies []*CompanySummary
if len(customer.CompanyIDs) == 0 {
return []*CompanySummary{}, nil
}
// 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{
// Load companies in batch using the new GetCompaniesByIDs method
companies, err := s.companyService.GetCompaniesByIDs(ctx, customer.CompanyIDs)
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,
})
return []*CompanySummary{}, err
}
// Convert to CompanySummary format
var companySummaries []*CompanySummary
for _, company := range companies {
companySummaries = append(companySummaries, &CompanySummary{
ID: company.ID.Hex(),
Name: company.Name,
})
}
return companies, nil
s.logger.Info("Companies loaded for customer", map[string]interface{}{
"customer_id": customer.ID,
"requested_count": len(customer.CompanyIDs),
"loaded_count": len(companySummaries),
})
return companySummaries, nil
}