From ee5a68046833dd9c4486965179af9a94092cf506 Mon Sep 17 00:00:00 2001 From: Tiago Yamamoto Date: Fri, 26 Dec 2025 10:20:38 -0300 Subject: [PATCH] Add missing CRUD routes: Companies GET by ID, Support Tickets --- backend/docs/docs.go | 38 +++++++++++++++++++ backend/docs/swagger.json | 38 +++++++++++++++++++ backend/docs/swagger.yaml | 25 ++++++++++++ .../internal/api/handlers/core_handlers.go | 27 +++++++++++++ backend/internal/router/router.go | 9 +++++ backend/internal/services/admin_service.go | 8 ++-- 6 files changed, 141 insertions(+), 4 deletions(-) diff --git a/backend/docs/docs.go b/backend/docs/docs.go index 53876f8..7ed9c21 100644 --- a/backend/docs/docs.go +++ b/backend/docs/docs.go @@ -364,6 +364,44 @@ const docTemplate = `{ } } }, + "/api/v1/companies/{id}": { + "get": { + "description": "Retrieves a company by its ID.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Companies" + ], + "summary": "Get Company", + "parameters": [ + { + "type": "string", + "description": "Company ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "string" + } + } + } + } + }, "/api/v1/jobs": { "get": { "description": "Get a paginated list of job postings with optional filters", diff --git a/backend/docs/swagger.json b/backend/docs/swagger.json index 8cef1b2..e5cab07 100644 --- a/backend/docs/swagger.json +++ b/backend/docs/swagger.json @@ -357,6 +357,44 @@ } } }, + "/api/v1/companies/{id}": { + "get": { + "description": "Retrieves a company by its ID.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Companies" + ], + "summary": "Get Company", + "parameters": [ + { + "type": "string", + "description": "Company ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "string" + } + } + } + } + }, "/api/v1/jobs": { "get": { "description": "Get a paginated list of job postings with optional filters", diff --git a/backend/docs/swagger.yaml b/backend/docs/swagger.yaml index 09dbbf8..7af59b2 100644 --- a/backend/docs/swagger.yaml +++ b/backend/docs/swagger.yaml @@ -620,6 +620,31 @@ paths: summary: Create Company (Tenant) tags: - Companies + /api/v1/companies/{id}: + get: + consumes: + - application/json + description: Retrieves a company by its ID. + parameters: + - description: Company ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + type: object + "404": + description: Not Found + schema: + type: string + summary: Get Company + tags: + - Companies /api/v1/jobs: get: consumes: diff --git a/backend/internal/api/handlers/core_handlers.go b/backend/internal/api/handlers/core_handlers.go index f0657f7..afc1299 100644 --- a/backend/internal/api/handlers/core_handlers.go +++ b/backend/internal/api/handlers/core_handlers.go @@ -228,6 +228,33 @@ func (h *CoreHandlers) ListCompanies(w http.ResponseWriter, r *http.Request) { json.NewEncoder(w).Encode(resp) } +// GetCompanyByID retrieves a single company by ID. +// @Summary Get Company +// @Description Retrieves a company by its ID. +// @Tags Companies +// @Accept json +// @Produce json +// @Param id path string true "Company ID" +// @Success 200 {object} object +// @Failure 404 {string} string "Not Found" +// @Router /api/v1/companies/{id} [get] +func (h *CoreHandlers) GetCompanyByID(w http.ResponseWriter, r *http.Request) { + id := r.PathValue("id") + if id == "" { + http.Error(w, "Company ID is required", http.StatusBadRequest) + return + } + + company, err := h.adminService.GetCompanyByID(r.Context(), id) + if err != nil { + http.Error(w, "Company not found", http.StatusNotFound) + return + } + + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(company) +} + // CreateUser creates a new user within the authenticated tenant. // @Summary Create User // @Description Creates a new user under the current tenant. Requires Admin role. diff --git a/backend/internal/router/router.go b/backend/internal/router/router.go index 8158408..d977e8f 100755 --- a/backend/internal/router/router.go +++ b/backend/internal/router/router.go @@ -193,9 +193,18 @@ func NewRouter() http.Handler { // /api/v1/admin/candidates -> /api/v1/candidates mux.Handle("GET /api/v1/candidates", authMiddleware.HeaderAuthGuard(adminOnly(http.HandlerFunc(adminHandlers.ListCandidates)))) + // Get Company by ID (Public) + mux.HandleFunc("GET /api/v1/companies/{id}", coreHandlers.GetCompanyByID) + // Notifications Route mux.Handle("GET /api/v1/notifications", authMiddleware.HeaderAuthGuard(http.HandlerFunc(coreHandlers.ListNotifications))) + // Support Ticket Routes + mux.Handle("GET /api/v1/support/tickets", authMiddleware.HeaderAuthGuard(http.HandlerFunc(coreHandlers.ListTickets))) + mux.Handle("POST /api/v1/support/tickets", authMiddleware.HeaderAuthGuard(http.HandlerFunc(coreHandlers.CreateTicket))) + mux.Handle("GET /api/v1/support/tickets/{id}", authMiddleware.HeaderAuthGuard(http.HandlerFunc(coreHandlers.GetTicket))) + mux.Handle("POST /api/v1/support/tickets/{id}/messages", authMiddleware.HeaderAuthGuard(http.HandlerFunc(coreHandlers.AddMessage))) + // Application Routes mux.HandleFunc("POST /api/v1/applications", applicationHandler.CreateApplication) mux.HandleFunc("GET /api/v1/applications", applicationHandler.GetApplications) diff --git a/backend/internal/services/admin_service.go b/backend/internal/services/admin_service.go index b5eefe7..045200c 100644 --- a/backend/internal/services/admin_service.go +++ b/backend/internal/services/admin_service.go @@ -139,7 +139,7 @@ func (s *AdminService) ListUsers(ctx context.Context, page, limit int, companyID } func (s *AdminService) UpdateCompanyStatus(ctx context.Context, id string, active *bool, verified *bool) (*models.Company, error) { - company, err := s.getCompanyByID(ctx, id) + company, err := s.GetCompanyByID(ctx, id) if err != nil { return nil, err } @@ -536,7 +536,7 @@ func isActiveApplicationStatus(status string) bool { } } -func (s *AdminService) getCompanyByID(ctx context.Context, id string) (*models.Company, error) { +func (s *AdminService) GetCompanyByID(ctx context.Context, id string) (*models.Company, error) { query := ` SELECT id, name, slug, type, document, address, region_id, city_id, phone, email, website, logo_url, description, active, verified, created_at, updated_at FROM companies WHERE id = $1 @@ -626,7 +626,7 @@ func (s *AdminService) GetCompanyByUserID(ctx context.Context, userID string) (* } func (s *AdminService) UpdateCompany(ctx context.Context, id string, req dto.UpdateCompanyRequest) (*models.Company, error) { - company, err := s.getCompanyByID(ctx, id) + company, err := s.GetCompanyByID(ctx, id) if err != nil { return nil, err } @@ -700,7 +700,7 @@ func (s *AdminService) UpdateCompany(ctx context.Context, id string, req dto.Upd func (s *AdminService) DeleteCompany(ctx context.Context, id string) error { // First check if exists - _, err := s.getCompanyByID(ctx, id) + _, err := s.GetCompanyByID(ctx, id) if err != nil { return err }