fix ttc bugs

timetoconfirm
Raz 7 months ago
parent 05296bbb64
commit 715972b115
  1. 2
      tournaments/apps.py
  2. 3
      tournaments/models/tournament.py
  3. 18
      tournaments/services/email_service.py
  4. 6
      tournaments/signals.py
  5. 2
      tournaments/static/tournaments/css/style.css
  6. 3
      tournaments/tasks.py
  7. 131
      tournaments/templates/tournaments/tournament_info.html
  8. 6
      tournaments/views.py

@ -18,7 +18,7 @@ class TournamentsConfig(AppConfig):
Task.objects.filter(task_name='tournaments.tasks.check_confirmation_deadlines').delete() Task.objects.filter(task_name='tournaments.tasks.check_confirmation_deadlines').delete()
# Schedule the task to run every 30 minutes (1800 seconds) # Schedule the task to run every 30 minutes (1800 seconds)
check_confirmation_deadlines(repeat=1800) check_confirmation_deadlines(repeat=settings.BACKGROUND_TASK_REPEAT_INTERVAL * 60)
except: except:
# Handle exceptions during startup # Handle exceptions during startup
pass pass

@ -1488,9 +1488,6 @@ class Tournament(BaseModel):
if self.enable_time_to_confirm is False: if self.enable_time_to_confirm is False:
return None return None
if waiting_list_count == 0:
return None
config = settings.TOURNAMENT_SETTINGS['TIME_TO_CONFIRM'] config = settings.TOURNAMENT_SETTINGS['TIME_TO_CONFIRM']
TIME_PROXIMITY_RULES = config['TIME_PROXIMITY_RULES'] TIME_PROXIMITY_RULES = config['TIME_PROXIMITY_RULES']
WAITING_LIST_RULES = config['WAITING_LIST_RULES'] WAITING_LIST_RULES = config['WAITING_LIST_RULES']

@ -17,7 +17,17 @@ class TeamEmailType(Enum):
WALKOUT = "walkout" WALKOUT = "walkout"
UNEXPECTED_OUT_OF_TOURNAMENT = 'unexpected_out_of_tournament' UNEXPECTED_OUT_OF_TOURNAMENT = 'unexpected_out_of_tournament'
def email_subject(self) -> str: 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
]
if time_to_confirm and self in confirmation_types:
return "Participation en attente de confirmation"
else:
subjects = { subjects = {
self.REGISTERED: "Participation confirmée", self.REGISTERED: "Participation confirmée",
self.WAITING_LIST: "Liste d'attente", self.WAITING_LIST: "Liste d'attente",
@ -213,7 +223,7 @@ class TournamentEmailService:
def _build_out_of_tournament_email_body(tournament, captain, tournament_details_str, other_player): def _build_out_of_tournament_email_body(tournament, captain, tournament_details_str, other_player):
body_parts = [ body_parts = [
"Bonjour,\n\n", "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}" f"Suite à une modification de la taille du tournoi, vous avez été placé en liste d'attente. Votre participation au tournoi {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" absolute_url = f"https://padelclub.app/tournament/{tournament.id}/info"
@ -295,7 +305,7 @@ class TournamentEmailService:
def _build_unexpected_out_of_tournament_email_body(tournament, captain, tournament_details_str, other_player): def _build_unexpected_out_of_tournament_email_body(tournament, captain, tournament_details_str, other_player):
body_parts = [ body_parts = [
"Bonjour,\n\n", "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}" f"En raison d'une décision du juge-arbitre, vous avez été placé en liste d'attente. Votre participation au tournoi {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" absolute_url = f"https://padelclub.app/tournament/{tournament.id}/info"
@ -415,7 +425,7 @@ class TournamentEmailService:
if email_body is None: if email_body is None:
return return
topic = message_type.email_subject() topic = message_type.email_subject(captain.time_to_confirm)
email_subject = TournamentEmailService.email_subject(tournament, topic) email_subject = TournamentEmailService.email_subject(tournament, topic)
TournamentEmailService._send_email(captain.email, email_subject, email_body) TournamentEmailService._send_email(captain.email, email_subject, email_body)

@ -131,6 +131,7 @@ def check_waiting_list(sender, instance, **kwargs):
notify_team(team.team_registration, instance, TeamEmailType.IN_TOURNAMENT_STRUCTURE) notify_team(team.team_registration, instance, TeamEmailType.IN_TOURNAMENT_STRUCTURE)
for team in teams_out_to_warn: for team in teams_out_to_warn:
team.team_registration.set_time_to_confirm(None)
notify_team(team.team_registration, instance, TeamEmailType.OUT_OF_TOURNAMENT_STRUCTURE) notify_team(team.team_registration, instance, TeamEmailType.OUT_OF_TOURNAMENT_STRUCTURE)
@receiver(pre_save, sender=TeamRegistration) @receiver(pre_save, sender=TeamRegistration)
@ -160,7 +161,7 @@ def warn_team_walkout_status_change(sender, instance, **kwargs):
if not instance.out_of_tournament() and is_out and (previous_instance.out_of_tournament() or not was_out): if not instance.out_of_tournament() and is_out and (previous_instance.out_of_tournament() or not was_out):
notify_team(instance, instance.tournament, TeamEmailType.OUT_OF_WALKOUT_WAITING_LIST) notify_team(instance, instance.tournament, TeamEmailType.OUT_OF_WALKOUT_WAITING_LIST)
elif was_out and not is_out: elif was_out and not is_out:
waiting_list_teams = instance.tournament.waiting_list_teams(previous_teams) waiting_list_teams = instance.tournament.waiting_list_teams(current_teams)
if waiting_list_teams is not None: if waiting_list_teams is not None:
ttc = instance.tournament.calculate_time_to_confirm(len(waiting_list_teams)) ttc = instance.tournament.calculate_time_to_confirm(len(waiting_list_teams))
instance.set_time_to_confirm(ttc) instance.set_time_to_confirm(ttc)
@ -171,11 +172,12 @@ def warn_team_walkout_status_change(sender, instance, **kwargs):
if was_out and not is_out: if was_out and not is_out:
first_out_of_list = instance.tournament.first_waiting_list_team(current_teams) first_out_of_list = instance.tournament.first_waiting_list_team(current_teams)
if first_out_of_list: if first_out_of_list:
first_out_of_list.set_time_to_confirm(None)
notify_team(first_out_of_list, instance.tournament, TeamEmailType.UNEXPECTED_OUT_OF_TOURNAMENT) notify_team(first_out_of_list, instance.tournament, TeamEmailType.UNEXPECTED_OUT_OF_TOURNAMENT)
elif not was_out and is_out: elif not was_out and is_out:
first_waiting_list_team = instance.tournament.first_waiting_list_team(previous_teams) first_waiting_list_team = instance.tournament.first_waiting_list_team(previous_teams)
if first_waiting_list_team: if first_waiting_list_team:
waiting_list_teams = instance.tournament.waiting_list_teams(previous_teams) waiting_list_teams = instance.tournament.waiting_list_teams(current_teams)
if waiting_list_teams is not None: if waiting_list_teams is not None:
ttc = instance.tournament.calculate_time_to_confirm(len(waiting_list_teams)) ttc = instance.tournament.calculate_time_to_confirm(len(waiting_list_teams))
first_waiting_list_team.set_time_to_confirm(ttc) first_waiting_list_team.set_time_to_confirm(ttc)

@ -162,7 +162,7 @@ tr {
.rounded-button { .rounded-button {
background-color: #fae7ce; /* Green background */ background-color: #fae7ce; /* Green background */
color: #505050; /* White text */ color: #505050; /* White text */
padding: 15px 32px; /* Some padding */ padding: 12px 24px; /* Some padding */
font-size: 1em; font-size: 1em;
font-weight: 800; font-weight: 800;
cursor: pointer; /* Add a mouse pointer on hover */ cursor: pointer; /* Add a mouse pointer on hover */

@ -1,12 +1,13 @@
from background_task import background from background_task import background
from django.utils import timezone from django.utils import timezone
from django.db import transaction from django.db import transaction
from django.conf import settings
from .models import PlayerRegistration from .models import PlayerRegistration
from .models.enums import RegistrationStatus from .models.enums import RegistrationStatus
from .services.email_service import TournamentEmailService, TeamEmailType from .services.email_service import TournamentEmailService, TeamEmailType
@background(schedule=1) # Run every 30 minutes (30*60 seconds) @background(schedule=settings.BACKGROUND_SCHEDULED_TASK_INTERVAL * 60) # Run every 30 minutes (30*60 seconds)
def check_confirmation_deadlines(): def check_confirmation_deadlines():
""" """
Periodic task to check for expired confirmation deadlines Periodic task to check for expired confirmation deadlines

@ -14,38 +14,10 @@
<div class="grid-x"> <div class="grid-x">
<div class="cell medium-6 large-6 padding10"> <div class="cell medium-12 large-6 padding10">
{% if tournament.enable_online_registration and team %} {% if tournament.enable_online_registration and team %}
<h1 class="club padding10 topmargin20">Votre équipe</h1 > <h1 class="club padding10 topmargin20">Votre équipe</h1 >
<div class="bubble"> <div class="bubble">
{% if team.needs_confirmation %}
<div class="alert {% if team.get_confirmation_deadline %}alert-warning{% else %}alert-info{% endif %}">
<h4 class="semibold">Confirmation requise</h4>
<p>Votre place dans le tournoi a été libérée suite à une désinscription.</p>
{% if tournament.should_request_payment and tournament.online_payment_is_mandatory %}
<p>Vous devez payer votre participation pour confirmer votre inscription.</p>
{% endif %}
{% if team.get_confirmation_deadline %}
{% timezone tournament.timezone %}
{% with time_to_confirm=team.get_confirmation_deadline %}
{% now "Y-m-d H:i:s" as current_time_str %}
{% if time_to_confirm %}
{% if time_to_confirm|date:"Y-m-d H:i:s" > current_time_str %}
<p>Vous devez confirmer votre participation avant le:</p>
<p class="semibold highlight">{{ time_to_confirm|date:"d/m/Y à H:i" }}</p>
<p>Temps restant: <span class="countdown-timer">{{ time_to_confirm|timeuntil }}</span></p>
{% else %}
<p class="alert alert-danger">
Le délai de confirmation est expiré. Votre place a été proposée à une autre équipe.
</p>
{% endif %}
{% endif %}
{% endwith %}
{% endtimezone %}
{% endif %}
</div>
{% endif %}
{% if messages %} {% if messages %}
<div class="messages"> <div class="messages">
{% for message in messages %} {% for message in messages %}
@ -55,7 +27,6 @@
{% endfor %} {% endfor %}
</div> </div>
{% endif %} {% endif %}
<div class="alert"> <div class="alert">
{% if team.is_in_waiting_list >= 0 %} {% if team.is_in_waiting_list >= 0 %}
Tournoi complet, vous êtes en liste d'attente. Tournoi complet, vous êtes en liste d'attente.
@ -81,6 +52,33 @@
<div>Inscrits le {{ team.local_registration_date }}</div> <div>Inscrits le {{ team.local_registration_date }}</div>
</p> </p>
{% if team.needs_confirmation %}
<h4 class="semibold">Confirmation requise</h4>
<div>Une place dans le tournoi a été libérée !</div>
{% if tournament.should_request_payment and tournament.online_payment_is_mandatory %}
<div>Vous devez payer votre inscription pour confirmer votre participation.</div>
{% endif %}
{% if team.get_confirmation_deadline %}
{% timezone tournament.timezone %}
{% with time_to_confirm=team.get_confirmation_deadline %}
{% now "Y-m-d H:i:s" as current_time_str %}
{% if time_to_confirm %}
{% if time_to_confirm|date:"Y-m-d H:i:s" > current_time_str %}
<div>Vous devez confirmer votre participation avant le : </div>
<p class="semibold alert">{{ time_to_confirm|date:"d/m/Y à H:i" }}</p>
<p>Temps restant: <span class="countdown-timer">{{ time_to_confirm|timeuntil }}</span></p>
{% else %}
<p class="alert alert-danger">
Le délai de confirmation est expiré. Votre place a été proposée à une autre équipe.
</p>
{% endif %}
{% endif %}
{% endwith %}
{% endtimezone %}
{% endif %}
{% endif %}
{% if team.call_date %} {% if team.call_date %}
<div class="topmargin20"> <div class="topmargin20">
<h4 class="semibold">Convocation</h4> <h4 class="semibold">Convocation</h4>
@ -109,58 +107,55 @@
<!-- Payment status information --> <!-- Payment status information -->
{% if tournament.should_request_payment and team.is_in_waiting_list < 0 %} {% if tournament.should_request_payment and team.is_in_waiting_list < 0 %}
<div class="topmargin20"> <div class="topmargin20">
<h4 class="semibold">Paiement</h4>
{% if team.is_paid %} {% if team.is_paid %}
<div class="success-message"> <div class="success-message topmargin20">
<span class="icon"></span> Paiement confirmé <span class="icon"></span> Paiement confirmé
</div> </div>
{% else %} {% else %}
<div> <a href="{% url 'proceed_to_payment' tournament.id %}" class="rounded-button positive-button">
<a href="{% url 'proceed_to_payment' tournament.id %}" class="rounded-button positive-button"> {% if team.needs_confirmation %}
{% if team.needs_confirmation %} Confirmer en payant ({{ team.get_remaining_fee }}€)
Confirmer en payant ({{ team.get_remaining_fee }}€) {% else %}
{% else %} Procéder au paiement ({{ team.get_remaining_fee }}€)
Procéder au paiement ({{ team.get_remaining_fee }}€) {% endif %}
{% endif %} </a>
</a>
</div>
{% endif %} {% endif %}
</div> </div>
{% endif %} {% endif %}
{% if team.needs_confirmation and tournament.online_payment_is_mandatory is False %} {% if team.needs_confirmation and tournament.online_payment_is_mandatory is False %}
<div class="alert {% if team.get_confirmation_deadline %}alert-warning{% else %}alert-info{% endif %}"> <div class="topmargin20">
<form method="post" action="{% url 'confirm_tournament_registration' tournament.id %}"> <form method="post" action="{% url 'confirm_tournament_registration' tournament.id %}">
{% csrf_token %} {% csrf_token %}
<button type="submit" class="rounded-button positive-button"> <button type="submit" class="rounded-button positive-button">
Confirmer ma participation Confirmer ma participation
</button> </button>
</form> </form>
</div> </div>
{% endif %} {% endif %}
{% if tournament.is_unregistration_possible %} {% if tournament.is_unregistration_possible %}
<div> <div class="topmargin20">
{% if tournament.is_refund_possible and team.is_paid %} {% if tournament.is_refund_possible and team.is_paid %}
<p class="minor info"> <p class="minor info">
Si vous vous désinscrivez, votre inscription sera remboursée automatiquement sur votre carte bancaire. Si vous vous désinscrivez, votre inscription sera remboursée automatiquement sur votre carte bancaire.
{% if tournament.refund_date_limit %} {% if tournament.refund_date_limit %}
<div>Remboursement possible jusqu'au {{ tournament.refund_date_limit|date:"d/m/Y à H:i" }}</div> <div>Remboursement possible jusqu'au {{ tournament.refund_date_limit|date:"d/m/Y à H:i" }}</div>
{% endif %}
</p>
{% endif %} {% endif %}
</p>
<a href="{% url 'unregister_tournament' tournament.id %}" {% endif %}
class="rounded-button destructive-button" <div style="margin-top: 40px;">
onclick="return confirm('Êtes-vous sûr de vouloir vous désinscrire ?{% if tournament.is_refund_possible and team.is_paid %} Votre inscription sera remboursée automatiquement.{% endif %}');"> <a href="{% url 'unregister_tournament' tournament.id %}"
{% if team.is_in_waiting_list >= 0 %} class="rounded-button destructive-button"
Se retirer de la liste d'attente onclick="return confirm('Êtes-vous sûr de vouloir vous désinscrire ?{% if tournament.is_refund_possible and team.is_paid %} Votre inscription sera remboursée automatiquement.{% endif %}');">
{% else %} {% if team.is_in_waiting_list >= 0 %}
Se désinscrire Se retirer de la liste d'attente
{% endif %} {% else %}
</a> Se désinscrire
{% endif %}
</a>
</div> </div>
{% endif %} {% endif %}
</div>
</div> </div>
{% endif %} {% endif %}
<h1 class="club padding10 topmargin20">{{ tournament.display_name }} {{ tournament.get_federal_age_category_display}}</h1> <h1 class="club padding10 topmargin20">{{ tournament.display_name }} {{ tournament.get_federal_age_category_display}}</h1>

@ -1073,16 +1073,16 @@ def confirm_tournament_registration(request, tournament_id):
if not team_registrations.exists(): if not team_registrations.exists():
messages.error(request, "Aucune inscription trouvée pour ce tournoi.") messages.error(request, "Aucune inscription trouvée pour ce tournoi.")
return redirect('tournament_info', tournament_id=tournament_id) return redirect('tournament-info', tournament_id=tournament_id)
team_registration = team_registrations.first() team_registration = team_registrations.first()
# Confirm registration # Confirm registration
team_registration.confirm_registration() team_registration.confirm_registration()
messages.success(request, "Votre participation est confirmée !") messages.success(request, "Votre participation est confirmée !")
return redirect('tournament_info', tournament_id=tournament_id) return redirect('tournament-info', tournament_id=tournament_id)
return redirect('tournament_info', tournament_id=tournament_id) return redirect('tournament-info', tournament_id=tournament_id)
@login_required @login_required
def proceed_to_payment(request, tournament_id): def proceed_to_payment(request, tournament_id):

Loading…
Cancel
Save