from django.shortcuts import render, get_object_or_404 from django.contrib.auth.decorators import login_required from django.views.decorators.http import require_http_methods from django.http import HttpResponse, HttpResponseRedirect from django.db.models import Q, Min, Avg, Max, Sum from django.urls import reverse from django.contrib.auth import get_user_model User = get_user_model() from ultron.people.models import Gymnast from ultron.planning.models import Event from ultron.objective.models import Skill from .models import ( Plan, Note, Point, Chrono, Accident, MindState, LearnedSkill, HeightWeight, ChronoDetails, NumberOfRoutineDone, ) from .forms import ( PlanForm, NoteForm, ScoreForm, ChronoForm, AccidentForm, MindStateForm, HeightWeightForm, LearnedSkillForm, NumberOfRoutineDoneForm, ) from datetime import date, datetime import pendulum @login_required @require_http_methods(["GET"]) def jump_chrono_details(request, chrono_id): """Récupère toutes les informations d'un chrono""" chrono = get_object_or_404(Chrono, pk=chrono_id) sum_value = chrono.details.all().aggregate(total=Sum('value')) chrono.score = sum_value['total'] if chrono.score_type == 0: chrono.tof = Chrono.compute_tof(sum_value['total']) chrono.save() mean_value = chrono.details.all().aggregate(Avg('value')) tmp_min_value = chrono.details.all().aggregate(Min('value')) tmp_max_value = chrono.details.all().aggregate(Max('value')) min_value = mean_value['value__avg'] - (tmp_min_value['value__min'] / 20) max_value = mean_value['value__avg'] - (tmp_max_value['value__max'] / 20) context = {"chrono": chrono, "average_value": mean_value['value__avg'], "min_value": min_value, "max_value": max_value} return render(request, "followup/chronos/details.html", context) @login_required @require_http_methods(["GET"]) def chrono_listing(request, gymnast_id=None): """ Si la personne connectée est un entraîneur, la fonction récupère la liste des chronos d'un gymnaste précis ou de tout le monde. Si la personne connectée est un gymnaste, la fonction récupère la liste de ses chronos à lui/elle. Args: gymnast_id (int) identifiant d'un gymnaste """ gymnast = None if request.user.groups.filter(name='trainer').exists(): if gymnast_id: chrono_list = Chrono.objects.filter(gymnast=gymnast_id) gymnast = Gymnast.objects.get(pk=gymnast_id) else: chrono_list = Chrono.objects.all() else: chrono_list = Chrono.objects.filter( Q(gymnast__last_name=request.user.last_name) & Q(gymnast__first_name=request.user.first_name) ) context = {"chrono_list": chrono_list, "gymnast": gymnast} return render(request, "followup/chronos/list.html", context) @login_required @require_http_methods(["GET"]) def note_listing(request, gymnast_id=None): """ Si la personne connectée est un entraîneur, la fonction récupère la liste des notes d'un gymnaste précis ou de tout le monde. Si la personne connectée est un gymnaste, la fonction récupère la liste de ses notes à lui/elle. """ gymnast = None if request.user.groups.filter(name='trainer').exists(): if gymnast_id: note_list = Note.objects.filter(gymnast=gymnast_id) gymnast = Gymnast.objects.get(pk=gymnast_id) else: note_list = Note.objects.all() else: note_list = Note.objects.filter( Q(gymnast__last_name=request.user.last_name) & Q(gymnast__first_name=request.user.first_name) ) context = {"note_list": note_list, "gymnast": gymnast} return render(request, "followup/notes/list.html", context) @login_required @require_http_methods(["GET"]) def note_details(request, note_id): """ Récupère toutes les informations d'un note. """ note = get_object_or_404(Note, pk=note_id) return render(request, "followup/notes/details.html", {"note": note}) @login_required @require_http_methods(["GET", "POST"]) def note_create_or_update(request, note_id=None, gymnast_id=None): """Création ou modification d'un chrono Args: note_id (int) identifiant d'une note gymnast_id (int) identifiant d'un gymnaste TODO: pq ne puis-je pas récuperer l'idantifiant du caoch via le form. (cf ##..) """ coach = User.objects.get(pk=request.user.id)##.. if note_id: note = get_object_or_404(Note, pk=note_id) data = { "coach": coach.id,##.. "gymnast": note.gymnast.id, "gymnast_related": str(note.gymnast), } else: note = None data = { "coach": coach.id,##.. } if gymnast_id is not None: gymnast = get_object_or_404(Gymnast, pk=gymnast_id) data["gymnast"] = gymnast_id data["gymnast_related"] = str(gymnast) if request.method == "POST": form = NoteForm(request.POST, instance=note) if form.is_valid(): new_note = form.save() return HttpResponseRedirect(reverse("gymnast_details_tab", args=(new_note.gymnast.id, 'event'))) else: return render(request, "followup/notes/create.html", {'form': form}) form = NoteForm(instance=note, initial=data) context = {"form": form, "note_id": note_id} return render(request, "followup/notes/create.html", context) @login_required @require_http_methods(["GET", "POST"]) def chrono_create_or_update(request, chrono_id=None, gymnast_id=None): """Création ou modification d'un chrono""" if chrono_id: chrono = get_object_or_404(Chrono, pk=chrono_id) data = { "gymnast": chrono.gymnast.id, "gymnast_related": str(chrono.gymnast), } else: chrono = None data = None if gymnast_id is not None: gymnast = get_object_or_404(Gymnast, pk=gymnast_id) data = {"gymnast": gymnast_id, "gymnast_related": gymnast} if request.method == "POST": form = ChronoForm(request.POST, instance=chrono) if form.is_valid(): new_chrono = form.save(commit=False) if new_chrono.score_type == 1: new_chrono.tof = new_chrono.score else: new_chrono.tof = Chrono.compute_tof(new_chrono.score) new_chrono.save() return HttpResponseRedirect(reverse("gymnast_details_tab", args=(new_chrono.gymnast.id, 'scores'))) else: return render(request, "followup/chronos/create.html", {'form': form}) form = ChronoForm(instance=chrono, initial=data) context = {"form": form, "chrono_id": chrono_id} return render(request, "followup/chronos/create.html", context) @login_required @require_http_methods(["POST"]) def gymnast_learn_skill(request): """ Lie un gymnast à une figure. """ # utiliser un FORM pour cette fonction. gymnast_id = request.POST.get("gymnast_id", None) skill_id = request.POST.get("skill_id", None) learning_step = request.POST.get("learning_step", 0) if gymnast_id and skill_id: gymnast = get_object_or_404(Gymnast, pk=gymnast_id) skill = Skill.objects.get(pk=skill_id) learned_skill = LearnedSkill( gymnast=gymnast, skill=skill, learning_step=learning_step, date=datetime.now() ) learned_skill.save() return HttpResponse(status=200) if gymnast_id: print("Error : can not link Gymnast and skill. Missing Skill_ID.") else: print("Error : can not link Gymnast and skill. Missing Gymnast_ID.") return HttpResponse(status=500) @login_required @require_http_methods(["GET", "POST"]) def learnedskill_create_or_update(request, gymnast_id=None): """ Formulaire de creation et modification d'un lien skill/gymnaste. """ if gymnast_id: gymnast = get_object_or_404(Gymnast, pk=gymnast_id) data = { "gymnast": gymnast.id, "gymnast_related": str(gymnast), } else: data = None if request.method == "POST": form = LearnedSkillForm(request.POST) if form.is_valid(): form.save() return HttpResponseRedirect( reverse("gymnast_details", args=(form.cleaned_data["gymnast"].id,)) ) else: render(request, "followup/learnedskills/create.html", {"form": form}) form = LearnedSkillForm(initial=data) context = {"form": form, "gymnast_id": gymnast_id} return render(request, "followup/learnedskills/create.html", context) @login_required @require_http_methods(["GET", "POST"]) def score_create_or_update(request, score_id=None, gymnast_id=None): """ Formulaire de création d'un nouveau score. """ if score_id: score = get_object_or_404(Point, pk=score_id) data = { "gymnast_related": str(score.gymnast), "event_related": str(score.event), } else: score = None data = None if gymnast_id is not None: gymnast = get_object_or_404(Gymnast, pk=gymnast_id) data = {"gymnast": gymnast_id, "gymnast_related": str(gymnast)} if request.method == "POST": form = ScoreForm(request.POST, instance=score) if form.is_valid(): form.save() if form.cleaned_data['add_to_chrono']: new_chrono = Chrono( gymnast=form.cleaned_data["gymnast"], chrono_type=form.cleaned_data["routine_type"], score_type=1, score=form.cleaned_data["point_time_of_flight"], tof=form.cleaned_data["point_time_of_flight"], date=form.cleaned_data["event"].date_begin, ) new_chrono.save() return HttpResponseRedirect( reverse( "gymnast_details_tab", args=(form.cleaned_data["gymnast"].id, 'scores') ) ) else: render(request, "followup/scores/create.html", {"form": form}) form = ScoreForm(instance=score, initial=data) context = {"form": form, "score_id": score_id} return render(request, "followup/scores/create.html", context) @login_required @require_http_methods(["GET"]) def score_listing(request, gymnast_id=None): """ Revoie la liste des scores """ pattern = request.GET.get("pattern", None) gymnast = None if pattern: score_list = Point.objects.filter( Q(event__icontains=pattern) | Q(gymnast__icontains=pattern) ) elif gymnast_id: score_list = Point.objects.filter(gymnast=gymnast_id) gymnast = get_object_or_404(Gymnast, pk=gymnast_id) else: score_list = Point.objects.all() context = {"score_list": score_list, "gymnast": gymnast} return render(request, "followup/scores/list.html", context) @login_required @require_http_methods(["GET"]) def accident_listing(request): """ Récupère la liste des accidents. Si c'est un gymnaste qui est connecté, il ne peut récupérer que la liste de ses accidents. Si c'est un autre utilisateur (entraîneur), la liste peut répondre à un pattern si celui-ci est définit. """ if request.user.groups.filter(name='trainer').exists(): pattern = request.GET.get("pattern", None) if pattern: accident_list = Accident.objects.filter( Q(gymnast__last_name__icontains=pattern) | Q(gymnast__first_name__icontains=pattern) ) else: accident_list = Accident.objects.all() else: accident_list = Accident.objects.filter( Q(gymnast__last_name=request.user.last_name) & Q(gymnast__first_name=request.user.first_name) ) context = {"accident_list": accident_list} return render(request, "followup/accidents/list.html", context) @login_required @require_http_methods(["GET", "POST"]) def accident_create_or_update(request, accident_id=None, gymnast_id=None): """ Formulaire de création d'un nouvel accident. """ if accident_id: accident = get_object_or_404(Accident, pk=accident_id) data = { "gymnast_related": accident.gymnast, "skill_related": accident.skill, } else: accident = None data = None if gymnast_id is not None: gymnast = get_object_or_404(Gymnast, pk=gymnast_id) data = {"gymnast": gymnast_id, "gymnast_related": str(gymnast)} if request.method == "POST": form = AccidentForm(request.POST, instance=accident) if form.is_valid(): accident = form.save() return HttpResponseRedirect(reverse("accident_details", args=(accident.pk,))) else: return render(request, "followup/accidents/create.html", {"form": form}) form = AccidentForm(instance=accident, initial=data) context = {"form": form, "accident_id": accident_id} return render(request, "followup/accidents/create.html", context) @login_required @require_http_methods(["GET"]) def accident_detail(request, accident_id): """ Récupère toutes les informations d'un accident. """ accident = get_object_or_404(Accident, pk=accident_id) return render(request, "followup/accidents/details.html", {"accident": accident}) @login_required @require_http_methods(["GET"]) def mindstate_listing(request, gymnast_id=None): """ Récupère la liste des évaluations mentales suivant (d'un gymnaste si définit en paramètre). """ gymnast = None if gymnast_id: mindstate_list = MindState.objects.filter(gymnast=gymnast_id) gymnast = get_object_or_404(Gymnast, pk=gymnast_id) else: mindstate_list = MindState.objects.all() context = {"mindstate_list": mindstate_list, "gymnast": gymnast} return render(request, "followup/mindstates/list.html", context) @login_required @require_http_methods(["GET", "POST"]) def mindstate_create_or_update( request, mindstate_id=None, gymnast_id=None, event_id=None ): """ Formulaire de création d'un nouvel accident. """ if mindstate_id: mindstate = get_object_or_404(MindState, pk=mindstate_id) data = {"gymnast_related": mindstate.gymnast, "event_related": mindstate.event} else: mindstate = None data = None if gymnast_id is not None: gymnast = get_object_or_404(Gymnast, pk=gymnast_id) data = {"gymnast": gymnast_id, "gymnast_related": str(gymnast)} if event_id is not None: event = get_object_or_404(Event, pk=event_id) data = {"event": event_id, "event_related": str(event)} if request.method == "POST": form = MindStateForm(request.POST, instance=mindstate) if form.is_valid(): mindstate = form.save() return HttpResponseRedirect(reverse("mindstate_details", args=(mindstate.pk,))) else: return render(request, "followup/mindstates/create.html", {"form": form}) form = MindStateForm(instance=mindstate, initial=data) context = {"form": form, "mindstate_id": mindstate_id} return render(request, "followup/mindstates/create.html", context) @login_required @require_http_methods(["GET"]) def mindstate_detail(request, mindstate_id): """ Récupère toutes les informations d'une évaluation psychologique. """ mindstate = get_object_or_404(MindState, pk=mindstate_id) return render(request, "followup/mindstates/details.html", {"mindstate": mindstate}) @login_required @require_http_methods(["GET"]) def heightweight_listing(request, gymnast_id=None): """ Récupère la liste des couples taille/poids suivant (d'un gymnast si définit en paramètre). """ gymnast = None if gymnast_id: heightweight_list = HeightWeight.objects.filter(gymnast=gymnast_id) gymnast = Gymnast.objects.get(pk=gymnast_id) else: heightweight_list = HeightWeight.objects.all() context = {"heightweight_list": heightweight_list, "gymnast": gymnast} return render(request, "followup/heightweight/list.html", context) @login_required @require_http_methods(["GET", "POST"]) def heightweight_create_or_update(request, heightweight_id=None, gymnast_id=None): """ Formulaire de creation et modification d'un couple taille/couple. """ if heightweight_id: heightweight = get_object_or_404(HeightWeight, pk=heightweight_id) data = {"gymnast_related": heightweight.gymnast} else: heightweight = None data = None if gymnast_id: heightweight = ( HeightWeight.objects.filter(gymnast=gymnast_id) .order_by("-date") .first() ) gymnast = get_object_or_404(Gymnast, pk=gymnast_id) data = {"gymnast": gymnast_id, "gymnast_related": str(gymnast)} if request.method == "POST": form = HeightWeightForm(request.POST, instance=heightweight) if form.is_valid(): form.save() return HttpResponseRedirect( reverse("gymnast_details_tab", args=(form.cleaned_data["gymnast"].id, 'physiological')) ) else: print(form.errors) return render(request, "followup/heightweight/create.html", {"form": form}) form = HeightWeightForm(instance=heightweight, initial=data) context = { "form": form, "gymnast_id": gymnast_id, "heightweight_id": heightweight_id, } return render(request, "followup/heightweight/create.html", context) @login_required @require_http_methods(["GET"]) def routine_done_listing(request, gymnast_id=None): """ Liste tous les record de la table NumberOfRoutineDone """ if gymnast_id: gymnast = get_object_or_404(Gymnast, pk=gymnast_id) routine_done_list = gymnast.number_of_routine_done.all() else: gymnast = None routine_done_list = NumberOfRoutineDone.objects.all() context = {"routine_done_list": routine_done_list, "gymnast": gymnast} return render(request, "followup/routinedone/list.html", context) @require_http_methods(["POST"]) def increment_routinedone(request): """ Incrémente le nombre de routine faite pour aujourd'hui et incrémente, si besoin, le nombre de routine réussie """ data = { 'gymnast': get_object_or_404(Gymnast, pk=request.POST.get("gymnast_id", None)), 'routine_type': request.POST.get("routine_type", 1), 'date': request.POST.get("date", date.today()), } routine = data['gymnast'].has_routine.filter(routine_type=request.POST.get("routine_type", 1)).first() data['routine'] = routine.routine routinedone, _ = NumberOfRoutineDone.objects.get_or_create(date=data["date"], gymnast=data["gymnast"], routine_type=data["routine_type"]) data["number_of_try"] = routinedone.number_of_try + 1 success = request.POST.get("success", 0) if int(success) == 1: data["number_of_successes"] = routinedone.number_of_successes + 1 else: data["number_of_successes"] = routinedone.number_of_successes form = NumberOfRoutineDoneForm(data, instance=routinedone) if form.is_valid(): form.save() return HttpResponse(status=200) else: return HttpResponse(status=406) @login_required @require_http_methods(["GET", "POST"]) def routinedone_create_or_update(request, routinedone_id=None, gymnast_id=None): """Création ou modification d'un chrono""" if routinedone_id: routinedone = get_object_or_404(NumberOfRoutineDone, pk=routinedone_id) data = { "gymnast": routinedone.gymnast.id, "gymnast_related": str(routinedone.gymnast), "routine": routinedone.routine.id, "routine_related": str(routinedone.routine), } else: routinedone = None data = None if gymnast_id is not None: gymnast = get_object_or_404(Gymnast, pk=gymnast_id) data = {"gymnast": gymnast_id, "gymnast_related": gymnast} if request.method == "POST": form = NumberOfRoutineDoneForm(request.POST, instance=routinedone) if form.is_valid(): form.save() return HttpResponseRedirect( reverse("gymnast_details", args=(form.cleaned_data["gymnast"].id,)) ) else: return render(request, "followup/routinedone/create.html", {"form": form}) form = NumberOfRoutineDoneForm(instance=routinedone, initial=data) context = {"form": form, "routinedone_id": routinedone_id} return render(request, "followup/routinedone/create.html", context) @login_required @require_http_methods(["GET", "POST"]) def plan_create_or_update(request, plan_id=None, gymnast_id=None, skill_id=None): """Création d'un plan. Args: plan_id (int): identifiant d'un plan (classe ). gymnast_id (int): identifiant d'un gymnaste (classe ). skill_id (int): identifiant d'un skill (classe ). """ if plan_id: plan = get_object_or_404(Plan, pk=plan_id) data = { "gymnast": plan.gymnast.id, "gymnast_related": str(plan.gymnast), "skill": plan.skill.id, "skill_related": str(plan.skill), } else: plan = None data = {} if gymnast_id: gymnast = get_object_or_404(Gymnast, pk=gymnast_id) data["gymnast"] = gymnast_id data["gymnast_related"] = str(gymnast) if skill_id: skill = get_object_or_404(Skill, pk=skill_id) data["educative"] = skill_id data["educative_related"] = str(skill) if request.method == "POST": form = PlanForm(request.POST, instance=plan) if form.is_valid(): plan = form.save() return HttpResponseRedirect( reverse("gymnast_details", args=(form.cleaned_data["gymnast"].id,)) ) else: return render(request, "followup/plan/create.html", {"form": form}) form = PlanForm(instance=plan, initial=data) context = {"form": form, "plan_id": plan_id} return render(request, "followup/plan/create.html", context)