570 lines
23 KiB
Markdown
570 lines
23 KiB
Markdown
# Esquema de Base de Datos
|
|
|
|
## Visión General
|
|
|
|
Base de datos MySQL 8 con 24 tablas. El esquema se inicializa mediante `db/init.sql` en el arranque del contenedor MySQL. Hibernate opera en modo `validate` para verificar que el mapeo JPA coincida con el esquema.
|
|
|
|
## Diagrama de Tablas
|
|
|
|
```
|
|
property_groups ──── properties ──── property_types
|
|
│ │ property_statuses
|
|
│ └── property_status_history
|
|
│
|
|
roles ──── users ──── user_permissions
|
|
│
|
|
│
|
|
├── tenants ──── tenant_types
|
|
│
|
|
├── contracts ──── contract_statuses
|
|
│ │ payment_periods
|
|
│ │
|
|
│ └── income_receipts ──── income_categories
|
|
│ │ income_statuses
|
|
│ │
|
|
│ └── email_log
|
|
│
|
|
├── expense_templates ──── expense_categories
|
|
│ expense_statuses
|
|
│ payment_periods
|
|
│
|
|
├── expense_receipts ──── expense_categories
|
|
│ expense_statuses
|
|
│
|
|
├── incidents ──── incident_statuses
|
|
│ incident_priorities
|
|
│
|
|
├── scheduled_maintenance ──── maintenance_periods
|
|
│
|
|
└── notifications ──── notification_types
|
|
|
|
documents ──── document_types ──── document_type_entity_allowed
|
|
|
|
receipt_series
|
|
```
|
|
|
|
## Tablas Detalladas
|
|
|
|
### 1. roles
|
|
|
|
| Columna | Tipo | Descripción |
|
|
|---------|------|-------------|
|
|
| id | INT PK | Auto-increment |
|
|
| name | VARCHAR(30) UNIQUE | Nombre del rol |
|
|
| description | VARCHAR(255) | Descripción |
|
|
|
|
**Datos semilla:** ADMIN, GERENTE, CONTABLE, VISUALIZADOR
|
|
|
|
### 2. users
|
|
|
|
| Columna | Tipo | Descripción |
|
|
|---------|------|-------------|
|
|
| id | BIGINT PK | Auto-increment |
|
|
| username | VARCHAR(50) UNIQUE | Nombre de usuario |
|
|
| email | VARCHAR(100) UNIQUE | Correo electrónico |
|
|
| password_hash | VARCHAR(255) | Hash BCrypt |
|
|
| full_name | VARCHAR(150) | Nombre completo |
|
|
| phone | VARCHAR(20) | Teléfono |
|
|
| role_id | INT FK → roles(id) | Rol del usuario |
|
|
| active | BOOLEAN | Usuario activo (soporta soft-delete) |
|
|
| created_at | DATETIME | Fecha de creación |
|
|
| updated_at | DATETIME | Fecha de modificación |
|
|
| last_login | DATETIME | Último inicio de sesión |
|
|
|
|
### 3. user_permissions
|
|
|
|
| Columna | Tipo | Descripción |
|
|
|---------|------|-------------|
|
|
| id | BIGINT PK | Auto-increment |
|
|
| user_id | BIGINT FK → users(id) CASCADE | Usuario |
|
|
| permission | VARCHAR(50) | Permiso específico |
|
|
| granted | BOOLEAN | Concedido/denegado |
|
|
|
|
**Unique:** (user_id, permission)
|
|
|
|
### 4. property_types
|
|
|
|
| Columna | Tipo | Descripción |
|
|
|---------|------|-------------|
|
|
| id | INT PK | Auto-increment |
|
|
| name | VARCHAR(50) UNIQUE | Tipo (EDIFICIO, PISO, etc.) |
|
|
| description | VARCHAR(255) | Descripción |
|
|
|
|
### 5. property_statuses
|
|
|
|
| Columna | Tipo | Descripción |
|
|
|---------|------|-------------|
|
|
| id | INT PK | Auto-increment |
|
|
| name | VARCHAR(50) UNIQUE | Estado (DISPONIBLE, ALQUILADO, etc.) |
|
|
| description | VARCHAR(255) | Descripción |
|
|
|
|
### 6. properties
|
|
|
|
| Columna | Tipo | Descripción |
|
|
|---------|------|-------------|
|
|
| id | BIGINT PK | Auto-increment |
|
|
| parent_id | BIGINT FK → properties(id) SET NULL | Propiedad padre (jerarquía) |
|
|
| group_id | BIGINT FK → property_groups(id) SET NULL | Conjunto al que pertenece |
|
|
| type_id | INT FK → property_types(id) | Tipo de propiedad |
|
|
| status_id | INT FK → property_statuses(id) | Estado actual |
|
|
| reference | VARCHAR(50) UNIQUE | Referencia interna |
|
|
| name | VARCHAR(200) | Nombre identificativo |
|
|
| description | TEXT | Descripción |
|
|
| address_street | VARCHAR(200) | Calle |
|
|
| address_number | VARCHAR(20) | Número |
|
|
| address_city | VARCHAR(100) | Ciudad |
|
|
| address_postal_code | VARCHAR(10) | Código postal |
|
|
| address_province | VARCHAR(100) | Provincia |
|
|
| cadastral_ref | VARCHAR(30) | Referencia catastral |
|
|
| surface_m2 | DECIMAL(10,2) | Superficie en m² |
|
|
| floor | VARCHAR(50) | Planta / Piso |
|
|
| door | VARCHAR(50) | Puerta |
|
|
| rental_amount | DECIMAL(12,2) | Importe de alquiler |
|
|
| rented_since | DATE | Alquilado desde |
|
|
| vacant_since | DATE | Vacío desde |
|
|
| occupied_since | DATE | Ocupado desde |
|
|
| notes | TEXT | Notas |
|
|
| active | BOOLEAN | Activo (soft-delete) |
|
|
| created_by | BIGINT FK → users(id) SET NULL | Creado por |
|
|
| created_at | DATETIME | Creación |
|
|
| updated_at | DATETIME | Modificación |
|
|
|
|
**Índices:** parent, type, status, active
|
|
|
|
### 7. property_status_history
|
|
|
|
| Columna | Tipo | Descripción |
|
|
|---------|------|-------------|
|
|
| id | BIGINT PK | Auto-increment |
|
|
| property_id | BIGINT FK → properties(id) CASCADE | Propiedad |
|
|
| status_id | INT FK → property_statuses(id) | Nuevo estado |
|
|
| changed_by | BIGINT FK → users(id) SET NULL | Quién cambió |
|
|
| changed_at | DATETIME | Cuándo |
|
|
| notes | VARCHAR(500) | Motivo del cambio |
|
|
|
|
### 8. property_groups
|
|
|
|
| Columna | Tipo | Descripción |
|
|
|---------|------|-------------|
|
|
| id | BIGINT PK | Auto-increment |
|
|
| name | VARCHAR(200) | Nombre del conjunto |
|
|
| address_street | VARCHAR(200) | Calle |
|
|
| address_number | VARCHAR(20) | Número |
|
|
| address_city | VARCHAR(100) | Ciudad |
|
|
| address_postal_code | VARCHAR(10) | Código postal |
|
|
| is_active | BOOLEAN | Activo |
|
|
| created_at | DATETIME | Creación |
|
|
| updated_at | DATETIME | Modificación |
|
|
|
|
**Relaciones:** Una propiedad puede pertenecer opcionalmente a un conjunto. Al eliminar un conjunto, las propiedades asociadas quedan con `group_id = NULL` (`ON DELETE SET NULL`).
|
|
|
|
### 9. tenant_types
|
|
|
|
| Columna | Tipo | Descripción |
|
|
|---------|------|-------------|
|
|
| id | INT PK | Auto-increment |
|
|
| name | VARCHAR(30) UNIQUE | PERSONA_FISICA / PERSONA_JURIDICA |
|
|
|
|
### 10. tenants
|
|
|
|
| Columna | Tipo | Descripción |
|
|
|---------|------|-------------|
|
|
| id | BIGINT PK | Auto-increment |
|
|
| tenant_type_id | INT FK → tenant_types(id) | Tipo de inquilino |
|
|
| fiscal_id | VARCHAR(20) UNIQUE | DNI/NIF/CIF |
|
|
| full_name | VARCHAR(200) | Nombre o razón social |
|
|
| business_name | VARCHAR(200) | Solo personas jurídicas |
|
|
| email | VARCHAR(100) | Correo electrónico |
|
|
| phone | VARCHAR(20) | Teléfono |
|
|
| address | VARCHAR(300) | Dirección |
|
|
| iban | VARCHAR(34) | IBAN para domiciliación |
|
|
| notes | TEXT | Notas |
|
|
| active | BOOLEAN | Activo (soft-delete) |
|
|
| created_at | DATETIME | Creación |
|
|
| updated_at | DATETIME | Modificación |
|
|
|
|
### 11. contract_statuses
|
|
|
|
| Columna | Tipo | Descripción |
|
|
|---------|------|-------------|
|
|
| id | INT PK | Auto-increment |
|
|
| name | VARCHAR(30) UNIQUE | ACTIVO, VENCIDO, RENOVADO, RESCINDIDO, ANULADO |
|
|
|
|
### 12. payment_periods
|
|
|
|
| Columna | Tipo | Descripción |
|
|
|---------|------|-------------|
|
|
| id | INT PK | Auto-increment |
|
|
| name | VARCHAR(30) UNIQUE | MENSUAL, TRIMESTRAL, SEMESTRAL, ANUAL |
|
|
|
|
### 13. contracts
|
|
|
|
| Columna | Tipo | Descripción |
|
|
|---------|------|-------------|
|
|
| id | BIGINT PK | Auto-increment |
|
|
| property_id | BIGINT FK → properties(id) | Propiedad |
|
|
| tenant_id | BIGINT FK → tenants(id) | Inquilino |
|
|
| status_id | INT FK → contract_statuses(id) | Estado |
|
|
| period_id | INT FK → payment_periods(id) DEFAULT 1 | Período de pago |
|
|
| contract_number | VARCHAR(50) UNIQUE | Número de contrato |
|
|
| start_date | DATE | Fecha de inicio |
|
|
| end_date | DATE | Fecha de fin |
|
|
| renewal_date | DATE | Fecha de renovación |
|
|
| rental_amount | DECIMAL(12,2) | Renta mensual |
|
|
| deposit_amount | DECIMAL(12,2) | Fianza |
|
|
| payment_day | INT DEFAULT 1 | Día de pago |
|
|
| payment_day_end | INT DEFAULT NULL | Día final del rango de pago (NULL = día único) |
|
|
| iban_charge | VARCHAR(34) | IBAN domiciliación |
|
|
| notes | TEXT | Notas |
|
|
| signed_at | DATE | Fecha de firma |
|
|
| terminated_at | DATE | Fecha de terminación |
|
|
| termination_cause | VARCHAR(500) | Causa de terminación |
|
|
| created_by | BIGINT FK → users(id) SET NULL | Creado por |
|
|
| created_at | DATETIME | Creación |
|
|
| updated_at | DATETIME | Modificación |
|
|
|
|
### 14. document_types
|
|
|
|
| Columna | Tipo | Descripción |
|
|
|---------|------|-------------|
|
|
| id | INT PK | Auto-increment |
|
|
| name | VARCHAR(50) UNIQUE | Tipo de documento |
|
|
|
|
**Tipos:** CONTRATO, ANEXO_CONTRATO, DNI_ARREENDATARIO, CIF_EMPRESA, FOTO_PROPIEDAD, FOTO_INCIDENCIA, FACTURA, JUSTIFICANTE_PAGO, CERTIFICADO, OTRO
|
|
|
|
### 16. documents
|
|
|
|
| Columna | Tipo | Descripción |
|
|
|---------|------|-------------|
|
|
| id | BIGINT PK | Auto-increment |
|
|
| document_type_id | INT FK → document_types(id) | Tipo |
|
|
| original_name | VARCHAR(255) | Nombre original del archivo |
|
|
| stored_name | VARCHAR(255) | Nombre almacenado en disco (UUID + extensión) |
|
|
| mime_type | VARCHAR(100) | Tipo MIME |
|
|
| file_size | BIGINT | Tamaño en bytes |
|
|
| description | VARCHAR(500) | Descripción |
|
|
| uploaded_by | BIGINT FK → users(id) SET NULL | Subido por |
|
|
| uploaded_at | DATETIME | Fecha de subida |
|
|
|
|
**Relaciones:** Relación One-to-Many con `document_entities`.
|
|
|
|
### 17. document_entities (tabla pivote)
|
|
|
|
| Columna | Tipo | Descripción |
|
|
|---------|------|-------------|
|
|
| id | BIGINT PK | Auto-increment |
|
|
| document_id | BIGINT FK → documents(id) CASCADE | Documento |
|
|
| entity_type | VARCHAR(30) | Tipo de entidad asociada |
|
|
| entity_id | BIGINT | ID de la entidad |
|
|
| created_at | DATETIME | Fecha de creación |
|
|
|
|
**Entidades soportadas:** PROPERTY, TENANT, CONTRACT, INCOME, EXPENSE, INCIDENT, MAINTENANCE
|
|
|
|
**Caso de uso:** Permite asociar un mismo documento a múltiples entidades. Por ejemplo, una fianza puede estar asociada tanto a un INCOME (cuando se recibe) como a un EXPENSE (cuando se devuelve).
|
|
|
|
**Índices:** UNIQUE(document_id, entity_type, entity_id), INDEX(entity_type, entity_id)
|
|
|
|
### 17. document_type_entity_allowed (tabla pivote)
|
|
|
|
Define qué tipos de documento pueden asociarse a qué tipos de entidades del sistema.
|
|
|
|
| Columna | Tipo | Descripción |
|
|
|---------|------|-------------|
|
|
| id | INT PK | Auto-increment |
|
|
| document_type_id | INT FK → document_types(id) | Tipo de documento |
|
|
| entity_type | VARCHAR(30) | Tipo de entidad (PROPERTY, TENANT, CONTRACT, INCOME, EXPENSE, INCIDENT, MAINTENANCE) |
|
|
| can_upload | BOOLEAN | Si el usuario puede subir este tipo en esta entidad |
|
|
| must_have | BOOLEAN | Si es obligatorio al crear/editar la entidad |
|
|
| description | VARCHAR(255) | Descripción del uso del documento |
|
|
| created_at | DATETIME | Fecha de creación |
|
|
|
|
**Relaciones permitidas:**
|
|
|
|
| Tipo Documento | Entidad | Obligatorio | Descripción |
|
|
|----------------|---------|-------------|-------------|
|
|
| CONTRATO | CONTRACT | Sí | Documento principal del contrato |
|
|
| CONTRATO | TENANT | No | Copia firmada por inquilino |
|
|
| CONTRATO | PROPERTY | No | Contrato asociado al inmueble |
|
|
| ANEXO_CONTRATO | CONTRACT | No | Anexos y modificaciones |
|
|
| DNI_ARRENDATARIO | TENANT | Sí | DNI del inquilino |
|
|
| CIF_EMPRESA | TENANT | No | Para personas jurídicas |
|
|
| FOTO_PROPIEDAD | PROPERTY | Sí | Fotos del inmueble |
|
|
| FOTO_INCIDENCIA | INCIDENT | No | Fotos de la incidencia |
|
|
| FACTURA | EXPENSE | Sí | Factura o justificante del gasto |
|
|
| JUSTIFICANTE_PAGO | INCOME | Sí | Justificante de pago |
|
|
| CERTIFICADO | TENANT | No | Certificados varios |
|
|
| CERTIFICADO | CONTRACT | No | Certificados asociados |
|
|
| OTRO | Todas | No | Otros documentos |
|
|
|
|
**Índices:** UNIQUE(document_type_id, entity_type), INDEX(entity_type)
|
|
|
|
### 18. income_categories
|
|
|
|
| Columna | Tipo | Descripción |
|
|
|---------|------|-------------|
|
|
| id | BIGINT PK | Auto-increment |
|
|
| name | VARCHAR(100) | Nombre |
|
|
| description | VARCHAR(255) | Descripción |
|
|
| active | BOOLEAN | Activo |
|
|
|
|
**Categorías:** ALQUILER, FIANZA, GASTOS_COMUNIDAD, INTERESES_DEMORA, INDEMNIZACION, OTROS_INGRESOS
|
|
|
|
### 17. income_statuses
|
|
|
|
| Columna | Tipo | Descripción |
|
|
|---------|------|-------------|
|
|
| id | INT PK | Auto-increment |
|
|
| name | VARCHAR(30) UNIQUE | PENDIENTE, PAGADO, VENCIDO, PARCIAL, ANULADO |
|
|
|
|
### 18. income_receipts
|
|
|
|
| Columna | Tipo | Descripción |
|
|
|---------|------|-------------|
|
|
| id | BIGINT PK | Auto-increment |
|
|
| contract_id | BIGINT FK → contracts(id) SET NULL | Contrato asociado |
|
|
| property_id | BIGINT FK → properties(id) | Propiedad (NOT NULL) |
|
|
| tenant_id | BIGINT FK → tenants(id) SET NULL | Inquilino |
|
|
| bank_account_id | BIGINT FK → bank_accounts(id) SET NULL | Cuenta bancaria |
|
|
| is_domiciled | BOOLEAN DEFAULT FALSE | Domiciliado |
|
|
| category_id | BIGINT FK → income_categories(id) SET NULL | Categoría |
|
|
| status_id | INT FK → income_statuses(id) | Estado |
|
|
| period_label | VARCHAR(20) | Etiqueta de período (ej: "2026-07") |
|
|
| amount | DECIMAL(12,2) | Importe bruto |
|
|
| tax_withheld | DECIMAL(12,2) DEFAULT 0 | Retención IRPF |
|
|
| net_amount | DECIMAL(12,2) | Importe neto |
|
|
| issue_date | DATE | Fecha de emisión |
|
|
| due_date | DATE | Fecha de vencimiento |
|
|
| payment_date | DATE | Fecha de pago |
|
|
| payment_method | VARCHAR(30) | TRANSFERENCIA / EFECTIVO / BIZUM / RECIBO / TARJETA |
|
|
| description | VARCHAR(500) | Descripción |
|
|
| receipt_number | VARCHAR(50) | Número de recibo |
|
|
| notes | TEXT | Notas |
|
|
| created_by | BIGINT FK → users(id) SET NULL | Creado por |
|
|
| created_at | DATETIME | Creación |
|
|
| updated_at | DATETIME | Modificación |
|
|
|
|
### 19. expense_categories
|
|
|
|
| Columna | Tipo | Descripción |
|
|
|---------|------|-------------|
|
|
| id | BIGINT PK | Auto-increment |
|
|
| name | VARCHAR(100) | Nombre |
|
|
| description | VARCHAR(255) | Descripción |
|
|
| active | BOOLEAN | Activo |
|
|
|
|
### 20. expense_statuses
|
|
|
|
| Columna | Tipo | Descripción |
|
|
|---------|------|-------------|
|
|
| id | INT PK | Auto-increment |
|
|
| name | VARCHAR(30) UNIQUE | PENDIENTE, PAGADO, VENCIDO, ANULADO |
|
|
|
|
### 21. expense_templates
|
|
|
|
| Columna | Tipo | Descripción |
|
|
|---------|------|-------------|
|
|
| id | BIGINT PK | Auto-increment |
|
|
| property_id | BIGINT FK → properties(id) NULL | Propiedad asociada |
|
|
| property_group_id | BIGINT FK → property_groups(id) NULL | Conjunto asociado |
|
|
| bank_account_id | BIGINT FK → bank_accounts(id) NULL | Cuenta bancaria |
|
|
| is_domiciled | BOOLEAN DEFAULT FALSE | Domiciliado |
|
|
| category_id | BIGINT FK → expense_categories(id) SET NULL | Categoría |
|
|
| period_id | INT FK → payment_periods(id) | Periodicidad |
|
|
| payment_day | INT DEFAULT 1 | Día de pago |
|
|
| supplier_name | VARCHAR(200) | Proveedor |
|
|
| supplier_fiscal_id | VARCHAR(20) | NIF/CIF |
|
|
| amount | DECIMAL(12,2) NULL | Importe fijo (NULL = variable) |
|
|
| tax_amount | DECIMAL(12,2) | Importe impuestos |
|
|
| description | VARCHAR(500) | Concepto |
|
|
| notes | TEXT | Notas |
|
|
| is_variable | BOOLEAN DEFAULT FALSE | Importe variable (usuario rellena cada mes) |
|
|
| active | BOOLEAN DEFAULT TRUE | Template activo/inactivo |
|
|
| created_by | BIGINT FK → users(id) SET NULL | Creador |
|
|
| created_at | DATETIME | Creación |
|
|
| updated_at | DATETIME | Modificación |
|
|
|
|
### 22. expense_receipts
|
|
|
|
| Columna | Tipo | Descripción |
|
|
|---------|------|-------------|
|
|
| id | BIGINT PK | Auto-increment |
|
|
| template_id | BIGINT FK → expense_templates(id) SET NULL | Template origen (NULL = gasto manual) |
|
|
| property_id | BIGINT FK → properties(id) NULL | Propiedad asociada |
|
|
| property_group_id | BIGINT FK → property_groups(id) NULL | Conjunto asociado |
|
|
| bank_account_id | BIGINT FK → bank_accounts(id) NULL | Cuenta bancaria |
|
|
| is_domiciled | BOOLEAN DEFAULT FALSE | Domiciliado |
|
|
| category_id | BIGINT FK → expense_categories(id) SET NULL | Categoría |
|
|
| status_id | INT FK → expense_statuses(id) | Estado |
|
|
| supplier_name | VARCHAR(200) | Proveedor |
|
|
| supplier_fiscal_id | VARCHAR(20) | NIF/CIF |
|
|
| invoice_number | VARCHAR(50) | Número de factura |
|
|
| amount | DECIMAL(12,2) DEFAULT 0 | Base imponible |
|
|
| tax_amount | DECIMAL(12,2) DEFAULT 0 | Importe impuestos |
|
|
| total_amount | DECIMAL(12,2) | Total con impuestos |
|
|
| is_variable | BOOLEAN DEFAULT FALSE | Es gasto variable |
|
|
| previous_amount | DECIMAL(12,2) NULL | Importe del periodo anterior (para variables) |
|
|
| issue_date | DATE | Fecha de emisión |
|
|
| due_date | DATE | Fecha de vencimiento |
|
|
| payment_date | DATE | Fecha de pago |
|
|
| payment_method | VARCHAR(30) | Método de pago |
|
|
| description | VARCHAR(500) | Concepto |
|
|
| notes | TEXT | Notas |
|
|
| created_by | BIGINT FK → users(id) SET NULL | Creador |
|
|
| created_at | DATETIME | Creación |
|
|
| updated_at | DATETIME | Modificación |
|
|
|
|
**Índices:** template, property, property_group, category, status, issue_date
|
|
|
|
### 23. incident_statuses
|
|
|
|
| Columna | Tipo | Descripción |
|
|
|---------|------|-------------|
|
|
| id | INT PK | Auto-increment |
|
|
| name | VARCHAR(50) UNIQUE | SIN_REVISAR, TECNICO_AVISADO, REPARACION_PREVISTA, REPARADO, IGNORADO, ANULADO |
|
|
|
|
### 24. incident_priorities
|
|
|
|
| Columna | Tipo | Descripción |
|
|
|---------|------|-------------|
|
|
| id | INT PK | Auto-increment |
|
|
| name | VARCHAR(20) UNIQUE | BAJA, MEDIA, ALTA, URGENTE |
|
|
|
|
### 25. incidents
|
|
|
|
| Columna | Tipo | Descripción |
|
|
|---------|------|-------------|
|
|
| id | BIGINT PK | Auto-increment |
|
|
| property_id | BIGINT FK → properties(id) | Propiedad |
|
|
| status_id | INT FK → incident_statuses(id) | Estado |
|
|
| priority_id | INT FK → incident_priorities(id) | Prioridad |
|
|
| title | VARCHAR(200) | Título |
|
|
| description | TEXT | Descripción |
|
|
| reported_by | BIGINT FK → users(id) SET NULL | Reportado por |
|
|
| assigned_to | BIGINT FK → users(id) SET NULL | Asignado a |
|
|
| reported_at | DATETIME | Fecha de reporte |
|
|
| scheduled_date | DATE | Fecha prevista reparación |
|
|
| resolved_at | DATETIME | Fecha de resolución |
|
|
| resolution_notes | TEXT | Notas de resolución |
|
|
| cost_estimate | DECIMAL(12,2) | Coste estimado |
|
|
| final_cost | DECIMAL(12,2) | Coste final |
|
|
| created_at | DATETIME | Creación |
|
|
| updated_at | DATETIME | Modificación |
|
|
|
|
### 26. maintenance_periods
|
|
|
|
| Columna | Tipo | Descripción |
|
|
|---------|------|-------------|
|
|
| id | INT PK | Auto-increment |
|
|
| name | VARCHAR(30) UNIQUE | UNICA_VEZ, MENSUAL, TRIMESTRAL, etc. |
|
|
|
|
### 27. scheduled_maintenance
|
|
|
|
| Columna | Tipo | Descripción |
|
|
|---------|------|-------------|
|
|
| id | BIGINT PK | Auto-increment |
|
|
| property_id | BIGINT FK → properties(id) | Propiedad |
|
|
| period_id | INT FK → maintenance_periods(id) | Periodicidad |
|
|
| title | VARCHAR(200) | Título |
|
|
| description | TEXT | Descripción |
|
|
| estimated_cost | DECIMAL(12,2) | Coste estimado |
|
|
| last_execution | DATE | Última ejecución |
|
|
| next_execution | DATE | Próxima ejecución |
|
|
| reminder_days_before | INT DEFAULT 30 | Días antes para recordatorio |
|
|
| responsible | VARCHAR(200) | Responsable |
|
|
| notes | TEXT | Notas |
|
|
| completed | BOOLEAN | Completado |
|
|
| completed_at | DATE | Fecha de finalización |
|
|
| completed_by | BIGINT FK → users(id) SET NULL | Completado por |
|
|
| created_by | BIGINT FK → users(id) SET NULL | Creado por |
|
|
| created_at | DATETIME | Creación |
|
|
| updated_at | DATETIME | Modificación |
|
|
|
|
### 28. notification_types
|
|
|
|
| Columna | Tipo | Descripción |
|
|
|---------|------|-------------|
|
|
| id | INT PK | Auto-increment |
|
|
| name | VARCHAR(50) UNIQUE | INCIDENCIA_ABIERTA, MANTENIMIENTO_PROXIMO, RECIBO_VENCIDO, CONTRATO_PROXIMO_VENCER, CONTRATO_VENCIDO, SISTEMA |
|
|
|
|
### 29. notifications
|
|
|
|
| Columna | Tipo | Descripción |
|
|
|---------|------|-------------|
|
|
| id | BIGINT PK | Auto-increment |
|
|
| user_id | BIGINT FK → users(id) CASCADE | Usuario destinatario |
|
|
| type_id | INT FK → notification_types(id) | Tipo |
|
|
| title | VARCHAR(200) | Título |
|
|
| body | TEXT | Cuerpo |
|
|
| entity_type | VARCHAR(30) | Tipo de entidad relacionada |
|
|
| entity_id | BIGINT | ID de entidad |
|
|
| sent_by_email | BOOLEAN | Enviado por email |
|
|
| read | BOOLEAN | Leído |
|
|
| read_at | DATETIME | Fecha de lectura |
|
|
| created_at | DATETIME | Creación |
|
|
|
|
### 30. receipt_series
|
|
|
|
| Columna | Tipo | Descripción |
|
|
|---------|------|-------------|
|
|
| id | BIGINT PK | Auto-increment |
|
|
| series_name | VARCHAR(50) | Nombre de la serie |
|
|
| fiscal_year | INT | Año fiscal |
|
|
| last_number | INT DEFAULT 0 | Último número usado |
|
|
| prefix | VARCHAR(20) DEFAULT 'R-' | Prefijo del número |
|
|
| active | BOOLEAN | Serie activa |
|
|
| created_at | DATETIME | Creación |
|
|
| updated_at | DATETIME | Modificación |
|
|
|
|
**Unique:** (series_name, fiscal_year)
|
|
|
|
### 31. email_log
|
|
|
|
| Columna | Tipo | Descripción |
|
|
|---------|------|-------------|
|
|
| id | BIGINT PK | Auto-increment |
|
|
| income_receipt_id | BIGINT | ID del recibo de ingreso asociado |
|
|
| recipient_email | VARCHAR(200) | Email del destinatario |
|
|
| subject | VARCHAR(300) | Asunto |
|
|
| body | TEXT | Cuerpo del mensaje |
|
|
| success | BOOLEAN | Envío exitoso |
|
|
| error_message | TEXT | Mensaje de error si falló |
|
|
| sent_at | DATETIME | Fecha de envío |
|
|
|
|
## Notas Técnicas
|
|
|
|
- **Soft-delete:** Las tablas `users`, `properties`, `tenants` tienen columna `active` para borrado lógico.
|
|
- **Índices:** Las columnas más consultadas tienen índices (foreign keys, fechas, estados).
|
|
- **Charset:** `utf8mb4` con collation `utf8mb4_unicode_ci` para soporte completo de Unicode.
|
|
- **Motor:** Todas las tablas usan InnoDB para integridad referencial y transacciones.
|
|
- **Integridad referencial:** 32 constraints FK en total (incluyendo V5 para document_type_entity_allowed).
|
|
- **Al borrar el volumen de datos**, el script `init.sql` se ejecuta automáticamente al arrancar el contenedor MySQL.
|
|
- **Hibernate:** Opera con `ddl-auto: validate`. Cualquier cambio en las entidades JPA requiere actualizar `init.sql`.
|
|
|
|
## Codificación de caracteres (UTF-8)
|
|
|
|
Para evitar problemas con acentos y caracteres especiales (tildes, eñes, etc.) en todo el sistema:
|
|
|
|
- **Base de datos:** charset `utf8mb4` y collation `utf8mb4_unicode_ci`.
|
|
- **Conexión JDBC (`application.yml`):** la URL incluye `characterEncoding=UTF-8&connectionCollation=utf8mb4_unicode_ci` para forzar la lectura/escritura en UTF-8.
|
|
- **Respuestas HTTP (`application.yml`):** `server.servlet.encoding.charset=UTF-8` y `force=true` para que el header `Content-Type` siempre incluya `charset=UTF-8`.
|
|
- **Frontend (nginx):** directiva `charset utf-8;` en el bloque `server` del `Dockerfile.frontend`.
|
|
- **Datos de prueba (`seed.sql`):** el script incluye `SET NAMES utf8mb4;` al inicio para evitar corrupciones al insertar desde clientes con charset por defecto (latin1).
|
|
|
|
Si se ejecuta `seed.sql` manualmente desde un cliente MySQL, usar siempre `--default-character-set=utf8mb4` o ejecutar primero `SET NAMES utf8mb4;`.
|
|
|
|
## Datos de prueba (seed)
|
|
|
|
El archivo `backend/src/main/resources/db/seed.sql` contiene datos de demostración (usuarios adicionales, propiedades, inquilinos, contratos, recibos de ingresos, plantillas de gastos, recibos de gastos, incidencias, etc.).
|
|
|
|
**Para poblar la base de datos tras un `docker compose down -v`:**
|
|
|
|
```bash
|
|
# Copiar el script al contenedor
|
|
docker cp backend/src/main/resources/db/seed.sql sa-polar-mysql:/tmp/seed.sql
|
|
|
|
# Ejecutarlo forzando UTF-8
|
|
docker exec sa-polar-mysql bash -c "mysql -u root -proot --default-character-set=utf8mb4 sa_polar < /tmp/seed.sql"
|
|
```
|
|
|
|
> Las contraseñas de los usuarios de prueba (`admin`, `gerente`, `contable`) son todas `admin123` y solo válidas para desarrollo local.
|