- Java
- Spring Boot
- PostgreSQL
- Docker
- Angular
SportReserve
SaaS multi-tenant para la gestión de reservas de espacios en clubes y asociaciones.
Demo en vivo
Puedes probar el sistema con las siguientes credenciales:
| Rol | Contraseña | |
|---|---|---|
| Administrador | [email protected] | Demo1234! |
Demo de Club de Tenis Valencia: https://sportreserve.andresgranerosala.com/club/club-tenis-valencia
Qué es y a quién va dirigido
SportReserve es un software para clubes y asociaciones cuyos socios reservan espacios de uso común (pistas de tenis, salas de reuniones de un coworking, aulas…) sin tener que recibir llamadas ni gestionar muchos mensajes en un grupo de WhatsApp. Es un SaaS multi-tenant: un mismo sistema sirve a muchos clubs a la vez, de forma modular y automatizada, y cada club se adapta a su negocio con personalización de colores y textos, su página pública, su horario, sus espacios y sus anuncios.
Cómo funciona
Login y sesión
Se entra con email, contraseña y club, porque un mismo email puede ser socio de varios clubs como cuentas independientes. Al acertar, el sistema emite un token firmado que acompaña a cada petición (y se renueva), para no tener que pedir la contraseña continuamente.
Permisos y seguridad
Hay tres roles jerárquicos que actúan dentro de su zona: PROVIDER (superadministrador: crea clubs y a otros administradores), TENANT (administrador de su club) y USER (socio que reserva). El sistema no confía en lo que dice la petición: valida la identidad, fuerza el club correcto y comprueba la propiedad de cada dato; así nadie puede actuar fuera de su club.
El viaje de una petición
Separar la entrada, la lógica y la salida hace el sistema seguro, claro y fácil de mantener.
Reservas y errores
Todo se valida en el servidor, no solo en la pantalla: horario del club, sin solapes, duración en múltiplos del intervalo del club, tope diario/semanal por socio y avisos de cierre. Cualquier error responde siempre con el mismo formato.
Frontend, con honestidad
El proyecto tiene dos aplicaciones web (la página pública del club y el panel de administración) construidas casi íntegras con IA generativa; mis conocimientos de frontend son básicos y los potencio con IA. El valor técnico sólido está en el backend.
Despliegue
Alojado en un servidor virtual propio con Dockploy: el backend y el frontend van en imágenes Docker separadas que Dockploy instala y actualiza en el servidor, cada una con un solo Dockerfile.
Crear un club desde JSON
Un club completo (datos, espacios, horario, anuncios y personalización) se crea pegando un JSON que se valida entero antes de escribir nada; si algo falla, no se crea nada y se puede reintentar.
Decisiones de diseño
El flujo request → bind → service → repository → response es deliberado y no casual. Mientras creaba SportReserve me di cuenta de que la parte más crítica de un SaaS multi-tenant no es la CRUD, sino quiénes pueden tocar qué y cuándo. Por eso separé la defensa en capas en lugar de confiarla a un único punto:
- JwtAuthFilter resuelve quién eres (userId, zona y rol) solo con el token.
- BindingAdvice obliga a que el
zoneId/userIdque llega del cliente se amarre al contexto autenticado antes de validar el formulario. Así, un socio no puede escribir en el club de otro aunque manipule el JSON de la petición. - El servicio vuelve a comprobar la propiedad con
findByIdAndZoneId(si no,AccessDenied) y aplica las reglas de negocio: horario, solapes, cupos y duración múltiplo deslotMinutes. - ExceptionManager centraliza todas las respuestas de error en
{ "error": "…" }con el código HTTP correcto.
Lo hice así porque he pensado en el producto, no solo en el código: si una demo en vivo usa los colores, los nombres y el horario reales de la empresa, el cliente se ve a sí mismo en la pantalla y entiende el valor en 10 segundos. Y porque no oculto que el proceso está asistido por IA: controlar el prompt, el formato y la verificación también es parte del trabajo de ingeniería.
Cómo se creó
- Agentes de IA (OpenCode): configuré
AGENTS.mdcomo arnés de convenciones y reglas del proyecto, y lo he usado también para depurar y arreglar errores a lo largo de todo el desarrollo. - De la web al club, en tres líneas: OpenCode busca en internet la información real de la empresa (personas, colores, logo, horario), la valida contra las reglas del sistema y genera el JSON del club; de ese mismo JSON se genera el CV, de forma determinista.
- Frontend asistido por IA: la parte Angular (widget y panel) está construida en su práctica totalidad con IA generativa.
- Rigor negocio: la demo usa colores, nombres y horarios reales de la empresa para que el cliente «se vea» en el producto.
- Transparencia: la demo se ha generado con asistencia de IA; el código y las decisiones son propios.
Stack
Backend
Java 21, Spring Boot, Spring Security, REST API, JWT, JPA/Hibernate
Base de datos
PostgreSQL 16, SQL
Frontend
Angular 22 (standalone, signals), TypeScript, HTML/CSS
Infraestructura
Docker, nginx, servidor virtual propio con Dockploy
Metodología
Multi-tenant, defensa en profundidad, arquitectura por capas, DTOs, Bean Validation
Herramientas
Git, Gradle, npm, OpenCode (IA)