Files
ContabilidadSaPolar/docs/tecnicas/arquitectura.md
T

156 lines
7.3 KiB
Markdown

# Arquitectura del Sistema
## 1. Visión General
Sa Polar es un **monolito modular** con frontend separado. El backend Spring Boot expone una API RESTful que consume un frontend React. La base de datos MySQL se inicializa mediante un script SQL ejecutado en el arranque del contenedor.
```
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Cliente │────▶│ Frontend │────▶│ Backend │────▶│ MySQL 8 │
│ (Browser) │ │ (React 19) │ │ (Spring Boot)│ │ │
│ │◀────│ (Vite 8) │◀────│ (Java 21) │◀────│ │
└──────────────┘ └──────────────┘ └──────────────┘
│ │
│ /api/* │ JPA/Hibernate
▼ ▼
Nginx (proxy) JWT Security
```
## 2. Componentes
### 2.1 Backend (Spring Boot 3.4.1)
El backend se organiza en **paquetes verticales** por dominio de negocio:
| Paquete | Responsabilidad |
|---------|----------------|
| `auth` | Autenticación JWT, login, registro, refresh |
| `user` | CRUD de usuarios, roles, permisos |
| `property` | Gestión de inmuebles (jerárquica), tipos, estados y conjuntos (PropertyGroup) |
| `tenant` | Gestión de inquilinos (personas físicas/jurídicas) |
| `contract` | Contratos de alquiler, estados, periodos de pago |
| `finance.income` | Recibos de ingresos (IncomeReceipt), cobros, categorías |
| `finance.expense` | Plantillas de gastos (ExpenseTemplate), recibos de gastos (ExpenseReceipt), categorías |
| `finance.receipt` | Recibos, PDF, email, reportes Excel, scheduler |
| `incident` | Incidencias, prioridades, asignación técnica |
| `maintenance` | Mantenimiento programado recurrente |
| `notification` | Notificaciones por usuario |
| `document` | Gestión de documentos adjuntos (polimórfico) |
| `dashboard` | Agregaciones y resúmenes |
| `config` | Seguridad, CORS, OpenAPI, almacenamiento |
| `common` | DTOs genéricos, excepciones, utilidades |
### 2.2 Frontend (React 19 + TypeScript 6)
Aplicación SPA con las siguientes capas:
| Capa | Descripción |
|------|-------------|
| `api/client.ts` | Instancia Axios con interceptor JWT y redirección 401 |
| `api/auth.ts` | Funciones de login y refresh |
| `api/resources.ts` | Funciones CRUD para cada recurso |
| `contexts/AuthContext.tsx` | Estado global de autenticación |
| `components/Layout.tsx` | Sidebar de navegación + contenido principal |
| `pages/*.tsx` | Páginas individuales (Login, Dashboard, Properties, etc.) |
| `types/api.ts` | Interfaces TypeScript para los DTOs |
### 2.3 Base de datos (MySQL 8)
Esquema gestionado mediante script SQL de inicialización (`db/init.sql`). Hibernate opera en modo `validate` para verificar que el mapeo JPA coincida con el esquema existente.
## 3. Seguridad
### 3.1 Autenticación JWT
1. El usuario envía credenciales a `POST /api/auth/login`
2. El servidor valida contra la base de datos y devuelve:
- `accessToken`: válido por 24 horas
- `refreshToken`: válido por 30 días
3. El frontend almacena los tokens en `localStorage`
4. Cada petición incluye `Authorization: Bearer <token>`
5. El `JwtAuthenticationFilter` extrae y valida el token en cada request
6. Si el token expira, el frontend usa `POST /api/auth/refresh` para obtener uno nuevo
### 3.2 Roles y permisos
| Rol | Acceso |
|-----|--------|
| `ADMIN` | Todos los endpoints, incluyendo gestión de usuarios |
| `GERENTE` | Propiedades, inquilinos, contratos, incidencias, mantenimiento, recibos de ingresos, plantillas de gastos, recibos de gastos, dashboard |
| `CONTABLE` | Recibos de ingresos, plantillas de gastos, recibos de gastos, dashboard, reportes |
| `VISUALIZADOR` | Autenticado (acceso básico de solo lectura según configuración) |
### 3.3 Seguridad adicional
- CSRF deshabilitado (API stateless)
- Sesiones sin estado (`SessionCreationPolicy.STATELESS`)
- CORS configurable mediante `app.cors.allowed-origins`
- Contraseñas almacenadas con BCrypt
## 4. Flujo de Datos
### 4.1 Autenticación
```
Browser Frontend Backend MySQL
│ │ │ │
│ login(user, pass) │ │ │
│──────────────────────▶│ POST /api/auth/login │ │
│ │───────────────────────▶│ │
│ │ │ SELECT user by email │
│ │ │───────────────────────▶│
│ │ │◀───────────────────────│
│ │ │ Verificar BCrypt hash │
│ │ │ Generar JWT tokens │
│ │◀───────────────────────│ │
│◀──────────────────────│ TokenResponse │ │
│ Guardar en localStorage │ │
```
### 4.2 Generación de recibos automáticos
```
Scheduler (cron: 0 0 6 1 * ?)
ReceiptService.generateMonthlyReceipts()
├── Buscar contratos ACTIVOS con payment_day = mes actual
├── Para cada contrato:
│ ├── Obtener siguiente número de serie (ReceiptSeries)
│ ├── Crear registro IncomeReceipt con receipt_number
│ ├── Generar PDF (PdfReceiptService)
│ └── Enviar email si el inquilino tiene email (EmailReceiptService)
└── Log de emails enviados (email_log)
```
## 5. Despliegue
### 5.1 Docker Compose
Tres servicios orquestados:
1. **mysql**: Imagen `mysql:8.0`, puerto `3307:3306`, volumen persistente, script init.sql
2. **backend**: Build multi-etapa (Maven + JRE), puerto `8080:8080`
3. **frontend**: Build multi-etapa (Node + Nginx), puerto `3000:3000`, proxy reverso `/api/` al backend
### 5.2 Entornos
| Entorno | Backend URL | Frontend URL | Propósito |
|---------|-------------|--------------|-----------|
| Desarrollo | `localhost:8080` | `localhost:5173` (Vite) | Desarrollo local |
| Producción | `localhost:8080` | `localhost:3000` (Nginx) | Docker compose |
## 6. Dependencias Externas
| Dependencia | Versión | Uso |
|-------------|---------|-----|
| Spring Boot | 3.4.1 | Framework principal |
| JJWT | 0.12.6 | Tokens JWT |
| SpringDoc OpenAPI | 2.7.0 | Documentación Swagger |
| iText | 8.0.5 | Generación de PDFs |
| Apache POI | 5.3.0 | Generación de Excel |
| MapStruct | 1.6.3 | Mapeo de DTOs (si se usa) |
| Lombok | 1.18.36 | Reducción de boilerplate |
| Flyway | - | Dependencia incluida pero deshabilitada |