|
1 | | -# Sistema de Gestión de Tareas Empresariales |
| 1 | +# Plataforma de Automatización de Tareas Empresariales |
2 | 2 |
|
3 | 3 | [](https://github.com/ardelperal/scripts-python/actions/workflows/python-ci.yml) |
4 | 4 | [](https://codecov.io/gh/ardelperal/scripts-python) |
5 | 5 |
|
6 | | -Sistema de **monitoreo continuo** para la gestión automatizada de tareas empresariales desarrollado en Python. El objetivo principal es ejecutar el script maestro `run_master.py` que funciona como un **daemon de producción** que monitorea y ejecuta automáticamente todos los módulos del sistema según horarios específicos. |
| 6 | +Sistema en Python para orquestar y ejecutar tareas empresariales (diarias y continuas) bajo un único proceso maestro (`run_master.py`). Se centra en: |
| 7 | +- Ejecución controlada por calendario laboral (Madrid) con soporte de festivos y fallback local. |
| 8 | +- Ciclo continuo con tareas recurrentes (correo, mantenimiento, monitorización). |
| 9 | +- Registro estructurado de logs y facilidad de supervisión (Loki/Grafana opcional). |
| 10 | +- Extensibilidad mediante definición de nuevas tareas. |
7 | 11 |
|
8 | | -## 🎯 Objetivo Principal |
| 12 | +--- |
| 13 | +## 1. Visión General |
9 | 14 |
|
10 | | -El **script maestro (`run_master.py`)** es el corazón del sistema y reemplaza al script original `script-continuo.vbs`. Funciona como un **servicio continuo** que: |
| 15 | +El proceso principal se lanza mediante `scripts/run_master.py` y puede trabajar en dos modos: |
| 16 | +1. Modo continuo (por defecto): bucle infinito que ejecuta tareas según ventanas horarias y tipo de día. |
| 17 | +2. Modo simple (`--simple`): ejecuta una sola pasada (útil para cron, pruebas o diagnósticos rápidos). |
11 | 18 |
|
12 | | -- 🔄 **Monitorea continuamente** todos los sistemas involucrados |
13 | | -- ⏰ **Ejecuta tareas diarias** una vez por día laborable (después de las 7 AM) |
14 | | -- 📧 **Ejecuta tareas continuas** (correos y tareas) en cada ciclo |
15 | | -- 📅 **Respeta días festivos** y horarios laborables |
16 | | -- ⚙️ **Ajusta tiempos de ciclo** según horario y tipo de día |
17 | | -- 📊 **Genera logs detallados** y archivos de estado |
18 | | -- 🛡️ **Manejo robusto de errores** y recuperación automática |
19 | | -- 🔍 **Modo verbose** para debugging y monitoreo detallado |
| 19 | +Tipos de tareas: |
| 20 | +- Tareas diarias: se ejecutan una vez por día laborable (tras la hora configurada interna, por defecto >= 07:00). |
| 21 | +- Tareas continuas: se ejecutan en cada ciclo (por ejemplo, envío de correos pendientes). |
20 | 22 |
|
21 | | -### 📋 Módulos Integrados en el Script Maestro |
22 | | - |
23 | | -#### Tareas Diarias (ejecutadas una vez por día laborable): |
24 | | -1. **AGEDYS** (`run_agedys.py`): Sistema de gestión de facturas y visados técnicos |
25 | | -2. **BRASS** (`run_brass.py`): Sistema de gestión de tareas BRASS |
26 | | -3. **Expedientes** (`run_expedientes.py`): Gestión de expedientes y documentación |
27 | | -4. **No Conformidades** (`run_no_conformidades.py`): Gestión de no conformidades |
28 | | -5. **Riesgos** (`run_riesgos.py`): Gestión de riesgos empresariales |
29 | | - |
30 | | -#### Tareas Continuas (ejecutadas en cada ciclo): |
31 | | -6. **Email Services** (`run_email_services.py`): Servicio unificado de envío de correos (fusiona antiguos módulos `correos` y `correo_tareas`) |
32 | | - |
33 | | -### 🆕 Cambios Arquitectónicos Recientes (Refactor 2025) |
34 | | - |
35 | | -Refactor integral para simplificar arquitectura, mejorar testabilidad y eliminar código legacy. |
36 | | - |
37 | | -Principales mejoras: |
38 | | -1. Capa de datos unificada: |
39 | | - - Eliminados `AccessAdapter` y `DemoDatabase`. |
40 | | - - Nueva clase única `AccessDatabase` con soporte opcional de pool. |
41 | | - - Introducido `AccessConnectionPool` (gestiona instancias reutilizables por cadena de conexión). |
42 | | -2. Gestión de tareas: |
43 | | - - Reemplazo de funciones globales por clase `TaskRegistry` (extensible, inyectable, test-friendly). |
44 | | - - API: `get_daily_tasks()`, `get_continuous_tasks()`, `get_all_tasks()`, `summary()`, filtros y extensión por parámetros `extra_daily/extra_continuous`. |
45 | | - - Backwards compatibility: funciones wrapper conservadas para código legado. |
46 | | -3. Script maestro (`run_master.py`): |
47 | | - - Consolidado antiguo `run_master_new.py` (eliminado). |
48 | | - - Añadido modo `--simple` sobre `TaskRegistry` con resumen estructurado. |
49 | | - - Fast-path en tests (`MASTER_DRY_SUBPROCESS=1`) evitando importaciones pesadas. |
50 | | -4. Riesgos y No Conformidades: parametrización explícita de frecuencias vía variables de entorno para subtareas. |
51 | | -5. Limpieza y cobertura: |
52 | | - - Eliminado definitivamente archivo legacy `database_adapter.py` y su test. |
53 | | - - Stub ligero de `RiesgosTask` para unit tests cuando el módulo completo no es necesario. |
54 | | -6. Documentación actualizada: ejemplos de extensión de tareas, uso de pools y guía de migración. |
55 | | - |
56 | | -Pendiente futuro (no implementado aún): |
57 | | -- Sistema de plugins de tareas (descubrimiento dinámico). |
58 | | -- Persistencia de métricas de ejecución (duración/estado) para observabilidad. |
59 | | -- Reducción selectiva de coste de importación en módulos grandes (lazy loading adicional). |
60 | | - |
61 | | -### Uso de TaskRegistry |
| 23 | +--- |
| 24 | +## 2. Estructura Principal del Repositorio |
62 | 25 |
|
63 | | -```python |
64 | | -from common.task_registry import TaskRegistry |
| 26 | +``` |
| 27 | +scripts/ Scripts ejecutables (incluye run_master.py) |
| 28 | +src/common/ Utilidades, configuración, lógica compartida |
| 29 | +dbs-locales/ Bases de datos Access (entorno local / demo) |
| 30 | +hERRAMIENTAS/ Recursos auxiliares (CSS, Festivos.txt, etc.) |
| 31 | +tests/ Tests unitarios e integración (pytest) |
| 32 | +docs/ Documentación funcional y técnica adicional |
| 33 | +``` |
65 | 34 |
|
66 | | -registry = TaskRegistry() |
67 | | -for task in registry.get_daily_tasks(): |
68 | | - if task.debe_ejecutarse(): |
69 | | - task.ejecutar() |
70 | | - task.marcar_como_completada() |
| 35 | +--- |
| 36 | +## 3. Preparación del Entorno (Desarrollo / Local) |
| 37 | + |
| 38 | +Requisitos mínimos: |
| 39 | +- Python 3.11+ (Windows preferente por dependencias de Access) |
| 40 | +- Controlador ODBC para Access (Microsoft Access Database Engine 2016 o similar) |
| 41 | +- Git |
| 42 | + |
| 43 | +Pasos recomendados: |
| 44 | + |
| 45 | +```powershell |
| 46 | +git clone https://github.com/ardelperal/scripts-python.git |
| 47 | +cd scripts-python |
| 48 | +python -m venv venv |
| 49 | +./venv/Scripts/Activate.ps1 |
| 50 | +pip install -r requirements.txt |
| 51 | +pip install -r requirements-dev.txt # Solo si vas a desarrollar / testear |
71 | 52 | ``` |
72 | 53 |
|
73 | | -Extender con tareas personalizadas: |
| 54 | +Variables de entorno opcionales (crear `.env` en raíz si se desea ajustar): |
| 55 | + |
| 56 | +``` |
| 57 | +ENVIRONMENT=local # o 'office' |
| 58 | +DEFAULT_RECIPIENT=admin@empresa.com |
| 59 | +LOCAL_DB_AGEDYS=dbs-locales/AGEDYS_DATOS.accdb |
| 60 | +LOCAL_DB_BRASS=dbs-locales/Gestion_Brass_Gestion_Datos.accdb |
| 61 | +# ... resto ver config.py |
| 62 | +``` |
| 63 | + |
| 64 | +Para SMTP local de pruebas puedes usar un servidor dummy (por ejemplo MailHog, smtp4dev o Python `smtpd`). |
| 65 | + |
| 66 | +--- |
| 67 | +## 4. Ejecución del Proceso Maestro |
| 68 | + |
| 69 | +Desde la raíz del proyecto (con el entorno activado): |
| 70 | + |
| 71 | +```powershell |
| 72 | +python scripts/run_master.py # Modo continuo |
| 73 | +python scripts/run_master.py -v # Modo continuo con más detalle |
| 74 | +python scripts/run_master.py --simple # Ejecución única (diarias + continuas) |
| 75 | +python scripts/run_master.py --simple -v # Ejecución única verbose |
| 76 | +python scripts/run_master.py --list-tasks # Listar tareas y su estado previsto |
| 77 | +``` |
| 78 | + |
| 79 | +Salida clave registrada en `logs/app.log`. |
| 80 | + |
| 81 | +Finalización limpia: CTRL+C (manejo de señal implementado) o detener el servicio (ver sección despliegue). |
| 82 | + |
| 83 | +--- |
| 84 | +## 5. Calendario Laboral y Festivos |
| 85 | + |
| 86 | +La función `es_laborable` combina: |
| 87 | +1. Librería `holidays` (España, Comunidad de Madrid). |
| 88 | +2. Archivo de respaldo `herramientas/Festivos.txt` (formato: `DD/MM/YYYY` por línea) en caso de falta de librería o conectividad. |
| 89 | + |
| 90 | +Si necesitas añadir festivos personalizados: edita el archivo `herramientas/Festivos.txt` (un festivo por línea). |
| 91 | + |
| 92 | +--- |
| 93 | +## 6. Definición y Extensión de Tareas |
| 94 | + |
| 95 | +Las tareas se gestionan mediante un registro interno. Para agregar una nueva tarea: |
| 96 | +1. Crear módulo de tarea en `src/` (ej. `src/agedys/nueva_tarea.py`). |
| 97 | +2. Implementar una clase que exponga al menos: |
| 98 | + - `name` (str) |
| 99 | + - `debe_ejecutarse()` -> bool |
| 100 | + - `ejecutar()` -> bool (True si éxito) |
| 101 | + - `marcar_como_completada()` (si aplica) |
| 102 | +3. Registrar la tarea (según mecanismo del registro existente). Revisa ejemplos en tareas actuales. |
| 103 | + |
| 104 | +Ejemplo simplificado de patrón: |
74 | 105 |
|
75 | 106 | ```python |
76 | | -from common.base_task import TareaDiaria |
77 | | -from common.task_registry import TaskRegistry |
| 107 | +class MiTarea: |
| 108 | + name = "mi_tarea_demo" |
| 109 | + |
| 110 | + def debe_ejecutarse(self) -> bool: |
| 111 | + return True |
| 112 | + |
| 113 | + def ejecutar(self) -> bool: |
| 114 | + # Lógica principal |
| 115 | + return True |
| 116 | + |
| 117 | + def marcar_como_completada(self): |
| 118 | + pass |
| 119 | +``` |
| 120 | + |
| 121 | +--- |
| 122 | +## 7. Logs y Observabilidad |
| 123 | + |
| 124 | +- Archivo principal: `logs/app.log`. |
| 125 | +- Rotación/handlers adicionales configurables en `common.utils.setup_logging` si se emplea en otras partes. |
| 126 | +- Integración opcional con Loki / Promtail (ver carpetas `loki/`, `promtail/`, `grafana/`). |
| 127 | + |
| 128 | +--- |
| 129 | +## 8. Testing |
| 130 | + |
| 131 | +Ejecutar test suite completa: |
| 132 | + |
| 133 | +```powershell |
| 134 | +pytest |
| 135 | +``` |
| 136 | + |
| 137 | +Cobertura HTML: abrir `htmlcov/index.html` tras una ejecución con cobertura (por defecto ya configurada en `pyproject.toml`). |
| 138 | + |
| 139 | +Tests relevantes para calendario laboral: `tests/unit/common/test_utils.py` (función `es_laborable`). |
| 140 | + |
| 141 | +--- |
| 142 | +## 9. Despliegue / Operación (IT) |
| 143 | + |
| 144 | +Escenarios típicos: |
| 145 | + |
| 146 | +1. Servicio Windows (sugerido): crear un servicio que invoque el intérprete Python con `scripts/run_master.py`. Herramientas posibles: NSSM (Non-Sucking Service Manager) o `sc.exe create` envolviendo un `.bat` que active el entorno y lance el script. |
| 147 | +2. Tarea Programada (solo modo simple): programar ejecución diaria en modo `--simple` si se prefiere orquestación externa (no continuo). |
| 148 | + |
| 149 | +Ejemplo de script launcher (`run_master.bat`): |
| 150 | + |
| 151 | +```bat |
| 152 | +@echo off |
| 153 | +cd /d C:\ruta\scripts-python |
| 154 | +call venv\Scripts\activate.bat |
| 155 | +python scripts\run_master.py -v |
| 156 | +``` |
| 157 | + |
| 158 | +Supervisión: |
| 159 | +- Revisar `logs/app.log`. |
| 160 | +- Validar que el proceso (o servicio) permanece activo. |
| 161 | +- Integrar Promtail si se desea centralizar logs. |
| 162 | + |
| 163 | +Actualización: |
| 164 | +```powershell |
| 165 | +git pull |
| 166 | +pip install -r requirements.txt --upgrade |
| 167 | +``` |
| 168 | + |
| 169 | +--- |
| 170 | +## 10. Variables y Personalización Clave |
| 171 | + |
| 172 | +| Variable | Uso | Ejemplo | |
| 173 | +|----------|-----|---------| |
| 174 | +| ENVIRONMENT | Selección de rutas (local/office) | local | |
| 175 | +| DEFAULT_RECIPIENT | Email destino por defecto | admin@empresa.com | |
| 176 | +| LOCAL_DB_AGEDYS | Ruta BD local | dbs-locales/AGEDYS_DATOS.accdb | |
| 177 | +| MASTER_LOG_LEVEL | Nivel de log del maestro | INFO | |
| 178 | +| SMTP_OVERRIDE_* | Forzar servidor SMTP alternativo | ver config.py | |
| 179 | + |
| 180 | +Consulta `src/common/config.py` para el listado completo. |
| 181 | + |
| 182 | +--- |
| 183 | +## 11. Seguridad y Buenas Prácticas |
| 184 | + |
| 185 | +- No commitear `.env` con credenciales reales. |
| 186 | +- Asegurar acceso restringido a las bases `.accdb` en producción. |
| 187 | +- Configurar backups regulares de las bases Access en entorno corporativo. |
| 188 | +- Monitorizar tamaño de logs y aplicar rotación si se prolonga el uso intensivo. |
| 189 | + |
| 190 | +--- |
| 191 | +## 12. Roadmap Técnico (alto nivel) |
| 192 | + |
| 193 | +- Métricas de ejecución (duración, estado) exportables. |
| 194 | +- Health endpoint ligero (modo HTTP opcional). |
| 195 | +- Plugins de tareas dinámicos. |
| 196 | + |
| 197 | +--- |
| 198 | +## 13. Soporte Rápido |
| 199 | + |
| 200 | +| Qué | Dónde mirar | |
| 201 | +|-----|-------------| |
| 202 | +| Error de BD | Rutas en `.env` / permisos de red | |
| 203 | +| No ejecuta tareas diarias | Ver `es_laborable`, hora del sistema | |
| 204 | +| Emails no salen | Config SMTP en `.env` / logs de correo | |
| 205 | +| Festivo no detectado | Formato en `herramientas/Festivos.txt` | |
| 206 | + |
| 207 | +--- |
| 208 | +## 14. Licencia |
| 209 | + |
| 210 | +Proyecto interno. Uso restringido al ámbito corporativo. |
| 211 | + |
| 212 | +--- |
| 213 | +## 15. Contacto |
| 214 | + |
| 215 | +Equipo de Automatización / IT Interno. |
78 | 216 |
|
79 | | -class MiTarea(TareaDiaria): |
80 | | - def __init__(self): |
81 | 217 | super().__init__(name="MiTarea", script_filename="run_mi_tarea.py", task_names=["MiTareaDiaria"], frequency_days=1) |
82 | 218 | def debe_ejecutarse(self): |
83 | 219 | return True |
|
0 commit comments