From e5cc96bae6ee360659ca4e067ba410e1aa72e9a4 Mon Sep 17 00:00:00 2001
From: Raz
Date: Tue, 10 Dec 2024 09:46:49 +0100
Subject: [PATCH] improve online register
---
.../0100_playerregistration_coach_and_more.py | 28 +++++
tournaments/models/__init__.py | 2 +-
tournaments/models/enums.py | 26 ++++
tournaments/models/player_registration.py | 1 +
tournaments/models/team_registration.py | 6 +-
tournaments/models/tournament.py | 116 ++++++++++++++++--
.../tournaments/tournament_info.html | 40 ++++--
.../templates/tournaments/tournament_row.html | 6 +-
tournaments/views.py | 3 +
9 files changed, 202 insertions(+), 26 deletions(-)
create mode 100644 tournaments/migrations/0100_playerregistration_coach_and_more.py
diff --git a/tournaments/migrations/0100_playerregistration_coach_and_more.py b/tournaments/migrations/0100_playerregistration_coach_and_more.py
new file mode 100644
index 0000000..ae642b3
--- /dev/null
+++ b/tournaments/migrations/0100_playerregistration_coach_and_more.py
@@ -0,0 +1,28 @@
+# Generated by Django 4.2.11 on 2024-12-10 08:14
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('tournaments', '0099_remove_tournament_display_entry_fee_information'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='playerregistration',
+ name='coach',
+ field=models.BooleanField(default=False),
+ ),
+ migrations.AddField(
+ model_name='teamregistration',
+ name='unregistered',
+ field=models.BooleanField(default=False),
+ ),
+ migrations.AddField(
+ model_name='teamregistration',
+ name='unregistration_date',
+ field=models.DateTimeField(blank=True, null=True),
+ ),
+ ]
diff --git a/tournaments/models/__init__.py b/tournaments/models/__init__.py
index ff8321d..d385a4e 100644
--- a/tournaments/models/__init__.py
+++ b/tournaments/models/__init__.py
@@ -2,7 +2,7 @@ from .custom_user import CustomUser
from .club import Club
from .court import Court
from .date_interval import DateInterval
-from .enums import TournamentPayment, FederalCategory, FederalLevelCategory, FederalAgeCategory, FederalMatchCategory
+from .enums import TournamentPayment, FederalCategory, FederalLevelCategory, FederalAgeCategory, FederalMatchCategory, OnlineRegistrationStatus
from .player_enums import PlayerSexType, PlayerDataSource, PlayerPaymentType
from .event import Event
from .tournament import Tournament, TeamSummon, TeamSortingType, TeamItem
diff --git a/tournaments/models/enums.py b/tournaments/models/enums.py
index c5099cd..255df99 100644
--- a/tournaments/models/enums.py
+++ b/tournaments/models/enums.py
@@ -85,3 +85,29 @@ class FederalMatchCategory(models.IntegerChoices):
return 1
else:
return 3
+
+
+class OnlineRegistrationStatus(models.IntegerChoices):
+ OPEN = 1, 'Open'
+ 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'
+
+ def status_localized(self) -> str:
+ status_map = {
+ OnlineRegistrationStatus.OPEN: "Inscription ouverte",
+ 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_FULL: "Liste d'attente complète",
+ OnlineRegistrationStatus.IN_PROGRESS: "Tournoi en cours",
+ OnlineRegistrationStatus.ENDED_WITH_RESULTS: "Tournoi terminé"
+ }
+ return status_map.get(self, "")
diff --git a/tournaments/models/player_registration.py b/tournaments/models/player_registration.py
index 7e9e6ec..5b1007c 100644
--- a/tournaments/models/player_registration.py
+++ b/tournaments/models/player_registration.py
@@ -34,6 +34,7 @@ class PlayerRegistration(models.Model):
source = models.IntegerField(choices=PlayerDataSource.choices, null=True, blank=True)
has_arrived = models.BooleanField(default=False)
captain = models.BooleanField(default=False)
+ coach = models.BooleanField(default=False)
def __str__(self):
return self.name()
diff --git a/tournaments/models/team_registration.py b/tournaments/models/team_registration.py
index 6c09558..af2774a 100644
--- a/tournaments/models/team_registration.py
+++ b/tournaments/models/team_registration.py
@@ -29,7 +29,8 @@ class TeamRegistration(models.Model):
final_ranking = models.IntegerField(null=True, blank=True)
points_earned = models.IntegerField(null=True, blank=True)
-
+ unregistered = models.BooleanField(default=False)
+ unregistration_date = models.DateTimeField(null=True, blank=True)
def __str__(self):
if self.name:
@@ -115,3 +116,6 @@ class TeamRegistration(models.Model):
else:
# print("no date")
return None
+
+ def out_of_tournament(self):
+ return self.walk_out or self.unregistered
diff --git a/tournaments/models/tournament.py b/tournaments/models/tournament.py
index 12ca9d6..bb10fd8 100644
--- a/tournaments/models/tournament.py
+++ b/tournaments/models/tournament.py
@@ -5,7 +5,7 @@ from typing import TYPE_CHECKING
if TYPE_CHECKING:
from tournaments.models import group_stage
-from . import Event, TournamentPayment, FederalMatchCategory, FederalCategory, FederalLevelCategory, FederalAgeCategory
+from . import Event, TournamentPayment, FederalMatchCategory, FederalCategory, FederalLevelCategory, FederalAgeCategory, OnlineRegistrationStatus
import uuid
from django.utils import timezone, formats
from datetime import datetime, timedelta
@@ -219,12 +219,19 @@ class Tournament(models.Model):
return f"{len(teams)} {word}"
else:
return None
+
+ registration_status = None
+ if self.online_register_is_enabled() is True:
+ registration_status = self.get_online_registration_status().status_localized()
if teams is not None and len(teams) > 0:
word = "inscription"
if len(teams) > 1:
word = word + "s"
- return f"{len(teams)} {word}"
+ if registration_status is not None:
+ return f"{registration_status}\n{len(teams)} {word}"
else:
+ if registration_status is not None:
+ return f"{registration_status}"
return None
def name_and_event(self):
@@ -277,6 +284,7 @@ class Tournament(models.Model):
def rankings(self):
rankings = []
for team_registration in self.teamregistration_set.all():
+
if team_registration.walk_out is False and team_registration.final_ranking is not None:
names = team_registration.team_names()
ranking = team_registration.final_ranking
@@ -309,8 +317,7 @@ class Tournament(models.Model):
if team_registration.registration_date is None:
is_valid = True
# print(f"Is valid: {is_valid}")
-
- if team_registration.walk_out is False:
+ if team_registration.out_of_tournament() is False:
team = TeamItem(team_registration)
# print(f"Created team: {team}")
if team_registration.group_stage_position is not None:
@@ -880,28 +887,117 @@ class Tournament(models.Model):
return False
return True
+ def options_online_registration(self):
+ options = []
+
+ # Date d'ouverture
+ if self.opening_registration_date:
+ date = formats.date_format(self.opening_registration_date, format='j F Y H:i')
+ options.append(f"Ouverture des inscriptions le {date}")
+
+ # Date limite
+ if self.registration_date_limit:
+ date = formats.date_format(self.registration_date_limit, format='j F Y H:i')
+ options.append(f"Clôture des inscriptions le {date}")
+
+ # Cible d'équipes
+ if self.target_team_count:
+ options.append(f"Maximum {self.target_team_count} équipes")
+
+ # Liste d'attente
+ if self.waiting_list_limit:
+ options.append(f"Liste d'attente limitée à {self.waiting_list_limit} équipes")
+
+ # Options d'inscription
+ if self.account_is_required:
+ options.append("Compte requis")
+ if self.license_is_required:
+ options.append("Licence requise")
+
+ # Joueurs par équipe
+ min_players = self.minimum_player_per_team
+ max_players = self.maximum_player_per_team
+ if min_players == max_players:
+ options.append(f"{min_players} joueurs par équipe")
+ else:
+ options.append(f"Entre {min_players} et {max_players} joueurs par équipe")
+
+ return options
+
def online_register_is_enabled(self):
if self.supposedly_in_progress():
return False
if self.end_date is not None:
return False
- now = datetime.now()
+ now = timezone.now()
+
# Check if online registration is enabled
if not self.enable_online_registration:
return False
# Check opening registration date
- if self.opening_registration_date is not None and now < self.opening_registration_date:
- return False
+ if self.opening_registration_date is not None:
+ timezoned_datetime = timezone.localtime(self.opening_registration_date)
+ if now < timezoned_datetime:
+ return False
# Check registration date limit
- if self.registration_date_limit is not None and now > self.registration_date_limit:
- return False
+ if self.registration_date_limit is not None:
+ timezoned_datetime = timezone.localtime(self.registration_date_limit)
+ if now > timezoned_datetime:
+ return False
- # All conditions are satisfied
+ # Check target team count and waiting list limit
+ if self.target_team_count is not None:
+ current_team_count = len([tr for tr in self.teamregistration_set.all() if tr.out_of_tournament() is False])
+ 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 False
return True
+ def get_online_registration_status(self):
+ if self.supposedly_in_progress():
+ return OnlineRegistrationStatus.IN_PROGRESS
+ if self.end_date is not None:
+ return OnlineRegistrationStatus.ENDED_WITH_RESULTS
+
+ now = timezone.now()
+
+ if self.opening_registration_date is not None:
+ timezoned_datetime = timezone.localtime(self.opening_registration_date)
+ if now < timezoned_datetime:
+ return OnlineRegistrationStatus.NOT_STARTED
+
+ if self.registration_date_limit is not None:
+ timezoned_datetime = timezone.localtime(self.registration_date_limit)
+ if now > timezoned_datetime:
+ return OnlineRegistrationStatus.ENDED
+
+ if self.target_team_count is not None:
+ # Get all team registrations excluding walk_outs
+ current_team_count = len([tr for tr in self.teamregistration_set.all() if tr.out_of_tournament() is False])
+ 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
+ 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.OPEN
+
+
class MatchGroup:
def __init__(self, name, matches, formatted_schedule):
self.name = name
diff --git a/tournaments/templates/tournaments/tournament_info.html b/tournaments/templates/tournaments/tournament_info.html
index 5beae08..40e7516 100644
--- a/tournaments/templates/tournaments/tournament_info.html
+++ b/tournaments/templates/tournaments/tournament_info.html
@@ -48,23 +48,37 @@
{% if tournament.online_register_is_enabled %}
-
Statut
- {% if tournament.registration_count_display %}
- {{ tournament.registration_count_display }}
- {% else %}
- Aucune équipe inscrite
+ Inscription en ligne
+
+ {% if tournament.options_online_registration %}
+
+ {% for option in tournament.options_online_registration %}
+ - {{ option }}
+ {% endfor %}
+
{% endif %}
- {% endif %}
- {% if tournament.online_register_is_enabled and team is None %}
+
+
+ {% if tournament.registration_count_display %}
+
{{ tournament.registration_count_display }}
+ {% else %}
+
Aucune équipe inscrite
+ {% endif %}
+
+
-
- L'inscription en ligne est possible.
-
+
+ {{ tournament.get_online_registration_status.status_localized }}
+
+ {% endif %}
+
+ {% if tournament.online_register_is_enabled and team is None %}
+
{% if tournament.account_is_required is False or user.is_authenticated and user.is_active %}
@@ -114,7 +128,7 @@
Inscrit le {{ team.registration_date }}
- {% if is_captain %}
+
+
+
{% endif %}
{% endif %}
diff --git a/tournaments/templates/tournaments/tournament_row.html b/tournaments/templates/tournaments/tournament_row.html
index 6d3492b..d953fc2 100644
--- a/tournaments/templates/tournaments/tournament_row.html
+++ b/tournaments/templates/tournaments/tournament_row.html
@@ -26,12 +26,14 @@
{% if tournament.tournament_status_display %}
- {{ tournament.tournament_status_display }}
+
+ {{ tournament.tournament_status_display|linebreaksbr }}
+
{% endif %}
{{ tournament.formatted_start_date }}
{% if tournament.tournament_status_display %}
-
{{ tournament.tournament_status_display }}
+
{{ tournament.tournament_status_display|linebreaksbr }}
{% endif %}
diff --git a/tournaments/views.py b/tournaments/views.py
index eddf5c8..b28937a 100644
--- a/tournaments/views.py
+++ b/tournaments/views.py
@@ -852,6 +852,9 @@ def unregister_tournament(request, tournament_id):
def validate_license_id(licence_id, tournament):
teams = TeamRegistration.objects.filter(tournament=tournament)
+ # Filter out walkouts and unregistered teams
+ teams = teams.filter(walk_out=False, unregistered=False)
+
# Check if any player in any team in the tournament already has this licence_id
# Normalize the licence ID before querying
# Loop through each team and check if any of its players has the same licence_id