Compare commits

...

18 Commits

Author SHA1 Message Date
Gregory Trullemans 142c4969f4 Fix bug into email sending feature 2024-02-04 14:12:02 +01:00
Gregory Trullemans 5dce3830d0 Update SeasonInformations model and fix bug on SI create_or_update view 2024-02-04 12:15:01 +01:00
Gregory Trullemans 88fa233b7a Update intensity listing 2024-02-04 08:45:45 +01:00
Gregory Trullemans 5083a452a1 Update intensity listing 2024-02-04 08:43:02 +01:00
Gregory Trullemans 0239da245c Update listing title 2024-02-04 08:34:31 +01:00
Gregory Trullemans 8764fc98bb Update intensity listing 2024-02-04 08:00:13 +01:00
Gregory Trullemans f63225cad1 Update intensity listing 2024-02-04 07:45:45 +01:00
Gregory Trullemans ac05d69afd Fix command to compute intensity theorical data 2024-02-03 20:34:58 +01:00
Gregory Trullemans 13b749d1a9 Fix command to compute intensity theorical data 2024-02-03 20:20:49 +01:00
Gregory Trullemans 9ed7017474 Add command to compute intensity theorical data 2024-02-03 20:14:31 +01:00
Gregory Trullemans 9f1452a569 Bug fix in note form 2024-02-03 19:56:07 +01:00
Gregory Trullemans 6444125550 Update intensite form 2024-02-03 19:14:26 +01:00
Gregory Trullemans 871b7d4221 Update Intentisty email and listing 2024-02-03 18:51:57 +01:00
Gregory Trullemans d655b79fcc Update intensity list 2024-02-03 18:28:38 +01:00
Gregory Trullemans 46680bc5ff Update intensity list 2024-02-03 18:25:33 +01:00
Gregory Trullemans f1a69276bf Update redirection after intensity add 2024-02-03 18:19:39 +01:00
Gregory Trullemans d08291712e Update intensity listing 2024-02-03 17:47:03 +01:00
Gregory Trullemans 81bfbc93cb Update intensity listing 2024-02-03 17:44:40 +01:00
12 changed files with 177 additions and 68 deletions

View File

@ -0,0 +1,30 @@
"""This command manages Closure Tables implementation
It adds new levels and cleans links between Educatives.
This way, it's relatively easy to fetch an entire tree with just one tiny request.
"""
import pendulum
from django.core.management.base import BaseCommand
from jarvis.followup.models import Intensity
class Command(BaseCommand):
def handle(self, *args, **options):
today = pendulum.date(2024, 1, 31)
intensity_list = Intensity.objects.filter(date__lte=today)
count = 0
for intensity in intensity_list:
count += 1
intensity.theorical_time = intensity.time
intensity.difficulty_asked = intensity.difficulty
intensity.number_of_passes_asked = 21
intensity.quantity_of_skill_asked = intensity.quantity_of_skill
intensity.number_of_gymnast = 2
intensity.save()
print(f"Traitement de {count} intensité terminés")

View File

@ -0,0 +1,31 @@
# Generated by Django 4.2 on 2024-02-04 11:13
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("followup", "0062_intensity_difficulty_asked_and_more"),
]
operations = [
migrations.AlterField(
model_name="seasoninformation",
name="number_of_hours_per_week",
field=models.DecimalField(
decimal_places=1, max_digits=3, verbose_name="# Hours/w"
),
),
migrations.AlterField(
model_name="seasoninformation",
name="number_of_s_and_c_hours_per_week",
field=models.DecimalField(
blank=True,
decimal_places=1,
max_digits=3,
null=True,
verbose_name="# S&C hours/w",
),
),
]

View File

@ -758,18 +758,20 @@ class SeasonInformation(models.Model):
number_of_training_sessions_per_week = models.PositiveSmallIntegerField( number_of_training_sessions_per_week = models.PositiveSmallIntegerField(
verbose_name="# Training/w" verbose_name="# Training/w"
) )
number_of_hours_per_week = models.PositiveSmallIntegerField( number_of_hours_per_week = models.DecimalField(
verbose_name="# Hours/w" verbose_name="# Hours/w", max_digits=3, decimal_places=1
) )
number_of_s_and_c_sessions_per_week = models.PositiveSmallIntegerField( number_of_s_and_c_sessions_per_week = models.PositiveSmallIntegerField(
verbose_name="# S&C training/w", verbose_name="# S&C training/w",
blank=True, blank=True,
null=True, null=True,
) )
number_of_s_and_c_hours_per_week = models.PositiveSmallIntegerField( number_of_s_and_c_hours_per_week = models.DecimalField(
verbose_name="# S&C hours/w", verbose_name="# S&C hours/w",
blank=True, blank=True,
null=True, null=True,
max_digits=3,
decimal_places=1,
) )
category = models.PositiveSmallIntegerField( category = models.PositiveSmallIntegerField(
choices=CATEGORY_CHOICES_ARRAY, choices=CATEGORY_CHOICES_ARRAY,

View File

@ -5,7 +5,8 @@
<div class="card-header"> <div class="card-header">
<div class="row"> <div class="row">
<div class="col-8"> <div class="col-8">
<h4 class=""> Chronos listing {% if gymnast %}for <i><a href="{% url 'gymnast_details_tab' gymnast.id 'scores' %}">{{ gymnast }}</a></i>{% endif %} <h4 class="">
{% if gymnast %}for <i><a href="{% url 'gymnast_details_tab' gymnast.id 'scores' %}">{{ gymnast }}</a></i>'s{% endif %} chronos listing
</h4> </h4>
</div> </div>
<div class="col-1 ml-auto"> <div class="col-1 ml-auto">

View File

@ -7,7 +7,7 @@
<div class="card"> <div class="card">
<div class="card-header row"> <div class="card-header row">
<div class="col-10 pr-0"> <div class="col-10 pr-0">
<h4 class="">Height/Weight list {% if gymnast %}for <a href="{% url 'gymnast_details_tab' gymnast.id 'physiological' %}"><i>{{ gymnast }}</i></a>{% endif %}</h4> <h4 class="">{% if gymnast %}for <a href="{% url 'gymnast_details_tab' gymnast.id 'physiological' %}"><i>{{ gymnast }}</i></a>'s{% endif %} Height/Weight listing </h4>
</div> </div>
<div class="col-2 ml-auto pl-0"> <div class="col-2 ml-auto pl-0">
<div class="text-right"> <div class="text-right">

View File

@ -102,7 +102,7 @@
</div> </div>
<div class="form-group text-center"> <div class="form-group text-center">
<input type="submit" value="{% if note_id %}Save{% else %}Add{% endif %}" <input type="submit" value="{% if intensity_id %}Update{% else %}Add{% endif %}"
class="btn btn-warning" /> class="btn btn-warning" />
</div> </div>
</form> </form>

View File

@ -6,7 +6,7 @@
<div class="row"> <div class="row">
<div class="col-8"> <div class="col-8">
<h4 class=""> <h4 class="">
Intensity listing {% if gymnast %}for <i><a href="{% url 'gymnast_details_tab' gymnast.id 'routine' %}">{{ gymnast }}</a></i>{% endif %} {% if gymnast %}<i><a href="{% url 'gymnast_details_tab' gymnast.id 'routine' %}">{{ gymnast }}</a></i>'s{% endif %} intensity listing
</h4> </h4>
</div> </div>
<div class="col-1 ml-auto"> <div class="col-1 ml-auto">
@ -28,18 +28,21 @@
<tr> <tr>
<th style="width: 3%">&nbsp;</th> <th style="width: 3%">&nbsp;</th>
<th style="width: 8%" class="header">Date</th> <th style="width: 8%" class="header">Date</th>
{% if not gymnast %}
<th style="width: 18%" class="header text-left">Gymnast</th> <th style="width: 18%" class="header text-left">Gymnast</th>
{% endif %}
<th style="width: 7%" class="header text-center"># passes</th> <th style="width: 7%" class="header text-center">Time</th>
<th style="width: 6%" class="header text-center">Time</th> <th style="width: 7%" class="header text-center">Diff</th>
<th style="width: 6%" class="header text-center"># Skill</th> <th style="width: 7%" class="header text-center">Skill</th>
<th style="width: 6%" class="header text-center">Diff</th> <th style="width: 7%" class="header text-center">Passe</th>
<th style="width: 7%" class="header text-center">Quality</th>
<th style="width: 7%" class="header text-center">T/p</th><!-- Time by passe --> <th style="width: 7%" class="header text-center">T/p</th><!-- Time by passe -->
<th style="width: 7%" class="header text-center">D/p</th><!-- Difficulty by passe --> <th style="width: 7%" class="header text-center">D/p</th><!-- Difficulty by passe -->
<th style="width: 7%" class="header text-center">S/p</th><!-- # skill by passe --> <th style="width: 7%" class="header text-center">S/p</th><!-- # skill by passe -->
<th style="width: 7%" class="header text-center">D/S</th><!-- Difficulty by skill --> <th style="width: 7%" class="header text-center">D/S</th><!-- Difficulty by skill -->
<th style="width: 7%" class="header text-center">S/T</th><!-- Skill by time --> <!-- <th style="width: 7%" class="header text-center">S/T</th>Skill by time -->
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -51,18 +54,31 @@
</a> </a>
</td> </td>
<td><a href="{% url 'intensity_details' intensity.id %}">{{ intensity.date | date:"d-m-Y" }}</a></td> <td><a href="{% url 'intensity_details' intensity.id %}">{{ intensity.date | date:"d-m-Y" }}</a></td>
{% if not gymnast %}
<td class="text-left"> <td class="text-left">
<a href="{% url 'gymnast_details_tab' intensity.gymnast.id 'routine' %}"> <a href="{% url 'gymnast_details_tab' intensity.gymnast.id 'routine' %}">
{{ intensity.gymnast }} {{ intensity.gymnast }}
</a> </a>
</td> </td>
{% endif %}
<td class="text-right">{{ intensity.number_of_passes }}</td> <td class="text-center">{{ intensity.time_quality | floatformat:0 }}</td>
<td class="text-right">{{ intensity.time }}</td> <td class="text-center">{{ intensity.difficulty_quality | floatformat:0 }}</td>
<td class="text-right">{{ intensity.quantity_of_skill }}</td> <td class="text-center">{{ intensity.quantity_of_skill_quality | floatformat:0 }}</td>
<td class="text-right">{{ intensity.difficulty_in_unit }}</td> <td class="text-center">{{ intensity.number_of_passes_quality | floatformat:0 }}</td>
<td class="text-center">
<b>
{% if intensity.average_quality < 85.0 %}
<span class="text-danger">{{ intensity.average_quality | floatformat:1 }}%</span>
{% elif intensity.average_quality < 95.0 %}
<span class="text-warning">{{ intensity.average_quality | floatformat:1 }}%</span>
{% else %}
<span class="text-success">{{ intensity.average_quality | floatformat:1 }}%</span>
{% endif %}
</b>
</td>
<td class="text-right"><!-- Time by passe --> <td class="text-center"><!-- Time by passe -->
<b> <b>
{% if intensity.number_of_gymnast == 2 %} {% if intensity.number_of_gymnast == 2 %}
{% if intensity.mean_time_by_passe > 3.50 %} {% if intensity.mean_time_by_passe > 3.50 %}
@ -85,18 +101,26 @@
{% endif %} {% endif %}
</b> </b>
</td> </td>
<td class="text-right">{{ intensity.mean_difficulty_by_passe_in_unit | floatformat:2 }}</td><!-- Difficulty by passe --> <!-- Difficulty by passe -->
<td class="text-right"><!-- # skill by passe --> <td class="text-center">
{{ intensity.mean_difficulty_by_passe_in_unit | floatformat:2 }}
</td>
<!-- # skill by passe -->
<td class="text-center">
<b> <b>
{{ intensity.mean_quantity_of_skill_by_passe | floatformat:2 }} {{ intensity.mean_quantity_of_skill_by_passe | floatformat:2 }}
</b> </b>
</td> </td>
<td class="text-right">{{ intensity.mean_difficulty_by_skill_in_unit | floatformat:2 }}</td><!-- Difficulty by skill --> <!-- Difficulty by skill -->
<td class="text-right"><!-- Skill by time --> <td class="text-center">
{{ intensity.mean_difficulty_by_skill_in_unit | floatformat:2 }}
</td>
<!-- Skill by time -->
<!-- <td class="text-right">
<b> <b>
{{ intensity.mean_quantity_of_skill_by_time | floatformat:2 }} {{ intensity.mean_quantity_of_skill_by_time | floatformat:2 }}
</b> </b>
</td> </td> -->
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>

View File

@ -5,7 +5,9 @@
<div class="card-header"> <div class="card-header">
<div class="row"> <div class="row">
<div class="col-8"> <div class="col-8">
<h4 class=""> Notes listing {% if gymnast %}for <i>{{ gymnast }}</i>{% endif %}</h4> <h4 class="">
{% if gymnast %}<i><a href="#">{{ gymnast }}</a></i>'s{% endif %} notes listing
</h4>
</div> </div>
<div class="col-1 ml-auto"> <div class="col-1 ml-auto">
<div class="text-right"> <div class="text-right">

View File

@ -7,7 +7,9 @@
<div class="card"> <div class="card">
<div class="card-header row"> <div class="card-header row">
<div class="col-8"> <div class="col-8">
<h4 class="">Routine done list {% if gymnast %}for <a href="{% url 'gymnast_details_tab' gymnast.id 'routine' %}"><i>{{ gymnast }}</i></a>{% endif %}</h4> <h4 class="">
{% if gymnast %}for <a href="{% url 'gymnast_details_tab' gymnast.id 'routine' %}"><i>{{ gymnast }}</i></a>'s {% endif %} routine done listing
</h4>
</div> </div>
<div class="col-1 ml-auto"> <div class="col-1 ml-auto">
<div class="text-right"> <div class="text-right">

View File

@ -7,7 +7,9 @@
<div class="card"> <div class="card">
<div class="card-header row"> <div class="card-header row">
<div class="col-8"> <div class="col-8">
<h4 class="">Scores listing {% if gymnast %}for <a href="{% url 'gymnast_details_tab' gymnast.id 'scores' %}"><i>{{ gymnast }}</i></a>{% endif %}</h4> <h4 class="">
{% if gymnast %}for <a href="{% url 'gymnast_details_tab' gymnast.id 'scores' %}"><i>{{ gymnast }}</i></a>'s {% endif %} Scores listing
</h4>
</div> </div>
<div class="col-1 ml-auto"> <div class="col-1 ml-auto">
<div class="text-right"> <div class="text-right">

View File

@ -7,7 +7,9 @@
<div class="card"> <div class="card">
<div class="card-header row"> <div class="card-header row">
<div class="col-10 pr-0"> <div class="col-10 pr-0">
<h4 class="">Well being list {% if gymnast %}for <a href="{% url 'gymnast_details_tab' gymnast.id 'physiological' %}"><i>{{ gymnast }}</i></a>{% endif %}</h4> <h4 class="">
{% if gymnast %}for <a href="{% url 'gymnast_details_tab' gymnast.id 'physiological' %}"><i>{{ gymnast }}</i></a>'s {% endif %} Well being list
</h4>
</div> </div>
<div class="col-2 ml-auto pl-0"> <div class="col-2 ml-auto pl-0">
<div class="text-right"> <div class="text-right">

View File

@ -558,17 +558,20 @@ def note_create_or_update(request, note_id=None, gymnast_id=None):
url = request.build_absolute_uri( url = request.build_absolute_uri(
reverse("gymnast_details_tab", args=(new_note.gymnast.id, "event")) reverse("gymnast_details_tab", args=(new_note.gymnast.id, "event"))
) )
# content = (form.cleaned_data["informations"]) receivers = [
new_note.gymnast.user.email,
new_note.gymnast.email_trainer,
]
title = f"{new_note.gymnast} : Nouvelle note"
body = f"""<p>Bonjour,</p><p>Une nouvelle note vous a été envoyée. Vous pouvez la consulter en cliquant <a href='{url}'>ici</a>.</p>"""
send_mail( send_mail(
"Nouvelle note", title,
"Une nouvelle note vous a été envoyée", "Une nouvelle note vous a été envoyée",
settings.EMAIL_HOST_USER, settings.EMAIL_HOST_USER,
[new_note.gymnast.user.email, new_note.gymnast.email_trainer], receivers,
fail_silently=False, fail_silently=False,
html_message=f"""<p>Bonjour,</p> html_message=body + MAIL_FOOTER,
<p>Une nouvelle note vous a été envoyée. Vous pouvez la consulter en cliquant <a href='{url}'>ici</a>.</p>
{MAIL_FOOTER}""",
) )
return HttpResponseRedirect( return HttpResponseRedirect(
reverse("gymnast_details_tab", args=(new_note.gymnast.id, "event")) reverse("gymnast_details_tab", args=(new_note.gymnast.id, "event"))
@ -632,12 +635,12 @@ def chrono_create_or_update(request, chrono_id=None, gymnast_id=None):
receivers.append(notification.user.email) receivers.append(notification.user.email)
title = f"{new_chrono.gymnast} : Nouveau chrono" title = f"{new_chrono.gymnast} : Nouveau chrono"
html_message = f"""<p>Bonjour,</p><p>Nouveau chrono pour {new_chrono.gymnast} : {SCORE_TYPE_CHOICE[new_chrono.score_type][1]} {CHRONO_TYPE_CHOICE[new_chrono.chrono_type][1]} - {new_chrono.score}.</p>""" body = f"""<p>Bonjour,</p><p>Nouveau chrono pour {new_chrono.gymnast} : {SCORE_TYPE_CHOICE[new_chrono.score_type][1]} {CHRONO_TYPE_CHOICE[new_chrono.chrono_type][1]} - {new_chrono.score}.</p>"""
Email.objects.create( Email.objects.create(
receivers=receivers, receivers=receivers,
title=title, title=title,
body=html_message, body=body,
) )
send_mail( send_mail(
@ -646,7 +649,7 @@ def chrono_create_or_update(request, chrono_id=None, gymnast_id=None):
settings.EMAIL_HOST_USER, settings.EMAIL_HOST_USER,
receivers, receivers,
fail_silently=False, fail_silently=False,
html_message=html_message + MAIL_FOOTER, html_message=body + MAIL_FOOTER,
) )
return HttpResponseRedirect( return HttpResponseRedirect(
@ -1156,7 +1159,7 @@ def heightweight_create_or_update(request, heightweight_id=None, gymnast_id=None
settings.EMAIL_HOST_USER, settings.EMAIL_HOST_USER,
receivers, receivers,
fail_silently=False, fail_silently=False,
html_message=body + {MAIL_FOOTER}, html_message=body + MAIL_FOOTER,
) )
return HttpResponseRedirect( return HttpResponseRedirect(
@ -1299,7 +1302,7 @@ def routinedone_create_or_update(request, routinedone_id=None, gymnast_id=None):
settings.EMAIL_HOST_USER, settings.EMAIL_HOST_USER,
receivers, receivers,
fail_silently=False, fail_silently=False,
html_message=body + {MAIL_FOOTER}, html_message=body + MAIL_FOOTER,
) )
return HttpResponseRedirect( return HttpResponseRedirect(
@ -1376,7 +1379,7 @@ def plan_create_or_update(request, plan_id=None, gymnast_id=None, skill_id=None)
settings.EMAIL_HOST_USER, settings.EMAIL_HOST_USER,
receivers, receivers,
fail_silently=False, fail_silently=False,
html_message=body + {MAIL_FOOTER}, html_message=body + MAIL_FOOTER,
) )
return HttpResponseRedirect( return HttpResponseRedirect(
@ -1473,8 +1476,8 @@ def intensity_create_or_update(request, intensity_id=None, gymnast_id=None):
): ):
receivers.append(notification.user.email) receivers.append(notification.user.email)
html_message = f"""<p>Bonjour,</p> title = f"{intensity.gymnast} : Nouvelle intensité"
<p>{intensity.gymnast} a encodé une nouvelle intensité pour le {date.strftime('%d %B %Y')}:</p> body = f"""<p>Bonjour,</p><p>{intensity.gymnast} a encodé une nouvelle intensité pour le {date.strftime('%d %B %Y')}:</p>
<ul> <ul>
<li>{intensity.number_of_passes} passages</li> <li>{intensity.number_of_passes} passages</li>
<li>{intensity.time} minutes</li> <li>{intensity.time} minutes</li>
@ -1483,10 +1486,11 @@ def intensity_create_or_update(request, intensity_id=None, gymnast_id=None):
</ul> </ul>
<p><u>Quality:</u></p> <p><u>Quality:</u></p>
<ul> <ul>
<li>Time: {intensity.time_quality:.2f}%</li> <li>Time: {intensity.time_quality:.1f}%</li>
<li>Diff: {intensity.difficulty_quality:.2f}%</li> <li>Diff: {intensity.difficulty_quality:.1f}%</li>
<li>Skill: {intensity.quantity_of_skill_quality:.2f}%</li> <li>Skill: {intensity.quantity_of_skill_quality:.1f}%</li>
<li>Passe: {intensity.number_of_passes_quality:.2f}%</li> <li>Passe: {intensity.number_of_passes_quality:.1f}%</li>
<li><b>Passe: {intensity.average_quality:.2f}%</b></li>
</ul> </ul>
<p><u>Statistics:</u></p> <p><u>Statistics:</u></p>
<ul> <ul>
@ -1496,17 +1500,26 @@ def intensity_create_or_update(request, intensity_id=None, gymnast_id=None):
<li>Diff/passe: {intensity.mean_difficulty_by_passe:.2f}</li> <li>Diff/passe: {intensity.mean_difficulty_by_passe:.2f}</li>
<li>Diff/skill: {intensity.mean_difficulty_by_skill:.2f}</li> <li>Diff/skill: {intensity.mean_difficulty_by_skill:.2f}</li>
</ul>""" </ul>"""
Email.objects.create( Email.objects.create(
receivers=receivers, receivers=receivers,
title=f"{intensity.gymnast} : Nouvelle intensité", title=title,
body=html_message, body=body,
# model_name="Intensity" )
send_mail(
title,
f"Une nouvelle information de saison enregistrée pour {intensity.gymnast}",
settings.EMAIL_HOST_USER,
receivers,
fail_silently=False,
html_message=body + MAIL_FOOTER,
) )
return HttpResponseRedirect( return HttpResponseRedirect(
reverse( reverse(
"gymnast_details_tab", "intensity_details",
args=(form.cleaned_data["gymnast"].id, "routine"), args=(intensity.id,),
) )
) )
@ -1564,7 +1577,7 @@ def season_information_create_or_update(
title = f"{season_information.gymnast} : Nouvelle information de saison" title = f"{season_information.gymnast} : Nouvelle information de saison"
body = f"""<p>Bonjour,</p> body = f"""<p>Bonjour,</p>
<p>Une nouvelle information de saison enregistrée pour {gymnast}.</p>""" <p>Une nouvelle information de saison enregistrée pour {season_information.gymnast}.</p>"""
Email.objects.create(receivers=receivers, title=title, body=body) Email.objects.create(receivers=receivers, title=title, body=body)
@ -1574,7 +1587,7 @@ def season_information_create_or_update(
settings.EMAIL_HOST_USER, settings.EMAIL_HOST_USER,
receivers, receivers,
fail_silently=False, fail_silently=False,
html_message=body + {MAIL_FOOTER}, html_message=body + MAIL_FOOTER,
) )
return HttpResponseRedirect( return HttpResponseRedirect(