package company import ( "strconv" "tm/internal/user" "tm/pkg/logger" "tm/pkg/response" "github.com/labstack/echo/v4" ) // Handler handles HTTP requests for company operations type Handler struct { service Service userHandler *user.Handler logger logger.Logger } // NewHandler creates a new company handler func NewHandler(service Service, userHandler *user.Handler, logger logger.Logger) *Handler { return &Handler{ service: service, userHandler: userHandler, logger: logger, } } // RegisterRoutes registers company routes func (h *Handler) RegisterRoutes(e *echo.Echo) { // Admin routes for web panel adminV1 := e.Group("/admin/v1/companies") adminV1.Use(h.userHandler.AuthMiddleware()) adminV1.POST("", h.CreateCompany) adminV1.GET("", h.ListCompanies) adminV1.GET("/:id", h.GetCompany) adminV1.PUT("/:id", h.UpdateCompany) adminV1.DELETE("/:id", h.DeleteCompany) adminV1.GET("/search", h.SearchCompanies) adminV1.PATCH("/:id/status", h.UpdateCompanyStatus) adminV1.PATCH("/:id/verification", h.UpdateCompanyVerification) adminV1.PUT("/:id/tags", h.UpdateCompanyTags) adminV1.POST("/:id/tags/add", h.AddTags) adminV1.POST("/:id/tags/remove", h.RemoveTags) adminV1.POST("/:id/verify", h.VerifyCompany) adminV1.POST("/:id/suspend", h.SuspendCompany) adminV1.POST("/:id/activate", h.ActivateCompany) adminV1.GET("/stats", h.GetCompanyStats) adminV1.GET("/type/:type", h.GetCompaniesByType) adminV1.GET("/status/:status", h.GetCompaniesByStatus) adminV1.GET("/industry/:industry", h.GetCompaniesByIndustry) } // Web Panel Endpoints // CreateCompany creates a new company (Web Panel) // @Summary Create a new company // @Description Create a new company with comprehensive information including business details, address, tags, and customer assignment. This endpoint is used by the web panel for full company registration. // @Tags Companies-Admin // @Accept json // @Produce json // @Param company body CreateCompanyForm true "Company information including type, business details, address, tags, and optional customer assignment" // @Success 201 {object} response.APIResponse{data=CompanyResponse} "Company created successfully" // @Failure 400 {object} response.APIResponse "Bad request - Invalid input data" // @Failure 409 {object} response.APIResponse "Conflict - Company with this name/registration/tax ID already exists" // @Failure 422 {object} response.APIResponse "Validation error - Invalid request data" // @Failure 500 {object} response.APIResponse "Internal server error" // @Security BearerAuth // @Router /admin/v1/companies [post] func (h *Handler) CreateCompany(c echo.Context) error { form, err := response.Parse[CreateCompanyForm](c) if err != nil { return response.ValidationError(c, "Invalid request data", err.Error()) } // Get user ID from JWT token context createdBy, err := user.GetUserIDFromContext(c) if err != nil { return response.Unauthorized(c, "User not authenticated") } company, err := h.service.CreateCompany(c.Request().Context(), form, &createdBy) if err != nil { if err.Error() == "company with this name already exists" || err.Error() == "company with this registration number already exists" || err.Error() == "company with this tax ID already exists" { return response.Conflict(c, err.Error()) } return response.InternalServerError(c, "Failed to create company") } return response.Created(c, company.ToResponse(), "Company created successfully") } // GetCompany retrieves a company by ID (Web Panel) // @Summary Get company by ID // @Description Retrieve detailed company information by company ID // @Tags Companies-Admin // @Accept json // @Produce json // @Param id path string true "Company ID" // @Success 200 {object} response.APIResponse{data=CompanyResponse} "Company retrieved successfully" // @Failure 400 {object} response.APIResponse "Bad request - Invalid company ID" // @Failure 404 {object} response.APIResponse "Not found - Company not found" // @Failure 500 {object} response.APIResponse "Internal server error" // @Security BearerAuth // @Router /admin/v1/companies/{id} [get] func (h *Handler) GetCompany(c echo.Context) error { id := c.Param("id") company, err := h.service.GetCompanyByID(c.Request().Context(), id) if err != nil { if err.Error() == "company not found" { return response.NotFound(c, "Company not found") } return response.InternalServerError(c, "Failed to get company") } return response.Success(c, company.ToResponse(), "Company retrieved successfully") } // UpdateCompany updates a company (Web Panel) // @Summary Update company information // @Description Update company information including business details, address, tags, and customer assignment // @Tags Companies-Admin // @Accept json // @Produce json // @Param id path string true "Company ID" // @Param company body UpdateCompanyForm true "Company update information" // @Success 200 {object} response.APIResponse{data=CompanyResponse} "Company updated successfully" // @Failure 400 {object} response.APIResponse "Bad request - Invalid input data" // @Failure 404 {object} response.APIResponse "Not found - Company not found" // @Failure 409 {object} response.APIResponse "Conflict - Company with this name/registration/tax ID already exists" // @Failure 422 {object} response.APIResponse "Validation error - Invalid request data" // @Failure 500 {object} response.APIResponse "Internal server error" // @Security BearerAuth // @Router /admin/v1/companies/{id} [put] func (h *Handler) UpdateCompany(c echo.Context) error { id := c.Param("id") form, err := response.Parse[UpdateCompanyForm](c) if err != nil { return response.ValidationError(c, "Invalid request data", err.Error()) } // Get user ID from JWT token context updatedBy, err := user.GetUserIDFromContext(c) if err != nil { return response.Unauthorized(c, "User not authenticated") } company, err := h.service.UpdateCompany(c.Request().Context(), id, form, &updatedBy) if err != nil { if err.Error() == "company not found" { return response.NotFound(c, "Company not found") } if err.Error() == "company with this name already exists" || err.Error() == "company with this registration number already exists" || err.Error() == "company with this tax ID already exists" { return response.Conflict(c, err.Error()) } return response.InternalServerError(c, "Failed to update company") } return response.Success(c, company.ToResponse(), "Company updated successfully") } // DeleteCompany deletes a company (Web Panel) // @Summary Delete company // @Description Soft delete a company by setting status to inactive // @Tags Companies-Admin // @Accept json // @Produce json // @Param id path string true "Company ID" // @Success 200 {object} response.APIResponse "Company deleted successfully" // @Failure 400 {object} response.APIResponse "Bad request - Invalid company ID" // @Failure 404 {object} response.APIResponse "Not found - Company not found" // @Failure 500 {object} response.APIResponse "Internal server error" // @Security BearerAuth // @Router /admin/v1/companies/{id} [delete] func (h *Handler) DeleteCompany(c echo.Context) error { id := c.Param("id") // Get user ID from JWT token context deletedBy, err := user.GetUserIDFromContext(c) if err != nil { return response.Unauthorized(c, "User not authenticated") } err = h.service.DeleteCompany(c.Request().Context(), id, &deletedBy) if err != nil { if err.Error() == "company not found" { return response.NotFound(c, "Company not found") } return response.InternalServerError(c, "Failed to delete company") } return response.Success(c, map[string]interface{}{ "message": "Company deleted successfully", }, "Company deleted successfully") } // ListCompanies lists companies with filters and pagination (Web Panel) // @Summary List companies with filters and pagination // @Description Retrieve a paginated list of companies with advanced filtering options including search, type, status, industry, verification status, tags, and business criteria. Supports sorting and pagination. // @Tags Companies-Admin // @Accept json // @Produce json // @Param search query string false "Search term to filter companies by name, description, or industry" // @Param type query string false "Filter by company type" Enums(private, public, government, ngo, startup) // @Param status query string false "Filter by company status" Enums(active, inactive, suspended, pending) // @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" // @Param specializations query array false "Filter by specializations" // @Param employee_count_min query integer false "Minimum employee count" // @Param employee_count_max query integer false "Maximum employee count" // @Param annual_revenue_min query number false "Minimum annual revenue" // @Param annual_revenue_max query number false "Maximum annual revenue" // @Param founded_year_min query integer false "Minimum founded year" // @Param founded_year_max query integer false "Maximum founded year" // @Param limit query integer false "Number of companies per page (1-100)" minimum(1) maximum(100) default(20) // @Param offset query integer false "Number of companies to skip for pagination" minimum(0) default(0) // @Param sort_by query string false "Field to sort by" Enums(name, type, industry, created_at, updated_at, status, employee_count, annual_revenue) default(created_at) // @Param sort_order query string false "Sort order" Enums(asc, desc) default(desc) // @Success 200 {object} response.APIResponse{data=CompanyListResponse} "Companies retrieved successfully" // @Failure 400 {object} response.APIResponse "Bad request - Invalid query parameters" // @Failure 422 {object} response.APIResponse "Validation error - Invalid query parameters" // @Failure 500 {object} response.APIResponse "Internal server error" // @Security BearerAuth // @Router /admin/v1/companies [get] func (h *Handler) ListCompanies(c echo.Context) error { form, err := response.Parse[ListCompaniesForm](c) if err != nil { return response.ValidationError(c, "Invalid request data", err.Error()) } result, err := h.service.ListCompanies(c.Request().Context(), form) if err != nil { return response.InternalServerError(c, "Failed to list companies") } return response.Success(c, result, "Companies retrieved successfully") } // SearchCompanies searches companies with advanced filters (Web Panel) // @Summary Advanced search for companies // @Description Search companies with advanced filtering capabilities including tags, business criteria, and location // @Tags Companies-Admin // @Accept json // @Produce json // @Param q query string false "Search query" // @Param cpv_codes query array false "CPV codes filter" // @Param categories query array false "Categories filter" // @Param keywords query array false "Keywords filter" // @Param specializations query array false "Specializations filter" // @Param industry query string false "Industry filter" // @Param location query string false "Location filter" // @Param min_employees query integer false "Minimum employees" // @Param max_employees query integer false "Maximum employees" // @Param min_revenue query number false "Minimum revenue" // @Param max_revenue query number false "Maximum revenue" // @Param is_verified query boolean false "Verification status" // @Param is_compliant query boolean false "Compliance status" // @Param limit query integer false "Limit" default(20) // @Param offset query integer false "Offset" default(0) // @Success 200 {object} response.APIResponse{data=CompanyListResponse} "Companies search completed" // @Failure 400 {object} response.APIResponse "Bad request - Invalid query parameters" // @Failure 422 {object} response.APIResponse "Validation error - Invalid query parameters" // @Failure 500 {object} response.APIResponse "Internal server error" // @Security BearerAuth // @Router /admin/v1/companies/search [get] func (h *Handler) SearchCompanies(c echo.Context) error { form, err := response.Parse[CompanySearchForm](c) if err != nil { return response.ValidationError(c, "Invalid request data", err.Error()) } result, err := h.service.SearchCompanies(c.Request().Context(), form) if err != nil { return response.InternalServerError(c, "Failed to search companies") } return response.Success(c, result, "Companies search completed") } // UpdateCompanyStatus updates company status (Web Panel) // @Summary Update company status // @Description Update company account status (active, inactive, suspended, pending) // @Tags Companies-Admin // @Accept json // @Produce json // @Param id path string true "Company ID" // @Param status body UpdateCompanyStatusForm true "New company status" // @Success 200 {object} response.APIResponse "Company status updated successfully" // @Failure 400 {object} response.APIResponse "Bad request - Invalid input data" // @Failure 404 {object} response.APIResponse "Not found - Company not found" // @Failure 422 {object} response.APIResponse "Validation error - Invalid request data" // @Failure 500 {object} response.APIResponse "Internal server error" // @Security BearerAuth // @Router /admin/v1/companies/{id}/status [patch] func (h *Handler) UpdateCompanyStatus(c echo.Context) error { id := c.Param("id") form, err := response.Parse[UpdateCompanyStatusForm](c) if err != nil { return response.ValidationError(c, "Invalid request data", err.Error()) } // Get user ID from JWT token context updatedBy, err := user.GetUserIDFromContext(c) if err != nil { return response.Unauthorized(c, "User not authenticated") } err = h.service.UpdateCompanyStatus(c.Request().Context(), id, form, &updatedBy) if err != nil { if err.Error() == "company not found" { return response.NotFound(c, "Company not found") } return response.InternalServerError(c, "Failed to update company status") } return response.Success(c, map[string]interface{}{ "message": "Company status updated successfully", }, "Company status updated successfully") } // UpdateCompanyVerification updates company verification status (Web Panel) // @Summary Update company verification status // @Description Update company verification and compliance status // @Tags Companies-Admin // @Accept json // @Produce json // @Param id path string true "Company ID" // @Param verification body UpdateCompanyVerificationForm true "Verification status update" // @Success 200 {object} response.APIResponse "Company verification updated successfully" // @Failure 400 {object} response.APIResponse "Bad request - Invalid input data" // @Failure 404 {object} response.APIResponse "Not found - Company not found" // @Failure 422 {object} response.APIResponse "Validation error - Invalid request data" // @Failure 500 {object} response.APIResponse "Internal server error" // @Security BearerAuth // @Router /admin/v1/companies/{id}/verification [patch] func (h *Handler) UpdateCompanyVerification(c echo.Context) error { id := c.Param("id") form, err := response.Parse[UpdateCompanyVerificationForm](c) if err != nil { return response.ValidationError(c, "Invalid request data", err.Error()) } // Get user ID from JWT token context updatedBy, err := user.GetUserIDFromContext(c) if err != nil { return response.Unauthorized(c, "User not authenticated") } err = h.service.UpdateCompanyVerification(c.Request().Context(), id, form, &updatedBy) if err != nil { if err.Error() == "company not found" { return response.NotFound(c, "Company not found") } return response.InternalServerError(c, "Failed to update company verification") } return response.Success(c, map[string]interface{}{ "message": "Company verification updated successfully", }, "Company verification updated successfully") } // UpdateCompanyTags updates company tags (Web Panel) // @Summary Update company tags // @Description Update company tags (CPV, categories, keywords, specializations, certifications) // @Tags Companies-Admin // @Accept json // @Produce json // @Param id path string true "Company ID" // @Param tags body UpdateCompanyTagsForm true "Tags update information" // @Success 200 {object} response.APIResponse "Company tags updated successfully" // @Failure 400 {object} response.APIResponse "Bad request - Invalid input data" // @Failure 404 {object} response.APIResponse "Not found - Company not found" // @Failure 422 {object} response.APIResponse "Validation error - Invalid request data" // @Failure 500 {object} response.APIResponse "Internal server error" // @Security BearerAuth // @Router /admin/v1/companies/{id}/tags [put] func (h *Handler) UpdateCompanyTags(c echo.Context) error { id := c.Param("id") form, err := response.Parse[UpdateCompanyTagsForm](c) if err != nil { return response.ValidationError(c, "Invalid request data", err.Error()) } // Get user ID from JWT token context updatedBy, err := user.GetUserIDFromContext(c) if err != nil { return response.Unauthorized(c, "User not authenticated") } err = h.service.UpdateCompanyTags(c.Request().Context(), id, form, &updatedBy) if err != nil { if err.Error() == "company not found" { return response.NotFound(c, "Company not found") } return response.InternalServerError(c, "Failed to update company tags") } return response.Success(c, map[string]interface{}{ "message": "Company tags updated successfully", }, "Company tags updated successfully") } // AddTags adds tags to a company (Web Panel) // @Summary Add tags to company // @Description Add specific tags to a company // @Tags Companies-Admin // @Accept json // @Produce json // @Param id path string true "Company ID" // @Param tags body AddTagsForm true "Tags to add" // @Success 200 {object} response.APIResponse "Tags added successfully" // @Failure 400 {object} response.APIResponse "Bad request - Invalid input data" // @Failure 404 {object} response.APIResponse "Not found - Company not found" // @Failure 422 {object} response.APIResponse "Validation error - Invalid request data" // @Failure 500 {object} response.APIResponse "Internal server error" // @Security BearerAuth // @Router /admin/v1/companies/{id}/tags/add [post] func (h *Handler) AddTags(c echo.Context) error { id := c.Param("id") form, err := response.Parse[AddTagsForm](c) if err != nil { return response.ValidationError(c, "Invalid request data", err.Error()) } // Get user ID from JWT token context updatedBy, err := user.GetUserIDFromContext(c) if err != nil { return response.Unauthorized(c, "User not authenticated") } err = h.service.AddTags(c.Request().Context(), id, form, &updatedBy) if err != nil { if err.Error() == "company not found" { return response.NotFound(c, "Company not found") } return response.InternalServerError(c, "Failed to add tags") } return response.Success(c, map[string]interface{}{ "message": "Tags added successfully", }, "Tags added successfully") } // RemoveTags removes tags from a company (Web Panel) // @Summary Remove tags from company // @Description Remove specific tags from a company // @Tags Companies-Admin // @Accept json // @Produce json // @Param id path string true "Company ID" // @Param tags body RemoveTagsForm true "Tags to remove" // @Success 200 {object} response.APIResponse "Tags removed successfully" // @Failure 400 {object} response.APIResponse "Bad request - Invalid input data" // @Failure 404 {object} response.APIResponse "Not found - Company not found" // @Failure 422 {object} response.APIResponse "Validation error - Invalid request data" // @Failure 500 {object} response.APIResponse "Internal server error" // @Security BearerAuth // @Router /admin/v1/companies/{id}/tags/remove [post] func (h *Handler) RemoveTags(c echo.Context) error { id := c.Param("id") form, err := response.Parse[RemoveTagsForm](c) if err != nil { return response.ValidationError(c, "Invalid request data", err.Error()) } // Get user ID from JWT token context updatedBy, err := user.GetUserIDFromContext(c) if err != nil { return response.Unauthorized(c, "User not authenticated") } err = h.service.RemoveTags(c.Request().Context(), id, form, &updatedBy) if err != nil { if err.Error() == "company not found" { return response.NotFound(c, "Company not found") } return response.InternalServerError(c, "Failed to remove tags") } return response.Success(c, map[string]interface{}{ "message": "Tags removed successfully", }, "Tags removed successfully") } // VerifyCompany verifies a company (Web Panel) // @Summary Verify company // @Description Mark a company as verified // @Tags Companies-Admin // @Accept json // @Produce json // @Param id path string true "Company ID" // @Success 200 {object} response.APIResponse "Company verified successfully" // @Failure 400 {object} response.APIResponse "Bad request - Invalid company ID" // @Failure 404 {object} response.APIResponse "Not found - Company not found" // @Failure 500 {object} response.APIResponse "Internal server error" // @Security BearerAuth // @Router /admin/v1/companies/{id}/verify [post] func (h *Handler) VerifyCompany(c echo.Context) error { id := c.Param("id") // Get user ID from JWT token context verifiedBy, err := user.GetUserIDFromContext(c) if err != nil { return response.Unauthorized(c, "User not authenticated") } err = h.service.VerifyCompany(c.Request().Context(), id, &verifiedBy) if err != nil { if err.Error() == "company not found" { return response.NotFound(c, "Company not found") } return response.InternalServerError(c, "Failed to verify company") } return response.Success(c, map[string]interface{}{ "message": "Company verified successfully", }, "Company verified successfully") } // SuspendCompany suspends a company (Web Panel) // @Summary Suspend company // @Description Suspend a company account with reason // @Tags Companies-Admin // @Accept json // @Produce json // @Param id path string true "Company ID" // @Param suspension body SuspendCompanyForm true "Suspension information" // @Success 200 {object} response.APIResponse "Company suspended successfully" // @Failure 400 {object} response.APIResponse "Bad request - Invalid input data" // @Failure 404 {object} response.APIResponse "Not found - Company not found" // @Failure 422 {object} response.APIResponse "Validation error - Invalid request data" // @Failure 500 {object} response.APIResponse "Internal server error" // @Security BearerAuth // @Router /admin/v1/companies/{id}/suspend [post] func (h *Handler) SuspendCompany(c echo.Context) error { id := c.Param("id") form, err := response.Parse[SuspendCompanyForm](c) if err != nil { return response.ValidationError(c, "Invalid request data", err.Error()) } // Get user ID from JWT token context suspendedBy, err := user.GetUserIDFromContext(c) if err != nil { return response.Unauthorized(c, "User not authenticated") } err = h.service.SuspendCompany(c.Request().Context(), id, form.Reason, &suspendedBy) if err != nil { if err.Error() == "company not found" { return response.NotFound(c, "Company not found") } return response.InternalServerError(c, "Failed to suspend company") } return response.Success(c, map[string]interface{}{ "message": "Company suspended successfully", }, "Company suspended successfully") } // ActivateCompany activates a company (Web Panel) // @Summary Activate company // @Description Activate a suspended company account // @Tags Companies-Admin // @Accept json // @Produce json // @Param id path string true "Company ID" // @Success 200 {object} response.APIResponse "Company activated successfully" // @Failure 400 {object} response.APIResponse "Bad request - Invalid company ID" // @Failure 404 {object} response.APIResponse "Not found - Company not found" // @Failure 500 {object} response.APIResponse "Internal server error" // @Security BearerAuth // @Router /admin/v1/companies/{id}/activate [post] func (h *Handler) ActivateCompany(c echo.Context) error { id := c.Param("id") // Get user ID from JWT token context activatedBy, err := user.GetUserIDFromContext(c) if err != nil { return response.Unauthorized(c, "User not authenticated") } err = h.service.ActivateCompany(c.Request().Context(), id, &activatedBy) if err != nil { if err.Error() == "company not found" { return response.NotFound(c, "Company not found") } return response.InternalServerError(c, "Failed to activate company") } return response.Success(c, map[string]interface{}{ "message": "Company activated successfully", }, "Company activated successfully") } // GetCompanyStats returns company statistics (Web Panel) // @Summary Get company statistics // @Description Get comprehensive company statistics for dashboard // @Tags Companies-Admin // @Accept json // @Produce json // @Success 200 {object} response.APIResponse{data=CompanyStatsResponse} "Company statistics retrieved successfully" // @Failure 500 {object} response.APIResponse "Internal server error" // @Security BearerAuth // @Router /admin/v1/companies/stats [get] func (h *Handler) GetCompanyStats(c echo.Context) error { stats, err := h.service.GetCompanyStats(c.Request().Context()) if err != nil { return response.InternalServerError(c, "Failed to get company statistics") } return response.Success(c, stats, "Company statistics retrieved successfully") } // GetCompaniesByType retrieves companies by type (Web Panel) // @Summary Get companies by type // @Description Retrieve companies filtered by their type (private, public, government, ngo, startup) // @Tags Companies-Admin // @Accept json // @Produce json // @Param type path string true "Company type" Enums(private, public, government, ngo, startup) // @Param limit query integer false "Number of companies per page (1-100)" minimum(1) maximum(100) default(20) // @Param offset query integer false "Number of companies to skip for pagination" minimum(0) default(0) // @Success 200 {object} response.APIResponse{data=[]CompanyResponse,meta=response.Meta} "Companies retrieved successfully" // @Failure 400 {object} response.APIResponse "Bad request - Invalid company type" // @Failure 500 {object} response.APIResponse "Internal server error" // @Security BearerAuth // @Router /admin/v1/companies/type/{type} [get] func (h *Handler) GetCompaniesByType(c echo.Context) error { companyTypeStr := c.Param("type") companyType := CompanyType(companyTypeStr) // Validate company type if companyType != CompanyTypePrivate && companyType != CompanyTypePublic && companyType != CompanyTypeGovernment && companyType != CompanyTypeNgo && companyType != CompanyTypeStartup { return response.BadRequest(c, "Invalid company type", "Must be private, public, government, ngo, or startup") } limit := 20 if limitStr := c.QueryParam("limit"); limitStr != "" { if parsedLimit, err := strconv.Atoi(limitStr); err == nil && parsedLimit > 0 && parsedLimit <= 100 { limit = parsedLimit } } offset := 0 if offsetStr := c.QueryParam("offset"); offsetStr != "" { if parsedOffset, err := strconv.Atoi(offsetStr); err == nil && parsedOffset >= 0 { offset = parsedOffset } } companies, total, err := h.service.GetCompaniesByType(c.Request().Context(), companyType, limit, offset) if err != nil { return response.InternalServerError(c, "Failed to retrieve companies by type") } var companyResponses []*CompanyResponse for _, company := range companies { companyResponses = append(companyResponses, company.ToResponse()) } meta := &response.Meta{ Total: int(total), Limit: limit, Offset: offset, } return response.SuccessWithMeta(c, companyResponses, meta, "Companies retrieved successfully") } // GetCompaniesByStatus retrieves companies by status (Web Panel) // @Summary Get companies by status // @Description Retrieve companies filtered by their status (active, inactive, suspended, pending) // @Tags Companies-Admin // @Accept json // @Produce json // @Param status path string true "Company status" Enums(active, inactive, suspended, pending) // @Param limit query integer false "Number of companies per page (1-100)" minimum(1) maximum(100) default(20) // @Param offset query integer false "Number of companies to skip for pagination" minimum(0) default(0) // @Success 200 {object} response.APIResponse{data=[]CompanyResponse,meta=response.Meta} "Companies retrieved successfully" // @Failure 400 {object} response.APIResponse "Bad request - Invalid company status" // @Failure 500 {object} response.APIResponse "Internal server error" // @Security BearerAuth // @Router /admin/v1/companies/status/{status} [get] func (h *Handler) GetCompaniesByStatus(c echo.Context) error { statusStr := c.Param("status") status := CompanyStatus(statusStr) // Validate company status if status != CompanyStatusActive && status != CompanyStatusInactive && status != CompanyStatusSuspended && status != CompanyStatusPending { return response.BadRequest(c, "Invalid company status", "Must be active, inactive, suspended, or pending") } limit := 20 if limitStr := c.QueryParam("limit"); limitStr != "" { if parsedLimit, err := strconv.Atoi(limitStr); err == nil && parsedLimit > 0 && parsedLimit <= 100 { limit = parsedLimit } } offset := 0 if offsetStr := c.QueryParam("offset"); offsetStr != "" { if parsedOffset, err := strconv.Atoi(offsetStr); err == nil && parsedOffset >= 0 { offset = parsedOffset } } companies, total, err := h.service.GetCompaniesByStatus(c.Request().Context(), status, limit, offset) if err != nil { return response.InternalServerError(c, "Failed to retrieve companies by status") } var companyResponses []*CompanyResponse for _, company := range companies { companyResponses = append(companyResponses, company.ToResponse()) } meta := &response.Meta{ Total: int(total), Limit: limit, Offset: offset, } return response.SuccessWithMeta(c, companyResponses, meta, "Companies retrieved successfully") } // GetCompaniesByIndustry retrieves companies by industry (Web Panel) // @Summary Get companies by industry // @Description Retrieve companies filtered by their industry // @Tags Companies-Admin // @Accept json // @Produce json // @Param industry path string true "Industry" // @Param limit query integer false "Number of companies per page (1-100)" minimum(1) maximum(100) default(20) // @Param offset query integer false "Number of companies to skip for pagination" minimum(0) default(0) // @Success 200 {object} response.APIResponse{data=[]CompanyResponse,meta=response.Meta} "Companies retrieved successfully" // @Failure 400 {object} response.APIResponse "Bad request - Invalid industry" // @Failure 500 {object} response.APIResponse "Internal server error" // @Security BearerAuth // @Router /admin/v1/companies/industry/{industry} [get] func (h *Handler) GetCompaniesByIndustry(c echo.Context) error { industry := c.Param("industry") limit := 20 if limitStr := c.QueryParam("limit"); limitStr != "" { if parsedLimit, err := strconv.Atoi(limitStr); err == nil && parsedLimit > 0 && parsedLimit <= 100 { limit = parsedLimit } } offset := 0 if offsetStr := c.QueryParam("offset"); offsetStr != "" { if parsedOffset, err := strconv.Atoi(offsetStr); err == nil && parsedOffset >= 0 { offset = parsedOffset } } companies, total, err := h.service.GetCompaniesByIndustry(c.Request().Context(), industry, limit, offset) if err != nil { return response.InternalServerError(c, "Failed to retrieve companies by industry") } var companyResponses []*CompanyResponse for _, company := range companies { companyResponses = append(companyResponses, company.ToResponse()) } meta := &response.Meta{ Total: int(total), Limit: limit, Offset: offset, } return response.SuccessWithMeta(c, companyResponses, meta, "Companies retrieved successfully") }