diff --git a/tournaments/models/tournament.py b/tournaments/models/tournament.py index 4bd4d17..eeef79c 100644 --- a/tournaments/models/tournament.py +++ b/tournaments/models/tournament.py @@ -348,8 +348,11 @@ class Tournament(models.Model): closed_date = self.closed_registration_date # Process each team registration - for team_reg in self.teamregistration_set.all(): - if team_reg.out_of_tournament() and ((un_walk_out_team and team_reg.id is not un_walk_out_team.id) or un_walk_out_team is None): + for db_team_reg in self.teamregistration_set.all(): + team_reg = db_team_reg + if un_walk_out_team and team_reg.id == un_walk_out_team.id: + team_reg = un_walk_out_team + if team_reg.out_of_tournament(): continue # Create team item diff --git a/tournaments/services/email_service.py b/tournaments/services/email_service.py index 580d671..0912077 100644 --- a/tournaments/services/email_service.py +++ b/tournaments/services/email_service.py @@ -14,6 +14,20 @@ class TeamEmailType(Enum): WALKOUT = "walkout" UNEXPECTED_OUT_OF_TOURNAMENT = 'unexpected_out_of_tournament' + def email_subject(self) -> str: + subjects = { + self.UNREGISTERED: "Désistement", + self.OUT_OF_WAITING_LIST: "Participation confirmée", + self.TOURNAMENT_CANCELED: "Tournoi annulé", + self.IN_TOURNAMENT_STRUCTURE: "Participation confirmée", + self.OUT_OF_TOURNAMENT_STRUCTURE: "Participation annulée", + self.OUT_OF_WALKOUT_IS_IN: "Participation confirmée", + self.OUT_OF_WALKOUT_WAITING_LIST: "Liste d'attente", + self.WALKOUT: "Participation annulée", + self.UNEXPECTED_OUT_OF_TOURNAMENT: "Participation annulée", + } + return subjects.get(self, "Tournament Notification") + class TournamentEmailService: @staticmethod def _convert_newlines_to_html(text): @@ -53,9 +67,9 @@ class TournamentEmailService: @staticmethod def _build_email_subject(tournament, tournament_details_str, waiting_list_position): if waiting_list_position >= 0: - base_subject = "En liste d'attente du tournoi" + base_subject = "Liste d'attente" else: - base_subject = "Confirmation d'inscription au tournoi" + base_subject = "Participation confirmé" return TournamentEmailService.email_subject(tournament, base_subject) @staticmethod @@ -89,20 +103,6 @@ class TournamentEmailService: return "\n".join(body_parts) - @staticmethod - def send_unregistration_confirmation(captain, tournament, other_player): - tournament_details_str = tournament.build_tournament_details_str() - - email_subject = TournamentEmailService.email_subject(tournament, "Désistement du tournoi") - email_body = TournamentEmailService._build_unregistration_email_body( - tournament, - captain, - tournament_details_str, - other_player - ) - - TournamentEmailService._send_email(captain.email, email_subject, email_body) - @staticmethod def _build_unregistration_email_body(tournament, captain, tournament_details_str, other_player): body_parts = [ @@ -240,7 +240,7 @@ class TournamentEmailService: def _build_walk_out_email_body(tournament, captain, tournament_details_str, other_player): body_parts = [ "Bonjour,\n\n", - f"Le Juge-Arbitre a annulé votre participation au tournoi {tournament_details_str}, prévu le {tournament.formatted_start_date()} au club {tournament.event.club.name}" + f"Le juge-arbitre a annulé 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" @@ -361,7 +361,8 @@ class TournamentEmailService: if email_body is None: return - email_subject = TournamentEmailService.email_subject(tournament, "Participation au tournoi") + topic = message_type.email_subject() + email_subject = TournamentEmailService.email_subject(tournament, topic) TournamentEmailService._send_email(captain.email, email_subject, email_body) @staticmethod @@ -370,6 +371,10 @@ class TournamentEmailService: body = TournamentEmailService._build_out_of_waiting_list_email_body( tournament, recipient, tournament_details_str, other_player ) + elif message_type == TeamEmailType.UNREGISTERED: + body = TournamentEmailService._build_unregistration_email_body( + tournament, recipient, tournament_details_str, other_player + ) elif message_type == TeamEmailType.TOURNAMENT_CANCELED: body = TournamentEmailService._build_tournament_cancellation_email_body( tournament, recipient, tournament_details_str, other_player @@ -391,11 +396,11 @@ class TournamentEmailService: tournament, recipient, tournament_details_str, other_player ) elif message_type == TeamEmailType.OUT_OF_TOURNAMENT_STRUCTURE: - body = TournamentEmailService._build_tournament_cancellation_email_body( + body = TournamentEmailService._build_out_of_tournament_email_body( tournament, recipient, tournament_details_str, other_player ) elif message_type == TeamEmailType.IN_TOURNAMENT_STRUCTURE: - body = TournamentEmailService._build_out_of_tournament_email_body( + body = TournamentEmailService._build_in_tournament_email_body( tournament, recipient, tournament_details_str, other_player ) else: @@ -412,6 +417,7 @@ class TournamentEmailService: ) email.content_subtype = "html" email.send() + print("TournamentEmailService._send_email", to, subject) @staticmethod def notify_team(team, tournament, message_type: TeamEmailType): diff --git a/tournaments/signals.py b/tournaments/signals.py index ee3cb66..d9188f5 100644 --- a/tournaments/signals.py +++ b/tournaments/signals.py @@ -50,20 +50,21 @@ def notify_object_creation_on_discord(created, instance): send_discord_log_message(message) def notify_team(team, tournament, message_type): - if tournament.online_registration is False: + if tournament.enable_online_registration is False: return + print(team, message_type) TournamentEmailService.notify_team(team, tournament, message_type) @receiver(pre_delete, sender=TeamRegistration) def unregister_team(sender, instance, **kwargs): if instance.tournament.is_deleted: return - if instance.online_registration is False: + if instance.tournament.enable_online_registration is False: return notify_team(instance, instance.tournament, TeamEmailType.UNREGISTERED) first_waiting_list_team = instance.tournament.first_waiting_list_team() - if first_waiting_list_team: + if first_waiting_list_team and first_waiting_list_team.id != instance.id: notify_team(first_waiting_list_team, instance.tournament, TeamEmailType.OUT_OF_WAITING_LIST) @receiver(post_save, sender=Tournament) @@ -71,7 +72,7 @@ def notify_players_of_tournament_cancellation(sender, instance, **kwargs): if not instance.is_deleted: return - if instance.online_registration is False: + if instance.enable_online_registration is False: return for team_registration in instance.teamregistration_set.all(): @@ -82,10 +83,14 @@ def check_waiting_list(sender, instance, **kwargs): if instance.id is None: return - if instance.online_registration is False: + if instance.enable_online_registration is False: return - previous_state = Tournament.objects.get(id=instance.id) + try: + previous_state = Tournament.objects.get(id=instance.id) + except Tournament.DoesNotExist: + previous_state = None + if previous_state is None: return @@ -94,8 +99,9 @@ def check_waiting_list(sender, instance, **kwargs): if previous_state.team_count > instance.team_count: teams_to_remove_count = previous_state.team_count - instance.team_count + previous_state_teams = previous_state.teams(True) sorted_teams = sorted( - [team for team in previous_state.teams(True) if team.stage != "Attente" and not (team.wildcard_bracket or team.wildcard_groupstage)], + [team for team in previous_state_teams if team.stage != "Attente" and not (team.wildcard_bracket or team.wildcard_groupstage)], key=lambda t: ( t.registration_date is None, t.registration_date or datetime.min, t.initial_weight, t.team_registration.id ) if previous_state.team_sorting == TeamSortingType.INSCRIPTION_DATE else @@ -103,37 +109,61 @@ def check_waiting_list(sender, instance, **kwargs): ) teams_out_to_warn = sorted_teams[-teams_to_remove_count:] elif previous_state.team_count < instance.team_count: - teams_in_to_warn = previous_state.teams(True)[:(instance.team_count - previous_state.team_count)] + teams_in_to_warn = [ + team for team in previous_state.teams(True)[(instance.team_count - previous_state.team_count):] + if team.stage == "Attente" + ] for team in teams_in_to_warn: - notify_team(team, instance, TeamEmailType.IN_TOURNAMENT_STRUCTURE) + notify_team(team.team_registration, instance, TeamEmailType.IN_TOURNAMENT_STRUCTURE) for team in teams_out_to_warn: - notify_team(team, instance, TeamEmailType.OUT_OF_TOURNAMENT_STRUCTURE) + notify_team(team.team_registration, instance, TeamEmailType.OUT_OF_TOURNAMENT_STRUCTURE) @receiver(pre_save, sender=TeamRegistration) def warn_team_walkout_status_change(sender, instance, **kwargs): if instance.id is None: return - - if instance.tournament.online_registration is False: + if instance.tournament.enable_online_registration is False: return - previous_instance = TeamRegistration.objects.get(id=instance.id) + try: + previous_instance = TeamRegistration.objects.get(id=instance.id) + except TeamRegistration.DoesNotExist: + previous_instance = None + if previous_instance is None: return - if previous_instance.out_of_tournament() and not instance.out_of_tournament(): + previous_teams = previous_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] + current_retrieved_teams = [team for team in current_teams if team.team_registration.id == instance.id] + was_out = previous_instance.out_of_tournament() + is_out = instance.out_of_tournament() + if len(previous_retrieved_teams) > 0: + if previous_retrieved_teams[0].stage == "Attente": + was_out = True + + if len(current_retrieved_teams) > 0: + if current_retrieved_teams[0].stage == "Attente": + is_out = True + + print(was_out, previous_instance.out_of_tournament(), is_out, instance.out_of_tournament()) + if not instance.out_of_tournament() and is_out: + notify_team(instance, instance.tournament, TeamEmailType.OUT_OF_WALKOUT_WAITING_LIST) + + if not previous_instance.out_of_tournament() and instance.out_of_tournament(): + notify_team(instance, instance.tournament, TeamEmailType.WALKOUT) + + if was_out and not is_out: is_in, first_out_of_list = instance.tournament.first_out_of_list(instance) if is_in: notify_team(instance, instance.tournament, TeamEmailType.OUT_OF_WALKOUT_IS_IN) - else: - notify_team(instance, instance.tournament, TeamEmailType.OUT_OF_WALKOUT_WAITING_LIST) if first_out_of_list: notify_team(first_out_of_list, instance.tournament, TeamEmailType.UNEXPECTED_OUT_OF_TOURNAMENT) - elif not previous_instance.out_of_tournament() and instance.out_of_tournament(): - notify_team(instance, instance.tournament, TeamEmailType.WALKOUT) + elif not was_out and is_out: first_waiting_list_team = instance.tournament.first_waiting_list_team() if first_waiting_list_team: notify_team(first_waiting_list_team, instance.tournament, TeamEmailType.OUT_OF_WAITING_LIST)