566fa07574
- Changed tags from "Customers-Mobile" to "Customers-Authorization" in Swagger documentation for customer logout and profile retrieval endpoints. - Updated the Company entity to replace CustomerID with OwnerCustomerID to better represent ownership. - Removed obsolete customer assignment methods and related forms from the company domain, streamlining the codebase. - Adjusted customer forms to include CompanyID instead of CompanyName for better consistency in customer management. - Enhanced Swagger documentation to accurately reflect the new structure and authorization details for customer-related endpoints.
788 lines
32 KiB
Go
788 lines
32 KiB
Go
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")
|
|
}
|