# Inventschario — Documento de Arquitectura **Versión:** 1.0.0-iteracion1 **Fecha:** 2026-08-03 **Estado:** Propuesta para revisión --- ## 1. Visión General Inventschario采用 arquitectura de tres capas con separación clara entre presentación, lógica de negocio y persistencia. La capa de presentación se ejecuta en el navegador del usuario; la capa de negocio y persistencia corren como un servidor local HTTP que solo escucha en `127.0.0.1`. La pasarela entre frontend y backend es una API REST documentada, de forma que el frontend puede sustituirse completamente sin modificar ninguna línea del backend, y viceversa. --- ## 2. Diagrama de Componentes ``` ┌─────────────────────────────────────────────────────────────────┐ │ NAVEGADOR (Edge) │ │ │ │ ┌───────────────────────────────────────────────────────────┐ │ │ │ FRONTEND │ │ │ │ │ │ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ │ │Dashboard │ │Inventario│ │ Formular │ │ Config │ │ │ │ │ │ Page │ │ Page │ │ ios │ │ Page │ │ │ │ │ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │ │ │ │ │ │ │ │ │ │ │ │ ┌────┴──────────────┴──────────────┴──────────────┴────┐ │ │ │ │ Router (SPA) │ │ │ │ └────────────────────┬─────────────────────────────────┘ │ │ │ │ │ │ │ │ │ ┌────────────────────┴─────────────────────────────────┐ │ │ │ │ API Client (fetch wrapper) │ │ │ │ └────────────────────┬─────────────────────────────────┘ │ │ │ │ │ │ │ │ │ ┌────────────────────┴─────────────────────────────────┐ │ │ │ │ Component Library │ │ │ │ │ Table | Form | Modal | Toast | Sidebar | Charts │ │ │ │ └──────────────────────────────────────────────────────┘ │ │ │ └───────────────────────────┬───────────────────────────────┘ │ │ │ HTTP localhost:PORT │ ├──────────────────────────────┼──────────────────────────────────┤ │ │ │ │ ┌───────────────────────────┴───────────────────────────────┐ │ │ │ API GATEWAY │ │ │ │ │ │ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ │ │ /devices │ │ /import │ │ /backups │ │ /config │ │ │ │ │ │ /history │ │ /export │ │ │ │ /labels │ │ │ │ │ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │ │ │ │ │ │ │ │ │ │ │ │ ┌────┴──────────────┴──────────────┴──────────────┴────┐ │ │ │ │ │ Middleware Layer │ │ │ │ │ │ CORS (localhost) | JSON parsing | Error handling │ │ │ │ │ └────────────────────┬─────────────────────────────────┘ │ │ │ └───────────────────────┼───────────────────────────────────┘ │ │ │ │ │ ┌───────────────────────┴───────────────────────────────────┐ │ │ │ SERVICE LAYER │ │ │ │ │ │ │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │ │ │DeviceService │ │BackupService │ │ImportService │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │- CRUD │ │- crear │ │- parse CSV │ │ │ │ │ │- buscar │ │- restaurar │ │- mapear │ │ │ │ │ │- filtrar │ │- eliminar │ │- validar │ │ │ │ │ │- baja │ │- verificar │ │- duplicados │ │ │ │ │ │- enajenar │ │ antigüedad │ │ │ │ │ │ │ │- historial │ │ │ │ │ │ │ │ │ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │ │ │ │ │ │ │ │ │ │ │ ┌──────┴──────────────────┴──────────────────┴───────┐ │ │ │ │ │ ExportService | ConfigService │ │ │ │ │ └──────────────────────┬─────────────────────────────┘ │ │ │ └─────────────────────────┼─────────────────────────────────┘ │ │ │ │ │ ┌─────────────────────────┴─────────────────────────────────┐ │ │ │ DATA LAYER │ │ │ │ │ │ │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │ │ │ DeviceRepo │ │ ConfigRepo │ │ BackupRepo │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ SQLite CRUD │ │ KV Store │ │ Log CRUD │ │ │ │ │ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │ │ │ │ │ │ │ │ │ │ │ ┌──────┴──────────────────┴──────────────────┴───────┐ │ │ │ │ │ SQLite (WAL mode) │ │ │ │ │ │ inventschario.db │ │ │ │ │ └────────────────────────────────────────────────────┘ │ │ │ └───────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────┘ ``` --- ## 3. Alternativas de Arquitectura ### Alternativa A: Python + Flask (Recomendada) ``` [Browser] ──HTTP──► [Flask server] ──► [SQLite] │ │ │ HTML/CSS/JS │ Python services │ (Alpine.js) │ (DeviceService, etc.) │ │ ◄──── JSON ──────────►│ ``` **Por qué se recomienda:** - Python stdlib incluye sqlite3, http.server, json, gzip, csv, shutil - Flask es ligero (~500KB) y no necesita build step - PyInstaller empaqueta todo en un .exe autocontenido - El ecosistema Python tiene librerías para todo lo necesario - Desarrollo rápido, fácil de mantener **Componentes:** - `flask` — Servidor web minimalista - `schedule` — Programador de tareas (backups diarios) - `pyinstaller` — Empaquetado en .exe ### Alternativa B: .NET 8 Minimal API ``` [Browser] ──HTTP──► [Kestrel server] ──► [SQLite via EF Core] │ │ │ HTML/CSS/JS │ C# services │ (embebido) │ (DeviceService, etc.) │ │ ◄──── JSON ──────────►│ ``` **Por qué es alternativa válida:** - `dotnet publish -r win-x64 --self-contained` produce .exe sin runtime - Rendimiento superior a Python en operaciones intensivas - Integración nativa con Windows - Entity Framework Core para ORM robusto **Componentes:** - ASP.NET Core Minimal API - Microsoft.Data.Sqlite - Hangfire (tareas programadas) ### Alternativa C: Go + net/http ``` [Browser] ──HTTP──► [Go HTTP server] ──► [SQLite via CGO] │ │ │ HTML/CSS/JS │ Go handlers │ (embed.FS) │ (DeviceService, etc.) │ │ ◄──── JSON ──────────►│ ``` **Por qué es alternativa válida:** - Binario más pequeño (10-15 MB) - Rendimiento excepcional - Sin dependencias en runtime - `embed.FS` embebe archivos estáticos directamente en el binario **Componentes:** - `net/http` (stdlib) - `mattn/go-sqlite3` (CGO) - `embed.FS` (archivos estáticos) ### Decisión: Python + Flask Para la primera iteración, Python + Flask es la opción que mejor equilibra: - Velocidad de desarrollo - Facilidad de distribución (PyInstaller) - Modularidad del frontend (API REST pura) - Ecosistema de herramientas Si en iteraciones futuras el tamaño del .exe o la detección por antivirus se convierten en problemas, se documentará la migración a .NET 8. --- ## 4. Patrones de Diseño ### 4.1 Repository Pattern (Capa de Datos) Cada tabla tiene su repository que encapsula las consultas SQL: ```python class DeviceRepository: def __init__(self, db_path): self.db_path = db_path def get_all(self, filters=None): ... def get_by_id(self, device_id): ... def create(self, device_data): ... def update(self, device_id, device_data): ... def delete(self, device_id): ... def search(self, query): ... ``` ### 4.2 Service Layer (Lógica de Negocio) Los services orquestan la lógica sin conocer la API HTTP: ```python class DeviceService: def __init__(self, device_repo, history_repo): self.device_repo = device_repo self.history_repo = history_repo def create_device(self, data, user): device = self.device_repo.create(data) self.history_repo.log(device.id, 'created', user=user) return device def decommission(self, device_id, reason, user): device = self.device_repo.get_by_id(device_id) self.device_repo.update_status(device_id, 'decommissioned') self.history_repo.log(device_id, 'decommissioned', notes=reason, user=user) ``` ### 4.3 API Gateway (Capa HTTP) Las rutas API son delgadas — solo parsean la request, llaman al service, y formatean la response: ```python @bp.route('/api/v1/devices', methods=['POST']) def create_device(): data = request.get_json() device = device_service.create_device(data, current_user) return jsonify(device.to_dict()), 201 ``` ### 4.4 Frontend Component Architecture El frontend usa un patrón de componentes simples sin framework pesado: ```javascript // Cada componente es un objeto con render() y bind() const DeviceTable = { render(devices) { return `