TimeSlot Engine

Sistema completo de gestión de reservas para canchas deportivas con motor de disponibilidad en tiempo real, políticas de cancelación configurables y notificaciones WebSocket.

NestJSReactTypeScriptPostgreSQL
TimeSlot Engine

El Riesgo Real

Reservar una cancha a las 19:00 no debería fallar. Pero “no debería” no es un constraint — es un deseo. Si dos personas pulsan Confirmar en el mismo segundo con la misma cancha y la misma hora, una de las dos va a llegar al club y encontrarse la pista ocupada. Es el tipo de bug que no se ve en testing y se vuelve viral cuando se reproduce.

Las Decisiones Que Hicieron El Motor

Los solapamientos se rechazan a nivel de base de datos, no de aplicación. Un EXCLUDE USING gist sobre una columna tstzrange generada por trigger significa que dos transacciones concurrentes no pueden crear solapamientos aunque la aplicación esté mal escrita. Si falla, 23P01 se traduce a 409 Conflict. Probado con tres requests paralelos al mismo slot: una sola pasa.

Las políticas de cancelación son código, no configuración hardcodeada. Strategy pattern con tres implementaciones y fallback a la global. Cambiar “ahora el reembolso es 50%” no requiere deploy — es un POST /api/policies/global.

Luxon para zonas horarias, no strings. Cada recurso declara su TZ IANA. El slot generator convierte de esa TZ a UTC al calcular, y a la TZ del recurso al renderizar. El usuario en México ve la hora del club.

El slot es un producto de la base de datos, no del frontend. El backend calcula las franjas, resta las reservas como intervalos half-open [start, end), y devuelve los huecos. El frontend solo renderiza.

Lo Que Se Ve, Lo Que No Se Ve

La UI es discreta: canchas con foto y precio, slots de 60 minutos agrupados por turno, confirmación inmediata. El admin ve un panel separado protegido por rol.

Lo que no se ve:

  • Trigger BEFORE INSERT/UPDATE que mantiene la columna time_range sincronizada con startAt/endAt.
  • Transacciones Serializable con raw query tstzrange && time_range antes de insertar.
  • WebSocket gateway con rooms por usuario y admins, para notificaciones en tiempo real.
  • Refresh tokens hasheados (SHA-256) en tabla separada, revocables individualmente.
  • 13 tests unitarios del generador de slots y las tres estrategias de política.

El sistema no es perfecto — no hay pagos integrados ni notificaciones por email. Pero lo que hace, lo hace con la garantía de que la base de datos nunca va a ser inconsistente. En un sistema de reservas, eso es lo único que importa.

analyticsImpacto

EXCLUDE
Anti-overlap en DB
Socket.IO
Tiempo real

Highlights de la Interfaz

Listado de canchas

Listado de canchas

Exploración de canchas disponibles con fotos, horarios y precios configurables.

Detalle y reserva

Detalle y reserva

Vista de detalle con generación de slots en tiempo real y soporte de zonas horarias.

Mis reservas

Mis reservas

Historial de reservas del usuario con estado y opciones de cancelación.

Panel de administración

Panel de administración

Gestión completa de canchas, reservas y usuarios con permisos diferenciados.

Gestión de canchas

Gestión de canchas

CRUD completo con fotos, horarios y precios configurables por cancha.

Gestión de reservas

Gestión de reservas

Vista admin de todas las reservas con seguimiento de estado.

Login

Login

Autenticación JWT con tokens de acceso y refresco, hashing con Argon2.

Registro

Registro

Creación de cuenta con validación de datos y roles de usuario.

Siguiente

SettleUp

arrow_forward