diff --git a/backend/BACKEND.md b/backend/BACKEND.md index 233b58e..3ef567d 100755 --- a/backend/BACKEND.md +++ b/backend/BACKEND.md @@ -137,35 +137,63 @@ Este workflow é disparado automaticamente ao realizar um push para o branch `de --- -## 📡 Endpoints Principais +## 📡 Endpoints (API Reference) -### Helper & System -| Recurso | Método | Endpoint | Descrição | -|---------|--------|----------|-----------| -| Health | `GET` | `/health` | Health Check | -| Docs | `GET` | `/docs/*` | Swagger UI | -| Settings| `GET` | `/api/v1/system/settings/{key}` | Obter configurações públicas | +### 🔐 Auth & Core +| Método | Endpoint | Descrição | Roles | +|--------|----------|-----------|-------| +| `POST` | `/api/v1/auth/login` | Autenticação de usuário | Public | +| `POST` | `/api/v1/auth/register` | Registro de Candidato | Public | +| `POST` | `/api/v1/auth/register/company` | Registro de Empresa | Public | +| `GET` | `/api/v1/users/me` | Dados do usuário logado | Auth | +| `PATCH` | `/api/v1/users/me/profile` | Atualizar perfil | Auth | +| `GET` | `/api/v1/notifications` | Listar notificações | Auth | +| `POST` | `/api/v1/tokens` | Salvar token FCM | Auth | -### Auth & Usuários -| Recurso | Método | Endpoint | Roles | -|---------|--------|----------|-------| -| Login | `POST` | `/api/v1/auth/login` | Public | -| Me | `GET` | `/api/v1/users/me` | Auth | -| Profile | `PATCH`| `/api/v1/users/me/profile` | Auth | +### 💼 Jobs (Vagas) +| Método | Endpoint | Descrição | Roles | +|--------|----------|-----------|-------| +| `GET` | `/api/v1/jobs` | Listar vagas (filtros) | Public | +| `GET` | `/api/v1/jobs/{id}` | Detalhes da vaga | Public | +| `POST` | `/api/v1/jobs` | Criar nova vaga | Recruiter | +| `PUT` | `/api/v1/jobs/{id}` | Editar vaga | Recruiter | +| `DELETE` | `/api/v1/jobs/{id}` | Remover vaga | Recruiter | -### Tickets & Suporte (Novo) -| Recurso | Método | Endpoint | Roles | -|---------|--------|----------|-------| -| Listar | `GET` | `/api/v1/support/tickets` | Auth | -| Criar | `POST` | `/api/v1/support/tickets` | Auth | -| Mensagem| `POST` | `/api/v1/support/tickets/{id}/messages`| Auth | +### 📝 Applications (Candidaturas) +| Método | Endpoint | Descrição | Roles | +|--------|----------|-----------|-------| +| `POST` | `/api/v1/applications` | Candidatar-se a uma vaga | Candidate | +| `GET` | `/api/v1/applications` | Minhas candidaturas | Auth | +| `GET` | `/api/v1/applications/{id}` | Detalhes da candidatura | Auth | +| `PUT` | `/api/v1/applications/{id}/status` | Atualizar status | Recruiter | +| `DELETE` | `/api/v1/applications/{id}` | Desistir/Remover | Auth | -### Admin & Credenciais (Novo) -| Recurso | Método | Endpoint | Roles | -|---------|--------|----------|-------| -| Credentials | `GET` | `/api/v1/system/credentials` | Admin | -| Credentials | `POST` | `/api/v1/system/credentials` | Admin | -| Purge Cache | `POST` | `/api/v1/system/cloudflare/purge`| Admin | +### 🎫 Support (Tickets) +| Método | Endpoint | Descrição | Roles | +|--------|----------|-----------|-------| +| `GET` | `/api/v1/support/tickets` | Meus tickets de suporte | Auth | +| `POST` | `/api/v1/support/tickets` | Abrir novo ticket | Auth | +| `GET` | `/api/v1/support/tickets/{id}` | Ver conversa do ticket | Auth | +| `POST` | `/api/v1/support/tickets/{id}/messages` | Enviar mensagem | Auth | +| `PATCH` | `/api/v1/support/tickets/{id}/close` | Fechar ticket | Auth | + +### 💬 Chat & Locais +| Método | Endpoint | Descrição | Roles | +|--------|----------|-----------|-------| +| `GET` | `/api/v1/conversations` | Listar conversas | Auth | +| `GET` | `/api/v1/conversations/{id}/messages` | Ver mensagens | Auth | +| `POST` | `/api/v1/conversations/{id}/messages` | Enviar mensagem | Auth | +| `GET` | `/api/v1/locations/search` | Buscar cidade/estado | Public | + +### 🛡️ Admin & System +| Método | Endpoint | Descrição | Roles | +|--------|----------|-----------|-------| +| `GET` | `/api/v1/users` | Listar todos usuários | Admin | +| `GET` | `/api/v1/jobs/moderation` | Moderação de vagas | Admin | +| `GET` | `/api/v1/system/credentials` | Ver credenciais (mascaradas) | Admin | +| `POST` | `/api/v1/system/credentials` | Salvar credencial | Admin | +| `POST` | `/api/v1/system/cloudflare/purge` | Limpar cache CDN | Admin | +| `GET` | `/api/v1/admin/email-templates` | Gerenciar emails | Admin | --- diff --git a/backend/docs/docs.go b/backend/docs/docs.go index 7ed9c21..43436b6 100644 --- a/backend/docs/docs.go +++ b/backend/docs/docs.go @@ -43,7 +43,7 @@ const docTemplate = `{ "schema": { "type": "array", "items": { - "$ref": "#/definitions/models.Application" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Application" } } }, @@ -80,7 +80,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.CreateApplicationRequest" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_dto.CreateApplicationRequest" } } ], @@ -88,7 +88,7 @@ const docTemplate = `{ "201": { "description": "Created", "schema": { - "$ref": "#/definitions/models.Application" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Application" } }, "400": { @@ -132,7 +132,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/models.Application" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Application" } }, "400": { @@ -216,7 +216,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.UpdateApplicationStatusRequest" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_dto.UpdateApplicationStatusRequest" } } ], @@ -224,7 +224,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/models.Application" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Application" } }, "400": { @@ -400,6 +400,224 @@ const docTemplate = `{ } } } + }, + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Deletes a company by ID (admin only)", + "tags": [ + "Companies" + ], + "summary": "Delete Company", + "parameters": [ + { + "type": "string", + "description": "Company ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "401": { + "description": "Unauthorized", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + }, + "patch": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Updates company information by ID (admin only)", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Companies" + ], + "summary": "Update Company", + "parameters": [ + { + "type": "string", + "description": "Company ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Company update data", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_dto.UpdateCompanyRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object" + } + }, + "400": { + "description": "Invalid Request", + "schema": { + "type": "string" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/conversations": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "List chat conversations for candidate or company", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Chat" + ], + "summary": "List Conversations", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_services.Conversation" + } + } + } + } + } + }, + "/api/v1/conversations/{id}/messages": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get message history for a conversation", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Chat" + ], + "summary": "List Messages", + "parameters": [ + { + "type": "string", + "description": "Conversation ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_services.Message" + } + } + } + } + }, + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Send a message to a conversation", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Chat" + ], + "summary": "Send Message", + "parameters": [ + { + "type": "string", + "description": "Conversation ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Message Content", + "name": "request", + "in": "body", + "required": true, + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_services.Message" + } + } + } } }, "/api/v1/jobs": { @@ -445,7 +663,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/dto.PaginatedResponse" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_dto.PaginatedResponse" } }, "500": { @@ -475,7 +693,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.CreateJobRequest" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_dto.CreateJobRequest" } } ], @@ -483,7 +701,7 @@ const docTemplate = `{ "201": { "description": "Created", "schema": { - "$ref": "#/definitions/models.Job" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Job" } }, "400": { @@ -533,7 +751,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/models.Job" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Job" } }, "400": { @@ -576,7 +794,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.UpdateJobRequest" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_dto.UpdateJobRequest" } } ], @@ -584,7 +802,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/models.Job" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Job" } }, "400": { @@ -780,7 +998,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/handlers.CreateCheckoutRequest" + "$ref": "#/definitions/internal_handlers.CreateCheckoutRequest" } } ], @@ -788,7 +1006,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/handlers.CreateCheckoutResponse" + "$ref": "#/definitions/internal_handlers.CreateCheckoutResponse" } }, "400": { @@ -896,7 +1114,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/handlers.DownloadURLRequest" + "$ref": "#/definitions/internal_handlers.DownloadURLRequest" } } ], @@ -904,7 +1122,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/handlers.DownloadURLResponse" + "$ref": "#/definitions/internal_handlers.DownloadURLResponse" } }, "400": { @@ -993,7 +1211,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/handlers.UploadURLRequest" + "$ref": "#/definitions/internal_handlers.UploadURLRequest" } } ], @@ -1001,7 +1219,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/handlers.UploadURLResponse" + "$ref": "#/definitions/internal_handlers.UploadURLResponse" } }, "400": { @@ -1105,6 +1323,57 @@ const docTemplate = `{ } } }, + "/api/v1/support/tickets/all": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Returns all support tickets for admin review.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Support" + ], + "summary": "List All Tickets (Admin)", + "parameters": [ + { + "type": "string", + "description": "Filter by status (open, in_progress, closed)", + "name": "status", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "type": "object" + } + } + }, + "403": { + "description": "Forbidden", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, "/api/v1/support/tickets/{id}": { "get": { "security": [ @@ -1152,6 +1421,161 @@ const docTemplate = `{ } } } + }, + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Deletes a support ticket (admin only).", + "tags": [ + "Support" + ], + "summary": "Delete Ticket", + "parameters": [ + { + "type": "string", + "description": "Ticket ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "401": { + "description": "Unauthorized", + "schema": { + "type": "string" + } + }, + "403": { + "description": "Forbidden", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + }, + "patch": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Updates a ticket's status and/or priority.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Support" + ], + "summary": "Update Ticket", + "parameters": [ + { + "type": "string", + "description": "Ticket ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Update data (status, priority)", + "name": "ticket", + "in": "body", + "required": true, + "schema": { + "type": "object" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object" + } + }, + "400": { + "description": "Invalid Request", + "schema": { + "type": "string" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/support/tickets/{id}/close": { + "patch": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Closes a support ticket.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Support" + ], + "summary": "Close Ticket", + "parameters": [ + { + "type": "string", + "description": "Ticket ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } } }, "/api/v1/support/tickets/{id}/messages": { @@ -1212,6 +1636,117 @@ const docTemplate = `{ } } }, + "/api/v1/system/credentials": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Saves encrypted credentials payload (e.g. Stripe key encrypted by Backoffice)", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "System" + ], + "summary": "Save Credentials", + "parameters": [ + { + "description": "Credentials Payload", + "name": "request", + "in": "body", + "required": true, + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "Invalid Request", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/tokens": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Saves or updates the FCM token for push notifications.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Notifications" + ], + "summary": "Save FCM Token", + "parameters": [ + { + "description": "FCM Token", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_core_dto.SaveFCMTokenRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "Invalid Request", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, "/api/v1/users": { "get": { "security": [ @@ -1349,7 +1884,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/dto.User" + "type": "object" } }, "401": { @@ -1577,7 +2112,18 @@ const docTemplate = `{ } }, "definitions": { - "dto.CreateApplicationRequest": { + "github_com_rede5_gohorsejobs_backend_internal_core_dto.SaveFCMTokenRequest": { + "type": "object", + "properties": { + "platform": { + "type": "string" + }, + "token": { + "type": "string" + } + } + }, + "github_com_rede5_gohorsejobs_backend_internal_dto.CreateApplicationRequest": { "type": "object", "required": [ "jobId" @@ -1616,7 +2162,7 @@ const docTemplate = `{ } } }, - "dto.CreateJobRequest": { + "github_com_rede5_gohorsejobs_backend_internal_dto.CreateJobRequest": { "type": "object", "required": [ "companyId", @@ -1641,7 +2187,12 @@ const docTemplate = `{ "USD", "EUR", "GBP", - "JPY" + "JPY", + "CNY", + "AED", + "CAD", + "AUD", + "CHF" ] }, "description": { @@ -1680,6 +2231,9 @@ const docTemplate = `{ "salaryMin": { "type": "number" }, + "salaryNegotiable": { + "type": "boolean" + }, "salaryType": { "type": "string", "enum": [ @@ -1717,16 +2271,16 @@ const docTemplate = `{ } } }, - "dto.PaginatedResponse": { + "github_com_rede5_gohorsejobs_backend_internal_dto.PaginatedResponse": { "type": "object", "properties": { "data": {}, "pagination": { - "$ref": "#/definitions/dto.Pagination" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_dto.Pagination" } } }, - "dto.Pagination": { + "github_com_rede5_gohorsejobs_backend_internal_dto.Pagination": { "type": "object", "properties": { "limit": { @@ -1740,7 +2294,7 @@ const docTemplate = `{ } } }, - "dto.UpdateApplicationStatusRequest": { + "github_com_rede5_gohorsejobs_backend_internal_dto.UpdateApplicationStatusRequest": { "type": "object", "required": [ "status" @@ -1761,7 +2315,58 @@ const docTemplate = `{ } } }, - "dto.UpdateJobRequest": { + "github_com_rede5_gohorsejobs_backend_internal_dto.UpdateCompanyRequest": { + "type": "object", + "properties": { + "active": { + "type": "boolean" + }, + "address": { + "type": "string" + }, + "cityId": { + "type": "integer" + }, + "description": { + "type": "string" + }, + "document": { + "type": "string" + }, + "email": { + "type": "string" + }, + "logoUrl": { + "type": "string" + }, + "name": { + "type": "string", + "maxLength": 255, + "minLength": 3 + }, + "phone": { + "type": "string" + }, + "regionId": { + "type": "integer" + }, + "slug": { + "type": "string", + "maxLength": 255, + "minLength": 3 + }, + "type": { + "type": "string" + }, + "verified": { + "type": "boolean" + }, + "website": { + "type": "string" + } + } + }, + "github_com_rede5_gohorsejobs_backend_internal_dto.UpdateJobRequest": { "type": "object", "properties": { "benefits": { @@ -1778,7 +2383,12 @@ const docTemplate = `{ "USD", "EUR", "GBP", - "JPY" + "JPY", + "CNY", + "AED", + "CAD", + "AUD", + "CHF" ] }, "description": { @@ -1817,6 +2427,9 @@ const docTemplate = `{ "salaryMin": { "type": "number" }, + "salaryNegotiable": { + "type": "boolean" + }, "salaryType": { "type": "string", "enum": [ @@ -1854,117 +2467,7 @@ const docTemplate = `{ } } }, - "dto.User": { - "type": "object", - "properties": { - "companyId": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "email": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "role": { - "type": "string" - }, - "status": { - "type": "string" - } - } - }, - "handlers.CreateCheckoutRequest": { - "type": "object", - "properties": { - "cancelUrl": { - "description": "URL after cancel", - "type": "string" - }, - "jobId": { - "type": "integer" - }, - "priceId": { - "description": "Stripe Price ID", - "type": "string" - }, - "successUrl": { - "description": "URL after success", - "type": "string" - } - } - }, - "handlers.CreateCheckoutResponse": { - "type": "object", - "properties": { - "checkoutUrl": { - "type": "string" - }, - "sessionId": { - "type": "string" - } - } - }, - "handlers.DownloadURLRequest": { - "type": "object", - "properties": { - "key": { - "type": "string" - } - } - }, - "handlers.DownloadURLResponse": { - "type": "object", - "properties": { - "downloadUrl": { - "type": "string" - }, - "expiresIn": { - "description": "seconds", - "type": "integer" - } - } - }, - "handlers.UploadURLRequest": { - "type": "object", - "properties": { - "contentType": { - "type": "string" - }, - "filename": { - "type": "string" - }, - "folder": { - "description": "Optional: logos, resumes, documents", - "type": "string" - } - } - }, - "handlers.UploadURLResponse": { - "type": "object", - "properties": { - "expiresIn": { - "description": "seconds", - "type": "integer" - }, - "key": { - "type": "string" - }, - "publicUrl": { - "type": "string" - }, - "uploadUrl": { - "type": "string" - } - } - }, - "models.Application": { + "github_com_rede5_gohorsejobs_backend_internal_models.Application": { "type": "object", "properties": { "createdAt": { @@ -1975,7 +2478,7 @@ const docTemplate = `{ "description": "Array of {type, url}", "allOf": [ { - "$ref": "#/definitions/models.JSONMap" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.JSONMap" } ] }, @@ -2024,15 +2527,15 @@ const docTemplate = `{ } } }, - "models.JSONMap": { + "github_com_rede5_gohorsejobs_backend_internal_models.JSONMap": { "type": "object", "additionalProperties": true }, - "models.Job": { + "github_com_rede5_gohorsejobs_backend_internal_models.Job": { "type": "object", "properties": { "benefits": { - "$ref": "#/definitions/models.JSONMap" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.JSONMap" }, "cityId": { "type": "integer" @@ -2080,7 +2583,7 @@ const docTemplate = `{ "description": "Requirements \u0026 Benefits (JSONB arrays)", "allOf": [ { - "$ref": "#/definitions/models.JSONMap" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.JSONMap" } ] }, @@ -2091,6 +2594,10 @@ const docTemplate = `{ "description": "Salary", "type": "number" }, + "salaryNegotiable": { + "description": "Candidate proposes salary", + "type": "boolean" + }, "salaryType": { "description": "hourly, daily, weekly, monthly, yearly", "type": "string" @@ -2118,6 +2625,146 @@ const docTemplate = `{ "type": "string" } } + }, + "github_com_rede5_gohorsejobs_backend_internal_services.Conversation": { + "type": "object", + "properties": { + "candidateId": { + "type": "string" + }, + "companyId": { + "type": "string" + }, + "id": { + "type": "string" + }, + "jobId": { + "type": "string" + }, + "lastMessage": { + "type": "string" + }, + "lastMessageAt": { + "type": "string" + }, + "participantAvatar": { + "type": "string" + }, + "participantName": { + "type": "string" + }, + "unreadCount": { + "type": "integer" + } + } + }, + "github_com_rede5_gohorsejobs_backend_internal_services.Message": { + "type": "object", + "properties": { + "content": { + "type": "string" + }, + "conversationId": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "id": { + "type": "string" + }, + "isMine": { + "description": "Populated by handler/frontend logic", + "type": "boolean" + }, + "senderId": { + "type": "string" + } + } + }, + "internal_handlers.CreateCheckoutRequest": { + "type": "object", + "properties": { + "cancelUrl": { + "description": "URL after cancel", + "type": "string" + }, + "jobId": { + "type": "integer" + }, + "priceId": { + "description": "Stripe Price ID", + "type": "string" + }, + "successUrl": { + "description": "URL after success", + "type": "string" + } + } + }, + "internal_handlers.CreateCheckoutResponse": { + "type": "object", + "properties": { + "checkoutUrl": { + "type": "string" + }, + "sessionId": { + "type": "string" + } + } + }, + "internal_handlers.DownloadURLRequest": { + "type": "object", + "properties": { + "key": { + "type": "string" + } + } + }, + "internal_handlers.DownloadURLResponse": { + "type": "object", + "properties": { + "downloadUrl": { + "type": "string" + }, + "expiresIn": { + "description": "seconds", + "type": "integer" + } + } + }, + "internal_handlers.UploadURLRequest": { + "type": "object", + "properties": { + "contentType": { + "type": "string" + }, + "filename": { + "type": "string" + }, + "folder": { + "description": "Optional: logos, resumes, documents", + "type": "string" + } + } + }, + "internal_handlers.UploadURLResponse": { + "type": "object", + "properties": { + "expiresIn": { + "description": "seconds", + "type": "integer" + }, + "key": { + "type": "string" + }, + "publicUrl": { + "type": "string" + }, + "uploadUrl": { + "type": "string" + } + } } } }` diff --git a/backend/docs/swagger.json b/backend/docs/swagger.json index e5cab07..b72d773 100644 --- a/backend/docs/swagger.json +++ b/backend/docs/swagger.json @@ -36,7 +36,7 @@ "schema": { "type": "array", "items": { - "$ref": "#/definitions/models.Application" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Application" } } }, @@ -73,7 +73,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.CreateApplicationRequest" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_dto.CreateApplicationRequest" } } ], @@ -81,7 +81,7 @@ "201": { "description": "Created", "schema": { - "$ref": "#/definitions/models.Application" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Application" } }, "400": { @@ -125,7 +125,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/models.Application" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Application" } }, "400": { @@ -209,7 +209,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.UpdateApplicationStatusRequest" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_dto.UpdateApplicationStatusRequest" } } ], @@ -217,7 +217,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/models.Application" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Application" } }, "400": { @@ -393,6 +393,224 @@ } } } + }, + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Deletes a company by ID (admin only)", + "tags": [ + "Companies" + ], + "summary": "Delete Company", + "parameters": [ + { + "type": "string", + "description": "Company ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "401": { + "description": "Unauthorized", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + }, + "patch": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Updates company information by ID (admin only)", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Companies" + ], + "summary": "Update Company", + "parameters": [ + { + "type": "string", + "description": "Company ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Company update data", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_dto.UpdateCompanyRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object" + } + }, + "400": { + "description": "Invalid Request", + "schema": { + "type": "string" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/conversations": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "List chat conversations for candidate or company", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Chat" + ], + "summary": "List Conversations", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_services.Conversation" + } + } + } + } + } + }, + "/api/v1/conversations/{id}/messages": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get message history for a conversation", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Chat" + ], + "summary": "List Messages", + "parameters": [ + { + "type": "string", + "description": "Conversation ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_services.Message" + } + } + } + } + }, + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Send a message to a conversation", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Chat" + ], + "summary": "Send Message", + "parameters": [ + { + "type": "string", + "description": "Conversation ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Message Content", + "name": "request", + "in": "body", + "required": true, + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_services.Message" + } + } + } } }, "/api/v1/jobs": { @@ -438,7 +656,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/dto.PaginatedResponse" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_dto.PaginatedResponse" } }, "500": { @@ -468,7 +686,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.CreateJobRequest" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_dto.CreateJobRequest" } } ], @@ -476,7 +694,7 @@ "201": { "description": "Created", "schema": { - "$ref": "#/definitions/models.Job" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Job" } }, "400": { @@ -526,7 +744,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/models.Job" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Job" } }, "400": { @@ -569,7 +787,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.UpdateJobRequest" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_dto.UpdateJobRequest" } } ], @@ -577,7 +795,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/models.Job" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Job" } }, "400": { @@ -773,7 +991,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/handlers.CreateCheckoutRequest" + "$ref": "#/definitions/internal_handlers.CreateCheckoutRequest" } } ], @@ -781,7 +999,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/handlers.CreateCheckoutResponse" + "$ref": "#/definitions/internal_handlers.CreateCheckoutResponse" } }, "400": { @@ -889,7 +1107,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/handlers.DownloadURLRequest" + "$ref": "#/definitions/internal_handlers.DownloadURLRequest" } } ], @@ -897,7 +1115,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/handlers.DownloadURLResponse" + "$ref": "#/definitions/internal_handlers.DownloadURLResponse" } }, "400": { @@ -986,7 +1204,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/handlers.UploadURLRequest" + "$ref": "#/definitions/internal_handlers.UploadURLRequest" } } ], @@ -994,7 +1212,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/handlers.UploadURLResponse" + "$ref": "#/definitions/internal_handlers.UploadURLResponse" } }, "400": { @@ -1098,6 +1316,57 @@ } } }, + "/api/v1/support/tickets/all": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Returns all support tickets for admin review.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Support" + ], + "summary": "List All Tickets (Admin)", + "parameters": [ + { + "type": "string", + "description": "Filter by status (open, in_progress, closed)", + "name": "status", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "type": "object" + } + } + }, + "403": { + "description": "Forbidden", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, "/api/v1/support/tickets/{id}": { "get": { "security": [ @@ -1145,6 +1414,161 @@ } } } + }, + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Deletes a support ticket (admin only).", + "tags": [ + "Support" + ], + "summary": "Delete Ticket", + "parameters": [ + { + "type": "string", + "description": "Ticket ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "401": { + "description": "Unauthorized", + "schema": { + "type": "string" + } + }, + "403": { + "description": "Forbidden", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + }, + "patch": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Updates a ticket's status and/or priority.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Support" + ], + "summary": "Update Ticket", + "parameters": [ + { + "type": "string", + "description": "Ticket ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Update data (status, priority)", + "name": "ticket", + "in": "body", + "required": true, + "schema": { + "type": "object" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object" + } + }, + "400": { + "description": "Invalid Request", + "schema": { + "type": "string" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/support/tickets/{id}/close": { + "patch": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Closes a support ticket.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Support" + ], + "summary": "Close Ticket", + "parameters": [ + { + "type": "string", + "description": "Ticket ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } } }, "/api/v1/support/tickets/{id}/messages": { @@ -1205,6 +1629,117 @@ } } }, + "/api/v1/system/credentials": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Saves encrypted credentials payload (e.g. Stripe key encrypted by Backoffice)", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "System" + ], + "summary": "Save Credentials", + "parameters": [ + { + "description": "Credentials Payload", + "name": "request", + "in": "body", + "required": true, + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "Invalid Request", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/tokens": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Saves or updates the FCM token for push notifications.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Notifications" + ], + "summary": "Save FCM Token", + "parameters": [ + { + "description": "FCM Token", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_core_dto.SaveFCMTokenRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "Invalid Request", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, "/api/v1/users": { "get": { "security": [ @@ -1342,7 +1877,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/dto.User" + "type": "object" } }, "401": { @@ -1570,7 +2105,18 @@ } }, "definitions": { - "dto.CreateApplicationRequest": { + "github_com_rede5_gohorsejobs_backend_internal_core_dto.SaveFCMTokenRequest": { + "type": "object", + "properties": { + "platform": { + "type": "string" + }, + "token": { + "type": "string" + } + } + }, + "github_com_rede5_gohorsejobs_backend_internal_dto.CreateApplicationRequest": { "type": "object", "required": [ "jobId" @@ -1609,7 +2155,7 @@ } } }, - "dto.CreateJobRequest": { + "github_com_rede5_gohorsejobs_backend_internal_dto.CreateJobRequest": { "type": "object", "required": [ "companyId", @@ -1634,7 +2180,12 @@ "USD", "EUR", "GBP", - "JPY" + "JPY", + "CNY", + "AED", + "CAD", + "AUD", + "CHF" ] }, "description": { @@ -1673,6 +2224,9 @@ "salaryMin": { "type": "number" }, + "salaryNegotiable": { + "type": "boolean" + }, "salaryType": { "type": "string", "enum": [ @@ -1710,16 +2264,16 @@ } } }, - "dto.PaginatedResponse": { + "github_com_rede5_gohorsejobs_backend_internal_dto.PaginatedResponse": { "type": "object", "properties": { "data": {}, "pagination": { - "$ref": "#/definitions/dto.Pagination" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_dto.Pagination" } } }, - "dto.Pagination": { + "github_com_rede5_gohorsejobs_backend_internal_dto.Pagination": { "type": "object", "properties": { "limit": { @@ -1733,7 +2287,7 @@ } } }, - "dto.UpdateApplicationStatusRequest": { + "github_com_rede5_gohorsejobs_backend_internal_dto.UpdateApplicationStatusRequest": { "type": "object", "required": [ "status" @@ -1754,7 +2308,58 @@ } } }, - "dto.UpdateJobRequest": { + "github_com_rede5_gohorsejobs_backend_internal_dto.UpdateCompanyRequest": { + "type": "object", + "properties": { + "active": { + "type": "boolean" + }, + "address": { + "type": "string" + }, + "cityId": { + "type": "integer" + }, + "description": { + "type": "string" + }, + "document": { + "type": "string" + }, + "email": { + "type": "string" + }, + "logoUrl": { + "type": "string" + }, + "name": { + "type": "string", + "maxLength": 255, + "minLength": 3 + }, + "phone": { + "type": "string" + }, + "regionId": { + "type": "integer" + }, + "slug": { + "type": "string", + "maxLength": 255, + "minLength": 3 + }, + "type": { + "type": "string" + }, + "verified": { + "type": "boolean" + }, + "website": { + "type": "string" + } + } + }, + "github_com_rede5_gohorsejobs_backend_internal_dto.UpdateJobRequest": { "type": "object", "properties": { "benefits": { @@ -1771,7 +2376,12 @@ "USD", "EUR", "GBP", - "JPY" + "JPY", + "CNY", + "AED", + "CAD", + "AUD", + "CHF" ] }, "description": { @@ -1810,6 +2420,9 @@ "salaryMin": { "type": "number" }, + "salaryNegotiable": { + "type": "boolean" + }, "salaryType": { "type": "string", "enum": [ @@ -1847,117 +2460,7 @@ } } }, - "dto.User": { - "type": "object", - "properties": { - "companyId": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "email": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "role": { - "type": "string" - }, - "status": { - "type": "string" - } - } - }, - "handlers.CreateCheckoutRequest": { - "type": "object", - "properties": { - "cancelUrl": { - "description": "URL after cancel", - "type": "string" - }, - "jobId": { - "type": "integer" - }, - "priceId": { - "description": "Stripe Price ID", - "type": "string" - }, - "successUrl": { - "description": "URL after success", - "type": "string" - } - } - }, - "handlers.CreateCheckoutResponse": { - "type": "object", - "properties": { - "checkoutUrl": { - "type": "string" - }, - "sessionId": { - "type": "string" - } - } - }, - "handlers.DownloadURLRequest": { - "type": "object", - "properties": { - "key": { - "type": "string" - } - } - }, - "handlers.DownloadURLResponse": { - "type": "object", - "properties": { - "downloadUrl": { - "type": "string" - }, - "expiresIn": { - "description": "seconds", - "type": "integer" - } - } - }, - "handlers.UploadURLRequest": { - "type": "object", - "properties": { - "contentType": { - "type": "string" - }, - "filename": { - "type": "string" - }, - "folder": { - "description": "Optional: logos, resumes, documents", - "type": "string" - } - } - }, - "handlers.UploadURLResponse": { - "type": "object", - "properties": { - "expiresIn": { - "description": "seconds", - "type": "integer" - }, - "key": { - "type": "string" - }, - "publicUrl": { - "type": "string" - }, - "uploadUrl": { - "type": "string" - } - } - }, - "models.Application": { + "github_com_rede5_gohorsejobs_backend_internal_models.Application": { "type": "object", "properties": { "createdAt": { @@ -1968,7 +2471,7 @@ "description": "Array of {type, url}", "allOf": [ { - "$ref": "#/definitions/models.JSONMap" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.JSONMap" } ] }, @@ -2017,15 +2520,15 @@ } } }, - "models.JSONMap": { + "github_com_rede5_gohorsejobs_backend_internal_models.JSONMap": { "type": "object", "additionalProperties": true }, - "models.Job": { + "github_com_rede5_gohorsejobs_backend_internal_models.Job": { "type": "object", "properties": { "benefits": { - "$ref": "#/definitions/models.JSONMap" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.JSONMap" }, "cityId": { "type": "integer" @@ -2073,7 +2576,7 @@ "description": "Requirements \u0026 Benefits (JSONB arrays)", "allOf": [ { - "$ref": "#/definitions/models.JSONMap" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.JSONMap" } ] }, @@ -2084,6 +2587,10 @@ "description": "Salary", "type": "number" }, + "salaryNegotiable": { + "description": "Candidate proposes salary", + "type": "boolean" + }, "salaryType": { "description": "hourly, daily, weekly, monthly, yearly", "type": "string" @@ -2111,6 +2618,146 @@ "type": "string" } } + }, + "github_com_rede5_gohorsejobs_backend_internal_services.Conversation": { + "type": "object", + "properties": { + "candidateId": { + "type": "string" + }, + "companyId": { + "type": "string" + }, + "id": { + "type": "string" + }, + "jobId": { + "type": "string" + }, + "lastMessage": { + "type": "string" + }, + "lastMessageAt": { + "type": "string" + }, + "participantAvatar": { + "type": "string" + }, + "participantName": { + "type": "string" + }, + "unreadCount": { + "type": "integer" + } + } + }, + "github_com_rede5_gohorsejobs_backend_internal_services.Message": { + "type": "object", + "properties": { + "content": { + "type": "string" + }, + "conversationId": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "id": { + "type": "string" + }, + "isMine": { + "description": "Populated by handler/frontend logic", + "type": "boolean" + }, + "senderId": { + "type": "string" + } + } + }, + "internal_handlers.CreateCheckoutRequest": { + "type": "object", + "properties": { + "cancelUrl": { + "description": "URL after cancel", + "type": "string" + }, + "jobId": { + "type": "integer" + }, + "priceId": { + "description": "Stripe Price ID", + "type": "string" + }, + "successUrl": { + "description": "URL after success", + "type": "string" + } + } + }, + "internal_handlers.CreateCheckoutResponse": { + "type": "object", + "properties": { + "checkoutUrl": { + "type": "string" + }, + "sessionId": { + "type": "string" + } + } + }, + "internal_handlers.DownloadURLRequest": { + "type": "object", + "properties": { + "key": { + "type": "string" + } + } + }, + "internal_handlers.DownloadURLResponse": { + "type": "object", + "properties": { + "downloadUrl": { + "type": "string" + }, + "expiresIn": { + "description": "seconds", + "type": "integer" + } + } + }, + "internal_handlers.UploadURLRequest": { + "type": "object", + "properties": { + "contentType": { + "type": "string" + }, + "filename": { + "type": "string" + }, + "folder": { + "description": "Optional: logos, resumes, documents", + "type": "string" + } + } + }, + "internal_handlers.UploadURLResponse": { + "type": "object", + "properties": { + "expiresIn": { + "description": "seconds", + "type": "integer" + }, + "key": { + "type": "string" + }, + "publicUrl": { + "type": "string" + }, + "uploadUrl": { + "type": "string" + } + } } } } \ No newline at end of file diff --git a/backend/docs/swagger.yaml b/backend/docs/swagger.yaml index 7af59b2..2f10387 100644 --- a/backend/docs/swagger.yaml +++ b/backend/docs/swagger.yaml @@ -1,6 +1,13 @@ basePath: / definitions: - dto.CreateApplicationRequest: + github_com_rede5_gohorsejobs_backend_internal_core_dto.SaveFCMTokenRequest: + properties: + platform: + type: string + token: + type: string + type: object + github_com_rede5_gohorsejobs_backend_internal_dto.CreateApplicationRequest: properties: documents: additionalProperties: true @@ -26,7 +33,7 @@ definitions: required: - jobId type: object - dto.CreateJobRequest: + github_com_rede5_gohorsejobs_backend_internal_dto.CreateJobRequest: properties: benefits: additionalProperties: true @@ -42,6 +49,11 @@ definitions: - EUR - GBP - JPY + - CNY + - AED + - CAD + - AUD + - CHF type: string description: minLength: 20 @@ -70,6 +82,8 @@ definitions: type: number salaryMin: type: number + salaryNegotiable: + type: boolean salaryType: enum: - hourly @@ -103,13 +117,13 @@ definitions: - description - title type: object - dto.PaginatedResponse: + github_com_rede5_gohorsejobs_backend_internal_dto.PaginatedResponse: properties: data: {} pagination: - $ref: '#/definitions/dto.Pagination' + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_dto.Pagination' type: object - dto.Pagination: + github_com_rede5_gohorsejobs_backend_internal_dto.Pagination: properties: limit: type: integer @@ -118,7 +132,7 @@ definitions: total: type: integer type: object - dto.UpdateApplicationStatusRequest: + github_com_rede5_gohorsejobs_backend_internal_dto.UpdateApplicationStatusRequest: properties: notes: type: string @@ -133,7 +147,42 @@ definitions: required: - status type: object - dto.UpdateJobRequest: + github_com_rede5_gohorsejobs_backend_internal_dto.UpdateCompanyRequest: + properties: + active: + type: boolean + address: + type: string + cityId: + type: integer + description: + type: string + document: + type: string + email: + type: string + logoUrl: + type: string + name: + maxLength: 255 + minLength: 3 + type: string + phone: + type: string + regionId: + type: integer + slug: + maxLength: 255 + minLength: 3 + type: string + type: + type: string + verified: + type: boolean + website: + type: string + type: object + github_com_rede5_gohorsejobs_backend_internal_dto.UpdateJobRequest: properties: benefits: additionalProperties: true @@ -147,6 +196,11 @@ definitions: - EUR - GBP - JPY + - CNY + - AED + - CAD + - AUD + - CHF type: string description: minLength: 20 @@ -175,6 +229,8 @@ definitions: type: number salaryMin: type: number + salaryNegotiable: + type: boolean salaryType: enum: - hourly @@ -204,87 +260,14 @@ definitions: workingHours: type: string type: object - dto.User: - properties: - companyId: - type: string - createdAt: - type: string - email: - type: string - id: - type: string - name: - type: string - role: - type: string - status: - type: string - type: object - handlers.CreateCheckoutRequest: - properties: - cancelUrl: - description: URL after cancel - type: string - jobId: - type: integer - priceId: - description: Stripe Price ID - type: string - successUrl: - description: URL after success - type: string - type: object - handlers.CreateCheckoutResponse: - properties: - checkoutUrl: - type: string - sessionId: - type: string - type: object - handlers.DownloadURLRequest: - properties: - key: - type: string - type: object - handlers.DownloadURLResponse: - properties: - downloadUrl: - type: string - expiresIn: - description: seconds - type: integer - type: object - handlers.UploadURLRequest: - properties: - contentType: - type: string - filename: - type: string - folder: - description: 'Optional: logos, resumes, documents' - type: string - type: object - handlers.UploadURLResponse: - properties: - expiresIn: - description: seconds - type: integer - key: - type: string - publicUrl: - type: string - uploadUrl: - type: string - type: object - models.Application: + github_com_rede5_gohorsejobs_backend_internal_models.Application: properties: createdAt: description: Metadata type: string documents: allOf: - - $ref: '#/definitions/models.JSONMap' + - $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.JSONMap' description: Array of {type, url} email: type: string @@ -317,13 +300,13 @@ definitions: whatsapp: type: string type: object - models.JSONMap: + github_com_rede5_gohorsejobs_backend_internal_models.JSONMap: additionalProperties: true type: object - models.Job: + github_com_rede5_gohorsejobs_backend_internal_models.Job: properties: benefits: - $ref: '#/definitions/models.JSONMap' + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.JSONMap' cityId: type: integer companyId: @@ -356,13 +339,16 @@ definitions: type: integer requirements: allOf: - - $ref: '#/definitions/models.JSONMap' + - $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.JSONMap' description: Requirements & Benefits (JSONB arrays) salaryMax: type: number salaryMin: description: Salary type: number + salaryNegotiable: + description: Candidate proposes salary + type: boolean salaryType: description: hourly, daily, weekly, monthly, yearly type: string @@ -383,6 +369,99 @@ definitions: workingHours: type: string type: object + github_com_rede5_gohorsejobs_backend_internal_services.Conversation: + properties: + candidateId: + type: string + companyId: + type: string + id: + type: string + jobId: + type: string + lastMessage: + type: string + lastMessageAt: + type: string + participantAvatar: + type: string + participantName: + type: string + unreadCount: + type: integer + type: object + github_com_rede5_gohorsejobs_backend_internal_services.Message: + properties: + content: + type: string + conversationId: + type: string + createdAt: + type: string + id: + type: string + isMine: + description: Populated by handler/frontend logic + type: boolean + senderId: + type: string + type: object + internal_handlers.CreateCheckoutRequest: + properties: + cancelUrl: + description: URL after cancel + type: string + jobId: + type: integer + priceId: + description: Stripe Price ID + type: string + successUrl: + description: URL after success + type: string + type: object + internal_handlers.CreateCheckoutResponse: + properties: + checkoutUrl: + type: string + sessionId: + type: string + type: object + internal_handlers.DownloadURLRequest: + properties: + key: + type: string + type: object + internal_handlers.DownloadURLResponse: + properties: + downloadUrl: + type: string + expiresIn: + description: seconds + type: integer + type: object + internal_handlers.UploadURLRequest: + properties: + contentType: + type: string + filename: + type: string + folder: + description: 'Optional: logos, resumes, documents' + type: string + type: object + internal_handlers.UploadURLResponse: + properties: + expiresIn: + description: seconds + type: integer + key: + type: string + publicUrl: + type: string + uploadUrl: + type: string + type: object info: contact: {} description: API for GoHorseJobs recruitment platform. @@ -407,7 +486,7 @@ paths: description: OK schema: items: - $ref: '#/definitions/models.Application' + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Application' type: array "400": description: Bad Request @@ -430,14 +509,14 @@ paths: name: application required: true schema: - $ref: '#/definitions/dto.CreateApplicationRequest' + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_dto.CreateApplicationRequest' produces: - application/json responses: "201": description: Created schema: - $ref: '#/definitions/models.Application' + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Application' "400": description: Bad Request schema: @@ -492,7 +571,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/models.Application' + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Application' "400": description: Bad Request schema: @@ -520,14 +599,14 @@ paths: name: body required: true schema: - $ref: '#/definitions/dto.UpdateApplicationStatusRequest' + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_dto.UpdateApplicationStatusRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/models.Application' + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Application' "400": description: Bad Request schema: @@ -621,6 +700,30 @@ paths: tags: - Companies /api/v1/companies/{id}: + delete: + description: Deletes a company by ID (admin only) + parameters: + - description: Company ID + in: path + name: id + required: true + type: string + responses: + "204": + description: No Content + "401": + description: Unauthorized + schema: + type: string + "500": + description: Internal Server Error + schema: + type: string + security: + - BearerAuth: [] + summary: Delete Company + tags: + - Companies get: consumes: - application/json @@ -645,6 +748,120 @@ paths: summary: Get Company tags: - Companies + patch: + consumes: + - application/json + description: Updates company information by ID (admin only) + parameters: + - description: Company ID + in: path + name: id + required: true + type: string + - description: Company update data + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_dto.UpdateCompanyRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + type: object + "400": + description: Invalid Request + schema: + type: string + "401": + description: Unauthorized + schema: + type: string + "500": + description: Internal Server Error + schema: + type: string + security: + - BearerAuth: [] + summary: Update Company + tags: + - Companies + /api/v1/conversations: + get: + consumes: + - application/json + description: List chat conversations for candidate or company + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_services.Conversation' + type: array + security: + - BearerAuth: [] + summary: List Conversations + tags: + - Chat + /api/v1/conversations/{id}/messages: + get: + consumes: + - application/json + description: Get message history for a conversation + parameters: + - description: Conversation ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_services.Message' + type: array + security: + - BearerAuth: [] + summary: List Messages + tags: + - Chat + post: + consumes: + - application/json + description: Send a message to a conversation + parameters: + - description: Conversation ID + in: path + name: id + required: true + type: string + - description: Message Content + in: body + name: request + required: true + schema: + additionalProperties: + type: string + type: object + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_services.Message' + security: + - BearerAuth: [] + summary: Send Message + tags: + - Chat /api/v1/jobs: get: consumes: @@ -673,7 +890,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/dto.PaginatedResponse' + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_dto.PaginatedResponse' "500": description: Internal Server Error schema: @@ -691,14 +908,14 @@ paths: name: job required: true schema: - $ref: '#/definitions/dto.CreateJobRequest' + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_dto.CreateJobRequest' produces: - application/json responses: "201": description: Created schema: - $ref: '#/definitions/models.Job' + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Job' "400": description: Bad Request schema: @@ -757,7 +974,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/models.Job' + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Job' "400": description: Bad Request schema: @@ -784,14 +1001,14 @@ paths: name: job required: true schema: - $ref: '#/definitions/dto.UpdateJobRequest' + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_dto.UpdateJobRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/models.Job' + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Job' "400": description: Bad Request schema: @@ -885,14 +1102,14 @@ paths: name: request required: true schema: - $ref: '#/definitions/handlers.CreateCheckoutRequest' + $ref: '#/definitions/internal_handlers.CreateCheckoutRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/handlers.CreateCheckoutResponse' + $ref: '#/definitions/internal_handlers.CreateCheckoutResponse' "400": description: Bad Request schema: @@ -960,14 +1177,14 @@ paths: name: request required: true schema: - $ref: '#/definitions/handlers.DownloadURLRequest' + $ref: '#/definitions/internal_handlers.DownloadURLRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/handlers.DownloadURLResponse' + $ref: '#/definitions/internal_handlers.DownloadURLResponse' "400": description: Bad Request schema: @@ -1021,14 +1238,14 @@ paths: name: request required: true schema: - $ref: '#/definitions/handlers.UploadURLRequest' + $ref: '#/definitions/internal_handlers.UploadURLRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/handlers.UploadURLResponse' + $ref: '#/definitions/internal_handlers.UploadURLResponse' "400": description: Bad Request schema: @@ -1097,6 +1314,34 @@ paths: tags: - Support /api/v1/support/tickets/{id}: + delete: + description: Deletes a support ticket (admin only). + parameters: + - description: Ticket ID + in: path + name: id + required: true + type: string + responses: + "204": + description: No Content + "401": + description: Unauthorized + schema: + type: string + "403": + description: Forbidden + schema: + type: string + "500": + description: Internal Server Error + schema: + type: string + security: + - BearerAuth: [] + summary: Delete Ticket + tags: + - Support get: consumes: - application/json @@ -1127,6 +1372,77 @@ paths: summary: Get Ticket Details tags: - Support + patch: + consumes: + - application/json + description: Updates a ticket's status and/or priority. + parameters: + - description: Ticket ID + in: path + name: id + required: true + type: string + - description: Update data (status, priority) + in: body + name: ticket + required: true + schema: + type: object + produces: + - application/json + responses: + "200": + description: OK + schema: + type: object + "400": + description: Invalid Request + schema: + type: string + "401": + description: Unauthorized + schema: + type: string + "500": + description: Internal Server Error + schema: + type: string + security: + - BearerAuth: [] + summary: Update Ticket + tags: + - Support + /api/v1/support/tickets/{id}/close: + patch: + consumes: + - application/json + description: Closes a support ticket. + parameters: + - description: Ticket ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + type: object + "401": + description: Unauthorized + schema: + type: string + "500": + description: Internal Server Error + schema: + type: string + security: + - BearerAuth: [] + summary: Close Ticket + tags: + - Support /api/v1/support/tickets/{id}/messages: post: consumes: @@ -1164,6 +1480,109 @@ paths: summary: Add Ticket Message tags: - Support + /api/v1/support/tickets/all: + get: + consumes: + - application/json + description: Returns all support tickets for admin review. + parameters: + - description: Filter by status (open, in_progress, closed) + in: query + name: status + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + type: object + type: array + "403": + description: Forbidden + schema: + type: string + "500": + description: Internal Server Error + schema: + type: string + security: + - BearerAuth: [] + summary: List All Tickets (Admin) + tags: + - Support + /api/v1/system/credentials: + post: + consumes: + - application/json + description: Saves encrypted credentials payload (e.g. Stripe key encrypted + by Backoffice) + parameters: + - description: Credentials Payload + in: body + name: request + required: true + schema: + additionalProperties: + type: string + type: object + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: + type: string + type: object + "400": + description: Invalid Request + schema: + type: string + "500": + description: Internal Server Error + schema: + type: string + security: + - BearerAuth: [] + summary: Save Credentials + tags: + - System + /api/v1/tokens: + post: + consumes: + - application/json + description: Saves or updates the FCM token for push notifications. + parameters: + - description: FCM Token + in: body + name: request + required: true + schema: + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_core_dto.SaveFCMTokenRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: + type: string + type: object + "400": + description: Invalid Request + schema: + type: string + "500": + description: Internal Server Error + schema: + type: string + security: + - BearerAuth: [] + summary: Save FCM Token + tags: + - Notifications /api/v1/users: get: consumes: @@ -1315,7 +1734,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/dto.User' + type: object "401": description: Unauthorized schema: diff --git a/backend/internal/api/handlers/core_handlers.go b/backend/internal/api/handlers/core_handlers.go index 197fae4..1032bb9 100644 --- a/backend/internal/api/handlers/core_handlers.go +++ b/backend/internal/api/handlers/core_handlers.go @@ -1035,7 +1035,7 @@ func (h *CoreHandlers) UploadMyAvatar(w http.ResponseWriter, r *http.Request) { // @Accept json // @Produce json // @Security BearerAuth -// @Success 200 {object} dto.User +// @Success 200 {object} object // @Failure 401 {string} string "Unauthorized" // @Failure 500 {string} string "Internal Server Error" // @Router /api/v1/users/me [get] @@ -1046,7 +1046,7 @@ func (h *CoreHandlers) UploadMyAvatar(w http.ResponseWriter, r *http.Request) { // @Accept json // @Produce json // @Security BearerAuth -// @Success 200 {object} dto.User +// @Success 200 {object} object // @Failure 401 {string} string "Unauthorized" // @Failure 500 {string} string "Internal Server Error" // @Router /api/v1/users/me [get]