|
|
from django.core.mail import EmailMessage
|
|
|
from enum import Enum
|
|
|
from ..models.enums import RegistrationStatus, FederalLevelCategory
|
|
|
from ..models.tournament import TeamSortingType
|
|
|
from django.utils import timezone
|
|
|
from tournaments.services.currency_service import CurrencyService
|
|
|
|
|
|
class TeamEmailType(Enum):
|
|
|
REGISTERED = "registered"
|
|
|
WAITING_LIST = "waiting_list"
|
|
|
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'
|
|
|
REQUIRES_TIME_CONFIRMATION = 'requires_time_confirmation'
|
|
|
|
|
|
def email_topic(self, category=None, 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.REQUIRES_TIME_CONFIRMATION,
|
|
|
]
|
|
|
word = "Tournoi"
|
|
|
grammar = ''
|
|
|
if category is not None:
|
|
|
federal_category = FederalLevelCategory(category)
|
|
|
word = federal_category.localized_word().capitalize()
|
|
|
grammar = 'e' if federal_category.is_feminine_word() else ''
|
|
|
|
|
|
if time_to_confirm and self in confirmation_types:
|
|
|
return "Participation en attente de confirmation"
|
|
|
else:
|
|
|
subjects = {
|
|
|
self.REGISTERED: "Participation confirmée",
|
|
|
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: f"{word} annulé{grammar}",
|
|
|
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', '<br>')
|
|
|
return f"""
|
|
|
<html>
|
|
|
<body>
|
|
|
{html_content}
|
|
|
</body>
|
|
|
</html>
|
|
|
"""
|
|
|
|
|
|
@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):
|
|
|
if waiting_list_position >= 0:
|
|
|
TournamentEmailService.notify_team(team_registration, tournament, TeamEmailType.WAITING_LIST)
|
|
|
else:
|
|
|
TournamentEmailService.notify_team(team_registration, tournament, TeamEmailType.REGISTERED)
|
|
|
|
|
|
@staticmethod
|
|
|
def _build_registration_confirmation_email_body(tournament, captain, tournament_details_str, other_player):
|
|
|
return TournamentEmailService._build_registration_email_body(tournament, captain, tournament_details_str, other_player, False)
|
|
|
|
|
|
@staticmethod
|
|
|
def _build_waiting_list_confirmation_email_body(tournament, captain, tournament_details_str, other_player):
|
|
|
return TournamentEmailService._build_registration_email_body(tournament, captain, tournament_details_str, other_player, True)
|
|
|
|
|
|
@staticmethod
|
|
|
def _build_registration_email_body(tournament, captain, tournament_details_str, other_player, waiting_list):
|
|
|
inscription_date = captain.team_registration.local_registration_date().strftime("%d/%m/%Y à %H:%M")
|
|
|
federal_level_category = FederalLevelCategory(tournament.federal_level_category)
|
|
|
tournament_word = federal_level_category.localized_word()
|
|
|
tournament_prefix_at = federal_level_category.localized_prefix_at()
|
|
|
tournament_prefix_of = federal_level_category.localized_prefix_of()
|
|
|
tournament_prefix_that = federal_level_category.localized_prefix_that()
|
|
|
|
|
|
body_parts = []
|
|
|
body_parts.append("Bonjour,\n")
|
|
|
|
|
|
if waiting_list:
|
|
|
body_parts.append(f"Votre inscription en liste d'attente {tournament_prefix_of}{tournament_word} {tournament_details_str} prévu le {tournament.formatted_start_date()} au club {tournament.event.club.name} est confirmée.")
|
|
|
else:
|
|
|
body_parts.append(f"Votre inscription {tournament_prefix_at}{tournament_word} {tournament_details_str} prévu le {tournament.formatted_start_date()} au club {tournament.event.club.name} est confirmée.")
|
|
|
if tournament.team_sorting == TeamSortingType.RANK:
|
|
|
cloture_date = tournament.local_registration_federal_limit()
|
|
|
loc = ""
|
|
|
if cloture_date is not None:
|
|
|
loc = f", prévu le {cloture_date.strftime("%d/%m/%Y à %H:%M")}"
|
|
|
body_parts.append(f"Attention, la sélection définitive se fera par poids d'équipe à la clôture des inscriptions{loc}.")
|
|
|
|
|
|
|
|
|
absolute_url = f"https://padelclub.app/tournament/{tournament.id}/info"
|
|
|
link_text = f"informations sur {tournament_prefix_that}{tournament_word}"
|
|
|
absolute_url = f'<a href="{absolute_url}">{link_text}</a>'
|
|
|
|
|
|
if other_player:
|
|
|
body_parts.extend([
|
|
|
f"\nDate d'inscription: {inscription_date}",
|
|
|
f"\nÉquipe inscrite: {captain.name()} et {other_player.name()}",
|
|
|
f"\nVoir les {absolute_url}"
|
|
|
])
|
|
|
else:
|
|
|
body_parts.extend([
|
|
|
f"\nDate d'inscription: {inscription_date}",
|
|
|
f"\nVotre inscription: {captain.name()}",
|
|
|
f"\nVoir les {absolute_url}"
|
|
|
])
|
|
|
|
|
|
# Add payment information if applicable
|
|
|
if tournament.should_request_payment():
|
|
|
payment_info = TournamentEmailService._build_payment_info(tournament, captain.team_registration)
|
|
|
body_parts.append(payment_info)
|
|
|
|
|
|
body_parts.extend([
|
|
|
"\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{TournamentEmailService._format_umpire_contact(tournament)}",
|
|
|
"\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):
|
|
|
federal_level_category = FederalLevelCategory(tournament.federal_level_category)
|
|
|
tournament_word = federal_level_category.localized_word()
|
|
|
tournament_prefix_at = federal_level_category.localized_prefix_at()
|
|
|
tournament_prefix_that = federal_level_category.localized_prefix_that()
|
|
|
|
|
|
body_parts = [
|
|
|
"Bonjour,\n\n",
|
|
|
f"Votre inscription {tournament_prefix_at}{tournament_word} {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 = f"informations sur {tournament_prefix_that}{tournament_word}"
|
|
|
absolute_url = f'<a href="{absolute_url}">{link_text}</a>'
|
|
|
|
|
|
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{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_out_of_waiting_list_email_body(tournament, captain, tournament_details_str, other_player):
|
|
|
federal_level_category = FederalLevelCategory(tournament.federal_level_category)
|
|
|
tournament_word = federal_level_category.localized_word()
|
|
|
tournament_prefix_at = federal_level_category.localized_prefix_at()
|
|
|
|
|
|
body_parts = [
|
|
|
"Bonjour,\n\n",
|
|
|
f"Suite au désistement d'une paire, vous êtes maintenant inscrit {tournament_prefix_at}{tournament_word} {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 = f"accéder {tournament_prefix_at}{tournament_word}"
|
|
|
absolute_url = f'<a href="{absolute_url}">{link_text}</a>'
|
|
|
|
|
|
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_requires_confirmation_email_body(tournament, captain, tournament_details_str, other_player):
|
|
|
federal_level_category = FederalLevelCategory(tournament.federal_level_category)
|
|
|
tournament_word = federal_level_category.localized_word()
|
|
|
tournament_prefix_at = federal_level_category.localized_prefix_at()
|
|
|
|
|
|
body_parts = [
|
|
|
"Bonjour,\n\n",
|
|
|
f"Vous n'avez toujours pas confirmé votre participation {tournament_prefix_at}{tournament_word} {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 = f"accéder {tournament_prefix_at}{tournament_word}"
|
|
|
absolute_url = f'<a href="{absolute_url}">{link_text}</a>'
|
|
|
|
|
|
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):
|
|
|
federal_level_category = FederalLevelCategory(tournament.federal_level_category)
|
|
|
tournament_word = federal_level_category.localized_word()
|
|
|
tournament_prefix_that = federal_level_category.localized_prefix_that()
|
|
|
|
|
|
body_parts = [
|
|
|
"Bonjour,\n\n",
|
|
|
f"{tournament_prefix_that.capitalize()}{tournament_word} {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{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_in_tournament_email_body(tournament, captain, tournament_details_str, other_player):
|
|
|
federal_level_category = FederalLevelCategory(tournament.federal_level_category)
|
|
|
tournament_word = federal_level_category.localized_word()
|
|
|
tournament_prefix_at = federal_level_category.localized_prefix_at()
|
|
|
tournament_prefix_of = federal_level_category.localized_prefix_of()
|
|
|
|
|
|
body_parts = [
|
|
|
"Bonjour,\n\n",
|
|
|
f"Suite à une modification de la taille {tournament_prefix_of}{tournament_word}, vous pouvez participer {tournament_prefix_at}{tournament_word} {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 = f"accéder {tournament_prefix_at}{tournament_word}"
|
|
|
absolute_url = f'<a href="{absolute_url}">{link_text}</a>'
|
|
|
|
|
|
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_out_of_tournament_email_body(tournament, captain, tournament_details_str, other_player):
|
|
|
federal_level_category = FederalLevelCategory(tournament.federal_level_category)
|
|
|
tournament_word = federal_level_category.localized_word()
|
|
|
tournament_prefix_at = federal_level_category.localized_prefix_at()
|
|
|
tournament_prefix_of = federal_level_category.localized_prefix_of()
|
|
|
tournament_prefix_that = federal_level_category.localized_prefix_that()
|
|
|
|
|
|
body_parts = [
|
|
|
"Bonjour,\n\n",
|
|
|
f"Suite à une modification de la taille {tournament_prefix_of}{tournament_word}, vous avez été placé en liste d'attente. Votre participation {tournament_prefix_at}{tournament_word} {tournament_details_str}, prévu le {tournament.formatted_start_date()} au club {tournament.event.club.name} n'est plus confirmée."
|
|
|
]
|
|
|
|
|
|
absolute_url = f"https://padelclub.app/tournament/{tournament.id}/info"
|
|
|
link_text = f"informations sur {tournament_prefix_that}{tournament_word}"
|
|
|
absolute_url = f'<a href="{absolute_url}">{link_text}</a>'
|
|
|
|
|
|
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{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_walk_out_email_body(tournament, captain, tournament_details_str, other_player):
|
|
|
federal_level_category = FederalLevelCategory(tournament.federal_level_category)
|
|
|
tournament_word = federal_level_category.localized_word()
|
|
|
tournament_prefix_at = federal_level_category.localized_prefix_at()
|
|
|
|
|
|
body_parts = [
|
|
|
"Bonjour,\n\n",
|
|
|
f"Le juge-arbitre a annulé votre participation {tournament_prefix_at}{tournament_word} {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 = f"accéder {tournament_prefix_at}{tournament_word}"
|
|
|
absolute_url = f'<a href="{absolute_url}">{link_text}</a>'
|
|
|
|
|
|
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{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_out_of_walkout_is_in_email_body(tournament, captain, tournament_details_str, other_player):
|
|
|
federal_level_category = FederalLevelCategory(tournament.federal_level_category)
|
|
|
tournament_word = federal_level_category.localized_word()
|
|
|
tournament_prefix_at = federal_level_category.localized_prefix_at()
|
|
|
tournament_prefix_that = federal_level_category.localized_prefix_that()
|
|
|
|
|
|
body_parts = [
|
|
|
"Bonjour,\n\n",
|
|
|
f"Le juge-arbitre vous a ré-intégré {tournament_prefix_at}{tournament_word} {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 = f"informations sur {tournament_prefix_that}{tournament_word}"
|
|
|
absolute_url = f'<a href="{absolute_url}">{link_text}</a>'
|
|
|
|
|
|
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."
|
|
|
)
|
|
|
|
|
|
confirmation_message = TournamentEmailService._build_confirmation_message(captain, tournament, absolute_url)
|
|
|
body_parts.append(confirmation_message)
|
|
|
|
|
|
body_parts.extend([
|
|
|
"\n\nPour toute question, veuillez contacter votre juge-arbitre : ",
|
|
|
f"\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_unexpected_out_of_tournament_email_body(tournament, captain, tournament_details_str, other_player):
|
|
|
federal_level_category = FederalLevelCategory(tournament.federal_level_category)
|
|
|
tournament_word = federal_level_category.localized_word()
|
|
|
tournament_prefix_at = federal_level_category.localized_prefix_at()
|
|
|
tournament_prefix_that = federal_level_category.localized_prefix_that()
|
|
|
|
|
|
body_parts = [
|
|
|
"Bonjour,\n\n",
|
|
|
f"En raison d'une décision du juge-arbitre, vous avez été placé en liste d'attente. Votre participation {tournament_prefix_at}{tournament_word} {tournament_details_str}, prévu le {tournament.formatted_start_date()} au club {tournament.event.club.name} n'est plus confirmée."
|
|
|
]
|
|
|
|
|
|
absolute_url = f"https://padelclub.app/tournament/{tournament.id}/info"
|
|
|
link_text = f"informations sur {tournament_prefix_that}{tournament_word}"
|
|
|
absolute_url = f'<a href="{absolute_url}">{link_text}</a>'
|
|
|
|
|
|
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{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_out_of_walkout_waiting_list_email_body(tournament, captain, tournament_details_str, other_player):
|
|
|
federal_level_category = FederalLevelCategory(tournament.federal_level_category)
|
|
|
tournament_word = federal_level_category.localized_word()
|
|
|
tournament_prefix_of = federal_level_category.localized_prefix_of()
|
|
|
tournament_prefix_that = federal_level_category.localized_prefix_that()
|
|
|
|
|
|
body_parts = [
|
|
|
"Bonjour,\n\n",
|
|
|
]
|
|
|
if captain.registration_status == RegistrationStatus.CANCELED:
|
|
|
body_parts.append("Le temps accordé pour confirmer votre inscription s'est écoulé.")
|
|
|
body_parts.append(f"Vous avez été replacé en liste d'attente {tournament_prefix_of}{tournament_word} {tournament_details_str}, prévu le {tournament.formatted_start_date()} au club {tournament.event.club.name}")
|
|
|
else:
|
|
|
body_parts.append(f"Le juge-arbitre vous a placé en liste d'attente {tournament_prefix_of}{tournament_word} {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 = f"informations sur {tournament_prefix_that}{tournament_word}"
|
|
|
absolute_url = f'<a href="{absolute_url}">{link_text}</a>'
|
|
|
|
|
|
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{TournamentEmailService._format_umpire_contact(tournament)}",
|
|
|
"\n\nCeci est un e-mail automatique, veuillez ne pas y répondre."
|
|
|
])
|
|
|
|
|
|
return "".join(body_parts)
|
|
|
|
|
|
@staticmethod
|
|
|
def _format_umpire_contact(tournament):
|
|
|
contact_parts = []
|
|
|
creator_full_name = tournament.umpire_contact()
|
|
|
if creator_full_name:
|
|
|
contact_parts.append(creator_full_name)
|
|
|
|
|
|
if not tournament.hide_umpire_mail:
|
|
|
creator_email = tournament.umpire_mail()
|
|
|
if creator_email:
|
|
|
contact_parts.append(creator_email)
|
|
|
|
|
|
if not tournament.hide_umpire_phone:
|
|
|
creator_phone = tournament.umpire_phone()
|
|
|
if creator_phone:
|
|
|
contact_parts.append(creator_phone)
|
|
|
|
|
|
return "\n".join(contact_parts)
|
|
|
|
|
|
@staticmethod
|
|
|
def _build_confirmation_message(captain, tournament, absolute_url):
|
|
|
"""
|
|
|
Build a standardized confirmation message for emails.
|
|
|
|
|
|
Args:
|
|
|
captain: The player (captain) receiving the email
|
|
|
tournament: The tournament
|
|
|
absolute_url: The URL for confirmation/unregistration
|
|
|
|
|
|
Returns:
|
|
|
str: Formatted confirmation message
|
|
|
"""
|
|
|
time_to_confirm = getattr(captain, 'time_to_confirm', None)
|
|
|
|
|
|
# Common URL and account info text
|
|
|
account_info = "\nVous devez avoir un compte Padel Club."
|
|
|
url_info = f"\n{absolute_url}"
|
|
|
|
|
|
federal_level_category = FederalLevelCategory(tournament.federal_level_category)
|
|
|
tournament_word = federal_level_category.localized_word()
|
|
|
tournament_prefix_at = federal_level_category.localized_prefix_at()
|
|
|
tournament_prefix_this = federal_level_category.localized_prefix_this()
|
|
|
|
|
|
# Base message varies based on whether confirmation is needed
|
|
|
if time_to_confirm is not None:
|
|
|
# Format the deadline time with proper timezone
|
|
|
deadline_str = time_to_confirm.astimezone(tournament.timezone()).strftime("%d/%m/%Y à %H:%M (%Z)")
|
|
|
|
|
|
# Confirmation required message
|
|
|
action_text = f"Pour confirmer votre participation {tournament_prefix_at}{tournament_word}, cliquez sur ce lien pour {url_info} ou contactez rapidement le juge-arbitre."
|
|
|
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 = f"Pour confirmer votre participation {tournament_prefix_at}{tournament_word}, cliquez sur ce lien pour {url_info} ou contactez rapidement le juge-arbitre."
|
|
|
warning_text = f"⚠️ ATTENTION : Actuellement, il n'y a pas de liste d'attente pour {tournament_prefix_this}{tournament_word}. 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 = f"Si vous n'êtes plus disponible pour participer à {tournament_prefix_this}{tournament_word}, cliquez sur ce lien pour {url_info} ou contactez rapidement le juge-arbitre."
|
|
|
warning_text = ""
|
|
|
|
|
|
# Construct the complete message
|
|
|
return f"\n\n{warning_text}{action_text}{account_info}"
|
|
|
|
|
|
@staticmethod
|
|
|
def notify(captain, other_player, tournament, message_type: TeamEmailType):
|
|
|
print("TournamentEmailService.notify", captain.email, captain.registered_online, tournament, message_type)
|
|
|
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_topic(tournament.federal_level_category, captain.time_to_confirm)
|
|
|
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, request=None, waiting_list_position=None):
|
|
|
if message_type == TeamEmailType.REGISTERED:
|
|
|
body = TournamentEmailService._build_registration_confirmation_email_body(
|
|
|
tournament, recipient, tournament_details_str, other_player
|
|
|
)
|
|
|
elif message_type == TeamEmailType.WAITING_LIST:
|
|
|
body = TournamentEmailService._build_waiting_list_confirmation_email_body(
|
|
|
tournament, recipient, tournament_details_str, other_player
|
|
|
)
|
|
|
elif 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.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
|
|
|
)
|
|
|
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):
|
|
|
# Notify both players separately if there is no captain or the captain is unavailable
|
|
|
players = list(team.players_sorted_by_captain)
|
|
|
if len(players) == 2:
|
|
|
print("TournamentEmailService.notify_team 2p", team)
|
|
|
first_player, second_player = players
|
|
|
TournamentEmailService.notify(first_player, second_player, tournament, message_type)
|
|
|
if first_player.email != second_player.email:
|
|
|
TournamentEmailService.notify(second_player, first_player, tournament, message_type)
|
|
|
elif len(players) == 1:
|
|
|
print("TournamentEmailService.notify_team 1p", team)
|
|
|
# If there's only one player, just send them the notification
|
|
|
TournamentEmailService.notify(players[0], None, tournament, message_type)
|
|
|
|
|
|
@staticmethod
|
|
|
def notify_umpire(team, tournament, message_type):
|
|
|
# Notify the umpire if needed
|
|
|
umpire_email = tournament.umpire_mail()
|
|
|
if umpire_email:
|
|
|
tournament_details_str = tournament.build_tournament_details_str()
|
|
|
|
|
|
federal_level_category = FederalLevelCategory(tournament.federal_level_category)
|
|
|
tournament_word = federal_level_category.localized_word()
|
|
|
tournament_prefix_that = federal_level_category.localized_prefix_that()
|
|
|
|
|
|
body_parts = [
|
|
|
"Email automatique suite à une désinscription",
|
|
|
f"\n\n{tournament_details_str} | {tournament.formatted_start_date()} | {tournament.event.club.name}"
|
|
|
"\n\nL'équipe ci-dessous a annulé son inscription via le site PadelClub :",
|
|
|
]
|
|
|
|
|
|
for player in team.players_sorted_by_rank:
|
|
|
body_parts.append(
|
|
|
f"\n{player.name()}"
|
|
|
)
|
|
|
|
|
|
absolute_url = f"https://padelclub.app/tournament/{tournament.id}/info"
|
|
|
link_text = f"informations sur {tournament_prefix_that}{tournament_word} sur https://padelclub.app"
|
|
|
absolute_url = f'<a href="{absolute_url}">{link_text}</a>'
|
|
|
|
|
|
body_parts.append(
|
|
|
f"\n\nVoir les {absolute_url}",
|
|
|
)
|
|
|
|
|
|
body_parts.extend([
|
|
|
"\n\nCeci est un e-mail automatique."
|
|
|
])
|
|
|
|
|
|
email_body = "".join(body_parts)
|
|
|
|
|
|
if email_body is None:
|
|
|
return
|
|
|
|
|
|
topic = message_type.email_topic(tournament.federal_level_category)
|
|
|
email_subject = TournamentEmailService.email_subject(tournament, topic)
|
|
|
TournamentEmailService._send_email(umpire_email, email_subject, email_body)
|
|
|
|
|
|
@staticmethod
|
|
|
def _build_payment_info(tournament, team_registration):
|
|
|
"""
|
|
|
Build payment information section for emails
|
|
|
"""
|
|
|
if not tournament.should_request_payment():
|
|
|
return ""
|
|
|
|
|
|
if tournament.is_free():
|
|
|
return ""
|
|
|
|
|
|
# Check payment status
|
|
|
payment_status = team_registration.get_payment_status()
|
|
|
|
|
|
if payment_status == 'PAID':
|
|
|
return "\n\n✅ Le paiement de votre inscription a bien été reçu."
|
|
|
|
|
|
if team_registration.is_in_waiting_list() >= 0:
|
|
|
return ""
|
|
|
|
|
|
currency_service = CurrencyService()
|
|
|
|
|
|
# For unpaid teams, add payment instructions
|
|
|
formatted_fee = currency_service.format_amount(tournament.entry_fee, tournament.currency_code)
|
|
|
payment_info = [
|
|
|
"\n\n⚠️ Paiement des frais d'inscription requis",
|
|
|
f"Les frais d'inscription de {formatted_fee} par joueur doivent être payés pour confirmer votre participation.",
|
|
|
"Vous pouvez effectuer le paiement en vous connectant à votre compte Padel Club.",
|
|
|
f"Lien pour payer: https://padelclub.app/tournament/{tournament.id}/info"
|
|
|
]
|
|
|
|
|
|
return "\n".join(payment_info)
|
|
|
|
|
|
@staticmethod
|
|
|
def send_payment_confirmation(team_registration, payment):
|
|
|
"""
|
|
|
Send a payment confirmation email to team members
|
|
|
|
|
|
Args:
|
|
|
team_registration: The team registration
|
|
|
payment: The payment details from Stripe
|
|
|
"""
|
|
|
tournament = team_registration.tournament
|
|
|
player_registrations = team_registration.players_sorted_by_captain
|
|
|
|
|
|
# Calculate payment amount
|
|
|
payment_amount = None
|
|
|
currency_service = CurrencyService()
|
|
|
|
|
|
if payment and 'amount' in payment:
|
|
|
# Get currency from payment metadata or tournament
|
|
|
payment_currency = payment.get('currency', tournament.currency_code or 'EUR')
|
|
|
# Convert cents/minor units to standard format
|
|
|
payment_amount = currency_service.convert_from_stripe_amount(payment['amount'], payment_currency)
|
|
|
formatted_amount = currency_service.format_amount(payment_amount, payment_currency)
|
|
|
else:
|
|
|
# Fallback to tournament fee
|
|
|
formatted_amount = currency_service.format_amount(team_registration.get_team_registration_fee(), tournament.currency_code)
|
|
|
|
|
|
federal_level_category = FederalLevelCategory(tournament.federal_level_category)
|
|
|
tournament_word = federal_level_category.localized_word()
|
|
|
tournament_prefix_that = federal_level_category.localized_prefix_that()
|
|
|
processed_emails = set()
|
|
|
for player in player_registrations:
|
|
|
if not player.email or not player.registered_online:
|
|
|
continue
|
|
|
if player.email in processed_emails:
|
|
|
continue
|
|
|
processed_emails.add(player.email)
|
|
|
|
|
|
tournament_details_str = tournament.build_tournament_details_str()
|
|
|
other_player = team_registration.get_other_player(player) if len(player_registrations) > 1 else None
|
|
|
|
|
|
body_parts = [
|
|
|
"Bonjour,\n\n",
|
|
|
f"Votre paiement pour {tournament_prefix_that}{tournament_word} {tournament_details_str}, prévu le {tournament.formatted_start_date()} au club {tournament.event.club.name} a été reçu avec succès."
|
|
|
]
|
|
|
|
|
|
# Add information about the other player if available
|
|
|
if other_player:
|
|
|
body_parts.append(
|
|
|
f"\n\nVous êtes inscrit avec {other_player.name()}, n'oubliez pas de prévenir votre partenaire de la confirmation du paiement."
|
|
|
)
|
|
|
|
|
|
# Add payment details
|
|
|
body_parts.append(
|
|
|
f"\n\nMontant payé : {formatted_amount}"
|
|
|
)
|
|
|
|
|
|
payment_date = timezone.now().strftime("%d/%m/%Y")
|
|
|
body_parts.append(
|
|
|
f"\nDate du paiement : {payment_date}"
|
|
|
)
|
|
|
|
|
|
absolute_url = f"https://padelclub.app/tournament/{tournament.id}/info"
|
|
|
link_text = f"informations sur {tournament_prefix_that}{tournament_word}"
|
|
|
absolute_url = f'<a href="{absolute_url}">{link_text}</a>'
|
|
|
|
|
|
body_parts.append(f"\n\nVoir les {absolute_url}")
|
|
|
|
|
|
if tournament.team_sorting == TeamSortingType.RANK:
|
|
|
cloture_date = tournament.local_registration_federal_limit().strftime("%d/%m/%Y à %H:%M")
|
|
|
loc = ""
|
|
|
if cloture_date is not None:
|
|
|
loc = f", prévu le {cloture_date}"
|
|
|
body_parts.append(f"\n\nAttention, la sélection définitive se fera par poids d'équipe à la clôture des inscriptions{loc}.")
|
|
|
|
|
|
body_parts.extend([
|
|
|
f"\n\n{TournamentEmailService._format_umpire_contact(tournament)}",
|
|
|
"\n\nCeci est un e-mail automatique, veuillez ne pas y répondre."
|
|
|
])
|
|
|
|
|
|
email_body = "".join(body_parts)
|
|
|
|
|
|
email_subject = TournamentEmailService.email_subject(tournament, "Confirmation de paiement")
|
|
|
TournamentEmailService._send_email(player.email, email_subject, email_body)
|
|
|
|
|
|
@staticmethod
|
|
|
def send_refund_confirmation(tournament, team_registration, refund_details):
|
|
|
"""
|
|
|
Send a refund confirmation email to team members
|
|
|
|
|
|
Args:
|
|
|
tournament: The tournament
|
|
|
team_registration: The team registration
|
|
|
refund_details: The refund details from Stripe
|
|
|
"""
|
|
|
player_registrations = team_registration.players_sorted_by_captain
|
|
|
refund_amount = None
|
|
|
|
|
|
currency_service = CurrencyService()
|
|
|
|
|
|
if refund_details and 'amount' in refund_details:
|
|
|
# Get currency from refund details or tournament
|
|
|
refund_currency = refund_details.get('currency', tournament.currency_code or 'EUR')
|
|
|
# Convert cents/minor units to standard format
|
|
|
refund_amount = currency_service.convert_from_stripe_amount(refund_details['amount'], refund_currency)
|
|
|
formatted_amount = currency_service.format_amount(refund_amount, refund_currency)
|
|
|
else:
|
|
|
# Fallback to tournament fee
|
|
|
formatted_amount = currency_service.format_amount(tournament.entry_fee, tournament.currency_code)
|
|
|
|
|
|
if refund_details and 'amount' in refund_details:
|
|
|
# Convert cents to euros
|
|
|
refund_amount = refund_details['amount'] / 100
|
|
|
|
|
|
|
|
|
if refund_amount is None:
|
|
|
refund_amount = team_registration.get_remaining_fee()
|
|
|
|
|
|
federal_level_category = FederalLevelCategory(tournament.federal_level_category)
|
|
|
tournament_word = federal_level_category.localized_word()
|
|
|
tournament_prefix_that = federal_level_category.localized_prefix_that()
|
|
|
processed_emails = set()
|
|
|
for player in player_registrations:
|
|
|
if not player.email or not player.registered_online:
|
|
|
continue
|
|
|
if player.email in processed_emails:
|
|
|
continue
|
|
|
processed_emails.add(player.email)
|
|
|
|
|
|
tournament_details_str = tournament.build_tournament_details_str()
|
|
|
other_player = team_registration.get_other_player(player) if len(player_registrations) > 1 else None
|
|
|
|
|
|
body_parts = [
|
|
|
"Bonjour,\n\n",
|
|
|
f"Votre remboursement pour {tournament_prefix_that}{tournament_word} {tournament_details_str}, prévu le {tournament.formatted_start_date()} au club {tournament.event.club.name} a été traité avec succès."
|
|
|
]
|
|
|
|
|
|
# Add information about the other player if available
|
|
|
if other_player:
|
|
|
body_parts.append(
|
|
|
f"\n\nVous étiez inscrit avec {other_player.name()}, n'oubliez pas de prévenir votre partenaire du remboursement."
|
|
|
)
|
|
|
|
|
|
# Add refund details
|
|
|
body_parts.append(
|
|
|
f"\n\nMontant remboursé : {formatted_amount}"
|
|
|
)
|
|
|
|
|
|
refund_date = timezone.now().strftime("%d/%m/%Y")
|
|
|
body_parts.append(
|
|
|
f"\nDate du remboursement : {refund_date}"
|
|
|
)
|
|
|
|
|
|
absolute_url = f"https://padelclub.app/tournament/{tournament.id}/info"
|
|
|
link_text = f"informations sur {tournament_prefix_that}{tournament_word}"
|
|
|
absolute_url = f'<a href="{absolute_url}">{link_text}</a>'
|
|
|
|
|
|
body_parts.append(f"\n\nVoir les {absolute_url}")
|
|
|
|
|
|
body_parts.extend([
|
|
|
f"\n\n{TournamentEmailService._format_umpire_contact(tournament)}",
|
|
|
"\n\nCeci est un e-mail automatique, veuillez ne pas y répondre."
|
|
|
])
|
|
|
|
|
|
email_body = "".join(body_parts)
|
|
|
|
|
|
email_subject = TournamentEmailService.email_subject(tournament, "Confirmation de remboursement")
|
|
|
TournamentEmailService._send_email(player.email, email_subject, email_body)
|
|
|
|