# Metafoliador v2

Sistema de gestión documental e indexación electrónica integrado con **Alfresco** (ECM).

**Versión:** 2.0.0  
**Autor:** MetaBiblioteca &copy; 2026

---

## Descripción

Metafoliador v2 permite sincronizar sitios, Series, Subseries y Expedientes y archivos desde Alfresco, generar índices electrónicos (`index.xml`) en formato colombiano (`TipoDocumentoFoliado`), calcular hashes SHA-256 y conteo de páginas por archivo, y subir los índices de vuelta a Alfresco. Incluye un panel web administrativo con control de acceso basado en roles (RBAC).

---

## Stack Tecnológico

| Capa | Tecnología | Versión |
|------|-----------|---------|
| Lenguaje | Python 3 | — |
| Framework Web | FastAPI | 0.115.6 |
| Servidor ASGI | Uvicorn | 0.34.0 |
| ORM | SQLAlchemy | 2.0.36 |
| Migraciones | Alembic | 1.14.0 |
| Base de datos | PostgreSQL 16 (psycopg2-binary) | 2.9.10 |
| Cola de tareas | Celery | 5.4.0 |
| Message Broker | RabbitMQ (pika) | 1.3.2 |
| Result Backend | Redis | 5.2.0 |
| Procesamiento XML | lxml | 5.3.0 |
| Cliente HTTP | httpx | 0.28.1 |
| Configuración | pydantic-settings | 2.6.1 |
| Frontend | HTML/CSS/JS vanilla + Jinja2 | — |
| Reportes Excel | openpyxl | 3.1.5 |
| Gráficos | matplotlib | 3.9.3 |
| PDF | reportlab | 4.2.5 |
| Conteo páginas PDF | PyPDF2 | 3.0.1 |
| Conteo páginas DOCX | python-docx | 1.1.2 |
| Criptografía | cryptography (Fernet) | 44.0.0 |
| JWT | PyJWT | 2.10.1 |

---

## Requisitos

- Python 3
- PostgreSQL 16
- RabbitMQ
- Redis
- Acceso a una instancia de Alfresco

---

## Instalación

### Instalación automática (recomendada para servidor nuevo)

```bash
sudo ./scripts/install.sh
```

Este script configura todo automáticamente:
1. Instala dependencias del sistema (Python, PostgreSQL, RabbitMQ, Redis)
2. Crea la base de datos y usuario PostgreSQL
3. Clona/configura el proyecto en `/var/www/html/metafoliadorv2`
4. Crea venv e instala dependencias Python
5. Configura `.env`
6. Ejecuta migraciones
7. Instala y activa servicios systemd
8. Inicia los servicios

### Instalación manual

#### 1. Clonar el repositorio

```bash
git clone <repo-url>
cd metafoliador
```

#### 2. Crear base de datos PostgreSQL

```bash
sudo -u postgres psql -f scripts/setup_database.sql
```

#### 3. Crear entorno virtual e instalar dependencias

```bash
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
```

#### 4. Configurar variables de entorno

Copiar el archivo de ejemplo y editar los valores:

```bash
cp .env.example .env
```

| Variable | Default | Descripción |
|----------|---------|-------------|
| `DATABASE_URL` | `postgresql://metafoliador:v2_password_here@localhost:5433/metafoliadorv2` | URL de conexión PostgreSQL (tenant) |
| `MAIN_DATABASE_URL` | `postgresql://metafoliador:v2_password_here@localhost:5433/metafoliador_main` | URL de conexión PostgreSQL (BD principal) |
| `MAIN_DOMAIN` | `metafoliador.local` | Dominio del panel principal |
| `RABBITMQ_URL` | `amqp://guest:guest@localhost:5672/` | URL de RabbitMQ |
| `REDIS_URL` | `redis://localhost:6379/0` | URL de Redis |
| `SWAGGER_USERNAME` | `admin` | Usuario para acceder a Swagger UI (HTTP Basic Auth) |
| `SWAGGER_PASSWORD` | `tykUGJ#Nr3u9%DZ!HndX` | Contraseña para acceder a Swagger UI (HTTP Basic Auth) |
| `LOG_LEVEL` | `INFO` | Nivel de logging |
| `SWAGGER_USERNAME` | `admin` | Usuario para acceder a Swagger UI (HTTP Basic Auth) |
| `SWAGGER_PASSWORD` | `tykUGJ#Nr3u9%DZ!HndX` | Contraseña para acceder a Swagger UI (HTTP Basic Auth) |
| `LOG_LEVEL` | `INFO` | Nivel de logging |

#### 5. Ejecutar migraciones

```bash
alembic upgrade head
```

#### 6. Iniciar servicios

```bash
# Servidor API
uvicorn app.main:app --host 127.0.0.1 --port 8000

# Worker Celery
celery -A app.worker worker --loglevel=info -Q celery
```

---

## Estructura del Proyecto

```
metafoliador/
├── .env.example              # Template de variables de entorno
├── .gitignore
├── alembic.ini               # Configuración de Alembic
├── alembic_main.ini          # Configuración de Alembic (BD principal)
├── requirements.txt          # Dependencias Python
├── deploy.sh                 # Script de despliegue a producción
├── docs/                      # Documentación
│   ├── manual-tecnico.md      # Manual técnico completo (23 capítulos)
│   └── manual-usuario.md      # Manual de usuario detallado (14 capítulos)
├── scripts/                  # Scripts de instalación y configuración
│   ├── install.sh            # Instalación completa en servidor nuevo
│   ├── setup_database.sql    # Creación de BD y usuario PostgreSQL
│   ├── metafoliadorv2.service
│   ├── metafoliadorv2-worker.service
│   └── metafoliadorv2-webhook-worker.service
├── alembic/                  # Migraciones de BD
│   ├── env.py
│   ├── script.py.mako
│   └── versions/
├── alembic_main/             # Migraciones de BD principal
├── app/                      # Paquete principal
│   ├── main.py               # Entry point FastAPI
│   ├── config.py             # Settings con pydantic-settings
│   ├── worker.py             # Definición de Celery app
│   ├── worker_tasks.py       # Tareas Celery
│   ├── middleware/            # Middleware de resolución de tenant
│   ├── models/               # Modelos SQLAlchemy (11 modelos)
│   ├── services/             # Lógica de negocio
│   └── api/
│       ├── routes/           # 13 routers tenant (56 endpoints)
│       └── main/             # Routers del panel principal (17 endpoints)
├── static/
│   ├── css/
│   ├── js/
│   │   └── main/             # JS del panel principal
│   └── img/
└── templates/
    ├── main/                  # Templates del panel principal
    └── (templates tenant)
```

---

## Funcionalidades

### Conexiones Alfresco
- CRUD de conexiones a instancias Alfresco (URL, usuario, contraseña, tipo de auth)
- Test de conexión y descubrimiento de sitios

### Sincronización de Sitios
- Sincronización recursiva de Series, Subseries y Expedientes y archivos desde Alfresco
- Dos modos: **shallow** (solo primer nivel) y **deep** (recursivo completo)
- Opción de generar o no índices electrónicos durante la sincronización
- Tracking de progreso en tiempo real
- Soft delete para elementos eliminados en Alfresco
- Detección y reactivación automática de archivos
- Historial de movimientos de archivos entre Series, Subseries y Expedientes

### Generación de Índices Electrónicos
- Formato colombiano `TipoDocumentoFoliado` con `DocumentoIndizado`
- Extracción de tipología documental desde nombres de Serie, Subserie o Expediente
- Cálculo de hash SHA-256 por archivo
- Conteo de páginas/folios (PDF, DOCX, TXT, imágenes)
- Subida automática del `index.xml` a Alfresco vía API REST
- Versionado con aspect `cm:versionable`

### Webhook Listener
- Recepción de eventos de Alfresco (create/update/delete/move)
- Autorización por IP
- Logging de requests entrantes
- Procesamiento asíncrono vía Celery

### Panel Administrativo Web
- Login con JWT (cookie-based)
- Dashboard con estadísticas y gráficos interactivos (Chart.js)
- Navegador de cuadro de clasificación con visor de index.xml con syntax highlighting
- Gestión de conexiones, sitios, usuarios y jobs
- RBAC con 32 permisos granulares
- Reportes internos en Excel (TRD/Tipologías) y PDF (Gráficos por Dependencia)
- Reportes externos con URL personalizada y CRUD completo
- Visor de logs del listener
- **Tema claro/oscuro**: Toggle con persistencia en `localStorage`. Usa variables CSS (`:root` / `[data-theme="dark"]`) para cambiar toda la paleta de colores sin recargar la página. Los gráficos Chart.js adaptan sus colores dinámicamente al detectar el cambio de tema vía evento `themeChanged`. Botón accesible en la barra superior y en la página de login.

### Sistema Multitenant
- **Panel Principal**: dominio principal con login independiente, CRUD de clientes y gestión de usuarios administradores
- **Panel Tenant**: subdominios con la funcionalidad completa de Metafoliador por cliente
- **Resolución automática**: middleware detecta el subdominio y conecta a la BD tenant correspondiente
- **Creación de tenant**: al crear un cliente se crea automáticamente la BD (`metafoliador_tenant_{subdominio}`), se migra y se replica el usuario creador
- **Activación/Inactivación**: tenants inactivos retornan 403 bloqueando todo acceso
- **Auto-login**: si un usuario del panel principal existe en el tenant, inicia sesión automáticamente
- **Sesiones separadas**: cookies JWT independientes para panel principal y tenant
- **Nombre del cliente**: el login del tenant muestra el nombre del cliente desde la BD principal

---

## Despliegue a Producción

El script `deploy.sh` sincroniza cambios al servidor productivo vía `tar` + `scp` sobre SSH.

```bash
./deploy.sh              # Solo archivos modificados desde el último deploy
./deploy.sh --all        # Despliegue completo
./deploy.sh --force      # Fuerza reinicio de todos los servicios
```

El script detecta automáticamente qué cambió y ejecuta las acciones necesarias (pip install, migraciones, reinicios de servicios).

**Servicios systemd en producción:**
- `metafoliadorv2.service` — API (uvicorn)
- `metafoliadorv2-worker.service` — Celery worker (cola `celery`)

---

## Modelos de Datos

| Modelo | Tabla | Propósito |
|--------|-------|-----------|
| MainUser | main_users | Usuarios del panel principal |
| Customer | customers | Clientes/tenants (subdominio, db_url, activo) |
| User | users | Usuarios del sistema |
| AlfrescoConnection | alfresco_connections | Configuración de conexión Alfresco |
| AlfrescoSite | alfresco_sites | Sitios Alfresco |
| AlfrescoFolder | alfresco_folders | Cuadro jerárquico de clasificación |
| AlfrescoFile | alfresco_files | Metadatos de archivos |
| AlfrescoFileHistory | alfresco_file_history | Historial de movimientos |
| AlfrescoListenerLog | alfresco_listener_logs | Logs del webhook listener |
| Role / Permission | roles, permissions, role_permissions | RBAC |
| SyncProgress | sync_progress | Progreso de sincronización |
| Reporte | reportes | Definiciones de reportes |

---

## Documentación de la API (Swagger)

La documentación interactiva de la API está disponible en:

- **Swagger UI:** `/docs`
- **ReDoc:** `/redoc`
- **OpenAPI Schema:** `/openapi.json`

### Acceso protegido

Los endpoints de documentación están protegidos con **HTTP Basic Auth** independiente del sistema. Las credenciales se configuran en las variables de entorno `SWAGGER_USERNAME` y `SWAGGER_PASSWORD`.

La documentación incluye:
- **13 tags** con descripciones detalladas
- **56 endpoints** documentados con summary y descripción en español
- **13 esquemas Pydantic** con descripciones de cada campo
- Parámetros de query, path y body tipados y documentados

---

## Flujo de Sincronización

1. Usuario crea una conexión Alfresco y descubre sitios
2. Usuario selecciona un sitio y dispara sync (shallow o deep)
3. Se crea un `SyncProgress` y se lanza tarea Celery
4. La tarea recorre Series, Subseries y Expedientes/archivos vía API Alfresco y los persiste en BD
5. Se detectan archivos eliminados comparando IDs contra la BD
6. Para cada Serie, Subserie o Expediente hoja se genera `index.xml` y se sube a Alfresco
7. Se actualiza `has_index_xml = True` en la Serie, Subserie o Expediente

---

## Documentación

El proyecto incluye documentación completa en el directorio `docs/`:

| Documento | Descripción |
|-----------|-------------|
| `docs/manual-tecnico.md` | Manual técnico con 23 capítulos: arquitectura, instalación, configuración, base de datos, modelos, API REST (56 endpoints), autenticación, RBAC, Celery, índices electrónicos, webhooks, reportes, despliegue, solución de problemas y glosario. |
| `docs/manual-usuario.md` | Manual de usuario con 14 capítulos: primeros pasos, dashboard, conexiones, sitios, sincronización, índices, trabajos, usuarios, roles, reportes, logs, solución de problemas y glosario. |

---

## Licencia

No especificada.
