timetoconfirm
Raz 7 months ago
parent 174e96402e
commit a19afb2299
  1. 18
      tournaments/models/team_registration.py
  2. 12
      tournaments/models/tournament.py
  3. 37
      tournaments/services/email_service.py
  4. 37
      tournaments/signals.py
  5. 16
      tournaments/tasks.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

@ -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')"""

@ -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'<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):
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

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

@ -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:

Loading…
Cancel
Save