Jarvis/jarvis/core/views.py

381 lines
14 KiB
Python
Raw Normal View History

2023-04-25 17:06:14 +02:00
from datetime import timedelta
2024-04-24 10:04:37 +02:00
from weasyprint import HTML, CSS
import pendulum
2023-04-25 17:06:14 +02:00
2024-04-24 10:04:37 +02:00
from django.db.models import Max
from django.conf import settings
2023-05-22 08:53:55 +02:00
from django.db.models import Q, F, OuterRef, Subquery
2024-05-09 21:38:23 +02:00
from django.shortcuts import render, get_object_or_404
2023-04-25 17:06:14 +02:00
from django.utils import timezone
from django.contrib.auth import authenticate, login as auth_login, logout as auth_logout
from django.http import HttpResponse, HttpResponseRedirect
from django.contrib.auth.decorators import login_required
from django.views.decorators.http import require_http_methods
from django.template.loader import render_to_string
from django.urls import reverse
2024-05-02 10:23:12 +02:00
from django.contrib.auth import get_user_model
2023-04-25 17:06:14 +02:00
from jarvis.objective.models import Routine
from jarvis.profiles.models import Profile
2024-05-09 21:38:23 +02:00
from jarvis.followup.models import (
Skill,
Point,
Chrono,
WellBeing,
Intensity,
HeightWeight,
LearnedSkill
)
2023-04-25 17:06:14 +02:00
from jarvis.location.models import Place, Club
from jarvis.people.models import Gymnast
from jarvis.people.views import gymnast_details
from jarvis.planning.models import Event
from jarvis.tools.models import from_date_to_week_number
2024-02-06 13:07:12 +01:00
from jarvis.tools.clean_name import clean_name
2023-10-31 08:15:23 +01:00
from jarvis.tools.models import Season
2024-04-24 10:04:37 +02:00
from .models import Citation
2023-04-25 17:06:14 +02:00
2024-05-02 10:23:12 +02:00
User = get_user_model()
2023-04-25 17:06:14 +02:00
def login(request):
2024-02-12 16:03:05 +01:00
"""Fonction d'authentifictation."""
2023-04-25 17:06:14 +02:00
if request.method == "POST":
username = request.POST["login"]
password = request.POST["password"]
user = authenticate(username=username, password=password)
2023-05-20 19:33:47 +02:00
if user is not None:
2023-04-25 17:06:14 +02:00
if user.is_active:
auth_login(request, user)
2024-02-12 16:03:05 +01:00
2024-02-12 16:05:48 +01:00
try:
profile = Profile.objects.get(user=user)
2023-04-25 17:06:14 +02:00
request.session["profileid"] = profile.id
request.session["template"] = profile.template_color
request.session["sidebar"] = profile.sidebar_color
request.session["is_sidebar_minified"] = profile.is_sidebar_minified
2024-02-12 16:05:48 +01:00
except Profile.DoesNotExist:
pass
2024-02-11 09:25:20 +01:00
2024-05-01 16:57:15 +02:00
request.session["available_gymnast"] = [x.gymnast.id for x in user.can_view.all()]
2023-04-25 17:06:14 +02:00
return HttpResponseRedirect(reverse("home"))
context = {"message": "Account disabled."}
else:
context = {"message": "Wrong login/password."}
else:
context = {}
return render(request, "login.html", context)
@login_required
@require_http_methods(["GET"])
def logout(request):
"""
Fonction de déconnexion
"""
auth_logout(request)
return HttpResponseRedirect(reverse("login"))
def next_birthdays(request, number_of_birthday):
"""
Renvoie la liste des `number_of_birthday` prochains anniversaires.
"""
birthday_list = sorted(
Gymnast.objects.all(), key=lambda t: t.next_birthday_in_days
)[:number_of_birthday]
return birthday_list
2024-05-10 21:53:02 +02:00
def gymnast_have_birthday(request):
"""
Renvoie la liste des gymnastes qui ont leur anniversaire aujourd'hui.
"""
today = pendulum.now().date()
return Gymnast.objects.filter(birthdate__day=today.day, birthdate__month=today.month).values_list("id")
2023-04-25 17:06:14 +02:00
# @lru_cache()
# def get_last_updated_gymnasts(expiration_date):
# ...
2024-05-11 09:41:29 +02:00
# TODO: liste de mots pour souhaiter la bienvenue
2024-05-10 21:53:02 +02:00
# TODO: véririer si c'est l'anniversaire de la personne qui est connectée.
2023-04-25 17:06:14 +02:00
2024-05-10 21:53:02 +02:00
# TODO: check if gymnast have point
# ---------------------------
# 1. récupérer tous les évènements passés
# 2. pour chaque event, vérifier que tous les gymnastes renseignés
# dans les participants ont des points associés.
# S'il n'y a pas de point, faire une alerte à l'utilisateur qui se connecte.
# TODO: Check if gymnast have update
# -----------------------------
# lister tous les gymnastes qui n'ont pas eu d'update depuis... 2 semaines ?
# peut-être le paramètre (en jour) devrait être stocké en DB.
# S'il n'y a pas d'update, faire une alerte à l'utilisateur qui se connecte.
2023-04-25 17:06:14 +02:00
@login_required
@require_http_methods(["GET"])
def home(request):
"""
Génère la page d'accueil du site basée sur la saison (si celle-ci est connue)
"""
2023-07-03 13:09:24 +02:00
today = timezone.now() # pendulum.now().date()
2023-06-22 13:14:56 +02:00
_, week_number = from_date_to_week_number(today)
2023-04-25 17:06:14 +02:00
2024-05-10 21:53:02 +02:00
context = {
"week_number": week_number,
"quote": Citation.objects.order_by("?").first(),
"event_list": Event.objects.filter(date_begin__gte=today).order_by("date_begin")[:10],
"nb_active_gymnast": Gymnast.objects.filter(is_active=True).count(),
"nb_trainer": User.objects.filter(is_active=True, groups__name="trainer").count(),
"nb_event": Event.objects.all().count(),
"nb_skill": Skill.objects.all().count(),
"nb_routine": Routine.objects.all().count(),
"nb_score": Point.objects.all().count(),
"nb_club": Club.objects.all().count(),
"percentage_week": (week_number / 52) * 100,
"birthday_list": next_birthdays(request, 10),
}
2023-04-25 17:06:14 +02:00
2024-05-07 11:02:45 +02:00
is_trainer = request.user.groups.filter(name="trainer").exists()
if is_trainer:
last_updated_gymnasts = set()
last_updated_gymnasts.update(
Gymnast.objects.filter(wellbeings__created_at__gt=request.user.last_login)
2023-10-31 08:15:23 +01:00
)
2024-05-07 11:02:45 +02:00
last_updated_gymnasts.update(
Gymnast.objects.filter(height_weight__date__gt=request.user.last_login)
)
last_updated_gymnasts.update(
Gymnast.objects.filter(intensities__date__gt=request.user.last_login)
)
last_updated_gymnasts.update(
Gymnast.objects.filter(points__created_at__gt=request.user.last_login)
)
last_updated_gymnasts.update(
Gymnast.objects.filter(chronos__created_at__gt=request.user.last_login)
)
last_updated_gymnasts.update(
Gymnast.objects.filter(injuries__created_at__gt=request.user.last_login)
)
last_updated_gymnasts.update(
Gymnast.objects.filter(known_skills__created_at__gt=request.user.last_login)
)
season = Season()
# Paramètre dans le fichier .env ?
limit_date = today - timedelta(days=7)
waiting_update_gymnast = (
Gymnast.objects.filter(season_informations__season=season)
.exclude(
Q(is_active=False)
| Q(wellbeings__created_at__gte=limit_date)
| Q(points__created_at__gte=limit_date)
| Q(chronos__created_at__gte=limit_date)
| Q(injuries__created_at__gte=limit_date)
| Q(known_skills__created_at__gte=limit_date)
)
.distinct()
)
2023-04-25 17:06:14 +02:00
2024-05-10 21:53:02 +02:00
context["is_trainer"] = is_trainer
context["last_updated_gymnasts"] = last_updated_gymnasts
context["waiting_update_gymnast"] = waiting_update_gymnast
2023-04-25 17:06:14 +02:00
2024-05-10 21:53:02 +02:00
else:
todate = pendulum.now().date()
birthday_list = gymnast_have_birthday(request)
gymnast = get_object_or_404(Gymnast, pk=request.user.gymnast.id)
2024-05-11 09:41:29 +02:00
context["gymnast"] = gymnast
2023-04-25 17:06:14 +02:00
2024-05-10 21:53:02 +02:00
# if birthday_list is not None and gymnast.id in birthday_list:
# print("C'est l'anniversaire du gymnaste !")
# else:
# print("Pas son annif…")
2023-04-25 17:06:14 +02:00
2024-05-10 21:53:02 +02:00
wellbeing_last_record_date = WellBeing.objects.filter(gymnast=gymnast).values_list("date").order_by("-date").first()
2024-05-13 14:13:38 +02:00
wellbeing_state = None
if wellbeing_last_record_date:
if todate.diff(wellbeing_last_record_date[0]).in_days() > 21:
wellbeing_state = "danger bold"
elif todate.diff(wellbeing_last_record_date[0]).in_days() > 14:
wellbeing_state = "danger"
elif todate.diff(wellbeing_last_record_date[0]).in_days() > 7:
wellbeing_state = "warning"
2024-05-10 21:53:02 +02:00
height_weight_last_record_date = HeightWeight.objects.filter(gymnast=gymnast).values_list("date").order_by("-date").first()
2024-05-13 14:13:38 +02:00
height_weight_state = None
if height_weight_last_record_date:
if todate.diff(height_weight_last_record_date[0]).in_days() > 21:
height_weight_state = "danger bold"
elif todate.diff(height_weight_last_record_date[0]).in_days() > 14:
height_weight_state = "danger"
elif todate.diff(height_weight_last_record_date[0]).in_days() > 7:
height_weight_state = "warning"
2024-05-10 21:53:02 +02:00
intensities_last_record_date = Intensity.objects.filter(gymnast=gymnast).values_list("date").order_by("-date").first()
2024-05-13 14:13:38 +02:00
intensity_state = None
if intensities_last_record_date:
if todate.diff(intensities_last_record_date[0]).in_days() > 21:
intensity_state = "danger bold"
elif todate.diff(intensities_last_record_date[0]).in_days() > 14:
intensity_state = "danger"
elif todate.diff(intensities_last_record_date[0]).in_days() > 7:
intensity_state = "warning"
2023-04-25 17:06:14 +02:00
2024-05-10 21:53:02 +02:00
# points_last_update = Gymnast.objects.all().order_by("-date")[:1]
chrono_last_record_date = Chrono.objects.filter(gymnast=gymnast).values_list("date").order_by("-date").first()
2024-05-13 14:13:38 +02:00
chrono_state = None
if chrono_last_record_date:
if todate.diff(chrono_last_record_date[0]).in_days() > 21:
chrono_state = "danger bold"
elif todate.diff(chrono_last_record_date[0]).in_days() > 14:
chrono_state = "danger"
elif todate.diff(chrono_last_record_date[0]).in_days() > 7:
chrono_state = "warning"
2024-05-10 21:53:02 +02:00
known_skills_last_record_date = LearnedSkill.objects.filter(gymnast=gymnast).values_list("date").order_by("-date").first()
2024-05-13 14:13:38 +02:00
known_skills_state = None
if known_skills_last_record_date:
if todate.diff(known_skills_last_record_date[0]).in_days() > 21:
known_skills_state = "danger bold"
elif todate.diff(known_skills_last_record_date[0]).in_days() > 14:
known_skills_state = "danger"
elif todate.diff(known_skills_last_record_date[0]).in_days() > 7:
known_skills_state = "warning"
2024-05-10 21:53:02 +02:00
context["wellbeing_last_record_date"] = wellbeing_last_record_date
context["wellbeing_state"] = wellbeing_state
context["height_weight_last_record_date"] = height_weight_last_record_date
context["height_weight_state"] = height_weight_state
context["intensities_last_record_date"] = intensities_last_record_date
context["intensity_state"] = intensity_state
2024-05-09 21:38:23 +02:00
# "points_last_update": points_last_update,
2024-05-10 21:53:02 +02:00
context["chrono_last_record_date"] = chrono_last_record_date
context["chrono_state"] = chrono_state
context["known_skills_last_record_date"] = known_skills_last_record_date
context["known_skills_state"] = known_skills_state
2023-04-25 17:06:14 +02:00
return render(request, "dashboard/dashboard.html", context)
@login_required
@require_http_methods(["GET"])
def search(request):
"""
Recherche globale au travers de toutes les applications.
"""
pattern = request.GET.get("pattern", None)
if pattern:
2024-02-06 13:07:12 +01:00
name = clean_name(pattern)
2023-04-25 17:06:14 +02:00
gymnast_list = Gymnast.objects.filter(
2024-02-06 13:07:12 +01:00
Q(cleaned_last_name__icontains=name) | Q(cleaned_first_name__icontains=name)
2023-04-25 17:06:14 +02:00
)
if gymnast_list.count() == 1:
gymnast = gymnast_list.first()
return gymnast_details(request, gymnast.id)
else:
skill_list = Skill.objects.filter(
2024-04-15 11:23:18 +02:00
Q(long_label__icontains=pattern)
| Q(short_label__icontains=pattern)
| Q(notation__icontains=pattern)
2023-04-25 17:06:14 +02:00
)
event_list = Event.objects.filter(
Q(name__icontains=pattern) | Q(place__name__icontains=pattern)
)
place_list = Place.objects.filter(
Q(name__icontains=pattern) | Q(city__icontains=pattern)
)
club_list = Club.objects.filter(
Q(name__icontains=pattern)
| Q(place__name__icontains=pattern)
| Q(place__city__icontains=pattern)
)
context = {
"gymnast_list": gymnast_list,
"skill_list": skill_list,
"event_list": event_list,
"place_list": place_list,
"club_list": club_list,
"pattern": pattern,
}
else:
context = {}
return render(request, "search/results.html", context)
2024-04-05 13:00:17 +02:00
@login_required
@require_http_methods(["GET"])
2023-05-20 19:33:47 +02:00
def report_listing(request):
"""Liste des rapports disponibles"""
2024-04-05 13:00:17 +02:00
return render(request, "reports/list.html", {})
2023-05-20 19:33:47 +02:00
2024-04-05 13:00:17 +02:00
@login_required
@require_http_methods(["GET"])
2023-04-25 17:06:14 +02:00
def generate_best_straightjump_listing(request):
2023-05-22 08:53:55 +02:00
"""Va chercher le meilleur chrono pour chaque gymnaste et sa date de réalisation pour en générer
un fichier PDF."""
2023-04-25 17:06:14 +02:00
date_begin = pendulum.now().date()
season, week_number = from_date_to_week_number(date_begin)
records_list = (
2023-05-22 08:53:55 +02:00
Gymnast.objects.values("last_name", "first_name")
.annotate(
score=Max("chronos__score"),
date=Subquery(
Chrono.objects.filter(gymnast=OuterRef("pk"))
.order_by(F("score").desc(nulls_last=True))
.values("date")[:1]
),
)
2023-05-21 11:11:33 +02:00
.order_by("-score")
2023-04-25 17:06:14 +02:00
)
context = {
"SITE_TITLE": settings.SITE_TITLE,
"CLUB_NAME": settings.CLUB_NAME,
"ADDRESS": settings.ADDRESS,
"CITY": settings.CITY,
"ZIP": settings.ZIP,
"HEAD_COACH": settings.HEAD_COACH,
"MOBILE_PHONE": settings.MOBILE_PHONE,
"HEAD_COACH_EMAIL": settings.HEAD_COACH_EMAIL,
"week_number": week_number,
"today": date_begin,
"records_list": records_list,
}
2023-05-21 11:11:33 +02:00
# return render(request, "reports/records_10.html", context)
2023-04-25 17:06:14 +02:00
response = HttpResponse(content_type="application/pdf")
response["Content-Disposition"] = "attachment; filename=report-top_straightjump.pdf"
2023-05-20 19:33:47 +02:00
html = render_to_string("reports/records_10.html", context)
2023-04-25 17:06:14 +02:00
# font_config = FontConfiguration()
HTML(string=html, base_url=request.build_absolute_uri()).write_pdf(
response,
stylesheets=[
2024-04-29 12:55:05 +02:00
CSS(settings.STATICFILES_DIRS[0] + "/css/a4_paper.css"),
2023-04-25 17:06:14 +02:00
CSS(settings.STATICFILES_DIRS[0] + "/css/black-dashboard_report.css"),
CSS(settings.STATICFILES_DIRS[0] + "/css/font_awesome_all_5.15.3.css"),
],
) # , font_config=font_config)
return response
2024-04-05 13:00:17 +02:00
@login_required
@require_http_methods(["GET"])
def help_view(request):
""" Appel à la vue d'aide. """
return render(request, "help/help.html", {})