Jarvis/jarvis/followup/views.py

747 lines
25 KiB
Python

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"""<p>Bonjour,</p><p>Une nouvelle note vous a été envoyée. Vous pouvez la consulter en cliquant <a href='{url}'>ici</a>.</p>"""
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"""<p>Bonjour,</p><p>{learned_skill.gymnast} a appris {learned_skill.skill} ({learned_skill.learning_step}).</p>"""
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"""<p>Bonjour,</p><p>Un nouveau score a été enregistré pour {score.gymnast} :<br /><br />
{score.event.name} à {score.event.place.address} - {score.event.place.postal} {score.event.place.city}
{score.routine_type} : {score.total} points
<ul>
<li>Diff: {score.point_difficulty}</li>
<li>ToF: {score.point_time_of_flight}</li>
<li>Exe: {score.point_execution}</li>
<li>HD: {score.point_horizontal_displacement}</li>
<li>Pen: {score.penality}</li>
</ul></p>"""
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"""<p>Bonjour,</p>
<p>Nouvelle série comptabilisée pour {routine_done.gymnast}.</p>"""
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 <Plan>).
gymnast_id (int) identifiant d'un gymnaste (classe <Gymnast>).
skill_id (int) identifiant d'un skill (classe <Skill>).
"""
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"""<p>Bonjour,</p>
<p>Nouvel objectif fixé pour {plan.gymnast} : {plan.educative} ({plan.learning_step}) pour le {date.strftime('%d %B %Y')} au plus tard.</p>"""
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 <SeasonInformation>).
gymnast_id (int): identifiant d'un gymnaste (classe <Gymnast>).
"""
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"""<p>Bonjour,</p>
<p>Une nouvelle information de saison enregistrée pour {season_information.gymnast}.</p>"""
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)