online_registration
Raz 11 months ago
parent c70deac834
commit e6526cbb8f
  1. 2
      tournaments/forms.py
  2. 12
      tournaments/models/enums.py
  3. 3
      tournaments/models/team_registration.py
  4. 56
      tournaments/models/tournament.py
  5. 56
      tournaments/static/tournaments/css/style.css
  6. 8
      tournaments/templates/profile.html
  7. 18
      tournaments/templates/register_tournament.html
  8. 8
      tournaments/templates/tournaments/navigation_base.html
  9. 26
      tournaments/templates/tournaments/navigation_tournament.html
  10. 21
      tournaments/templates/tournaments/tournament_info.html
  11. 2
      tournaments/templates/tournaments/tournament_row.html
  12. 5
      tournaments/templates/tournaments/tournaments.html
  13. 39
      tournaments/views.py

@ -47,7 +47,7 @@ class SimpleForm(forms.Form):
class TournamentRegistrationForm(forms.Form):
#first_name = forms.CharField(label='Prénom', max_length=50)
#last_name = forms.CharField(label='Nom', max_length=50)
email = forms.EmailField(label='E-mail')
email = forms.EmailField(label='E-mail', widget=forms.EmailInput(attrs={'readonly': 'readonly'}))
mobile_number = forms.CharField(
label='Téléphone (facultatif)',
max_length=15,

@ -92,11 +92,10 @@ class OnlineRegistrationStatus(models.IntegerChoices):
NOT_ENABLED = 2, 'Not Enabled'
NOT_STARTED = 3, 'Not Started'
ENDED = 4, 'Ended'
REGISTRATION_FULL = 5, 'Registration Full'
WAITING_LIST_POSSIBLE = 6, 'Waiting List Possible'
WAITING_LIST_FULL = 7, 'Waiting List Full'
IN_PROGRESS = 8, 'In Progress'
ENDED_WITH_RESULTS = 9, 'Ended with Results'
WAITING_LIST_POSSIBLE = 5, 'Waiting List Possible'
WAITING_LIST_FULL = 6, 'Waiting List Full'
IN_PROGRESS = 7, 'In Progress'
ENDED_WITH_RESULTS = 8, 'Ended with Results'
def status_localized(self) -> str:
status_map = {
@ -104,8 +103,7 @@ class OnlineRegistrationStatus(models.IntegerChoices):
OnlineRegistrationStatus.NOT_ENABLED: "Inscription désactivée",
OnlineRegistrationStatus.NOT_STARTED: "Inscription pas encore ouverte",
OnlineRegistrationStatus.ENDED: "Inscription terminée",
OnlineRegistrationStatus.REGISTRATION_FULL: "Inscription complète",
OnlineRegistrationStatus.WAITING_LIST_POSSIBLE: "Liste d'attente disponible",
OnlineRegistrationStatus.WAITING_LIST_POSSIBLE: "Liste d'attente ouverte",
OnlineRegistrationStatus.WAITING_LIST_FULL: "Liste d'attente complète",
OnlineRegistrationStatus.IN_PROGRESS: "Tournoi en cours",
OnlineRegistrationStatus.ENDED_WITH_RESULTS: "Tournoi terminé"

@ -125,3 +125,6 @@ class TeamRegistration(models.Model):
if p != player:
return p
return None
def is_in_waiting_list(self):
return self.tournament.get_team_waiting_list_position(self)

@ -200,7 +200,9 @@ class Tournament(models.Model):
def registration_count_display(self):
teams = self.teams(True)
if teams is not None and len(teams) > 0:
if teams is not None and len(teams) == 1:
return f"{len(teams)} équipe inscrite"
elif teams is not None and len(teams) > 1:
return f"{len(teams)} équipes inscrites"
else:
return None
@ -295,6 +297,18 @@ class Tournament(models.Model):
rankings.sort(key=lambda r: r.ranking)
return rankings
def get_team_waiting_list_position(self, team_registration):
# Use the teams method to get sorted list of teams
all_teams = self.teams(True)
waiting_teams = [t for t in all_teams if t.stage == "Attente"]
# Find matching team in waiting list and return its index
for i, team in enumerate(waiting_teams):
if team.team_registration.id == team_registration.id:
return i
return -1 # Team not found in waiting list
def teams(self, includeWaitingList):
# print("Starting teams method")
bracket_teams = []
@ -988,17 +1002,7 @@ class Tournament(models.Model):
waiting_list_count = current_team_count - self.target_team_count
if waiting_list_count >= self.waiting_list_limit:
return OnlineRegistrationStatus.WAITING_LIST_FULL
return OnlineRegistrationStatus.WAITING_LIST_POSSIBLE
return OnlineRegistrationStatus.REGISTRATION_FULL
current_team_count = self.teamregistration_set.filter(walk_out=False).count()
if current_team_count >= self.target_team_count:
if self.waiting_list_limit is not None:
waiting_list_count = current_team_count - self.target_team_count
if waiting_list_count >= self.waiting_list_limit:
return OnlineRegistrationStatus.WAITING_LIST_FULL
return OnlineRegistrationStatus.WAITING_LIST_POSSIBLE
return OnlineRegistrationStatus.REGISTRATION_FULL
return OnlineRegistrationStatus.WAITING_LIST_POSSIBLE
return OnlineRegistrationStatus.OPEN
def is_unregistration_possible(self):
@ -1021,9 +1025,35 @@ class Tournament(models.Model):
# Otherwise unregistration is allowed
return True
def get_waiting_list_position(self):
# If no target team count exists, no one goes to waiting list
if self.target_team_count is None:
return -1
# Get count of active teams (not walked out)
current_team_count = len([tr for tr in self.teamregistration_set.all() if tr.out_of_tournament() is False])
# If current count is less than target count, next team is not in waiting list
if current_team_count < self.target_team_count:
return -1
# If we have a waiting list limit
if self.waiting_list_limit is not None:
waiting_list_count = current_team_count - self.target_team_count
# If waiting list is full
if waiting_list_count >= self.waiting_list_limit:
return -1
# Return waiting list position
return waiting_list_count
# In waiting list with no limit
return current_team_count - self.target_team_count
def build_tournament_details_str(self):
tournament_details = []
tournament_details.append(self.level())
if self.federal_level_category > 0:
tournament_details.append(self.level())
if self.category():
tournament_details.append(self.category())
if self.age():

@ -82,6 +82,26 @@ nav a {
font-weight: 600;
}
nav a.orange {
color: white;
background-color: #f39200;
}
nav a.orange:hover {
color: #1b223a; /* Same text color on hover */
text-decoration: none; /* Prevent underline on <a> hover */
}
nav a.red {
color: white;
background-color: #e84038;
}
nav a.red:hover {
color: white; /* Same text color on hover */
background-color: #1b223a;
}
hr {
margin: 2px 0px;
}
@ -323,7 +343,7 @@ tr {
}
.red {
background-color: red;
background-color: #e84038;
}
svg {
@ -712,7 +732,7 @@ h-margin {
}
.alert {
color: red; /* Make the text red */
color: #e84038; /* Make the text red */
font-weight: bold; /* Optional: Make the text bold */
}
@ -725,35 +745,3 @@ h-margin {
background-color: #cc0000; /* Darker red on hover */
color: white; /* White text on hover */
}
.top-link {
display: block;
text-align: center;
margin-top: 10px;
font-style: italic;
text-decoration: underline;
}
.login-buttons {
position: relative;
display: flex;
margin-left: 10px;
gap: 10px;
padding: 0px;
}
.login-buttons .button {
display: block;
padding: 8px 8px;
border: none;
background: none;
border-radius: 4px;
text-align: center;
text-decoration: underline;
color: #333;
transition: background 0.2s;
}
.login-buttons .button:hover {
background: #f39200;
}

@ -6,12 +6,12 @@
{% block content %}
<nav class="margin10">
<a href="{% url 'index' %}">Accueil</a>
<a href="{% url 'clubs' %}">Clubs</a>
<a href="{% url 'index' %}" class="orange">Accueil</a>
<a href="{% url 'clubs' %}" class="orange">Clubs</a>
{% if user.is_authenticated %}
<a href="{% url 'my-tournaments' %}">Mes tournois</a>
<a href="{% url 'my-tournaments' %}" class="orange">Mes tournois</a>
<a href="{% url 'profile' %}">Mon compte</a>
<a href="{% url 'logout' %}">Se déconnecter</a>
<a href="{% url 'logout' %}" class="red">Se déconnecter</a>
{% else %}
<a href="{% url 'login' %}">Se connecter</a>
{% endif %}

@ -110,8 +110,24 @@
{% if current_players|length >= tournament.minimum_player_per_team %}
<div class="margin10">
</div>
<div class="semibold margin10">
{% if tournament.get_waiting_list_position == 1 %}
{{ tournament.get_waiting_list_position }} équipe en liste d'attente devant vous
{% elif tournament.get_waiting_list_position > 1 %}
{{ tournament.get_waiting_list_position }} équipes en liste d'attente devant vous
{% elif tournament.get_waiting_list_position == 0 %}
Aucune équipe en liste d'attente devant vous
{% endif %}
</div>
<div>
<button type="submit" name="register_team" class="rounded-button">Confirmer l'inscription</button>
<button type="submit" name="register_team" class="rounded-button">
{% if tournament.get_waiting_list_position < 0 %}
Confirmer l'inscription
{% else %}
Se mettre en liste d'attente
{% endif %}
</button>
</div>
{% endif %}
</form>

@ -1,11 +1,13 @@
<nav class="margin10">
<a href="{% url 'index' %}">Accueil</a>
<a href="{% url 'clubs' %}">Clubs</a>
<a href="{% url 'index' %}" class="orange">Accueil</a>
<a href="{% url 'clubs' %}" class="orange">Clubs</a>
{% if user.is_authenticated %}
<a href="{% url 'my-tournaments' %}">Mes tournois</a>
<a href="{% url 'my-tournaments' %}" class="orange">Mes tournois</a>
<a href="{% url 'profile' %}">Mon compte</a>
{% else %}
<a href="{% url 'login' %}">Se connecter</a>
{% endif %}
<a href="{% url 'download' %}">Ajouter vos tournois</a>
</nav>

@ -1,32 +1,30 @@
<nav class="margin10">
{% if user.is_authenticated %}
<a href="{% url 'profile' %}">Mon compte</a>
{% else %}
<a href="{% url 'login' %}">Se connecter</a>
{% endif %}
</nav>
<nav class="margin10">
<a href="{% url 'tournament-info' tournament.id %}" class="topmargin5">Informations</a>
<a href="{% url 'tournament-info' tournament.id %}" class="topmargin5 orange">Informations</a>
{% if tournament.display_matches or tournament.display_group_stages %}
<a href="{% url 'tournament' tournament.id %}" class="topmargin5">Matches</a>
<a href="{% url 'tournament' tournament.id %}" class="topmargin5 orange">Matches</a>
{% endif %}
{% if tournament.display_group_stages %}
<a href="{% url 'group-stages' tournament.id %}" class="topmargin5">Poules</a>
<a href="{% url 'group-stages' tournament.id %}" class="topmargin5 orange">Poules</a>
{% endif %}
{% if tournament.display_summons %}
<a href="{% url 'tournament-summons' tournament.id %}" class="topmargin5">Convocations</a>
<a href="{% url 'tournament-summons' tournament.id %}" class="topmargin5 orange">Convocations</a>
{% endif %}
{% if tournament.display_teams %}
<a href="{% url 'tournament-teams' tournament.id %}" class="topmargin5">Équipes</a>
<a href="{% url 'tournament-teams' tournament.id %}" class="topmargin5 orange">Équipes</a>
{% endif %}
{% if tournament.display_rankings %}
<a href="{% url 'tournament-rankings' tournament.id %}" class="topmargin5">Classement</a>
<a href="{% url 'tournament-rankings' tournament.id %}" class="topmargin5 orange">Classement</a>
{% endif %}
{% if user.is_authenticated %}
<a href="{% url 'profile' %}" class="topmargin5">Mon compte</a>
{% else %}
<a href="{% url 'login' %}" class="topmargin5">Se connecter</a>
{% endif %}
</nav>

@ -117,6 +117,19 @@
<h1 class="club my-block topmargin20">Votre équipe</h1 >
<div class="bubble">
<div class="semibold">
{% if team.is_in_waiting_list >= 0 %}
Vous êtes en liste d'attente.
{% if team.is_in_waiting_list == 1 %}
{{ tournament.get_waiting_list_position }} équipe en liste d'attente devant vous
{% elif tournament.get_waiting_list_position > 1 %}
{{ tournament.get_waiting_list_position }} équipes en liste d'attente devant vous
{% elif tournament.get_waiting_list_position == 0 %}
Aucune équipe en liste d'attente devant vous
{% endif %}
{% endif %}
</div>
<p>
<div class="semibold">
{% for player in team.players %}
@ -125,7 +138,7 @@
</div>
</p>
<p>
<div>Inscrit le {{ team.registration_date }}</div>
<div>Inscrits le {{ team.registration_date }}</div>
</p>
{% if tournament.is_unregistration_possible %}
@ -140,7 +153,11 @@
<a href="{% url 'unregister_tournament' tournament.id %}"
class="rounded-button destructive-button"
onclick="return confirm('Êtes-vous sûr de vouloir vous désinscrire ?');">
Se désinscrire
{% if team.is_in_waiting_list >= 0 %}
Se retirer de la liste d'attente
{% else %}
Se désinscrire
{% endif %}
</a>
</p>

@ -26,7 +26,7 @@
</div>
{% if tournament.tournament_status_display %}
<div class="table-cell-responsive-large center horizontal-padding">
<div class="table-cell-responsive-large right horizontal-padding">
{{ tournament.tournament_status_display|linebreaksbr }}
</div>
{% endif %}

@ -6,11 +6,6 @@
{% block right_header %}
<div class="medium-6 large-3 cell topblock my-block flex">
<div class="right-content w300px">
<a href="{% url 'download' %}" class="large_button">Téléchargez l'app pour organiser vos tournois !</a>
</div>
</div>
{% endblock %}
{% block content %}

@ -133,7 +133,9 @@ def tournament_info(request, tournament_id):
# Check if there is a PlayerRegistration for this user in this tournament
registered_user = PlayerRegistration.objects.filter(
licence_id__startswith=stripped_license,
team_registration__tournament=tournament
team_registration__tournament=tournament,
team_registration__walk_out=False,
team_registration__unregistered=False,
).first()
# If the user is registered, retrieve their team registration
@ -716,6 +718,7 @@ def register_tournament(request, tournament_id):
# Check if the team registration form is valid and finalize the registration
elif 'register_team' in request.POST and team_form.is_valid():
waiting_list_position = tournament.get_waiting_list_position()
registration_date = timezone.now().replace(microsecond=0)
team_registration = TeamRegistration.objects.create(
tournament=tournament,
@ -777,17 +780,28 @@ def register_tournament(request, tournament_id):
# Send confirmation email
tournament_details_str = tournament.build_tournament_details_str()
name_str = tournament.build_name_details_str()
email_subject = f"Confirmation d'inscription au {tournament_details_str}{name_str}"
email_subject = f"Confirmation d'inscription au tournoi {tournament_details_str}{name_str}"
if waiting_list_position >= 0:
email_subject = f"En liste d'attente du tournoi {tournament_details_str}{name_str}"
inscription_date = timezone.now().strftime("%d/%m/%Y à %H:%M")
team_members = [player.name() for player in team_registration.playerregistration_set.all()]
team_members_str = " et ".join(team_members)
email_body = f"Bonjour,\n\nVotre inscription au tournoi {tournament_details_str}{name_str} est confirmée."
email_body = f"Bonjour,\n\nVotre inscription au tournoi{tournament_details_str}{name_str} est confirmée."
if tournament.get_waiting_list_position() >= 0:
email_body = f"Bonjour,\n\nVotre inscription en liste d'attente du tournoi{tournament_details_str}{name_str} est confirmée."
email_body += f"\n\nDate d'inscription: {inscription_date}"
email_body += f"\n\nÉquipe inscrite: {team_members_str}"
email_body += f"\n\nLe tournoi commencera le {tournament.start_date.strftime('%d/%m/%Y')}"
email_body += f" @ {tournament.event.club.name}"
email_body += f"\n\nVoir les informations sur {request.build_absolute_uri(f'/tournament/{tournament.id}/')}"
email_body += "\n\nPour toute question, veuillez contacter votre juge-arbitre. Si vous n'êtes pas à l'origine de cette inscription, merci de le contacter rapidement.\nCeci est un e-mail automatique, veuillez ne pas y répondre."
email_body += "\n\nPour toute question, veuillez contacter votre juge-arbitre. Si vous n'êtes pas à l'origine de cette inscription, merci de le contacter rapidement."
email_body += f"\n{tournament.event.creator.full_name()}\n{tournament.event.creator.email}"
email_body += "\n\nCeci est un e-mail automatique, veuillez ne pas y répondre."
email_body += "\n\nCordialement,\n\nPadel Club"
@ -876,7 +890,9 @@ def unregister_tournament(request, tournament_id):
player_registration = PlayerRegistration.objects.filter(
licence_id__startswith=user_licence_id,
team_registration__tournament_id=tournament_id
team_registration__tournament_id=tournament_id,
team_registration__walk_out=False,
team_registration__unregistered=False,
).first() # Get the first match, if any
@ -884,7 +900,9 @@ def unregister_tournament(request, tournament_id):
if player_registration:
team_registration = player_registration.team_registration # Get the related TeamRegistration
other_player = team_registration.get_other_player(player_registration)
team_registration.delete() # Delete the team registration
team_registration.unregistered = True # Delete the team registration
team_registration.unregistration_date = timezone.now()
team_registration.save()
else:
messages.error(request, "La désincription a échouée. Veuillez contacter le juge-arbitre.")
return redirect('tournament-info', tournament_id=tournament_id)
@ -894,17 +912,18 @@ def unregister_tournament(request, tournament_id):
if tournament and request.user.email: # Ensure we have valid tournament and user email
tournament_details_str = tournament.build_tournament_details_str()
name_str = tournament.build_name_details_str()
email_subject = f"Confirmation de désistement au {tournament_details_str}{name_str}"
email_subject = f"Confirmation de désistement du tournoi{tournament_details_str}{name_str}"
email_body = f"Bonjour,\n\nVous venez de vous désinscrire du tournoi {tournament_details_str}{name_str}"
email_body = f"Bonjour,\n\nVous venez de vous désinscrire du tournoi{tournament_details_str}{name_str}"
email_body += f" du {tournament.start_date.strftime('%d/%m/%Y')}"
email_body += f" au {tournament.event.club.name}"
if other_player is not None:
email_body += f"\n\nVous étiez inscrit avec {other_player.name()}, n'oubliez pas de prévenir votre partenaire."
email_body += f"\n\nVoir les informations sur {request.build_absolute_uri(f'/tournament/{tournament.id}/')}"
email_body += "\n\nPour toute question, veuillez contacter votre juge-arbitre. Si vous n'êtes pas à l'origine de ce désistement, merci de le contacter rapidement.\nCeci est un e-mail automatique, veuillez ne pas y répondre."
email_body += "\n\nCordialement,\n\nPadel Club."
email_body += "\n\nPour toute question, veuillez contacter votre juge-arbitre. Si vous n'êtes pas à l'origine de cette inscription, merci de le contacter rapidement."
email_body += f"\n{tournament.event.creator.full_name()}\n{tournament.event.creator.email}"
email_body += "\n\nCeci est un e-mail automatique, veuillez ne pas y répondre."
email = EmailMessage(
subject=email_subject,

Loading…
Cancel
Save