Plataforma escolar integral para la red Universidad de Guadalajara. Reemplaza procesos manuales dispersos con una sola app: navegaciΓ³n del campus, horarios con detecciΓ³n de conflictos, calificaciones, asistencia, trΓ‘mites en lΓnea, anuncios y panel administrativo.
Hoy en CUValles cada cosa vive en un lado distinto: el horario impreso, el kΓ‘rdex en una ventanilla, el mapa en un PDF, los anuncios en un grupo de WhatsApp. Matute Guide unifica todo en una sola plataforma, accesible desde la web y desde una app Android.
| Antes | Con Matute Guide |
|---|---|
| Llegar al salΓ³n equivocado porque el horario estΓ‘ desactualizado | Horario en tiempo real con detecciΓ³n automΓ‘tica de conflictos |
| Perderse buscando un edificio | Mapa interactivo del campus con cΓ³mo-llegar |
| Hacer fila para una constancia | TrΓ‘mites en lΓnea con folio y seguimiento |
| Enterarte tarde de un parcial | Notificaciones push + en-app de cada cambio |
| Llamar al coordinador para preguntar tu calificaciΓ³n | Calificaciones publicadas y visibles para el estudiante |
| El admin maneja todo en Excel | Panel con KPIs, CRUD y export CSV |
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β WEB (Flask + Jinja) MΓVIL (Flutter Android) β
β ββββββββββββββββββββββββ ββββββββββββββββββββββ β
β β Estudiante β β Login β β
β β Β· Dashboard 5 tabs β β Dashboard β β
β β Β· Horario builder β ββββ β Horario scrollable β β
β β Β· Inscripciones β β β Salones + Mapa β β
β β Β· TrΓ‘mites β β β Calif/Asistencia β β
β ββββββββββββββββββββββββ β β TrΓ‘mites β β
β ββββββββββββββββββββββββ β β Notifs (local) β β
β β Profesor β β βββββββββββ¬βββββββββββ β
β β Β· Pasar lista β β β β
β β Β· Capturar calif. β β β Bearer JWT β
β ββββββββββββββββββββββββ β β β
β ββββββββββββββββββββββββ β βΌ β
β β Admin β β ββββββββββββββββββββββββββββββ β
β β Β· KPIs dashboard β ββββββΊ Backend Flask β β
β β Β· CRUD usuarios β Cookies β Β· 13 blueprints API β β
β β Β· Horarios 3 vistas β httpOnlyβ Β· 19 modelos SQLAlchemy β β
β β Β· Reportes CSV β + sesiΓ³nβ Β· JWT 1h+30d con rotaciΓ³n β β
β β Β· Audit log β β Β· Audit log + Soft-delete β β
β ββββββββββββββββββββββββ β Β· SSE notificaciones β β
β β Β· Rate limit + CORS β β
β β Β· SQLite dev / Postgres β β
β β prod β β
β βββββββββββββββββββββββββββββ β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# 1) Clonar y entrar al proyecto
git clone https://github.com/MapSchool1/web.git matute-guide
cd matute-guide
# 2) Instalar dependencias Python en un venv
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
# 3) Poblar la base de datos con datos realistas
python seed.py
# β 1 plantel, 3 carreras, 44 salones, 72 materias,
# 12 usuarios, horario completo de Γlvaro CON conflicto MiΓ© 11:00
# 4) Levantar el servidor
python run.py
# β http://localhost:5001cd flutter_app
flutter pub get
# Lanzar emulador y correr
flutter emulators --launch <id>
flutter run --dart-define=API_BASE=http://10.0.2.2:5001
# O construir APK release
flutter build apk --release --target-platform android-arm64
# β build/app/outputs/flutter-apk/app-release.apk (~19 MB)Todas las cuentas estΓ‘n en seed.py. La interesante es Γlvaro porque su horario tiene un conflicto real el miΓ©rcoles 11:00 (ProgramaciΓ³n Web LAB-4 vs Bases de Datos II LAB-2) β sirve para validar que la detecciΓ³n automΓ‘tica funciona.
| Password | Rol | Lo que verΓ‘s | |
|---|---|---|---|
[email protected] |
Admin1234! |
admin | Panel con KPIs Β· CRUD usuarios Β· 3 vistas de horarios Β· export CSV |
[email protected] |
Director1! |
director | Mismo panel, alcance plantel |
[email protected] |
Coordinador1! |
coordinador | Mismo panel, alcance departamento |
[email protected] |
Estudiante1! |
estudiante | Dashboard 4Β° InformΓ‘tica con conflicto MiΓ© 11:00 β |
[email protected] |
Estudiante1! |
estudiante | 2Β° BiotecnologΓa |
[email protected] |
Estudiante1! |
estudiante | 6Β° EnergΓas |
[email protected] |
Profesor1! |
profesor | CΓ‘lculo I β pasa lista, captura calificaciones |
| 5 profesores mΓ‘s | Profesor1! |
profesor | β |
| Capa | QuΓ© hace |
|---|---|
app/api/ β 13 blueprints REST |
auth Β· users Β· academic Β· campus Β· horarios Β· inscripciones Β· tramites Β· notifications (SSE) Β· stats Β· mapa Β· search Β· audit Β· anuncios |
app/web/ β vistas Jinja |
landing Β· auth Β· student Β· profesor Β· admin Β· components-demo |
app/models/ β 19 modelos SQLAlchemy en 7 dominios |
usuarios (con soft-delete) Β· acadΓ©mico Β· campus Β· horarios (con detecciΓ³n de conflictos) Β· inscripciones Β· trΓ‘mites Β· notificaciones |
app/utils/ |
roles_required decorator Β· pagination Β· audit log helper Β· notify() Β· detectar_conflictos_horario() |
seed.py |
Datos realistas reproducibles β incluye conflicto intencional para QA |
Endurecimiento de seguridad incluido:
- JWT access 1h + refresh 30d con rotaciΓ³n automΓ‘tica y blacklist
- En web: cookies httpOnly + SameSite=Lax + sesiΓ³n Flask. En APK: Bearer header
- Bcrypt cost factor 12 Β· Rate limit 10/min en login Β· CORS explΓcito
- Audit log inmutable de cada acciΓ³n privilegiada (
user.delete,horario.publish, etc.) - Soft-delete en usuarios/horarios/materias β nunca
DROP - Headers
X-Content-Type-Options,X-Frame-Options,Referrer-Policy - Password reset con token 1h + revocaciΓ³n de todas las sesiones al cambiar
- Sistema de diseΓ±o MapSchool v1: tokens CSS (
navy #172846, Lexend / DM Sans / DM Mono, grid 4px, WCAG AA) - 27 componentes reusables como macros Jinja: ButtonΓ6 Β· Input Β· Switch Β· StatusBadge Β· RoleTag Β· Avatar Β· Tabs Β· AlertΓ4 Β· Toast (auto-dismiss) Β· DialogΓ2 Β· Dropdown Β· Tooltip Β· Breadcrumbs Β· Pagination Β· Cards Β· StatCard Β· DataTable Β· EmptyState Β· ScheduleGrid
- PΓ‘gina
/components(sΓ³lo enDEBUG=True) con los 21 componentes en vivo usando datos reales del seed - Notificaciones en tiempo real vΓa SSE β bell badge actualiza sin recargar
- Mapa SVG interactivo con click en edificios y "ΒΏCΓ³mo llegar?" textual
- Accesibilidad: skip-link,
aria-*en todos los botones de iconos,Esccierra paneles, focus visible 3px navy
- 21 pantallas: Login Β· Register Β· Dashboard (5 tabs) Β· Horario Β· Salones Β· SalonDetail Β· Mapa (InteractiveViewer) Β· Calificaciones Β· Asistencia Β· TrΓ‘mites Β· Perfil Β· Profesor Β· Admin (Drawer + KPIs) Β· AdminUsuarios Β· AdminHorarios Β· AdminSalones Β· Notificaciones
- GoRouter con auth guard Β· Provider para estado Β· ApiService con interceptor 401βrefreshβretryβlogout
- Notificaciones locales vΓa
flutter_local_notificationscon polling 30s - Espejo del design system:
MapColors/MapTextcon los mismos hex quetokens.css - APK release ~19 MB con desugaring + minSdk 21
| Tipo | Archivos | Cobertura |
|---|---|---|
| Pytest (backend) | tests/test_health.py Β· test_auth.py Β· test_salones.py Β· test_horarios.py |
health Β· login + roles + refresh Β· salones Β· conflicto MiΓ© 11:00 + dashboard |
| Dart unit | test/models/*_test.dart Γ 4 |
AppUser Β· Bloque Β· Salon Β· Horario.fromResponse |
| Flutter widget | test/widgets/*_test.dart Γ 4 |
AppAvatar Β· StatusBadge Β· StatCard Β· ScheduleGrid (con tap callback) |
| Flutter integration | integration_test/login_flow_test.dart |
Login β Dashboard β Conflicto visible (E2E) |
# Correr toda la suite
source .venv/bin/activate && pytest -q # Backend (15 tests)
cd flutter_app && flutter test test/ # Dart (43 tests)
flutter test integration_test/login_flow_test.dart \ # E2E (requiere backend up)
--dart-define=API_BASE=http://10.0.2.2:5001Las que no se rompen, sin excepciΓ³n:
- Cero datos hardcodeados. Todo viene de la BD vΓa API.
- Cero colores hardcodeados. Web usa
var(--token), Flutter usaMapColors.*. - Copy en espaΓ±ol, segunda persona, acentos correctos.
- WCAG AA en todos los pares texto/fondo.
- Cada vista tiene su empty state.
- Cada formulario tiene validaciΓ³n inline.
- Soft-delete para entidades crΓticas. Nunca
DROP. - Audit log para cada operaciΓ³n destructiva o privilegiada.
# Health check
curl http://localhost:5001/health
# Login (devuelve JWT)
TOKEN=$(curl -s -X POST http://localhost:5001/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]","password":"Estudiante1!"}' \
| jq -r .access_token)
# Horario con conflicto detectado automΓ‘ticamente
curl -H "Authorization: Bearer $TOKEN" \
http://localhost:5001/api/v1/horarios/1 | jq '.bloques[] | select(.conflicto)'
# 44 salones con disponibilidad ahora calculada
curl http://localhost:5001/api/v1/salones | jq '.data[0]'
# Dashboard admin con KPIs
ADMIN=$(curl -s -X POST http://localhost:5001/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]","password":"Admin1234!"}' | jq -r .access_token)
curl -H "Authorization: Bearer $ADMIN" \
http://localhost:5001/api/v1/stats/dashboard | jq
# Export CSV de usuarios (descarga binaria)
curl -H "Authorization: Bearer $ADMIN" \
http://localhost:5001/api/v1/stats/export/usuarios.csv -o usuarios.csvmatute-guide/
βββ README.md β este archivo
βββ MATUTE_GUIDE_PRD.md β spec completa (requisitos, modelos, endpoints)
βββ seed.py β poblaciΓ³n inicial reproducible
βββ run.py β entry point Flask (:5001)
βββ config.py β Desarrollo / Pruebas / ProducciΓ³n
βββ requirements.txt
βββ .env.example β variables sin secretos
βββ app/
β βββ __init__.py β create_app() factory
β βββ extensions.py β db, migrate, jwt, cors, limiter
β βββ api/ β 13 blueprints REST
β βββ web/ β vistas Jinja
β βββ models/ β 19 modelos en 7 dominios
β βββ utils/ β decorators, audit, notify, conflicts
β βββ static/
β β βββ css/tokens.css β MapSchool v1 (cero hex hardcoded)
β β βββ css/style.css β componentes
β β βββ js/app.js β Toast, Dialog, SSE, popover
β βββ templates/
β βββ _base.html β layout + skip-link + aria-live
β βββ components/ β 27 macros + /components demo
β βββ public/ β landing, salones, mapa, oferta
β βββ auth/ β login, register, forgot, reset
β βββ student/, profesor/, admin/
β βββ errors/
βββ tests/ β pytest (15 tests)
βββ flutter_app/ β Android APK (Flutter 3.41)
β βββ lib/
β β βββ main.dart
β β βββ theme/ β MapColors + MapText (cero hex inline)
β β βββ services/ β ApiService, AuthService, Storage, Notifications
β β βββ models/, providers/, widgets/, screens/ (21 pantallas)
β βββ test/ β Dart unit + widget tests (43 tests)
β βββ integration_test/ β E2E test
β βββ android/ β keystore config + RELEASE.md
β βββ pubspec.yaml
βββ Untitled Diagram.drawio Β· mapas.drawio β diagramas originales
Cosas que todavΓa valen la pena agregar:
- Export PDF de reportes (CSV ya existe)
- Drag-and-drop real del plan de estudios admin (hoy son botones β β)
- MigraciΓ³n a PostgreSQL en producciΓ³n (modelos ya neutrales β sin SQL especΓfico)
- CI/CD GitHub Actions:
pytest+flutter test+ build APK en cada PR - Firma release del APK con keystore propio (ver
flutter_app/RELEASE.md) - Backups automΓ‘ticos del audit log
MATUTE_GUIDE_PRD.mdβ EspecificaciΓ³n completa: 19 modelos con tipos, 13 blueprints con todos los endpoints, 21 componentes con specs CSS, 14 pantallas web con comportamiento, 13 pantallas Flutter, DoD por faseflutter_app/RELEASE.mdβ CΓ³mo generar keystore release, firmar APK/AAB, subir a Play StoreUntitled Diagram.drawioymapas.drawioβ Diagramas originales del proyecto
MapSchool v1.0.0 β diseΓ±ado especΓficamente para Matute Guide:
- Color: navy
#172846como primario, paleta navy 100β950, semΓ‘nticos success/warning/danger/info - TipografΓa: Lexend (display) Β· DM Sans (body) Β· DM Mono (mono/badges)
- Grid: 4px baseline, escalas s-1 (4px) hasta s-20 (80px)
- Componentes: 27 piezas con variantes documentadas
- Schedule blocks color-coded por tipo: tronco comΓΊn (navy-800) Β· Γ‘rea profesional (navy-500) Β· laboratorio (success) Β· idiomas (navy-400) Β· conflicto (warning + borde danger pulsante)
- WCAG AA en todos los pares texto/fondo (auditado)
MIT β uso libre para la red Universidad de Guadalajara y derivados.
Hecho con foco en lo que la comunidad de CUValles realmente necesita.
