Revert "docs: add project history narrative in Spanish for Ivan"\n\nThis commit has been undone by moving the file to ~/tmp/
This commit is contained in:
parent
d184b0423e
commit
9662f98169
1 changed files with 0 additions and 637 deletions
|
|
@ -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/<id>` - 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 `</style>` 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
|
|
||||||
<h1>{{ _('Tablet Management System') }}</h1>
|
|
||||||
<p>{{ _('Available Tablets') }}: {{ count }}</p>
|
|
||||||
```
|
|
||||||
|
|
||||||
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*
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue