Volver a proyectosTFG

OposApp

Mi Trabajo de Fin de Grado (DAM): app móvil en Flutter que automatiza el seguimiento de convocatorias del BOPA y genera tests de práctica con IA local (Ollama), con privacidad total por diseño.

FlutterSpring BootIA Local (Ollama)PostgreSQLRGPD
Rol
Full-stack + infra
Año
2025–2026
Ciclo
DAM (TFG)
Licencia
MIT
OposApp

187 ms

Listado de 200 convocatorias

11,3 s

Test IA (10 preguntas)

312 ms

Login con BCrypt

OposApp es mi Trabajo de Fin de Grado (Desarrollo de Aplicaciones Multiplataforma, curso 2025-2026): una aplicación full-stack que resuelve dos problemas reales del opositor medio en Asturias — los 15-30 minutos diarios perdidos buscando convocatorias a mano y los 50-150 €/mes que cuesta preparar los exámenes en academias tradicionales.

Qué hace

  • Seguimiento automático del BOPA — un workflow de n8n rastrea el boletín oficial cada día a las 07:00 y guarda las convocatorias nuevas en PostgreSQL, con filtros por categoría, organismo, fecha y estado, y búsqueda full-text tolerante a erratas.
  • Tests con IA local — un modelo en local (Ollama, familia Qwen: qwen2.5-coder en el plan gratuito y un modelo mayor qwen3 en premium) genera tests personalizados en ~11 s mediante un flujo asíncrono (el backend devuelve un solicitudId y la app hace polling), sin enviar ningún dato a servicios externos.
  • Dashboard de progreso — KPIs en tiempo real (tests, aciertos, racha), gráfico de evolución e historial completo.

Arquitectura y stack

La app Flutter (Android 14+, Material Design 3, provider, go_router, Dio + Retrofit) se comunica por REST/JWT con una API Spring Boot 3 · Java 21 en arquitectura por capas estricta. Los datos viven en PostgreSQL 15, con Spring Security (JWT HS512 + BCrypt coste 12), rate limiting con Bucket4j (30 req/min por IP) y documentación OpenAPI/Swagger.

Todo corre autohospedado en un NAS Synology detrás de Caddy (HTTPS automático), con n8n para el scraping y Ollama para la IA. Cero dependencias de nube de pago.

Un único APK para dos entornos: al arrancar, la app comprueba si el NAS es alcanzable en la red local; si lo es usa la IP directa (más rápido) y, si no, cae automáticamente al dominio HTTPS externo. El mismo binario funciona dentro y fuera de casa sin recompilar.

Funcionamiento clave

  • Modo offline con caché local Hive y detección de red (connectivity_plus): las últimas convocatorias siguen accesibles sin conexión.
  • Generación asíncrona de tests: el backend devuelve un solicitudId al instante y la app hace polling del estado; corrección inmediata con explicación por pregunta y animación de resultado.
  • Dashboard de progreso con gráficos fl_chart (evolución, aciertos, racha) e historial.
  • Panel de administración (rol ROLE_ADMIN): usuarios, estado de servicios (PostgreSQL, Ollama), registro de auditoría y métricas de scraping.

Privacidad por diseño (RGPD)

  • IA 100% local: sin servicios de terceros, sin salida de datos de la infraestructura propia.
  • Consentimiento opt-in explícito con registro de timestamp, borrado total de cuenta (Art. 17) y exportación del perfil en JSON (Art. 20).

Seguridad

  • JWT HS512 stateless (7 días), validado en cada petición.
  • BCrypt (coste 12) — contraseñas nunca en texto plano.
  • Bucket4j contra abuso, Bean Validation en todos los DTOs y JPA/Hibernate (imposible inyección SQL).
  • Panel de administración restringido a red local del NAS (LAN / WireGuard) + rol ROLE_ADMIN.

Contexto académico

TFG del ciclo DAM (2025-2026). Tutores: Delio Tolivia Cadrecha (PIDAM) y Mario Álvarez Fernández (PDAW). Publicado como código abierto bajo licencia MIT.

OposApp is my final degree project (Multiplatform App Development, 2025-2026). It is a full-stack mobile app that solves two real problems for public-exam candidates in Asturias: the 15-30 minutes a day spent manually searching for job listings, and the 50-150 €/month cost of traditional exam-prep academies.

What it does

  • Automated BOPA tracking — an n8n workflow scrapes the official bulletin every day at 07:00 and stores new listings in PostgreSQL.
  • AI practice tests — a local model (Ollama, Qwen family: qwen2.5-coder on the free tier, a larger qwen3 model on premium) generates personalized tests in ~11 s, with no data ever leaving my own infrastructure.
  • Progress dashboard — real-time KPIs, evolution chart and full history.

Architecture & stack

Flutter (Android 14+, Material 3, provider, GoRouter, Dio + Retrofit) talking over REST/JWT to a Spring Boot 3 / Java 21 API, with PostgreSQL 15, Spring Security (JWT HS512 + BCrypt), Bucket4j rate limiting and OpenAPI docs. Everything runs self-hosted on a Synology NAS behind Caddy (automatic HTTPS), with n8n and Ollama for automation and AI.

One APK, two environments: on launch the app checks whether the NAS is reachable on the local network — if so it uses the direct IP, otherwise it falls back to the external HTTPS domain. The same binary works inside and outside the LAN with no rebuild.

Key features

  • Offline mode with local Hive cache and network detection.
  • Asynchronous test generation (immediate solicitudId + polling), instant grading with per-question explanations.
  • Progress dashboard with fl_chart graphs and full history.
  • Admin panel (ROLE_ADMIN): users, service health (PostgreSQL, Ollama), audit log and scraping metrics.

Privacy by design (GDPR)

  • 100% local AI — no third-party services, no data leaving the infrastructure.
  • Explicit opt-in consent with timestamp log; full account deletion (Art. 17) and JSON data export (Art. 20).