Files
ContabilidadSaPolar/docs/tecnicas/api.md
T

371 lines
12 KiB
Markdown

# Referencia de la API REST
## Formato General
Todas las respuestas siguen el formato `ApiResponse<T>`:
```json
{
"success": true,
"message": "OK",
"data": { ... },
"timestamp": "2026-07-04T12:00:00"
}
```
Los errores usan el mismo formato con `success: false` y mensaje descriptivo.
## Autenticación
### `POST /api/auth/login`
Iniciar sesión.
**Request body:**
```json
{
"username": "admin",
"password": "admin123"
}
```
**Response (200):**
```json
{
"success": true,
"message": "OK",
"data": {
"accessToken": "eyJhbGciOi...",
"refreshToken": "eyJhbGciOi...",
"tokenType": "Bearer",
"userId": 1,
"username": "admin",
"role": "ADMIN"
}
}
```
### `POST /api/auth/register`
Registrar nuevo usuario.
**Request body:**
```json
{
"username": "usuario1",
"email": "user@example.com",
"password": "password123",
"fullName": "Usuario Ejemplo",
"phone": "600123456",
"roleName": "GERENTE"
}
```
### `POST /api/auth/refresh`
Renovar token de acceso.
**Request body:**
```json
{
"refreshToken": "eyJhbGciOi..."
}
```
## Usuarios (solo ADMIN)
| Método | Ruta | Descripción |
|--------|------|-------------|
| `GET` | `/api/users` | Listar todos los usuarios |
| `GET` | `/api/users/{id}` | Obtener usuario por ID |
| `PUT` | `/api/users/{id}` | Actualizar usuario |
| `DELETE` | `/api/users/{id}` | Desactivar usuario (soft-delete) |
## Propiedades
| Método | Ruta | Descripción |
|--------|------|-------------|
| `GET` | `/api/properties` | Listar propiedades activas |
| `GET` | `/api/properties/tree` | Obtener propiedades raíz (sin padre) |
| `GET` | `/api/properties/{id}/children` | Obtener hijos de una propiedad |
| `GET` | `/api/properties/{id}` | Obtener propiedad por ID |
| `POST` | `/api/properties` | Crear propiedad |
| `PUT` | `/api/properties/{id}` | Actualizar propiedad |
| `PATCH` | `/api/properties/{id}/status` | Cambiar estado de propiedad |
| `GET` | `/api/properties/{id}/history` | Historial de cambios de estado |
| `DELETE` | `/api/properties/{id}` | Eliminar propiedad (soft-delete) |
| `GET` | `/api/properties/types` | Listar tipos de propiedad |
| `GET` | `/api/properties/statuses` | Listar estados de propiedad |
**Estructura de Property:**
```json
{
"id": 1,
"parent": null,
"group": { "id": 1, "name": "Residencial Centro" },
"type": { "id": 2, "name": "PISO", "description": "Vivienda..." },
"status": { "id": 2, "name": "ALQUILADO", "description": "..." },
"reference": "PIS-001",
"name": "Piso Centro",
"addressStreet": "Calle Mayor",
"addressNumber": "12",
"addressCity": "Madrid",
"addressPostalCode": "28001",
"addressProvince": "Madrid",
"cadastralRef": "1234567VK1234A",
"surfaceM2": 85.50,
"floor": "3",
"door": "A",
"rentalAmount": 850.00,
"active": true
}
```
## Conjuntos (Property Groups)
| Método | Ruta | Descripción |
|--------|------|-------------|
| `GET` | `/api/property-groups` | Listar todos los conjuntos |
| `GET` | `/api/property-groups/{id}` | Obtener conjunto por ID |
| `POST` | `/api/property-groups` | Crear conjunto |
| `PUT` | `/api/property-groups/{id}` | Actualizar conjunto |
| `DELETE` | `/api/property-groups/{id}` | Eliminar conjunto |
| `GET` | `/api/property-groups/{id}/properties` | Propiedades pertenecientes al conjunto |
**Estructura de PropertyGroup:**
```json
{
"id": 1,
"name": "Residencial Centro",
"addressStreet": "Calle Mayor",
"addressNumber": "10",
"addressCity": "Madrid",
"addressPostalCode": "28001",
"isActive": true
}
```
## Inquilinos
| Método | Ruta | Descripción |
|--------|------|-------------|
| `GET` | `/api/tenants?search=` | Listar/buscar inquilinos |
| `GET` | `/api/tenants/{id}` | Obtener inquilino por ID |
| `POST` | `/api/tenants` | Crear inquilino |
| `PUT` | `/api/tenants/{id}` | Actualizar inquilino |
| `DELETE` | `/api/tenants/{id}` | Eliminar inquilino (soft-delete) |
## Contratos
| Método | Ruta | Descripción |
|--------|------|-------------|
| `GET` | `/api/contracts?propertyId=&tenantId=` | Listar/filtrar contratos |
| `GET` | `/api/contracts/{id}` | Obtener contrato por ID |
| `POST` | `/api/contracts` | Crear contrato (auto: propiedad → ALQUILADO) |
| `PUT` | `/api/contracts/{id}` | Actualizar contrato |
| `POST` | `/api/contracts/{id}/terminate` | Terminar contrato (auto: propiedad → VACIO) |
## Recibos de Ingresos (Income Receipts)
| Método | Ruta | Descripción |
|--------|------|-------------|
| `GET` | `/api/income-receipts?propertyId=&contractId=&from=&to=&statusId=` | Listar/filtrar recibos de ingresos |
| `GET` | `/api/income-receipts/pending` | Total pendiente de cobro |
| `GET` | `/api/income-receipts/{id}` | Obtener recibo por ID |
| `POST` | `/api/income-receipts` | Crear recibo |
| `PUT` | `/api/income-receipts/{id}` | Actualizar recibo |
| `PATCH` | `/api/income-receipts/{id}/pay` | Registrar pago |
| `DELETE` | `/api/income-receipts/{id}` | Eliminar recibo |
## Plantillas de Gastos (Expense Templates)
| Método | Ruta | Descripción |
|--------|------|-------------|
| `GET` | `/api/expense-templates?propertyId=&categoryId=` | Listar/filtrar plantillas |
| `GET` | `/api/expense-templates/active` | Plantillas activas |
| `GET` | `/api/expense-templates/{id}` | Obtener plantilla por ID |
| `POST` | `/api/expense-templates` | Crear plantilla |
| `PUT` | `/api/expense-templates/{id}` | Actualizar plantilla |
| `PATCH` | `/api/expense-templates/{id}/toggle` | Activar/desactivar plantilla |
| `POST` | `/api/expense-templates/{id}/generate` | Generar recibo de gasto desde plantilla |
| `DELETE` | `/api/expense-templates/{id}` | Eliminar plantilla |
## Recibos de Gastos (Expense Receipts)
| Método | Ruta | Descripción |
|--------|------|-------------|
| `GET` | `/api/expense-receipts?propertyId=&templateId=&from=&to=&statusId=` | Listar/filtrar recibos de gastos |
| `GET` | `/api/expense-receipts/{id}` | Obtener recibo por ID |
| `POST` | `/api/expense-receipts` | Crear recibo manual |
| `PUT` | `/api/expense-receipts/{id}` | Actualizar recibo |
| `PATCH` | `/api/expense-receipts/{id}/pay` | Registrar pago |
| `DELETE` | `/api/expense-receipts/{id}` | Eliminar recibo |
## Incidencias
| Método | Ruta | Descripción |
|--------|------|-------------|
| `GET` | `/api/incidents?propertyId=&statusId=` | Listar/filtrar incidencias |
| `GET` | `/api/incidents/{id}` | Obtener incidencia por ID |
| `POST` | `/api/incidents` | Crear incidencia |
| `PATCH` | `/api/incidents/{id}/status` | Actualizar estado |
| `PATCH` | `/api/incidents/{id}/assign` | Asignar técnico |
| `PATCH` | `/api/incidents/{id}/schedule` | Programar reparación |
| `DELETE` | `/api/incidents/{id}` | Eliminar incidencia |
**Flujo de estados de incidencia:**
`SIN_REVISAR``TECNICO_AVISADO``REPARACION_PREVISTA``REPARADO`
`IGNORADO`
`ANULADO`
## Mantenimiento Programado
| Método | Ruta | Descripción |
|--------|------|-------------|
| `GET` | `/api/maintenance?propertyId=` | Listar mantenimientos |
| `GET` | `/api/maintenance/pending` | Mantenimientos pendientes |
| `GET` | `/api/maintenance/upcoming?from=&to=` | Próximos mantenimientos |
| `GET` | `/api/maintenance/{id}` | Obtener por ID |
| `POST` | `/api/maintenance` | Crear mantenimiento |
| `PUT` | `/api/maintenance/{id}` | Actualizar |
| `PATCH` | `/api/maintenance/{id}/complete` | Marcar completado |
| `DELETE` | `/api/maintenance/{id}` | Eliminar |
## Recibos
| Método | Ruta | Descripción | Rol |
|--------|------|-------------|-----|
| `GET` | `/api/receipts` | Listar recibos | ADMIN, GERENTE, CONTABLE |
| `GET` | `/api/receipts/{id}` | Obtener recibo | ADMIN, GERENTE, CONTABLE |
| `POST` | `/api/receipts/generate` | Generar recibo individual | ADMIN, GERENTE, CONTABLE |
| `POST` | `/api/receipts/generate-monthly` | Generar recibos mensuales | ADMIN |
| `GET` | `/api/receipts/{id}/pdf` | Descargar PDF | ADMIN, GERENTE, CONTABLE |
| `POST` | `/api/receipts/{id}/send-email` | Enviar por email | ADMIN, GERENTE, CONTABLE |
| `GET` | `/api/receipts/reports/monthly?year=&month=` | Reporte Excel mensual | ADMIN, GERENTE, CONTABLE |
### `POST /api/receipts/generate`
Genera un recibo individual para un contrato específico.
**Request body:**
```json
{
"contractId": 1,
"issueDate": "2026-07-01",
"dueDate": "2026-07-15",
"description": "Alquiler julio 2026"
}
```
### `POST /api/receipts/generate-monthly`
Genera recibos para todos los contratos activos cuyo `payment_day` coincida con el mes actual. Solo ADMIN.
### `GET /api/receipts/{id}/pdf`
Devuelve el PDF del recibo como `application/pdf` con header `Content-Disposition: attachment; filename="recibo-R-2026-00001.pdf"`.
### `POST /api/receipts/{id}/send-email`
Envía el recibo por email al inquilino con el PDF adjunto.
### `GET /api/receipts/reports/monthly?year=2026&month=7`
Descarga un informe Excel (`.xlsx`) con el resumen de recibos de ingresos, recibos de gastos y balance del mes.
## Notificaciones
| Método | Ruta | Descripción |
|--------|------|-------------|
| `GET` | `/api/notifications?unreadOnly=true` | Listar notificaciones del usuario |
| `GET` | `/api/notifications/unread-count` | Contar no leídas |
| `PATCH` | `/api/notifications/{id}/read` | Marcar como leída |
| `PATCH` | `/api/notifications/read-all` | Marcar todas como leídas |
## Dashboard
| Método | Ruta | Descripción |
|--------|------|-------------|
| `GET` | `/api/dashboard/summary` | Resumen general (contadores, YTD) |
| `GET` | `/api/dashboard/income-expense?year=2026` | Ingresos/gastos mensuales del año |
**Respuesta de `/summary`:**
```json
{
"success": true,
"data": {
"totalProperties": 10,
"rentedProperties": 5,
"activeContracts": 5,
"totalTenants": 8,
"openIncidents": 2,
"pendingMaintenance": 1,
"incomeYtd": 42500.00,
"expenseYtd": 12300.00,
"pendingIncome": 2850.00
}
}
```
## Documentos
| Método | Ruta | Descripción |
|--------|------|-------------|
| `POST` | `/api/documents/upload` | Subir archivo (multipart) |
| `GET` | `/api/documents/entity/{entityType}/{entityId}` | Documentos de una entidad |
| `GET` | `/api/documents/types-for-entity/{entityType}` | Tipos de documento permitidos para una entidad |
| `GET` | `/api/documents/search` | Búsqueda avanzada con filtros |
| `GET` | `/api/documents/{id}/download` | Descargar documento |
| `DELETE` | `/api/documents/{id}` | Eliminar documento |
| `GET` | `/api/documents/{id}/entities` | Ver entidades asociadas a un documento |
| `POST` | `/api/documents/{id}/entities` | Asociar documento a otra entidad |
| `DELETE` | `/api/documents/{id}/entities/{entityType}/{entityId}` | Desasociar documento de una entidad |
**Tipos de entidad soportados:** `PROPERTY`, `CONTRACT`, `TENANT`, `INCIDENT`, `MAINTENANCE`
**Upload params:** `file` (multipart), `entityType`, `entityId`, `documentTypeId`, `description` (opcional)
### `GET /api/documents/types-for-entity/{entityType}`
Devuelve los tipos de documento permitidos para una entidad, indicando cuáles son obligatorios.
**Response (200):**
```json
{
"success": true,
"data": [
{
"documentTypeId": 1,
"documentTypeName": "CONTRATO",
"canUpload": true,
"mustHave": true,
"description": "Documento principal del contrato de alquiler"
},
{
"documentTypeId": 10,
"documentTypeName": "OTRO",
"canUpload": true,
"mustHave": false,
"description": "Otros documentos del contrato"
}
]
}
```
## Códigos de Error
| Código | Significado |
|--------|-------------|
| 200 | OK |
| 201 | Creado |
| 400 | Bad Request (validación, datos incorrectos) |
| 401 | No autenticado |
| 403 | No autorizado (rol insuficiente) |
| 404 | Recurso no encontrado |
| 409 | Conflicto (duplicado) |
| 500 | Error interno del servidor |
## Documentación Interactiva (Swagger)
Disponible en `http://localhost:8080/swagger-ui.html` cuando el backend está corriendo. También se puede obtener el spec OpenAPI en `http://localhost:8080/api-docs`.