diff --git a/tournaments/models/enums.py b/tournaments/models/enums.py index 29225cb..1ed426c 100644 --- a/tournaments/models/enums.py +++ b/tournaments/models/enums.py @@ -47,6 +47,28 @@ class FederalLevelCategory(models.IntegerChoices): P1500 = 1500, 'P1500' P2000 = 2000, 'P2000' + @staticmethod + def min_player_rank(level=None, category=None, age_category=None) -> int: + if level == FederalLevelCategory.P25: + if age_category in [FederalAgeCategory.SENIOR, FederalAgeCategory.A45, FederalAgeCategory.A55]: + return 20000 if category == FederalCategory.MEN else 1000 + return 0 + + elif level == FederalLevelCategory.P100: + if age_category in [FederalAgeCategory.SENIOR, FederalAgeCategory.A45, FederalAgeCategory.A55]: + return 2000 if category == FederalCategory.MEN else 300 + return 0 + + elif level == FederalLevelCategory.P250: + if age_category in [FederalAgeCategory.SENIOR, FederalAgeCategory.A45, FederalAgeCategory.A55]: + if category == FederalCategory.MIXED: + return 0 + return 500 if category == FederalCategory.MEN else 100 + return 0 + + return 0 + + class FederalAgeCategory(models.IntegerChoices): UNLISTED = 0, '' A11_12 = 120, 'U12' diff --git a/tournaments/models/player_registration.py b/tournaments/models/player_registration.py index 5b1007c..0e3e628 100644 --- a/tournaments/models/player_registration.py +++ b/tournaments/models/player_registration.py @@ -1,5 +1,5 @@ from django.db import models -from . import TeamRegistration, PlayerSexType, PlayerDataSource, PlayerPaymentType +from . import TeamRegistration, PlayerSexType, PlayerDataSource, PlayerPaymentType, FederalCategory import uuid class PlayerRegistration(models.Model): diff --git a/tournaments/models/tournament.py b/tournaments/models/tournament.py index 571c45b..a9a5b1c 100644 --- a/tournaments/models/tournament.py +++ b/tournaments/models/tournament.py @@ -1076,17 +1076,17 @@ class Tournament(models.Model): name_details.append(self.event.name) name_str = " - ".join(filter(None, name_details)) if name_str: - name_str = f" {name_str}" + name_str = f"{name_str}" return name_str - def user_register_check(self, user): + def player_register_check(self, licence_id): reasons = [] - - if not user.licence_id: + if not licence_id: return None - data, found = get_player_name_from_csv(self.federal_category, user.licence_id) + data, found = get_player_name_from_csv(self.federal_category, licence_id) if not found or not data: + print("not found or not data") return None birth_year = data.get('birth_year', None) @@ -1104,7 +1104,7 @@ class Tournament(models.Model): current_year += 1 user_age = current_year - int(birth_year) - + print(user_age) # Check age category restrictions if self.federal_age_category == FederalAgeCategory.A11_12 and user_age > 12: reasons.append("Ce tournoi est réservé aux -12 ans") @@ -1119,49 +1119,20 @@ class Tournament(models.Model): if self.federal_age_category == FederalAgeCategory.A55 and user_age < 55: reasons.append("Ce tournoi est réservé aux +55 ans") - return reasons if reasons else None - -def user_can_register(self, user): - if not user.licence_id: - return True - - data, found = get_player_name_from_csv(self.federal_category, user.licence_id) - if not found: - return True - if not data: - return True - - birth_year = data.get('birth_year', None) - is_woman = data.get('is_woman', None) - - # Check gender category restrictions - if is_woman is not None and self.federal_category == FederalCategory.WOMEN and is_woman is False: - return False - - if birth_year is None: - return True - - current_year = timezone.now().year - if timezone.now().month >= 9: # Check if current month is September or later - current_year += 1 + addon = 0 + computedRank = int(data.get("rank", 0)) + if is_woman and self.federal_category == FederalCategory.MEN: + addon = FederalCategory.female_in_male_assimilation_addition(computedRank) + computedRank = computedRank + addon - user_age = current_year - int(birth_year) + if computedRank <= self.min_player_rank(): + name = data['first_name'] + " " + data['last_name'].upper() + reasons.append(f"{name} ({licence_id}): trop bien classé pour ce tournoi") - # Check age category restrictions - if self.federal_age_category == FederalAgeCategory.A11_12 and user_age > 12: - return False - if self.federal_age_category == FederalAgeCategory.A13_14 and user_age > 14: - return False - if self.federal_age_category == FederalAgeCategory.A15_16 and user_age > 16: - return False - if self.federal_age_category == FederalAgeCategory.A17_18 and user_age > 18: - return False - if self.federal_age_category == FederalAgeCategory.A45 and user_age < 45: - return False - if self.federal_age_category == FederalAgeCategory.A55 and user_age < 55: - return False + return reasons if reasons else None - return True + def min_player_rank(self): + return FederalLevelCategory.min_player_rank(self.federal_level_category, self.federal_category, self.federal_age_category) class MatchGroup: def __init__(self, name, matches, formatted_schedule): diff --git a/tournaments/services/email_service.py b/tournaments/services/email_service.py index 83e7bbe..1a385c7 100644 --- a/tournaments/services/email_service.py +++ b/tournaments/services/email_service.py @@ -32,9 +32,9 @@ class TournamentEmailService: @staticmethod def _build_email_subject(tournament_details_str, name_str, waiting_list_position): - base_subject = f"Confirmation d'inscription au tournoi{tournament_details_str}{name_str}" + base_subject = f"Confirmation d'inscription au tournoi {tournament_details_str} {name_str}" if waiting_list_position >= 0: - base_subject = f"En liste d'attente du tournoi{tournament_details_str}{name_str}" + base_subject = f"En liste d'attente du tournoi {tournament_details_str} {name_str}" return base_subject @staticmethod @@ -48,9 +48,9 @@ class TournamentEmailService: body_parts.append(f"Bonjour,\n") if waiting_list_position >= 0: - body_parts.append(f"Votre inscription en liste d'attente du tournoi{tournament_details_str}{name_str} est confirmée.") + body_parts.append(f"Votre inscription en liste d'attente du tournoi {tournament_details_str} {name_str} est confirmée.") else: - body_parts.append(f"Votre inscription au tournoi{tournament_details_str}{name_str} est confirmée.") + body_parts.append(f"Votre inscription au tournoi {tournament_details_str} {name_str} est confirmée.") body_parts.extend([ f"\nDate d'inscription: {inscription_date}", @@ -90,7 +90,7 @@ class TournamentEmailService: def _build_unregistration_email_body(tournament, captain, tournament_details_str, name_str, other_player): body_parts = [ "Bonjour,\n", - f"Votre inscription au tournoi{tournament_details_str}{name_str} du {tournament.start_date.strftime('%d/%m/%Y')} @ {tournament.event.club.name} a été annulée" + f"Votre inscription au tournoi {tournament_details_str} {name_str} du {tournament.start_date.strftime('%d/%m/%Y')} @ {tournament.event.club.name} a été annulée" ] if other_player is not None: diff --git a/tournaments/services/tournament_registration.py b/tournaments/services/tournament_registration.py index 389e9c2..8550c14 100644 --- a/tournaments/services/tournament_registration.py +++ b/tournaments/services/tournament_registration.py @@ -1,8 +1,11 @@ from django.utils import timezone from ..forms import TournamentRegistrationForm, AddPlayerForm -from ..validators import TournamentRegistrationValidator from ..repositories import TournamentRegistrationRepository from .email_service import TournamentEmailService +from django.contrib import messages +from ..validators import LicenseValidator +from ..utils.player_search import get_player_name_from_csv +from tournaments.models import PlayerRegistration class TournamentRegistrationService: def __init__(self, request, tournament): @@ -10,7 +13,6 @@ class TournamentRegistrationService: self.tournament = tournament self.context = {} self.repository = TournamentRegistrationRepository() - self.validator = TournamentRegistrationValidator() self.email_service = TournamentEmailService() def initialize_context(self): @@ -38,11 +40,25 @@ class TournamentRegistrationService: return player_data = self.context['add_player_form'].cleaned_data - if not self.validator.validate_player_license(self.request, self.tournament, player_data): + licence_id = player_data.get('licence_id', '').upper() + + # Validate license + if not self._validate_license(licence_id): return - self.add_player_to_session(player_data) - self.context['add_player_form'] = AddPlayerForm() + # Check for duplicate players + if self._is_duplicate_player(licence_id): + return + + # Check if player is already registered in tournament + if self._is_already_registered(licence_id): + return + + # Handle player data + if self.context['add_player_form'].names_is_valid(): + self._handle_valid_names(player_data) + else: + self._handle_invalid_names(licence_id, player_data) def handle_team_registration(self): if not self.context['team_form'].is_valid(): @@ -107,8 +123,8 @@ class TournamentRegistrationService: player_data = self._get_authenticated_user_data() if player_data: - self.context['current_players'] = self.request.session.get('team_registration', []) self.request.session['team_registration'].insert(0, player_data) + self.context['current_players'] = self.request.session.get('team_registration', []) self.request.session.modified = True def _handle_user_without_license(self): @@ -147,3 +163,123 @@ class TournamentRegistrationService: }) return player_data + + def _validate_license(self, licence_id): + validator = LicenseValidator(licence_id) + + if validator.validate_license() is False and self.tournament.license_is_required: + if not licence_id: + message = ("Le numéro de licence est obligatoire." + if not self.request.session.get('team_registration', []) + else "Le numéro de licence de votre partenaire est obligatoire.") + messages.error(self.request, message) + else: + # computed_license_key = validator.computed_license_key + # messages.error(self.request, f"Le numéro de licence est invalide, la lettre ne correspond pas. {computed_license_key}") + messages.error(self.request, "Le numéro de licence est invalide, la lettre ne correspond pas.") + return False + return True + + def _is_duplicate_player(self, licence_id): + existing_players = [player['licence_id'] for player in self.request.session.get('team_registration', [])] + if licence_id in existing_players: + messages.error(self.request, "Ce joueur est déjà dans l'équipe.") + return True + return False + + def _is_already_registered(self, licence_id): + validator = LicenseValidator(licence_id) + if (validator.validate_license() and + self._license_already_registered(validator.stripped_license) and + self.tournament.license_is_required): + messages.error(self.request, "Un joueur avec ce numéro de licence est déjà inscrit dans une équipe.") + return True + return False + + def _handle_valid_names(self, player_data): + if player_data.get('rank') is None: + self._set_default_rank(player_data) + + self.add_player_to_session(player_data) + + if self.request.user.is_authenticated and self.request.user.licence_id is None: + self._update_user_license(player_data.get('licence_id')) + + self.context['add_player_form'] = AddPlayerForm() + + def _handle_invalid_names(self, licence_id, player_data): + if not self.context['add_player_form'].first_tournament: + data, found = get_player_name_from_csv(self.tournament.federal_category, licence_id) + if found and data: + self._update_player_data_from_csv(player_data, data) + player_check = self._player_check(player_data) + if player_check == True: + self.add_player_to_session(player_data) + self.context['add_player_form'] = AddPlayerForm() + else: + return + else: + self._handle_first_tournament_case(data) + + def _set_default_rank(self, player_data): + if self.request.session.get('last_rank') is None: + data, found = get_player_name_from_csv(self.tournament.federal_category, None) + if data: + self.request.session['last_rank'] = data['rank'] + self.request.session['is_woman'] = data['is_woman'] + self.request.session.modified = True + + player_data['rank'] = self.request.session.get('last_rank', 0) + player_data['is_woman'] = self.request.session.get('is_woman', False) + + def _update_user_license(self, licence_id): + self.request.session['user_without_licence'] = False + self.request.user.licence_id = LicenseValidator(licence_id).computed_licence_id + self.request.user.save() + + def _update_player_data_from_csv(self, player_data, csv_data): + player_data.update({ + 'first_name': csv_data['first_name'], + 'last_name': csv_data['last_name'], + 'rank': csv_data['rank'], + 'is_woman': csv_data['is_woman'], + 'points': csv_data.get('points'), + 'assimilation': csv_data.get('assimilation'), + 'tournament_count': csv_data.get('tournament_count'), + 'ligue_name': csv_data.get('ligue_name'), + 'club_name': csv_data.get('club_name'), + 'birth_year': csv_data.get('birth_year') + }) + + def _handle_first_tournament_case(self, data): + if data: + self.request.session['last_rank'] = data['rank'] + self.request.session['is_woman'] = data['is_woman'] + self.request.session.modified = True + + self.context['add_player_form'].first_tournament = True + + if not self.context['add_player_form'].names_is_valid(): + message = ("Pour confirmer votre inscription votre prénom et votre nom sont obligatoires." + if not self.request.session.get('team_registration', []) + else "Pour rajouter un partenaire, son prénom et son nom sont obligatoires.") + messages.error(self.request, message) + + def _player_check(self, player_data): + licence_id = player_data['licence_id'].upper() + validator = LicenseValidator(licence_id) + is_license_valid = validator.validate_license() + + player_register_check = self.tournament.player_register_check(licence_id) + if is_license_valid and player_register_check is not None: + for message in player_register_check: + messages.error(self.request, message) + return False + + return True + + def _license_already_registered(self, stripped_license): + return PlayerRegistration.objects.filter( + team_registration__tournament=self.tournament, + licence_id__startswith=stripped_license + ).exists() diff --git a/tournaments/templates/register_tournament.html b/tournaments/templates/register_tournament.html index 3a42e1a..f8554f9 100644 --- a/tournaments/templates/register_tournament.html +++ b/tournaments/templates/register_tournament.html @@ -21,8 +21,10 @@
{% if registration_successful %} -

Merci, l'inscription a bien été envoyé au juge-arbitre.

-

Un email de confirmation a été envoyé à {{ user.email }} pour confirmer votre inscription. Pensez à vérifier vos spams si vous ne recevez pas l'email. En cas de problème, contactez le juge-arbitre.

+

Merci, l'inscription a bien été envoyée au juge-arbitre.

+

+ Un email de confirmation a été envoyée à {{ user.email }} pour confirmer votre inscription. Pensez à vérifier vos spams si vous ne recevez pas l'email. En cas de problème, contactez le juge-arbitre. +

{% else %}
{% csrf_token %} diff --git a/tournaments/templates/tournaments/tournament_info.html b/tournaments/templates/tournaments/tournament_info.html index 8a29253..ce77a9b 100644 --- a/tournaments/templates/tournaments/tournament_info.html +++ b/tournaments/templates/tournaments/tournament_info.html @@ -79,7 +79,7 @@ {% 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 %} - {% if user_register_check is None %} + {% if player_register_check is None %}

S'inscrire @@ -91,7 +91,7 @@ Vous ne pouvez pas vous inscrire à ce tournoi.
- {% for reason in user_register_check %} + {% for reason in player_register_check %}
{{ reason }}
{% endfor %}
diff --git a/tournaments/validators.py b/tournaments/validators.py deleted file mode 100644 index d6ffdc5..0000000 --- a/tournaments/validators.py +++ /dev/null @@ -1,49 +0,0 @@ -from django.contrib import messages -from .models import PlayerRegistration -from tournaments.utils.licence_validator import LicenseValidator -# Remove unused import since get_player_name_from_csv is not used in this class - -class TournamentRegistrationValidator: - @staticmethod - def validate_player_license(request, tournament, player_data): - licence_id = player_data['licence_id'].upper() - validator = LicenseValidator(licence_id) - - if not validator.validate_license() and tournament.license_is_required: - TournamentRegistrationValidator._handle_invalid_license(request, licence_id) - return False - - if validator.validate_license() and TournamentRegistrationValidator._is_duplicate_license( - licence_id, request.session['team_registration']): - messages.error(request, "Ce joueur est déjà dans l'équipe.") - return False - - if validator.validate_license() and tournament.license_is_required: - stripped_license = validator.stripped_license - if TournamentRegistrationValidator._license_already_registered(stripped_license, tournament): - messages.error(request, "Un joueur avec ce numéro de licence est déjà inscrit dans une équipe.") - return False - - return True - - @staticmethod - def _handle_invalid_license(request, licence_id): - if not licence_id: - if not request.session.get('team_registration'): - messages.error(request, "Le numéro de licence est obligatoire.") - else: - messages.error(request, "Le numéro de licence de votre partenaire est obligatoire.") - else: - messages.error(request, "Le numéro de licence est invalide, la lettre ne correspond pas.") - - @staticmethod - def _is_duplicate_license(licence_id, team_registration): - existing_licenses = [player['licence_id'] for player in team_registration] - return licence_id in existing_licenses - - @staticmethod - def _license_already_registered(stripped_license, tournament): - return PlayerRegistration.objects.filter( - team_registration__tournament=tournament, - licence_id__startswith=stripped_license - ).exists() diff --git a/tournaments/views.py b/tournaments/views.py index e0a78be..13cf31e 100644 --- a/tournaments/views.py +++ b/tournaments/views.py @@ -130,13 +130,13 @@ def tournament_info(request, tournament_id): registered_user = None team_registration = None is_captain = False - user_register_check = None + player_register_check = None if request.user.is_authenticated: # Assuming user's licence_id is stored in the user profile (e.g., request.user.licence_id) user_licence_id = request.user.licence_id - - if user_licence_id is not None: + player_register_check = tournament.player_register_check(user_licence_id) + if user_licence_id is not None and player_register_check is None: validator = LicenseValidator(user_licence_id) stripped_license = validator.stripped_license # Check if there is a PlayerRegistration for this user in this tournament @@ -150,14 +150,12 @@ def tournament_info(request, tournament_id): if registered_user: is_captain = registered_user.captain team_registration = registered_user.team_registration - else: - user_register_check = tournament.user_register_check(request.user) return render(request, 'tournaments/tournament_info.html', { 'tournament': tournament, 'team': team_registration, 'is_captain': is_captain, - 'user_register_check': user_register_check + 'player_register_check': player_register_check })