2023-04-25 17:06:14 +02:00
|
|
|
from datetime import timedelta
|
|
|
|
|
2023-05-22 08:53:55 +02:00
|
|
|
from django.db.models import Q, F, OuterRef, Subquery
|
2023-04-25 17:06:14 +02:00
|
|
|
from django.shortcuts import render
|
|
|
|
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
|
|
|
|
|
|
|
|
from jarvis.objective.models import Routine
|
|
|
|
from jarvis.profiles.models import Profile
|
|
|
|
from jarvis.followup.models import Skill, Point, Chrono
|
|
|
|
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 django.db.models import Max
|
|
|
|
from django.conf import settings
|
|
|
|
from .models import Citation
|
|
|
|
from jarvis.tools.models import from_date_to_week_number
|
|
|
|
|
|
|
|
from weasyprint import HTML, CSS
|
|
|
|
import pendulum
|
|
|
|
|
|
|
|
|
|
|
|
def login(request):
|
|
|
|
"""
|
|
|
|
Formulaire d'authentifictation.
|
|
|
|
"""
|
|
|
|
|
|
|
|
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)
|
|
|
|
try:
|
|
|
|
profile = Profile.objects.get(user=user)
|
|
|
|
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
|
|
|
|
except Exception:
|
|
|
|
pass
|
|
|
|
# request.session["clubid"] = request.POST.get("clubid", None)
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
|
# @lru_cache()
|
|
|
|
# def get_last_updated_gymnasts(expiration_date):
|
|
|
|
# ...
|
|
|
|
|
|
|
|
|
|
|
|
@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-07-03 13:09:24 +02:00
|
|
|
event_list = Event.objects.filter(date_begin__gte=today).order_by("date_begin")[:10]
|
2023-04-25 17:06:14 +02:00
|
|
|
|
|
|
|
quote = Citation.objects.order_by("?").first()
|
|
|
|
|
2023-06-22 13:14:56 +02:00
|
|
|
# A METTRE EN CACHE.
|
|
|
|
# last_updated_gymnast = None
|
2023-07-03 13:38:31 +02:00
|
|
|
last_updated_gymnasts = set()
|
|
|
|
last_updated_gymnasts.update(
|
|
|
|
Gymnast.objects.filter(mindstate__created_at__gt=request.user.last_login)
|
|
|
|
)
|
|
|
|
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(accident__created_at__gt=request.user.last_login)
|
|
|
|
)
|
|
|
|
last_updated_gymnasts.update(
|
|
|
|
Gymnast.objects.filter(known_skills__created_at__gt=request.user.last_login)
|
|
|
|
)
|
2023-04-25 17:06:14 +02:00
|
|
|
|
2023-07-03 13:09:24 +02:00
|
|
|
limit_date = today - timedelta(days=14)
|
2023-04-25 17:06:14 +02:00
|
|
|
waiting_update_gymnast = Gymnast.objects.exclude(
|
|
|
|
Q(is_active=False)
|
|
|
|
| Q(mindstate__created_at__gte=limit_date)
|
|
|
|
| Q(points__created_at__gte=limit_date)
|
|
|
|
| Q(chronos__created_at__gte=limit_date)
|
|
|
|
| Q(accident__created_at__gte=limit_date)
|
|
|
|
| Q(known_skills__created_at__gte=limit_date)
|
|
|
|
).distinct()
|
|
|
|
|
|
|
|
nb_active_gymnast = Gymnast.objects.filter(is_active=True).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 = int(
|
|
|
|
# (get_number_of_weeks_between(datetime(2021, 9, 1), datetime.now()) / 52) * 100
|
|
|
|
# )
|
|
|
|
|
|
|
|
percentage_week = (week_number / 52) * 100
|
|
|
|
|
|
|
|
birthday_list = next_birthdays(request, 10)
|
|
|
|
|
2023-06-22 13:14:56 +02:00
|
|
|
# # 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.
|
2023-04-25 17:06:14 +02:00
|
|
|
|
2023-06-22 13:14:56 +02:00
|
|
|
# # 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
|
|
|
|
|
|
|
context = {
|
|
|
|
"quote": quote,
|
2023-06-22 13:14:56 +02:00
|
|
|
"week_number": week_number,
|
2023-04-25 17:06:14 +02:00
|
|
|
"event_list": event_list,
|
2023-07-03 13:38:31 +02:00
|
|
|
"last_updated_gymnasts": last_updated_gymnasts,
|
2023-04-25 17:06:14 +02:00
|
|
|
"waiting_update_gymnast": waiting_update_gymnast,
|
|
|
|
"nb_active_gymnast": nb_active_gymnast,
|
|
|
|
"nb_event": nb_event,
|
|
|
|
"nb_skill": nb_skill,
|
|
|
|
"nb_routine": nb_routine,
|
|
|
|
"nb_score": nb_score,
|
|
|
|
"nb_club": nb_club,
|
|
|
|
"percentage_week": percentage_week,
|
|
|
|
"birthday_list": birthday_list,
|
|
|
|
}
|
|
|
|
return render(request, "dashboard/dashboard.html", context)
|
2023-06-22 13:14:56 +02:00
|
|
|
# return render(request, "dashboard/dashboard.html", {})
|
2023-04-25 17:06:14 +02:00
|
|
|
|
|
|
|
|
|
|
|
@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:
|
|
|
|
gymnast_list = Gymnast.objects.filter(
|
|
|
|
Q(last_name__icontains=pattern) | Q(first_name__icontains=pattern)
|
|
|
|
)
|
|
|
|
|
|
|
|
if gymnast_list.count() == 1:
|
|
|
|
gymnast = gymnast_list.first()
|
|
|
|
return gymnast_details(request, gymnast.id)
|
|
|
|
else:
|
|
|
|
skill_list = Skill.objects.filter(
|
|
|
|
Q(long_label__icontains=pattern) | Q(short_label__icontains=pattern)
|
|
|
|
)
|
|
|
|
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)
|
|
|
|
|
|
|
|
|
2023-05-20 19:33:47 +02:00
|
|
|
def report_listing(request):
|
|
|
|
"""Liste des rapports disponibles"""
|
|
|
|
context = {}
|
|
|
|
return render(request, "reports/list.html", context)
|
|
|
|
|
|
|
|
|
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=[
|
|
|
|
CSS(settings.STATICFILES_DIRS[0] + "/css/gymnast_report.css"),
|
|
|
|
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
|