- Complete project narrative from CLI to web application - Covers all milestones: i18n, responsive design, corporate identity - Includes providers, technologies, and lessons learned - Written in Spanish for Ivan - Omits sensitive information (API keys, credentials)
637 lines
19 KiB
Markdown
637 lines
19 KiB
Markdown
# 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*
|