FASE 6 PARCIAL: Extras y Diferenciadores (base implementada)

Implementados módulos base de Fase 6:

1. WALL OF FAME (base)
   - Modelo de base de datos
   - Servicio CRUD
   - Controladores
   - Endpoints: GET /wall-of-fame/*

2. ACHIEVEMENTS/LOGROS (base)
   - Modelo de logros desbloqueables
   - Servicio de progreso
   - Controladores base
   - Endpoints: GET /achievements/*

3. QR CHECK-IN (completo)
   - Generación de códigos QR
   - Validación y procesamiento
   - Check-in/check-out
   - Endpoints: /checkin/*

4. BASE DE DATOS
   - Tablas: wall_of_fame, achievements, qr_codes, check_ins
   - Tablas preparadas: equipment, orders, notifications, activities

Estructura lista para:
- Equipment/Material rental
- Orders/Servicios del club
- Wearables integration
- Challenges/Retos

Nota: Algunos módulos avanzados requieren ajustes finales.
This commit is contained in:
2026-01-31 21:59:36 +00:00
parent 5e50dd766f
commit e135e7ad24
51 changed files with 11323 additions and 4 deletions

View File

@@ -90,6 +90,17 @@ model User {
studentEnrollments StudentEnrollment[]
coachReviews CoachReview[]
// Servicios del Club (Fase 6.3)
orders Order[]
notifications Notification[]
userActivities UserActivity[]
// Check-ins (Fase 6.2)
checkIns CheckIn[]
// Alquileres de equipamiento (Fase 6.2)
equipmentRentals EquipmentRental[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@ -148,6 +159,9 @@ model Court {
tournamentMatches TournamentMatch[]
classBookings ClassBooking[]
// Servicios del Club (Fase 6.3)
orders Order[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@ -211,6 +225,16 @@ model Booking {
// Uso de bonos
bonusUsages BonusUsage[]
// Servicios del Club (Fase 6.3)
orders Order[]
userActivities UserActivity[]
// Alquileres de equipamiento asociados (Fase 6.2)
equipmentRentals EquipmentRental[]
// Check-ins asociados (Fase 6.2)
checkIns CheckIn[]
// Timestamps
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@ -1221,3 +1245,320 @@ model CoachReview {
@@index([rating])
@@map("coach_reviews")
}
// ============================================
// Modelos de Servicios del Club (Fase 6.3)
// ============================================
// Modelo de Item del Menú (productos del bar/cafetería)
model MenuItem {
id String @id @default(uuid())
// Información básica
name String
description String?
// Categoría: DRINK, SNACK, FOOD, OTHER
category String @default("OTHER")
// Precio en centavos
price Int
// Imagen
imageUrl String?
// Disponibilidad y estado
isAvailable Boolean @default(true)
isActive Boolean @default(true)
// Tiempo de preparación en minutos
preparationTime Int?
// Timestamps
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([category])
@@index([isAvailable])
@@index([isActive])
@@map("menu_items")
}
// Modelo de Pedido (órdenes a la cancha)
model Order {
id String @id @default(uuid())
// Usuario que realiza el pedido
user User @relation(fields: [userId], references: [id])
userId String
// Reserva asociada (vinculado a reserva activa)
booking Booking @relation(fields: [bookingId], references: [id])
bookingId String
// Cancha donde se entregará
court Court @relation(fields: [courtId], references: [id])
courtId String
// Items del pedido (JSON array de {itemId, quantity, notes, price})
items String
// Estado del pedido: PENDING, PREPARING, READY, DELIVERED, CANCELLED
status String @default("PENDING")
// Monto total en centavos
totalAmount Int
// Estado de pago: PENDING, PAID
paymentStatus String @default("PENDING")
// ID de referencia de pago (MercadoPago u otro)
paymentId String?
// Notas adicionales
notes String?
// Timestamps
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([userId])
@@index([bookingId])
@@index([courtId])
@@index([status])
@@index([paymentStatus])
@@index([createdAt])
@@map("orders")
}
// Modelo de Notificación (push/in-app)
model Notification {
id String @id @default(uuid())
// Usuario destinatario
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId String
// Tipo de notificación: ORDER_READY, BOOKING_REMINDER, TOURNAMENT_START, etc.
type String
// Contenido
title String
message String
// Datos adicionales (JSON)
data String? // Puede contener orderId, bookingId, etc.
// Estado de lectura
isRead Boolean @default(false)
// Timestamps
createdAt DateTime @default(now())
@@index([userId])
@@index([type])
@@index([isRead])
@@index([createdAt])
@@map("notifications")
}
// ============================================
// Modelos de Integración con Wearables (Fase 6.3)
// ============================================
// Modelo de Actividad de Usuario (registro de actividad física)
model UserActivity {
id String @id @default(uuid())
// Usuario
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId String
// Fuente de datos: APPLE_HEALTH, GOOGLE_FIT, MANUAL
source String
// Tipo de actividad: PADEL_GAME, WORKOUT
activityType String @default("PADEL_GAME")
// Tiempos
startTime DateTime
endTime DateTime
duration Int // Duración en minutos
// Métricas de salud
caloriesBurned Int
heartRateAvg Int?
heartRateMax Int?
steps Int?
distance Float? // km
// Metadatos adicionales (JSON)
metadata String?
// Reserva asociada (opcional)
booking Booking? @relation(fields: [bookingId], references: [id], onDelete: SetNull)
bookingId String?
// Timestamps
createdAt DateTime @default(now())
@@index([userId])
@@index([source])
@@index([activityType])
@@index([startTime])
@@index([bookingId])
@@map("user_activities")
}
// ============================================
// Modelos de Check-in Digital QR (Fase 6.2)
// ============================================
// Modelo de Código QR
model QRCode {
id String @id @default(uuid())
code String @unique
type String // BOOKING_CHECKIN, EVENT_ACCESS, etc.
referenceId String // ID de la entidad (booking, etc.)
expiresAt DateTime
usedAt DateTime?
usedBy String? // userId que usó el QR
isActive Boolean @default(true)
createdAt DateTime @default(now())
// Relaciones
checkIns CheckIn[]
@@index([code])
@@index([referenceId])
@@index([type])
@@index([isActive])
@@map("qr_codes")
}
// Modelo de CheckIn (registro de asistencia)
model CheckIn {
id String @id @default(uuid())
bookingId String
userId String
qrCodeId String?
checkInTime DateTime
checkOutTime DateTime?
method String // QR, MANUAL
verifiedBy String? // admin que verificó
notes String?
// Relaciones
qrCode QRCode? @relation(fields: [qrCodeId], references: [id], onDelete: SetNull)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
booking Booking @relation(fields: [bookingId], references: [id], onDelete: Cascade)
@@index([bookingId])
@@index([userId])
@@index([checkInTime])
@@index([method])
@@map("check_ins")
}
// ============================================
// Modelos de Gestión de Material (Fase 6.2)
// ============================================
// Modelo de Item de Equipamiento
model EquipmentItem {
id String @id @default(uuid())
name String
description String?
category String // RACKET, BALLS, ACCESSORIES, SHOES
brand String?
model String?
size String? // talla si aplica
condition String @default("NEW") // NEW, GOOD, FAIR, POOR
hourlyRate Int? // tarifa por hora (en centavos)
dailyRate Int? // tarifa por día (en centavos)
depositRequired Int @default(0) // depósito requerido (en centavos)
quantityTotal Int @default(1)
quantityAvailable Int @default(1)
imageUrl String?
isActive Boolean @default(true)
// Relaciones
rentals EquipmentRentalItem[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([category])
@@index([isActive])
@@index([quantityAvailable])
@@map("equipment_items")
}
// Modelo de Alquiler de Equipamiento
model EquipmentRental {
id String @id @default(uuid())
userId String
bookingId String? // vinculado a reserva opcional
startDate DateTime
endDate DateTime
totalCost Int // en centavos
depositAmount Int // en centavos
depositReturned Int @default(0) // depósito devuelto (en centavos)
status String @default("RESERVED") // RESERVED, PICKED_UP, RETURNED, LATE, DAMAGED
pickedUpAt DateTime?
returnedAt DateTime?
paymentId String?
notes String?
// Relaciones
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
booking Booking? @relation(fields: [bookingId], references: [id], onDelete: SetNull)
items EquipmentRentalItem[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([userId])
@@index([bookingId])
@@index([status])
@@index([startDate])
@@index([endDate])
@@map("equipment_rentals")
}
// Modelo intermedio para items de un alquiler
model EquipmentRentalItem {
id String @id @default(uuid())
rentalId String
itemId String
quantity Int @default(1)
hourlyRate Int? // tarifa aplicada al momento del alquiler
dailyRate Int? // tarifa aplicada al momento del alquiler
// Relaciones
rental EquipmentRental @relation(fields: [rentalId], references: [id], onDelete: Cascade)
item EquipmentItem @relation(fields: [itemId], references: [id], onDelete: Cascade)
@@index([rentalId])
@@index([itemId])
@@map("equipment_rental_items")
}