bug fix and add rank check

online_registration
Raz 11 months ago
parent be61151ede
commit d2503121e4
  1. 22
      tournaments/models/enums.py
  2. 2
      tournaments/models/player_registration.py
  3. 63
      tournaments/models/tournament.py
  4. 10
      tournaments/services/email_service.py
  5. 148
      tournaments/services/tournament_registration.py
  6. 6
      tournaments/templates/register_tournament.html
  7. 4
      tournaments/templates/tournaments/tournament_info.html
  8. 49
      tournaments/validators.py
  9. 10
      tournaments/views.py

@ -47,6 +47,28 @@ class FederalLevelCategory(models.IntegerChoices):
P1500 = 1500, 'P1500' P1500 = 1500, 'P1500'
P2000 = 2000, 'P2000' 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): class FederalAgeCategory(models.IntegerChoices):
UNLISTED = 0, '' UNLISTED = 0, ''
A11_12 = 120, 'U12' A11_12 = 120, 'U12'

@ -1,5 +1,5 @@
from django.db import models from django.db import models
from . import TeamRegistration, PlayerSexType, PlayerDataSource, PlayerPaymentType from . import TeamRegistration, PlayerSexType, PlayerDataSource, PlayerPaymentType, FederalCategory
import uuid import uuid
class PlayerRegistration(models.Model): class PlayerRegistration(models.Model):

@ -1076,17 +1076,17 @@ class Tournament(models.Model):
name_details.append(self.event.name) name_details.append(self.event.name)
name_str = " - ".join(filter(None, name_details)) name_str = " - ".join(filter(None, name_details))
if name_str: if name_str:
name_str = f" {name_str}" name_str = f"{name_str}"
return name_str return name_str
def user_register_check(self, user): def player_register_check(self, licence_id):
reasons = [] reasons = []
if not licence_id:
if not user.licence_id:
return None 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: if not found or not data:
print("not found or not data")
return None return None
birth_year = data.get('birth_year', None) birth_year = data.get('birth_year', None)
@ -1104,7 +1104,7 @@ class Tournament(models.Model):
current_year += 1 current_year += 1
user_age = current_year - int(birth_year) user_age = current_year - int(birth_year)
print(user_age)
# Check age category restrictions # Check age category restrictions
if self.federal_age_category == FederalAgeCategory.A11_12 and user_age > 12: if self.federal_age_category == FederalAgeCategory.A11_12 and user_age > 12:
reasons.append("Ce tournoi est réservé aux -12 ans") 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: if self.federal_age_category == FederalAgeCategory.A55 and user_age < 55:
reasons.append("Ce tournoi est réservé aux +55 ans") reasons.append("Ce tournoi est réservé aux +55 ans")
return reasons if reasons else None addon = 0
computedRank = int(data.get("rank", 0))
def user_can_register(self, user): if is_woman and self.federal_category == FederalCategory.MEN:
if not user.licence_id: addon = FederalCategory.female_in_male_assimilation_addition(computedRank)
return True computedRank = computedRank + addon
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
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 return reasons if reasons else None
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 True def min_player_rank(self):
return FederalLevelCategory.min_player_rank(self.federal_level_category, self.federal_category, self.federal_age_category)
class MatchGroup: class MatchGroup:
def __init__(self, name, matches, formatted_schedule): def __init__(self, name, matches, formatted_schedule):

@ -32,9 +32,9 @@ class TournamentEmailService:
@staticmethod @staticmethod
def _build_email_subject(tournament_details_str, name_str, waiting_list_position): 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: 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 return base_subject
@staticmethod @staticmethod
@ -48,9 +48,9 @@ class TournamentEmailService:
body_parts.append(f"Bonjour,\n") body_parts.append(f"Bonjour,\n")
if waiting_list_position >= 0: 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: 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([ body_parts.extend([
f"\nDate d'inscription: {inscription_date}", 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): def _build_unregistration_email_body(tournament, captain, tournament_details_str, name_str, other_player):
body_parts = [ body_parts = [
"Bonjour,\n", "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: if other_player is not None:

@ -1,8 +1,11 @@
from django.utils import timezone from django.utils import timezone
from ..forms import TournamentRegistrationForm, AddPlayerForm from ..forms import TournamentRegistrationForm, AddPlayerForm
from ..validators import TournamentRegistrationValidator
from ..repositories import TournamentRegistrationRepository from ..repositories import TournamentRegistrationRepository
from .email_service import TournamentEmailService 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: class TournamentRegistrationService:
def __init__(self, request, tournament): def __init__(self, request, tournament):
@ -10,7 +13,6 @@ class TournamentRegistrationService:
self.tournament = tournament self.tournament = tournament
self.context = {} self.context = {}
self.repository = TournamentRegistrationRepository() self.repository = TournamentRegistrationRepository()
self.validator = TournamentRegistrationValidator()
self.email_service = TournamentEmailService() self.email_service = TournamentEmailService()
def initialize_context(self): def initialize_context(self):
@ -38,11 +40,25 @@ class TournamentRegistrationService:
return return
player_data = self.context['add_player_form'].cleaned_data 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 return
self.add_player_to_session(player_data) # Check for duplicate players
self.context['add_player_form'] = AddPlayerForm() 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): def handle_team_registration(self):
if not self.context['team_form'].is_valid(): if not self.context['team_form'].is_valid():
@ -107,8 +123,8 @@ class TournamentRegistrationService:
player_data = self._get_authenticated_user_data() player_data = self._get_authenticated_user_data()
if player_data: if player_data:
self.context['current_players'] = self.request.session.get('team_registration', [])
self.request.session['team_registration'].insert(0, player_data) self.request.session['team_registration'].insert(0, player_data)
self.context['current_players'] = self.request.session.get('team_registration', [])
self.request.session.modified = True self.request.session.modified = True
def _handle_user_without_license(self): def _handle_user_without_license(self):
@ -147,3 +163,123 @@ class TournamentRegistrationService:
}) })
return player_data 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()

@ -21,8 +21,10 @@
<div class="bubble"> <div class="bubble">
{% if registration_successful %} {% if registration_successful %}
<p>Merci, l'inscription a bien été envoyé au juge-arbitre.</p> <p>Merci, l'inscription a bien été envoyée au juge-arbitre.</p>
<p>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.</p> <p style="text-align: justify;">
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.
</p>
{% else %} {% else %}
<form method="post"> <form method="post">
{% csrf_token %} {% csrf_token %}

@ -79,7 +79,7 @@
{% if tournament.online_register_is_enabled and team is None %} {% 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 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 %}
<p> <p>
<div> <div>
<a href="{% url 'register_tournament' tournament.id %}" class="rounded-button">S'inscrire</a> <a href="{% url 'register_tournament' tournament.id %}" class="rounded-button">S'inscrire</a>
@ -91,7 +91,7 @@
Vous ne pouvez pas vous inscrire à ce tournoi. Vous ne pouvez pas vous inscrire à ce tournoi.
</div> </div>
<div class="alert"> <div class="alert">
{% for reason in user_register_check %} {% for reason in player_register_check %}
<div>{{ reason }}</div> <div>{{ reason }}</div>
{% endfor %} {% endfor %}
</div> </div>

@ -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()

@ -130,13 +130,13 @@ def tournament_info(request, tournament_id):
registered_user = None registered_user = None
team_registration = None team_registration = None
is_captain = False is_captain = False
user_register_check = None player_register_check = None
if request.user.is_authenticated: if request.user.is_authenticated:
# Assuming user's licence_id is stored in the user profile (e.g., request.user.licence_id) # Assuming user's licence_id is stored in the user profile (e.g., request.user.licence_id)
user_licence_id = request.user.licence_id user_licence_id = request.user.licence_id
player_register_check = tournament.player_register_check(user_licence_id)
if user_licence_id is not None: if user_licence_id is not None and player_register_check is None:
validator = LicenseValidator(user_licence_id) validator = LicenseValidator(user_licence_id)
stripped_license = validator.stripped_license stripped_license = validator.stripped_license
# Check if there is a PlayerRegistration for this user in this tournament # 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: if registered_user:
is_captain = registered_user.captain is_captain = registered_user.captain
team_registration = registered_user.team_registration team_registration = registered_user.team_registration
else:
user_register_check = tournament.user_register_check(request.user)
return render(request, 'tournaments/tournament_info.html', { return render(request, 'tournaments/tournament_info.html', {
'tournament': tournament, 'tournament': tournament,
'team': team_registration, 'team': team_registration,
'is_captain': is_captain, 'is_captain': is_captain,
'user_register_check': user_register_check 'player_register_check': player_register_check
}) })

Loading…
Cancel
Save