diff --git a/docs/HISTORIA_PROYECTO_IVAN.md b/docs/HISTORIA_PROYECTO_IVAN.md deleted file mode 100644 index ded8f21..0000000 --- a/docs/HISTORIA_PROYECTO_IVAN.md +++ /dev/null @@ -1,637 +0,0 @@ -# Historia del Proyecto GestionTablets - -*Un relato técnico para Iván sobre el desarrollo del Sistema de Gestión de Tablets* - ---- - -## 📖 Índice - -1. [Los Inicios](#los-inicios) -2. [La Arquitectura Base](#la-arquitectura-base) -3. [Proveedores y Tecnologías](#proveedores-y-tecnologías) -4. [Hitos del Desarrollo](#hitos-del-desarrollo) -5. [Internacionalización (i18n)](#internacionalización-i18n) -6. [Identidad Corporativa](#identidad-corporativa) -7. [Lecciones Aprendidas](#lecciones-aprendidas) -8. [Estado Actual](#estado-actual) - ---- - -## 🚀 Los Inicios - -El proyecto **GestionTablets** nació como una herramienta interna para gestionar el préstamo de tablets y otros dispositivos en un entorno de equipo pequeño (5 usuarios técnicos). La idea inicial era simple: llevar un control claro de qué dispositivo estaba con qué persona, cuándo se prestó y cuándo se devolvió. - -### Contexto Inicial -- **Tipo de proyecto**: Herramienta interna (no aplicación pública) -- **Usuarios objetivo**: 5 usuarios técnicos -- **Requisitos principales**: - - Registrar tablets y otros dispositivos - - Gestionar préstamos a usuarios - - Historial de transacciones - - Interfaz sencilla y funcional - -### Primera Versión: CLI - -El proyecto comenzó con una versión **CLI (Command Line Interface)** en Python puro con SQLite. Esta versión, aunque funcional, tenía limitaciones: - -```python -# Ejemplo de la versión CLI inicial -import sqlite3 -from datetime import datetime - -def add_tablet(brand, model, serial_number): - """Añadir una nueva tablet al inventario""" - conn = sqlite3.connect('tablets.db') - cursor = conn.cursor() - cursor.execute(''' - INSERT INTO tablets (brand, model, serial_number, status) - VALUES (?, ?, ?, 'available') - ''', (brand, model, serial_number)) - conn.commit() - print(f"✓ Tablet añadida: {brand} {model} ({serial_number})") -``` - -**Limitaciones de la CLI:** -- Interfaz no intuitiva para usuarios no técnicos -- Sin visualización de datos en formato amigable -- Dificultad para ver el estado actual de préstamos - ---- - -## 🏗️ La Arquitectura Base - -### Transición a Web: Flask - -Se decidió migrar a una **aplicación web** usando **Flask**, un micro-framework de Python, para proporcionar una interfaz más amigable. - -**Estructura del proyecto:** -``` -GestionTablets/ -├── app.py # Aplicación principal Flask -├── minimal_app.py # Versión CLI (deprecada) -├── templates/ # Plantillas HTML (Jinja2) -│ ├── base.html # Plantilla base -│ ├── index.html # Página principal -│ ├── add_tablet.html # Formulario añadir tablet -│ ├── add_user.html # Formulario añadir usuario -│ ├── loan_tablet.html # Formulario préstamo -│ └── ... -├── static/ # Archivos estáticos -│ └── Schamann.png # Logo corporativo -├── translations/ # Archivos de traducción -│ ├── es/LC_MESSAGES.mo -│ └── es/LC_MESSAGES.po -├── docs/ # Documentación -│ ├── CORPORATE_DESIGN.md # Diseño corporativo -│ ├── FRONTEND_OPTIONS.md # Opciones de frontend -│ ├── MIGRATION_TO_POSTGRES.md -│ └── RESPONSIVE_CSS.md -├── tests/ # Suite de pruebas -│ ├── conftest.py -│ ├── test_core.py -│ ├── test_edge_cases.py -│ └── test_minimal_app.py -├── tablets.db # Base de datos SQLite -├── pyproject.toml # Configuración del proyecto -├── requirements.txt # Dependencias -└── README.md # Documentación principal -``` - -### Base de Datos: SQLite - -Se optó por **SQLite** como base de datos por su simplicidad y porque es perfecta para: -- Aplicaciones internas con pocos usuarios -- No requiere servidor de base de datos -- Fácil de mantener y hacer backup -- Incluida en Python (sin dependencias adicionales) - -**Esquema de la base de datos:** - -```sql --- Tablets -CREATE TABLE tablets ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - brand TEXT NOT NULL, - model TEXT NOT NULL, - serial_number TEXT UNIQUE NOT NULL, - status TEXT DEFAULT 'available', - notes TEXT -); - --- Usuarios -CREATE TABLE users ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - name TEXT NOT NULL, - email TEXT, - phone TEXT, - identification TEXT UNIQUE -); - --- Préstamos -CREATE TABLE loans ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - tablet_id INTEGER NOT NULL, - user_id INTEGER NOT NULL, - loan_date TEXT NOT NULL, - return_date TEXT, - status TEXT DEFAULT 'active', - FOREIGN KEY (tablet_id) REFERENCES tablets(id), - FOREIGN KEY (user_id) REFERENCES users(id) -); - --- Dispositivos no prestables -CREATE TABLE non_loanable_devices ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - brand TEXT NOT NULL, - model TEXT NOT NULL, - serial_number TEXT UNIQUE NOT NULL, - device_type TEXT NOT NULL, - location TEXT, - status TEXT DEFAULT 'available', - notes TEXT, - purchase_date TEXT, - purchase_cost REAL -); -``` - ---- - -## 🛠️ Proveedores y Tecnologías - -### Lenguaje y Framework -- **Python 3.14+**: Lenguaje principal del proyecto -- **Flask 3.x**: Framework web principal -- **Flask-Babel 4.0.0**: Para internacionalización (i18n) -- **Jinja2**: Motor de plantillas - -### Frontend -- **Tailwind CSS**: Framework CSS para estilos (vía CDN) -- **HTMX**: Para interactividad sin JavaScript (en algunas partes) -- **Alpine.js**: Considerado pero no implementado - -### Base de Datos -- **SQLite**: Base de datos principal (embebida) -- **PostgreSQL**: Opción futura documentada (ver `docs/MIGRATION_TO_POSTGRES.md`) - -### Herramientas de Desarrollo -- **pytest**: Framework de pruebas -- **pytest-cov**: Cobertura de código -- **Git**: Control de versiones -- **GitHub/GitLab**: Hosting del repositorio (servidor propio en `hq.ijuanes.ovh:3333`) - -### Infraestructura -- **Servidor Git**: `http://hq.ijuanes.ovh:3333` -- **Usuario**: `ijuanes` -- **Repositorio**: `GestionTablets` - ---- - -## 🎯 Hitos del Desarrollo - -### Fase 1: Versión CLI Inicial -**Fecha**: Junio 2026 (inicio) - -- Creación de `minimal_app.py` con funciones básicas -- Implementación de CRUD para tablets y usuarios -- Gestión básica de préstamos -- Base de datos SQLite - -**Commit representativo**: Versión inicial del proyecto - ---- - -### Fase 2: Migración a Web -**Fecha**: Mediados de Junio 2026 - -- Creación de `app.py` con Flask -- Diseño de plantillas HTML con Jinja2 -- Implementación de rutas web: - - `/` - Página principal con tablets disponibles - - `/add_tablet` - Añadir nueva tablet - - `/add_user` - Añadir nuevo usuario - - `/loan_tablet` - Prestar tablet - - `/return_tablet/` - Devolver tablet - - `/history` - Historial de préstamos - -**Mejoras:** -- Interfaz visual más intuitiva -- Navegación entre páginas -- Visualización de datos en tablas - ---- - -### Fase 3: Internacionalización (i18n) -**Fecha**: Junio 2026 - -#### Problema Inicial -La aplicación solo estaba en inglés y no tenía soporte para múltiples idiomas. - -#### Solución Implementada -1. **Flask-Babel 4.0.0**: Integración con Flask -2. **Estructura de traducción**: - ``` - translations/ - └── es/ - ├── LC_MESSAGES.mo # Archivo binario - └── LC_MESSAGES.po # Archivo fuente - ``` -3. **Configuración**: - ```python - app.config['BABEL_DEFAULT_LOCALE'] = 'es' - app.config['LANGUAGES'] = {'en': 'English', 'es': 'Español'} - app.config['BABEL_TRANSLATION_DIRECTORIES'] = 'translations' - ``` - -#### Problemas y Soluciones - -**Problema 1**: Flask-Babel 4.0.0 cambió su API -- ❌ `@babel.localeselector` - Eliminado -- ❌ `@babel.locale_selector` - No existe -- ✅ `Babel(app, locale_selector=func)` - Enfoque correcto - -**Solución**: Reescribir la configuración para usar el nuevo API. - -**Commit**: `49e4562` - fix(i18n): define get_locale function before passing to Babel constructor - -**Problema 2**: Las plantillas no usaban el sistema de traducción -- Muchas plantillas tenían texto en inglés hardcodeado -- Ejemplo: `add_tablet.html`, `add_user.html`, `loan_tablet.html` - -**Solución**: Actualizar todas las plantillas para usar `{{ _('texto') }}` - -**Commit**: `2248237` - fix(i18n): enable translations in all templates - -**Problema 3**: No se guardaba la preferencia de idioma -- El idioma se perdía al navegar entre páginas -- No había cookies ni sesión para persistir la selección - -**Solución**: Implementar persistencia con cookies + sesión - -```python -# En app.py -from flask import session, make_response - -def get_locale(): - # 1. Intentar obtener de cookie - lang = request.cookies.get('language') - if lang and lang in app.config['LANGUAGES']: - return lang - # 2. Intentar obtener de sesión - if hasattr(request, 'session') and 'language' in request.session: - return request.session['language'] - # 3. Default a Español - return 'es' - -@app.route('/set_language') -def set_language(): - lang = request.args.get('lang') - if lang and lang in app.config['LANGUAGES']: - session['language'] = lang - resp = make_response(redirect(request.referrer or '/')) - resp.set_cookie('language', lang, max_age=31536000) # 1 año - return resp - return redirect(request.referrer or '/') -``` - -**Commit**: `2248237` - Cookie-based language persistence - ---- - -### Fase 4: Pruebas Unitarias -**Fecha**: Junio 2026 - -Se implementó una **suite completa de pruebas** con pytest: - -**Estructura:** -``` -tests/ -├── __init__.py -├── conftest.py # Fixtures de pytest -├── test_core.py # 21 pruebas de funcionalidad principal -├── test_edge_cases.py # 14 pruebas de casos límite -└── test_minimal_app.py # 11 pruebas de funciones de aplicación -``` - -**Cobertura:** -- Pruebas de funciones CRUD -- Casos límite (prestar tablet ya prestada, devolver préstamo inexistente) -- Validación de datos (números de serie duplicados) -- Manejo de errores - -**Resultado**: 46 pruebas, todas pasando ✅ - -**Commits:** -- `83ac67f` - test: add comprehensive unit test suite -- `dea2f23` - docs(ui): update RESPONSIVE_CSS.md with bug fix documentation - ---- - -### Fase 5: Diseño Responsive -**Fecha**: Junio 2026 - -**Problema**: La navegación desbordaba en pantallas pequeñas o al hacer zoom. - -**Solución**: Implementar CSS responsive con Tailwind CSS - -**Cambios:** -- Añadir `overflow-x: hidden` a body y contenedores -- Envolver tablas en contenedores con scroll horizontal -- Añadir breakpoints para móvil, tablet y desktop -- Crear `docs/RESPONSIVE_CSS.md` con documentación - -**Commits:** -- `28232db` - fix(ui): add missing `` tag in base.html -- `927c323` - feat(ui): add responsive CSS for mobile accessibility -- `26b77cf` - fix(ui): prevent navigation overflow on zoom and small screens - ---- - -### Fase 6: Documentación de Migración a PostgreSQL -**Fecha**: Junio 2026 - -Aunque el proyecto usa SQLite, se documentó el camino para migrar a PostgreSQL: - -**Archivo**: `docs/MIGRATION_TO_POSTGRES.md` - -**Contenido:** -- Comparación SQLite vs PostgreSQL -- Pasos de migración -- Cambios en el código -- Configuración de conexión -- Scripts SQL para crear tablas - -**Commit**: `dea2f23` - docs: add PostgreSQL migration guide - ---- - -### Fase 7: Identidad Corporativa -**Fecha**: 20 Junio 2026 - -#### Logo Corporativo -- **Archivo**: `assets/Schamann.png` (175x161 píxeles) -- **Ubicación web**: `/static/Schamann.png` -- **Integración**: Añadido al header de la aplicación -- **Estilo**: Forzado a 40px de altura con `object-contain` - -**Commit**: `c233040` - Add corporative logo - -#### Paleta de Colores Corporativos -Se reemplazó la paleta de colores genérica por los colores corporativos: - -| Color | Código Hex | RGB | Uso | -|-------|------------|-----|-----| -| **Azul Cobalto** | `#1338BE` | rgb(19, 56, 190) | Headers, navegación | -| **Naranja Tigre** | `#FC6A03` | rgb(252, 106, 3) | Acentos, indicadores de carga | -| **Verde Esmeralda** | `#028A0F` | rgb(2, 138, 15) | Estados de éxito | - -**Configuración en Tailwind:** -```javascript -tailwind.config = { - theme: { - extend: { - colors: { - cobalt: { - 50: '#f0f5ff', - 500: '#1338BE', - // ... todas las sombras - }, - tiger: { - 50: '#fff8f0', - 500: '#FC6A03', - // ... - }, - emerald: { - 50: '#f0fdf4', - 500: '#028A0F', - // ... - } - } - } - } -} -``` - -**Documentación**: `docs/CORPORATE_DESIGN.md` - -**Commit**: `8c1d12a` - feat(ui): add corporate logo and update colors - ---- - -## 🌍 Internacionalización (i18n) - -### Estado Actual - -✅ **Completo**: -- Flask-Babel 4.0.0 configurado correctamente -- Archivos de traducción creados (es/LC_MESSAGES.po, es/LC_MESSAGES.mo) -- Todas las plantillas usan `{{ _('texto') }}` -- Persistencia de idioma con cookies (1 año) + sesión -- Español como idioma por defecto -- Cambiador de idioma funcional en el header - -### Cómo Funciona - -1. **Selección de idioma**: - - Por defecto: Español - - URL: `?lang=en` o `?lang=es` - - Cookie: `language` (1 año de expiración) - - Sesión: `session['language']` - -2. **Uso en plantillas**: - ```html -

{{ _('Tablet Management System') }}

-

{{ _('Available Tablets') }}: {{ count }}

- ``` - -3. **Traducciones**: - - Los archivos `.po` contienen las traducciones - - Se compilan a `.mo` para uso en producción - - Comando para actualizar: `pybabel extract -o translations/messages.pot .` - -### Idiomas Soportados -- **Español (es)**: Idioma por defecto -- **Inglés (en)**: Alternativa - ---- - -## 🎨 Identidad Corporativa - -### Logo -- **Archivo**: `Schamann.png` -- **Dimensiones**: 175x161 píxeles -- **Formato**: PNG con transparencia -- **Ubicación**: `/static/Schamann.png` -- **Visualización**: 40px de altura, manteniendo proporciones - -### Colores - -#### Azul Cobalto (#1338BE) -- **Uso principal**: Headers, navegación, acciones principales -- **Significado**: Profesionalismo, confianza -- **Contraste**: Texto blanco sobre fondos oscuros - -#### Naranja Tigre (#FC6A03) -- **Uso principal**: Acentos, indicadores de carga, acciones secundarias -- **Significado**: Energía, acción -- **Contraste**: Texto blanco sobre fondos - -#### Verde Esmeralda (#028A0F) -- **Uso principal**: Estados de éxito, confirmaciones -- **Significado**: Éxito, positividad -- **Contraste**: Texto blanco sobre fondos - -### Documentación -Todo el diseño corporativo está documentado en `docs/CORPORATE_DESIGN.md`: -- Paleta de colores completa con sombras -- Guías de uso -- Ejemplos de implementación -- Accesibilidad - ---- - -## 📚 Lecciones Aprendidas - -### 1. Versiones de Librerías -**Lección**: Siempre verificar la compatibilidad de versiones. - -**Ejemplo**: Flask-Babel 4.0.0 cambió su API completamente. Lo que funcionaba en la versión 3.x no funcionaba en 4.x. - -**Solución**: Leer la documentación de la versión específica que se está usando. - ---- - -### 2. Internacionalización desde el Inicio -**Lección**: Implementar i18n desde el principio, no como un afterthought. - -**Problema**: Muchas plantillas tenían texto hardcodeado en inglés. - -**Solución**: Revisar todas las plantillas y envolver todo el texto visible con `{{ _('...') }}`. - ---- - -### 3. Persistencia de Preferencias -**Lección**: Para aplicaciones internas, las cookies son suficientes. - -**Decisión**: No implementar consentimiento de cookies (es una app interna). - -**Implementación**: Cookie de 1 año + sesión para persistencia de idioma. - ---- - -### 4. Diseño Responsive -**Lección**: Probar en diferentes tamaños de pantalla y niveles de zoom. - -**Problema**: La navegación desbordaba al hacer zoom o en pantallas pequeñas. - -**Solución**: Usar `overflow-x: hidden` y contenedores con scroll. - ---- - -### 5. Pruebas Unitarias -**Lección**: Las pruebas dan confianza para hacer refactorización. - -**Beneficio**: Al tener 46 pruebas pasando, pudimos hacer cambios en la configuración de i18n sin miedo a romper algo. - ---- - -## 🎯 Estado Actual - -### Versión -- **Branch principal**: `develop` -- **Commits recientes**: - - `2248237` - fix(i18n): enable translations in all templates and implement cookie-based language persistence - - `8c1d12a` - feat(ui): add corporate logo and update colors to Cobalt Blue, Tiger Orange, Emerald Green - - `c233040` - Add corporative logo - - `49e4562` - fix(i18n): define get_locale function before passing to Babel constructor - -### Funcionalidades - -| Funcionalidad | Estado | Notas | -|---------------|--------|-------| -| Gestión de tablets | ✅ | CRUD completo | -| Gestión de usuarios | ✅ | CRUD completo | -| Préstamos | ✅ | Prestar y devolver | -| Historial | ✅ | Visualización completa | -| Internacionalización | ✅ | Español/Inglés | -| Persistencia de idioma | ✅ | Cookies + sesión | -| Diseño responsive | ✅ | Móvil, tablet, desktop | -| Logo corporativo | ✅ | Integración completa | -| Colores corporativos | ✅ | Paleta aplicada | -| Pruebas unitarias | ✅ | 46 pruebas pasando | - -### Próximos Pasos (Opcionales) - -1. **Migración a PostgreSQL**: Documentación lista, solo falta implementar -2. **Más idiomas**: Añadir francés, alemán, etc. -3. **Autenticación**: Implementar login para usuarios -4. **Notificaciones**: Recordatorios de devoluciones -5. **Exportación**: Exportar datos a CSV/Excel - ---- - -## 📞 Cómo Ejecutar el Proyecto - -### Requisitos -- Python 3.14+ -- pip o uv (gestor de paquetes) - -### Instalación - -```bash -# Clonar el repositorio -git clone http://hq.ijuanes.ovh:3333/ijuanes/GestionTablets.git -cd GestionTablets - -# Crear entorno virtual -python3 -m venv .venv -source .venv/bin/activate # Linux/Mac -# .venv\Scripts\activate # Windows - -# Instalar dependencias -pip install -r requirements.txt - -# Inicializar base de datos -python3 app.py # La base de datos se crea automáticamente -``` - -### Ejecutar - -```bash -# Desarrollo -python3 app.py - -# Acceder a: -# http://localhost:5000 - Español (por defecto) -# http://localhost:5000?lang=en - Inglés -``` - -### Pruebas - -```bash -# Ejecutar todas las pruebas -python3 -m pytest tests/ -v - -# Con cobertura -python3 -m pytest tests/ --cov=. --cov-report=html -``` - ---- - -## 🏁 Conclusión - -El proyecto **GestionTablets** ha evolucionado de una simple CLI a una aplicación web completa con: -- ✅ Internacionalización funcional -- ✅ Identidad corporativa integrada -- ✅ Diseño responsive -- ✅ Suite de pruebas completa -- ✅ Documentación exhaustiva - -Es un ejemplo de cómo una herramienta interna puede ser profesional, mantenible y escalable, incluso con recursos limitados. - -**Para Iván**: Este proyecto demuestra que con Python, Flask y SQLite se pueden crear aplicaciones robustas para equipos pequeños, y que la internacionalización y el diseño corporativo son importantes incluso en herramientas internas. - ---- - -*Documento generado el 20 de Junio de 2026* -*Para: Iván* -*Proyecto: GestionTablets*