Ayman, inicio

Casos / Cada rol ve y hace solo lo suyo

Cada rol ve y hace solo lo suyo.

Plataforma completa para una cadena hotelera de aprendizaje: web pública con reservas, área de cliente y un ERP para el personal con tres roles.

rol
Proyecto de clase reescrito por mi cuenta
año
2025
stack
Java 21Spring BootPostgreSQLReactTypeScriptTestcontainersaxe
enlaces
Código ↗Demo ↗
Portada de Zellige Hotels con el titular y la foto en arco de un patio
// contexto

Contexto.

Empezó como un proyecto de clase del ciclo DAW. Después lo reescribí entero por mi cuenta para aprender lo que quería de verdad: Spring Boot en el backend, React en el frontend, autenticación real, restricciones en la base de datos y tests contra un PostgreSQL de verdad.

Es lo que más me enseñó sobre roles y permisos: qué roles hay y qué puede hacer cada uno.

Después le di un diseño propio con movimiento ligado al scroll, ordené el frontend y lo hice accesible. El objetivo es WCAG 2.2 AA y lo comprueba axe en la CI.

// problema

El problema.

Administración, gerencia, recepción y clientes usan la misma plataforma, pero cada uno solo debe ver y tocar lo suyo.

// decisiones

Lo que decidí, y por qué.

01

Cuatro perfiles, tres de personal

qué
Administración, gerencia y recepción en el ERP, y cliente en su área. Las reglas viven en el backend y el frontend solo enseña lo que cada rol puede usar.
por qué
Si la regla solo estuviera en la interfaz, bastaría con llamar a la API para saltársela.
02

Refresh tokens que rotan

qué
El token de acceso vive en memoria y el de refresco cambia en cada uso. Si uno se usa dos veces, se revoca toda la familia.
por qué
Mi primera versión emitía un token largo y ya está. Al leer OWASP con calma vi que la rotación con detección de reutilización era barata y mucho más segura.
03

Que la base de datos impida las reservas solapadas

qué
El servicio rechaza reservas que se pisan y, además, PostgreSQL tiene una restricción EXCLUDE USING gist como red de seguridad.
por qué
Mis dos primeras comprobaciones a mano fallaban: una con el día de salida y otra con las zonas horarias. La tercera la hace la base de datos y el test es una línea.
04

Accesibilidad comprobada en cada PR

qué
Un trabajo de la CI recorre 18 pantallas a 390 y 1440 px con axe y mide el desplazamiento horizontal. Falla si hay violaciones serias o críticas.
por qué
Una revisión a mano al final se olvida. Con la prueba en cada PR, una regresión se ve el mismo día.
05

Datos de demo que no caducan

qué
Un proceso opcional renueva las reservas, facturas y tareas de demo para que el panel no muestre 0 € ni 0 reservas. Los clientes de demo no tienen cuenta y sus reservas no envían correos. Está apagado por defecto y se activa con una variable de entorno.
por qué
Un panel vacío no enseña lo que hace el ERP, y las fechas escritas a mano caducan.
Panel de administración con indicadores, ingresos por mes y ocupación
Panel de administración con indicadores, ingresos por mes y ocupación
Los tres hoteles en tarjetas que entran con el scroll
Los tres hoteles en tarjetas que entran con el scroll
// resultado

Resultado.

  • 31 pruebas en el backend, incluidas pruebas con Testcontainers contra PostgreSQL.
  • axe en la CI: 18 pantallas a 390 y 1440 px, sin violaciones serias ni críticas.
  • Despliegue gratuito con demo pública.
// qué aprendí

Qué aprendí.

  • La rotación de refresh tokens no es opcional.
  • Una restricción en la base de datos vale más que tres comprobaciones a mano.
  • TanStack Query cambió mi forma de pensar el estado del frontend.

Qué haría distinto

  • Empezaría con componentes más grandes y los dividiría solo cuando algo se repita de verdad.