Clases
Endpoints para obtener y gestionar clases del gimnasio.
Modelos de Datos
Section titled “Modelos de Datos”Los siguientes modelos de Prisma pertenecen al schema gym:
model Class { id String @id @default(cuid()) name String description String? type ClassType difficulty ClassDifficulty duration Int maxCapacity Int @map("max_capacity") price Float isActive Boolean @default(true) @map("is_active")
schedules ClassSchedule[] classSessions ClassSession[] trainers Trainer[] @relation("ClassTrainers") attendees UserProfile[] @relation("ClassAttendees")
createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at")
@@map("classes") @@schema("gym")}ClassSchedule
Section titled “ClassSchedule”Representa un patrón de horario recurrente para una clase (ej: “Lunes de 9:00 a 10:00”).
model ClassSchedule { id String @id @default(cuid()) classId String @map("class_id") dayOfWeek Int @map("day_of_week") startTime String @map("start_time") endTime String @map("end_time") isActive Boolean @default(true) @map("is_active")
class Class @relation(fields: [classId], references: [id], onDelete: Cascade) classSessions ClassSession[]
createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at")
@@map("class_schedules") @@schema("gym")}ClassSession
Section titled “ClassSession”Representa una sesión individual de una clase en una fecha específica. Las reservaciones se hacen sobre sesiones, no sobre clases directamente.
model ClassSession { id String @id @default(cuid()) classId String @map("class_id") classScheduleId String? @map("class_schedule_id") sessionDate DateTime @map("session_date") startTime String @map("start_time") endTime String @map("end_time") status ClassSessionStatus @default(SCHEDULED) maxCapacity Int? @map("max_capacity") currentBookings Int @default(0) @map("current_bookings") notes String?
class Class @relation(fields: [classId], references: [id], onDelete: Cascade) classSchedule ClassSchedule? @relation(fields: [classScheduleId], references: [id], onDelete: SetNull) reservations Reservation[]
createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at")
@@unique([classId, sessionDate, startTime]) @@map("class_sessions") @@schema("gym")}ClassType (Enum)
Section titled “ClassType (Enum)”enum ClassType { YOGA PILATES CROSSFIT ZUMBA SPINNING WEIGHTLIFTING CARDIO BOXING SWIMMING PERSONAL_TRAINING
@@schema("gym")}ClassDifficulty (Enum)
Section titled “ClassDifficulty (Enum)”enum ClassDifficulty { BEGINNER INTERMEDIATE ADVANCED ALL_LEVELS
@@schema("gym")}ClassSessionStatus (Enum)
Section titled “ClassSessionStatus (Enum)”enum ClassSessionStatus { SCHEDULED IN_PROGRESS COMPLETED CANCELLED
@@schema("gym")}Sistema de Estados (Lazy Evaluation + Persistencia)
Section titled “Sistema de Estados (Lazy Evaluation + Persistencia)”El sistema utiliza un enfoque híbrido para gestionar los estados de las sesiones:
-
Estados en tiempo real (Lazy Evaluation):
- Al consultar sesiones, el estado se calcula basado en la fecha/hora actual
- Esto garantiza que el estado siempre sea correcto sin necesidad de procesos en background
-
Estados manuales:
CANCELLED: Se persiste en BD y se respeta siempre
-
Sincronización opcional:
- El endpoint
POST /sessions/sync-completedpersiste estados COMPLETED - Útil para histórico y reportes
- El endpoint
Reglas de cálculo:
| Condición | Estado Retornado |
|---|---|
status === 'CANCELLED' | CANCELLED |
hora_actual < hora_inicio | SCHEDULED |
hora_inicio <= hora_actual < hora_fin | IN_PROGRESS |
hora_actual >= hora_fin | COMPLETED |
Endpoints
Section titled “Endpoints”Obtener Clases
Section titled “Obtener Clases”Obtener una lista de clases públicas con filtrado opcional.
- URL:
/api/v1/classes - Método:
GET - Autenticación Requerida: Sí
Descripción Interna
Section titled “Descripción Interna”Este endpoint obtiene clases del gimnasio con filtrado avanzado:
-
Filtros disponibles:
search: Búsqueda en nombre y descripción (case-insensitive)trainerId: Filtra clases que tengan al entrenador especificadohasAvailability: Solo clases con cupos disponibles
-
Incluye relaciones:
schedules: Horarios activos ordenados por día y horatrainers: Con userProfile y user asociados
-
Filtro de disponibilidad (si
hasAvailability: true):- Verifica que la clase tenga horarios activos
- Verifica que las reservas confirmadas no alcancen la capacidad máxima
-
Paginación con
pageylimit
Parámetros de Consulta de Solicitud (Opcionales)
Section titled “Parámetros de Consulta de Solicitud (Opcionales)”search: Buscar en nombre y descripcióntrainerId: Filtrar por ID de entrenadorhasAvailability: Solo clases con cupos disponiblespage: Número de página (por defecto: 1)limit: Resultados por página (por defecto: 10)
Respuesta
Section titled “Respuesta”{ "data": [ { "id": "...", "name": "Yoga", "description": "...", "maxCapacity": 20, "schedules": [...], "trainers": [...] } ], "pagination": { "page": 1, "limit": 10, "total": 5, "totalPages": 1 }}Ejemplo de Cliente Hono
Section titled “Ejemplo de Cliente Hono”import { hcWithType } from '@vitality-gym/api/client'
const client = hcWithType('http://localhost:3000')
const res = await client.api.v1.classes.$get({ query: { search: 'yoga', hasAvailability: 'true' }})Obtener Clase por ID
Section titled “Obtener Clase por ID”Obtener detalles de una clase específica incluyendo horarios y entrenadores.
- URL:
/api/v1/classes/:id - Método:
GET - Autenticación Requerida: Sí
Descripción Interna
Section titled “Descripción Interna”Este endpoint obtiene los detalles completos de una clase:
- Busca la clase por ID
- Incluye:
schedules: Horarios activos ordenados por día y horatrainers: Con userProfile y userclassSessions: Sesiones futuras no canceladas (máximo 20)_count.classSessions: Contador total de sesiones
- Lanza 404 si la clase no existe
Respuesta
Section titled “Respuesta”{ "message": "Clase obtenida exitosamente", "data": { "id": "...", "name": "Yoga", "description": "...", "type": "YOGA", "difficulty": "INTERMEDIATE", "maxCapacity": 20, "duration": 60, "price": 0, "schedules": [...], "trainers": [...], "classSessions": [ { "id": "...", "sessionDate": "2023-10-27", "startTime": "09:00", "endTime": "10:00", "status": "SCHEDULED", "_count": { "reservations": 5 } } ], "_count": { "classSessions": 15 } }}Ejemplo de Cliente Hono
Section titled “Ejemplo de Cliente Hono”import { hcWithType } from '@vitality-gym/api/client'
const client = hcWithType('http://localhost:3000')
const res = await client.api.v1.classes[':id'].$get({ param: { id: 'class_id_here' }})Obtener Horario de Hoy
Section titled “Obtener Horario de Hoy”Obtener el horario de clases para el día actual.
- URL:
/api/v1/classes/schedule/today - Método:
GET - Autenticación Requerida: Sí
Descripción Interna
Section titled “Descripción Interna”Este endpoint obtiene los horarios de clases para hoy:
- Obtiene el día actual usando
new Date().getDay()(0=Domingo, 6=Sábado) - Busca horarios activos donde
dayOfWeekcoincide con hoy - Incluye información de la clase:
- id, name, description, maxCapacity
- Ordena por
startTimeascendente
Respuesta
Section titled “Respuesta”{ "message": "Horarios de hoy obtenidos exitosamente", "data": [ { "id": "...", "dayOfWeek": 1, "startTime": "09:00", "endTime": "10:00", "class": { "id": "...", "name": "Yoga", "maxCapacity": 20 } } ]}Ejemplo de Cliente Hono
Section titled “Ejemplo de Cliente Hono”import { hcWithType } from '@vitality-gym/api/client'
const client = hcWithType('http://localhost:3000')
const res = await client.api.v1.classes.schedule.today.$get()Obtener Horarios
Section titled “Obtener Horarios”Obtener horarios de clases con filtros.
- URL:
/api/v1/classes/schedules - Método:
GET - Autenticación Requerida: Sí
Descripción Interna
Section titled “Descripción Interna”Este endpoint obtiene horarios de clases con filtrado:
- Filtros disponibles:
classId: Filtrar por clase específicatrainerId: Filtrar clases de un entrenador
- Solo horarios activos (
isActive: true) - Solo de clases activas
- Incluye información de la clase (id, name, description, maxCapacity)
- Ordenado por día de semana y hora de inicio
- Paginación con límite por defecto de 50
Parámetros de Consulta de Solicitud
Section titled “Parámetros de Consulta de Solicitud”classId: Filtrar por ID de clasetrainerId: Filtrar por ID de entrenadorpage: Número de página (por defecto: 1)limit: Resultados por página (por defecto: 50)
Ejemplo de Cliente Hono
Section titled “Ejemplo de Cliente Hono”import { hcWithType } from '@vitality-gym/api/client'
const client = hcWithType('http://localhost:3000')
const res = await client.api.v1.classes.schedules.$get({ query: { classId: 'class_id', trainerId: 'trainer_id' }})Obtener Capacidad de Sesión
Section titled “Obtener Capacidad de Sesión”Obtener la capacidad de una sesión específica.
- URL:
/api/v1/classes/:id/capacity - Método:
GET - Autenticación Requerida: Sí
Descripción Interna
Section titled “Descripción Interna”Este endpoint verifica la capacidad disponible de una sesión:
- Busca la sesión con su clase asociada
- Calcula capacidad:
maxCapacity: Capacidad de la sesión (o de la clase si no está definida)currentReservations: Reservas actuales (campocurrentBookings)availableSpots: Cupos disponiblesisAvailable: true si hay cupos
Parámetros de Consulta de Solicitud
Section titled “Parámetros de Consulta de Solicitud”sessionId: ID de la sesión para verificar capacidad
Respuesta
Section titled “Respuesta”{ "message": "Capacidad obtenida exitosamente", "data": { "maxCapacity": 20, "currentReservations": 15, "availableSpots": 5, "isAvailable": true }}Ejemplo de Cliente Hono
Section titled “Ejemplo de Cliente Hono”import { hcWithType } from '@vitality-gym/api/client'
const client = hcWithType('http://localhost:3000')
const res = await client.api.v1.classes[':id'].capacity.$get({ param: { id: 'class_id' }, query: { sessionId: 'session_id' }})Endpoints de Sesiones
Section titled “Endpoints de Sesiones”Las sesiones representan instancias específicas de clases en fechas concretas. Las reservaciones se hacen sobre sesiones.
Obtener Sesiones de Hoy
Section titled “Obtener Sesiones de Hoy”Obtener todas las sesiones programadas para el día actual.
- URL:
/api/v1/classes/sessions/today - Método:
GET - Autenticación Requerida: Sí
Descripción Interna
Section titled “Descripción Interna”Este endpoint obtiene las sesiones del día actual:
- Filtra sesiones donde
sessionDatees hoy - Excluye sesiones canceladas
- Incluye:
- Información de la clase (id, name, description, maxCapacity)
- Entrenadores de la clase
- Contador de reservaciones
- Ordena por
startTimeascendente
Respuesta
Section titled “Respuesta”{ "message": "Sesiones de hoy obtenidas exitosamente", "data": [ { "id": "...", "sessionDate": "2023-10-27", "startTime": "09:00", "endTime": "10:00", "status": "SCHEDULED", "currentBookings": 5, "class": { "id": "...", "name": "Yoga", "maxCapacity": 20, "trainers": [...] }, "_count": { "reservations": 5 } } ]}Ejemplo de Cliente Hono
Section titled “Ejemplo de Cliente Hono”import { hcWithType } from '@vitality-gym/api/client'
const client = hcWithType('http://localhost:3000')
const res = await client.api.v1.classes.sessions.today.$get()Obtener Sesiones
Section titled “Obtener Sesiones”Obtener sesiones con filtros.
- URL:
/api/v1/classes/sessions - Método:
GET - Autenticación Requerida: Sí
Descripción Interna
Section titled “Descripción Interna”Este endpoint obtiene sesiones con filtrado:
- Filtros disponibles:
classId: Filtrar por clase específicastatus: SCHEDULED, IN_PROGRESS, COMPLETED, CANCELLEDdateFrom/dateTo: Rango de fechas
- Incluye:
- Información completa de la clase con entrenadores
- Información del horario base (si existe)
- Contador de reservaciones
- Ordenado por fecha y hora de inicio
- Paginación estándar
Parámetros de Consulta de Solicitud
Section titled “Parámetros de Consulta de Solicitud”classId: Filtrar por ID de clasestatus: Filtrar por estado de sesióndateFrom: Fecha inicial del rangodateTo: Fecha final del rangopage: Número de página (por defecto: 1)limit: Resultados por página (por defecto: 20)
Respuesta
Section titled “Respuesta”{ "data": [ { "id": "...", "sessionDate": "2023-10-27", "startTime": "09:00", "endTime": "10:00", "status": "SCHEDULED", "currentBookings": 5, "maxCapacity": null, "class": {...}, "classSchedule": {...}, "_count": { "reservations": 5 } } ], "pagination": { "page": 1, "limit": 20, "total": 50, "totalPages": 3 }}Ejemplo de Cliente Hono
Section titled “Ejemplo de Cliente Hono”import { hcWithType } from '@vitality-gym/api/client'
const client = hcWithType('http://localhost:3000')
const res = await client.api.v1.classes.sessions.$get({ query: { classId: 'class_id', status: 'SCHEDULED', dateFrom: '2023-10-27', dateTo: '2023-11-03' }})Obtener Sesión por ID
Section titled “Obtener Sesión por ID”Obtener detalles de una sesión específica.
- URL:
/api/v1/classes/sessions/:sessionId - Método:
GET - Autenticación Requerida: Sí
Descripción Interna
Section titled “Descripción Interna”Este endpoint obtiene los detalles completos de una sesión:
- Busca la sesión por ID
- Incluye:
- Información completa de la clase con entrenadores
- Horario base (si existe)
- Lista de reservaciones con información del usuario
- Contador de reservaciones
- Lanza 404 si la sesión no existe
Respuesta
Section titled “Respuesta”{ "message": "Sesión obtenida exitosamente", "data": { "id": "...", "sessionDate": "2023-10-27", "startTime": "09:00", "endTime": "10:00", "status": "SCHEDULED", "currentBookings": 5, "maxCapacity": null, "notes": null, "class": { "id": "...", "name": "Yoga", "maxCapacity": 20, "duration": 60, "trainers": [...] }, "classSchedule": {...}, "reservations": [ { "id": "...", "status": "CONFIRMED", "userProfile": { "id": "...", "name": "John Doe", "avatar_url": "..." } } ], "_count": { "reservations": 5 } }}Ejemplo de Cliente Hono
Section titled “Ejemplo de Cliente Hono”import { hcWithType } from '@vitality-gym/api/client'
const client = hcWithType('http://localhost:3000')
const res = await client.api.v1.classes.sessions[':sessionId'].$get({ param: { sessionId: 'session_id' }})Crear Sesión (Admin/Staff)
Section titled “Crear Sesión (Admin/Staff)”Crear una sesión individual para una clase.
- URL:
/api/v1/classes/sessions - Método:
POST - Autenticación Requerida: Sí Admin Staff
Descripción Interna
Section titled “Descripción Interna”Este endpoint crea una nueva sesión:
- Verifica que la clase existe y está activa
- Verifica que no existe sesión duplicada (misma clase, fecha y hora)
- Crea la sesión con:
- classId, sessionDate, startTime, endTime
- classScheduleId (opcional, si se generó desde un horario)
- maxCapacity (opcional, override de la clase)
- status: SCHEDULED
Cuerpo de Solicitud
Section titled “Cuerpo de Solicitud”{ "classId": "class_id", "sessionDate": "2023-10-27", "startTime": "09:00", "endTime": "10:00", "classScheduleId": "schedule_id", "maxCapacity": 15, "notes": "Sesión especial de yoga al aire libre"}Errores Comunes
Section titled “Errores Comunes”404 Not Found: La clase no existe400 Bad Request: La clase no está activa409 Conflict: Ya existe una sesión para esa clase, fecha y hora
Ejemplo de Cliente Hono
Section titled “Ejemplo de Cliente Hono”import { hcWithType } from '@vitality-gym/api/client'
const client = hcWithType('http://localhost:3000')
const res = await client.api.v1.classes.sessions.$post({ json: { classId: 'class_id', sessionDate: '2023-10-27', startTime: '09:00', endTime: '10:00' }})Generar Sesiones desde Horarios (Admin/Staff)
Section titled “Generar Sesiones desde Horarios (Admin/Staff)”Generar automáticamente sesiones basadas en los horarios configurados de una clase.
- URL:
/api/v1/classes/sessions/generate - Método:
POST - Autenticación Requerida: Sí Admin Staff
Descripción Interna
Section titled “Descripción Interna”Este endpoint genera sesiones automáticamente:
- Obtiene la clase con sus horarios activos
- Valida:
- La clase debe existir y estar activa
- La clase debe tener al menos un horario configurado
- Itera por cada día en el rango de fechas
- Para cada día, busca horarios que coincidan con ese día de la semana
- Crea sesiones para cada coincidencia
- Ignora duplicados (si ya existe la sesión, la omite)
Cuerpo de Solicitud
Section titled “Cuerpo de Solicitud”{ "classId": "class_id", "dateFrom": "2023-10-27", "dateTo": "2023-11-27"}Respuesta
Section titled “Respuesta”{ "message": "Se crearon 12 sesiones (2 omitidas por duplicado)", "data": { "created": 12, "skipped": 2, "sessions": [...] }}Errores Comunes
Section titled “Errores Comunes”404 Not Found: La clase no existe400 Bad Request: La clase no está activa o no tiene horarios
Ejemplo de Cliente Hono
Section titled “Ejemplo de Cliente Hono”import { hcWithType } from '@vitality-gym/api/client'
const client = hcWithType('http://localhost:3000')
const res = await client.api.v1.classes.sessions.generate.$post({ json: { classId: 'class_id', dateFrom: '2023-10-27', dateTo: '2023-11-27' }})Generar Sesiones de Todas las Clases Activas (Admin/Staff)
Section titled “Generar Sesiones de Todas las Clases Activas (Admin/Staff)”Generar automáticamente sesiones para todas las clases activas basadas en sus horarios configurados.
- URL:
/api/v1/classes/sessions/generate-all - Método:
POST - Autenticación Requerida: Sí Admin Staff
Descripción Interna
Section titled “Descripción Interna”Este endpoint genera sesiones para todas las clases activas:
- Obtiene todas las clases activas con sus horarios activos
- Valida que existan clases activas
- Para cada clase:
- Itera por cada día en el rango de fechas
- Busca horarios que coincidan con ese día de la semana
- Crea sesiones para cada coincidencia
- Ignora duplicados (si ya existe la sesión, la omite)
- Retorna resumen con totales y desglose por clase
Cuerpo de Solicitud
Section titled “Cuerpo de Solicitud”{ "dateFrom": "2023-10-27", "dateTo": "2023-11-27"}Respuesta
Section titled “Respuesta”{ "message": "Se crearon 48 sesiones en 5 clases (8 omitidas por duplicado)", "data": { "totalCreated": 48, "totalSkipped": 8, "classesProcessed": 5, "resultsByClass": [ { "classId": "...", "className": "Yoga Matutino", "created": 12, "skipped": 2 }, { "classId": "...", "className": "CrossFit Avanzado", "created": 8, "skipped": 0 } ] }}Errores Comunes
Section titled “Errores Comunes”400 Bad Request: No hay clases activas disponibles
Ejemplo de Cliente Hono
Section titled “Ejemplo de Cliente Hono”import { hcWithType } from '@vitality-gym/api/client'
const client = hcWithType('http://localhost:3000')
const res = await client.api.v1.classes.sessions['generate-all'].$post({ json: { dateFrom: '2023-10-27', dateTo: '2023-11-27' }})Sincronizar Sesiones Completadas (Admin/Staff)
Section titled “Sincronizar Sesiones Completadas (Admin/Staff)”Sincroniza los estados de sesiones que deberían estar marcadas como COMPLETED en la base de datos. Útil para mantener el histórico actualizado.
- URL:
/api/v1/classes/sessions/sync-completed - Método:
POST - Autenticación Requerida: Sí Admin Staff
Descripción Interna
Section titled “Descripción Interna”Este endpoint sincroniza estados de sesiones pasadas:
-
Contexto: El sistema usa “Lazy Evaluation” para calcular estados en tiempo real
- Al consultar sesiones, el estado se calcula basado en fecha/hora actual
- Estados calculados: SCHEDULED, IN_PROGRESS, COMPLETED
- Estado manual respetado: CANCELLED
-
Función de este endpoint:
- Persiste en BD los estados COMPLETED para sesiones que ya terminaron
- Útil para mantener histórico correcto y reportes
-
Proceso:
- Busca sesiones con
sessionDate <= nowy status SCHEDULED o IN_PROGRESS - Para cada sesión, calcula el estado real basado en fecha/hora
- Si el estado calculado es COMPLETED, actualiza en BD
- Busca sesiones con
-
Caso de uso típico:
- Llamar desde un cron job diario/semanal
- Llamar manualmente antes de generar reportes
Cálculo de Estado
Section titled “Cálculo de Estado”El estado se calcula así:
- CANCELLED: Se respeta siempre (estado manual)
- SCHEDULED:
hora_actual < hora_iniciode la sesión - IN_PROGRESS:
hora_inicio <= hora_actual < hora_fin - COMPLETED:
hora_actual >= hora_fin
Respuesta
Section titled “Respuesta”{ "message": "Se sincronizaron 15 sesiones de 23 revisadas", "data": { "checkedCount": 23, "updatedCount": 15, "updatedIds": ["session_id_1", "session_id_2", "..."] }}Ejemplo de Cliente Hono
Section titled “Ejemplo de Cliente Hono”import { hcWithType } from '@vitality-gym/api/client'
const client = hcWithType('http://localhost:3000')
const res = await client.api.v1.classes.sessions['sync-completed'].$post()Ejemplo de Cron Job (GitHub Actions)
Section titled “Ejemplo de Cron Job (GitHub Actions)”name: Sync Completed Sessionson: schedule: - cron: '0 0 * * *' # Diariamente a medianoche
jobs: sync: runs-on: ubuntu-latest steps: - name: Sync completed sessions run: | curl -X POST "${{ secrets.API_URL }}/api/v1/classes/sessions/sync-completed" \ -H "Authorization: Bearer ${{ secrets.ADMIN_TOKEN }}"Actualizar Sesión (Admin/Staff)
Section titled “Actualizar Sesión (Admin/Staff)”Actualizar el estado o configuración de una sesión.
- URL:
/api/v1/classes/sessions/:sessionId - Método:
PATCH - Autenticación Requerida: Sí Admin Staff
Descripción Interna
Section titled “Descripción Interna”Este endpoint actualiza una sesión:
- Busca la sesión existente
- Valida transición de estado (si se actualiza status):
- Desde SCHEDULED: puede ir a IN_PROGRESS, CANCELLED
- Desde IN_PROGRESS: puede ir a COMPLETED, CANCELLED
- Desde COMPLETED: no puede cambiar
- Desde CANCELLED: no puede cambiar
- Actualiza status, maxCapacity, notes
Cuerpo de Solicitud
Section titled “Cuerpo de Solicitud”{ "status": "IN_PROGRESS", "maxCapacity": 25, "notes": "Clase en progreso"}Errores Comunes
Section titled “Errores Comunes”404 Not Found: La sesión no existe400 Bad Request: Transición de estado no válida
Ejemplo de Cliente Hono
Section titled “Ejemplo de Cliente Hono”import { hcWithType } from '@vitality-gym/api/client'
const client = hcWithType('http://localhost:3000')
const res = await client.api.v1.classes.sessions[':sessionId'].$patch({ param: { sessionId: 'session_id' }, json: { status: 'COMPLETED' }})Cancelar Sesión (Admin/Staff)
Section titled “Cancelar Sesión (Admin/Staff)”Cancelar una sesión y todas sus reservaciones asociadas.
- URL:
/api/v1/classes/sessions/:sessionId - Método:
DELETE - Autenticación Requerida: Sí Admin Staff
Descripción Interna
Section titled “Descripción Interna”Este endpoint cancela una sesión:
- Busca la sesión con sus reservaciones confirmadas
- Validaciones:
- No puede cancelar si ya está CANCELLED
- No puede cancelar si está COMPLETED
- En una transacción:
- Actualiza sesión a status CANCELLED
- Actualiza todas las reservaciones CONFIRMED a CANCELLED
- Retorna sesión cancelada con cantidad de reservaciones afectadas
TODO: Implementar notificación a usuarios con reservaciones canceladas
Respuesta
Section titled “Respuesta”{ "message": "Sesión cancelada exitosamente", "data": { "id": "...", "status": "CANCELLED", "cancelledReservations": 5 }}Errores Comunes
Section titled “Errores Comunes”404 Not Found: La sesión no existe400 Bad Request: La sesión ya está cancelada o completada
Ejemplo de Cliente Hono
Section titled “Ejemplo de Cliente Hono”import { hcWithType } from '@vitality-gym/api/client'
const client = hcWithType('http://localhost:3000')
const res = await client.api.v1.classes.sessions[':sessionId'].$delete({ param: { sessionId: 'session_id' }})Endpoints de Clases (Admin)
Section titled “Endpoints de Clases (Admin)”Crear una nueva clase.
- URL:
/api/v1/classes - Método:
POST - Autenticación Requerida: Sí Admin Staff
Descripción Interna
Section titled “Descripción Interna”Este endpoint crea una nueva clase:
-
Verifica conflictos de horarios:
- Para cada schedule proporcionado, verifica si hay solapamiento
- Solo verifica conflictos con clases del mismo tipo
- Permite múltiples clases de diferentes tipos en el mismo horario
-
Crea la clase con:
- Datos básicos: name, description, type, difficulty, maxCapacity, duration, price
- Relaciona entrenadores usando
trainerIds - Crea horarios (
schedules) con nested create
-
Retorna la clase creada con schedules ordenados y trainers incluidos
Validación de Conflictos de Horarios
Section titled “Validación de Conflictos de Horarios”- Caso conflicto: Nuevo horario se solapa con existente del mismo tipo
- Sin conflicto: Termina exactamente cuando empieza otro, o completamente separados
Cuerpo de Solicitud
Section titled “Cuerpo de Solicitud”{ "name": "New Class", "description": "Description...", "type": "YOGA", "difficulty": "BEGINNER", "maxCapacity": 20, "duration": 60, "price": 0, "trainerIds": ["trainer_id_1"], "schedules": [ { "dayOfWeek": 1, "startTime": "09:00", "endTime": "10:00" } ]}Errores Comunes
Section titled “Errores Comunes”409 Conflict: Ya existe otra clase del mismo tipo en ese horario
Ejemplo de Cliente Hono
Section titled “Ejemplo de Cliente Hono”import { hcWithType } from '@vitality-gym/api/client'
const client = hcWithType('http://localhost:3000')
const res = await client.api.v1.classes.$post({ json: { name: 'New Class', description: 'Description...', type: 'YOGA', difficulty: 'BEGINNER', maxCapacity: 20, duration: 60, trainerIds: ['trainer_id'], schedules: [{ dayOfWeek: 1, startTime: '09:00', endTime: '10:00' }] }})Actualizar Clase (Admin/Staff)
Section titled “Actualizar Clase (Admin/Staff)”Actualizar una clase existente.
- URL:
/api/v1/classes/:id - Método:
PUT - Autenticación Requerida: Sí Admin Staff
Descripción Interna
Section titled “Descripción Interna”Este endpoint actualiza una clase existente:
- Actualiza campos editables:
- name, description, maxCapacity, duration
- Actualiza entrenadores si se proporciona
trainerIds:- Primero desconecta todos (
set: []) - Luego conecta los nuevos
- Primero desconecta todos (
- Incluye schedules, trainers y contador de reservas en la respuesta
Nota: Los schedules se gestionan por separado, no se actualizan aquí.
Cuerpo de Solicitud (Parcial)
Section titled “Cuerpo de Solicitud (Parcial)”{ "name": "Updated Name", "maxCapacity": 25, "trainerIds": ["trainer_id_1", "trainer_id_2"]}Ejemplo de Cliente Hono
Section titled “Ejemplo de Cliente Hono”import { hcWithType } from '@vitality-gym/api/client'
const client = hcWithType('http://localhost:3000')
const res = await client.api.v1.classes[':id'].$put({ param: { id: 'class_id' }, json: { name: 'Updated Name' }})Eliminar Clase (Admin)
Section titled “Eliminar Clase (Admin)”Eliminar una clase.
- URL:
/api/v1/classes/:id - Método:
DELETE - Autenticación Requerida: Sí Admin
Descripción Interna
Section titled “Descripción Interna”Este endpoint elimina una clase:
- Elimina la clase por ID
- Eliminación en cascada: Elimina automáticamente:
- Horarios asociados (ClassSchedule)
- Relaciones con entrenadores
- Las reservas pueden quedar huérfanas (verificar configuración de FK)
Advertencia: Este endpoint realiza eliminación física. Considerar soft delete para producción.
Ejemplo de Cliente Hono
Section titled “Ejemplo de Cliente Hono”import { hcWithType } from '@vitality-gym/api/client'
const client = hcWithType('http://localhost:3000')
const res = await client.api.v1.classes[':id'].$delete({ param: { id: 'class_id' }})