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:
@@ -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": {
|
"/admin/v1/health": {
|
||||||
"get": {
|
"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.",
|
"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.",
|
||||||
|
|||||||
@@ -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": {
|
"/admin/v1/health": {
|
||||||
"get": {
|
"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.",
|
"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.",
|
||||||
|
|||||||
@@ -2546,47 +2546,6 @@ paths:
|
|||||||
summary: Verify customer
|
summary: Verify customer
|
||||||
tags:
|
tags:
|
||||||
- Admin-Customers
|
- 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}:
|
/admin/v1/customers/company/{companyId}:
|
||||||
get:
|
get:
|
||||||
consumes:
|
consumes:
|
||||||
|
|||||||
@@ -73,9 +73,7 @@ func RegisterAdminRoutes(e *echo.Echo, userHandler *user.Handler, companyHandler
|
|||||||
customersGP.Use(userHandler.AuthMiddleware())
|
customersGP.Use(userHandler.AuthMiddleware())
|
||||||
customersGP.POST("", customerHandler.CreateCustomer)
|
customersGP.POST("", customerHandler.CreateCustomer)
|
||||||
customersGP.GET("", customerHandler.ListCustomers)
|
customersGP.GET("", customerHandler.ListCustomers)
|
||||||
customersGP.GET("/with-companies", customerHandler.ListCustomersWithCompanies)
|
|
||||||
customersGP.GET("/:id", customerHandler.GetCustomerByID)
|
customersGP.GET("/:id", customerHandler.GetCustomerByID)
|
||||||
customersGP.GET("/:id/with-companies", customerHandler.GetCustomerByIDWithCompanies)
|
|
||||||
customersGP.PUT("/:id", customerHandler.UpdateCustomer)
|
customersGP.PUT("/:id", customerHandler.UpdateCustomer)
|
||||||
customersGP.DELETE("/:id", customerHandler.DeleteCustomer)
|
customersGP.DELETE("/:id", customerHandler.DeleteCustomer)
|
||||||
customersGP.PATCH("/:id/status", customerHandler.UpdateCustomerStatus)
|
customersGP.PATCH("/:id/status", customerHandler.UpdateCustomerStatus)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
mongopkg "tm/pkg/mongo"
|
mongopkg "tm/pkg/mongo"
|
||||||
|
|
||||||
"go.mongodb.org/mongo-driver/bson"
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Repository defines the interface for company data operations
|
// Repository defines the interface for company data operations
|
||||||
@@ -17,6 +18,7 @@ type Repository interface {
|
|||||||
GetByName(ctx context.Context, name string) (*Company, error)
|
GetByName(ctx context.Context, name string) (*Company, error)
|
||||||
GetByRegistrationNumber(ctx context.Context, registrationNumber string) (*Company, error)
|
GetByRegistrationNumber(ctx context.Context, registrationNumber string) (*Company, error)
|
||||||
GetByTaxID(ctx context.Context, taxID 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
|
Update(ctx context.Context, company *Company) error
|
||||||
Delete(ctx context.Context, id string) error
|
Delete(ctx context.Context, id string) error
|
||||||
List(ctx context.Context, limit, offset int) ([]*Company, 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
|
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
|
// Update updates a company
|
||||||
func (r *companyRepository) Update(ctx context.Context, company *Company) error {
|
func (r *companyRepository) Update(ctx context.Context, company *Company) error {
|
||||||
// Set updated timestamp using Unix timestamp
|
// Set updated timestamp using Unix timestamp
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ type Service interface {
|
|||||||
// Core company operations
|
// Core company operations
|
||||||
CreateCompany(ctx context.Context, form *CreateCompanyForm, createdBy *string) (*Company, error)
|
CreateCompany(ctx context.Context, form *CreateCompanyForm, createdBy *string) (*Company, error)
|
||||||
GetCompanyByID(ctx context.Context, id 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)
|
UpdateCompany(ctx context.Context, id string, form *UpdateCompanyForm, updatedBy *string) (*Company, error)
|
||||||
DeleteCompany(ctx context.Context, id string, deletedBy *string) 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
|
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
|
// UpdateCompany updates a company
|
||||||
func (s *companyService) UpdateCompany(ctx context.Context, id string, form *UpdateCompanyForm, updatedBy *string) (*Company, error) {
|
func (s *companyService) UpdateCompany(ctx context.Context, id string, form *UpdateCompanyForm, updatedBy *string) (*Company, error) {
|
||||||
// Get existing company
|
// Get existing company
|
||||||
|
|||||||
@@ -84,33 +84,6 @@ func (h *Handler) CreateCustomer(c echo.Context) error {
|
|||||||
func (h *Handler) GetCustomerByID(c echo.Context) error {
|
func (h *Handler) GetCustomerByID(c echo.Context) error {
|
||||||
idStr := c.Param("id")
|
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)
|
customer, err := h.service.GetCustomerByIDWithCompanies(c.Request().Context(), idStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err.Error() == "customer not found" {
|
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())
|
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 {
|
if err != nil {
|
||||||
return response.InternalServerError(c, "Failed to list customers")
|
return response.InternalServerError(c, "Failed to list customers")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1280,24 +1280,35 @@ func (s *customerService) getDefaultTimezone(timezone *string) string {
|
|||||||
|
|
||||||
// loadCompaniesForCustomer loads company summaries for a customer
|
// loadCompaniesForCustomer loads company summaries for a customer
|
||||||
func (s *customerService) loadCompaniesForCustomer(ctx context.Context, customer *Customer) ([]*CompanySummary, error) {
|
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
|
// Load companies in batch using the new GetCompaniesByIDs method
|
||||||
for _, companyID := range customer.CompanyIDs {
|
companies, err := s.companyService.GetCompaniesByIDs(ctx, customer.CompanyIDs)
|
||||||
company, err := s.companyService.GetCompanyByID(ctx, companyID)
|
if err != nil {
|
||||||
if err != nil {
|
s.logger.Error("Failed to load companies for customer", map[string]interface{}{
|
||||||
s.logger.Warn("Failed to load company for customer", map[string]interface{}{
|
"error": err.Error(),
|
||||||
"error": err.Error(),
|
"customer_id": customer.ID,
|
||||||
"customer_id": customer.ID,
|
"company_ids": customer.CompanyIDs,
|
||||||
"company_id": companyID,
|
})
|
||||||
})
|
return []*CompanySummary{}, err
|
||||||
continue // Skip companies that can't be loaded
|
}
|
||||||
}
|
|
||||||
companies = append(companies, &CompanySummary{
|
// Convert to CompanySummary format
|
||||||
|
var companySummaries []*CompanySummary
|
||||||
|
for _, company := range companies {
|
||||||
|
companySummaries = append(companySummaries, &CompanySummary{
|
||||||
ID: company.ID.Hex(),
|
ID: company.ID.Hex(),
|
||||||
Name: company.Name,
|
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
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user