From a19afb22991abbe9c307d45117c89ecb66b52ac5 Mon Sep 17 00:00:00 2001 From: Raz Date: Thu, 17 Apr 2025 17:47:33 +0200 Subject: [PATCH] fix stuff --- tournaments/models/team_registration.py | 18 +++++++++--- tournaments/models/tournament.py | 12 ++++++-- tournaments/services/email_service.py | 37 +++++++++++++++++++++++-- tournaments/signals.py | 37 +++++++++++++++---------- tournaments/tasks.py | 16 +++++++---- 5 files changed, 93 insertions(+), 27 deletions(-) diff --git a/tournaments/models/team_registration.py b/tournaments/models/team_registration.py index 2b039f8..66d0276 100644 --- a/tournaments/models/team_registration.py +++ b/tournaments/models/team_registration.py @@ -310,12 +310,22 @@ class TeamRegistration(SideStoreModel): for p in self.players_sorted_by_rank: if p.registered_online: p.time_to_confirm = ttc - if ttc is None: - p.registration_status = RegistrationStatus.WAITING - else: - p.registration_status = RegistrationStatus.PENDING + p.registration_status = RegistrationStatus.PENDING p.save() + def cancel_time_to_confirm(self): + for p in self.players_sorted_by_rank: + if p.registered_online: + save = False + if p.time_to_confirm is not None: + save = True + p.time_to_confirm = None + if p.registration_status == RegistrationStatus.PENDING: + save = True + p.registration_status = RegistrationStatus.WAITING + if save: + p.save() + def needs_confirmation(self): """Check if this team needs to confirm their registration""" # Check if any player has status PENDING and is registered online diff --git a/tournaments/models/tournament.py b/tournaments/models/tournament.py index 808e0e1..f7fe3f0 100644 --- a/tournaments/models/tournament.py +++ b/tournaments/models/tournament.py @@ -1599,13 +1599,13 @@ class Tournament(BaseModel): # 24 hours before tournament: 7am - 10pm business_start_hour = 7 business_end_hour = 22 - minutes_to_confirm = config.MINIMUM_RESPONSE_TIME + minutes_to_confirm = config['MINIMUM_RESPONSE_TIME'] if hours_until_tournament <= 12: # 12 hours before tournament: 6am - 1am (next day) business_start_hour = 6 business_end_hour = 25 # 1am next day (25 in 24-hour format) - minutes_to_confirm = config.MINIMUM_RESPONSE_TIME + minutes_to_confirm = config['MINIMUM_RESPONSE_TIME'] live_testing = getattr(settings, 'LIVE_TESTING', False) # Divide by 10 if LIVE_TESTING is enabled @@ -1650,6 +1650,11 @@ class Tournament(BaseModel): print(f"Raw Deadline is after tournament_start_date_minus_five: {raw_deadline}, {tournament_start_date_minus_five}") raw_deadline = tournament_start_date_minus_five + raw_deadline = raw_deadline.replace( + second=0, + microsecond=0 + ) + print(f"Live testing: {live_testing}") print(f"Current time: {current_time}") print(f"Minutes to confirm: {minutes_to_confirm}") @@ -1659,6 +1664,9 @@ class Tournament(BaseModel): return raw_deadline + def is_online_registration_irrevelant(self): + return self.enable_time_to_confirm is False or self.has_started() or self.has_ended() or self.is_canceled() or self.is_deleted + @property def week_day(self): """Return the weekday name (e.g., 'Monday')""" diff --git a/tournaments/services/email_service.py b/tournaments/services/email_service.py index 27247b2..98f5c5f 100644 --- a/tournaments/services/email_service.py +++ b/tournaments/services/email_service.py @@ -16,13 +16,15 @@ class TeamEmailType(Enum): OUT_OF_WALKOUT_WAITING_LIST = "out_of_walkout_waiting_list" WALKOUT = "walkout" UNEXPECTED_OUT_OF_TOURNAMENT = 'unexpected_out_of_tournament' + REQUIRES_TIME_CONFIRMATION = 'requires_time_confirmation' def email_subject(self, time_to_confirm=None) -> str: confirmation_types = [ self.REGISTERED, self.OUT_OF_WAITING_LIST, self.IN_TOURNAMENT_STRUCTURE, - self.OUT_OF_WALKOUT_IS_IN + self.OUT_OF_WALKOUT_IS_IN, + self.REQUIRES_TIME_CONFIRMATION, ] if time_to_confirm and self in confirmation_types: @@ -33,6 +35,7 @@ class TeamEmailType(Enum): self.WAITING_LIST: "Liste d'attente", self.UNREGISTERED: "Désistement", self.OUT_OF_WAITING_LIST: "Participation confirmée", + self.REQUIRES_TIME_CONFIRMATION: "Participation en attente de confirmation", self.TOURNAMENT_CANCELED: "Tournoi annulé", self.IN_TOURNAMENT_STRUCTURE: "Participation confirmée", self.OUT_OF_TOURNAMENT_STRUCTURE: "Participation annulée", @@ -173,6 +176,32 @@ class TournamentEmailService: return "".join(body_parts) + @staticmethod + def _build_requires_confirmation_email_body(tournament, captain, tournament_details_str, other_player): + body_parts = [ + "Bonjour,\n\n", + f"Vous n'avez toujours pas confirmé votre participation au tournoi {tournament_details_str}, prévu le {tournament.formatted_start_date()} au club {tournament.event.club.name}" + ] + + absolute_url = f"https://padelclub.app/tournament/{tournament.id}/info" + link_text = "accéder au tournoi" + absolute_url = f'{link_text}' + + if other_player is not None: + body_parts.append( + f"\nVoici le partenaire indiqué dans l'inscription : {other_player.name()}, n'oubliez pas de le prévenir." + ) + + confirmation_message = TournamentEmailService._build_confirmation_message(captain, tournament, absolute_url) + body_parts.append(confirmation_message) + + body_parts.extend([ + f"\n\n{TournamentEmailService._format_umpire_contact(tournament)}", + "\n\nCeci est un e-mail automatique, veuillez ne pas y répondre." + ]) + + return "".join(body_parts) + @staticmethod def _build_tournament_cancellation_email_body(tournament, player, tournament_details_str, other_player): body_parts = [ @@ -405,7 +434,7 @@ class TournamentEmailService: warning_text = f"⚠️ ATTENTION : Vous avez jusqu'au {deadline_str} pour confirmer votre participation. Passé ce délai, votre place sera automatiquement proposée à l'équipe suivante sur liste d'attente.\n\n" elif captain.registration_status == RegistrationStatus.PENDING: action_text = "Pour confirmer votre participation au tournoi, cliquez sur ce lien ou contactez rapidement le juge-arbitre." - warning_text = "" + warning_text = "⚠️ ATTENTION : Actuellement, il n'y a pas de liste d'attente pour ce tournoi. Dès qu'une liste d'attente se formera, vous recevrez un email avec un délai précis pour confirmer votre participation.\n\n" else: # Standard message for teams already confirmed action_text = "Si vous n'êtes plus disponible pour participer à ce tournoi, cliquez sur ce lien ou contactez rapidement le juge-arbitre." @@ -467,6 +496,10 @@ class TournamentEmailService: body = TournamentEmailService._build_out_of_walkout_waiting_list_email_body( tournament, recipient, tournament_details_str, other_player ) + elif message_type == TeamEmailType.REQUIRES_TIME_CONFIRMATION: + body = TournamentEmailService._build_requires_confirmation_email_body( + tournament, recipient, tournament_details_str, other_player + ) elif message_type == TeamEmailType.UNEXPECTED_OUT_OF_TOURNAMENT: body = TournamentEmailService._build_unexpected_out_of_tournament_email_body( tournament, recipient, tournament_details_str, other_player diff --git a/tournaments/signals.py b/tournaments/signals.py index 90e5731..1c3c5ac 100644 --- a/tournaments/signals.py +++ b/tournaments/signals.py @@ -79,9 +79,11 @@ def unregister_team(sender, instance, **kwargs): teams = instance.tournament.teams(True) first_waiting_list_team = instance.tournament.first_waiting_list_team(teams) if first_waiting_list_team and first_waiting_list_team.id != instance.id: - waiting_list_teams = instance.tournament.waiting_list_teams(teams) - if waiting_list_teams is not None: - ttc = instance.tournament.calculate_time_to_confirm(len(waiting_list_teams)) + if instance.tournament.automatic_waiting_list(): + waiting_list_teams = instance.tournament.waiting_list_teams(teams) + ttc = None + if waiting_list_teams is not None: + ttc = instance.tournament.calculate_time_to_confirm(len(waiting_list_teams)) first_waiting_list_team.set_time_to_confirm(ttc) notify_team(first_waiting_list_team, instance.tournament, TeamEmailType.OUT_OF_WAITING_LIST) @@ -129,14 +131,17 @@ def check_waiting_list(sender, instance, **kwargs): ] waiting_list_teams = previous_state.waiting_list_teams(previous_state_teams) + automatic_waiting_list = instance.automatic_waiting_list() + ttc = None for team in teams_in_to_warn: - if waiting_list_teams is not None: - ttc = previous_state.calculate_time_to_confirm(len(waiting_list_teams)) + if automatic_waiting_list: + if waiting_list_teams is not None: + ttc = previous_state.calculate_time_to_confirm(len(waiting_list_teams)) team.team_registration.set_time_to_confirm(ttc) notify_team(team.team_registration, instance, TeamEmailType.IN_TOURNAMENT_STRUCTURE) for team in teams_out_to_warn: - team.team_registration.set_time_to_confirm(None) + team.team_registration.cancel_time_to_confirm() notify_team(team.team_registration, instance, TeamEmailType.OUT_OF_TOURNAMENT_STRUCTURE) @receiver(pre_save, sender=TeamRegistration) @@ -152,7 +157,7 @@ def warn_team_walkout_status_change(sender, instance, **kwargs): print("TeamRegistration.DoesNotExist") return - + ttc = None previous_teams = instance.tournament.teams(True) current_teams = instance.tournament.teams(True, instance) previous_retrieved_teams = [team for team in previous_teams if team.team_registration.id == previous_instance.id] @@ -167,27 +172,31 @@ def warn_team_walkout_status_change(sender, instance, **kwargs): print(was_out, previous_instance.out_of_tournament(), is_out, instance.out_of_tournament()) if not instance.out_of_tournament() and is_out and (previous_instance.out_of_tournament() or not was_out): + instance.cancel_time_to_confirm() notify_team(instance, instance.tournament, TeamEmailType.OUT_OF_WALKOUT_WAITING_LIST) elif was_out and not is_out: - waiting_list_teams = instance.tournament.waiting_list_teams(current_teams) - if waiting_list_teams is not None: - ttc = instance.tournament.calculate_time_to_confirm(len(waiting_list_teams)) + if instance.tournament.automatic_waiting_list(): + waiting_list_teams = instance.tournament.waiting_list_teams(current_teams) + if waiting_list_teams is not None: + ttc = instance.tournament.calculate_time_to_confirm(len(waiting_list_teams)) instance.set_time_to_confirm(ttc) notify_team(instance, instance.tournament, TeamEmailType.OUT_OF_WALKOUT_IS_IN) elif not previous_instance.out_of_tournament() and instance.out_of_tournament(): + instance.cancel_time_to_confirm() notify_team(instance, instance.tournament, TeamEmailType.WALKOUT) if was_out and not is_out: first_out_of_list = instance.tournament.first_waiting_list_team(current_teams) if first_out_of_list: - first_out_of_list.set_time_to_confirm(None) + first_out_of_list.cancel_time_to_confirm() notify_team(first_out_of_list, instance.tournament, TeamEmailType.UNEXPECTED_OUT_OF_TOURNAMENT) elif not was_out and is_out: first_waiting_list_team = instance.tournament.first_waiting_list_team(previous_teams) if first_waiting_list_team: - waiting_list_teams = instance.tournament.waiting_list_teams(current_teams) - if waiting_list_teams is not None: - ttc = instance.tournament.calculate_time_to_confirm(len(waiting_list_teams)) + if instance.tournament.automatic_waiting_list(): + waiting_list_teams = instance.tournament.waiting_list_teams(current_teams) + if waiting_list_teams is not None: + ttc = instance.tournament.calculate_time_to_confirm(len(waiting_list_teams)) first_waiting_list_team.set_time_to_confirm(ttc) notify_team(first_waiting_list_team, instance.tournament, TeamEmailType.OUT_OF_WAITING_LIST) diff --git a/tournaments/tasks.py b/tournaments/tasks.py index 0b996ae..f14116b 100644 --- a/tournaments/tasks.py +++ b/tournaments/tasks.py @@ -64,19 +64,25 @@ def check_confirmation_deadlines(): should_update_team = False should_send_mail = False + is_online_registration_irrevelant = team_registration.tournament.is_online_registration_irrevelant() for team_player in team_players: - if team_player.time_to_confirm is None and first_waiting_list_team is not None: + if is_online_registration_irrevelant: + team_player.registration_status = RegistrationStatus.CANCELED + team_player.save() + elif team_player.time_to_confirm is None and first_waiting_list_team is not None: team_registration.set_time_to_confirm(ttc) team_player.save() should_send_mail = True print(team_player, "team_player.time_to_confirm is None and", ttc) elif team_player.time_to_confirm is not None and now > team_player.time_to_confirm: - team_player.registration_status = RegistrationStatus.CANCELED + if first_waiting_list_team is not None: + team_player.registration_status = RegistrationStatus.CANCELED + team_registration.registration_date = now + should_update_team = True + team_player.time_to_confirm = None team_player.save() - team_registration.registration_date = now print(team_player, "time_to_confirm = ", team_player.time_to_confirm) - should_update_team = True # elif team_player.time_to_confirm is not None and team_player.time_to_confirm > ttc: # team_player.registration_status = RegistrationStatus.PENDING # team_player.time_to_confirm = ttc @@ -87,7 +93,7 @@ def check_confirmation_deadlines(): TournamentEmailService.notify_team( team_registration, tournament, - TeamEmailType.OUT_OF_WAITING_LIST + TeamEmailType.REQUIRES_TIME_CONFIRMATION ) if should_update_team: