2023-04-25 17:06:14 +02:00
|
|
|
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
|
2023-04-28 12:20:55 +02:00
|
|
|
from django.contrib.contenttypes.models import ContentType
|
2023-04-25 17:06:14 +02:00
|
|
|
|
|
|
|
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
|
|
|
|
|
2023-11-18 18:29:18 +01:00
|
|
|
from .models import (
|
|
|
|
CHRONO_TYPE_CHOICE,
|
|
|
|
SCORE_TYPE_CHOICE,
|
|
|
|
INJURY_MECHANISM_CHOICE,
|
|
|
|
INJURY_BODY_SIDE_CHOICE,
|
|
|
|
INJURY_TYPE_CHOICE,
|
|
|
|
INJURY_LOCATION_CHOICE,
|
|
|
|
)
|
2023-04-25 17:06:14 +02:00
|
|
|
from .models import (
|
|
|
|
Plan,
|
|
|
|
Note,
|
|
|
|
Point,
|
|
|
|
Chrono,
|
2023-10-11 16:32:09 +02:00
|
|
|
Injury,
|
2023-07-05 10:51:49 +02:00
|
|
|
WellBeing,
|
2023-04-25 17:06:14 +02:00
|
|
|
Intensity,
|
|
|
|
LearnedSkill,
|
|
|
|
HeightWeight,
|
|
|
|
ChronoDetails,
|
|
|
|
GymnastHasRoutine,
|
|
|
|
SeasonInformation,
|
|
|
|
NumberOfRoutineDone,
|
|
|
|
)
|
|
|
|
|
|
|
|
from .forms import (
|
|
|
|
PlanForm,
|
|
|
|
NoteForm,
|
|
|
|
ScoreForm,
|
|
|
|
ChronoForm,
|
2023-10-11 16:32:09 +02:00
|
|
|
InjuryForm,
|
2023-07-05 09:33:03 +02:00
|
|
|
WellBeingForm,
|
2023-04-25 17:06:14 +02:00
|
|
|
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()
|
|
|
|
|
2023-11-22 10:27:41 +01:00
|
|
|
MAIL_HEADER = """
|
|
|
|
<html><head><style id="canary-invert">html {
|
|
|
|
filter: invert(100%) hue-rotate(180deg) !important;
|
|
|
|
}
|
|
|
|
|
|
|
|
img,
|
|
|
|
video,
|
|
|
|
:not(object):not(body)>embed,
|
|
|
|
object,
|
|
|
|
svg image,
|
|
|
|
[style*="background:url"],
|
|
|
|
[style*="background-image:url"],
|
|
|
|
[style*="background: url"],
|
|
|
|
[style*="background-image: url"],
|
|
|
|
[background],
|
|
|
|
twitterwidget,
|
|
|
|
.canary-emoji {
|
|
|
|
filter: invert(100%) hue-rotate(180deg) !important;
|
|
|
|
}
|
|
|
|
|
|
|
|
[style*="background:url"] *,
|
|
|
|
[style*="background-image:url"] *,
|
|
|
|
[style*="background: url"] *,
|
|
|
|
[style*="background-image: url"] *,
|
|
|
|
input,
|
|
|
|
[background] *,
|
|
|
|
img[src^="https://s0.wp.com/latex.php"],
|
|
|
|
twitterwidget .NaturalImage-image {
|
|
|
|
filter: none !important;
|
|
|
|
}
|
|
|
|
</style></head><body contenteditable="true" style="font-family:Helvetica;font-size:13px;">Gregory Trullemans<br>
|
|
|
|
|
|
|
|
|
|
|
|
</body></html>"""
|
|
|
|
|
2023-11-26 17:29:28 +01:00
|
|
|
MAIL_FOOTER = """<br />
|
|
|
|
<p>Excellente journée</p>
|
|
|
|
<p>Jarvis</p>
|
|
|
|
<p><b>Trampoline Trainer Help</b></p>
|
|
|
|
<table border="0">
|
|
|
|
<tbody>
|
|
|
|
<tr>
|
|
|
|
<td>
|
|
|
|
<img id="CB70323B-AC4A-4992-9DD8-3F25DC32658C" height="80px" src="https://www.flyingacrobaticstrampoline.be/img/logo_120px.png" style="max-width: 100vw;">
|
|
|
|
</td>
|
|
|
|
<td>
|
|
|
|
<b><span class="" style="color: rgb(253, 221, 12);">F</span><span class="" style="color: rgb(251, 214, 13);">l</span><span class="" style="color: rgb(249, 207, 14);">y</span><span class="" style="color: rgb(247, 200, 15);">i</span><span class="" style="color: rgb(245, 194, 16);">n</span><span class="" style="color: rgb(243, 187, 17);">g</span> <span class="" style="color: rgb(241, 180, 18);"></span><span class="" style="color: rgb(239, 173, 19);">A</span><span class="" style="color: rgb(237, 166, 20);">c</span><span class="" style="color: rgb(234, 159, 21);">r</span><span class="" style="color: rgb(232, 153, 22);">o</span><span class="" style="color: rgb(230, 146, 23);">b</span><span class="" style="color: rgb(228, 139, 24);">a</span><span class="" style="color: rgb(226, 132, 25);">t</span><span class="" style="color: rgb(224, 125, 26);">i</span><span class="" style="color: rgb(222, 118, 27);">c</span><span class="" style="color: rgb(220, 112, 28);">s</span> <span class="" style="color: rgb(218, 105, 29);"></span><span class="" style="color: rgb(216, 98, 30);">T</span><span class="" style="color: rgb(214, 91, 31);">r</span><span class="" style="color: rgb(212, 84, 32);">a</span><span class="" style="color: rgb(210, 77, 33);">m</span><span class="" style="color: rgb(208, 70, 34);">p</span><span class="" style="color: rgb(206, 64, 35);">o</span><span class="" style="color: rgb(204, 57, 36);">l</span><span class="" style="color: rgb(201, 50, 37);">i</span><span class="" style="color: rgb(199, 43, 38);">n</span><span class="" style="color: rgb(197, 36, 39);">e</span> <span class="" style="color: rgb(195, 29, 40);"></span><span class="" style="color: rgb(193, 23, 41);">C</span><span class="" style="color: rgb(191, 16, 42);">l</span><span class="" style="color: rgb(189, 9, 43);">u</span><span class="" style="color: rgb(187, 2, 44);">b</span></b><br>
|
|
|
|
<span style="font-size: 13px; letter-spacing: 0.01em; line-height: 1.2;">Rue René Francq, 7</span><br>
|
|
|
|
<span style="font-size: 13px; letter-spacing: 0.01em; line-height: 1.2;">1428 Lillois-Witterzée</span>
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
</tbody>
|
|
|
|
</table>"""
|
|
|
|
|
2023-04-25 17:06:14 +02:00
|
|
|
|
|
|
|
@login_required
|
|
|
|
@require_http_methods(["GET"])
|
|
|
|
def jump_chrono_details(request, chrono_id):
|
|
|
|
"""Récupère toutes les informations détaillées d'un chrono. La fonction en profite pour
|
|
|
|
recalculer le total et s'assure que cela correspond à la valeur stockée dans le model
|
|
|
|
Chrono.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
chrono_id (int) identifiant chrono
|
|
|
|
|
|
|
|
QTF : Est-ce que je ne devrais pas faire un prefetch_related sur mon objet chrono pour optimiser mon affichage ?
|
|
|
|
chrono = Chrono.object.get(pk=chrono_id).prefetch_related('chrono_details') ?
|
|
|
|
"""
|
|
|
|
|
|
|
|
chrono = get_object_or_404(Chrono, pk=chrono_id)
|
|
|
|
sum_value = chrono.details.all().aggregate(total=Sum("value"))
|
|
|
|
|
|
|
|
if chrono.score != sum_value["total"]:
|
|
|
|
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(mean=Avg("value"))["mean"]
|
|
|
|
tmp_min_value = chrono.details.all().aggregate(min=Min("value"))["min"]
|
|
|
|
tmp_max_value = chrono.details.all().aggregate(max=Max("value"))["max"]
|
|
|
|
chart_min_value = mean_value - (tmp_min_value / 20)
|
|
|
|
chart_max_value = mean_value - (tmp_max_value / 20)
|
|
|
|
|
|
|
|
context = {
|
|
|
|
"chrono": chrono,
|
|
|
|
"mean_value": mean_value,
|
|
|
|
"chart_min_value": chart_min_value,
|
|
|
|
"chart_max_value": chart_max_value,
|
|
|
|
}
|
|
|
|
return render(request, "chronos/details.html", context)
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
@require_http_methods(["GET"])
|
|
|
|
def average_jump_chrono_details_for_gymnast(
|
|
|
|
request, gymnast_id, routine_type=1, season=None, week_number=1
|
|
|
|
):
|
|
|
|
"""Récupère tout les chronos entre deux date pour un gymnaste et un type de série
|
|
|
|
|
|
|
|
Args:
|
2023-05-14 19:10:34 +02:00
|
|
|
gymnast_id (int) Identifiant d'un gymnaste
|
|
|
|
routine_type (int) Type de série (cf. jarvis/followup/models.py > ROUTINE_CHOICE)
|
|
|
|
season (string) Saison sous forme "xxxx-xxxy"
|
|
|
|
week_number (int) numéro de semaine (1, …, 52)
|
2023-04-25 17:06:14 +02:00
|
|
|
"""
|
|
|
|
if season is None:
|
|
|
|
today = pendulum.now().date()
|
|
|
|
season, week_number = from_date_to_week_number(today)
|
|
|
|
else:
|
2023-06-13 19:32:35 +02:00
|
|
|
season = Season(season).label
|
2023-04-25 17:06:14 +02:00
|
|
|
|
|
|
|
if week_number > 52:
|
|
|
|
week_number = 52
|
|
|
|
|
|
|
|
if week_number < 1:
|
|
|
|
week_number = 1
|
|
|
|
|
2023-06-13 19:32:35 +02:00
|
|
|
date_begin, date_end = from_week_number_to_date(season, week_number)
|
2023-04-25 17:06:14 +02:00
|
|
|
|
|
|
|
return average_jump_chrono_details_for_season_and_week(
|
|
|
|
request,
|
|
|
|
gymnast_id,
|
|
|
|
routine_type,
|
|
|
|
season,
|
|
|
|
week_number,
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
@require_http_methods(["POST"])
|
|
|
|
def remove_jump_chrono_value(request):
|
|
|
|
"""
|
2023-05-14 19:10:34 +02:00
|
|
|
Recoit trois informations permettant de supprimer le chrono d'un saut à un chrono.
|
2023-04-25 17:06:14 +02:00
|
|
|
"""
|
|
|
|
chrono_id = request.POST.get("chrono_id", None)
|
|
|
|
order = request.POST.get("order", None)
|
|
|
|
chrono = get_object_or_404(Chrono, pk=chrono_id)
|
|
|
|
try:
|
|
|
|
ChronoDetails.objects.filter(chrono=chrono, order=order).delete()
|
|
|
|
except Exception:
|
|
|
|
return HttpResponse(409)
|
|
|
|
|
|
|
|
return HttpResponse(200)
|
|
|
|
|
|
|
|
|
|
|
|
@require_http_methods(["POST"])
|
|
|
|
def add_jump_chrono_value(request):
|
|
|
|
"""
|
2023-05-14 19:10:34 +02:00
|
|
|
Recoit trois informations permettant d'ajouter le chrono d'un saut à un chrono.
|
2023-04-25 17:06:14 +02:00
|
|
|
"""
|
|
|
|
chrono_id = request.POST.get("chrono_id", None)
|
|
|
|
order = request.POST.get("order", None)
|
|
|
|
value = request.POST.get("value", None)
|
|
|
|
|
|
|
|
chrono = get_object_or_404(Chrono, pk=chrono_id)
|
|
|
|
row, created = ChronoDetails.objects.get_or_create(
|
|
|
|
chrono=chrono, order=order, value=value
|
|
|
|
)
|
|
|
|
|
|
|
|
if created:
|
|
|
|
return HttpResponse(200, (row, created)) # devrait être un 201
|
|
|
|
else:
|
|
|
|
return HttpResponse(400, (row, created))
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
@require_http_methods(["GET"])
|
|
|
|
def jump_chrono_values_create_or_update(request, chrono_id):
|
|
|
|
"""
|
|
|
|
Ajoute des scores de saut à un chrono.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
chrono_id (int) identifiant chrono
|
|
|
|
"""
|
|
|
|
|
|
|
|
chrono = get_object_or_404(Chrono, pk=chrono_id)
|
|
|
|
jump_list = chrono.details.all()
|
|
|
|
number_of_jump = jump_list.count()
|
|
|
|
context = {
|
|
|
|
"chrono": chrono,
|
|
|
|
"jump_list": jump_list,
|
|
|
|
"number_of_jump": number_of_jump,
|
|
|
|
"score_type": chrono.score_type,
|
|
|
|
}
|
|
|
|
return render(request, "chronos/add_details.html", context)
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
@require_http_methods(["GET"])
|
|
|
|
def average_jump_chrono_details_between_two_date(
|
|
|
|
request, gymnast_id, routine_type=1, date_begin=None, date_end=None
|
|
|
|
):
|
|
|
|
"""Récupère tout les chronos entre deux date pour un gymnaste et un type de série
|
2023-05-14 19:10:34 +02:00
|
|
|
|
2023-04-25 17:06:14 +02:00
|
|
|
Args:
|
|
|
|
gymnast_id (int) Identifiant d'un gymnaste
|
|
|
|
routine_type (int) type de série (cf. jarvis/followup/models.py > ROUTINE_CHOICE)
|
|
|
|
date_begin (date) date de début
|
|
|
|
date_end (date) date de fin
|
2023-05-14 19:10:34 +02:00
|
|
|
|
|
|
|
QTF : le cast en date devrait être dans un try mais comment gérer correctement l'erreur - si erreur il y a ?
|
2023-04-25 17:06:14 +02:00
|
|
|
"""
|
|
|
|
|
|
|
|
if date_end:
|
|
|
|
try:
|
|
|
|
date_end = datetime.strptime(date_end, "%Y-%m-%d").date()
|
|
|
|
except (ValueError, TypeError):
|
|
|
|
date_end = pendulum.now().date()
|
|
|
|
else:
|
|
|
|
date_end = pendulum.now().date()
|
|
|
|
|
|
|
|
if date_begin:
|
|
|
|
try:
|
|
|
|
date_begin = datetime.strptime(date_begin, "%Y-%m-%d").date()
|
|
|
|
except (ValueError, TypeError):
|
|
|
|
date_begin = datetime(date_end.year, 9, 1)
|
|
|
|
else:
|
|
|
|
date_begin = datetime(date_end.year, 9, 1)
|
|
|
|
|
|
|
|
gymnast = get_object_or_404(Gymnast, pk=gymnast_id)
|
|
|
|
|
|
|
|
stat_values = (
|
|
|
|
ChronoDetails.objects.filter(
|
|
|
|
chrono__gymnast=gymnast_id,
|
|
|
|
chrono__chrono_type=routine_type,
|
|
|
|
chrono__date__gte=date_begin,
|
|
|
|
chrono__date__lte=date_end,
|
|
|
|
)
|
|
|
|
.values("order")
|
|
|
|
.annotate(
|
|
|
|
avg_score=Avg("value"), max_score=Max("value"), min_score=Min("value")
|
|
|
|
)
|
|
|
|
.order_by("order")
|
|
|
|
)
|
|
|
|
|
|
|
|
chrono_list = Chrono.objects.filter(
|
|
|
|
gymnast=gymnast_id,
|
|
|
|
date__gte=date_begin,
|
|
|
|
date__lte=date_end,
|
|
|
|
chrono_type=routine_type,
|
|
|
|
)
|
|
|
|
|
|
|
|
context = {
|
|
|
|
"gymnast": gymnast,
|
|
|
|
"date_begin": date_begin,
|
|
|
|
"date_end": date_end,
|
|
|
|
"chrono_list": chrono_list,
|
|
|
|
"stat_values": stat_values,
|
|
|
|
}
|
|
|
|
return render(request, "chronos/list_details.html", context)
|
|
|
|
|
|
|
|
|
|
|
|
@require_http_methods(["GET"])
|
|
|
|
def get_chrono_detail_distinct_season(request, gymnast_id):
|
2023-05-14 19:10:34 +02:00
|
|
|
"""Récupère toutes les saisons pour lesquelles le gymnaste a des chronos détaillés.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
gymnast_id (int) Identifiant d'un gymnaste
|
|
|
|
"""
|
2023-04-25 17:06:14 +02:00
|
|
|
gymnast = get_object_or_404(Gymnast, pk=gymnast_id)
|
|
|
|
season_list = list(
|
|
|
|
gymnast.chronos.values_list("season", flat=True)
|
|
|
|
.distinct("season")
|
|
|
|
.order_by("season")
|
|
|
|
)
|
|
|
|
return JsonResponse(season_list, safe=False)
|
|
|
|
|
|
|
|
|
|
|
|
@require_http_methods(["GET"])
|
|
|
|
def get_chrono_detail_distinct_weeknumber_for_season(request, gymnast_id, season):
|
|
|
|
"""Récupère toutes les week_number pour lesquelles le gymnaste a des chronos détaillés au cours
|
2023-05-14 19:10:34 +02:00
|
|
|
d'une saison.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
gymnast_id (int) Identifiant d'un gymnaste
|
|
|
|
season (string) Season
|
|
|
|
"""
|
2023-04-25 17:06:14 +02:00
|
|
|
gymnast = get_object_or_404(Gymnast, pk=gymnast_id)
|
|
|
|
weeknumber_list = list(
|
|
|
|
gymnast.chronos.values_list("week_number", flat=True)
|
|
|
|
.filter(season=season)
|
|
|
|
.distinct("week_number")
|
|
|
|
.order_by("week_number")
|
|
|
|
)
|
|
|
|
return JsonResponse(weeknumber_list, safe=False)
|
|
|
|
|
|
|
|
|
|
|
|
@require_http_methods(["GET"])
|
|
|
|
def get_average_jump_chrono_details_for_season_and_week(
|
|
|
|
request, gymnast_id, routine_type, season, week_number
|
|
|
|
):
|
|
|
|
"""Récupère tout les chronos moyen par saut pour une saison & semaine d'un gymnaste
|
2023-05-14 19:10:34 +02:00
|
|
|
|
2023-04-25 17:06:14 +02:00
|
|
|
Args:
|
|
|
|
gymnast_id (int) Identifiant d'un gymnaste
|
|
|
|
routine_type (int) Type de série (cf. jarvis/followup/models.py > ROUTINE_CHOICE)
|
|
|
|
season (string) Season
|
|
|
|
week_number (int) Numero de la semaine
|
|
|
|
"""
|
|
|
|
|
|
|
|
stat_values = list(
|
|
|
|
ChronoDetails.objects.filter(
|
|
|
|
chrono__gymnast=gymnast_id,
|
|
|
|
chrono__chrono_type=routine_type,
|
|
|
|
chrono__season=season,
|
|
|
|
chrono__week_number=week_number,
|
|
|
|
)
|
|
|
|
.values("order")
|
|
|
|
.annotate(avg_score=Avg("value"))
|
|
|
|
.order_by("order")
|
|
|
|
)
|
|
|
|
return JsonResponse(stat_values, safe=False)
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
@require_http_methods(["GET"])
|
|
|
|
def average_jump_chrono_details_for_season_and_week(
|
|
|
|
request, gymnast_id, routine_type, season, week_number
|
|
|
|
):
|
|
|
|
"""Récupère tout les chronos entre deux date pour un gymnaste et un type de série
|
2023-05-14 19:10:34 +02:00
|
|
|
|
2023-04-25 17:06:14 +02:00
|
|
|
Args:
|
|
|
|
gymnast_id (int) Identifiant d'un gymnaste
|
|
|
|
routine_type (int) Type de série (cf. jarvis/followup/models.py > ROUTINE_CHOICE)
|
|
|
|
season (string) Season
|
|
|
|
week_number (int) Numero de la semaine
|
|
|
|
"""
|
|
|
|
|
|
|
|
gymnast = get_object_or_404(Gymnast, pk=gymnast_id)
|
|
|
|
|
|
|
|
stat_values = (
|
|
|
|
ChronoDetails.objects.filter(
|
|
|
|
chrono__gymnast=gymnast_id,
|
|
|
|
chrono__chrono_type=routine_type,
|
|
|
|
chrono__season=season,
|
|
|
|
chrono__week_number=week_number,
|
|
|
|
)
|
|
|
|
.values("order")
|
|
|
|
.annotate(
|
|
|
|
avg_score=Avg("value"), max_score=Max("value"), min_score=Min("value")
|
|
|
|
)
|
|
|
|
.order_by("order")
|
|
|
|
)
|
|
|
|
# print(stat_values)
|
|
|
|
|
|
|
|
distinct_season_list = (
|
|
|
|
gymnast.chronos.values_list("season", flat=True)
|
|
|
|
.distinct("season")
|
|
|
|
.order_by("season")
|
|
|
|
)
|
|
|
|
distinct_week_number_list = (
|
|
|
|
gymnast.chronos.values_list("week_number", flat=True)
|
|
|
|
.filter(season=season)
|
|
|
|
.distinct("week_number")
|
|
|
|
.order_by("week_number")
|
|
|
|
)
|
|
|
|
distinct_routine_type_list = (
|
|
|
|
gymnast.chronos.values_list("chrono_type", flat=True)
|
|
|
|
.distinct("chrono_type")
|
|
|
|
.order_by("chrono_type")
|
|
|
|
)
|
|
|
|
|
|
|
|
chrono_list = Chrono.objects.filter(
|
|
|
|
gymnast=gymnast_id,
|
|
|
|
season=season,
|
|
|
|
week_number=week_number,
|
|
|
|
chrono_type=routine_type,
|
|
|
|
)
|
|
|
|
# print(chrono_list)
|
|
|
|
|
|
|
|
context = {
|
|
|
|
"gymnast": gymnast,
|
|
|
|
"selected_season": season,
|
|
|
|
"selected_week_number": week_number,
|
|
|
|
"selected_routine_type": routine_type,
|
|
|
|
"chrono_list": chrono_list,
|
|
|
|
"stat_values": stat_values,
|
|
|
|
"distinct_season_list": distinct_season_list,
|
|
|
|
"distinct_week_number_list": distinct_week_number_list,
|
|
|
|
"distinct_routine_type_list": distinct_routine_type_list,
|
|
|
|
}
|
|
|
|
return render(request, "chronos/list_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.
|
|
|
|
|
|
|
|
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, "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.
|
2023-05-14 19:10:34 +02:00
|
|
|
|
|
|
|
Args:
|
|
|
|
gymnast_id (int) identifiant d'un gymnaste
|
2023-04-25 17:06:14 +02:00
|
|
|
"""
|
|
|
|
|
|
|
|
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, "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.
|
2023-05-14 19:10:34 +02:00
|
|
|
|
|
|
|
Args:
|
|
|
|
note_id (int) identifiant d'une note
|
2023-04-25 17:06:14 +02:00
|
|
|
"""
|
|
|
|
note = get_object_or_404(Note, pk=note_id)
|
|
|
|
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'un chrono
|
|
|
|
|
|
|
|
Args:
|
|
|
|
note_id (int) identifiant d'une note
|
|
|
|
gymnast_id (int) identifiant d'un gymnaste
|
|
|
|
|
2023-05-14 19:10:34 +02:00
|
|
|
TODO: pq ne puis-je pas récuperer l'idantifiant du coach via le form ?
|
2023-04-25 17:06:14 +02:00
|
|
|
"""
|
|
|
|
|
|
|
|
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
|
2023-11-14 14:17:55 +01:00
|
|
|
today = pendulum.now().date()
|
|
|
|
season, week_number = from_date_to_week_number(today)
|
2023-11-14 14:19:15 +01:00
|
|
|
data = {
|
|
|
|
"coach": coach.id,
|
|
|
|
"title": f"Note of the week {week_number} ({season})",
|
|
|
|
}
|
2023-04-25 17:06:14 +02:00
|
|
|
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()
|
2023-07-05 09:33:03 +02:00
|
|
|
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
|
|
|
|
):
|
2023-10-31 12:34:53 +01:00
|
|
|
|
|
|
|
url = request.build_absolute_uri(
|
|
|
|
reverse("gymnast_details_tab", args=(new_note.gymnast.id, "event"))
|
|
|
|
)
|
2023-11-19 19:47:02 +01:00
|
|
|
# content = (form.cleaned_data["informations"])
|
2023-10-31 12:34:53 +01:00
|
|
|
|
2023-07-05 09:33:03 +02:00
|
|
|
send_mail(
|
|
|
|
"Nouvelle note",
|
|
|
|
"Une nouvelle note vous a été envoyée",
|
|
|
|
settings.EMAIL_HOST_USER,
|
|
|
|
[new_note.gymnast.user.email, new_note.gymnast.email_trainer],
|
|
|
|
fail_silently=False,
|
2023-10-31 12:34:53 +01:00
|
|
|
html_message=f"""<p>Bonjour,</p>
|
2023-11-22 10:27:41 +01:00
|
|
|
<p>Une nouvelle note vous a été envoyée. Vous pouvez la consulter en cliquant <a href='{url}'>ici</a>.</p>
|
2023-11-26 17:29:28 +01:00
|
|
|
{MAIL_FOOTER}""",
|
2023-07-05 09:33:03 +02:00
|
|
|
)
|
2023-04-25 17:06:14 +02:00
|
|
|
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):
|
2023-05-14 19:10:34 +02:00
|
|
|
"""Création ou modification d'un chrono
|
|
|
|
|
|
|
|
Args:
|
|
|
|
chrono_id (int) identifiant d'un chrono
|
|
|
|
gymnast_id (int) identifiant d'un gymnaste
|
|
|
|
"""
|
2023-04-25 17:06:14 +02:00
|
|
|
|
|
|
|
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
|
2023-04-29 15:31:14 +02:00
|
|
|
receiver = []
|
2023-05-20 18:21:27 +02:00
|
|
|
score = form.cleaned_data["score"]
|
|
|
|
score_type = form.cleaned_data["score_type"]
|
|
|
|
chrono_type = form.cleaned_data["chrono_type"]
|
2023-04-25 17:06:14 +02:00
|
|
|
gymnast = Gymnast.objects.get(pk=form.cleaned_data["gymnast"].id)
|
2023-04-28 12:20:55 +02:00
|
|
|
functionality = ContentType.objects.get(model="chrono")
|
|
|
|
for notification in gymnast.notifications.filter(
|
|
|
|
functionality=functionality
|
|
|
|
):
|
2023-04-29 15:31:14 +02:00
|
|
|
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"""<p>Bonjour,</p>
|
2023-11-26 17:29:28 +01:00
|
|
|
<p>Nouveau chrono pour {gymnast} : {SCORE_TYPE_CHOICE[score_type][1]} {CHRONO_TYPE_CHOICE[chrono_type][1]} - {score}.</p>
|
|
|
|
{MAIL_FOOTER}""",
|
2023-04-29 15:31:14 +02:00
|
|
|
)
|
2023-04-25 17:06:14 +02:00
|
|
|
|
|
|
|
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.
|
2023-05-14 19:10:34 +02:00
|
|
|
|
|
|
|
Args:
|
|
|
|
gymnast_id (int) identifiant d'un gymnaste
|
2023-04-25 17:06:14 +02:00
|
|
|
"""
|
|
|
|
|
|
|
|
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
|
2023-04-29 15:31:14 +02:00
|
|
|
receiver = []
|
2023-05-20 18:12:54 +02:00
|
|
|
skill = form.cleaned_data["skill"]
|
|
|
|
learning_step = form.cleaned_data["learning_step"]
|
2023-04-25 17:06:14 +02:00
|
|
|
gymnast = Gymnast.objects.get(pk=form.cleaned_data["gymnast"].id)
|
2023-04-28 12:20:55 +02:00
|
|
|
functionality = ContentType.objects.get(model="learnedskill")
|
|
|
|
for notification in gymnast.notifications.filter(
|
|
|
|
functionality=functionality
|
|
|
|
):
|
2023-04-29 15:31:14 +02:00
|
|
|
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"""<p>Bonjour,</p>
|
2023-11-26 17:29:28 +01:00
|
|
|
<p>{gymnast} a appris {skill} ({learning_step}).</p>
|
|
|
|
{MAIL_FOOTER}""",
|
2023-04-29 15:31:14 +02:00
|
|
|
)
|
2023-04-25 17:06:14 +02:00
|
|
|
|
|
|
|
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.
|
2023-05-14 19:10:34 +02:00
|
|
|
|
|
|
|
Args:
|
|
|
|
score_id (int) identifiant d'un score
|
|
|
|
gymnast_id (int) identifiant d'un gymnaste
|
2023-04-25 17:06:14 +02:00
|
|
|
"""
|
|
|
|
|
|
|
|
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
|
2023-04-29 15:31:14 +02:00
|
|
|
receiver = []
|
2023-04-25 17:06:14 +02:00
|
|
|
gymnast = Gymnast.objects.get(pk=form.cleaned_data["gymnast"].id)
|
2023-06-19 20:41:14 +02:00
|
|
|
event = form.cleaned_data["event"]
|
|
|
|
routine_type = form.cleaned_data["routine_type"]
|
|
|
|
total = form.cleaned_data["total"]
|
2023-04-28 12:20:55 +02:00
|
|
|
functionality = ContentType.objects.get(model="point")
|
|
|
|
for notification in gymnast.notifications.filter(
|
|
|
|
functionality=functionality
|
|
|
|
):
|
2023-04-29 15:31:14 +02:00
|
|
|
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"""<p>Bonjour,</p>
|
2023-11-26 17:29:28 +01:00
|
|
|
<p>Un nouveau score a été enregistré pour {gymnast} ({event}) : {routine_type} - {total}.</p>
|
|
|
|
{MAIL_FOOTER}""",
|
2023-04-29 15:31:14 +02:00
|
|
|
)
|
2023-04-25 17:06:14 +02:00
|
|
|
|
|
|
|
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
|
2023-05-14 19:10:34 +02:00
|
|
|
|
|
|
|
Args:
|
|
|
|
gymnast_id (int) identifiant d'un gymnaste
|
2023-04-25 17:06:14 +02:00
|
|
|
"""
|
|
|
|
|
|
|
|
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"])
|
2023-07-06 23:37:07 +02:00
|
|
|
def injuries_listing(request):
|
2023-04-25 17:06:14 +02:00
|
|
|
"""
|
2023-07-06 23:37:07 +02:00
|
|
|
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.
|
2023-04-25 17:06:14 +02:00
|
|
|
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:
|
2023-07-06 23:37:07 +02:00
|
|
|
injuries_list = Injury.objects.filter(
|
2023-04-25 17:06:14 +02:00
|
|
|
Q(gymnast__last_name__icontains=pattern)
|
|
|
|
| Q(gymnast__first_name__icontains=pattern)
|
|
|
|
)
|
|
|
|
else:
|
2023-07-06 23:37:07 +02:00
|
|
|
injuries_list = Injury.objects.all()
|
2023-04-25 17:06:14 +02:00
|
|
|
else:
|
2023-07-06 23:37:07 +02:00
|
|
|
injuries_list = Injury.objects.filter(
|
2023-04-25 17:06:14 +02:00
|
|
|
Q(gymnast__last_name=request.user.last_name)
|
|
|
|
& Q(gymnast__first_name=request.user.first_name)
|
|
|
|
)
|
|
|
|
|
2023-07-06 23:37:07 +02:00
|
|
|
context = {"injuries_list": injuries_list}
|
|
|
|
return render(request, "injuries/list.html", context)
|
2023-04-25 17:06:14 +02:00
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
@require_http_methods(["GET", "POST"])
|
2023-07-06 23:37:07 +02:00
|
|
|
def injury_create_or_update(request, injury_id=None, gymnast_id=None):
|
2023-04-25 17:06:14 +02:00
|
|
|
"""
|
2023-07-06 23:37:07 +02:00
|
|
|
Formulaire de création d'un nouvel blessure.
|
2023-05-14 19:10:34 +02:00
|
|
|
|
|
|
|
Args:
|
2023-07-06 23:37:07 +02:00
|
|
|
injury_id (int) identifiant d'une blessure
|
2023-05-14 19:10:34 +02:00
|
|
|
gymnast_id (int) identifiant d'un gymnaste
|
2023-04-25 17:06:14 +02:00
|
|
|
"""
|
|
|
|
|
2023-07-06 23:37:07 +02:00
|
|
|
if injury_id:
|
|
|
|
injury = get_object_or_404(Injury, pk=injury_id)
|
2023-04-25 17:06:14 +02:00
|
|
|
data = {
|
2023-07-06 23:37:07 +02:00
|
|
|
"gymnast_related": injury.gymnast,
|
|
|
|
"skill_related": injury.skill,
|
2023-04-25 17:06:14 +02:00
|
|
|
}
|
|
|
|
else:
|
2023-07-06 23:37:07 +02:00
|
|
|
injury = None
|
2023-04-25 17:06:14 +02:00
|
|
|
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":
|
2023-07-06 23:37:07 +02:00
|
|
|
form = InjuryForm(request.POST, instance=injury)
|
2023-04-25 17:06:14 +02:00
|
|
|
|
|
|
|
if form.is_valid():
|
2023-07-06 23:37:07 +02:00
|
|
|
injury = form.save()
|
2023-04-25 17:06:14 +02:00
|
|
|
|
|
|
|
# notification
|
2023-04-29 15:31:14 +02:00
|
|
|
receiver = []
|
2023-04-25 17:06:14 +02:00
|
|
|
gymnast = Gymnast.objects.get(pk=form.cleaned_data["gymnast"].id)
|
2023-11-18 18:29:18 +01:00
|
|
|
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"]
|
2023-07-06 23:37:07 +02:00
|
|
|
functionality = ContentType.objects.get(model="injury")
|
2023-04-28 12:20:55 +02:00
|
|
|
for notification in gymnast.notifications.filter(
|
|
|
|
functionality=functionality
|
|
|
|
):
|
2023-04-29 15:31:14 +02:00
|
|
|
receiver.append(notification.user.email)
|
|
|
|
|
|
|
|
send_mail(
|
2023-07-06 23:37:07 +02:00
|
|
|
f"{gymnast} : Nouvelle blessure enregistrée",
|
|
|
|
f"Une nouvelle blessure enregistrée pour {gymnast}",
|
2023-04-29 15:31:14 +02:00
|
|
|
settings.EMAIL_HOST_USER,
|
|
|
|
receiver,
|
|
|
|
fail_silently=False,
|
|
|
|
html_message=f"""<p>Bonjour,</p>
|
2023-11-18 18:29:18 +01:00
|
|
|
<p>Un nouvelle blessure enregistrée pour {gymnast} pour le {date.strftime('%d %B %Y')}:</p>
|
|
|
|
<ul>
|
2023-11-26 17:29:28 +01:00
|
|
|
<li>{INJURY_TYPE_CHOICE[injury_type][1]},</li>
|
2023-11-29 11:13:47 +01:00
|
|
|
<li>caused by {INJURY_MECHANISM_CHOICE[mechanism][1]},</li>
|
|
|
|
<li>on {INJURY_LOCATION_CHOICE[location][1]},</li>
|
|
|
|
<li>{INJURY_BODY_SIDE_CHOICE[body_side][1]} side,</li>
|
2023-11-18 18:29:18 +01:00
|
|
|
</ul>
|
2023-11-26 17:29:28 +01:00
|
|
|
{MAIL_FOOTER}""",
|
2023-04-29 15:31:14 +02:00
|
|
|
)
|
2023-04-25 17:06:14 +02:00
|
|
|
|
2023-07-06 23:37:07 +02:00
|
|
|
return HttpResponseRedirect(reverse("injury_details", args=(injury.pk,)))
|
2023-04-25 17:06:14 +02:00
|
|
|
else:
|
2023-07-06 23:37:07 +02:00
|
|
|
return render(request, "injuries/create.html", {"form": form})
|
2023-04-25 17:06:14 +02:00
|
|
|
|
2023-07-06 23:37:07 +02:00
|
|
|
form = InjuryForm(instance=injury, initial=data)
|
|
|
|
context = {"form": form, "injury_id": injury_id}
|
|
|
|
return render(request, "injuries/create.html", context)
|
2023-04-25 17:06:14 +02:00
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
@require_http_methods(["GET"])
|
2023-07-06 23:37:07 +02:00
|
|
|
def injury_detail(request, injury_id):
|
2023-04-25 17:06:14 +02:00
|
|
|
"""
|
2023-07-06 23:37:07 +02:00
|
|
|
Récupère toutes les informations d'une blessure.
|
2023-05-14 19:10:34 +02:00
|
|
|
|
|
|
|
Args:
|
2023-07-06 23:37:07 +02:00
|
|
|
injury_id (int) identifiant d'une blessure
|
2023-04-25 17:06:14 +02:00
|
|
|
"""
|
2023-07-06 23:37:07 +02:00
|
|
|
injury = get_object_or_404(Injury, pk=injury_id)
|
|
|
|
return render(request, "injuries/details.html", {"injury": injury})
|
2023-04-25 17:06:14 +02:00
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
@require_http_methods(["GET"])
|
2023-07-05 09:33:03 +02:00
|
|
|
def wellbeing_listing(request, gymnast_id=None):
|
2023-04-25 17:06:14 +02:00
|
|
|
"""
|
|
|
|
Récupère la liste des évaluations mentales suivant (d'un gymnaste si définit en paramètre).
|
2023-05-14 19:10:34 +02:00
|
|
|
|
|
|
|
Args:
|
|
|
|
gymnast_id (int) identifiant d'un gymnaste
|
2023-04-25 17:06:14 +02:00
|
|
|
"""
|
|
|
|
gymnast = None
|
|
|
|
if gymnast_id:
|
2023-07-05 10:51:49 +02:00
|
|
|
wellbeing_list = WellBeing.objects.filter(gymnast=gymnast_id)
|
2023-04-25 17:06:14 +02:00
|
|
|
gymnast = get_object_or_404(Gymnast, pk=gymnast_id)
|
|
|
|
else:
|
2023-07-05 10:51:49 +02:00
|
|
|
wellbeing_list = WellBeing.objects.all()
|
2023-04-25 17:06:14 +02:00
|
|
|
|
2023-07-05 09:33:03 +02:00
|
|
|
context = {"wellbeing_list": wellbeing_list, "gymnast": gymnast}
|
|
|
|
return render(request, "wellbeing/list.html", context)
|
2023-04-25 17:06:14 +02:00
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
@require_http_methods(["GET", "POST"])
|
2023-07-05 09:33:03 +02:00
|
|
|
def wellbeing_create_or_update(
|
|
|
|
request, wellbeing_id=None, gymnast_id=None, event_id=None
|
2023-04-25 17:06:14 +02:00
|
|
|
):
|
|
|
|
"""
|
2023-07-06 23:37:07 +02:00
|
|
|
Formulaire de création d'une nouvelle blessure.
|
2023-05-14 19:10:34 +02:00
|
|
|
|
|
|
|
Args:
|
2023-07-06 23:37:07 +02:00
|
|
|
wellbeing_id (int) identifiant d'une blessure
|
2023-05-14 19:10:34 +02:00
|
|
|
gymnast_id (int) identifiant d'un gymnaste
|
|
|
|
event_id (int) identifiant d'un événement
|
2023-04-25 17:06:14 +02:00
|
|
|
"""
|
|
|
|
|
2023-07-05 09:33:03 +02:00
|
|
|
if wellbeing_id:
|
2023-07-05 10:51:49 +02:00
|
|
|
wellbeing = get_object_or_404(WellBeing, pk=wellbeing_id)
|
2023-07-05 09:33:03 +02:00
|
|
|
data = {"gymnast_related": wellbeing.gymnast, "event_related": wellbeing.event}
|
2023-04-25 17:06:14 +02:00
|
|
|
else:
|
2023-07-05 09:33:03 +02:00
|
|
|
wellbeing = None
|
2023-04-25 17:06:14 +02:00
|
|
|
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":
|
2023-07-05 09:33:03 +02:00
|
|
|
form = WellBeingForm(request.POST, instance=wellbeing)
|
2023-04-25 17:06:14 +02:00
|
|
|
|
|
|
|
if form.is_valid():
|
2023-07-05 09:33:03 +02:00
|
|
|
wellbeing = form.save()
|
2023-04-25 17:06:14 +02:00
|
|
|
|
|
|
|
# notification
|
2023-04-29 15:31:14 +02:00
|
|
|
receiver = []
|
2023-04-25 17:06:14 +02:00
|
|
|
gymnast = Gymnast.objects.get(pk=form.cleaned_data["gymnast"].id)
|
2023-05-11 10:51:10 +02:00
|
|
|
date = form.cleaned_data["date"]
|
2023-07-05 09:33:03 +02:00
|
|
|
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"]
|
2023-11-29 11:13:47 +01:00
|
|
|
details = form.cleaned_data["informations"]
|
2023-07-05 10:51:49 +02:00
|
|
|
functionality = ContentType.objects.get(model="wellbeing")
|
2023-04-28 12:20:55 +02:00
|
|
|
for notification in gymnast.notifications.filter(
|
|
|
|
functionality=functionality
|
|
|
|
):
|
2023-04-29 15:31:14 +02:00
|
|
|
receiver.append(notification.user.email)
|
|
|
|
|
|
|
|
send_mail(
|
2023-07-05 09:33:03 +02:00
|
|
|
f"{gymnast} : Nouveau score de bien être",
|
|
|
|
f"{gymnast} a ajouté état de bien être ({date})",
|
2023-04-29 15:31:14 +02:00
|
|
|
settings.EMAIL_HOST_USER,
|
|
|
|
receiver,
|
|
|
|
fail_silently=False,
|
|
|
|
html_message=f"""<p>Bonjour,</p>
|
2023-11-14 12:15:09 +01:00
|
|
|
<p>{gymnast} a ajouté son état de bien être pour le ({date.strftime('%d %B %Y')}) :</p>
|
2023-07-05 09:33:03 +02:00
|
|
|
<ul>
|
|
|
|
<li>Mindstate: {mindstate}</li>
|
|
|
|
<li>Sleep: {sleep}</li>
|
|
|
|
<li>Stress: {stress}</li>
|
|
|
|
<li>Fatigue: {fatigue}</li>
|
2023-11-18 18:29:18 +01:00
|
|
|
<li>Muscle soreness: {muscle_soreness}</li>
|
2023-10-11 12:12:01 +02:00
|
|
|
</ul>
|
2023-11-29 11:13:47 +01:00
|
|
|
{details}
|
2023-11-26 17:29:28 +01:00
|
|
|
{MAIL_FOOTER}
|
|
|
|
""",
|
2023-04-29 15:31:14 +02:00
|
|
|
)
|
2023-04-25 17:06:14 +02:00
|
|
|
|
|
|
|
return HttpResponseRedirect(
|
2023-07-05 09:33:03 +02:00
|
|
|
reverse("wellbeing_details", args=(wellbeing.pk,))
|
2023-04-25 17:06:14 +02:00
|
|
|
)
|
|
|
|
else:
|
2023-07-05 09:33:03 +02:00
|
|
|
return render(request, "wellbeing/create.html", {"form": form})
|
2023-04-25 17:06:14 +02:00
|
|
|
|
2023-07-05 09:33:03 +02:00
|
|
|
form = WellBeingForm(instance=wellbeing, initial=data)
|
|
|
|
context = {"form": form, "wellbeing_id": wellbeing_id}
|
|
|
|
return render(request, "wellbeing/create.html", context)
|
2023-04-25 17:06:14 +02:00
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
@require_http_methods(["GET"])
|
2023-07-05 09:33:03 +02:00
|
|
|
def wellbeing_detail(request, wellbeing_id):
|
2023-04-25 17:06:14 +02:00
|
|
|
"""
|
|
|
|
Récupère toutes les informations d'une évaluation psychologique.
|
2023-05-14 19:10:34 +02:00
|
|
|
|
|
|
|
Args:
|
2023-07-05 09:33:03 +02:00
|
|
|
wellbeing_id (int) identifiant d'une évaluation psycho
|
2023-04-25 17:06:14 +02:00
|
|
|
"""
|
2023-07-05 10:51:49 +02:00
|
|
|
wellbeing = get_object_or_404(WellBeing, pk=wellbeing_id)
|
2023-07-05 09:33:03 +02:00
|
|
|
return render(request, "wellbeing/details.html", {"wellbeing": wellbeing})
|
2023-04-25 17:06:14 +02:00
|
|
|
|
|
|
|
|
|
|
|
@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).
|
2023-05-14 19:10:34 +02:00
|
|
|
|
|
|
|
Args:
|
|
|
|
gymnast_id (int) identifiant d'un gymnaste
|
2023-04-25 17:06:14 +02:00
|
|
|
"""
|
|
|
|
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, "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.
|
2023-05-14 19:10:34 +02:00
|
|
|
|
|
|
|
Args:
|
2023-05-16 14:55:41 +02:00
|
|
|
heightweight_id (int) identifiant d'un couple taille/couple
|
|
|
|
gymnast_id (int) identifiant d'un gymnaste
|
2023-04-25 17:06:14 +02:00
|
|
|
"""
|
|
|
|
|
|
|
|
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()
|
|
|
|
|
|
|
|
# notification
|
2023-04-29 15:31:14 +02:00
|
|
|
receiver = []
|
2023-11-14 12:15:09 +01:00
|
|
|
date = form.cleaned_data["date"]
|
2023-10-17 10:26:19 +02:00
|
|
|
height = form.cleaned_data["height"] / 100
|
2023-05-16 14:55:41 +02:00
|
|
|
weight = form.cleaned_data["weight"]
|
|
|
|
bmi = weight / (height * height)
|
2023-10-17 10:26:19 +02:00
|
|
|
bmi = format(bmi, ".1f")
|
2023-04-25 17:06:14 +02:00
|
|
|
gymnast = Gymnast.objects.get(pk=form.cleaned_data["gymnast"].id)
|
2023-04-28 12:20:55 +02:00
|
|
|
functionality = ContentType.objects.get(model="heightweight")
|
|
|
|
for notification in gymnast.notifications.filter(
|
|
|
|
functionality=functionality
|
|
|
|
):
|
2023-04-29 15:31:14 +02:00
|
|
|
receiver.append(notification.user.email)
|
|
|
|
|
|
|
|
send_mail(
|
|
|
|
f"{gymnast} : Nouveau poids/taille enregistré",
|
2023-11-21 09:10:28 +01:00
|
|
|
f"Un nouveau poids/taille enregistré pour {gymnast} ({date}) : {height} cm / {weight} kg (BMI: {bmi}).",
|
2023-04-29 15:31:14 +02:00
|
|
|
settings.EMAIL_HOST_USER,
|
|
|
|
receiver,
|
|
|
|
fail_silently=False,
|
|
|
|
html_message=f"""<p>Bonjour,</p>
|
2023-11-29 11:13:47 +01:00
|
|
|
<p>Un nouveau poids/taille enregistré pour {gymnast} pour le {date.strftime('%d %B %Y')}:</p>
|
2023-11-14 12:15:09 +01:00
|
|
|
<ul>
|
2023-11-21 09:10:28 +01:00
|
|
|
<li>Height: {height} cm</li>
|
|
|
|
<li>Weight: {weight} kg</li>
|
|
|
|
<li>BMI: {bmi}</li>
|
2023-11-14 12:15:09 +01:00
|
|
|
</ul>
|
2023-11-26 17:29:28 +01:00
|
|
|
{MAIL_FOOTER}""",
|
2023-04-29 15:31:14 +02:00
|
|
|
)
|
2023-04-25 17:06:14 +02:00
|
|
|
|
|
|
|
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
|
2023-05-14 19:10:34 +02:00
|
|
|
|
|
|
|
Args:
|
|
|
|
gymnast_id (int) identifiant d'un gymnaste
|
2023-04-25 17:06:14 +02:00
|
|
|
"""
|
|
|
|
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):
|
2023-05-14 19:10:34 +02:00
|
|
|
"""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
|
|
|
|
"""
|
2023-04-25 17:06:14 +02:00
|
|
|
|
|
|
|
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
|
2023-04-29 15:31:14 +02:00
|
|
|
receiver = []
|
2023-04-25 17:06:14 +02:00
|
|
|
gymnast = Gymnast.objects.get(pk=form.cleaned_data["gymnast"].id)
|
2023-04-28 12:20:55 +02:00
|
|
|
functionality = ContentType.objects.get(model="numberofroutinedone")
|
|
|
|
for notification in gymnast.notifications.filter(
|
|
|
|
functionality=functionality
|
|
|
|
):
|
2023-04-29 15:31:14 +02:00
|
|
|
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"""<p>Bonjour,</p>
|
2023-11-26 17:29:28 +01:00
|
|
|
<p>Nouvelle série comptabilisée pour {gymnast}.</p>
|
|
|
|
{MAIL_FOOTER}""",
|
2023-04-29 15:31:14 +02:00
|
|
|
)
|
2023-04-25 17:06:14 +02:00
|
|
|
|
|
|
|
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:
|
2023-05-14 19:10:34 +02:00
|
|
|
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>).
|
2023-04-25 17:06:14 +02:00
|
|
|
"""
|
|
|
|
|
|
|
|
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
|
2023-04-29 15:31:14 +02:00
|
|
|
receiver = []
|
2023-04-25 17:06:14 +02:00
|
|
|
gymnast = Gymnast.objects.get(pk=form.cleaned_data["gymnast"].id)
|
2023-06-13 14:35:29 +02:00
|
|
|
date = form.cleaned_data["date"]
|
|
|
|
educative = form.cleaned_data["educative"]
|
|
|
|
learning_step = form.cleaned_data["learning_step"]
|
2023-04-28 12:20:55 +02:00
|
|
|
functionality = ContentType.objects.get(model="plan")
|
|
|
|
for notification in gymnast.notifications.filter(
|
|
|
|
functionality=functionality
|
|
|
|
):
|
2023-04-29 15:31:14 +02:00
|
|
|
receiver.append(notification.user.email)
|
|
|
|
|
|
|
|
send_mail(
|
2023-06-13 14:35:29 +02:00
|
|
|
f"{gymnast} : Nouvel objectif fixé",
|
|
|
|
f"Nouvel objectif fixé pour {gymnast}",
|
2023-04-29 15:31:14 +02:00
|
|
|
settings.EMAIL_HOST_USER,
|
|
|
|
receiver,
|
|
|
|
fail_silently=False,
|
|
|
|
html_message=f"""<p>Bonjour,</p>
|
2023-11-14 12:15:09 +01:00
|
|
|
<p>Nouvel objectif fixé pour {gymnast} : {educative} ({learning_step}) pour le {date.strftime('%d %B %Y')} au plus tard.</p>
|
2023-11-26 17:29:28 +01:00
|
|
|
{MAIL_FOOTER}""",
|
2023-04-29 15:31:14 +02:00
|
|
|
)
|
2023-04-25 17:06:14 +02:00
|
|
|
|
|
|
|
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)
|
|
|
|
|
|
|
|
|
2023-11-12 19:22:52 +01:00
|
|
|
@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})
|
|
|
|
|
|
|
|
|
2023-04-25 17:06:14 +02:00
|
|
|
@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:
|
2023-05-15 13:58:02 +02:00
|
|
|
intensity_id (int) identifiant d'une intensité (classe <Intensity>).
|
|
|
|
gymnast_id (int) identifiant d'un gymnaste (classe <Gymnast>).
|
2023-04-25 17:06:14 +02:00
|
|
|
"""
|
|
|
|
|
|
|
|
if intensity_id:
|
|
|
|
intensity = get_object_or_404(Intensity, pk=intensity_id)
|
|
|
|
data = {
|
|
|
|
"gymnast": intensity.gymnast.id,
|
|
|
|
"gymnast_related": str(intensity.gymnast),
|
|
|
|
}
|
|
|
|
else:
|
|
|
|
intensity = 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 = IntensityForm(request.POST, instance=intensity)
|
|
|
|
|
|
|
|
if form.is_valid():
|
|
|
|
intensity = form.save()
|
|
|
|
|
|
|
|
# notification
|
2023-04-29 15:31:14 +02:00
|
|
|
receiver = []
|
2023-05-15 13:58:02 +02:00
|
|
|
date = form.cleaned_data["date"]
|
|
|
|
time = form.cleaned_data["time"]
|
|
|
|
difficulty = form.cleaned_data["difficulty"]
|
|
|
|
quantity_of_skill = form.cleaned_data["quantity_of_skill"]
|
|
|
|
number_of_passes = form.cleaned_data["number_of_passes"]
|
2023-11-18 18:29:18 +01:00
|
|
|
skill_by_time = quantity_of_skill / time
|
2023-11-12 17:47:46 +01:00
|
|
|
skill_by_passe = quantity_of_skill / number_of_passes
|
2023-11-29 11:13:47 +01:00
|
|
|
diff_by_skill = difficulty / (10 * quantity_of_skill)
|
|
|
|
diff_by_passe = difficulty / (10 * number_of_passes)
|
2023-11-12 17:47:46 +01:00
|
|
|
time_by_passe = time / number_of_passes
|
2023-04-25 17:06:14 +02:00
|
|
|
gymnast = Gymnast.objects.get(pk=form.cleaned_data["gymnast"].id)
|
2023-04-28 12:20:55 +02:00
|
|
|
functionality = ContentType.objects.get(model="intensity")
|
|
|
|
for notification in gymnast.notifications.filter(
|
|
|
|
functionality=functionality
|
|
|
|
):
|
2023-04-29 15:31:14 +02:00
|
|
|
receiver.append(notification.user.email)
|
|
|
|
|
|
|
|
send_mail(
|
|
|
|
f"{gymnast} : Nouvelle intensité",
|
2023-05-15 13:58:02 +02:00
|
|
|
f"{gymnast} a encodé une nouvelle intensité.",
|
2023-04-29 15:31:14 +02:00
|
|
|
settings.EMAIL_HOST_USER,
|
|
|
|
receiver,
|
|
|
|
fail_silently=False,
|
|
|
|
html_message=f"""<p>Bonjour,</p>
|
2023-11-29 11:13:47 +01:00
|
|
|
<p>{gymnast} a encodé une nouvelle intensité pour le {date.strftime('%d %B %Y')}:</p>
|
2023-11-12 17:47:46 +01:00
|
|
|
<ul>
|
|
|
|
<li>{number_of_passes} passages</li>
|
|
|
|
<li>{time} minutes</li>
|
|
|
|
<li>{quantity_of_skill} figures</li>
|
2023-11-22 10:27:41 +01:00
|
|
|
<li>{difficulty / 10} difficulty</li>
|
2023-11-12 17:47:46 +01:00
|
|
|
</ul>
|
2023-11-22 10:27:41 +01:00
|
|
|
<p><u>Statistics:</u></p>
|
2023-11-12 17:47:46 +01:00
|
|
|
<ul>
|
2023-11-29 11:13:47 +01:00
|
|
|
<li>Passe: {time_by_passe:.2f}min</li>
|
|
|
|
<li>Skill: {skill_by_time:.2f}min</li>
|
2023-11-18 18:29:18 +01:00
|
|
|
<li>Skill/passe: {skill_by_passe:.2f}</li>
|
|
|
|
<li>Diff/passe: {diff_by_passe:.2f}</li>
|
|
|
|
<li>Diff/skill: {diff_by_skill:.2f}</li>
|
2023-11-12 17:47:46 +01:00
|
|
|
</ul>
|
2023-11-26 17:29:28 +01:00
|
|
|
{MAIL_FOOTER}""",
|
2023-04-29 15:31:14 +02:00
|
|
|
)
|
2023-04-25 17:06:14 +02:00
|
|
|
|
|
|
|
return HttpResponseRedirect(
|
|
|
|
reverse(
|
|
|
|
"gymnast_details_tab",
|
|
|
|
args=(form.cleaned_data["gymnast"].id, "routine"),
|
|
|
|
)
|
|
|
|
)
|
|
|
|
else:
|
|
|
|
return render(request, "intensities/create.html", {"form": form})
|
|
|
|
|
|
|
|
form = IntensityForm(instance=intensity, initial=data)
|
|
|
|
context = {"form": form, "intensity_id": intensity_id}
|
|
|
|
return render(request, "intensities/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 Intentity.
|
|
|
|
|
|
|
|
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
|
|
|
|
)
|
|
|
|
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
|
2023-04-29 15:31:14 +02:00
|
|
|
receiver = []
|
2023-04-25 17:06:14 +02:00
|
|
|
gymnast = Gymnast.objects.get(pk=form.cleaned_data["gymnast"].id)
|
2023-04-28 12:20:55 +02:00
|
|
|
functionality = ContentType.objects.get(model="seasoninformation")
|
|
|
|
for notification in gymnast.notifications.filter(
|
|
|
|
functionality=functionality
|
|
|
|
):
|
2023-04-29 15:31:14 +02:00
|
|
|
receiver.append(notification.user.email)
|
|
|
|
|
|
|
|
send_mail(
|
|
|
|
f"{gymnast} : Nouvelle information de saison",
|
|
|
|
f"Une nouvelle information de saison enregistrée pour {gymnast}",
|
|
|
|
settings.EMAIL_HOST_USER,
|
|
|
|
receiver,
|
|
|
|
fail_silently=False,
|
|
|
|
html_message=f"""<p>Bonjour,</p>
|
2023-11-26 17:29:28 +01:00
|
|
|
<p>Une nouvelle information de saison enregistrée pour {gymnast}.</p>
|
|
|
|
{MAIL_FOOTER}""",
|
2023-04-29 15:31:14 +02:00
|
|
|
)
|
2023-04-25 17:06:14 +02:00
|
|
|
|
|
|
|
return HttpResponseRedirect(
|
|
|
|
reverse(
|
|
|
|
"gymnast_details",
|
|
|
|
args=(form.cleaned_data["gymnast"].id,),
|
|
|
|
)
|
|
|
|
)
|
|
|
|
else:
|
2023-10-29 20:18:35 +01:00
|
|
|
return render(request, "seasoninformations/create.html", {"form": form})
|
2023-04-25 17:06:14 +02:00
|
|
|
|
|
|
|
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):
|
2023-05-14 19:10:34 +02:00
|
|
|
"""Liste toutes les informations de saison pour un gymnaste.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
gymnast_id (int) identifiant d'un gymnaste
|
|
|
|
"""
|
2023-04-25 17:06:14 +02:00
|
|
|
|
|
|
|
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)
|