✅ FASE 3 COMPLETADA: Torneos y Ligas
Implementados 3 módulos con agent swarm: 1. SISTEMA DE TORNEOS - Tipos: Eliminación, Round Robin, Suizo, Consolación - Categorías: Masculina, Femenina, Mixta - Inscripciones con validación de niveles - Gestión de pagos y estados 2. CUADROS Y PARTIDOS - Generación automática de cuadros - Algoritmos: Circle method (Round Robin), Swiss pairing - Avance automático de ganadores - Asignación de canchas y horarios - Registro y confirmación de resultados 3. LIGAS POR EQUIPOS - Creación de equipos con capitán - Calendario round-robin automático - Tabla de clasificación con desempates - Estadísticas por equipo Modelos DB: - Tournament, TournamentParticipant, TournamentMatch - League, LeagueTeam, LeagueTeamMember, LeagueMatch, LeagueStanding Nuevos endpoints: - /tournaments/* - Gestión de torneos - /tournaments/:id/draw/* - Cuadros - /tournaments/:id/matches/* - Partidos de torneo - /leagues/* - Ligas - /league-teams/* - Equipos - /league-schedule/* - Calendario - /league-standings/* - Clasificación - /league-matches/* - Partidos de liga Datos de prueba: - Torneo de Verano 2024 (Eliminatoria) - Liga de Invierno (Round Robin) - Liga de Club 2024
This commit is contained in:
@@ -64,9 +64,18 @@ model User {
|
||||
groupsCreated Group[] @relation("GroupsCreated")
|
||||
groupMembers GroupMember[] @relation("GroupMemberships")
|
||||
|
||||
// Ligas
|
||||
leaguesCreated League[] @relation("LeaguesCreated") // Ligas creadas por el usuario
|
||||
teamCaptain LeagueTeam[] @relation("TeamCaptain") // Equipos donde es capitán
|
||||
leagueTeamMembers LeagueTeamMember[] // Membresías de equipo en liga
|
||||
|
||||
// Reservas recurrentes
|
||||
recurringBookings RecurringBooking[]
|
||||
|
||||
// Torneos
|
||||
tournamentsCreated Tournament[] @relation("TournamentsCreated")
|
||||
tournamentParticipations TournamentParticipant[]
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@ -121,6 +130,8 @@ model Court {
|
||||
bookings Booking[]
|
||||
schedules CourtSchedule[]
|
||||
recurringBookings RecurringBooking[]
|
||||
leagueMatches LeagueMatch[]
|
||||
tournamentMatches TournamentMatch[]
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
@@ -381,3 +392,368 @@ model UserStats {
|
||||
@@index([points])
|
||||
@@map("user_stats")
|
||||
}
|
||||
|
||||
// Modelo de Torneo
|
||||
model Tournament {
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
description String?
|
||||
|
||||
// Tipo de torneo
|
||||
type String // ELIMINATION, ROUND_ROBIN, SWISS, CONSOLATION
|
||||
|
||||
// Categoría
|
||||
category String // MEN, WOMEN, MIXED
|
||||
|
||||
// Niveles permitidos (almacenados como JSON string)
|
||||
allowedLevels String
|
||||
|
||||
// Capacidad
|
||||
maxParticipants Int
|
||||
|
||||
// Fechas importantes
|
||||
registrationStartDate DateTime
|
||||
registrationEndDate DateTime
|
||||
startDate DateTime
|
||||
endDate DateTime
|
||||
|
||||
// Canchas asignadas (almacenadas como JSON string de IDs)
|
||||
courtIds String
|
||||
|
||||
// Precio de inscripción (en centavos)
|
||||
price Int @default(0)
|
||||
|
||||
// Estado del torneo
|
||||
status String @default("DRAFT") // DRAFT, OPEN, CLOSED, IN_PROGRESS, FINISHED, CANCELLED
|
||||
|
||||
// Creador (admin)
|
||||
createdBy User @relation("TournamentsCreated", fields: [createdById], references: [id])
|
||||
createdById String
|
||||
|
||||
// Relaciones
|
||||
participants TournamentParticipant[] @relation("TournamentParticipants")
|
||||
matches TournamentMatch[]
|
||||
|
||||
// Timestamps
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([status])
|
||||
@@index([createdById])
|
||||
@@index([startDate])
|
||||
@@index([registrationStartDate])
|
||||
@@map("tournaments")
|
||||
}
|
||||
|
||||
// Modelo de Participante de Torneo
|
||||
model TournamentParticipant {
|
||||
id String @id @default(uuid())
|
||||
|
||||
// Torneo
|
||||
tournament Tournament @relation("TournamentParticipants", fields: [tournamentId], references: [id], onDelete: Cascade)
|
||||
tournamentId String
|
||||
|
||||
// Usuario (jugador individual)
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
userId String
|
||||
|
||||
// Fecha de inscripción
|
||||
registrationDate DateTime @default(now())
|
||||
|
||||
// Estado del pago
|
||||
paymentStatus String @default("PENDING") // PENDING, PAID, REFUNDED
|
||||
|
||||
// Número de cabeza de serie (opcional)
|
||||
seed Int?
|
||||
|
||||
// Estado de la inscripción
|
||||
status String @default("REGISTERED") // REGISTERED, CONFIRMED, WITHDRAWN
|
||||
|
||||
// Timestamps
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// Relaciones con partidos (como jugador individual)
|
||||
team1Player1Matches TournamentMatch[] @relation("T1P1")
|
||||
team1Player2Matches TournamentMatch[] @relation("T1P2")
|
||||
team2Player1Matches TournamentMatch[] @relation("T2P1")
|
||||
team2Player2Matches TournamentMatch[] @relation("T2P2")
|
||||
|
||||
@@unique([tournamentId, userId])
|
||||
@@index([tournamentId])
|
||||
@@index([userId])
|
||||
@@index([paymentStatus])
|
||||
@@index([status])
|
||||
@@map("tournament_participants")
|
||||
}
|
||||
|
||||
// Modelo de Partido de Torneo
|
||||
model TournamentMatch {
|
||||
id String @id @default(uuid())
|
||||
|
||||
// Torneo
|
||||
tournament Tournament @relation(fields: [tournamentId], references: [id], onDelete: Cascade)
|
||||
tournamentId String
|
||||
|
||||
// Ronda (1=final, 2=semifinal, etc. o número de ronda en liga)
|
||||
round Int
|
||||
|
||||
// Número de partido en la ronda
|
||||
matchNumber Int
|
||||
|
||||
// Posición en el cuadro
|
||||
position Int
|
||||
|
||||
// Equipo 1 (pareja o individual)
|
||||
team1Player1 TournamentParticipant? @relation("T1P1", fields: [team1Player1Id], references: [id], onDelete: SetNull)
|
||||
team1Player1Id String?
|
||||
team1Player2 TournamentParticipant? @relation("T1P2", fields: [team1Player2Id], references: [id], onDelete: SetNull)
|
||||
team1Player2Id String?
|
||||
|
||||
// Equipo 2 (pareja o individual)
|
||||
team2Player1 TournamentParticipant? @relation("T2P1", fields: [team2Player1Id], references: [id], onDelete: SetNull)
|
||||
team2Player1Id String?
|
||||
team2Player2 TournamentParticipant? @relation("T2P2", fields: [team2Player2Id], references: [id], onDelete: SetNull)
|
||||
team2Player2Id String?
|
||||
|
||||
// Cancha asignada
|
||||
court Court? @relation(fields: [courtId], references: [id], onDelete: SetNull)
|
||||
courtId String?
|
||||
|
||||
// Fecha y hora programada
|
||||
scheduledDate DateTime?
|
||||
scheduledTime String?
|
||||
|
||||
// Estado del partido
|
||||
status String @default("PENDING") // PENDING, SCHEDULED, IN_PROGRESS, FINISHED, CANCELLED, BYE
|
||||
|
||||
// Resultado
|
||||
team1Score Int?
|
||||
team2Score Int?
|
||||
winner String? // TEAM1, TEAM2, DRAW
|
||||
|
||||
// Avance en cuadro
|
||||
nextMatch TournamentMatch? @relation("NextMatch", fields: [nextMatchId], references: [id], onDelete: SetNull)
|
||||
nextMatchId String?
|
||||
parentMatches TournamentMatch[] @relation("NextMatch")
|
||||
|
||||
// Confirmaciones del resultado (JSON array de userIds)
|
||||
confirmedBy String @default("[]")
|
||||
|
||||
// Metadatos adicionales (para sistemas suizo, round robin, etc)
|
||||
metadata String? // JSON string con datos adicionales
|
||||
|
||||
// Timestamps
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([tournamentId])
|
||||
@@index([round])
|
||||
@@index([status])
|
||||
@@index([courtId])
|
||||
@@index([nextMatchId])
|
||||
@@index([tournamentId, round])
|
||||
@@map("tournament_matches")
|
||||
}
|
||||
|
||||
|
||||
// ============================================
|
||||
// Modelos de Liga por Equipos (Fase 3.3)
|
||||
// ============================================
|
||||
|
||||
// Modelo de Liga
|
||||
model League {
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
description String?
|
||||
|
||||
// Tipo y formato
|
||||
type String @default("TEAM_LEAGUE") // TEAM_LEAGUE, INDIVIDUAL_LEAGUE
|
||||
format String @default("DOUBLE_ROUND_ROBIN") // SINGLE_ROUND_ROBIN, DOUBLE_ROUND_ROBIN, etc.
|
||||
|
||||
// Configuración de partidos por jornada
|
||||
matchesPerMatchday Int @default(2) // Número de partidos entre dos equipos por jornada
|
||||
|
||||
// Fechas
|
||||
startDate DateTime?
|
||||
endDate DateTime?
|
||||
|
||||
// Estado
|
||||
status String @default("DRAFT") // DRAFT, ACTIVE, FINISHED, CANCELLED
|
||||
|
||||
// Creador (admin)
|
||||
createdBy User @relation("LeaguesCreated", fields: [createdById], references: [id])
|
||||
createdById String
|
||||
|
||||
// Relaciones
|
||||
teams LeagueTeam[]
|
||||
matches LeagueMatch[]
|
||||
standings LeagueStanding[]
|
||||
|
||||
// Timestamps
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([status])
|
||||
@@index([createdById])
|
||||
@@index([startDate])
|
||||
@@map("leagues")
|
||||
}
|
||||
|
||||
// Modelo de Equipo en Liga
|
||||
model LeagueTeam {
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
description String?
|
||||
|
||||
// Liga
|
||||
league League @relation(fields: [leagueId], references: [id], onDelete: Cascade)
|
||||
leagueId String
|
||||
|
||||
// Capitán del equipo
|
||||
captain User @relation("TeamCaptain", fields: [captainId], references: [id])
|
||||
captainId String
|
||||
|
||||
// Relaciones
|
||||
members LeagueTeamMember[]
|
||||
|
||||
// Partidos como equipo 1 o 2
|
||||
matchesAsTeam1 LeagueMatch[] @relation("Team1Matches")
|
||||
matchesAsTeam2 LeagueMatch[] @relation("Team2Matches")
|
||||
|
||||
// Clasificación
|
||||
standing LeagueStanding?
|
||||
|
||||
// Timestamps
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@unique([leagueId, name])
|
||||
@@index([leagueId])
|
||||
@@index([captainId])
|
||||
@@map("league_teams")
|
||||
}
|
||||
|
||||
// Modelo de Miembro de Equipo
|
||||
model LeagueTeamMember {
|
||||
id String @id @default(uuid())
|
||||
|
||||
// Equipo
|
||||
team LeagueTeam @relation(fields: [teamId], references: [id], onDelete: Cascade)
|
||||
teamId String
|
||||
|
||||
// Usuario
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
userId String
|
||||
|
||||
// Estado
|
||||
isActive Boolean @default(true)
|
||||
|
||||
// Fecha de unión
|
||||
joinedAt DateTime @default(now())
|
||||
|
||||
// Timestamps
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@unique([teamId, userId])
|
||||
@@index([teamId])
|
||||
@@index([userId])
|
||||
@@map("league_team_members")
|
||||
}
|
||||
|
||||
// Modelo de Partido de Liga
|
||||
model LeagueMatch {
|
||||
id String @id @default(uuid())
|
||||
|
||||
// Liga
|
||||
league League @relation(fields: [leagueId], references: [id], onDelete: Cascade)
|
||||
leagueId String
|
||||
|
||||
// Jornada
|
||||
matchday Int // Número de jornada
|
||||
|
||||
// Equipos
|
||||
team1 LeagueTeam @relation("Team1Matches", fields: [team1Id], references: [id])
|
||||
team1Id String
|
||||
team2 LeagueTeam @relation("Team2Matches", fields: [team2Id], references: [id])
|
||||
team2Id String
|
||||
|
||||
// Cancha y horario (opcional)
|
||||
court Court? @relation(fields: [courtId], references: [id], onDelete: SetNull)
|
||||
courtId String?
|
||||
|
||||
scheduledDate DateTime? // Fecha programada
|
||||
scheduledTime String? // Hora programada (formato HH:mm)
|
||||
|
||||
// Estado
|
||||
status String @default("SCHEDULED") // SCHEDULED, CONFIRMED, IN_PROGRESS, COMPLETED, CANCELLED, POSTPONED, WALKOVER
|
||||
|
||||
// Resultado
|
||||
team1Score Int? // Sets ganados por equipo 1
|
||||
team2Score Int? // Sets ganados por equipo 2
|
||||
|
||||
// Detalle de sets (almacenado como JSON)
|
||||
// Ej: [{team1Games: 6, team2Games: 4}, {team1Games: 6, team2Games: 2}]
|
||||
setDetails String?
|
||||
|
||||
// Ganador
|
||||
winner String? // TEAM1, TEAM2, DRAW
|
||||
|
||||
// Fecha de finalización
|
||||
completedAt DateTime?
|
||||
|
||||
// Notas
|
||||
notes String?
|
||||
|
||||
// Timestamps
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([leagueId])
|
||||
@@index([matchday])
|
||||
@@index([team1Id])
|
||||
@@index([team2Id])
|
||||
@@index([status])
|
||||
@@index([scheduledDate])
|
||||
@@map("league_matches")
|
||||
}
|
||||
|
||||
// Modelo de Clasificación
|
||||
model LeagueStanding {
|
||||
id String @id @default(uuid())
|
||||
|
||||
// Liga
|
||||
league League @relation(fields: [leagueId], references: [id], onDelete: Cascade)
|
||||
leagueId String
|
||||
|
||||
// Equipo
|
||||
team LeagueTeam @relation(fields: [teamId], references: [id], onDelete: Cascade)
|
||||
teamId String @unique
|
||||
|
||||
// Partidos
|
||||
matchesPlayed Int @default(0)
|
||||
matchesWon Int @default(0)
|
||||
matchesLost Int @default(0)
|
||||
matchesDrawn Int @default(0)
|
||||
|
||||
// Sets
|
||||
setsFor Int @default(0)
|
||||
setsAgainst Int @default(0)
|
||||
|
||||
// Games (opcional)
|
||||
gamesFor Int @default(0)
|
||||
gamesAgainst Int @default(0)
|
||||
|
||||
// Puntos
|
||||
points Int @default(0)
|
||||
|
||||
// Posición actual
|
||||
position Int @default(0)
|
||||
|
||||
// Timestamps
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@unique([leagueId, teamId])
|
||||
@@index([leagueId])
|
||||
@@index([position])
|
||||
@@index([points])
|
||||
@@map("league_standings")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user