from django.core.mail import EmailMessage from django.utils import timezone from django.urls import reverse from enum import Enum class TeamEmailType(Enum): UNREGISTERED = "unregistered" OUT_OF_WAITING_LIST = "out_of_waiting_list" TOURNAMENT_CANCELED = "tournament_canceled" IN_TOURNAMENT_STRUCTURE = "in_tournament_structure" OUT_OF_TOURNAMENT_STRUCTURE = "out_of_tournament_structure" OUT_OF_WALKOUT_IS_IN = "out_of_walkout_is_in" OUT_OF_WALKOUT_WAITING_LIST = "out_of_walkout_waiting_list" 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): html_content = text.replace('\n', '
') return f""" {html_content} """ @staticmethod def email_subject(tournament, topic): base_subject = f"[{tournament.build_tournament_type_str()}] [{tournament.formatted_start_date()}] " + topic return base_subject @staticmethod def send_registration_confirmation(request, tournament, team_registration, waiting_list_position): tournament_details_str = tournament.build_tournament_details_str() email_subject = TournamentEmailService._build_email_subject( tournament, tournament_details_str, waiting_list_position ) email_body = TournamentEmailService._build_email_body( request, tournament, team_registration, tournament_details_str, waiting_list_position ) TournamentEmailService._send_email(request.user.email, email_subject, email_body) @staticmethod def _build_email_subject(tournament, tournament_details_str, waiting_list_position): if waiting_list_position >= 0: base_subject = "Liste d'attente" else: base_subject = "Participation confirmée" return TournamentEmailService.email_subject(tournament, base_subject) @staticmethod def _build_email_body(request, tournament, team_registration, tournament_details_str, waiting_list_position): inscription_date = team_registration.local_registration_date().strftime("%d/%m/%Y à %H:%M") team_members = [player.name() for player in team_registration.playerregistration_set.all()] team_members_str = " et ".join(team_members) body_parts = [] body_parts.append("Bonjour,\n") if waiting_list_position >= 0: body_parts.append(f"Votre inscription en liste d'attente du tournoi {tournament_details_str} est confirmée.") else: body_parts.append(f"Votre inscription au tournoi {tournament_details_str} est confirmée.") absolute_url = f"{request.build_absolute_uri(f'/tournament/{tournament.id}/')}" link_text = "informations sur le tournoi" absolute_url = f'{link_text}' body_parts.extend([ f"\nDate d'inscription: {inscription_date}", f"\nÉquipe inscrite: {team_members_str}", f"\nLe tournoi commencera le {tournament.formatted_start_date()} au club {tournament.event.club.name}", f"\nVoir les {absolute_url}", "\nPour toute question, veuillez contacter votre juge-arbitre. Si vous n'êtes pas à l'origine de cette inscription, merci de le contacter rapidement.", f"\n{tournament.event.creator.full_name()}\n{tournament.event.creator.email}", "\nCeci est un e-mail automatique, veuillez ne pas y répondre.", "\nCordialement,\n\nPadel Club" ]) return "\n".join(body_parts) @staticmethod def _build_unregistration_email_body(tournament, captain, tournament_details_str, other_player): body_parts = [ "Bonjour,\n\n", f"Votre inscription au tournoi {tournament_details_str}, prévu le {tournament.formatted_start_date()} au club {tournament.event.club.name} a été annulée" ] if other_player is not None: body_parts.append( f"\n\nVous étiez inscrit avec {other_player.name()}, n'oubliez pas de prévenir votre partenaire." ) absolute_url = f"https://padelclub.app/tournament/{tournament.id}/info" link_text = "informations sur le tournoi" absolute_url = f'{link_text}' body_parts.append( f"\n\nVoir les {absolute_url}", ) body_parts.extend([ "\n\nPour toute question, veuillez contacter votre juge-arbitre. " "Si vous n'êtes pas à l'origine de cette désinscription, merci de le contacter rapidement.", f"\n{tournament.event.creator.full_name()}\n{tournament.event.creator.email}", "\n\nCeci est un e-mail automatique, veuillez ne pas y répondre." ]) return "".join(body_parts) @staticmethod def _build_out_of_waiting_list_email_body(tournament, captain, tournament_details_str, other_player): body_parts = [ "Bonjour,\n\n", f"Suite au désistement d'une paire, vous êtes maintenant inscrit 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." ) body_parts.append( "\n\nSi vous n'êtes plus disponible pour participer à ce tournoi, cliquez sur ce lien ou contactez rapidement le juge-arbitre." f"\n{absolute_url}" "\nPour vous désinscrire en ligne vous devez avoir un compte Padel Club." ) body_parts.extend([ f"\n\n{tournament.event.creator.full_name()}\n{tournament.event.creator.email}", "\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 = [ "Bonjour,\n\n", f"Le tournoi {tournament_details_str}, prévu le {tournament.formatted_start_date()} au club {tournament.event.club.name} a été annulé par le juge-arbitre." ] if other_player is not None: body_parts.append( f"\nVous étiez inscrit avec {other_player.name()}, n'oubliez pas de prévenir votre partenaire." ) body_parts.extend([ "\n\nPour toute question, veuillez contacter votre juge-arbitre:", f"\n{tournament.event.creator.full_name()}\n{tournament.event.creator.email}", "\n\nCeci est un e-mail automatique, veuillez ne pas y répondre." ]) return "".join(body_parts) @staticmethod def _build_in_tournament_email_body(tournament, captain, tournament_details_str, other_player): body_parts = [ "Bonjour,\n\n", f"Suite à une modification de la taille du tournoi, vous pouvez participer 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." ) body_parts.append( "\n\nSi vous n'êtes plus disponible pour participer à ce tournoi, cliquez sur ce lien ou contactez rapidement le juge-arbitre." f"\n{absolute_url}" "\nPour vous désinscrire en ligne vous devez avoir un compte Padel Club." ) body_parts.extend([ f"\n\n{tournament.event.creator.full_name()}\n{tournament.event.creator.email}", "\n\nCeci est un e-mail automatique, veuillez ne pas y répondre." ]) return "".join(body_parts) @staticmethod def _build_out_of_tournament_email_body(tournament, captain, tournament_details_str, other_player): body_parts = [ "Bonjour,\n\n", f"Suite à une modification de la taille du tournoi, vous ne faites plus partie des équipes participant 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 = "informations sur le tournoi" absolute_url = f'{link_text}' body_parts.append(f"\n\nVoir les {absolute_url}") if other_player is not None: body_parts.append( f"\nVous étiez inscrit avec {other_player.name()}, n'oubliez pas de prévenir votre partenaire." ) body_parts.extend([ "\n\nPour toute question, veuillez contacter votre juge-arbitre : ", f"\n{tournament.event.creator.full_name()}\n{tournament.event.creator.email}", "\n\nCeci est un e-mail automatique, veuillez ne pas y répondre." ]) return "".join(body_parts) @staticmethod 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}" ] absolute_url = f"https://padelclub.app/tournament/{tournament.id}/info" link_text = "accéder au tournoi" absolute_url = f'{link_text}' body_parts.append(f"\n\nVoir les {absolute_url}") if other_player is not None: body_parts.append( f"\nVous étiez inscrit avec {other_player.name()}, n'oubliez pas de prévenir votre partenaire." ) body_parts.extend([ "\n\nPour toute question, veuillez contacter votre juge-arbitre : ", f"\n{tournament.event.creator.full_name()}\n{tournament.event.creator.email}", "\n\nCeci est un e-mail automatique, veuillez ne pas y répondre." ]) return "".join(body_parts) @staticmethod def _build_out_of_walkout_is_in_email_body(tournament, captain, tournament_details_str, other_player): body_parts = [ "Bonjour,\n\n", f"Le juge-arbitre vous a ré-intégré 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 = "informations sur le tournoi" absolute_url = f'{link_text}' body_parts.append(f"\n\nVoir les {absolute_url}") if other_player is not None: body_parts.append( f"\nVous étiez inscrit avec {other_player.name()}, n'oubliez pas de prévenir votre partenaire." ) body_parts.extend([ "\n\nPour toute question, veuillez contacter votre juge-arbitre : ", f"\n{tournament.event.creator.full_name()}\n{tournament.event.creator.email}", "\n\nCeci est un e-mail automatique, veuillez ne pas y répondre." ]) return "".join(body_parts) @staticmethod def _build_unexpected_out_of_tournament_email_body(tournament, captain, tournament_details_str, other_player): body_parts = [ "Bonjour,\n\n", f"En raison d'une décision du juge-arbitre, vous ne faites plus partie des équipes participant 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 = "informations sur le tournoi" absolute_url = f'{link_text}' body_parts.append(f"\n\nVoir les {absolute_url}") if other_player is not None: body_parts.append( f"\nVous étiez inscrit avec {other_player.name()}, n'oubliez pas de prévenir votre partenaire." ) body_parts.extend([ "\n\nPour toute question, veuillez contacter votre juge-arbitre : ", f"\n{tournament.event.creator.full_name()}\n{tournament.event.creator.email}", "\n\nCeci est un e-mail automatique, veuillez ne pas y répondre." ]) return "".join(body_parts) @staticmethod def _build_out_of_walkout_waiting_list_email_body(tournament, captain, tournament_details_str, other_player): body_parts = [ "Bonjour,\n\n", f"Le juge-arbitre vous a ré-intégré au tournoi en liste d'attente {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 = "informations sur le tournoi" absolute_url = f'{link_text}' body_parts.append(f"\n\nVoir les {absolute_url}") if other_player is not None: body_parts.append( f"\nVous étiez inscrit avec {other_player.name()}, n'oubliez pas de prévenir votre partenaire." ) body_parts.extend([ "\n\nPour toute question, veuillez contacter votre juge-arbitre : ", f"\n{tournament.event.creator.full_name()}\n{tournament.event.creator.email}", "\n\nCeci est un e-mail automatique, veuillez ne pas y répondre." ]) return "".join(body_parts) @staticmethod def notify(captain, other_player, tournament, message_type: TeamEmailType): if not captain or not captain.registered_online or not captain.email: return tournament_details_str = tournament.build_tournament_details_str() email_body = TournamentEmailService._build_email_content( message_type, captain, tournament, tournament_details_str, other_player ) if email_body is None: return topic = message_type.email_subject() email_subject = TournamentEmailService.email_subject(tournament, topic) TournamentEmailService._send_email(captain.email, email_subject, email_body) @staticmethod def _build_email_content(message_type, recipient, tournament, tournament_details_str, other_player): if message_type == TeamEmailType.OUT_OF_WAITING_LIST: 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 ) elif message_type == TeamEmailType.WALKOUT: body = TournamentEmailService._build_walk_out_email_body( tournament, recipient, tournament_details_str, other_player ) elif message_type == TeamEmailType.OUT_OF_WALKOUT_IS_IN: body = TournamentEmailService._build_out_of_walkout_is_in_email_body( tournament, recipient, tournament_details_str, other_player ) elif message_type == TeamEmailType.OUT_OF_WALKOUT_WAITING_LIST: body = TournamentEmailService._build_out_of_walkout_waiting_list_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 ) elif message_type == TeamEmailType.OUT_OF_TOURNAMENT_STRUCTURE: 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_in_tournament_email_body( tournament, recipient, tournament_details_str, other_player ) else: return None return body @staticmethod def _send_email(to, subject, body): email = EmailMessage( subject=subject, body=TournamentEmailService._convert_newlines_to_html(body), to=[to] ) email.content_subtype = "html" email.send() print("TournamentEmailService._send_email", to, subject) @staticmethod def notify_team(team, tournament, message_type: TeamEmailType): captain = None other_player = None for player in team.playerregistration_set.all(): if player.captain: captain = player else: other_player = player if captain: TournamentEmailService.notify(captain, other_player, tournament, message_type) else: # Notify both players separately if there is no captain or the captain is unavailable players = list(team.playerregistration_set.all()) if len(players) == 2: first_player, second_player = players TournamentEmailService.notify(first_player, second_player, tournament, message_type) TournamentEmailService.notify(second_player, first_player, tournament, message_type) elif len(players) == 1: # If there's only one player, just send them the notification TournamentEmailService.notify(players[0], None, tournament, message_type)