✅ 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:
@@ -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")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user