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 HttpResponseRedirect from django.db.models import Min, Avg, Max from django.core.mail import send_mail from django.urls import reverse from django.conf import settings from django.contrib.contenttypes.models import ContentType from jarvis.core.models import Email from .models import Gymnast from .models import ( Injury, WellBeing, HeightWeight, ) from .forms import ( InjuryForm, WellBeingForm, HeightWeightForm, ) from .models import ( INJURY_MECHANISM_CHOICE, INJURY_BODY_SIDE_CHOICE, INJURY_TYPE_CHOICE, INJURY_LOCATION_CHOICE, ) from .email_vars import MAIL_HEADER, MAIL_FOOTER @login_required @require_http_methods(["GET"]) def injury_listing(request, gymnast_id=None): """ 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. """ gymnast = None if gymnast_id and ( request.user.is_superuser or ( request.session.has_key("available_gymnast") and gymnast_id in request.session["available_gymnast"] ) ): gymnast = get_object_or_404(Gymnast, pk=gymnast_id) injury_list = Injury.objects.filter(gymnast=gymnast_id) else: if request.user.is_superuser: injury_list = Injury.objects.all() else: injury_list = Injury.objects.filter( gymnast__in=request.session["available_gymnast"] ) context = {"injury_list": injury_list, "gymnast": gymnast} 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) if not request.user.is_superuser and ( request.session.has_key("available_gymnast") and injury.gymnast.id not in request.session["available_gymnast"] ): return injury_listing(request) 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 receivers = [] date = form.cleaned_data["date"] functionality = ContentType.objects.get(model="injury") for notification in injury.gymnast.notifications.filter( functionality=functionality ): receivers.append(notification.user.email) title = f"{injury.gymnast} : Nouvelle blessure enregistrée" body = f"""

Bonjour,

Un nouvelle blessure enregistrée pour {injury.gymnast} pour le {date.strftime('%d %B %Y')}:

""" Email.objects.create(receivers=receivers, title=title, body=body) send_mail( title, f"{injury.gymnast} a ajouté état de bien être ({date})", settings.EMAIL_HOST_USER, receivers, fail_silently=False, html_message=body + MAIL_FOOTER, ) return HttpResponseRedirect(reverse("injury_details", args=(injury.pk,))) 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_details(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) if not request.user.is_superuser and ( request.session.has_key("available_gymnast") and injury.gymnast.id not in request.session["available_gymnast"] ): return injury_listing(request) 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 de bien-être. Args: gymnast_id (int) identifiant d'un gymnaste """ gymnast = None if gymnast_id and ( request.user.is_superuser or request.user.gymnast.id == gymnast_id or ( request.session.has_key("available_gymnast") and gymnast_id in request.session["available_gymnast"] ) ): gymnast = get_object_or_404(Gymnast, pk=gymnast_id) wellbeing_list = gymnast.wellbeings.all() else: if request.user.is_superuser: # les super user peuvent voir tout le monde. wellbeing_list = WellBeing.objects.all() else: # les autres entraîneurs ne peuvent voir que certains élèves. wellbeing_list = WellBeing.objects.filter( gymnast__in=request.session["available_gymnast"] ) context = {"wellbeing_list": wellbeing_list, "gymnast": gymnast} return render(request, "wellbeing/list.html", context) def get_wellbeing_stats_for_season_week(gymnast_id, season, week_number): """Calcule le min, max et moyenne de bien-être d'un gymnaste pour une semaine donnéee Args: gymnast_id (int) identifiant d'un gymnaste season (str) saison week_number (int) numéro de semaine """ wellbeing_score = WellBeing.objects.filter( gymnast_id=gymnast_id, season=season, week_number=week_number ).aggregate( min_mindstate_value=Min("mindstate"), average_mindstate_value=Avg("mindstate"), max_mindstate_value=Max("mindstate"), min_sleep_value=Min("sleep"), average_sleep_value=Avg("sleep"), max_sleep_value=Max("sleep"), min_stress_value=Min("stress"), average_stress_value=Avg("stress"), max_stress_value=Max("stress"), min_fatigue_value=Min("fatigue"), average_fatigue_value=Avg("fatigue"), max_fatigue_value=Max("fatigue"), min_muscle_soreness_value=Min("muscle_soreness"), average_muscle_soreness_value=Avg("muscle_soreness"), max_muscle_soreness_value=Max("muscle_soreness"), ) return wellbeing_score @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) if not request.user.is_superuser and ( request.session.has_key("available_gymnast") and wellbeing.gymnast.id not in request.session["available_gymnast"] ): return wellbeing_listing(request) 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 receivers = [] date = form.cleaned_data["date"] functionality = ContentType.objects.get(model="wellbeing") for notification in wellbeing.gymnast.notifications.filter( functionality=functionality ): receivers.append(notification.user.email) title = f"{wellbeing.gymnast} : Nouveau score de bien être" html_message = f"""

Bonjour,

{wellbeing.gymnast} a ajouté son état de bien être pour le ({date.strftime('%d %B %Y')}) :

{wellbeing.informations}""" Email.objects.create(receivers=receivers, title=title, body=html_message) send_mail( title, f"{wellbeing.gymnast} a ajouté état de bien être ({date})", settings.EMAIL_HOST_USER, receivers, fail_silently=False, html_message=html_message + MAIL_FOOTER, ) return HttpResponseRedirect( reverse("wellbeing_details", args=(wellbeing.pk,)) ) return render(request, "wellbeing/create.html", {"form": form}) form = WellBeingForm(instance=wellbeing, initial=data) context = {"form": form, "wellbeing_id": wellbeing_id} return render(request, "wellbeing/create.html", context) @login_required @require_http_methods(["GET"]) def wellbeing_details(request, wellbeing_id): """ Récupère toutes les informations d'une évaluation psychologique. Args: wellbeing_id (int) identifiant d'une évaluation psycho """ wellbeing = get_object_or_404(WellBeing, pk=wellbeing_id) if not request.user.is_superuser and ( request.session.has_key("available_gymnast") and wellbeing.gymnast.id not in request.session["available_gymnast"] ) and ( wellbeing.gymnast.id != request.user.gymnast.id ): return HttpResponseRedirect(reverse("wellbeing_list")) return render(request, "wellbeing/details.html", {"wellbeing": wellbeing}) @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). Args: gymnast_id (int) identifiant d'un gymnaste """ gymnast = None if gymnast_id and ( request.user.is_superuser or request.user.gymnast.id == gymnast_id or ( request.session.has_key("available_gymnast") and gymnast_id in request.session["available_gymnast"] ) ): gymnast = get_object_or_404(Gymnast, pk=gymnast_id) heightweight_list = HeightWeight.objects.filter(gymnast=gymnast_id) else: if request.user.is_superuser: heightweight_list = HeightWeight.objects.all() else: heightweight_list = HeightWeight.objects.filter( gymnast__in=request.session["available_gymnast"] ) context = {"height_weight_list": heightweight_list, "gymnast": gymnast} return render(request, "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. Args: heightweight_id (int) identifiant d'un couple taille/couple gymnast_id (int) identifiant d'un gymnaste """ if heightweight_id: heightweight = get_object_or_404(HeightWeight, pk=heightweight_id) if not request.user.is_superuser and ( request.session.has_key("available_gymnast") and heightweight.gymnast.id not in request.session["available_gymnast"] ): return heightweight_listing(request) 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(): heightweight = form.save() # notification receivers = [] date = form.cleaned_data["date"] functionality = ContentType.objects.get(model="heightweight") for notification in heightweight.gymnast.notifications.filter( functionality=functionality ): receivers.append(notification.user.email) title = f"{heightweight.gymnast} : Nouveau poids/taille enregistré" body = f"""

Bonjour,

Un nouveau poids/taille enregistré pour {heightweight.gymnast} pour le {date.strftime('%d %B %Y')}:

""" Email.objects.create(receivers=receivers, title=title, body=body) send_mail( title, f"Un nouveau poids/taille enregistré pour {heightweight.gymnast} ({date}) : {heightweight.height} cm / {heightweight.weight} kg (BMI: {heightweight.bmi:.2f}).", # pylint: disable=line-too-long settings.EMAIL_HOST_USER, receivers, fail_silently=False, html_message=body + MAIL_FOOTER, ) return HttpResponseRedirect( reverse( "gymnast_details_tab", args=(form.cleaned_data["gymnast"].id, "physiological"), ) ) 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)