diff --git a/README.md b/README.md index 3f4e63f..ae0bfdf 100644 --- a/README.md +++ b/README.md @@ -23,8 +23,8 @@ services: - ./data:/var/lib/postgresql/data ``` - tapez la commande `docker-compose up -d` - - - pip install -r requirements.txt + - `pip install -r requirements.txt` + - `python manage.py runserver` ### Installation de weasyprint En plus du `pip install weasyprint` et `pip install django-weasyprint`, il faut installer weasyprint (via homebrew, …) puis, **pour les mac M1** exécuter les commandes : @@ -54,12 +54,14 @@ puis, **pour les mac M1** exécuter les commandes : heroku config:set ALLOWED_HOSTS="avengers-jarvis.herokuapp.com" heroku config:set SECRET_KEY="django-insecure-g_eoy6z%xshku4o5#k%o%i_%nb%_pz80config_#+t%f" heroku config:set DATABASE_NAME="ultron" - ``` - - - Push de l'application : `git push heroku master` + ``` - Se connecter à Héroku (via l'invite de commande) : `heroku login` + - Ajouter Heroku à Git : `git remote add heroku https://git.heroku.com/flying-ultron.git` + + - Push de l'application : `git push heroku master` + - Création du super user : `heroku run python manage.py createsuperuser` diff --git a/jarvis/followup/models.py b/jarvis/followup/models.py index d35eaaf..bf1bca1 100644 --- a/jarvis/followup/models.py +++ b/jarvis/followup/models.py @@ -101,12 +101,7 @@ class Chrono(Seasonisable): updated_at = models.DateTimeField(auto_now=True) def __str__(self): - return "%s - %s (%s - %s)" % ( - self.gymnast, - self.score, - self.date, - self.chrono_type, - ) + return f"{self.gymnast} - {self.score} ({self.date} - {self.chrono_type})" def timeline_representation(self): return f"
Bonjour,
-Un nouveau chrono enregistré pour {gymnast}.
Excellente journée
Jarvis
""", - ) + 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"""Bonjour,
+Un nouveau chrono enregistré pour {gymnast}.
Excellente journée
Jarvis
""", + ) return HttpResponseRedirect( reverse("gymnast_details_tab", args=(new_chrono.gymnast.id, "scores")) @@ -627,23 +628,24 @@ def learnedskill_create_or_update(request, gymnast_id=None): form.save() # notification + receiver = [] gymnast = Gymnast.objects.get(pk=form.cleaned_data["gymnast"].id) functionality = ContentType.objects.get(model="learnedskill") for notification in gymnast.notifications.filter( functionality=functionality ): - send_mail( - f"{gymnast} : Nouveau skill appris", - f"Un nouveau skill a été appris par {gymnast}", - settings.EMAIL_HOST_USER, - [ - notification.user.email, - ], - fail_silently=False, - html_message=f"""Bonjour,
-Un nouveau skill () a été appris par {gymnast}.
Excellente journée
Jarvis
""", - ) + 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"""Bonjour,
+Un nouveau skill () a été appris par {gymnast}.
Excellente journée
Jarvis
""", + ) return HttpResponseRedirect( reverse("gymnast_details", args=(form.cleaned_data["gymnast"].id,)) @@ -683,23 +685,24 @@ def score_create_or_update(request, score_id=None, gymnast_id=None): form.save() # notification + receiver = [] gymnast = Gymnast.objects.get(pk=form.cleaned_data["gymnast"].id) functionality = ContentType.objects.get(model="point") for notification in gymnast.notifications.filter( functionality=functionality ): - send_mail( - f"{gymnast} : Nouveau score enregistré", - f"Un nouveau score a été enregistré pour {gymnast}", - settings.EMAIL_HOST_USER, - [ - notification.user.email, - ], - fail_silently=False, - html_message=f"""Bonjour,
-Un nouveau score a été enregistré pour {gymnast}.
Excellente journée
Jarvis
""", - ) + 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"""Bonjour,
+Un nouveau score a été enregistré pour {gymnast}.
Excellente journée
Jarvis
""", + ) if form.cleaned_data["add_to_chrono"]: new_chrono = Chrono( @@ -806,23 +809,24 @@ def accident_create_or_update(request, accident_id=None, gymnast_id=None): accident = form.save() # notification + receiver = [] gymnast = Gymnast.objects.get(pk=form.cleaned_data["gymnast"].id) functionality = ContentType.objects.get(model="accident") for notification in gymnast.notifications.filter( functionality=functionality ): - send_mail( - f"{gymnast} : Nouvel accident enregistré", - f"Un nouvel accident enregistré pour {gymnast}", - settings.EMAIL_HOST_USER, - [ - notification.user.email, - ], - fail_silently=False, - html_message=f"""Bonjour,
-Un nouvel accident enregistré pour {gymnast}.
Excellente journée
Jarvis
""", - ) + receiver.append(notification.user.email) + + send_mail( + f"{gymnast} : Nouvel accident enregistré", + f"Un nouvel accident enregistré pour {gymnast}", + settings.EMAIL_HOST_USER, + receiver, + fail_silently=False, + html_message=f"""Bonjour,
+Un nouvel accident enregistré pour {gymnast}.
Excellente journée
Jarvis
""", + ) return HttpResponseRedirect( reverse("accident_details", args=(accident.pk,)) @@ -891,23 +895,24 @@ def mindstate_create_or_update( mindstate = form.save() # notification + receiver = [] gymnast = Gymnast.objects.get(pk=form.cleaned_data["gymnast"].id) functionality = ContentType.objects.get(model="mindstate") for notification in gymnast.notifications.filter( functionality=functionality ): - send_mail( - f"{gymnast} : Nouvel état d'esprit enregistré", - f"Un nouvel état d'esprit enregistré pour {gymnast}", - settings.EMAIL_HOST_USER, - [ - notification.user.email, - ], - fail_silently=False, - html_message=f"""Bonjour,
-Un nouvel état d'esprit enregistré pour {gymnast}.
Excellente journée
Jarvis
""", - ) + receiver.append(notification.user.email) + + send_mail( + f"{gymnast} : Nouvel état d'esprit enregistré", + f"Un nouvel état d'esprit enregistré pour {gymnast}", + settings.EMAIL_HOST_USER, + receiver, + fail_silently=False, + html_message=f"""Bonjour,
+Un nouvel état d'esprit enregistré pour {gymnast}.
Excellente journée
Jarvis
""", + ) return HttpResponseRedirect( reverse("mindstate_details", args=(mindstate.pk,)) @@ -976,23 +981,24 @@ def heightweight_create_or_update(request, heightweight_id=None, gymnast_id=None form.save() # notification + receiver = [] gymnast = Gymnast.objects.get(pk=form.cleaned_data["gymnast"].id) functionality = ContentType.objects.get(model="heightweight") for notification in gymnast.notifications.filter( functionality=functionality ): - send_mail( - f"{gymnast} : Nouveau poids/taille enregistré", - f"Un nouveau poids/taille enregistré pour {gymnast}", - settings.EMAIL_HOST_USER, - [ - notification.user.email, - ], - fail_silently=False, - html_message=f"""Bonjour,
-Un nouveau poids/taille enregistré pour {gymnast}.
Excellente journée
Jarvis
""", - ) + receiver.append(notification.user.email) + + send_mail( + f"{gymnast} : Nouveau poids/taille enregistré", + f"Un nouveau poids/taille enregistré pour {gymnast}", + settings.EMAIL_HOST_USER, + receiver, + fail_silently=False, + html_message=f"""Bonjour,
+Un nouveau poids/taille enregistré pour {gymnast}.
Excellente journée
Jarvis
""", + ) return HttpResponseRedirect( reverse( @@ -1107,23 +1113,24 @@ def routinedone_create_or_update(request, routinedone_id=None, gymnast_id=None): form.save() # notification + receiver = [] gymnast = Gymnast.objects.get(pk=form.cleaned_data["gymnast"].id) functionality = ContentType.objects.get(model="numberofroutinedone") for notification in gymnast.notifications.filter( functionality=functionality ): - send_mail( - f"{gymnast} : Nouvelle série comptabilisée", - f"Nouvelle série comptabilisée pour {gymnast}", - settings.EMAIL_HOST_USER, - [ - notification.user.email, - ], - fail_silently=False, - html_message=f"""Bonjour,
-Nouvelle série comptabilisée pour {gymnast}.
Excellente journée
Jarvis
""", - ) + 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"""Bonjour,
+Nouvelle série comptabilisée pour {gymnast}.
Excellente journée
Jarvis
""", + ) return HttpResponseRedirect( reverse( @@ -1179,23 +1186,24 @@ def plan_create_or_update(request, plan_id=None, gymnast_id=None, skill_id=None) plan = form.save() # notification + receiver = [] gymnast = Gymnast.objects.get(pk=form.cleaned_data["gymnast"].id) functionality = ContentType.objects.get(model="plan") for notification in gymnast.notifications.filter( functionality=functionality ): - send_mail( - f"{gymnast} : Nouvelle série comptabilisée", - f"Nouvelle série comptabilisée pour {gymnast}", - settings.EMAIL_HOST_USER, - [ - notification.user.email, - ], - fail_silently=False, - html_message=f"""Bonjour,
-Nouvelle série comptabilisée pour {gymnast}.
Excellente journée
Jarvis
""", - ) + 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"""Bonjour,
+Nouvelle série comptabilisée pour {gymnast}.
Excellente journée
Jarvis
""", + ) return HttpResponseRedirect( reverse("gymnast_details", args=(form.cleaned_data["gymnast"].id,)) @@ -1270,23 +1278,24 @@ def intensity_create_or_update(request, intensity_id=None, gymnast_id=None): intensity = form.save() # notification + receiver = [] gymnast = Gymnast.objects.get(pk=form.cleaned_data["gymnast"].id) functionality = ContentType.objects.get(model="intensity") for notification in gymnast.notifications.filter( functionality=functionality ): - send_mail( - f"{gymnast} : Nouvelle intensité", - f"Une nouvelle note vous a été envoyée pour {gymnast}", - settings.EMAIL_HOST_USER, - [ - notification.user.email, - ], - fail_silently=False, - html_message=f"""Bonjour,
-Une nouvelle intensité a été encodée pour {gymnast}.
Excellente journée
Jarvis
""", - ) + receiver.append(notification.user.email) + + send_mail( + f"{gymnast} : Nouvelle intensité", + f"Une nouvelle note vous a été envoyée pour {gymnast}", + settings.EMAIL_HOST_USER, + receiver, + fail_silently=False, + html_message=f"""Bonjour,
+Une nouvelle intensité a été encodée pour {gymnast}.
Excellente journée
Jarvis
""", + ) return HttpResponseRedirect( reverse( @@ -1340,23 +1349,24 @@ def season_information_create_or_update( season_information = form.save() # notification + receiver = [] gymnast = Gymnast.objects.get(pk=form.cleaned_data["gymnast"].id) functionality = ContentType.objects.get(model="seasoninformation") for notification in gymnast.notifications.filter( functionality=functionality ): - send_mail( - f"{gymnast} : Nouvelle information de saison", - f"Une nouvelle information de saison enregistrée pour {gymnast}", - settings.EMAIL_HOST_USER, - [ - notification.user.email, - ], - fail_silently=False, - html_message=f"""Bonjour,
-Une nouvelle information de saison enregistrée pour {gymnast}.
Excellente journée
Jarvis
""", - ) + 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"""Bonjour,
+Une nouvelle information de saison enregistrée pour {gymnast}.
Excellente journée
Jarvis
""", + ) return HttpResponseRedirect( reverse( diff --git a/jarvis/location/models.py b/jarvis/location/models.py index 444b2e4..0ff452d 100644 --- a/jarvis/location/models.py +++ b/jarvis/location/models.py @@ -19,7 +19,7 @@ class Country(models.Model): isonum = models.PositiveSmallIntegerField() def __str__(self): - return "%s (%s)" % (self.name, self.iso2) + return f"{self.name} ({self.iso2})" class Place(models.Model): diff --git a/jarvis/objective/models.py b/jarvis/objective/models.py index 891c1e7..bf3b674 100644 --- a/jarvis/objective/models.py +++ b/jarvis/objective/models.py @@ -102,11 +102,7 @@ class Educative(Markdownizable): # is_competitive = models.BooleanField(default=False) def __str__(self): - return "%s (%s - %s)" % ( - self.long_label, - self.short_label, - self.difficulty, - ) + return f"{self.long_label} ({self.short_label} - {self.difficulty})" def breadcrumb(self, path=[]): """ @@ -149,12 +145,7 @@ class PrerequisiteClosure(models.Model): path = models.PositiveIntegerField() def __str__(self): - return "%s -> %s (%s|%s)" % ( - self.ancestor.long_label, - self.descendant.long_label, - self.level, - self.path, - ) + return f"{self.ancestor.long_label} -> {self.descendant.long_label} ({self.level}|{self.path})" class TouchPosition(models.Model): @@ -175,7 +166,7 @@ class TouchPosition(models.Model): is_default = models.BooleanField(verbose_name="Défault ?", default=False) def __str__(self): - return "%s" % (self.long_label) + return f"{self.long_label}" def get_default_position(): @@ -250,7 +241,7 @@ class Skill(Educative): # importance = models.PositiveSmallIntegerField(default = 1) def __str__(self): - return "%s (%s)" % (self.long_label, self.notation) + return f"{self.long_label} ({self.notation})" class Routine(Educative): @@ -270,7 +261,7 @@ class Routine(Educative): is_competitive = models.BooleanField(default=False) def __str__(self): - return "%s (%s)" % (self.long_label, self.short_label) + return f"{self.long_label} ({self.short_label})" def compute_informations(self): """Calcule les informations (rank, niveau, ages, …) d'une routine.""" @@ -418,11 +409,7 @@ class RoutineSkill(models.Model): rank = models.PositiveSmallIntegerField() def __str__(self): - return "%s - %s : %s" % ( - self.rank, - self.routine.short_label, - self.skill.short_label, - ) + return f"{self.rank} - {self.routine.short_label} : {self.skill.short_label}" def max_even_if_none(value_1, value_2): diff --git a/jarvis/people/models.py b/jarvis/people/models.py index 31e85c1..cfc062c 100644 --- a/jarvis/people/models.py +++ b/jarvis/people/models.py @@ -4,12 +4,9 @@ from django.contrib.auth import get_user_model from django.db.models import Count from django.db import models -User = get_user_model() - from datetime import date import pendulum -from jarvis.location.models import Club from jarvis.objective.models import Skill from jarvis.tools.models import Markdownizable from jarvis.objective.tools import ( @@ -19,6 +16,8 @@ from jarvis.objective.tools import ( compute_statistics_by_type, ) +User = get_user_model() + GENDER_CHOICES = ((0, "Male"), (1, "Female")) @@ -56,7 +55,7 @@ class Gymnast(Markdownizable): created_at = models.DateTimeField(auto_now_add=True) def __str__(self): - return "%s %s" % (self.first_name, self.last_name) + return f"{self.first_name} {self.last_name}" @property def next_birthday(self): diff --git a/jarvis/people/views.py b/jarvis/people/views.py index eb5d421..803edae 100644 --- a/jarvis/people/views.py +++ b/jarvis/people/views.py @@ -1,6 +1,7 @@ from django.contrib.auth.decorators import login_required from django.contrib.auth.models import Group from django.contrib.auth import get_user_model +from django.contrib.contenttypes.models import ContentType from django.db.models import ( Q, @@ -41,10 +42,7 @@ from jarvis.followup.models import ( NumberOfRoutineDone, ) -from jarvis.followup.models import ( - CATEGORY_CHOICES, - LEARNING_STEP_CHOICES, -) +from jarvis.followup.models import LEARNING_STEP_CHOICES from jarvis.tools.models import Season @@ -391,11 +389,19 @@ def link_routine_to_gymnast(request, gymnast_id=None): form.save() if not gymnast: gymnast = get_object_or_404(Gymnast, pk=form.cleaned_data["gymnast"]) + + receiver = [] + functionality = ContentType.objects.get(model="gymnasthasroutine") + for notification in gymnast.notifications.filter( + functionality=functionality + ): + receiver.append(notification.user.email) + send_mail( "Nouvelle série", "Une nouvelle série vous a été associée.", settings.EMAIL_HOST_USER, - [gymnast.user.email, gymnast.email_trainer], + [gymnast.user.email, gymnast.email_trainer].append(receiver), fail_silently=False, html_message="""Bonjour,
Une nouvelle série vous a été associée.