docs: agregar documento de arquitectura y stack tecnologico

This commit is contained in:
Nachou-u
2026-09-08 10:28:37 -03:00
parent f3e236863e
commit 7303d04776
4 changed files with 112 additions and 0 deletions
+1
View File
@@ -227,3 +227,4 @@ Los mensajes de commit deben seguir esta estructura:
- [Manual de Usuario Final](docs/MANUAL_USUARIO.md): Guía paso a paso sobre cómo utilizar el ERP, registrar gastos, el flujo de aprobación y monitorear proyectos. - [Manual de Usuario Final](docs/MANUAL_USUARIO.md): Guía paso a paso sobre cómo utilizar el ERP, registrar gastos, el flujo de aprobación y monitorear proyectos.
- [Arquitectura y Stack Tecnológico](docs/STACK_ARCHITECTURE.md): Documentación del stack técnico elegido (HTMX, Alpine, Supabase, Django Asíncrono, Celery) y la hoja de ruta de implementación.
+84
View File
@@ -0,0 +1,84 @@
# Arquitectura y Stack Tecnológico - EFINTEL ERP
Este documento detalla la arquitectura técnica elegida para el desarrollo, escalabilidad y mantenimiento del ERP de EFINTEL. La selección del stack se basa en mantener una alta velocidad de desarrollo, aprovechando las capacidades asíncronas de Python moderno y evitando la sobrecarga de mantener un frontend y backend separados (SPA).
---
## 1. Stack Backend (Core)
### Framework: Django 6.1 (Modo Asíncrono)
Mantenemos Django como pilar fundamental por su ORM, su panel de administración y su sistema de autenticación integrado.
- **Asincronismo (`async def`)**: Dado que corremos sobre un servidor ASGI, utilizaremos vistas asíncronas para operaciones que requieran alta concurrencia o tiempos de espera I/O (lectura de BD masiva, llamadas a APIs externas).
- **Programación Orientada a Objetos (POO)**: Todas las vistas de la aplicación deben basarse en *Class-Based Views* (CBV) para aprovechar la herencia y los Mixins (ej. `RoleRequiredMixin`).
### API REST: Django Ninja
Para la comunicación interna del sistema y futuras integraciones de terceros.
- Reemplaza a Django REST Framework (DRF).
- Tipado estricto y validación automática mediante **Pydantic**.
- Soporte nativo para rutas asíncronas, lo que incrementa el rendimiento.
### Tareas en Segundo Plano: Celery + Redis
Para no bloquear el hilo de ejecución principal (ej. la interfaz del usuario), delegamos las tareas pesadas:
- Generación de reportes PDF / Excel masivos.
- Sincronización y cálculo de planillas de sueldos.
- Envío masivo de correos de notificación.
### WebSockets: Django Channels
Para actualizaciones en tiempo real (ej. cuando otro usuario aprueba un gasto o notificaciones del sistema), respaldado por Redis.
---
## 2. Stack Frontend (El patrón HDA)
Para evitar la complejidad de construir un Single Page Application (SPA) con React o Vue, adoptaremos el patrón **HDA (HTMX + Django + Alpine.js)**.
### HTMX
- **Propósito**: Realizar peticiones AJAX, filtros dinámicos, paginación y mutaciones del DOM sin escribir JavaScript.
- **WebSockets**: Utilizaremos la extensión `htmx-ws` para inyectar fragmentos HTML directamente al DOM cuando Channels emita un evento, eliminando el parseo manual de JSON en JS.
### Alpine.js
- **Propósito**: Manejo del estado efímero del lado del cliente.
- Casos de uso: Modales, menús desplegables (dropdowns), alertas (toasts), y pestañas (tabs). Sustituye por completo al código espagueti en Vanilla JS o jQuery.
### Tailwind CSS (Sugerido)
- **Propósito**: Sistema de diseño basado en utilidades.
- Permite estilizar componentes directamente en los templates de Django sin mantener un archivo `style.css` gigante y difícil de escalar.
### Formularios: `django-widget-tweaks`
- Herramienta para inyectar clases CSS (como las de Tailwind o Bootstrap) directamente en los campos del formulario desde el HTML, eliminando la necesidad de scripts globales que mutan el DOM (`MutationObserver`).
---
## 3. Infraestructura y Despliegue
### Base de Datos y Storage: Supabase
Migramos de servicios locales a servicios administrados en la nube para garantizar disponibilidad y backups automáticos.
- **PostgreSQL**: Base de datos principal conectada mediante un *Connection Pooler* transaccional.
- **S3 Storage**: Almacenamiento en la nube (vía `django-storages` y `boto3`) para evidencias, facturas y comprobantes, garantizando que el contenedor Docker sea *stateless* (sin estado local).
### Servidor de Aplicaciones: Gunicorn + Uvicorn
- Para producción, reemplazaremos la ejecución directa de Daphne por **Gunicorn** usando `UvicornWorker`. Esto permite levantar múltiples procesos *workers* que aprovechan mejor los núcleos del servidor y se reinician automáticamente si fallan.
### Caché: Redis
- Además de ser el broker de Celery y Channels, habilitaremos Redis como el backend de la variable `CACHES` en Django. Esto permite almacenar en memoria resultados de consultas pesadas (como los KPIs del Dashboard) reduciendo la carga sobre Supabase.
### Integración Continua (CI/CD)
- **GitHub Actions**: Implementación de un pipeline que ejecute pruebas automáticas, verifique la calidad del código (Linting) y construya la imagen de Docker en cada Push a la rama `main`.
---
## 4. Hoja de Ruta (Roadmap de Implementación)
1. **Fase 1: Estabilización de Infraestructura**
- [ ] Conectar definitivamente Supabase (DB + Storage) mediante el `.env`.
- [ ] Habilitar Redis como motor de Caché en Django.
- [ ] Cambiar el servidor de desarrollo a Gunicorn/Uvicorn para producción.
2. **Fase 2: Refactorización Frontend (HDA)**
- [ ] Instalar HTMX y configurarlo en `base.html`.
- [ ] Instalar `django-widget-tweaks` para refactorizar los formularios.
- [ ] Migrar el flujo de WebSockets en JS nativo hacia la extensión `htmx-ws`.
3. **Fase 3: Optimización Backend**
- [ ] Implementar la primera tarea en segundo plano con Celery (ej. Exportar CSV).
- [ ] Migrar el Dashboard a vistas asíncronas (`async def`) para acelerar la carga de KPIs.
+16
View File
@@ -0,0 +1,16 @@
import re
with open('docker-compose.yml', 'r') as f:
content = f.read()
new_service = """ tax-api:
build: ./tax_api
ports:
- "8001:8000"
restart: unless-stopped
celery:"""
content = content.replace(' celery:', new_service)
with open('docker-compose.yml', 'w') as f:
f.write(content)
+11
View File
@@ -0,0 +1,11 @@
import os
import django
from django.conf import settings
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')
django.setup()
from expenses.forms import ExpenseForm
form = ExpenseForm()
print(form['receipt'])