You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
71 lines
2.3 KiB
71 lines
2.3 KiB
from channels.layers import get_channel_layer |
|
from asgiref.sync import async_to_sync |
|
|
|
from django.shortcuts import render, redirect |
|
from django.contrib.auth.decorators import login_required |
|
from courses.models import Course, Arrivee |
|
from coureurs.models import Coureur |
|
from django.utils import timezone |
|
|
|
from courses.templatetags.temps_format import seconds_to_hms |
|
from .forms import ScanForm |
|
|
|
@login_required |
|
def scan_view(request): |
|
from django.shortcuts import get_object_or_404 |
|
courses = Course.objects.filter(depart__isnull=False, fin__isnull=True) |
|
result = None |
|
error = None |
|
course = None |
|
# Traitement AJAX POST |
|
if request.method == 'POST' and request.headers.get('x-requested-with') == 'XMLHttpRequest': |
|
course_id = request.POST.get('course_id') |
|
qrcode = request.POST.get('qrcode') |
|
if not course_id or not qrcode: |
|
error = "Paramètres manquants." |
|
elif qrcode.count(';') != 1: |
|
error = "Format QR code invalide." |
|
else: |
|
nom, classe = qrcode.split(';') |
|
course = get_object_or_404(Course, id=course_id) |
|
if not course.depart: |
|
error = "La course n'a pas démarré." |
|
else: |
|
coureur, _ = Coureur.objects.get_or_create(nom=nom.strip(), classe=classe.strip()) |
|
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 |
|
Arrivee.objects.create(course=course, coureur=coureur, temps=temps, rang=rang) |
|
result = { |
|
'nom': coureur.nom, |
|
'classe': coureur.classe, |
|
'rang': rang, |
|
'temps': str(seconds_to_hms(temps)) |
|
} |
|
# Broadcast websocket |
|
channel_layer = get_channel_layer() |
|
async_to_sync(channel_layer.group_send)( |
|
f'course_{course.id}', |
|
{ |
|
'type': 'send_arrivee', |
|
'data': result |
|
} |
|
) |
|
# Retourne juste le fragment HTML pour scanResult |
|
if result: |
|
return render(request, 'scan_result.html', {'result': result}) |
|
else: |
|
return render(request, 'scan_result.html', {'error': error}) |
|
# Affichage classique GET |
|
else: |
|
course_id = request.GET.get('course_id') |
|
if course_id: |
|
course = get_object_or_404(Course, id=course_id) |
|
return render(request, 'scan.html', { |
|
'courses': courses, |
|
'result': result, |
|
'error': error, |
|
'course': course |
|
})
|
|
|