Trabajo de Fin de Máster — Plataforma de gestión de eventos para un club deportivo de tiro.
El origen de este proyecto es completamente práctico: nace de una necesidad real detectada en el club de tiro deportivo del que el autor es socio. Hasta ahora, la gestión de las inscripciones a las competiciones —cuyo calendario publica la federación en un fichero CSV— se realizaba de forma totalmente manual. Una semana antes de cada competición, cada socio interesado debía enviar un WhatsApp al móvil personal del secretario del club indicando sus datos, la competición y el horario en el que deseaba participar. El secretario revisaba uno a uno esos mensajes, introducía los datos a mano, comprobaba si quedaban plazas disponibles y respondía individualmente a cada socio, ya fuera para confirmar la inscripción o para avisar de que la competición estaba completa. Tras plantear este problema a la junta directiva del club, surgió la idea de explorar cómo se podría modernizar y digitalizar el proceso, dando origen al presente prototipo, desarrollado como Trabajo de Fin de Máster.
⚠️ Aviso: la demo en producción se ejecuta en un servidor doméstico (homelab personal), por lo que no se puede garantizar una disponibilidad del 99,99%. Si detectas algún problema de acceso o funcionamiento, escribe al correo del alumno para solucionarlo lo antes posible.
- a. Descripción general del proyecto
- b. Stack tecnológico utilizado
- c. Instalación y ejecución
- d. Despliegue
- e. Observabilidad y métricas
- f. Estructura del proyecto
- g. Funcionalidades principales
- h. Usuario y contraseña de prueba
- i. Proyectos personales empleados en su construcción
- Enlaces de interés
SportsClubEventManager es una aplicación web para la gestión integral de eventos de un club deportivo: publicación de un calendario de eventos, autoinscripción y cancelación por parte de los socios, y un panel de administración completo (eventos, usuarios, inscripciones e importación masiva vía CSV), todo ello protegido con autenticación OAuth2 + JWT y control de acceso basado en roles.
El proyecto evolucionó en varias iteraciones (MILESTONES + ISSUES) hasta convertirse en una aplicación completa:
- MVP sin autenticación: modelo de dominio, persistencia y una API pública de solo lectura para consultar eventos.
- Autoinscripción: los eventos pasan a poder aceptar inscripciones y cancelaciones con control de aforo.
- Interfaz Blazor: calendario visual, listado, ficha de detalle y flujo de inscripción/cancelación para el usuario final.
- Seguridad y roles: login con Google OAuth2 o email/contraseña, JWT, y dos roles (
User/Administrator). - Panel de administración: gestión de usuarios, gestión de eventos (CRUD) y gestión de inscripciones, con registro de auditoría.
- Importación masiva: carga de eventos desde CSV con previsualización, detección de duplicados y normalización automática de títulos.
- Telemetría: métricas de negocio y de infraestructura expuestas en formato Prometheus y visualizadas en un dashboard de Grafana.
- Flujos de automatización: notificaciones a los socios (confirmación de inscripción, actualización o cancelación de eventos, recordatorios) mediante flujos de n8n.
- Despliegue automático: pipeline de CI/CD que construye, publica y despliega la aplicación de forma automática en cada cambio en
master, con smoke test y rollback automatizados.
El detalle completo del stack tecnológico (plataforma, backend, frontend, persistencia, autenticación, observabilidad, automatización, contenedores, CI/CD y testing) está documentado en docs/development/overview.md.
La guía completa, paso a paso, para instalar y ejecutar la aplicación (vía Docker Compose o dotnet run local), ejecutar los tests y resolver los problemas más comunes, está documentada en docs/development/installation.md.
La aplicación se despliega de forma continua a un homelab personal (Docker Compose + Portainer, accesible por Tailscale) mediante un pipeline de CI/CD que construye, valida, publica y despliega automáticamente en cada nueva versión, con smoke test y rollback automatizados. La guía completa, paso a paso — configuración inicial, cómo publicar una nueva versión y troubleshooting — está documentada en docs/deployment/homelab-deployment.md.
api y web exponen métricas en formato Prometheus (/metrics), que un Prometheus recolecta y una Grafana visualiza en un dashboard versionado como código (infrastructure/grafana/). En producción, ambos servicios se reutilizan del stack de monitorización ya existente del homelab en vez de desplegar una copia propia — la guía completa (arquitectura, procedimiento paso a paso y un incidente real ya resuelto) está documentada en docs/observability/observability.md.
El dashboard resultante es público y de solo lectura, sin necesidad de iniciar sesión:
La aplicación sigue una arquitectura en capas (Clean Architecture), con separación estricta entre dominio, aplicación, infraestructura y presentación (API + Blazor), CQRS con MediatR y los patrones de diseño derivados de ambos. El detalle completo — vistas de capas, grafo de dependencias entre proyectos, árbol de carpetas, modelo de dominio y flujos end-to-end, todo respaldado con diagramas Mermaid — está documentado en docs/architecture/architecture.md.
Para una vista más formal, orientada a quien evalúa el proyecto sin conocer el código: diagramas C4 (Contexto y Contenedores), el modelo Entidad-Relación verificado contra las migraciones, sequence diagrams de los flujos principales y el flujo de CI/CD, todos catalogados en docs/architecture/diagrams/.
Cada funcionalidad está documentada en detalle en docs/operations/, con un diagrama de flujo Mermaid y su explicación.
Para socios (rol User):
- Autenticación — inicio de sesión con Google OAuth2 o email/contraseña, y cierre de sesión.
- Consulta del calendario de eventos — vista de calendario o listado, y ficha de detalle, accesible sin autenticación.
- Inscripción y cancelación de inscripción a eventos — con validación automática de aforo y duplicados.
- Gestión del perfil propio — edición de datos personales y cambio de contraseña.
Para administradores (rol Administrator):
- Administración de usuarios — listado, edición, cambio de rol, activación/desactivación y borrado.
- Administración de eventos — CRUD completo de eventos.
- Administración de inscripciones — filtrado, inscripción manual, cancelación y exportación a CSV.
- Importación masiva de eventos por CSV — con previsualización, detección de duplicados y confirmación todo o nada.
Al ejecutar el entorno en modo Development (Docker con ASPNETCORE_ENVIRONMENT=Development, o tras aplicar las migraciones de datos de prueba en local — ver c. Instalación y ejecución) se dispone de los siguientes usuarios:
| Rol | Contraseña | |
|---|---|---|
| Administrador | admin@sportsclub.local |
La definida en la variable ADMIN_PASSWORD / secreto AdminUser:Password en el primer arranque |
| Socio | carmen.garcia@example.com |
Password1! |
| Socio | javier.martinez@example.com |
Password1! |
| Socio | ana.fernandez@example.com |
Password1! |
| Socio | miguel.sanchez@example.com |
Password1! |
| Socio | laura.rodriguez@example.com |
Password1! |
| Socio | carlos.jimenez@example.com |
Password1! |
El acceso mediante Google OAuth2 requiere registrar credenciales reales en Google Cloud Console; no existe un proveedor simulado para ese flujo. Para probarlo en local, crear un OAuth Client dedicado a desarrollo (nunca reutilizar el de producción) — ver el troubleshooting de "Login con Google no funciona" en la guía de instalación.
- Alta inicial: la migración
SeedAdministratorUser(a diferencia deAddDevelopmentSeedData/SeedDevelopmentUserPasswords, que solo se aplican enDevelopment) se ejecuta en cualquier entorno, incluida producción, y creaadmin@sportsclub.localleyendo su contraseña deAdminUser:Password(User Secrets en local, secreto de DockerADMIN_PASSWORDen Compose). Es idempotente (IF NOT EXISTS): solo inserta el usuario la primera vez, por lo que cambiarADMIN_PASSWORDen el.envdespués del primer arranque no modifica la contraseña de un administrador ya existente. - Cambiar la contraseña del administrador: al no existir ninguna funcionalidad de "restablecer contraseña de otro usuario" (ni siquiera para administradores — ver
administracion-usuarios.md, que solo permite editar datos, rol y estado, nunca la contraseña), la única vía es que el propio administrador inicie sesión y use el cambio de contraseña de autoservicio (PUT /api/users/{id}/password, verperfil-usuario.md). - Añadir o quitar administradores: cualquier administrador puede ascender a un socio existente al rol
Administrator(o degradarlo de vuelta aUser) desde Administración de usuarios (PUT /api/users/admin/{id}/role). El sistema impide quedarse sin ningún administrador: tanto este cambio de rol como el borrado de un usuario se rechazan si el afectado es el último administrador restante.
Este TFM se ha apoyado en varias herramientas y proyectos personales desarrollados previamente por el autor:
- 🏠 Homelab casero — infraestructura propia (Docker, Portainer) usada para el despliegue continuo de la aplicación.
- ⚙️ claude-sdlc-kit — kit de agentes de IA que automatiza el ciclo de vida completo de desarrollo de software (análisis, diseño, implementación, testing, documentación y revisión), utilizado durante todo el proyecto (ver carpeta
.claude/). - 🔨 BlitzSliceForge — plantilla de generación de soluciones .NET en Clean Architecture, empleada como punto de partida de este repositorio.
- 🌐 Aplicación en producción — instancia real desplegada en el homelab. El calendario de eventos es visible sin necesidad de iniciar sesión; para probar el resto de funcionalidades, inicia sesión con tu propia cuenta de Google (los usuarios de prueba de la sección h solo existen en local/desarrollo, no en esta instancia).
- 📊 Presentación del TFM — diapositivas del proyecto.
- 🎥 Vídeo explicativo del proyecto — presentación en vídeo del TFM.