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, JsonResponse from django.db.models import Q, Min, Avg, Max, Sum from django.urls import reverse from django.conf import settings from django.contrib.auth import get_user_model from django.contrib.contenttypes.models import ContentType from django.core.mail import send_mail from jarvis.people.models import Gymnast from jarvis.planning.models import Event from jarvis.objective.models import Skill from .models import ( CHRONO_TYPE_CHOICE, SCORE_TYPE_CHOICE, INJURY_MECHANISM_CHOICE, INJURY_BODY_SIDE_CHOICE, INJURY_TYPE_CHOICE, INJURY_LOCATION_CHOICE, ) from .models import ( Plan, Note, Point, Chrono, Injury, WellBeing, Intensity, LearnedSkill, HeightWeight, ChronoDetails, GymnastHasRoutine, SeasonInformation, NumberOfRoutineDone, ) from .forms import ( PlanForm, NoteForm, ScoreForm, ChronoForm, InjuryForm, WellBeingForm, IntensityForm, HeightWeightForm, LearnedSkillForm, SeasonInformationForm, NumberOfRoutineDoneForm, ) from jarvis.tools.date_week_transition import ( from_date_to_week_number, from_week_number_to_date, ) from jarvis.tools.models import Season from datetime import date, datetime import pendulum User = get_user_model() MAIL_HEADER = """
Gregory TrullemansBonjour,
Une nouvelle note vous a été envoyée. Vous pouvez la consulter en cliquant ici.
Excellente journée
Jarvis
""", ) return HttpResponseRedirect( reverse("gymnast_details_tab", args=(new_note.gymnast.id, "event")) ) else: return render(request, "notes/create.html", {"form": form}) else: last_note = ( Note.objects.filter(gymnast=gymnast_id, status=1).order_by("-date").first() ) if last_note: data["informations"] = last_note.informations form = NoteForm(instance=note, initial=data) context = {"form": form, "note_id": note_id} return render(request, "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 Args: chrono_id (int) identifiant d'un chrono gymnast_id (int) identifiant d'un gymnaste """ 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() # notification receiver = [] score = form.cleaned_data["score"] score_type = form.cleaned_data["score_type"] chrono_type = form.cleaned_data["chrono_type"] gymnast = Gymnast.objects.get(pk=form.cleaned_data["gymnast"].id) functionality = ContentType.objects.get(model="chrono") for notification in gymnast.notifications.filter( functionality=functionality ): receiver.append(notification.user.email) send_mail( f"{gymnast} : Nouveau chrono", f"Un nouveau chrono enregistré pour {gymnast}", settings.EMAIL_HOST_USER, receiver, fail_silently=False, html_message=f"""Bonjour,
Nouveau chrono pour {gymnast} : {SCORE_TYPE_CHOICE[score_type][1]} {CHRONO_TYPE_CHOICE[chrono_type][1]} - {score}.
Excellente journée
Jarvis
""", ) return HttpResponseRedirect( reverse("gymnast_details_tab", args=(new_chrono.gymnast.id, "scores")) ) else: return render(request, "chronos/create.html", {"form": form}) form = ChronoForm(instance=chrono, initial=data) context = {"form": form, "chrono_id": chrono_id} return render(request, "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. Args: gymnast_id (int) identifiant d'un 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() # notification receiver = [] skill = form.cleaned_data["skill"] learning_step = form.cleaned_data["learning_step"] gymnast = Gymnast.objects.get(pk=form.cleaned_data["gymnast"].id) functionality = ContentType.objects.get(model="learnedskill") for notification in gymnast.notifications.filter( functionality=functionality ): receiver.append(notification.user.email) send_mail( f"{gymnast} : Nouveau skill appris", f"Un nouveau skill a été appris par {gymnast}", settings.EMAIL_HOST_USER, receiver, fail_silently=False, html_message=f"""Bonjour,
{gymnast} a appris {skill} ({learning_step}).
Excellente journée
Jarvis
""", ) 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, "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. Args: score_id (int) identifiant d'un score gymnast_id (int) identifiant d'un gymnaste """ 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() # notification receiver = [] gymnast = Gymnast.objects.get(pk=form.cleaned_data["gymnast"].id) event = form.cleaned_data["event"] routine_type = form.cleaned_data["routine_type"] total = form.cleaned_data["total"] functionality = ContentType.objects.get(model="point") for notification in gymnast.notifications.filter( functionality=functionality ): receiver.append(notification.user.email) send_mail( f"{gymnast} : Nouveau score enregistré", f"Un nouveau score a été enregistré pour {gymnast}", settings.EMAIL_HOST_USER, receiver, fail_silently=False, html_message=f"""Bonjour,
Un nouveau score a été enregistré pour {gymnast} ({event}) : {routine_type} - {total}.
Excellente journée
Jarvis
""", ) 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, "scores/create.html", context) @login_required @require_http_methods(["GET"]) def score_listing(request, gymnast_id=None): """ Revoie la liste des scores Args: gymnast_id (int) identifiant d'un gymnaste """ 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, "scores/list.html", context) @login_required @require_http_methods(["GET"]) def injuries_listing(request): """ Récupère la liste des bessures. Si c'est un gymnaste qui est connecté, il ne peut récupérer que la liste de ses blessures. 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: injuries_list = Injury.objects.filter( Q(gymnast__last_name__icontains=pattern) | Q(gymnast__first_name__icontains=pattern) ) else: injuries_list = Injury.objects.all() else: injuries_list = Injury.objects.filter( Q(gymnast__last_name=request.user.last_name) & Q(gymnast__first_name=request.user.first_name) ) context = {"injuries_list": injuries_list} return render(request, "injuries/list.html", context) @login_required @require_http_methods(["GET", "POST"]) def injury_create_or_update(request, injury_id=None, gymnast_id=None): """ Formulaire de création d'un nouvel blessure. Args: injury_id (int) identifiant d'une blessure gymnast_id (int) identifiant d'un gymnaste """ if injury_id: injury = get_object_or_404(Injury, pk=injury_id) data = { "gymnast_related": injury.gymnast, "skill_related": injury.skill, } else: injury = 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 = InjuryForm(request.POST, instance=injury) if form.is_valid(): injury = form.save() # notification receiver = [] gymnast = Gymnast.objects.get(pk=form.cleaned_data["gymnast"].id) location = form.cleaned_data["location"] injury_type = form.cleaned_data["injury_type"] body_side = form.cleaned_data["body_side"] mechanism = form.cleaned_data["mechanism"] date = form.cleaned_data["date"] functionality = ContentType.objects.get(model="injury") for notification in gymnast.notifications.filter( functionality=functionality ): receiver.append(notification.user.email) send_mail( f"{gymnast} : Nouvelle blessure enregistrée", f"Une nouvelle blessure enregistrée pour {gymnast}", settings.EMAIL_HOST_USER, receiver, fail_silently=False, html_message=f"""Bonjour,
Un nouvelle blessure enregistrée pour {gymnast} pour le {date.strftime('%d %B %Y')}:
Excellente journée
Jarvis
""", ) return HttpResponseRedirect(reverse("injury_details", args=(injury.pk,))) else: return render(request, "injuries/create.html", {"form": form}) form = InjuryForm(instance=injury, initial=data) context = {"form": form, "injury_id": injury_id} return render(request, "injuries/create.html", context) @login_required @require_http_methods(["GET"]) def injury_detail(request, injury_id): """ Récupère toutes les informations d'une blessure. Args: injury_id (int) identifiant d'une blessure """ injury = get_object_or_404(Injury, pk=injury_id) return render(request, "injuries/details.html", {"injury": injury}) @login_required @require_http_methods(["GET"]) def wellbeing_listing(request, gymnast_id=None): """ Récupère la liste des évaluations mentales suivant (d'un gymnaste si définit en paramètre). Args: gymnast_id (int) identifiant d'un gymnaste """ gymnast = None if gymnast_id: wellbeing_list = WellBeing.objects.filter(gymnast=gymnast_id) gymnast = get_object_or_404(Gymnast, pk=gymnast_id) else: wellbeing_list = WellBeing.objects.all() context = {"wellbeing_list": wellbeing_list, "gymnast": gymnast} return render(request, "wellbeing/list.html", context) @login_required @require_http_methods(["GET", "POST"]) def wellbeing_create_or_update( request, wellbeing_id=None, gymnast_id=None, event_id=None ): """ Formulaire de création d'une nouvelle blessure. Args: wellbeing_id (int) identifiant d'une blessure gymnast_id (int) identifiant d'un gymnaste event_id (int) identifiant d'un événement """ if wellbeing_id: wellbeing = get_object_or_404(WellBeing, pk=wellbeing_id) data = {"gymnast_related": wellbeing.gymnast, "event_related": wellbeing.event} else: wellbeing = 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 = WellBeingForm(request.POST, instance=wellbeing) if form.is_valid(): wellbeing = form.save() # notification receiver = [] gymnast = Gymnast.objects.get(pk=form.cleaned_data["gymnast"].id) date = form.cleaned_data["date"] mindstate = form.cleaned_data["mindstate"] sleep = form.cleaned_data["sleep"] stress = form.cleaned_data["stress"] fatigue = form.cleaned_data["fatigue"] muscle_soreness = form.cleaned_data["muscle_soreness"] functionality = ContentType.objects.get(model="wellbeing") for notification in gymnast.notifications.filter( functionality=functionality ): receiver.append(notification.user.email) send_mail( f"{gymnast} : Nouveau score de bien être", f"{gymnast} a ajouté état de bien être ({date})", settings.EMAIL_HOST_USER, receiver, fail_silently=False, html_message=f"""Bonjour,
{gymnast} a ajouté son état de bien être pour le ({date.strftime('%d %B %Y')}) :
Excellente journée
Jarvis
Trampoline Trainer Help
Flying Acrobatics Trampoline Club Rue René Francq, 7 1428 Lillois-Witterzée |
Bonjour,
Un nouveau poids/taille enregistré pour {gymnast} pour le {date.strftime('%d %B %Y')} :
Excellente journée
Jarvis
""", ) return HttpResponseRedirect( reverse( "gymnast_details_tab", args=(form.cleaned_data["gymnast"].id, "physiological"), ) ) else: print(form.errors) return render(request, "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, "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 Args: gymnast_id (int) identifiant d'un gymnaste """ 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, "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 nombre de série tentée. Args: routinedone_id (int) identifiant d'une routinedone gymnast_id (int) identifiant d'un gymnaste """ if routinedone_id: routinedone = get_object_or_404(NumberOfRoutineDone, pk=routinedone_id) data = { "gymnast": routinedone.gymnast.id, "gymnast_related": str(routinedone.gymnast), } if routinedone.routine: data["routine"] = routinedone.routine.id data["routine_related"] = str(routinedone.routine) else: routine = ( GymnastHasRoutine.objects.filter(gymnast=routinedone.gymnast) .filter(routine_type=routinedone.routine_type) .filter(date_begin__lte=routinedone.date) .filter(Q(date_end__gte=routinedone.date) | Q(date_end__isnull=True)) .first() ) if routine: data["routine"] = routine.id data["routine_related"] = str(routine) else: data = None routinedone = 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() # notification receiver = [] gymnast = Gymnast.objects.get(pk=form.cleaned_data["gymnast"].id) functionality = ContentType.objects.get(model="numberofroutinedone") for notification in gymnast.notifications.filter( functionality=functionality ): receiver.append(notification.user.email) send_mail( f"{gymnast} : Nouvelle série comptabilisée", f"Nouvelle série comptabilisée pour {gymnast}", settings.EMAIL_HOST_USER, receiver, fail_silently=False, html_message=f"""Bonjour,
Nouvelle série comptabilisée pour {gymnast}.
Excellente journée
Jarvis
""", ) return HttpResponseRedirect( reverse( "gymnast_details_tab", args=(form.cleaned_data["gymnast"].id, "routine"), ) ) else: return render(request, "routinedone/create.html", {"form": form}) form = NumberOfRoutineDoneForm(instance=routinedone, initial=data) context = {"form": form, "routinedone_id": routinedone_id} return render(request, "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 (classeBonjour,
Nouvel objectif fixé pour {gymnast} : {educative} ({learning_step}) pour le {date.strftime('%d %B %Y')} au plus tard.
Excellente journée
Jarvis
""", ) return HttpResponseRedirect( reverse("gymnast_details", args=(form.cleaned_data["gymnast"].id,)) ) else: return render(request, "plan/create.html", {"form": form}) form = PlanForm(instance=plan, initial=data) context = {"form": form, "plan_id": plan_id} return render(request, "plan/create.html", context) @login_required @require_http_methods(["GET"]) def intensity_details(request, intensity_id): """ Récupère toutes les informations d'une intensité. Args: intensity_id (int) identifiant d'une intensité """ intensity = get_object_or_404(Intensity, pk=intensity_id) return render(request, "intensities/details.html", {"intensity": intensity}) @login_required @require_http_methods(["GET"]) def intensity_listing(request, gymnast_id=None): """ Si la personne connectée est un entraîneur, la fonction récupère la liste des intensités 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 intensités à lui/elle. Args: gymnast_id (int) identifiant d'un gymnaste """ gymnast = None if request.user.groups.filter(name="trainer").exists(): if gymnast_id: intensity_list = Intensity.objects.filter(gymnast=gymnast_id) gymnast = Gymnast.objects.get(pk=gymnast_id) else: intensity_list = Intensity.objects.all() else: intensity_list = Intensity.objects.filter( Q(gymnast__last_name=request.user.last_name) & Q(gymnast__first_name=request.user.first_name) ) context = {"intensity_list": intensity_list, "gymnast": gymnast} return render(request, "intensities/list.html", context) @login_required @require_http_methods(["GET", "POST"]) def intensity_create_or_update(request, intensity_id=None, gymnast_id=None): """Création d'un record de la class Intentity. Args: intensity_id (int) identifiant d'une intensité (classeBonjour,
{gymnast} a encodé une nouvelle intensité (pour le {date.strftime('%d %B %Y')}) :
Statistics:
Excellente journée
Jarvis
Trampoline Trainer Help
Flying Acrobatics Trampoline Club Rue René Francq, 7 1428 Lillois-Witterzée |
Bonjour,
Une nouvelle information de saison enregistrée pour {gymnast}.
Excellente journée
Jarvis
""", ) return HttpResponseRedirect( reverse( "gymnast_details", args=(form.cleaned_data["gymnast"].id,), ) ) else: return render(request, "seasoninformations/create.html", {"form": form}) form = SeasonInformationForm(instance=season_information, initial=data) context = {"form": form, "season_information_id": season_information_id} return render(request, "seasoninformations/create.html", context) @login_required @require_http_methods(["GET"]) def season_information_listing(request, gymnast_id=None): """Liste toutes les informations de saison pour un gymnaste. Args: gymnast_id (int) identifiant d'un gymnaste """ if gymnast_id is not None: gymnast = Gymnast.objects.get(pk=gymnast_id) season_information_list = SeasonInformation.objects.filter(gymnast=gymnast_id) else: season_information_list = SeasonInformation.objects.all() context = {"season_information_list": season_information_list, "gymnast": gymnast} return render(request, "seasoninformations/list.html", context)