371 lines
12 KiB
Markdown
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`.
|