From 58b9a821de5b2f2d128b092a28a530a6bc0f462e Mon Sep 17 00:00:00 2001 From: scayac Date: Thu, 9 Oct 2025 22:35:14 +0200 Subject: [PATCH] =?UTF-8?q?Interdiction=20du=20scan=20quand=20course=20ter?= =?UTF-8?q?min=C3=A9e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main/templates/scan.html | 4 ++ main/views.py | 123 ++++++++++++++++++++------------------- 2 files changed, 68 insertions(+), 59 deletions(-) diff --git a/main/templates/scan.html b/main/templates/scan.html index 94ac612..5932ba7 100644 --- a/main/templates/scan.html +++ b/main/templates/scan.html @@ -9,6 +9,9 @@
Scanner un coureur
+ {% if course and course.fin %} +
Cette course est terminée. Le scan n'est plus possible.
+ {% else %}
@@ -22,6 +25,7 @@ {% if error %}
{{ error }}
{% endif %} + {% endif %}
diff --git a/main/views.py b/main/views.py index 3b3fddd..d14ff8f 100644 --- a/main/views.py +++ b/main/views.py @@ -273,6 +273,7 @@ def scan_view(request): error = None course = None + if request.method == 'POST' and request.headers.get('x-requested-with') == 'XMLHttpRequest': course_id = request.POST.get('course_id') qrcode = request.POST.get('qrcode') @@ -281,72 +282,74 @@ def scan_view(request): else: # S'assurer que l'utilisateur scanne uniquement ses propres courses course = get_object_or_404(Course, id=course_id, owner=request.user) - - # Le QR code contient maintenant l'identifiant unique du Coureur - coureur = None - try: - coureur = Coureur.objects.get(id=qrcode.strip()) - except Coureur.DoesNotExist: - error = "Coureur introuvable pour ce code QR." - - if coureur: - # Si la course est de type unique : comportement existant (1 arrivée par coureur) - if course.type == Course.TYPE_UNIQUE: - if Arrivee.objects.filter(course=course, coureur=coureur).exists(): - error = "Ce coureur a déjà été scanné." + if course.fin: + error = "Cette course est terminée. Le scan n'est plus possible." + else: + # Le QR code contient maintenant l'identifiant unique du Coureur + coureur = None + try: + coureur = Coureur.objects.get(id=qrcode.strip()) + except Coureur.DoesNotExist: + error = "Coureur introuvable pour ce code QR." + + if coureur: + # Si la course est de type unique : comportement existant (1 arrivée par coureur) + if course.type == Course.TYPE_UNIQUE: + if Arrivee.objects.filter(course=course, coureur=coureur).exists(): + error = "Ce coureur a déjà été scanné." + else: + temps = timezone.now() - course.depart + rang = Arrivee.objects.filter(course=course).count() + 1 + arr = Arrivee.objects.create(course=course, coureur=coureur, temps=temps, rang=rang, tour=1) + temps_str = seconds_to_hms(temps) + # nombre total de scans pour cette course + scan_count = Arrivee.objects.filter(course=course).count() + result = { + 'nom': coureur.nom, + 'prenom': coureur.prenom, + 'classe': coureur.classe, + 'rang': arr.rang, + 'temps': temps_str, + 'tour': arr.tour, + 'scan_count': scan_count + } + # Pour les courses multi, autoriser plusieurs scans par coureur et calculer le tour/temps de tour else: - temps = timezone.now() - course.depart + # Compter les arrivées précédentes pour ce coureur sur cette course + previous = Arrivee.objects.filter(course=course, coureur=coureur).order_by('tour', 'date_arrivee') + last_arr = previous.last() + if last_arr: + # prochain tour = dernier tour + 1 + next_tour = last_arr.tour + 1 + lap_time = timezone.now() - last_arr.date_arrivee + else: + # premier scan pour ce coureur : tour 1, temps depuis le départ de la course + next_tour = 1 + lap_time = timezone.now() - course.depart + # rang = nombre d'arrivées global + 1 rang = Arrivee.objects.filter(course=course).count() + 1 - arr = Arrivee.objects.create(course=course, coureur=coureur, temps=temps, rang=rang, tour=1) - temps_str = seconds_to_hms(temps) - # nombre total de scans pour cette course + arr = Arrivee.objects.create(course=course, coureur=coureur, temps=lap_time, rang=rang, tour=next_tour) + lap_str = seconds_to_hms(lap_time) scan_count = Arrivee.objects.filter(course=course).count() result = { 'nom': coureur.nom, 'prenom': coureur.prenom, 'classe': coureur.classe, 'rang': arr.rang, - 'temps': temps_str, + 'temps': lap_str, 'tour': arr.tour, + 'lap_seconds': int(lap_time.total_seconds()), 'scan_count': scan_count } - # Pour les courses multi, autoriser plusieurs scans par coureur et calculer le tour/temps de tour - else: - # Compter les arrivées précédentes pour ce coureur sur cette course - previous = Arrivee.objects.filter(course=course, coureur=coureur).order_by('tour', 'date_arrivee') - last_arr = previous.last() - if last_arr: - # prochain tour = dernier tour + 1 - next_tour = last_arr.tour + 1 - lap_time = timezone.now() - last_arr.date_arrivee - else: - # premier scan pour ce coureur : tour 1, temps depuis le départ de la course - next_tour = 1 - lap_time = timezone.now() - course.depart - # rang = nombre d'arrivées global + 1 - rang = Arrivee.objects.filter(course=course).count() + 1 - arr = Arrivee.objects.create(course=course, coureur=coureur, temps=lap_time, rang=rang, tour=next_tour) - lap_str = seconds_to_hms(lap_time) - scan_count = Arrivee.objects.filter(course=course).count() - result = { - 'nom': coureur.nom, - 'prenom': coureur.prenom, - 'classe': coureur.classe, - 'rang': arr.rang, - 'temps': lap_str, - 'tour': arr.tour, - 'lap_seconds': int(lap_time.total_seconds()), - 'scan_count': scan_count - } - # Diffuser via le canal websocket - channel_layer = get_channel_layer() - async_to_sync(channel_layer.group_send)( - f'course_{course.id}', - { - 'type': 'send_arrivee', - 'data': result - } - ) + # Diffuser via le canal websocket + channel_layer = get_channel_layer() + async_to_sync(channel_layer.group_send)( + f'course_{course.id}', + { + 'type': 'send_arrivee', + 'data': result + } + ) if result: return render(request, 'scan_result.html', {'result': result, 'course_type': course.type if course else None}) @@ -357,17 +360,19 @@ def scan_view(request): course_id = request.GET.get('course_id') if course_id: course = get_object_or_404(Course, id=course_id, owner=request.user) + if course.fin: + error = "Cette course est terminée. Le scan n'est plus possible." # Formatage de la date pour affichage JJ/MM/AAAA - date_str = format_date(course.date) if course else '' + date_str = format_date(course.date) if course_id and 'course' in locals() else '' # nombre actuel de scans pour cette course - scan_count = Arrivee.objects.filter(course=course).count() if course else 0 + scan_count = Arrivee.objects.filter(course=course).count() if course_id and 'course' in locals() else 0 return render(request, 'scan.html', { - 'title': f'Scan course : {course.nom} ({date_str})' if course else '', + 'title': f'Scan course : {course.nom} ({date_str})' if course_id and 'course' in locals() else '', 'courses': courses, 'result': result, 'error': error, - 'course': course, + 'course': course if course_id and 'course' in locals() else None, 'scan_count': scan_count })