from datetime import date, datetime 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 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 import pendulum from jarvis.core.models import Email from jarvis.people.models import Gymnast from jarvis.people.views import gymnast_listing from jarvis.objective.models import Skill from jarvis.tools.date_week_transition import from_date_to_week_number from .models import ( Plan, Note, Point, Chrono, LearnedSkill, GymnastHasRoutine, SeasonInformation, NumberOfRoutineDone, ) from .forms import ( PlanForm, NoteForm, ScoreForm, LearnedSkillForm, SeasonInformationForm, NumberOfRoutineDoneForm, ) from .email_vars import MAIL_HEADER, MAIL_FOOTER User = get_user_model() @login_required @require_http_methods(["GET"]) def note_listing(request, gymnast_id=None): """ Récupère les notes des gymnastes autorisé(e)s Args: gymnast_id (int) identifiant d'un gymnaste """ 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"] ) ): note_list = Note.objects.filter(gymnast=gymnast_id) gymnast = Gymnast.objects.get(pk=gymnast_id) else: if request.user.is_superuser: note_list = Note.objects.all() else: note_list = Note.objects.filter( gymnast__in=request.session["available_gymnast"] ) context = {"note_list": note_list, "gymnast": gymnast} return render(request, "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 et vérifie si le demandeur peut avoir accès à la note. S'il ne peut pas il est redirigé vers le listing des notes. Args: note_id (int) identifiant d'une note """ note = get_object_or_404(Note, pk=note_id) if not request.user.is_superuser and ( request.session.has_key("available_gymnast") and note.gymnast.id not in request.session["available_gymnast"] ): return note_listing(request) return render(request, "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'une note 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 coach via le form ? """ coach = User.objects.get(pk=request.user.id) if note_id: note = get_object_or_404(Note, pk=note_id) if not request.user.is_superuser and ( request.session.has_key("available_gymnast") and note.gymnast.id not in request.session["available_gymnast"] ): return note_listing(request) data = { "coach": coach.id, "gymnast": note.gymnast.id, "gymnast_related": str(note.gymnast), } else: note = None today = pendulum.now().date() season, week_number = from_date_to_week_number(today) data = { "coach": coach.id, "title": f"Note of the week {week_number} ({season})", } 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() if ( (new_note.gymnast.user.email or new_note.gymnast.email_trainer) and ((not note_id) or (note_id and note.status == 0)) and new_note.status == 1 ): url = request.build_absolute_uri( reverse("gymnast_details_tab", args=(new_note.gymnast.id, "event")) ) receivers = [ new_note.gymnast.user.email, new_note.gymnast.email_trainer, ] title = f"{new_note.gymnast} : Nouvelle note" body = f"""

Bonjour,

Une nouvelle note vous a été envoyée. Vous pouvez la consulter en cliquant ici.

""" send_mail( title, "Une nouvelle note vous a été envoyée", settings.EMAIL_HOST_USER, receivers, fail_silently=False, html_message=body + MAIL_FOOTER, ) return HttpResponseRedirect( reverse("gymnast_details_tab", args=(new_note.gymnast.id, "event")) ) return render(request, "notes/create.html", {"form": form}) 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(["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: if not request.user.is_superuser and ( request.session.has_key("available_gymnast") and gymnast_id not in request.session["available_gymnast"] ): return gymnast_listing(request) 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(): learned_skill = form.save() # notification receivers = [] functionality = ContentType.objects.get(model="learnedskill") for notification in gymnast.notifications.filter( functionality=functionality ): receivers.append(notification.user.email) title = f"{learned_skill.gymnast} : Nouveau skill appris" html_message = f"""

Bonjour,

{learned_skill.gymnast} a appris {learned_skill.skill} ({learned_skill.learning_step}).

""" Email.objects.create( receivers=receivers, title=title, body=html_message, ) send_mail( title, f"{learned_skill.gymnast} a appris une nouvelle figure ({date})", settings.EMAIL_HOST_USER, receivers, fail_silently=False, html_message=html_message + MAIL_FOOTER, ) return HttpResponseRedirect( reverse("gymnast_details", args=(form.cleaned_data["gymnast"].id,)) ) return render(request, "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) if not request.user.is_superuser and ( request.session.has_key("available_gymnast") and score.gymnast.id not in request.session["available_gymnast"] ): return score_listing(request) 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(): score = form.save() # notification receivers = [] functionality = ContentType.objects.get(model="point") for notification in score.gymnast.notifications.filter( functionality=functionality ): receivers.append(notification.user.email) title = f"{score.gymnast} : Nouveau score enregistré" html_message = f"""

Bonjour,

Un nouveau score a été enregistré pour {score.gymnast} :

{score.event.name} à {score.event.place.address} - {score.event.place.postal} {score.event.place.city} {score.routine_type} : {score.total} points

""" Email.objects.create( receivers=receivers, title=title, body=html_message, ) send_mail( title, f"{score.gymnast} a ajouté un nouveau score ({date})", settings.EMAIL_HOST_USER, receivers, fail_silently=False, html_message=html_message + MAIL_FOOTER, ) 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, "routine"), ) ) return render(request, "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) # JE NE SAIS PLUS POURQUOI JE GERE UN PATTERN -> code commenté. # if pattern: # score_list = Point.objects.filter( # Q(event__icontains=pattern) | Q(gymnast__icontains=pattern) # ) # el 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) score_list = Point.objects.filter(gymnast=gymnast_id) else: if request.user.is_superuser: score_list = Point.objects.all() else: score_list = Point.objects.filter( gymnast__in=request.session["available_gymnast"] ) context = {"score_list": score_list, "gymnast": gymnast} return render(request, "scores/list.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 """ 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) routine_done_list = gymnast.number_of_routine_done.all() else: if request.user.is_superuser: routine_done_list = NumberOfRoutineDone.objects.all() else: routine_done_list = NumberOfRoutineDone.objects.filter( gymnast__in=request.session["available_gymnast"] ) 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) 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(): routine_done = form.save() # notification receivers = [] gymnast = Gymnast.objects.get(pk=form.cleaned_data["gymnast"].id) functionality = ContentType.objects.get(model="numberofroutinedone") for notification in routine_done.gymnast.notifications.filter( functionality=functionality ): receivers.append(notification.user.email) title = f"{routine_done.gymnast} : Nouvelle série comptabilisée" body = f"""

Bonjour,

Nouvelle série comptabilisée pour {routine_done.gymnast}.

""" Email.objects.create(receivers=receivers, title=title, body=body) send_mail( title, f"Nouvelle série comptabilisée pour {routine_done.gymnast}", 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, "routine"), ) ) 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 (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), "educative": plan.educative.id, "educative_related": str(plan.educative), } 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() # notification receivers = [] date = form.cleaned_data["date"] functionality = ContentType.objects.get(model="plan") for notification in plan.gymnast.notifications.filter( functionality=functionality ): receivers.append(notification.user.email) title = f"{plan.gymnast} : Nouvel objectif fixé" body = f"""

Bonjour,

Nouvel objectif fixé pour {plan.gymnast} : {plan.educative} ({plan.learning_step}) pour le {date.strftime('%d %B %Y')} au plus tard.

""" Email.objects.create(receivers=receivers, title=title, body=body) send_mail( title, f"Nouvel objectif fixé pour {plan.gymnast}", settings.EMAIL_HOST_USER, receivers, fail_silently=False, html_message=body + MAIL_FOOTER, ) return HttpResponseRedirect( reverse("gymnast_details", args=(form.cleaned_data["gymnast"].id,)) ) 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", "POST"]) def season_information_create_or_update( request, season_information_id=None, gymnast_id=None ): """Création d'un record de la class SeasonInformation. Args: season_information_id (int): identifiant d'un plan (classe ). gymnast_id (int): identifiant d'un gymnaste (classe ). """ if season_information_id: season_information = get_object_or_404( SeasonInformation, pk=season_information_id ) if not request.user.is_superuser and ( request.session.has_key("available_gymnast") and season_information.gymnast.id not in request.session["available_gymnast"] ): return season_information_listing(request) data = { "gymnast": season_information.gymnast.id, "gymnast_related": str(season_information.gymnast), "club": season_information.club.id, "club_related": str(season_information.club), } else: season_information = None data = {} if gymnast_id: gymnast = get_object_or_404(Gymnast, pk=gymnast_id) data["gymnast"] = gymnast_id data["gymnast_related"] = str(gymnast) if request.method == "POST": form = SeasonInformationForm(request.POST, instance=season_information) if form.is_valid(): season_information = form.save() # notification receivers = [] functionality = ContentType.objects.get(model="seasoninformation") for notification in season_information.gymnast.notifications.filter( functionality=functionality ): receivers.append(notification.user.email) title = f"{season_information.gymnast} : Nouvelle information de saison" body = f"""

Bonjour,

Une nouvelle information de saison enregistrée pour {season_information.gymnast}.

""" Email.objects.create(receivers=receivers, title=title, body=body) send_mail( title, f"Une nouvelle information de saison enregistrée pour {season_information.gymnast}", settings.EMAIL_HOST_USER, receivers, fail_silently=False, html_message=body + MAIL_FOOTER, ) return HttpResponseRedirect( reverse( "gymnast_details", args=(form.cleaned_data["gymnast"].id,), ) ) 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 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) season_information_list = SeasonInformation.objects.filter(gymnast=gymnast_id) else: if request.user.is_superuser: season_information_list = SeasonInformation.objects.all() else: season_information_list = SeasonInformation.objects.filter( gymnast__in=request.session["available_gymnast"] ) context = {"season_information_list": season_information_list, "gymnast": gymnast} return render(request, "seasoninformations/list.html", context)