Files
ContabilidadSaPolar/docs/tecnicas/arquitectura.md
T

7.3 KiB

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