Correction des présences et correction de plusieurs erreurs mineur de déplacement/parcours de l'utilisateur, harmonisation des processus

This commit is contained in:
cedrick2711
2026-07-28 18:11:02 -04:00
parent b982cd0318
commit a0f18a886c
19 changed files with 250 additions and 116 deletions
+2 -2
View File
@@ -89,7 +89,7 @@ def list_evaluations():
else:
sort_expr = sort_expr.desc()
if user.role == 'president':
if user.role == 'admin':
evaluations = Evaluation.query \
.outerjoin(Tryout, Evaluation.tryout_id == Tryout.id) \
.outerjoin(player_alias, Evaluation.player_id == player_alias.id) \
@@ -227,7 +227,7 @@ def evaluate_player(tryout_id, player_id):
return redirect(url_for('tryouts.view_tryout', tryout_id=tryout_id))
evaluators = None
if current_user.role == 'president':
if current_user.role == 'admin':
all_evaluations = Evaluation.query.filter_by(tryout_id=tryout_id, player_id=player_id).all()
evaluators = [{'evaluator': User.query.get(e.evaluator_id), 'eval': e} for e in all_evaluations]
+1 -1
View File
@@ -43,7 +43,7 @@ def dashboard():
user = current_user
stats = {}
if user.role == 'president':
if user.role == 'admin':
stats['total_users'] = User.query.count()
stats['total_players'] = User.query.filter_by(role='player').count()
stats['total_tryouts'] = Tryout.query.count()
+6 -4
View File
@@ -19,7 +19,7 @@ def can_schedule_match():
Returns:
bool: True if user is president, manager, coach, or scout.
"""
return current_user.role in ['president', 'manager', 'coach', 'scout']
return current_user.role in ['admin', 'manager', 'coach', 'scout']
@matches_bp.route('/calendar')
@@ -248,7 +248,7 @@ def get_visible_tryouts_for_user():
Returns:
list: Query result of Tryout objects.
"""
if current_user.role == 'president':
if current_user.role == 'admin':
return Tryout.query.order_by(Tryout.date).all()
elif current_user.role == 'manager':
return Tryout.query.filter_by(created_by=current_user.id).order_by(Tryout.date).all()
@@ -558,8 +558,10 @@ def edit_match(match_id):
# Handle player vs player matches - update participants
elif match.match_type == 'player_vs_player':
MatchParticipant.query.filter_by(match_id=match.id).delete()
team1_player_ids = request.form.getlist('team1_player_ids')
team2_player_ids = request.form.getlist('team2_player_ids')
team1_str = request.form.get('team1_player_ids', '')
team2_str = request.form.get('team2_player_ids', '')
team1_player_ids = [p for p in team1_str.split(',') if p.strip()] if team1_str else []
team2_player_ids = [p for p in team2_str.split(',') if p.strip()] if team2_str else []
notified_participant_ids = []
for pid in team1_player_ids:
participant = MatchParticipant(match_id=match.id, player_id=int(pid), team_side=1)
+3 -3
View File
@@ -20,7 +20,7 @@ def can_manage_team_match(team):
Returns:
bool: True if user is president, manager, or a coach of this team.
"""
if current_user.role in ['president']:
if current_user.role in ['admin']:
return True
if current_user.role == 'manager':
return True
@@ -45,7 +45,7 @@ def list_matches():
# Optional pre-filter by team_id from query param
filter_team_id = request.args.get('team_id', type=int)
if current_user.role == 'president':
if current_user.role == 'admin':
teams = OrgTeam.query.order_by(OrgTeam.name).all()
matches_query = TeamMatch.query
elif current_user.role == 'manager':
@@ -337,7 +337,7 @@ def api_manageable_teams():
if not current_user.can_schedule_matches():
return jsonify([])
if current_user.role in ['president', 'manager']:
if current_user.role in ['admin', 'manager']:
teams = OrgTeam.query.order_by(OrgTeam.name).all()
elif current_user.role == 'coach':
teams = OrgTeam.query.filter(
+42 -13
View File
@@ -24,7 +24,9 @@ def list_teams():
"""
can_manage = current_user.can_manage_teams()
if current_user.role == 'coach':
if current_user.role == 'admin':
teams = OrgTeam.query.order_by(OrgTeam.name).all()
elif current_user.role == 'coach':
teams = OrgTeam.query.filter(
db.or_(
OrgTeam.coaches.any(id=current_user.id),
@@ -181,18 +183,45 @@ def edit_team(team_id):
flash(f'Team "{name}" already exists.', 'danger')
return redirect(url_for('teams.list_teams'))
team.name = name
team.coach_id = int(coach_id) if coach_id else None
team.manager_id = int(manager_id) if manager_id else None
if coach_id:
coach_user = User.query.get(int(coach_id))
if coach_user and not team.coaches.filter_by(id=coach_user.id).first():
team.coaches.append(coach_user)
if manager_id:
manager_user = User.query.get(int(manager_id))
if manager_user and not team.managers.filter_by(id=manager_user.id).first():
team.managers.append(manager_user)
# Check if we're syncing staff (multi-select) or single legacy update
if request.form.get('sync_staff') == '1':
coach_ids = request.form.getlist('coach_ids')
manager_ids = request.form.getlist('manager_ids')
# Sync coaches many-to-many
team.coaches = []
for cid in coach_ids:
if cid and cid.strip():
coach_user = User.query.get(int(cid))
if coach_user and coach_user.role == 'coach':
team.coaches.append(coach_user)
# Update legacy coach_id with first coach
coach_list = team.coaches.all()
team.coach_id = coach_list[0].id if coach_list else None
# Sync managers many-to-many
team.managers = []
for mid in manager_ids:
if mid and mid.strip():
manager_user = User.query.get(int(mid))
if manager_user and manager_user.role == 'manager':
team.managers.append(manager_user)
# Update legacy manager_id with first manager
manager_list = team.managers.all()
team.manager_id = manager_list[0].id if manager_list else None
else:
# Legacy single dropdown update
team.coach_id = int(coach_id) if coach_id else None
team.manager_id = int(manager_id) if manager_id else None
if coach_id:
coach_user = User.query.get(int(coach_id))
if coach_user and not team.coaches.filter_by(id=coach_user.id).first():
team.coaches.append(coach_user)
if manager_id:
manager_user = User.query.get(int(manager_id))
if manager_user and not team.managers.filter_by(id=manager_user.id).first():
team.managers.append(manager_user)
db.session.commit()
flash(f'Team "{name}" updated successfully!', 'success')
+16 -4
View File
@@ -18,7 +18,7 @@ def can_manage():
Returns:
bool: True if user is president or manager.
"""
return current_user.role in ['president', 'manager']
return current_user.role in ['admin', 'manager']
@tryouts_bp.route('')
@@ -35,7 +35,7 @@ def list_tryouts():
Returns:
Response: Rendered tryouts list template.
"""
if current_user.role == 'president':
if current_user.role == 'admin':
tryouts = Tryout.query.order_by(Tryout.date.desc()).all()
elif current_user.role == 'manager':
tryouts = Tryout.query.filter_by(created_by=current_user.id).order_by(Tryout.date.desc()).all()
@@ -192,7 +192,7 @@ def view_tryout(tryout_id):
# Check if user has permission to view this tryout
can_view = False
if current_user.role == 'president':
if current_user.role == 'admin':
can_view = True
elif current_user.role == 'manager' and tryout.created_by == current_user.id:
can_view = True
@@ -276,6 +276,17 @@ def view_tryout(tryout_id):
confirmed_count = sum(1 for p in all_participants if p.attendance_confirmed)
total_count = len(all_participants)
# Build per-player presence data for toggle buttons
player_presence = []
for p in all_participants:
if p.player:
player_presence.append({
'participant_id': p.id,
'player_id': p.player_id,
'player_name': p.player.username,
'attendance_confirmed': p.attendance_confirmed
})
if match.match_type == 'team_vs_team':
participants = {
'team1': match.team1.name if match.team1 else 'TBD',
@@ -299,7 +310,8 @@ def view_tryout(tryout_id):
'match': match,
'participants': participants,
'confirmed_count': confirmed_count,
'total_count': total_count
'total_count': total_count,
'player_presence': player_presence
})
return render_template('pages/view_tryout.html',
+13 -13
View File
@@ -69,7 +69,7 @@ def list_users():
Returns:
Response: Rendered users list template or redirect to dashboard.
"""
if current_user.role != 'president':
if current_user.role != 'admin':
flash('Only the president can manage users.', 'danger')
return redirect(url_for('main.dashboard'))
@@ -91,7 +91,7 @@ def edit_user(user_id):
Returns:
Response: Edit form or redirect to users list.
"""
if current_user.role != 'president':
if current_user.role != 'admin':
flash('Only the president can edit users.', 'danger')
return redirect(url_for('main.dashboard'))
@@ -149,7 +149,7 @@ def delete_user(user_id):
Returns:
Response: Redirect to users list with status message.
"""
if current_user.role != 'president':
if current_user.role != 'admin':
flash('Only the president can delete users.', 'danger')
return redirect(url_for('main.dashboard'))
@@ -229,7 +229,7 @@ def create_user():
Returns:
Response: Create form or redirect to users list.
"""
if current_user.role != 'president':
if current_user.role != 'admin':
flash('Only the president can create users.', 'danger')
return redirect(url_for('main.dashboard'))
@@ -588,7 +588,7 @@ def can_manage_player_contract(user, player_id):
bool: True if user has permission to manage the contract.
"""
# President can manage all contracts
if user.role == 'president':
if user.role == 'admin':
return True
# Manager can upload contracts for any player
@@ -621,7 +621,7 @@ def list_contracts():
if current_user.role == 'player':
# Players see their own contracts
contracts = Contract.query.filter_by(player_id=current_user.id).order_by(Contract.uploaded_at.desc()).all()
elif current_user.role in ['president', 'manager', 'coach']:
elif current_user.role in ['admin', 'manager', 'coach']:
# Superiors see contracts for players on their teams
players = []
if current_user.role == 'coach':
@@ -636,7 +636,7 @@ def list_contracts():
player_ids = [p.id for p in players]
contracts = Contract.query.filter(Contract.player_id.in_(player_ids)).order_by(Contract.uploaded_at.desc()).all()
return render_template('pages/contracts.html', contracts=contracts, players=players if current_user.role in ['president', 'manager', 'coach'] else None)
return render_template('pages/contracts.html', contracts=contracts, players=players if current_user.role in ['admin', 'manager', 'coach'] else None)
@users_bp.route('/contracts/upload', methods=['GET', 'POST'])
@@ -650,7 +650,7 @@ def upload_contract():
Returns:
Response: Upload form or redirect to contracts list.
"""
if current_user.role not in ['president', 'manager', 'coach']:
if current_user.role not in ['admin', 'manager', 'coach']:
flash('Only presidents, managers, and coaches can upload contracts.', 'danger')
return redirect(url_for('users.list_contracts'))
@@ -1395,7 +1395,7 @@ def add_personal_note():
Returns:
Response: Create form or redirect to notes view.
"""
if current_user.role not in ['coach', 'manager', 'president']:
if current_user.role not in ['coach', 'manager', 'admin']:
flash('Only coaches and managers can add notes.', 'danger')
return redirect(url_for('main.dashboard'))
@@ -1407,7 +1407,7 @@ def add_personal_note():
if org_team:
player_ids = [tp.player_id for tp in TeamPlayer.query.filter_by(org_team_id=org_team.id).all()]
players = User.query.filter(User.id.in_(player_ids)).order_by(User.username).all() if player_ids else []
elif current_user.role in ['president', 'manager']:
elif current_user.role in ['admin', 'manager']:
players = User.query.filter_by(role='player').order_by(User.username).all()
# Get available matches and tryouts for context
@@ -1417,7 +1417,7 @@ def add_personal_note():
if current_user.role == 'coach' and org_team:
tryouts = Tryout.query.filter_by(target_org_team_id=org_team.id).order_by(Tryout.date.desc()).all()
matches = Match.query.join(Tryout).filter(Tryout.target_org_team_id == org_team.id).order_by(Match.date.desc()).all()
elif current_user.role in ['president', 'manager']:
elif current_user.role in ['admin', 'manager']:
tryouts = Tryout.query.order_by(Tryout.date.desc()).all()
matches = Match.query.order_by(Match.date.desc()).all()
teams = Team.query.order_by(Team.name).all()
@@ -1501,7 +1501,7 @@ def add_note_from_match(match_id):
Returns:
Response: Create form or redirect.
"""
if current_user.role not in ['coach', 'manager', 'president']:
if current_user.role not in ['coach', 'manager', 'admin']:
flash('Only coaches can add notes from matches.', 'danger')
return redirect(url_for('main.dashboard'))
@@ -1577,7 +1577,7 @@ def add_note_from_tryout(tryout_id):
Returns:
Response: Create form or redirect.
"""
if current_user.role not in ['coach', 'manager', 'president']:
if current_user.role not in ['coach', 'manager', 'admin']:
flash('Only coaches can add notes from tryouts.', 'danger')
return redirect(url_for('main.dashboard'))