Membresías
Endpoints para gestionar membresías de usuarios.
Modelos de Datos
Section titled “Modelos de Datos”Los siguientes modelos de Prisma pertenecen al schema users:
Membership
Section titled “Membership”model Membership { id String @id @default(cuid()) userProfileId String @unique @map("user_profile_id") type MembershipType status MembershipStatus @default(ACTIVE) startDate DateTime @map("start_date") endDate DateTime @map("end_date") price Float autoRenew Boolean @default(false) @map("auto_renew") suspendedAt DateTime? @map("suspended_at") cancelledAt DateTime? @map("cancelled_at") cancelReason String? @map("cancel_reason") notes String?
userProfile UserProfile @relation(fields: [userProfileId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at")
@@map("memberships") @@schema("users")}MembershipType (Enum)
Section titled “MembershipType (Enum)”enum MembershipType { BASIC PLUS PRO DAY_PASS
@@schema("users")}MembershipStatus (Enum)
Section titled “MembershipStatus (Enum)”enum MembershipStatus { ACTIVE INACTIVE SUSPENDED EXPIRED
@@schema("users")}Endpoints
Section titled “Endpoints”Obtener Membresías
Section titled “Obtener Membresías”Obtener todas las membresías. Admin Staff
- URL:
/api/v1/memberships - Método:
GET - Autenticación Requerida: Sí Admin Staff
Descripción Interna
Section titled “Descripción Interna”Este endpoint obtiene membresías con filtrado avanzado:
-
Filtros disponibles:
userProfileId: Filtrar por usuariotype: Tipo de membresía (MONTHLY, QUARTERLY, ANNUAL)status: Estado (ACTIVE, EXPIRED, SUSPENDED, INACTIVE)autoRenew: Filtrar por auto-renovaciónexpiresSoon: Solo membresías que expiran en 7 días
-
Lógica de expiresSoon:
- Calcula fecha 7 días adelante
- Filtra membresías ACTIVE con endDate entre hoy y 7 días
-
Incluye userProfile con nombre y email
-
Paginación y ordenamiento dinámico por sortBy/sortOrder
Parámetros de Consulta de Solicitud
Section titled “Parámetros de Consulta de Solicitud”status: Filtrar por statustype: Filtrar por tipouserProfileId: Filtrar por usuarioexpiresSoon: Solo membresías próximas a expirarpage: Número de páginalimit: Resultados por página
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.memberships.$get({ query: { status: 'ACTIVE' }})Obtener Mi Membresía Activa
Section titled “Obtener Mi Membresía Activa”Obtener la membresía activa del usuario actual.
- URL:
/api/v1/memberships/me/active - Método:
GET - Autenticación Requerida: Sí
Descripción Interna
Section titled “Descripción Interna”Este endpoint obtiene la membresía activa del usuario:
-
Busca membresía con:
- userProfileId del usuario autenticado
- status: ACTIVE
-
Ordena por endDate descendente (más reciente primero)
-
Lanza error si no tiene membresía activa (findFirstOrThrow)
Respuesta
Section titled “Respuesta”{ "data": { "id": "...", "type": "MONTHLY", "status": "ACTIVE", "startDate": "2023-10-01T00:00:00Z", "endDate": "2023-11-01T00:00:00Z", "price": 50, "autoRenew": 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.memberships.me.active.$get()Obtener Historial de Membresías
Section titled “Obtener Historial de Membresías”Obtener el historial de membresías para el usuario actual.
- URL:
/api/v1/memberships/me/history - Método:
GET - Autenticación Requerida: Sí
Descripción Interna
Section titled “Descripción Interna”Este endpoint obtiene el historial de membresías:
- Busca todas las membresías del usuario
- Ordena por createdAt descendente
- Retorna lista completa sin paginación
Crear Membresía (Admin/Staff)
Section titled “Crear Membresía (Admin/Staff)”Crear una nueva membresía para un usuario.
- URL:
/api/v1/memberships - Método:
POST - Autenticación Requerida: Sí Admin Staff
Descripción Interna
Section titled “Descripción Interna”Este endpoint crea una nueva membresía:
-
Verifica membresía activa existente:
- Busca si el usuario ya tiene membresía ACTIVE
- Si existe, lanza error 400
-
Valida fechas:
- endDate debe ser posterior a startDate
-
Crea la membresía con:
- status: ACTIVE por defecto
- Todos los campos proporcionados
-
Retorna membresía con userProfile incluido
Cuerpo de Solicitud
Section titled “Cuerpo de Solicitud”{ "userId": "user_id", "type": "MONTHLY", "startDate": "2023-10-01T00:00:00Z", "endDate": "2023-11-01T00:00:00Z", "price": 50}Errores Comunes
Section titled “Errores Comunes”400 Bad Request: El usuario ya tiene una membresía activa400 Bad Request: La fecha de fin debe ser posterior a la fecha de inicio
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.memberships.$post({ json: { userId: 'user_id', type: 'MONTHLY', startDate: '2023-10-01T00:00:00Z', endDate: '2023-11-01T00:00:00Z', price: 50 }})Renovar Membresía
Section titled “Renovar Membresía”Renovar una membresía existente.
- URL:
/api/v1/memberships/:id/renew - Método:
POST - Autenticación Requerida: Sí (Admin/Staff)
Descripción Interna
Section titled “Descripción Interna”Este endpoint renueva una membresía existente:
-
Obtiene membresía actual
-
Calcula nuevas fechas:
- newStartDate: Mayor entre endDate actual y hoy
- newEndDate: newStartDate + duration (en días)
-
Actualiza membresía con:
- Nuevas fechas
- Precio (proporcionado o existente)
- autoRenew (proporcionado o existente)
- status: ACTIVE
-
Retorna membresía actualizada
Cuerpo de Solicitud
Section titled “Cuerpo de Solicitud”{ "duration": 30, "price": 50, "autoRenew": true}Cancelar Membresía
Section titled “Cancelar Membresía”Cancelar una membresía.
- URL:
/api/v1/memberships/:id/cancel - Método:
POST - Autenticación Requerida: Sí
Descripción Interna
Section titled “Descripción Interna”Este endpoint cancela una membresía:
-
Verifica estado: Solo se pueden cancelar membresías ACTIVE
-
Registra cancelación:
- cancelledAt: Fecha actual
- autoRenew: false
- cancelReason: Motivo proporcionado
-
Si immediate es true:
- status: INACTIVE
- endDate: Fecha actual
-
Si immediate es false:
- Mantiene status ACTIVE
- Expira naturalmente en endDate
Cuerpo de Solicitud
Section titled “Cuerpo de Solicitud”{ "reason": "Moving away", "immediate": false}Errores Comunes
Section titled “Errores Comunes”400 Bad Request: Solo se pueden cancelar membresías activas
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.memberships[':id'].cancel.$post({ param: { id: 'membership_id' }, json: { reason: 'Moving away', immediate: false }})Suspender Membresía
Section titled “Suspender Membresía”Suspender temporalmente una membresía.
- URL:
/api/v1/memberships/:id/suspend - Método:
POST - Autenticación Requerida: Sí (Admin/Staff)
Descripción Interna
Section titled “Descripción Interna”Este endpoint suspende temporalmente una membresía:
- Verifica estado: Solo membresías ACTIVE pueden suspenderse
- Actualiza membresía:
- status: SUSPENDED
- suspendedAt: Fecha actual
- notes: Motivo de suspensión
Cuerpo de Solicitud
Section titled “Cuerpo de Solicitud”{ "reason": "Payment issue"}Reactivar Membresía
Section titled “Reactivar Membresía”Reactivar una membresía suspendida.
- URL:
/api/v1/memberships/:id/reactivate - Método:
POST - Autenticación Requerida: Sí (Admin/Staff)
Descripción Interna
Section titled “Descripción Interna”Este endpoint reactiva una membresía suspendida:
- Verifica estado: Solo membresías SUSPENDED pueden reactivarse
- Verifica expiración: Si endDate < hoy, no puede reactivarse (debe renovarse)
- Actualiza: status: ACTIVE
Errores Comunes
Section titled “Errores Comunes”400 Bad Request: Solo se pueden reactivar membresías suspendidas400 Bad Request: La membresía ha expirado, debe renovarla
Obtener Estadísticas de Membresías
Section titled “Obtener Estadísticas de Membresías”Obtener estadísticas de membresías (Admin).
- URL:
/api/v1/memberships/stats - Método:
GET - Autenticación Requerida: Sí Admin
Descripción Interna
Section titled “Descripción Interna”Este endpoint calcula estadísticas de membresías:
-
Estadísticas generales (transacción):
- Total de membresías
- Conteo por estado: ACTIVE, EXPIRED, SUSPENDED, INACTIVE
-
Por tipo: Agrupa y cuenta por tipo de membresía
-
Ingresos: Suma total de precios
-
Auto-renovación:
- Conteo de membresías con autoRenew activo
- Porcentaje sobre el total
Parámetros de Consulta de Solicitud
Section titled “Parámetros de Consulta de Solicitud”startDate: Filtrar estadísticas desde fechaendDate: Filtrar estadísticas hasta fecha
Respuesta
Section titled “Respuesta”{ "data": { "total": 500, "byStatus": { "active": 350, "expired": 100, "suspended": 30, "inactive": 20 }, "byType": [ { "type": "MONTHLY", "count": 200 }, { "type": "ANNUAL", "count": 150 } ], "revenue": { "total": 25000 }, "autoRenew": { "count": 280, "percentage": 56 } }}Obtener Membresías Próximas a Expirar
Section titled “Obtener Membresías Próximas a Expirar”Obtener membresías próximas a expirar (Admin/Staff).
- URL:
/api/v1/memberships/expiring - Método:
GET - Autenticación Requerida: Sí (Admin/Staff)
Descripción Interna
Section titled “Descripción Interna”Este endpoint obtiene membresías próximas a expirar:
- Calcula fecha límite: Hoy + días especificados (default: 7)
- Filtra membresías:
- status: ACTIVE
- endDate entre hoy y fecha límite
- Incluye userProfile con nombre y email
- Ordena por endDate ascendente (más urgentes primero)
Parámetros de Consulta de Solicitud
Section titled “Parámetros de Consulta de Solicitud”days: Días hasta expiración (por defecto: 7)