feat(db): add tournament_admin role and ownership fields to schema

This commit is contained in:
2026-03-29 19:25:02 -07:00
parent 025b195800
commit 8f1f2bf196
4 changed files with 503 additions and 173 deletions
@@ -0,0 +1,232 @@
-- CreateTable
CREATE TABLE "players" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"name" TEXT NOT NULL,
"rating" INTEGER NOT NULL DEFAULT 0,
"currentElo" INTEGER NOT NULL DEFAULT 1000,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL
);
-- CreateTable
CREATE TABLE "users" (
"id" TEXT NOT NULL PRIMARY KEY,
"email" TEXT NOT NULL,
"emailVerified" BOOLEAN NOT NULL DEFAULT false,
"name" TEXT,
"image" TEXT,
"role" TEXT NOT NULL DEFAULT 'player',
"playerId" INTEGER,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "users_playerId_fkey" FOREIGN KEY ("playerId") REFERENCES "players" ("id") ON DELETE SET NULL ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "events" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"event_id" INTEGER,
"name" TEXT NOT NULL,
"description" TEXT,
"eventDate" DATETIME,
"eventType" TEXT NOT NULL DEFAULT 'tournament',
"format" TEXT NOT NULL DEFAULT 'round_robin',
"status" TEXT NOT NULL DEFAULT 'planned',
"maxParticipants" INTEGER,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL
);
-- CreateTable
CREATE TABLE "event_participants" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"eventId" INTEGER NOT NULL,
"playerId" INTEGER NOT NULL,
"teamId" INTEGER,
"seed" INTEGER,
"status" TEXT NOT NULL DEFAULT 'registered',
"registrationDate" DATETIME,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "event_participants_teamId_fkey" FOREIGN KEY ("teamId") REFERENCES "teams" ("id") ON DELETE SET NULL ON UPDATE CASCADE,
CONSTRAINT "event_participants_playerId_fkey" FOREIGN KEY ("playerId") REFERENCES "players" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "event_participants_eventId_fkey" FOREIGN KEY ("eventId") REFERENCES "events" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "teams" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"eventId" INTEGER NOT NULL,
"teamName" TEXT,
"player1Id" INTEGER NOT NULL,
"player2Id" INTEGER NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "teams_player2Id_fkey" FOREIGN KEY ("player2Id") REFERENCES "players" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "teams_player1Id_fkey" FOREIGN KEY ("player1Id") REFERENCES "players" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "teams_eventId_fkey" FOREIGN KEY ("eventId") REFERENCES "events" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "tournament_rounds" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"eventId" INTEGER NOT NULL,
"roundNumber" INTEGER NOT NULL,
"status" TEXT NOT NULL DEFAULT 'pending',
"scheduledStart" DATETIME,
"actualStart" DATETIME,
"completedAt" DATETIME,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "tournament_rounds_eventId_fkey" FOREIGN KEY ("eventId") REFERENCES "events" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "bracket_matchups" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"roundId" INTEGER NOT NULL,
"eventId" INTEGER NOT NULL,
"team1Id" INTEGER,
"team2Id" INTEGER,
"matchId" INTEGER,
"tableNumber" INTEGER,
"bracketPosition" INTEGER,
"winnerTeamId" INTEGER,
"loserTeamId" INTEGER,
"status" TEXT NOT NULL DEFAULT 'pending',
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "bracket_matchups_matchId_fkey" FOREIGN KEY ("matchId") REFERENCES "matches" ("id") ON DELETE SET NULL ON UPDATE CASCADE,
CONSTRAINT "bracket_matchups_team2Id_fkey" FOREIGN KEY ("team2Id") REFERENCES "teams" ("id") ON DELETE SET NULL ON UPDATE CASCADE,
CONSTRAINT "bracket_matchups_team1Id_fkey" FOREIGN KEY ("team1Id") REFERENCES "teams" ("id") ON DELETE SET NULL ON UPDATE CASCADE,
CONSTRAINT "bracket_matchups_eventId_fkey" FOREIGN KEY ("eventId") REFERENCES "events" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "bracket_matchups_roundId_fkey" FOREIGN KEY ("roundId") REFERENCES "tournament_rounds" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "matches" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"eventId" INTEGER,
"playedAt" DATETIME,
"team1P1Id" INTEGER NOT NULL,
"team1P2Id" INTEGER NOT NULL,
"team2P1Id" INTEGER NOT NULL,
"team2P2Id" INTEGER NOT NULL,
"team1Score" INTEGER NOT NULL,
"team2Score" INTEGER NOT NULL,
"status" TEXT NOT NULL DEFAULT 'completed',
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "matches_team2P2Id_fkey" FOREIGN KEY ("team2P2Id") REFERENCES "players" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "matches_team2P1Id_fkey" FOREIGN KEY ("team2P1Id") REFERENCES "players" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "matches_team1P2Id_fkey" FOREIGN KEY ("team1P2Id") REFERENCES "players" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "matches_team1P1Id_fkey" FOREIGN KEY ("team1P1Id") REFERENCES "players" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "matches_eventId_fkey" FOREIGN KEY ("eventId") REFERENCES "events" ("id") ON DELETE SET NULL ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "elo_snapshots" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"playerId" INTEGER NOT NULL,
"matchId" INTEGER NOT NULL,
"ratingBefore" INTEGER NOT NULL,
"ratingAfter" INTEGER NOT NULL,
"ratingChange" INTEGER NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "elo_snapshots_matchId_fkey" FOREIGN KEY ("matchId") REFERENCES "matches" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "elo_snapshots_playerId_fkey" FOREIGN KEY ("playerId") REFERENCES "players" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "partnership_games" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"player1Id" INTEGER NOT NULL,
"player2Id" INTEGER NOT NULL,
"matchId" INTEGER NOT NULL,
"teamNumber" INTEGER,
"wonMatch" INTEGER,
"player1EloChange" INTEGER,
"player2EloChange" INTEGER,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "partnership_games_matchId_fkey" FOREIGN KEY ("matchId") REFERENCES "matches" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "partnership_games_player2Id_fkey" FOREIGN KEY ("player2Id") REFERENCES "players" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "partnership_games_player1Id_fkey" FOREIGN KEY ("player1Id") REFERENCES "players" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "partnership_stats" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"player1Id" INTEGER NOT NULL,
"player2Id" INTEGER NOT NULL,
"gamesPlayed" INTEGER NOT NULL DEFAULT 0,
"wins" INTEGER NOT NULL DEFAULT 0,
"losses" INTEGER NOT NULL DEFAULT 0,
"totalEloChange" INTEGER NOT NULL DEFAULT 0,
"lastPlayed" DATETIME,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "partnership_stats_player2Id_fkey" FOREIGN KEY ("player2Id") REFERENCES "players" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "partnership_stats_player1Id_fkey" FOREIGN KEY ("player1Id") REFERENCES "players" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "session" (
"id" TEXT NOT NULL PRIMARY KEY,
"expiresAt" DATETIME NOT NULL,
"token" TEXT NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
"ipAddress" TEXT,
"userAgent" TEXT,
"userId" TEXT NOT NULL,
CONSTRAINT "session_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "account" (
"id" TEXT NOT NULL PRIMARY KEY,
"accountId" TEXT NOT NULL,
"providerId" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"accessToken" TEXT,
"refreshToken" TEXT,
"idToken" TEXT,
"accessTokenExpiresAt" DATETIME,
"refreshTokenExpiresAt" DATETIME,
"scope" TEXT,
"password" TEXT,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "account_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "verification" (
"id" TEXT NOT NULL PRIMARY KEY,
"identifier" TEXT NOT NULL,
"value" TEXT NOT NULL,
"expiresAt" DATETIME NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL
);
-- CreateIndex
CREATE UNIQUE INDEX "players_name_key" ON "players"("name");
-- CreateIndex
CREATE UNIQUE INDEX "users_email_key" ON "users"("email");
-- CreateIndex
CREATE UNIQUE INDEX "users_playerId_key" ON "users"("playerId");
-- CreateIndex
CREATE INDEX "session_userId_idx" ON "session"("userId");
-- CreateIndex
CREATE UNIQUE INDEX "session_token_key" ON "session"("token");
-- CreateIndex
CREATE INDEX "account_userId_idx" ON "account"("userId");
-- CreateIndex
CREATE INDEX "verification_identifier_idx" ON "verification"("identifier");
@@ -0,0 +1,61 @@
-- RedefineTables
PRAGMA defer_foreign_keys=ON;
PRAGMA foreign_keys=OFF;
CREATE TABLE "new_events" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"event_id" INTEGER,
"name" TEXT NOT NULL,
"description" TEXT,
"eventDate" DATETIME,
"eventType" TEXT NOT NULL DEFAULT 'tournament',
"format" TEXT NOT NULL DEFAULT 'round_robin',
"status" TEXT NOT NULL DEFAULT 'planned',
"maxParticipants" INTEGER,
"ownerId" TEXT,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "events_ownerId_fkey" FOREIGN KEY ("ownerId") REFERENCES "users" ("id") ON DELETE SET NULL ON UPDATE CASCADE
);
INSERT INTO "new_events" ("createdAt", "description", "eventDate", "eventType", "event_id", "format", "id", "maxParticipants", "name", "status", "updatedAt") SELECT "createdAt", "description", "eventDate", "eventType", "event_id", "format", "id", "maxParticipants", "name", "status", "updatedAt" FROM "events";
DROP TABLE "events";
ALTER TABLE "new_events" RENAME TO "events";
CREATE TABLE "new_matches" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"eventId" INTEGER,
"playedAt" DATETIME,
"team1P1Id" INTEGER NOT NULL,
"team1P2Id" INTEGER NOT NULL,
"team2P1Id" INTEGER NOT NULL,
"team2P2Id" INTEGER NOT NULL,
"team1Score" INTEGER NOT NULL,
"team2Score" INTEGER NOT NULL,
"status" TEXT NOT NULL DEFAULT 'completed',
"createdById" TEXT,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "matches_team2P2Id_fkey" FOREIGN KEY ("team2P2Id") REFERENCES "players" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "matches_team2P1Id_fkey" FOREIGN KEY ("team2P1Id") REFERENCES "players" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "matches_team1P2Id_fkey" FOREIGN KEY ("team1P2Id") REFERENCES "players" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "matches_team1P1Id_fkey" FOREIGN KEY ("team1P1Id") REFERENCES "players" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "matches_eventId_fkey" FOREIGN KEY ("eventId") REFERENCES "events" ("id") ON DELETE SET NULL ON UPDATE CASCADE,
CONSTRAINT "matches_createdById_fkey" FOREIGN KEY ("createdById") REFERENCES "users" ("id") ON DELETE SET NULL ON UPDATE CASCADE
);
INSERT INTO "new_matches" ("createdAt", "eventId", "id", "playedAt", "status", "team1P1Id", "team1P2Id", "team1Score", "team2P1Id", "team2P2Id", "team2Score", "updatedAt") SELECT "createdAt", "eventId", "id", "playedAt", "status", "team1P1Id", "team1P2Id", "team1Score", "team2P1Id", "team2P2Id", "team2Score", "updatedAt" FROM "matches";
DROP TABLE "matches";
ALTER TABLE "new_matches" RENAME TO "matches";
CREATE TABLE "new_players" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"name" TEXT NOT NULL,
"rating" INTEGER NOT NULL DEFAULT 0,
"currentElo" INTEGER NOT NULL DEFAULT 1000,
"gamesPlayed" INTEGER NOT NULL DEFAULT 0,
"wins" INTEGER NOT NULL DEFAULT 0,
"losses" INTEGER NOT NULL DEFAULT 0,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL
);
INSERT INTO "new_players" ("createdAt", "currentElo", "id", "name", "rating", "updatedAt") SELECT "createdAt", "currentElo", "id", "name", "rating", "updatedAt" FROM "players";
DROP TABLE "players";
ALTER TABLE "new_players" RENAME TO "players";
PRAGMA foreign_keys=ON;
PRAGMA defer_foreign_keys=OFF;
+3
View File
@@ -0,0 +1,3 @@
# Please do not edit this file manually
# It should be added in your version-control system (e.g., Git)
provider = "sqlite"
+113 -79
View File
@@ -1,5 +1,3 @@
// EuchreCamp Database Schema
// Generated from existing Ruby/ROM implementation
generator client {
provider = "prisma-client-js"
@@ -10,58 +8,61 @@ datasource db {
url = env("DATABASE_URL")
}
// Player Model - Tracks individual player information
model Player {
id Int @id @default(autoincrement())
name String @unique
rating Int @default(0)
currentElo Int @default(1000)
name String
rating Int @default(0) // Historical rating (used for rankings)
currentElo Int @default(1000) // Current Elo rating
gamesPlayed Int @default(0) // Total games played
wins Int @default(0) // Total wins
losses Int @default(0) // Total losses
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relationships
users User[]
eventParticipants EventParticipant[]
teamsAsPlayer1 Team[] @relation("TeamPlayer1")
teamsAsPlayer2 Team[] @relation("TeamPlayer2")
matchesAsP1 Match[] @relation("MatchPlayer1")
matchesAsP2 Match[] @relation("MatchPlayer2")
matchesAsP3 Match[] @relation("MatchPlayer3")
matchesAsP4 Match[] @relation("MatchPlayer4")
eloSnapshots EloSnapshot[]
partnershipGames PartnershipGame[] @relation("PartnershipPlayer1")
eventParticipants EventParticipant[]
matchesAsP4 Match[] @relation("MatchPlayer4")
matchesAsP3 Match[] @relation("MatchPlayer3")
matchesAsP2 Match[] @relation("MatchPlayer2")
matchesAsP1 Match[] @relation("MatchPlayer1")
partnershipGames2 PartnershipGame[] @relation("PartnershipPlayer2")
partnershipStats PartnershipStat[] @relation("StatPlayer1")
partnershipGames PartnershipGame[] @relation("PartnershipPlayer1")
partnershipStats2 PartnershipStat[] @relation("StatPlayer2")
partnershipStats PartnershipStat[] @relation("StatPlayer1")
teamsAsPlayer2 Team[] @relation("TeamPlayer2")
teamsAsPlayer1 Team[] @relation("TeamPlayer1")
user User?
@@map("players")
}
// User Model - Authentication and authorization
model User {
id Int @id @default(autoincrement())
playerId Int @unique
id String @id @default(cuid())
email String @unique
passwordDigest String
role String @default("player")
confirmed Boolean @default(false)
confirmationToken String?
confirmationSentAt DateTime?
resetPasswordToken String?
resetPasswordSentAt DateTime?
failedLoginAttempts Int @default(0)
lockedUntil DateTime?
lastLoginAt DateTime?
lastLoginIp String?
emailVerified Boolean @default(false)
name String?
image String?
role String @default("player") // player, tournament_admin, club_admin
// Session and account references for Better Auth
sessions Session[]
accounts Account[]
// Link to EuchreCamp player (optional)
playerId Int? @unique
player Player? @relation(fields: [playerId], references: [id])
// Tournaments owned by this user
ownedTournaments Event[] @relation("TournamentOwner")
// Matches created by this user
createdMatches Match[] @relation("MatchCreator")
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
player Player @relation(fields: [playerId], references: [id])
@@map("users")
}
// Event (Tournament) Model
model Event {
id Int @id @default(autoincrement())
event_id Int?
@@ -72,20 +73,19 @@ model Event {
format String @default("round_robin")
status String @default("planned")
maxParticipants Int?
ownerId String? // User ID of the tournament owner (for tournament_admin)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relationships
bracketMatchups BracketMatchup[]
participants EventParticipant[]
matches Match[]
teams Team[]
rounds TournamentRound[]
bracketMatchups BracketMatchup[]
matches Match[]
owner User? @relation("TournamentOwner", fields: [ownerId], references: [id])
@@map("events")
}
// EventParticipant Model
model EventParticipant {
id Int @id @default(autoincrement())
eventId Int
@@ -96,15 +96,13 @@ model EventParticipant {
registrationDate DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
event Event @relation(fields: [eventId], references: [id])
player Player @relation(fields: [playerId], references: [id])
team Team? @relation(fields: [teamId], references: [id])
player Player @relation(fields: [playerId], references: [id])
event Event @relation(fields: [eventId], references: [id])
@@map("event_participants")
}
// Team Model
model Team {
id Int @id @default(autoincrement())
eventId Int
@@ -113,19 +111,16 @@ model Team {
player2Id Int
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relationships
event Event @relation(fields: [eventId], references: [id])
player1 Player @relation("TeamPlayer1", fields: [player1Id], references: [id])
player2 Player @relation("TeamPlayer2", fields: [player2Id], references: [id])
eventParticipants EventParticipant[]
bracketMatchups1 BracketMatchup[] @relation("BracketTeam1")
bracketMatchups2 BracketMatchup[] @relation("BracketTeam2")
bracketMatchups1 BracketMatchup[] @relation("BracketTeam1")
eventParticipants EventParticipant[]
player2 Player @relation("TeamPlayer2", fields: [player2Id], references: [id])
player1 Player @relation("TeamPlayer1", fields: [player1Id], references: [id])
event Event @relation(fields: [eventId], references: [id])
@@map("teams")
}
// TournamentRound Model
model TournamentRound {
id Int @id @default(autoincrement())
eventId Int
@@ -136,14 +131,12 @@ model TournamentRound {
completedAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
event Event @relation(fields: [eventId], references: [id])
bracketMatchups BracketMatchup[]
event Event @relation(fields: [eventId], references: [id])
@@map("tournament_rounds")
}
// BracketMatchup Model
model BracketMatchup {
id Int @id @default(autoincrement())
roundId Int
@@ -158,17 +151,15 @@ model BracketMatchup {
status String @default("pending")
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
round TournamentRound @relation(fields: [roundId], references: [id])
event Event @relation(fields: [eventId], references: [id])
team1 Team? @relation("BracketTeam1", fields: [team1Id], references: [id])
team2 Team? @relation("BracketTeam2", fields: [team2Id], references: [id])
match Match? @relation(fields: [matchId], references: [id])
team2 Team? @relation("BracketTeam2", fields: [team2Id], references: [id])
team1 Team? @relation("BracketTeam1", fields: [team1Id], references: [id])
event Event @relation(fields: [eventId], references: [id])
round TournamentRound @relation(fields: [roundId], references: [id])
@@map("bracket_matchups")
}
// Match Model
model Match {
id Int @id @default(autoincrement())
eventId Int?
@@ -180,22 +171,22 @@ model Match {
team1Score Int
team2Score Int
status String @default("completed")
createdById String? // User ID of the match creator (for tournament_admin)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
event Event? @relation(fields: [eventId], references: [id])
team1P1 Player @relation("MatchPlayer1", fields: [team1P1Id], references: [id])
team1P2 Player @relation("MatchPlayer2", fields: [team1P2Id], references: [id])
team2P1 Player @relation("MatchPlayer3", fields: [team2P1Id], references: [id])
team2P2 Player @relation("MatchPlayer4", fields: [team2P2Id], references: [id])
eloSnapshots EloSnapshot[]
partnershipGames PartnershipGame[]
bracketMatchups BracketMatchup[]
eloSnapshots EloSnapshot[]
team2P2 Player @relation("MatchPlayer4", fields: [team2P2Id], references: [id])
team2P1 Player @relation("MatchPlayer3", fields: [team2P1Id], references: [id])
team1P2 Player @relation("MatchPlayer2", fields: [team1P2Id], references: [id])
team1P1 Player @relation("MatchPlayer1", fields: [team1P1Id], references: [id])
event Event? @relation(fields: [eventId], references: [id])
partnershipGames PartnershipGame[]
createdBy User? @relation("MatchCreator", fields: [createdById], references: [id])
@@map("matches")
}
// EloSnapshot Model
model EloSnapshot {
id Int @id @default(autoincrement())
playerId Int
@@ -204,14 +195,12 @@ model EloSnapshot {
ratingAfter Int
ratingChange Int
createdAt DateTime @default(now())
player Player @relation(fields: [playerId], references: [id])
match Match @relation(fields: [matchId], references: [id])
player Player @relation(fields: [playerId], references: [id])
@@map("elo_snapshots")
}
// PartnershipGame Model - Tracks each game played by a partnership
model PartnershipGame {
id Int @id @default(autoincrement())
player1Id Int
@@ -222,15 +211,13 @@ model PartnershipGame {
player1EloChange Int?
player2EloChange Int?
createdAt DateTime @default(now())
player1 Player @relation("PartnershipPlayer1", fields: [player1Id], references: [id])
player2 Player @relation("PartnershipPlayer2", fields: [player2Id], references: [id])
match Match @relation(fields: [matchId], references: [id])
player2 Player @relation("PartnershipPlayer2", fields: [player2Id], references: [id])
player1 Player @relation("PartnershipPlayer1", fields: [player1Id], references: [id])
@@map("partnership_games")
}
// PartnershipStat Model - Aggregated partnership statistics
model PartnershipStat {
id Int @id @default(autoincrement())
player1Id Int
@@ -242,9 +229,56 @@ model PartnershipStat {
lastPlayed DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
player1 Player @relation("StatPlayer1", fields: [player1Id], references: [id])
player2 Player @relation("StatPlayer2", fields: [player2Id], references: [id])
player1 Player @relation("StatPlayer1", fields: [player1Id], references: [id])
@@map("partnership_stats")
}
model Session {
id String @id
expiresAt DateTime
token String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
ipAddress String?
userAgent String?
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([token])
@@index([userId])
@@map("session")
}
model Account {
id String @id
accountId String
providerId String
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
accessToken String?
refreshToken String?
idToken String?
accessTokenExpiresAt DateTime?
refreshTokenExpiresAt DateTime?
scope String?
password String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([userId])
@@map("account")
}
model Verification {
id String @id
identifier String
value String
expiresAt DateTime
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([identifier])
@@map("verification")
}