Ajout du statut remplaçant pour les joueurs
Possibilité d'ajouter/enlever coach et manager des équipes
les joueurs peuvent être associés à plusieurs équipes au lieu d'une seule
This commit is contained in:
cedrick2711
2026-07-20 17:41:22 -04:00
parent 027e529885
commit 346229778f
18 changed files with 343 additions and 69 deletions
+109 -15
View File
@@ -3,10 +3,10 @@
This module handles CRUD operations for organization teams and player assignments.
"""
from flask import Blueprint, render_template, redirect, url_for, flash, request
from flask import Blueprint, render_template, redirect, url_for, flash, request, jsonify
from flask_login import login_required, current_user
from extensions import db
from models import OrgTeam, User, Team, TeamMember, PersonalNote, TeamNote, Tryout
from models import OrgTeam, User, Team, TeamMember, PersonalNote, TeamNote, Tryout, TeamPlayer
teams_bp = Blueprint('teams', __name__, url_prefix='/teams')
@@ -35,8 +35,9 @@ def list_teams():
return redirect(url_for('main.dashboard'))
coaches = User.query.filter_by(role='coach').order_by(User.full_name).all()
managers = User.query.filter_by(role='manager').order_by(User.full_name).all()
all_players = User.query.filter_by(role='player').order_by(User.full_name).all()
return render_template('pages/teams.html', teams=teams, coaches=coaches, all_players=all_players, can_manage=can_manage)
return render_template('pages/teams.html', teams=teams, coaches=coaches, managers=managers, all_players=all_players, can_manage=can_manage)
@teams_bp.route('/create', methods=['POST'])
@@ -47,6 +48,7 @@ def create_team():
Args:
name: Team name from form.
coach_id: Optional coach assignment from form.
manager_id: Optional manager assignment from form.
Returns:
Response: Redirect to teams list with status message.
@@ -57,6 +59,7 @@ def create_team():
name = request.form.get('name')
coach_id = request.form.get('coach_id')
manager_id = request.form.get('manager_id')
if not name:
flash('Team name is required.', 'danger')
@@ -70,6 +73,7 @@ def create_team():
team = OrgTeam(
name=name,
coach_id=int(coach_id) if coach_id else None,
manager_id=int(manager_id) if manager_id else None,
created_by=current_user.id
)
db.session.add(team)
@@ -87,6 +91,7 @@ def edit_team(team_id):
team_id: The ID of the team to edit.
name: New team name from form.
coach_id: New coach assignment from form.
manager_id: New manager assignment from form.
Returns:
Response: Redirect to teams list with status message.
@@ -98,6 +103,7 @@ def edit_team(team_id):
name = request.form.get('name')
coach_id = request.form.get('coach_id')
manager_id = request.form.get('manager_id')
if not name:
flash('Team name is required.', 'danger')
@@ -110,6 +116,7 @@ def edit_team(team_id):
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
db.session.commit()
flash(f'Team "{name}" updated successfully!', 'success')
return redirect(url_for('teams.list_teams'))
@@ -144,22 +151,71 @@ def delete_team(team_id):
t.target_org_team_id = None
db.session.commit()
# Remove all team_players associations
TeamPlayer.query.filter_by(org_team_id=team_id).delete()
db.session.commit()
db.session.delete(team)
db.session.commit()
flash(f'Team "{name}" deleted successfully.', 'success')
return redirect(url_for('teams.list_teams'))
@teams_bp.route('/<int:team_id>/remove_coach', methods=['POST'])
@login_required
def remove_coach(team_id):
"""Remove the coach from an organization team.
Args:
team_id: The ID of the team.
Returns:
Response: Redirect to teams list with status message.
"""
team = OrgTeam.query.get_or_404(team_id)
if not current_user.can_manage_this_org_team(team):
flash('Permission denied.', 'danger')
return redirect(url_for('teams.list_teams'))
team.coach_id = None
db.session.commit()
flash(f'Coach removed from {team.name}.', 'success')
return redirect(url_for('teams.list_teams'))
@teams_bp.route('/<int:team_id>/remove_manager', methods=['POST'])
@login_required
def remove_manager(team_id):
"""Remove the manager from an organization team.
Args:
team_id: The ID of the team.
Returns:
Response: Redirect to teams list with status message.
"""
team = OrgTeam.query.get_or_404(team_id)
if not current_user.can_manage_this_org_team(team):
flash('Permission denied.', 'danger')
return redirect(url_for('teams.list_teams'))
team.manager_id = None
db.session.commit()
flash(f'Manager removed from {team.name}.', 'success')
return redirect(url_for('teams.list_teams'))
@teams_bp.route('/<int:team_id>/add_player', methods=['POST'])
@login_required
def add_player(team_id):
"""Add a player to an organization team.
If player is already on another team, they will be moved.
Players can now be in multiple teams.
Args:
team_id: The ID of the team to add the player to.
player_id: The ID of the player to add.
status: The player's status (starter or substitute).
Returns:
Response: Redirect to teams list with status message.
@@ -169,7 +225,7 @@ def add_player(team_id):
flash('Permission denied.', 'danger')
return redirect(url_for('teams.list_teams'))
player_id = request.form.get('player_id')
position = request.form.get('position', '')
status = request.form.get('status', 'starter')
if not player_id:
flash('Please select a player.', 'danger')
@@ -180,15 +236,19 @@ def add_player(team_id):
flash('Can only assign players to teams.', 'danger')
return redirect(url_for('teams.list_teams'))
# If player already belongs to a different team, remove them first
if player.team_id and player.team_id != team_id:
old_team = OrgTeam.query.get(player.team_id)
flash(f'{player.full_name} was moved from {old_team.name} to {team.name}.', 'info')
elif player.team_id == team_id:
# Check if player is already on this team
existing = TeamPlayer.query.filter_by(player_id=player.id, org_team_id=team.id).first()
if existing:
flash(f'{player.full_name} is already on {team.name}.', 'info')
return redirect(url_for('teams.list_teams'))
player.team_id = team_id
# Add player to the team using TeamPlayer model (allows multiple teams)
tp = TeamPlayer(
player_id=player.id,
org_team_id=team.id,
status=status
)
db.session.add(tp)
db.session.commit()
flash(f'{player.full_name} added to {team.name}!', 'success')
return redirect(url_for('teams.list_teams'))
@@ -213,16 +273,49 @@ def remove_player(team_id, player_id):
player = User.query.get_or_404(player_id)
if player.team_id != team_id:
tp = TeamPlayer.query.filter_by(player_id=player_id, org_team_id=team_id).first()
if not tp:
flash(f'{player.full_name} is not on {team.name}.', 'danger')
return redirect(url_for('teams.list_teams'))
player.team_id = None
db.session.delete(tp)
db.session.commit()
flash(f'{player.full_name} removed from {team.name}.', 'success')
return redirect(url_for('teams.list_teams'))
@teams_bp.route('/<int:team_id>/toggle_status/<int:player_id>', methods=['POST'])
@login_required
def toggle_player_status(team_id, player_id):
"""Toggle a player's status between starter and substitute.
Args:
team_id: The ID of the team.
player_id: The ID of the player.
Returns:
Response: JSON with new status.
"""
team = OrgTeam.query.get_or_404(team_id)
if not current_user.can_manage_this_org_team(team):
return jsonify({'error': 'Permission denied'}), 403
tp = TeamPlayer.query.filter_by(player_id=player_id, org_team_id=team_id).first()
if not tp:
return jsonify({'error': 'Player not found on this team'}), 404
# Toggle status
tp.status = 'substitute' if tp.status == 'starter' else 'starter'
db.session.commit()
return jsonify({
'success': True,
'player_id': player_id,
'new_status': tp.status,
'player_name': tp.player.full_name
})
# Note actions from team page
@@ -284,7 +377,8 @@ def add_player_note(team_id, player_id):
return redirect(url_for('teams.list_teams'))
# Verify player belongs to this team
if player.team_id != team_id:
tp = TeamPlayer.query.filter_by(player_id=player_id, org_team_id=team_id).first()
if not tp:
flash(f'{player.full_name} is not on {team.name}.', 'danger')
return redirect(url_for('teams.list_teams'))
@@ -300,4 +394,4 @@ def add_player_note(team_id, player_id):
db.session.commit()
flash(f'Note added for {player.full_name}!', 'success')
return redirect(url_for('teams.list_teams'))
return redirect(url_for('teams.list_teams'))