CREATE TABLE users ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, name VARCHAR(120) NOT NULL, email VARCHAR(160) NOT NULL UNIQUE, password_hash VARCHAR(255) NOT NULL, role ENUM('admin','delegate','public') NOT NULL DEFAULT 'public', active BOOLEAN NOT NULL DEFAULT TRUE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB; CREATE TABLE tournaments ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, name VARCHAR(160) NOT NULL, category ENUM('Masculino','Femenino','Mixto') NOT NULL, age_subcategory VARCHAR(80), format ENUM('Liga','Eliminacion directa','Doble eliminacion','Grupos + playoffs') NOT NULL, status ENUM('draft','active','finished') NOT NULL DEFAULT 'draft', starts_at DATE, ends_at DATE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, INDEX idx_tournaments_status (status), INDEX idx_tournaments_category (category) ) ENGINE=InnoDB; CREATE TABLE teams ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, tournament_id BIGINT UNSIGNED NOT NULL, name VARCHAR(160) NOT NULL, logo_path VARCHAR(255), coach_name VARCHAR(160), delegate_user_id BIGINT UNSIGNED, registration_token CHAR(32) NOT NULL UNIQUE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, CONSTRAINT fk_teams_tournament FOREIGN KEY (tournament_id) REFERENCES tournaments(id) ON DELETE CASCADE, CONSTRAINT fk_teams_delegate FOREIGN KEY (delegate_user_id) REFERENCES users(id) ON DELETE SET NULL, UNIQUE KEY uq_team_tournament_name (tournament_id, name), INDEX idx_teams_tournament (tournament_id) ) ENGINE=InnoDB; CREATE TABLE players ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, team_id BIGINT UNSIGNED NOT NULL, first_name VARCHAR(120) NOT NULL, last_name VARCHAR(120) NOT NULL, document_id VARCHAR(60) NOT NULL, birth_date DATE, jersey_number TINYINT UNSIGNED, position ENUM('Armador','Opuesto','Central','Punta','Libero','Universal'), photo_path VARCHAR(255), active BOOLEAN NOT NULL DEFAULT TRUE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, CONSTRAINT fk_players_team FOREIGN KEY (team_id) REFERENCES teams(id) ON DELETE CASCADE, UNIQUE KEY uq_player_document_team (team_id, document_id), UNIQUE KEY uq_player_number_team (team_id, jersey_number), INDEX idx_players_team (team_id) ) ENGINE=InnoDB; CREATE TABLE courts ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, name VARCHAR(120) NOT NULL, address VARCHAR(220), active BOOLEAN NOT NULL DEFAULT TRUE ) ENGINE=InnoDB; CREATE TABLE referees ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, name VARCHAR(140) NOT NULL, license VARCHAR(80), phone VARCHAR(60), active BOOLEAN NOT NULL DEFAULT TRUE ) ENGINE=InnoDB; CREATE TABLE matches ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, tournament_id BIGINT UNSIGNED NOT NULL, phase VARCHAR(80) NOT NULL DEFAULT 'regular', scheduled_at DATETIME, court_id BIGINT UNSIGNED, home_team_id BIGINT UNSIGNED NOT NULL, away_team_id BIGINT UNSIGNED NOT NULL, status ENUM('scheduled','live','finished','cancelled') NOT NULL DEFAULT 'scheduled', winner_team_id BIGINT UNSIGNED, home_sets TINYINT UNSIGNED NOT NULL DEFAULT 0, away_sets TINYINT UNSIGNED NOT NULL DEFAULT 0, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, CONSTRAINT fk_matches_tournament FOREIGN KEY (tournament_id) REFERENCES tournaments(id) ON DELETE CASCADE, CONSTRAINT fk_matches_court FOREIGN KEY (court_id) REFERENCES courts(id) ON DELETE SET NULL, CONSTRAINT fk_matches_home FOREIGN KEY (home_team_id) REFERENCES teams(id), CONSTRAINT fk_matches_away FOREIGN KEY (away_team_id) REFERENCES teams(id), CONSTRAINT fk_matches_winner FOREIGN KEY (winner_team_id) REFERENCES teams(id) ON DELETE SET NULL, CONSTRAINT chk_different_teams CHECK (home_team_id <> away_team_id), INDEX idx_matches_tournament_status (tournament_id, status), INDEX idx_matches_schedule (scheduled_at) ) ENGINE=InnoDB; CREATE TABLE match_referees ( match_id BIGINT UNSIGNED NOT NULL, referee_id BIGINT UNSIGNED NOT NULL, role VARCHAR(80) NOT NULL DEFAULT 'principal', PRIMARY KEY (match_id, referee_id), CONSTRAINT fk_match_referees_match FOREIGN KEY (match_id) REFERENCES matches(id) ON DELETE CASCADE, CONSTRAINT fk_match_referees_referee FOREIGN KEY (referee_id) REFERENCES referees(id) ON DELETE CASCADE ) ENGINE=InnoDB; CREATE TABLE match_sets ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, match_id BIGINT UNSIGNED NOT NULL, set_number TINYINT UNSIGNED NOT NULL, home_points TINYINT UNSIGNED NOT NULL DEFAULT 0, away_points TINYINT UNSIGNED NOT NULL DEFAULT 0, winner_team_id BIGINT UNSIGNED, side_state ENUM('normal','switched') NOT NULL DEFAULT 'normal', CONSTRAINT fk_sets_match FOREIGN KEY (match_id) REFERENCES matches(id) ON DELETE CASCADE, CONSTRAINT fk_sets_winner FOREIGN KEY (winner_team_id) REFERENCES teams(id) ON DELETE SET NULL, UNIQUE KEY uq_set_match_number (match_id, set_number) ) ENGINE=InnoDB; CREATE TABLE match_events ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, match_id BIGINT UNSIGNED NOT NULL, set_number TINYINT UNSIGNED NOT NULL, team_id BIGINT UNSIGNED, player_id BIGINT UNSIGNED, event_type ENUM('serve','point','error','ace','block','attack','rotation','substitution','timeout','libero','yellow_card','red_card','mvp','audit','signature') NOT NULL, points_home TINYINT UNSIGNED NOT NULL DEFAULT 0, points_away TINYINT UNSIGNED NOT NULL DEFAULT 0, notes VARCHAR(255), created_by BIGINT UNSIGNED, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, CONSTRAINT fk_events_match FOREIGN KEY (match_id) REFERENCES matches(id) ON DELETE CASCADE, CONSTRAINT fk_events_team FOREIGN KEY (team_id) REFERENCES teams(id) ON DELETE SET NULL, CONSTRAINT fk_events_player FOREIGN KEY (player_id) REFERENCES players(id) ON DELETE SET NULL, CONSTRAINT fk_events_user FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE SET NULL, INDEX idx_events_match_created (match_id, created_at), INDEX idx_events_player_type (player_id, event_type) ) ENGINE=InnoDB; CREATE TABLE rotations ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, match_id BIGINT UNSIGNED NOT NULL, team_id BIGINT UNSIGNED NOT NULL, set_number TINYINT UNSIGNED NOT NULL, position_number TINYINT UNSIGNED NOT NULL, player_id BIGINT UNSIGNED NOT NULL, is_libero BOOLEAN NOT NULL DEFAULT FALSE, CONSTRAINT fk_rotations_match FOREIGN KEY (match_id) REFERENCES matches(id) ON DELETE CASCADE, CONSTRAINT fk_rotations_team FOREIGN KEY (team_id) REFERENCES teams(id) ON DELETE CASCADE, CONSTRAINT fk_rotations_player FOREIGN KEY (player_id) REFERENCES players(id) ON DELETE CASCADE, UNIQUE KEY uq_rotation_slot (match_id, team_id, set_number, position_number) ) ENGINE=InnoDB; CREATE TABLE match_liberos ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, match_id BIGINT UNSIGNED NOT NULL, team_id BIGINT UNSIGNED NOT NULL, player_id BIGINT UNSIGNED NOT NULL, set_number TINYINT UNSIGNED NOT NULL, is_starting BOOLEAN NOT NULL DEFAULT FALSE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, CONSTRAINT fk_liberos_match FOREIGN KEY (match_id) REFERENCES matches(id) ON DELETE CASCADE, CONSTRAINT fk_liberos_team FOREIGN KEY (team_id) REFERENCES teams(id) ON DELETE CASCADE, CONSTRAINT fk_liberos_player FOREIGN KEY (player_id) REFERENCES players(id) ON DELETE CASCADE, UNIQUE KEY uq_match_team_set_libero (match_id, team_id, set_number, player_id) ) ENGINE=InnoDB; CREATE TABLE substitutions ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, match_id BIGINT UNSIGNED NOT NULL, team_id BIGINT UNSIGNED NOT NULL, set_number TINYINT UNSIGNED NOT NULL, player_out_id BIGINT UNSIGNED NOT NULL, player_in_id BIGINT UNSIGNED NOT NULL, reason VARCHAR(120), created_by BIGINT UNSIGNED, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, CONSTRAINT fk_substitutions_match FOREIGN KEY (match_id) REFERENCES matches(id) ON DELETE CASCADE, CONSTRAINT fk_substitutions_team FOREIGN KEY (team_id) REFERENCES teams(id) ON DELETE CASCADE, CONSTRAINT fk_substitutions_out FOREIGN KEY (player_out_id) REFERENCES players(id), CONSTRAINT fk_substitutions_in FOREIGN KEY (player_in_id) REFERENCES players(id), CONSTRAINT fk_substitutions_user FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE SET NULL, INDEX idx_substitutions_match_set (match_id, set_number, team_id) ) ENGINE=InnoDB; CREATE TABLE timeouts ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, match_id BIGINT UNSIGNED NOT NULL, team_id BIGINT UNSIGNED NOT NULL, set_number TINYINT UNSIGNED NOT NULL, points_home TINYINT UNSIGNED NOT NULL DEFAULT 0, points_away TINYINT UNSIGNED NOT NULL DEFAULT 0, requested_by VARCHAR(120), created_by BIGINT UNSIGNED, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, CONSTRAINT fk_timeouts_match FOREIGN KEY (match_id) REFERENCES matches(id) ON DELETE CASCADE, CONSTRAINT fk_timeouts_team FOREIGN KEY (team_id) REFERENCES teams(id) ON DELETE CASCADE, CONSTRAINT fk_timeouts_user FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE SET NULL, INDEX idx_timeouts_match_set (match_id, set_number, team_id) ) ENGINE=InnoDB; CREATE TABLE rally_history ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, match_id BIGINT UNSIGNED NOT NULL, set_number TINYINT UNSIGNED NOT NULL, rally_number INT UNSIGNED NOT NULL, serving_team_id BIGINT UNSIGNED, winning_team_id BIGINT UNSIGNED, result_type ENUM('point','error','ace','block','attack') NOT NULL DEFAULT 'point', points_home TINYINT UNSIGNED NOT NULL DEFAULT 0, points_away TINYINT UNSIGNED NOT NULL DEFAULT 0, notes VARCHAR(255), created_by BIGINT UNSIGNED, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, CONSTRAINT fk_rally_match FOREIGN KEY (match_id) REFERENCES matches(id) ON DELETE CASCADE, CONSTRAINT fk_rally_serving_team FOREIGN KEY (serving_team_id) REFERENCES teams(id) ON DELETE SET NULL, CONSTRAINT fk_rally_winning_team FOREIGN KEY (winning_team_id) REFERENCES teams(id) ON DELETE SET NULL, CONSTRAINT fk_rally_user FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE SET NULL, UNIQUE KEY uq_rally_number (match_id, set_number, rally_number) ) ENGINE=InnoDB; CREATE TABLE referee_audit_logs ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, match_id BIGINT UNSIGNED NOT NULL, user_id BIGINT UNSIGNED, action VARCHAR(80) NOT NULL, payload JSON, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, CONSTRAINT fk_audit_match FOREIGN KEY (match_id) REFERENCES matches(id) ON DELETE CASCADE, CONSTRAINT fk_audit_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL, INDEX idx_audit_match_created (match_id, created_at) ) ENGINE=InnoDB; CREATE TABLE referee_signatures ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, match_id BIGINT UNSIGNED NOT NULL, referee_id BIGINT UNSIGNED, signer_name VARCHAR(140) NOT NULL, role VARCHAR(80) NOT NULL DEFAULT 'principal', signature_hash CHAR(64) NOT NULL, signed_payload JSON, signed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, CONSTRAINT fk_signatures_match FOREIGN KEY (match_id) REFERENCES matches(id) ON DELETE CASCADE, CONSTRAINT fk_signatures_referee FOREIGN KEY (referee_id) REFERENCES referees(id) ON DELETE SET NULL, UNIQUE KEY uq_signature_match_role (match_id, role) ) ENGINE=InnoDB; CREATE TABLE sanctions ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, match_id BIGINT UNSIGNED NOT NULL, team_id BIGINT UNSIGNED, player_id BIGINT UNSIGNED, card_type ENUM('yellow','red') NOT NULL, reason VARCHAR(255), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, CONSTRAINT fk_sanctions_match FOREIGN KEY (match_id) REFERENCES matches(id) ON DELETE CASCADE, CONSTRAINT fk_sanctions_team FOREIGN KEY (team_id) REFERENCES teams(id) ON DELETE SET NULL, CONSTRAINT fk_sanctions_player FOREIGN KEY (player_id) REFERENCES players(id) ON DELETE SET NULL ) ENGINE=InnoDB; CREATE TABLE team_standings ( tournament_id BIGINT UNSIGNED NOT NULL, team_id BIGINT UNSIGNED NOT NULL, played INT UNSIGNED NOT NULL DEFAULT 0, won INT UNSIGNED NOT NULL DEFAULT 0, lost INT UNSIGNED NOT NULL DEFAULT 0, sets_for INT UNSIGNED NOT NULL DEFAULT 0, sets_against INT UNSIGNED NOT NULL DEFAULT 0, points INT UNSIGNED NOT NULL DEFAULT 0, PRIMARY KEY (tournament_id, team_id), CONSTRAINT fk_standings_tournament FOREIGN KEY (tournament_id) REFERENCES tournaments(id) ON DELETE CASCADE, CONSTRAINT fk_standings_team FOREIGN KEY (team_id) REFERENCES teams(id) ON DELETE CASCADE ) ENGINE=InnoDB;