diff --git a/instance/team_tryouts.db b/instance/team_tryouts.db index e42e0f7..dff8222 100644 Binary files a/instance/team_tryouts.db and b/instance/team_tryouts.db differ diff --git a/routes/__pycache__/evaluations.cpython-313.pyc b/routes/__pycache__/evaluations.cpython-313.pyc index c945e3a..694d793 100644 Binary files a/routes/__pycache__/evaluations.cpython-313.pyc and b/routes/__pycache__/evaluations.cpython-313.pyc differ diff --git a/routes/__pycache__/users.cpython-313.pyc b/routes/__pycache__/users.cpython-313.pyc index 0f1cb05..beafbbe 100644 Binary files a/routes/__pycache__/users.cpython-313.pyc and b/routes/__pycache__/users.cpython-313.pyc differ diff --git a/routes/evaluations.py b/routes/evaluations.py index 83f74c0..367fb64 100644 --- a/routes/evaluations.py +++ b/routes/evaluations.py @@ -40,7 +40,6 @@ def list_evaluations(): President: All evaluations with player score summaries. Evaluators (coach/manager): Their given evaluations. - Players: Their received evaluations. Supports sorting by any column header via 'sort' and 'order' query parameters. @@ -49,6 +48,11 @@ def list_evaluations(): """ user = current_user + # Players are not allowed to view evaluations + if user.role == 'player': + flash('You do not have permission to view evaluations.', 'danger') + return redirect(url_for('main.dashboard')) + # Get sort parameters sort_column = request.args.get('sort', 'created_at') sort_order = request.args.get('order', 'desc') diff --git a/routes/users.py b/routes/users.py index 94875b2..f4c1bcf 100644 --- a/routes/users.py +++ b/routes/users.py @@ -8,7 +8,7 @@ import os from flask import Blueprint, render_template, redirect, url_for, flash, request, jsonify, send_file from flask_login import login_required, current_user from extensions import db, hash_password -from models import User, ROLES, ESPORT_GAMES, PlayerDisponibility, UserGamertag, GAME_PLATFORMS, Contract, OrgTeam, CoachAvailability, TeamNote, PersonalNote, OneOnOneRequest, Match, Team, TeamMember, MatchParticipant, Tryout, TryoutRegistration, TeamPlayer +from models import User, ROLES, ESPORT_GAMES, PlayerDisponibility, UserGamertag, GAME_PLATFORMS, Contract, OrgTeam, CoachAvailability, TeamNote, PersonalNote, OneOnOneRequest, Evaluation, Match, Team, TeamMember, MatchParticipant, Tryout, TryoutRegistration, TeamPlayer from werkzeug.utils import secure_filename from datetime import datetime, timedelta, date as date_type import requests @@ -151,6 +151,60 @@ def delete_user(user_id): return redirect(url_for('users.list_users')) user = User.query.get_or_404(user_id) + + # Clean up related records before deleting the user + # 1. Delete evaluations involving this user + Evaluation.query.filter( + db.or_(Evaluation.evaluator_id == user_id, Evaluation.player_id == user_id) + ).delete(synchronize_session=False) + + # 2. Delete availability/disponibility records + PlayerDisponibility.query.filter_by(player_id=user_id).delete() + CoachAvailability.query.filter_by(coach_id=user_id).delete() + + # 3. Delete personal notes involving this user + PersonalNote.query.filter( + db.or_(PersonalNote.player_id == user_id, PersonalNote.coach_id == user_id) + ).delete(synchronize_session=False) + + # 4. Delete team notes authored by this user + TeamNote.query.filter_by(coach_id=user_id).delete() + + # 5. Delete one-on-one requests involving this user + OneOnOneRequest.query.filter( + db.or_(OneOnOneRequest.player_id == user_id, OneOnOneRequest.coach_id == user_id) + ).delete(synchronize_session=False) + + # 6. Delete gamertags + UserGamertag.query.filter_by(user_id=user_id).delete() + + # 7. Delete contracts for this player (and any they uploaded as manager/coach) + Contract.query.filter_by(player_id=user_id).delete() + + # 8. Delete tryout registrations + TryoutRegistration.query.filter_by(player_id=user_id).delete() + + # 9. Delete team placements + TeamPlayer.query.filter_by(player_id=user_id).delete() + + # 10. Delete team memberships in tryout teams + TeamMember.query.filter_by(player_id=user_id).delete() + + # 11. Delete match participants + MatchParticipant.query.filter_by(player_id=user_id).delete() + + # 12. Nullify org team references so the user can be deleted + OrgTeam.query.filter_by(coach_id=user_id).update({'coach_id': None}) + OrgTeam.query.filter_by(manager_id=user_id).update({'manager_id': None}) + + # 13. Handle records this user created (tryouts, matches, teams, org teams, contracts) + # Reassign created_by to the current president (deleting user) to avoid FK violations + Tryout.query.filter_by(created_by=user_id).update({'created_by': current_user.id}) + Match.query.filter_by(created_by=user_id).update({'created_by': current_user.id}) + Team.query.filter_by(created_by=user_id).update({'created_by': current_user.id}) + OrgTeam.query.filter_by(created_by=user_id).update({'created_by': current_user.id}) + Contract.query.filter_by(uploaded_by_id=user_id).update({'uploaded_by_id': current_user.id}) + db.session.delete(user) db.session.commit() flash(f'User {user.full_name} has been removed.', 'success') diff --git a/templates/pages/coach_availability.html b/templates/pages/coach_availability.html index e154bd5..29a933f 100644 --- a/templates/pages/coach_availability.html +++ b/templates/pages/coach_availability.html @@ -90,7 +90,7 @@ text-align: center; cursor: pointer; transition: var(--transition); - background: white; + background: var(--bg-secondary); border: 1px solid var(--border-color); } diff --git a/templates/pages/dashboard.html b/templates/pages/dashboard.html index b73121c..e9bfdaf 100644 --- a/templates/pages/dashboard.html +++ b/templates/pages/dashboard.html @@ -221,24 +221,6 @@
My Tryouts
-Avg Score
-Evaluations
-| Tryout | Evaluator | Score | Date |
|---|---|---|---|
| {{ e.tryout.title }} | -{{ e.evaluator.full_name }} | -{{ e.overall_score }} | -{{ e.created_at.strftime('%m/%d/%Y') }} | -
Tryouts Registered
-Evaluations Received
-Team Assignments