diff --git a/.pylintrc b/.pylintrc
index 8b45ce1..1c8bf0a 100644
--- a/.pylintrc
+++ b/.pylintrc
@@ -232,7 +232,7 @@ single-line-if-stmt=no
[VARIABLES]
-django-settings-module=khana.settings
+django-settings-module=config.settings
# List of additional names supposed to be defined in builtins. Remember that
# you should avoid defining new builtins when possible.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..1e88b0d
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,14 @@
+# Makefile for khana
+
+ifeq ($(shell which coverage >/dev/null 2>&1; echo $$?), 1)
+ $(error The 'coverage' command was not found. Make sure you have coverage installed)
+endif
+
+.PHONY: help coverage
+
+help:
+ @echo " coverage to run coverage check of the source files."
+
+coverage:
+ coverage run --source='.' manage.py test; coverage report; coverage html;
+ @echo "Testing of coverage in the sources finished."
diff --git a/src/base/__init__.py b/config/__init__.py
similarity index 100%
rename from src/base/__init__.py
rename to config/__init__.py
diff --git a/src/khana/settings.py b/config/settings.py
similarity index 84%
rename from src/khana/settings.py
rename to config/settings.py
index 32f882a..1beedde 100644
--- a/src/khana/settings.py
+++ b/config/settings.py
@@ -16,19 +16,17 @@ import environ
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
-env = environ.Env(
- DEBUG=(bool, False)
-)
+env = environ.Env(DEBUG=(bool, False))
environ.Env.read_env()
-DEBUG = env('DEBUG', default=True)
+DEBUG = env("DEBUG", default=True)
-SECRET_KEY = env('SECRET_KEY', default="6@9p0g-5ebcttbt$^*s4rda5!piezt6b7wj35g(+$mgz52k#d=")
+SECRET_KEY = env(
+ "SECRET_KEY", default="6@9p0g-5ebcttbt$^*s4rda5!piezt6b7wj35g(+$mgz52k#d="
+)
-DATABASES = {
- 'default': env.db('DATABASE_URL', default='sqlite:///db.sqlite3')
-}
+DATABASES = {"default": env.db("DATABASE_URL", default="sqlite:///db.sqlite3")}
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/
@@ -45,14 +43,14 @@ INSTALLED_APPS = (
"django.contrib.messages",
"django.contrib.staticfiles",
"django_extensions",
- "people",
- "location",
- "planning",
- "objective",
- "competition",
- "profile",
- "tools",
- "communication",
+ "khana.people",
+ "khana.location",
+ "khana.planning",
+ "khana.objective",
+ "khana.competition",
+ "khana.profile",
+ "khana.tools",
+ "khana.communication",
"rest_framework",
)
@@ -66,7 +64,7 @@ MIDDLEWARE = [
#'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
-ROOT_URLCONF = "khana.urls"
+ROOT_URLCONF = "config.urls"
TEMPLATES = [
{
@@ -122,4 +120,4 @@ DEBUG_TOOLBAR_CONFIG = {
"JQUERY_URL": STATIC_URL + "js/jquery-2.1.4.min.js",
}
-DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
+DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
diff --git a/src/khana/urls.py b/config/urls.py
similarity index 100%
rename from src/khana/urls.py
rename to config/urls.py
diff --git a/src/khana/views.py b/config/views.py
similarity index 98%
rename from src/khana/views.py
rename to config/views.py
index 4c1e062..2bc423b 100644
--- a/src/khana/views.py
+++ b/config/views.py
@@ -246,7 +246,8 @@ def search(request):
name__icontains=pattern
) # ou gymnaste qui y participe !
gymnast_list = Gymnast.objects.filter(
- Q(user__last_name__icontains=pattern) | Q(user__first_name__icontains=pattern)
+ Q(user__last_name__icontains=pattern)
+ | Q(user__first_name__icontains=pattern)
)
accident_list = Accident.objects.filter(
Q(gymnast__user__last_name__icontains=pattern)
diff --git a/src/khana/wsgi.py b/config/wsgi.py
similarity index 100%
rename from src/khana/wsgi.py
rename to config/wsgi.py
diff --git a/src/fixtures/initial_data.json b/fixtures/initial_data.json
similarity index 100%
rename from src/fixtures/initial_data.json
rename to fixtures/initial_data.json
diff --git a/src/communication/__init__.py b/khana/__init__.py
similarity index 100%
rename from src/communication/__init__.py
rename to khana/__init__.py
diff --git a/src/communication/migrations/__init__.py b/khana/base/__init__.py
similarity index 100%
rename from src/communication/migrations/__init__.py
rename to khana/base/__init__.py
diff --git a/src/base/models.py b/khana/base/models.py
similarity index 100%
rename from src/base/models.py
rename to khana/base/models.py
diff --git a/src/base/tests.py b/khana/base/tests.py
similarity index 100%
rename from src/base/tests.py
rename to khana/base/tests.py
diff --git a/src/competition/__init__.py b/khana/communication/__init__.py
similarity index 100%
rename from src/competition/__init__.py
rename to khana/communication/__init__.py
diff --git a/src/communication/admin.py b/khana/communication/admin.py
similarity index 99%
rename from src/communication/admin.py
rename to khana/communication/admin.py
index 888a2eb..17d2191 100644
--- a/src/communication/admin.py
+++ b/khana/communication/admin.py
@@ -9,6 +9,7 @@ from .models import Message
class MessageAdmin(admin.ModelAdmin):
"""La classe `MessageAdmin` contrôle la gestion des messages
"""
+
list_display = ("sender", "recipient", "written_at", "is_read", "read_at")
ordering = ("written_at", "sender")
search_fields = ("sender", "recipient", "message_title")
diff --git a/src/communication/apps.py b/khana/communication/apps.py
similarity index 69%
rename from src/communication/apps.py
rename to khana/communication/apps.py
index bcfabf0..9575409 100644
--- a/src/communication/apps.py
+++ b/khana/communication/apps.py
@@ -2,4 +2,4 @@ from django.apps import AppConfig
class CommunicationConfig(AppConfig):
- name = "communication"
+ name = "khana.communication"
diff --git a/src/communication/forms.py b/khana/communication/forms.py
similarity index 99%
rename from src/communication/forms.py
rename to khana/communication/forms.py
index 4465aef..a183e6a 100644
--- a/src/communication/forms.py
+++ b/khana/communication/forms.py
@@ -8,6 +8,7 @@ from .models import Message
class MessageForm(forms.ModelForm):
"""Formulaire de base pour la création et la modification de messages
"""
+
class Meta:
model = Message
fields = (
diff --git a/src/communication/migrations/0001_initial.py b/khana/communication/migrations/0001_initial.py
similarity index 100%
rename from src/communication/migrations/0001_initial.py
rename to khana/communication/migrations/0001_initial.py
diff --git a/src/communication/migrations/0002_auto_20190413_1028.py b/khana/communication/migrations/0002_auto_20190413_1028.py
similarity index 100%
rename from src/communication/migrations/0002_auto_20190413_1028.py
rename to khana/communication/migrations/0002_auto_20190413_1028.py
diff --git a/khana/communication/migrations/0003_auto_20210513_1058.py b/khana/communication/migrations/0003_auto_20210513_1058.py
new file mode 100644
index 0000000..93db0a3
--- /dev/null
+++ b/khana/communication/migrations/0003_auto_20210513_1058.py
@@ -0,0 +1,63 @@
+# Generated by Django 3.2.2 on 2021-05-13 10:58
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ("communication", "0002_auto_20190413_1028"),
+ ]
+
+ operations = [
+ migrations.RenameField(
+ model_name="message", old_name="message_body", new_name="body",
+ ),
+ migrations.RenameField(
+ model_name="message", old_name="date_of_reading", new_name="read_at",
+ ),
+ migrations.RenameField(
+ model_name="message", old_name="message_title", new_name="title",
+ ),
+ migrations.RenameField(
+ model_name="message", old_name="date_of_writing", new_name="written_at",
+ ),
+ migrations.RemoveField(model_name="message", name="is_read",),
+ migrations.RemoveField(model_name="message", name="reader",),
+ migrations.RemoveField(model_name="message", name="writer",),
+ migrations.AddField(
+ model_name="message",
+ name="content",
+ field=models.TextField(
+ blank=True,
+ help_text="Seul le MarkDown simple est accepté",
+ null=True,
+ verbose_name="Comments",
+ ),
+ ),
+ migrations.AddField(
+ model_name="message",
+ name="recipient",
+ field=models.ForeignKey(
+ default=1,
+ on_delete=django.db.models.deletion.CASCADE,
+ related_name="received_messages",
+ to="auth.user",
+ ),
+ preserve_default=False,
+ ),
+ migrations.AddField(
+ model_name="message",
+ name="sender",
+ field=models.ForeignKey(
+ default=1,
+ on_delete=django.db.models.deletion.CASCADE,
+ related_name="sent_messages",
+ to="auth.user",
+ ),
+ preserve_default=False,
+ ),
+ ]
diff --git a/src/competition/migrations/__init__.py b/khana/communication/migrations/__init__.py
similarity index 100%
rename from src/competition/migrations/__init__.py
rename to khana/communication/migrations/__init__.py
diff --git a/src/communication/models.py b/khana/communication/models.py
similarity index 79%
rename from src/communication/models.py
rename to khana/communication/models.py
index b449b12..3c25def 100644
--- a/src/communication/models.py
+++ b/khana/communication/models.py
@@ -12,7 +12,7 @@ from datetime import datetime
from django.db import models
from django.contrib.auth import get_user_model
-from base.models import Markdownizable
+from khana.base.models import Markdownizable
User = get_user_model()
@@ -33,13 +33,11 @@ class Message(Markdownizable):
sender = models.ForeignKey(
User, on_delete=models.CASCADE, related_name="sent_messages"
)
- written_at = models.DateTimeField(
- auto_now_add=True, verbose_name="Date of writing"
- )
- recipient = models.ForeignKey(User, on_delete=models.CASCADE, related_name="received_messages")
- read_at = models.DateTimeField(
- auto_now=True, verbose_name="Date of reading"
+ written_at = models.DateTimeField(auto_now_add=True, verbose_name="Date of writing")
+ recipient = models.ForeignKey(
+ User, on_delete=models.CASCADE, related_name="received_messages"
)
+ read_at = models.DateTimeField(auto_now=True, verbose_name="Date of reading")
title = models.CharField(max_length=255, verbose_name="Title")
body = models.TextField(null=True, blank=True, verbose_name="Message")
diff --git a/src/communication/tests_models.py b/khana/communication/tests_models.py
similarity index 88%
rename from src/communication/tests_models.py
rename to khana/communication/tests_models.py
index 254da67..1d44243 100644
--- a/src/communication/tests_models.py
+++ b/khana/communication/tests_models.py
@@ -14,6 +14,6 @@ def test_message_to_string():
"""Vérifie la représentation textuelle d'un message
"""
timing = datetime.now()
- user = User(username='fred', password='fredpassword')
+ user = User(username="fred", password="fredpassword")
message = Message(sender=user, written_at=timing, title="test")
assert str(message) == "fred - " + str(timing) + " : test"
diff --git a/src/communication/urls.py b/khana/communication/urls.py
similarity index 100%
rename from src/communication/urls.py
rename to khana/communication/urls.py
diff --git a/khana/communication/views.py b/khana/communication/views.py
new file mode 100644
index 0000000..5189119
--- /dev/null
+++ b/khana/communication/views.py
@@ -0,0 +1,92 @@
+"""Vues et fonctions pour tout ce qui touche à la communication entre plusieurs utilisateurs."""
+
+from datetime import datetime
+
+from django.contrib.auth.decorators import login_required
+from django.http import HttpResponse, HttpResponseRedirect
+from django.shortcuts import render, get_object_or_404
+from django.views.decorators.http import require_http_methods
+from django.urls import reverse
+
+from .forms import MessageForm
+from .models import Message
+
+
+@login_required
+def get_number_of_unread_message(request):
+ """Récupère le nombre de messages non lus associés à l'utilisateur en session.
+ """
+ return (
+ Message.objects.filter(recipient=request.user)
+ .filter(read_at__isnull=True)
+ .count()
+ )
+
+
+@login_required
+@require_http_methods(["GET"])
+def get_received_messages(request):
+ """Récupère des messages recus pour l'utilisateur connecté.
+ """
+ return request.user.received_messages.all()
+
+
+@login_required
+@require_http_methods(["GET"])
+def get_sent_messages(request):
+ """Récupère des messages envoyés par l'utilisateur connecté.
+ """
+ return request.user.sent_messages.all()
+
+
+@login_required
+@require_http_methods(["GET"])
+def get_message_details(request, messageid):
+ """Récupère les détails (l'affichage ?) d'un message.
+ """
+ message = get_object_or_404(Message, pk=messageid)
+ if not message.read_at and message.recipient == request.user.id:
+ message.read_at = datetime.now()
+ message.save()
+
+ context = {"message": message, "type": None}
+ return render(request, "message_details.html", context)
+
+
+@login_required
+@require_http_methods(["POST"])
+def delete_message(request, messageid):
+ """Supprime le message dont la clé est passée en paramètre.
+ """
+ try:
+ message = Message.objects.get(pk=messageid)
+
+ if message.sender == request.user or message.recipient == request.user:
+ message.delete()
+ else:
+ return HttpResponse(401)
+ except:
+ return HttpResponse(400)
+
+ return HttpResponse(200)
+
+
+@login_required
+@require_http_methods(["GET", "POST"])
+def compose_message(request):
+ """Permet à l'utilisateur connecté de rédiger un nouveau message.
+ """
+
+ if request.method == "POST":
+ form = MessageForm(request.POST)
+
+ if form.is_valid():
+ form.save()
+ return HttpResponseRedirect(reverse("sent_messages"))
+
+ print("Invalid form")
+ else:
+ form = MessageForm()
+
+ context = {"form": form, "writer": request.user.id}
+ return render(request, "message_create.html", context)
diff --git a/src/khana/__init__.py b/khana/competition/__init__.py
similarity index 100%
rename from src/khana/__init__.py
rename to khana/competition/__init__.py
diff --git a/src/competition/admin.py b/khana/competition/admin.py
similarity index 100%
rename from src/competition/admin.py
rename to khana/competition/admin.py
diff --git a/khana/competition/apps.py b/khana/competition/apps.py
new file mode 100644
index 0000000..3021000
--- /dev/null
+++ b/khana/competition/apps.py
@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class CompetitionConfig(AppConfig):
+ name = "khana.competition"
diff --git a/src/competition/forms.py b/khana/competition/forms.py
similarity index 100%
rename from src/competition/forms.py
rename to khana/competition/forms.py
diff --git a/src/competition/migrations/0001_initial.py b/khana/competition/migrations/0001_initial.py
similarity index 100%
rename from src/competition/migrations/0001_initial.py
rename to khana/competition/migrations/0001_initial.py
diff --git a/src/competition/migrations/0002_auto_20190316_1658.py b/khana/competition/migrations/0002_auto_20190316_1658.py
similarity index 100%
rename from src/competition/migrations/0002_auto_20190316_1658.py
rename to khana/competition/migrations/0002_auto_20190316_1658.py
diff --git a/src/competition/migrations/0003_auto_20190402_2026.py b/khana/competition/migrations/0003_auto_20190402_2026.py
similarity index 100%
rename from src/competition/migrations/0003_auto_20190402_2026.py
rename to khana/competition/migrations/0003_auto_20190402_2026.py
diff --git a/src/competition/migrations/0004_auto_20190402_2032.py b/khana/competition/migrations/0004_auto_20190402_2032.py
similarity index 100%
rename from src/competition/migrations/0004_auto_20190402_2032.py
rename to khana/competition/migrations/0004_auto_20190402_2032.py
diff --git a/src/competition/migrations/0005_auto_20190402_2035.py b/khana/competition/migrations/0005_auto_20190402_2035.py
similarity index 100%
rename from src/competition/migrations/0005_auto_20190402_2035.py
rename to khana/competition/migrations/0005_auto_20190402_2035.py
diff --git a/src/competition/migrations/0006_auto_20190429_1125.py b/khana/competition/migrations/0006_auto_20190429_1125.py
similarity index 100%
rename from src/competition/migrations/0006_auto_20190429_1125.py
rename to khana/competition/migrations/0006_auto_20190429_1125.py
diff --git a/src/competition/migrations/0007_auto_20190524_1211.py b/khana/competition/migrations/0007_auto_20190524_1211.py
similarity index 100%
rename from src/competition/migrations/0007_auto_20190524_1211.py
rename to khana/competition/migrations/0007_auto_20190524_1211.py
diff --git a/src/location/__init__.py b/khana/competition/migrations/__init__.py
similarity index 100%
rename from src/location/__init__.py
rename to khana/competition/migrations/__init__.py
diff --git a/src/competition/models.py b/khana/competition/models.py
similarity index 100%
rename from src/competition/models.py
rename to khana/competition/models.py
diff --git a/src/competition/tests_models.py b/khana/competition/tests_models.py
similarity index 94%
rename from src/competition/tests_models.py
rename to khana/competition/tests_models.py
index 2156169..89652ff 100644
--- a/src/competition/tests_models.py
+++ b/khana/competition/tests_models.py
@@ -1,12 +1,7 @@
# coding=UTF-8
import pytest
-from .models import (
- Point,
- Competition,
- Division,
- Level
-)
+from .models import Point, Competition, Division, Level
# class TestModelCompetition(TestCase):
@@ -14,6 +9,7 @@ from .models import (
# Tests relatifs à la classe `Compétition`.
# """
+
def test_competition_str_():
""" Vérifie la représentation textuelle de la classe. """
competition = Competition(name="Belgian Open Trampoline", acronym="BOT")
@@ -25,6 +21,7 @@ def test_competition_str_():
# Tests relatifs à la classe `Division`.
# """
+
def test_division_str_():
""" Vérifie la représentation textuelle de la classe. """
competition = Competition(name="Belgian Open Trampoline", acronym="BOT")
@@ -37,6 +34,7 @@ def test_division_str_():
# Tests relatifs à la classe `Level`.
# """
+
def test_level_str_():
""" Vérifie la représentation textuelle de la classe. """
competition = Competition(name="Belgian Open Trampoline", acronym="BOT")
diff --git a/src/competition/urls.py b/khana/competition/urls.py
similarity index 100%
rename from src/competition/urls.py
rename to khana/competition/urls.py
diff --git a/src/competition/views.py b/khana/competition/views.py
similarity index 100%
rename from src/competition/views.py
rename to khana/competition/views.py
diff --git a/src/location/migrations/__init__.py b/khana/location/__init__.py
similarity index 100%
rename from src/location/migrations/__init__.py
rename to khana/location/__init__.py
diff --git a/src/location/admin.py b/khana/location/admin.py
similarity index 100%
rename from src/location/admin.py
rename to khana/location/admin.py
diff --git a/khana/location/apps.py b/khana/location/apps.py
new file mode 100644
index 0000000..4cb417c
--- /dev/null
+++ b/khana/location/apps.py
@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class LocationConfig(AppConfig):
+ name = "khana.location"
diff --git a/src/location/forms.py b/khana/location/forms.py
similarity index 100%
rename from src/location/forms.py
rename to khana/location/forms.py
diff --git a/src/location/migrations/0001_initial.py b/khana/location/migrations/0001_initial.py
similarity index 100%
rename from src/location/migrations/0001_initial.py
rename to khana/location/migrations/0001_initial.py
diff --git a/src/location/migrations/0002_auto_20190402_2032.py b/khana/location/migrations/0002_auto_20190402_2032.py
similarity index 100%
rename from src/location/migrations/0002_auto_20190402_2032.py
rename to khana/location/migrations/0002_auto_20190402_2032.py
diff --git a/src/location/migrations/0003_auto_20190402_2035.py b/khana/location/migrations/0003_auto_20190402_2035.py
similarity index 100%
rename from src/location/migrations/0003_auto_20190402_2035.py
rename to khana/location/migrations/0003_auto_20190402_2035.py
diff --git a/src/location/tests/__init__.py b/khana/location/migrations/__init__.py
similarity index 100%
rename from src/location/tests/__init__.py
rename to khana/location/migrations/__init__.py
diff --git a/src/location/models.py b/khana/location/models.py
similarity index 100%
rename from src/location/models.py
rename to khana/location/models.py
diff --git a/src/objective/__init__.py b/khana/location/tests/__init__.py
similarity index 100%
rename from src/objective/__init__.py
rename to khana/location/tests/__init__.py
diff --git a/src/location/tests/test_models.py b/khana/location/tests/test_models.py
similarity index 66%
rename from src/location/tests/test_models.py
rename to khana/location/tests/test_models.py
index d404631..f6f8c4e 100644
--- a/src/location/tests/test_models.py
+++ b/khana/location/tests/test_models.py
@@ -8,10 +8,7 @@ from ..models import Club, Country, Place
class TestCountry(TestCase):
def test_str_should_contain_name_and_iso2(self):
country = Country.objects.create(
- nameus="Belgium",
- namefr="Belgique",
- isonum=56,
- iso2="BE"
+ nameus="Belgium", namefr="Belgique", isonum=56, iso2="BE"
)
self.assertEqual(str(country), "Belgique (BE)")
@@ -23,11 +20,8 @@ class TestPlace(TestCase):
name="Heaven",
postal=1080,
country=Country.objects.create(
- nameus="Belgium",
- namefr="Belgique",
- isonum=56,
- iso2="BE"
- )
+ nameus="Belgium", namefr="Belgique", isonum=56, iso2="BE"
+ ),
)
self.assertEqual(str(place), "Heaven (?)")
@@ -41,12 +35,9 @@ class TestClub(TestCase):
name="Heaven",
postal=1080,
country=Country.objects.create(
- nameus="Belgium",
- namefr="Belgique",
- isonum=56,
- iso2="BE"
- )
- )
+ nameus="Belgium", namefr="Belgique", isonum=56, iso2="BE"
+ ),
+ ),
)
- self.assertEqual(str(club), "RSCA (à ?)")
\ No newline at end of file
+ self.assertEqual(str(club), "RSCA (à ?)")
diff --git a/src/location/tests_models.py b/khana/location/tests_models.py
similarity index 79%
rename from src/location/tests_models.py
rename to khana/location/tests_models.py
index 1c93626..f5f002f 100644
--- a/src/location/tests_models.py
+++ b/khana/location/tests_models.py
@@ -1,10 +1,6 @@
# coding=UTF-8
-from .models import (
- Club,
- Place,
- Country
-)
+from .models import Club, Place, Country
import pytest
# class GymnastTestCase():
@@ -12,11 +8,13 @@ def test_country_tostring():
c = Country(namefr="Belgique", iso2="56")
assert str(c) == "Belgique (56)"
+
def test_place_tostring():
p = Place(name="FATC", city="Lillois")
assert str(p) == "FATC (Lillois)"
+
def test_club_tostring():
p = Place(name="FATC", city="Lillois")
club = Club(place=p, name="FATC2")
- assert str(club) == "FATC2 (à Lillois)"
\ No newline at end of file
+ assert str(club) == "FATC2 (à Lillois)"
diff --git a/src/location/urls.py b/khana/location/urls.py
similarity index 100%
rename from src/location/urls.py
rename to khana/location/urls.py
diff --git a/src/location/views.py b/khana/location/views.py
similarity index 100%
rename from src/location/views.py
rename to khana/location/views.py
diff --git a/src/main.py b/khana/main.py
similarity index 100%
rename from src/main.py
rename to khana/main.py
diff --git a/src/objective/migrations/__init__.py b/khana/objective/__init__.py
similarity index 100%
rename from src/objective/migrations/__init__.py
rename to khana/objective/__init__.py
diff --git a/src/objective/admin.py b/khana/objective/admin.py
similarity index 100%
rename from src/objective/admin.py
rename to khana/objective/admin.py
diff --git a/khana/objective/apps.py b/khana/objective/apps.py
new file mode 100644
index 0000000..d7d8166
--- /dev/null
+++ b/khana/objective/apps.py
@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class ObjectiveConfig(AppConfig):
+ name = "khana.objective"
diff --git a/src/objective/forms.py b/khana/objective/forms.py
similarity index 100%
rename from src/objective/forms.py
rename to khana/objective/forms.py
diff --git a/src/objective/migrations/0001_initial.py b/khana/objective/migrations/0001_initial.py
similarity index 100%
rename from src/objective/migrations/0001_initial.py
rename to khana/objective/migrations/0001_initial.py
diff --git a/src/objective/migrations/0002_auto_20190316_1658.py b/khana/objective/migrations/0002_auto_20190316_1658.py
similarity index 100%
rename from src/objective/migrations/0002_auto_20190316_1658.py
rename to khana/objective/migrations/0002_auto_20190316_1658.py
diff --git a/src/objective/migrations/0003_auto_20190318_0855.py b/khana/objective/migrations/0003_auto_20190318_0855.py
similarity index 100%
rename from src/objective/migrations/0003_auto_20190318_0855.py
rename to khana/objective/migrations/0003_auto_20190318_0855.py
diff --git a/src/objective/migrations/0004_auto_20190330_0920.py b/khana/objective/migrations/0004_auto_20190330_0920.py
similarity index 100%
rename from src/objective/migrations/0004_auto_20190330_0920.py
rename to khana/objective/migrations/0004_auto_20190330_0920.py
diff --git a/src/objective/migrations/0005_auto_20190330_1652.py b/khana/objective/migrations/0005_auto_20190330_1652.py
similarity index 100%
rename from src/objective/migrations/0005_auto_20190330_1652.py
rename to khana/objective/migrations/0005_auto_20190330_1652.py
diff --git a/src/objective/migrations/0006_auto_20190401_1755.py b/khana/objective/migrations/0006_auto_20190401_1755.py
similarity index 100%
rename from src/objective/migrations/0006_auto_20190401_1755.py
rename to khana/objective/migrations/0006_auto_20190401_1755.py
diff --git a/src/objective/migrations/0007_auto_20190402_0820.py b/khana/objective/migrations/0007_auto_20190402_0820.py
similarity index 100%
rename from src/objective/migrations/0007_auto_20190402_0820.py
rename to khana/objective/migrations/0007_auto_20190402_0820.py
diff --git a/src/objective/migrations/0008_auto_20190402_0830.py b/khana/objective/migrations/0008_auto_20190402_0830.py
similarity index 100%
rename from src/objective/migrations/0008_auto_20190402_0830.py
rename to khana/objective/migrations/0008_auto_20190402_0830.py
diff --git a/src/objective/migrations/0009_auto_20190402_2026.py b/khana/objective/migrations/0009_auto_20190402_2026.py
similarity index 100%
rename from src/objective/migrations/0009_auto_20190402_2026.py
rename to khana/objective/migrations/0009_auto_20190402_2026.py
diff --git a/src/objective/migrations/0010_auto_20190402_2032.py b/khana/objective/migrations/0010_auto_20190402_2032.py
similarity index 100%
rename from src/objective/migrations/0010_auto_20190402_2032.py
rename to khana/objective/migrations/0010_auto_20190402_2032.py
diff --git a/src/objective/migrations/0011_auto_20190402_2035.py b/khana/objective/migrations/0011_auto_20190402_2035.py
similarity index 100%
rename from src/objective/migrations/0011_auto_20190402_2035.py
rename to khana/objective/migrations/0011_auto_20190402_2035.py
diff --git a/src/objective/migrations/0012_auto_20190407_1837.py b/khana/objective/migrations/0012_auto_20190407_1837.py
similarity index 100%
rename from src/objective/migrations/0012_auto_20190407_1837.py
rename to khana/objective/migrations/0012_auto_20190407_1837.py
diff --git a/src/objective/migrations/0013_auto_20190429_0708.py b/khana/objective/migrations/0013_auto_20190429_0708.py
similarity index 100%
rename from src/objective/migrations/0013_auto_20190429_0708.py
rename to khana/objective/migrations/0013_auto_20190429_0708.py
diff --git a/src/objective/migrations/0014_evaluation.py b/khana/objective/migrations/0014_evaluation.py
similarity index 100%
rename from src/objective/migrations/0014_evaluation.py
rename to khana/objective/migrations/0014_evaluation.py
diff --git a/src/objective/migrations/0015_auto_20190524_1211.py b/khana/objective/migrations/0015_auto_20190524_1211.py
similarity index 100%
rename from src/objective/migrations/0015_auto_20190524_1211.py
rename to khana/objective/migrations/0015_auto_20190524_1211.py
diff --git a/src/objective/migrations/0016_rename_information_educative_content.py b/khana/objective/migrations/0016_rename_information_educative_content.py
similarity index 58%
rename from src/objective/migrations/0016_rename_information_educative_content.py
rename to khana/objective/migrations/0016_rename_information_educative_content.py
index f6fb3f0..e5c66b8 100644
--- a/src/objective/migrations/0016_rename_information_educative_content.py
+++ b/khana/objective/migrations/0016_rename_information_educative_content.py
@@ -6,13 +6,11 @@ from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
- ('objective', '0015_auto_20190524_1211'),
+ ("objective", "0015_auto_20190524_1211"),
]
operations = [
migrations.RenameField(
- model_name='educative',
- old_name='information',
- new_name='content',
+ model_name="educative", old_name="information", new_name="content",
),
]
diff --git a/khana/objective/migrations/0017_auto_20210620_1618.py b/khana/objective/migrations/0017_auto_20210620_1618.py
new file mode 100644
index 0000000..fbc3486
--- /dev/null
+++ b/khana/objective/migrations/0017_auto_20210620_1618.py
@@ -0,0 +1,75 @@
+# Generated by Django 3.2.2 on 2021-06-20 16:18
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("objective", "0016_rename_information_educative_content"),
+ ]
+
+ operations = [
+ migrations.RenameModel(old_name="Routine_Skill", new_name="RoutineSkill",),
+ migrations.AlterModelOptions(
+ name="educative",
+ options={
+ "ordering": ["label", "short_label"],
+ "verbose_name": "Educatif",
+ "verbose_name_plural": "Educatifs",
+ },
+ ),
+ migrations.AlterModelOptions(
+ name="touchposition",
+ options={
+ "ordering": [
+ "label",
+ "short_label",
+ "is_default",
+ "allowed_in_competition",
+ ],
+ "verbose_name": "Landing",
+ "verbose_name_plural": "Landings",
+ },
+ ),
+ migrations.RenameField(
+ model_name="educative", old_name="ageBoy", new_name="age_boy",
+ ),
+ migrations.RenameField(
+ model_name="educative", old_name="ageGirl", new_name="age_girl",
+ ),
+ migrations.RenameField(
+ model_name="educative", old_name="educative", new_name="educatives",
+ ),
+ migrations.RenameField(
+ model_name="educative", old_name="longLabel", new_name="label",
+ ),
+ migrations.RenameField(
+ model_name="educative", old_name="prerequisite", new_name="prerequisites",
+ ),
+ migrations.RenameField(
+ model_name="educative", old_name="shortLabel", new_name="short_label",
+ ),
+ migrations.RenameField(
+ model_name="skill", old_name="rotationType", new_name="rotation_type",
+ ),
+ migrations.RenameField(
+ model_name="skill",
+ old_name="simplyNotation",
+ new_name="simplified_notation",
+ ),
+ migrations.RenameField(
+ model_name="touchposition",
+ old_name="competition",
+ new_name="allowed_in_competition",
+ ),
+ migrations.RenameField(
+ model_name="touchposition", old_name="default", new_name="is_default",
+ ),
+ migrations.RenameField(
+ model_name="touchposition", old_name="longLabel", new_name="label",
+ ),
+ migrations.RenameField(
+ model_name="touchposition", old_name="shortLabel", new_name="short_label",
+ ),
+ ]
diff --git a/src/people/__init__.py b/khana/objective/migrations/__init__.py
similarity index 100%
rename from src/people/__init__.py
rename to khana/objective/migrations/__init__.py
diff --git a/src/objective/models.py b/khana/objective/models.py
similarity index 69%
rename from src/objective/models.py
rename to khana/objective/models.py
index 6d26ecc..8b617a2 100644
--- a/src/objective/models.py
+++ b/khana/objective/models.py
@@ -3,7 +3,7 @@
from datetime import date
from django.db import models
from django.db.models import Q
-from base.models import Markdownizable
+from khana.base.models import Markdownizable
from django.contrib.auth.models import User
@@ -17,24 +17,24 @@ class Educative(Markdownizable):
verbose_name_plural = "Educatifs"
ordering = ["label", "short_label"] # 'level',
- label = models.CharField(max_length = 255, verbose_name = "Long Name")
- short_label = models.CharField(max_length = 255, verbose_name = "Short Name")
+ label = models.CharField(max_length=255, verbose_name="Long Name")
+ short_label = models.CharField(max_length=255, verbose_name="Short Name")
difficulty = models.DecimalField(
- max_digits = 3, decimal_places = 1, verbose_name = "Difficulty"
+ max_digits=3, decimal_places=1, verbose_name="Difficulty"
)
- level = models.PositiveSmallIntegerField(verbose_name = "Level", default = 0)
- rank = models.PositiveSmallIntegerField(verbose_name = "Rank", default = 0)
+ level = models.PositiveSmallIntegerField(verbose_name="Level", default=0)
+ rank = models.PositiveSmallIntegerField(verbose_name="Rank", default=0)
educatives = models.ManyToManyField(
- "self", related_name = "educativeOf", blank = True, symmetrical = False
+ "self", related_name="educativeOf", blank=True, symmetrical=False
)
prerequisites = models.ManyToManyField(
- "self", related_name = "prerequisiteOf", blank = True, symmetrical = False
+ "self", related_name="prerequisiteOf", blank=True, symmetrical=False
)
age_boy = models.PositiveSmallIntegerField(
- blank = True, null = True, verbose_name = "Boy's age"
+ blank=True, null=True, verbose_name="Boy's age"
)
age_girl = models.PositiveSmallIntegerField(
- blank = True, null = True, verbose_name = "Girl's age"
+ blank=True, null=True, verbose_name="Girl's age"
)
def __str__(self):
@@ -56,10 +56,10 @@ class TouchPosition(models.Model):
verbose_name_plural = "Landings"
ordering = ["label", "short_label", "is_default", "allowed_in_competition"]
- label = models.CharField(max_length = 30, verbose_name = "Nom long")
- short_label = models.CharField(max_length = 15, verbose_name = "Nom court")
- allowed_in_competition = models.BooleanField(verbose_name = "Compétition")
- is_default = models.BooleanField(verbose_name = "Défaut")
+ label = models.CharField(max_length=30, verbose_name="Nom long")
+ short_label = models.CharField(max_length=15, verbose_name="Nom court")
+ allowed_in_competition = models.BooleanField(verbose_name="Compétition")
+ is_default = models.BooleanField(verbose_name="Défaut")
def __str__(self):
return "%s" % (self.longLabel)
@@ -104,29 +104,31 @@ class Skill(Educative):
(2, "Backward"),
)
- position = models.CharField(max_length = 2, choices = POSITION_CHOICES)
+ position = models.CharField(max_length=2, choices=POSITION_CHOICES)
departure = models.ForeignKey(
TouchPosition,
- related_name = "depart_of",
- default = get_default_position,
- verbose_name = "Take-off position",
- on_delete = models.CASCADE,
+ related_name="depart_of",
+ default=get_default_position,
+ verbose_name="Take-off position",
+ on_delete=models.CASCADE,
)
landing = models.ForeignKey(
TouchPosition,
- related_name = "landing_of",
- default = get_default_position,
- verbose_name = "Landing position",
- on_delete = models.CASCADE,
+ related_name="landing_of",
+ default=get_default_position,
+ verbose_name="Landing position",
+ on_delete=models.CASCADE,
)
rotation_type = models.PositiveSmallIntegerField(
- choices = ROTATION_CHOICES, verbose_name = "Type de rotation"
+ choices=ROTATION_CHOICES, verbose_name="Type de rotation"
)
- rotation = models.PositiveSmallIntegerField(verbose_name = "1/4 de rotation")
- twist = models.PositiveSmallIntegerField(verbose_name = "1/2 Vrille")
- notation = models.CharField(max_length = 25)
- simplified_notation = models.CharField(max_length = 25, verbose_name = "Notation simplifiée")
- is_competitive = models.BooleanField(default = False)
+ rotation = models.PositiveSmallIntegerField(verbose_name="1/4 de rotation")
+ twist = models.PositiveSmallIntegerField(verbose_name="1/2 Vrille")
+ notation = models.CharField(max_length=25)
+ simplified_notation = models.CharField(
+ max_length=25, verbose_name="Notation simplifiée"
+ )
+ is_competitive = models.BooleanField(default=False)
# importance = models.PositiveSmallIntegerField(default = 1)
def __str__(self):
@@ -144,9 +146,9 @@ class Routine(Educative):
active = models.BooleanField()
jumps = models.ManyToManyField(
- Skill, through = "RoutineSkill", verbose_name = "routine"
+ Skill, through="RoutineSkill", verbose_name="routine"
) # ceci n'est pas un vrai champ
- is_competitive = models.BooleanField(default = False)
+ is_competitive = models.BooleanField(default=False)
def __str__(self):
return "%s (%s)" % (self.label, self.short_label)
@@ -216,10 +218,10 @@ class RoutineSkill(models.Model):
ordering = ("rank",)
routine = models.ForeignKey(
- Routine, on_delete = models.CASCADE, default = None, related_name = "skill_links"
+ Routine, on_delete=models.CASCADE, default=None, related_name="skill_links"
)
skill = models.ForeignKey(
- Skill, on_delete = models.CASCADE, default = None, related_name = "routine_links"
+ Skill, on_delete=models.CASCADE, default=None, related_name="routine_links"
)
rank = models.PositiveSmallIntegerField()
@@ -247,13 +249,13 @@ class Chrono(models.Model):
(99, "Other"),
)
- routine = models.ForeignKey(Routine, on_delete = models.CASCADE, default = None)
- routine_type = models.PositiveSmallIntegerField(choices = ROUTINETYPE_CHOICE)
+ routine = models.ForeignKey(Routine, on_delete=models.CASCADE, default=None)
+ routine_type = models.PositiveSmallIntegerField(choices=ROUTINETYPE_CHOICE)
gymnast = models.ForeignKey(
- "people.gymnast", on_delete = models.CASCADE, default = None
+ "people.gymnast", on_delete=models.CASCADE, default=None
)
- date = models.DateField(default = date.today, verbose_name = "Date")
- score = models.DecimalField(max_digits = 5, decimal_places = 2)
+ date = models.DateField(default=date.today, verbose_name="Date")
+ score = models.DecimalField(max_digits=5, decimal_places=2)
def __str__(self):
return "%s le %s : %s pour %s" % (
@@ -278,13 +280,13 @@ class Evaluation(models.Model):
Classe permettant l'évaluation des éducatifs.
"""
- date = models.DateField(default = date.today, verbose_name = "Date")
- value = models.PositiveSmallIntegerField(default = 0)
+ date = models.DateField(default=date.today, verbose_name="Date")
+ value = models.PositiveSmallIntegerField(default=0)
educative = models.ForeignKey(
Educative,
- related_name = "depart_of",
- verbose_name = "Take-off position",
- on_delete = models.CASCADE,
+ related_name="depart_of",
+ verbose_name="Take-off position",
+ on_delete=models.CASCADE,
)
- type_of_evaluator = models.BooleanField(default = 0)
- evaluator = models.ForeignKey(User, null = True, on_delete = models.SET_NULL)
+ type_of_evaluator = models.BooleanField(default=0)
+ evaluator = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
diff --git a/src/objective/tests.py b/khana/objective/tests.py
similarity index 100%
rename from src/objective/tests.py
rename to khana/objective/tests.py
diff --git a/src/objective/urls.py b/khana/objective/urls.py
similarity index 95%
rename from src/objective/urls.py
rename to khana/objective/urls.py
index a8ff9a8..57e71cf 100644
--- a/src/objective/urls.py
+++ b/khana/objective/urls.py
@@ -42,11 +42,7 @@ routine_urlpatterns = [
views.delete_skill_from_routine,
name="delete_skill_from_routine",
),
- path(
- r"suggest/",
- views.suggest_routine,
- name="suggest_routine",
- )
+ path(r"suggest/", views.suggest_routine, name="suggest_routine",),
]
# Chrono
diff --git a/src/objective/views.py b/khana/objective/views.py
similarity index 90%
rename from src/objective/views.py
rename to khana/objective/views.py
index fa171cb..dcc9a74 100644
--- a/src/objective/views.py
+++ b/khana/objective/views.py
@@ -338,7 +338,9 @@ def random_skill(request, skill_quantity=20, is_competitive=True):
number_of_skill = skillid_list.count()
selected_skillid_list = [
skillid_list[x]["id"]
- for x in [random.randrange(0, number_of_skill, 1) for i in range(skill_quantity)]
+ for x in [
+ random.randrange(0, number_of_skill, 1) for i in range(skill_quantity)
+ ]
]
skill_list = Skill.objects.filter(id__in=selected_skillid_list)
@@ -387,12 +389,14 @@ def __construct_routine(
if current_routine:
skill_list = Skill.objects.filter(
- departure = current_routine[-1].landing
- ) # , difficulty__lte = total_difficulty_score
+ departure=current_routine[-1].landing
+ ) # , difficulty__lte = total_difficulty_score
if len(current_routine) == (max_routine_length - 1):
skill_list = skill_list.filter(landing__longLabel="Debout")
if logic and current_routine[-1].landing.longLabel == "Debout":
- skill_list = skill_list.exclude(rotationType = current_routine[-1].rotationType)
+ skill_list = skill_list.exclude(
+ rotationType=current_routine[-1].rotationType
+ )
else:
skill_list = Skill.objects.filter(departure__longLabel="Debout")
@@ -404,23 +408,31 @@ def __construct_routine(
min_diff_skill = total_difficulty_score
max_diff_skill = total_difficulty_score + 3
else:
- if math.ceil(total_difficulty_score / max_routine_length) <= max_skill_difficulty:
- min_diff_skill = math.ceil(max((total_difficulty_score / max_routine_length) - 5, 0))
+ if (
+ math.ceil(total_difficulty_score / max_routine_length)
+ <= max_skill_difficulty
+ ):
+ min_diff_skill = math.ceil(
+ max((total_difficulty_score / max_routine_length) - 5, 0)
+ )
else:
return
- if (math.ceil(total_difficulty_score / max_routine_length) + 2) <= max_skill_difficulty:
- max_diff_skill = math.ceil(total_difficulty_score / max_routine_length) + 2
+ if (
+ math.ceil(total_difficulty_score / max_routine_length) + 2
+ ) <= max_skill_difficulty:
+ max_diff_skill = (
+ math.ceil(total_difficulty_score / max_routine_length) + 2
+ )
else:
return
skill_list = skill_list.filter(
- difficulty__gte = (min_diff_skill / 10),
- difficulty__lte = (max_diff_skill / 10)
+ difficulty__gte=(min_diff_skill / 10), difficulty__lte=(max_diff_skill / 10)
)
if gymnast:
- skill_list = skill_list.filter(cando__gymnast = gymnast)
+ skill_list = skill_list.filter(cando__gymnast=gymnast)
for skill in skill_list:
current_routine.append(skill)
@@ -429,7 +441,9 @@ def __construct_routine(
current_routine,
max_routine_length,
max_skill_difficulty,
- total_difficulty_score - (skill.difficulty * 10) if total_difficulty_score is not None else None,
+ total_difficulty_score - (skill.difficulty * 10)
+ if total_difficulty_score is not None
+ else None,
competition,
logic,
gymnast,
@@ -442,7 +456,7 @@ def __construct_routine(
def suggest_routine(
request,
- max_routine_length = 2,
+ max_routine_length=2,
total_difficulty_score=None,
competition=True,
logic=True,
@@ -471,24 +485,32 @@ def suggest_routine(
total_difficulty_score = 26
if gymnast:
- max_skill_difficulty = Educative.objects.values('difficulty').filter(cando__gymnast=gymnast).order_by(
- "-difficulty"
- )[:1][0]["difficulty"] * 10
+ max_skill_difficulty = (
+ Educative.objects.values("difficulty")
+ .filter(cando__gymnast=gymnast)
+ .order_by("-difficulty")[:1][0]["difficulty"]
+ * 10
+ )
else:
- max_skill_difficulty = Skill.objects.values('difficulty').order_by("-difficulty")[:1][0]["difficulty"] * 10
+ max_skill_difficulty = (
+ Skill.objects.values("difficulty").order_by("-difficulty")[:1][0][
+ "difficulty"
+ ]
+ * 10
+ )
# difficulty_scores = range(5, 45, 5)
# for total_difficulty_score in difficulty_scores:
# print("===============================================================================================")
__construct_routine(
- routine,
- max_routine_length,
- max_skill_difficulty,
- total_difficulty_score,
- competition,
- logic,
- gymnast,
- )
+ routine,
+ max_routine_length,
+ max_skill_difficulty,
+ total_difficulty_score,
+ competition,
+ logic,
+ gymnast,
+ )
# print(routines)
diff --git a/src/people/management/__init__.py b/khana/people/__init__.py
similarity index 100%
rename from src/people/management/__init__.py
rename to khana/people/__init__.py
diff --git a/khana/people/admin.py b/khana/people/admin.py
new file mode 100644
index 0000000..c4cc275
--- /dev/null
+++ b/khana/people/admin.py
@@ -0,0 +1,127 @@
+"""Administration des gymnastes et des personnes.
+
+Remarks:
+ * Je ne pense pas qu'il faille encore passer par `ForeignKeyAutocompleteAdmin`.
+ https://docs.djangoproject.com/fr/3.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin.autocomplete_fields
+"""
+
+from django.contrib import admin
+
+from django_extensions.admin import ForeignKeyAutocompleteAdmin
+
+from .models import (
+ Gymnast,
+ Accident,
+ CanDoRelation,
+ ToDoRelation,
+ GymnastHasRoutine,
+)
+
+
+class CanDoRelationAdmin(ForeignKeyAutocompleteAdmin):
+ model = CanDoRelation
+
+ list_display = ("date", "gymnast", "educative")
+ list_filter = ("gymnast",)
+ search_fields = ("gymnast", "educative")
+ autocomplete_fields = ("gymnast",)
+
+ # related_search_fields = {
+ # 'gymnast': ('lastname', 'firstname'),
+ # }
+
+
+class InlineCanDoRelation(admin.TabularInline):
+ model = CanDoRelation
+
+
+class ToDoRelationAdmin(ForeignKeyAutocompleteAdmin):
+ model = ToDoRelation
+
+ list_display = ("date", "gymnast", "educative")
+ list_filter = ("gymnast",)
+ search_fields = ("gymnast", "educative")
+ autocomplete_fields = ("gymnast",)
+
+ # related_search_fields = {
+ # 'gymnast': ('lastname', 'firstname'),
+ # # 'educative': ('longLabel', 'shortLabel'), # TO_FRED : Pq ca marche pas ca ?
+ # }
+
+
+class GymnastHasRoutineAdmin(ForeignKeyAutocompleteAdmin):
+ model = GymnastHasRoutine
+
+ list_display = ("gymnast", "routine", "routine_type", "datebegin", "dateend")
+ list_filter = ("gymnast", "routine_type")
+ search_fields = ("gymnast", "routine")
+ autocomplete_fields = ("gymnast", "routine")
+
+
+class InlineToDoRelation(admin.TabularInline):
+ model = ToDoRelation
+
+
+class GymnastAdmin(admin.ModelAdmin):
+ model = Gymnast
+
+ def lastname(self, obj):
+ return obj.user.last_name
+
+ def firstname(self, obj):
+ return obj.user.first_name
+
+ def email(self, obj):
+ return obj.user.email
+
+ def is_active(self, obj):
+ return obj.user.is_active
+
+ fields = (
+ # "lastname",
+ # "firstname",
+ "birthdate",
+ "gender",
+ "club",
+ "niss",
+ "address",
+ "postal",
+ "city",
+ "phone",
+ "gsm",
+ # "user__email",
+ "fedid",
+ "year_of_practice",
+ "gsm_mother",
+ "email_mother",
+ "gsm_father",
+ "email_father",
+ # "user.is_active",
+ "orientation",
+ "trainer",
+ "picture",
+ "content",
+ )
+
+ list_display = ("lastname", "firstname", "birthdate", "age", "is_active")
+ list_filter = ("gender", "user__is_active")
+ search_fields = ("lastname", "firstname", "email")
+ inlines = [InlineToDoRelation, InlineCanDoRelation]
+ autocomplete_fields = ("club",)
+
+
+class AccidentAdmin(admin.ModelAdmin):
+ model = Accident
+
+ fields = ("date", "gymnast", "educative", "information")
+ list_display = ("date", "gymnast", "educative")
+ list_filter = ("date",)
+ search_fields = ("date", "gymnast", "educative")
+ autocomplete_fields = ["gymnast", "educative"]
+
+
+admin.site.register(Gymnast, GymnastAdmin)
+admin.site.register(Accident, AccidentAdmin)
+admin.site.register(CanDoRelation, CanDoRelationAdmin)
+admin.site.register(ToDoRelation, ToDoRelationAdmin)
+admin.site.register(GymnastHasRoutine, GymnastHasRoutineAdmin)
diff --git a/khana/people/apps.py b/khana/people/apps.py
new file mode 100644
index 0000000..c22a7cc
--- /dev/null
+++ b/khana/people/apps.py
@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class PeopleConfig(AppConfig):
+ name = "khana.people"
diff --git a/khana/people/forms.py b/khana/people/forms.py
new file mode 100644
index 0000000..ab913be
--- /dev/null
+++ b/khana/people/forms.py
@@ -0,0 +1,174 @@
+"""Formulaires de gestion des données entrantes pour les gymnastes et accidents."""
+
+from django import forms
+
+from .models import (
+ Accident,
+ Gymnast,
+ GymnastHasRoutine,
+)
+
+from django.contrib.auth.models import User
+
+
+class AccidentForm(forms.ModelForm):
+ class Meta:
+ model = Accident
+ fields = ("gymnast", "educative", "date", "content")
+ widgets = {
+ "date": forms.DateInput(
+ attrs={
+ "class": "form-control datepicker",
+ # "value": date.today().strftime("%Y-%m-%d"),
+ }
+ ),
+ "gymnast": forms.HiddenInput(),
+ "educative": forms.HiddenInput(),
+ "content": forms.Textarea(
+ attrs={
+ "class": "form-control",
+ "placeholder": "Informations about accident: context (why, where, …), consequencies, …",
+ }
+ ),
+ }
+
+ gymnast_related = forms.CharField(
+ widget=forms.TextInput(
+ attrs={
+ "class": "form-control",
+ "placeholder": "Searching gymnast…",
+ "data-ref": "#id_gymnast",
+ }
+ )
+ )
+ educative_related = forms.CharField(
+ widget=forms.TextInput(
+ attrs={
+ "class": "form-control",
+ "placeholder": "Searching skill…",
+ "data-ref": "#id_educative",
+ }
+ )
+ )
+
+
+class UserForm(forms.ModelForm):
+ class Meta:
+ model = User
+ fields = (
+ "last_name",
+ "first_name",
+ "email",
+ "is_active",
+ "username",
+ )
+
+
+class GymnastForm(forms.ModelForm):
+
+ lastname = forms.CharField(
+ widget=forms.TextInput(
+ attrs={"class": "form-control", "placeholder": "Lastname"}
+ )
+ )
+ firstname = forms.CharField(
+ widget=forms.TextInput(
+ attrs={"class": "form-control", "placeholder": "Firstname"}
+ )
+ )
+ email = forms.EmailField()
+ # is_active = forms.CheckboxInput()
+
+ class Meta:
+ model = Gymnast
+ fields = (
+ "id",
+ "birthdate",
+ "gender",
+ "address",
+ "postal",
+ "city",
+ "phone",
+ "gsm",
+ "gsm_main_responsible",
+ "email_main_responsible",
+ "gsm_second_responsible",
+ "email_second_responsible",
+ "orientation",
+ "picture",
+ "content",
+ )
+
+ widgets = {
+ "id": forms.HiddenInput(),
+ "lastname": forms.TextInput(
+ attrs={"class": "form-control", "placeholder": "Lastname"}
+ ),
+ "firstname": forms.TextInput(
+ attrs={"class": "form-control", "placeholder": "Firstname"}
+ ),
+ "birthdate": forms.DateInput(attrs={"class": "form-control datepicker"}),
+ "gender": forms.Select(attrs={"class": "form-control"}),
+ "address": forms.TextInput(attrs={"class": "form-control"}),
+ "postal": forms.TextInput(attrs={"class": "form-control"}),
+ "city": forms.TextInput(attrs={"class": "form-control"}),
+ "phone": forms.TextInput(attrs={"class": "form-control"}),
+ "gsm": forms.TextInput(attrs={"class": "form-control"}),
+ "email": forms.EmailInput(attrs={"class": "form-control"}),
+ "gsm_main_responsible": forms.TextInput(attrs={"class": "form-control"}),
+ "email_main_responsible": forms.EmailInput(attrs={"class": "form-control"}),
+ "gsm_second_responsible": forms.TextInput(attrs={"class": "form-control"}),
+ "email_second_responsible": forms.EmailInput(
+ attrs={"class": "form-control"}
+ ),
+ # "is_active": forms.CheckboxInput(
+ # attrs={
+ # "class": "bootstrap-switch mt-0",
+ # "data-on-label": "",
+ # "data-off-label": "",
+ # }
+ # ),
+ "orientation": forms.Select(attrs={"class": "form-control"}),
+ "picture": forms.Select(attrs={"class": "form-control"}),
+ "content": forms.Textarea(
+ attrs={
+ "class": "form-control",
+ "placeholder": "Informations about the gymnast.",
+ }
+ ),
+ }
+
+
+class GymnastHasRoutineForm(forms.ModelForm):
+ """
+ """
+
+ class Meta:
+ model = GymnastHasRoutine
+ fields = ("gymnast", "routine", "routine_type", "datebegin", "dateend")
+ widgets = {
+ "gymnast": forms.HiddenInput(),
+ "routine": forms.HiddenInput(),
+ "routine_type": forms.Select(attrs={"class": "form-control"}),
+ "datebegin": forms.DateInput(attrs={"class": "form-control datepicker",}),
+ "dateend": forms.DateInput(attrs={"class": "form-control datepicker",}),
+ }
+
+ gymnast_related = forms.CharField(
+ widget=forms.TextInput(
+ attrs={
+ "class": "form-control",
+ "placeholder": "Searching gymnast…",
+ "data-ref": "#id_gymnast",
+ }
+ )
+ )
+ routine_related = forms.CharField(
+ widget=forms.TextInput(
+ attrs={
+ "class": "form-control",
+ "placeholder": "Searching routine…",
+ "data-ref": "#id_routine",
+ }
+ )
+ )
diff --git a/src/people/management/commands/__init__.py b/khana/people/management/__init__.py
similarity index 100%
rename from src/people/management/commands/__init__.py
rename to khana/people/management/__init__.py
diff --git a/src/people/migrations/__init__.py b/khana/people/management/commands/__init__.py
similarity index 100%
rename from src/people/migrations/__init__.py
rename to khana/people/management/commands/__init__.py
diff --git a/src/people/management/commands/superpowers.py b/khana/people/management/commands/superpowers.py
similarity index 100%
rename from src/people/management/commands/superpowers.py
rename to khana/people/management/commands/superpowers.py
diff --git a/src/people/migrations/0001_initial.py b/khana/people/migrations/0001_initial.py
similarity index 100%
rename from src/people/migrations/0001_initial.py
rename to khana/people/migrations/0001_initial.py
diff --git a/src/people/migrations/0002_gymnast_club.py b/khana/people/migrations/0002_gymnast_club.py
similarity index 100%
rename from src/people/migrations/0002_gymnast_club.py
rename to khana/people/migrations/0002_gymnast_club.py
diff --git a/src/people/migrations/0003_auto_20190330_0920.py b/khana/people/migrations/0003_auto_20190330_0920.py
similarity index 100%
rename from src/people/migrations/0003_auto_20190330_0920.py
rename to khana/people/migrations/0003_auto_20190330_0920.py
diff --git a/src/people/migrations/0004_auto_20190330_0932.py b/khana/people/migrations/0004_auto_20190330_0932.py
similarity index 100%
rename from src/people/migrations/0004_auto_20190330_0932.py
rename to khana/people/migrations/0004_auto_20190330_0932.py
diff --git a/src/people/migrations/0005_auto_20190330_1652.py b/khana/people/migrations/0005_auto_20190330_1652.py
similarity index 100%
rename from src/people/migrations/0005_auto_20190330_1652.py
rename to khana/people/migrations/0005_auto_20190330_1652.py
diff --git a/src/people/migrations/0006_auto_20190331_0735.py b/khana/people/migrations/0006_auto_20190331_0735.py
similarity index 100%
rename from src/people/migrations/0006_auto_20190331_0735.py
rename to khana/people/migrations/0006_auto_20190331_0735.py
diff --git a/src/people/migrations/0007_auto_20190401_1755.py b/khana/people/migrations/0007_auto_20190401_1755.py
similarity index 100%
rename from src/people/migrations/0007_auto_20190401_1755.py
rename to khana/people/migrations/0007_auto_20190401_1755.py
diff --git a/src/people/migrations/0008_auto_20190402_0820.py b/khana/people/migrations/0008_auto_20190402_0820.py
similarity index 100%
rename from src/people/migrations/0008_auto_20190402_0820.py
rename to khana/people/migrations/0008_auto_20190402_0820.py
diff --git a/src/people/migrations/0009_auto_20190402_1215.py b/khana/people/migrations/0009_auto_20190402_1215.py
similarity index 100%
rename from src/people/migrations/0009_auto_20190402_1215.py
rename to khana/people/migrations/0009_auto_20190402_1215.py
diff --git a/src/people/migrations/0010_auto_20190402_1356.py b/khana/people/migrations/0010_auto_20190402_1356.py
similarity index 100%
rename from src/people/migrations/0010_auto_20190402_1356.py
rename to khana/people/migrations/0010_auto_20190402_1356.py
diff --git a/src/people/migrations/0011_auto_20190402_2032.py b/khana/people/migrations/0011_auto_20190402_2032.py
similarity index 100%
rename from src/people/migrations/0011_auto_20190402_2032.py
rename to khana/people/migrations/0011_auto_20190402_2032.py
diff --git a/src/people/migrations/0012_auto_20190402_2035.py b/khana/people/migrations/0012_auto_20190402_2035.py
similarity index 100%
rename from src/people/migrations/0012_auto_20190402_2035.py
rename to khana/people/migrations/0012_auto_20190402_2035.py
diff --git a/src/people/migrations/0013_auto_20190509_0805.py b/khana/people/migrations/0013_auto_20190509_0805.py
similarity index 100%
rename from src/people/migrations/0013_auto_20190509_0805.py
rename to khana/people/migrations/0013_auto_20190509_0805.py
diff --git a/src/people/migrations/0014_auto_20210513_1058.py b/khana/people/migrations/0014_auto_20210513_1058.py
similarity index 51%
rename from src/people/migrations/0014_auto_20210513_1058.py
rename to khana/people/migrations/0014_auto_20210513_1058.py
index 1b42506..ce1b2b6 100644
--- a/src/people/migrations/0014_auto_20210513_1058.py
+++ b/khana/people/migrations/0014_auto_20210513_1058.py
@@ -6,18 +6,14 @@ from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
- ('people', '0013_auto_20190509_0805'),
+ ("people", "0013_auto_20190509_0805"),
]
operations = [
migrations.RenameField(
- model_name='accident',
- old_name='information',
- new_name='content',
+ model_name="accident", old_name="information", new_name="content",
),
migrations.RenameField(
- model_name='gymnast',
- old_name='information',
- new_name='content',
+ model_name="gymnast", old_name="information", new_name="content",
),
]
diff --git a/khana/people/migrations/0015_auto_20210514_1619.py b/khana/people/migrations/0015_auto_20210514_1619.py
new file mode 100644
index 0000000..d502364
--- /dev/null
+++ b/khana/people/migrations/0015_auto_20210514_1619.py
@@ -0,0 +1,24 @@
+# Generated by Django 3.2.2 on 2021-05-14 16:19
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("people", "0014_auto_20210513_1058"),
+ ]
+
+ operations = [
+ migrations.AlterModelOptions(
+ name="gymnast",
+ options={
+ "ordering": ["user__last_name", "user__first_name"],
+ "verbose_name": "Gymnast",
+ "verbose_name_plural": "Gymnasts",
+ },
+ ),
+ migrations.RemoveField(model_name="gymnast", name="email",),
+ migrations.RemoveField(model_name="gymnast", name="firstname",),
+ migrations.RemoveField(model_name="gymnast", name="lastname",),
+ ]
diff --git a/khana/people/migrations/0016_auto_20210515_0800.py b/khana/people/migrations/0016_auto_20210515_0800.py
new file mode 100644
index 0000000..027393f
--- /dev/null
+++ b/khana/people/migrations/0016_auto_20210515_0800.py
@@ -0,0 +1,38 @@
+# Generated by Django 3.2.2 on 2021-05-15 08:00
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("people", "0015_auto_20210514_1619"),
+ ]
+
+ operations = [
+ migrations.RemoveField(model_name="gymnast", name="active",),
+ migrations.AlterField(
+ model_name="gymnast",
+ name="fedid",
+ field=models.CharField(
+ blank=True, max_length=10, null=True, verbose_name="Federation ID"
+ ),
+ ),
+ migrations.AlterField(
+ model_name="gymnast",
+ name="orientation",
+ field=models.PositiveSmallIntegerField(
+ blank=True,
+ choices=[(None, "Unknown"), (0, "Left"), (1, "Right")],
+ null=True,
+ verbose_name="Twist side",
+ ),
+ ),
+ migrations.AlterField(
+ model_name="gymnast",
+ name="phone",
+ field=models.CharField(
+ blank=True, max_length=9, null=True, verbose_name="Phond"
+ ),
+ ),
+ ]
diff --git a/src/people/migrations/0017_alter_gymnast_user.py b/khana/people/migrations/0017_alter_gymnast_user.py
similarity index 55%
rename from src/people/migrations/0017_alter_gymnast_user.py
rename to khana/people/migrations/0017_alter_gymnast_user.py
index 7773987..6a6a82d 100644
--- a/src/people/migrations/0017_alter_gymnast_user.py
+++ b/khana/people/migrations/0017_alter_gymnast_user.py
@@ -9,14 +9,19 @@ class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
- ('people', '0016_auto_20210515_0800'),
+ ("people", "0016_auto_20210515_0800"),
]
operations = [
migrations.AlterField(
- model_name='gymnast',
- name='user',
- field=models.OneToOneField(default=1, on_delete=django.db.models.deletion.CASCADE, related_name='gymnast', to='auth.user'),
+ model_name="gymnast",
+ name="user",
+ field=models.OneToOneField(
+ default=1,
+ on_delete=django.db.models.deletion.CASCADE,
+ related_name="gymnast",
+ to="auth.user",
+ ),
preserve_default=False,
),
]
diff --git a/src/people/migrations/0018_auto_20210621_1804.py b/khana/people/migrations/0018_auto_20210621_1804.py
similarity index 51%
rename from src/people/migrations/0018_auto_20210621_1804.py
rename to khana/people/migrations/0018_auto_20210621_1804.py
index a3ae865..ca77a82 100644
--- a/src/people/migrations/0018_auto_20210621_1804.py
+++ b/khana/people/migrations/0018_auto_20210621_1804.py
@@ -6,18 +6,14 @@ from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
- ('people', '0017_alter_gymnast_user'),
+ ("people", "0017_alter_gymnast_user"),
]
operations = [
migrations.RenameField(
- model_name='gymnast',
- old_name='fedid',
- new_name='federation_id',
+ model_name="gymnast", old_name="fedid", new_name="federation_id",
),
migrations.RenameField(
- model_name='gymnast',
- old_name='have_routine',
- new_name='routine',
+ model_name="gymnast", old_name="have_routine", new_name="routine",
),
]
diff --git a/khana/people/migrations/0019_auto_20210621_1809.py b/khana/people/migrations/0019_auto_20210621_1809.py
new file mode 100644
index 0000000..74008b4
--- /dev/null
+++ b/khana/people/migrations/0019_auto_20210621_1809.py
@@ -0,0 +1,39 @@
+# Generated by Django 3.2.2 on 2021-06-21 18:09
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("people", "0018_auto_20210621_1804"),
+ ]
+
+ operations = [
+ migrations.RenameField(
+ model_name="gymnast", old_name="cando", new_name="can_do",
+ ),
+ migrations.RenameField(
+ model_name="gymnast",
+ old_name="email_father",
+ new_name="email_main_responsible",
+ ),
+ migrations.RenameField(
+ model_name="gymnast",
+ old_name="email_mother",
+ new_name="email_second_responsible",
+ ),
+ migrations.RenameField(
+ model_name="gymnast",
+ old_name="gsm_mother",
+ new_name="gsm_main_responsible",
+ ),
+ migrations.RenameField(
+ model_name="gymnast",
+ old_name="gsm_father",
+ new_name="gsm_second_responsible",
+ ),
+ migrations.RenameField(
+ model_name="gymnast", old_name="haveToDo", new_name="have_to_do",
+ ),
+ ]
diff --git a/src/people/templatetags/__init__.py b/khana/people/migrations/__init__.py
similarity index 100%
rename from src/people/templatetags/__init__.py
rename to khana/people/migrations/__init__.py
diff --git a/khana/people/models.py b/khana/people/models.py
new file mode 100644
index 0000000..c74e3d4
--- /dev/null
+++ b/khana/people/models.py
@@ -0,0 +1,346 @@
+"""Modélisation des gymnastes, accidents et relations à faire/faites.
+
+Notes:
+ Est-ce qu'il ne faudrait pas refactoriser les GSM père/mère ?
+ Avec une table d'association, et un champ qui indique la qualité du contact ?
+ Du coup, cela permettrait se débarasser des champs phone, gsm, gsm_father et gsm_mother.
+
+ Comment sont gérées les évolutions ? Changement de clubs, de fédération,
+
+ A quoi correspond le champ `year_of_practice` ?
+ Comment se comportera-t-il dans un an ? Dans deux ans ?
+ Est-ce qu'il ne faudrait pas une date de début, plutôt ?
+
+ Idem pour la méthode `actual_year_of_pratice`.
+ Comme elle se base sur le champ `created_at`, il suffit que l'enregistrement ne soit pas
+ réalisé correctement pour que la méthode retourne une mauvaise information.
+
+ Que signifie qu'un gymnaste soit actif ou inactif ? Est-ce que cela ne devrait pas plutôt
+ être géré au niveau des utilisateurs ?
+
+ Au niveau des utilisateurs, comme un User Django a déjà les champs lastname/firstname
+ pourquoi ne pas les réutiliser ? On garde la clé OneToOne, mais on déplace dans l'autre
+ classe les champs qui peuvent l'être. `Email` s'y retrouve également.
+
+ Les relations `cando`, `haveToDo` et `have_routine` ne sont pas correctement nommées.
+ Si tu as une instance de `Gymnast`, tu devrais faire ceci :
+
+ >>> gregg = Gymnast.objects.first()
+ >>> gregg.have_routine <-- pas bien
+ >>> gregg.routines <-- ok
+
+ Idéalement, cela pourrait même être une indirection.
+
+ >>> gregg.routines <-- retourne la relation de type `have_routine`
+ >>> gregg.educatives.can_do <-- retourne les éducatifs qu'il **peut** faire
+ >>> gregg.educatives.must_do <-- retourne les éducatifs qu'il **doit** faire
+ (j'avoue ne pas tout à fait comprendre la nuance entre les deux)
+
+ Tu as des fonctions qui ne sont pas du tout utilisées et qui pourrissent un peu le fichier.
+ >>> next_age() ? N'est appelé nulle part ailleurs.
+ >>> known_skills() <-- peut être récupéré directement via l'attribut `cando`
+ (du coup, tu as sans doute une piste de renommage ;-))
+"""
+
+from datetime import date
+
+from django.contrib.auth.models import User
+from django.db import models
+
+import pendulum
+
+from khana.base.models import Markdownizable
+
+
+class Gymnast(Markdownizable):
+ """Représente un gymnaste.
+
+ En plus de sa signalétique (nom, prénom, date de naissance, ...),
+ un gymnaste aura une photo et une orientation (de vrille).
+
+ Un gymnaste peut être actif ou inactif.
+ """
+
+ class Meta:
+ verbose_name = "Gymnast"
+ verbose_name_plural = "Gymnasts"
+ ordering = ["user__last_name", "user__first_name"]
+
+ GENDER_CHOICES = ((0, "Male"), (1, "Female"))
+ ORIENTATION_CHOICES = ((None, "Unknown"), (0, "Left"), (1, "Right"))
+
+ birthdate = models.DateField(verbose_name="Date de naissance")
+ gender = models.PositiveSmallIntegerField(
+ choices=GENDER_CHOICES, verbose_name="Sexe"
+ )
+ niss = models.CharField(max_length=11, null=True, blank=True)
+ address = models.CharField(max_length=255, null=True, blank=True)
+ postal = models.CharField(max_length=6, null=True, blank=True)
+ city = models.CharField(max_length=150, null=True, blank=True)
+ phone = models.CharField(max_length=9, null=True, blank=True, verbose_name="Phond")
+ gsm = models.CharField(max_length=10, null=True, blank=True)
+ federation_id = models.CharField(
+ max_length=10, null=True, blank=True, verbose_name="Federation ID"
+ )
+ gsm_main_responsible = models.CharField(
+ max_length=10, null=True, blank=True, verbose_name="GSM mère"
+ )
+ email_main_responsible = models.EmailField(max_length=255, null=True, blank=True)
+ gsm_second_responsible = models.CharField(
+ max_length=10, null=True, blank=True, verbose_name="GSM père"
+ )
+ email_second_responsible = models.EmailField(max_length=255, null=True, blank=True)
+ orientation = models.PositiveSmallIntegerField(
+ choices=ORIENTATION_CHOICES, null=True, blank=True, verbose_name="Twist side",
+ )
+ user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="gymnast")
+ trainer = models.ForeignKey(
+ User, null=True, on_delete=models.SET_NULL, related_name="gymnasts"
+ )
+ club = models.ForeignKey(
+ "location.Club", null=True, on_delete=models.SET_NULL, related_name="gymnasts"
+ )
+ can_do = models.ManyToManyField(
+ "objective.Educative",
+ through="CanDoRelation",
+ related_name="isdoneby", # related_name to change
+ )
+ have_to_do = models.ManyToManyField(
+ "objective.Educative",
+ through="ToDoRelation",
+ related_name="mustBeDoneBy", # related_name to change
+ )
+ routine = models.ManyToManyField(
+ "objective.Routine",
+ through="GymnastHasRoutine",
+ related_name="doneBy", # related_name to change
+ )
+ picture = models.ImageField(upload_to="gymnasts", null=True, blank=True)
+ year_of_practice = models.PositiveSmallIntegerField(default=0)
+ created_at = models.DateTimeField(auto_now_add=True)
+
+ def __str__(self):
+ return u"%s, %s" % (self.user.last_name, self.user.first_name)
+
+ @property
+ def next_birthday(self):
+ """Définit la prochaine date (de fête) d'anniversaire pour cette personne.
+
+ Returns:
+ Soit le jour/mois pour cette année
+ Soit le jour/mois pour l'année prochaine.
+
+ Examples: en supposant qu'on soit le 23/05/2019
+ >>> from datetime import date
+ >>> gregg = People(name='Tru', firstname='Gregg', birthdate=date(1982, 2, 5)
+ >>> gregg.next_birthday()
+ Date(2020, 2, 5)
+ """
+
+ now = pendulum.now()
+
+ this_year_birthday = pendulum.date(
+ now.year, self.birthdate.month, self.birthdate.day
+ )
+
+ if this_year_birthday.is_past():
+ return pendulum.date(now.year + 1, self.birthdate.month, self.birthdate.day)
+ return this_year_birthday
+
+ @property
+ def next_birthday_in_days(self):
+ now = pendulum.now()
+ return self.next_birthday.diff(now).in_days()
+
+ @property
+ def age(self):
+ """ Renvoie l'âge d'un gymnaste. """
+ today = date.today()
+ return (
+ today.year
+ - self.birthdate.year
+ - ((today.month, today.day) < (self.birthdate.month, self.birthdate.day))
+ )
+
+ @property
+ def next_age(self):
+ """ Renvoie l'âge prochain du gymnaste. """
+ return (self.age) + 1
+
+ @property
+ def known_skills(self):
+ """ Renvoie la liste des objectifs qu'un gymnaste sait faire. """
+ return CanDoRelation.objects.filter(gymnast=self.id)
+
+ @property
+ def actual_year_of_pratice(self):
+ """
+ Renvoie le nombre d'année de pratique du gymnaste en se basant sur le
+ nombre d'année qu'il avait déjà lors de son introduction dans le
+ système + le nombre d'année qu'il est dans le système.
+ """
+ period = pendulum.now() - pendulum.instance(self.created_at, "Europe/Brussels")
+ return int(self.year_of_practice + period.in_years())
+
+
+class Accident(Markdownizable):
+ """La classe `Accident` permet d'indiquer qu'un gymnaste est tombé durant un saut.
+ """
+
+ class Meta:
+ verbose_name = "Accident"
+ verbose_name_plural = "Accidents"
+ # ordering = ["date", "gymnast"]
+
+ gymnast = models.ForeignKey(
+ Gymnast,
+ verbose_name="Gymnast",
+ related_name="accident",
+ on_delete=models.CASCADE,
+ )
+ educative = models.ForeignKey(
+ "objective.Skill",
+ verbose_name="Skill",
+ related_name="accident",
+ on_delete=models.CASCADE,
+ )
+ date = models.DateField(verbose_name="Date")
+
+ def __str__(self):
+ return "%s, %s (%s)" % (
+ self.gymnast.lastname,
+ self.gymnast.firstname,
+ self.date,
+ )
+
+
+class CanDoRelation(models.Model):
+ """
+ Représente les objectifs qu'un gymnaste sait faire (à partir d'une date donnée).
+ """
+
+ class Meta:
+ verbose_name = "CanDo"
+ verbose_name_plural = "CanDos"
+ ordering = ["date", "educative", "gymnast"]
+ unique_together = ("gymnast", "educative")
+
+ # TO_FRED : puis-je avoir ton avis là-dessus ?
+ #
+ # JE VAIS INDIQUER QUE DES ELEVES SAVENT FAIRE DES FIGURES (SKILL)
+ #
+ #
+ # QUESTIONS
+ # ---------
+ #
+ # 1) Cela ne dervait pas être deux relations ManyToMany dans chacune des tables GYMNAST et EDUCATIVE (ou SKILL) ?
+ # Un élève saura faire plusieurs figures.
+ # Et une figure pourra savoir être faite par plusieurs élèves... Donc, ?
+ #
+ # 2) Dans un premier temps, même si je l'appelle EDUCATIVE mon champs, pour être pérenne,
+ # je n'associerai QUE des figures à un élève. Je voudrais donc, dans l'admin, que mon champs
+ # ne soit populer qu'avec les éléments de la table SKILL et non pas tous les éléments de la
+ # table EDUCATIVE.
+ gymnast = models.ForeignKey(
+ Gymnast,
+ verbose_name="Gymnast",
+ related_name="toObjective",
+ on_delete=models.CASCADE,
+ )
+ educative = models.ForeignKey(
+ "objective.Educative",
+ verbose_name="Skill",
+ related_name="cando",
+ on_delete=models.CASCADE,
+ )
+ date = models.DateField(default=date.today, verbose_name="Date")
+
+ def __str__(self):
+ return "%s, %s - %s" % (
+ self.gymnast.user.last_name,
+ self.gymnast.user.first_name,
+ self.educative.shortLabel,
+ )
+
+ @staticmethod
+ def create(gymnast, skill, linkdate):
+ c = CanDoRelation()
+ c.gymnast = gymnast
+ c.educative = skill
+ c.date = linkdate
+ c.save()
+ return c
+
+
+class ToDoRelation(models.Model):
+ """
+ Classe représentant les objectifs qu'une gymnaste devra savoir faire pour une date donnée.
+ """
+
+ class Meta:
+ verbose_name = "ToDo"
+ verbose_name_plural = "ToDos"
+ ordering = ["date", "educative", "gymnast"]
+ unique_together = ("gymnast", "educative")
+
+ gymnast = models.ForeignKey(
+ Gymnast, verbose_name="Gymnast", related_name="todo", on_delete=models.CASCADE
+ )
+ educative = models.ForeignKey(
+ "objective.Educative",
+ verbose_name="Skill",
+ related_name="isInToDo",
+ on_delete=models.CASCADE,
+ )
+ date = models.DateField(default=date.today, verbose_name="Date")
+
+ def __str__(self):
+ return "%s, %s - %s" % (
+ self.gymnast.lastname,
+ self.gymnast.firstname,
+ self.educative.shortLabel,
+ )
+
+
+class GymnastHasRoutine(models.Model):
+ """
+ Classe représentant le lien entre les gymnastes et leurs séries.
+ """
+
+ class Meta:
+ verbose_name = "Gymnast Has Routine"
+ verbose_name_plural = "Gymnast Has Routines"
+
+ ROUTINETYPE_CHOICE = (
+ (1, "L1"),
+ (2, "L2"),
+ (3, "L3"),
+ (4, "L4"),
+ (5, "L1S"),
+ (6, "L2S"),
+ (7, "L3S"),
+ (8, "L4S"),
+ )
+
+ gymnast = models.ForeignKey(
+ Gymnast,
+ verbose_name="Gymnast",
+ related_name="has_routine",
+ on_delete=models.CASCADE,
+ )
+ routine = models.ForeignKey(
+ "objective.Routine",
+ verbose_name="Routine",
+ related_name="used_by_gymnast",
+ on_delete=models.CASCADE,
+ )
+ routine_type = models.PositiveSmallIntegerField(
+ choices=ROUTINETYPE_CHOICE, verbose_name="Type", default="1"
+ )
+ datebegin = models.DateField(default=date.today, verbose_name="Date begin")
+ dateend = models.DateField(
+ default=date.today, verbose_name="Date end", null=True, blank=True
+ )
+
+ def __str__(self):
+ return "%s - %s : %s" % (self.gymnast, self.routine_type, self.routine)
diff --git a/src/planning/__init__.py b/khana/people/templatetags/__init__.py
similarity index 100%
rename from src/planning/__init__.py
rename to khana/people/templatetags/__init__.py
diff --git a/src/people/templatetags/accident.py b/khana/people/templatetags/accident.py
similarity index 100%
rename from src/people/templatetags/accident.py
rename to khana/people/templatetags/accident.py
diff --git a/src/people/templatetags/chrono.py b/khana/people/templatetags/chrono.py
similarity index 100%
rename from src/people/templatetags/chrono.py
rename to khana/people/templatetags/chrono.py
diff --git a/src/people/templatetags/event.py b/khana/people/templatetags/event.py
similarity index 100%
rename from src/people/templatetags/event.py
rename to khana/people/templatetags/event.py
diff --git a/src/people/templatetags/format.py b/khana/people/templatetags/format.py
similarity index 100%
rename from src/people/templatetags/format.py
rename to khana/people/templatetags/format.py
diff --git a/src/people/templatetags/plannification.py b/khana/people/templatetags/plannification.py
similarity index 100%
rename from src/people/templatetags/plannification.py
rename to khana/people/templatetags/plannification.py
diff --git a/src/people/templatetags/planning.py b/khana/people/templatetags/planning.py
similarity index 100%
rename from src/people/templatetags/planning.py
rename to khana/people/templatetags/planning.py
diff --git a/src/people/templatetags/routines.py b/khana/people/templatetags/routines.py
similarity index 100%
rename from src/people/templatetags/routines.py
rename to khana/people/templatetags/routines.py
diff --git a/src/people/templatetags/scores.py b/khana/people/templatetags/scores.py
similarity index 100%
rename from src/people/templatetags/scores.py
rename to khana/people/templatetags/scores.py
diff --git a/src/people/templatetags/statistics.py b/khana/people/templatetags/statistics.py
similarity index 100%
rename from src/people/templatetags/statistics.py
rename to khana/people/templatetags/statistics.py
diff --git a/src/people/templatetags/training.py b/khana/people/templatetags/training.py
similarity index 100%
rename from src/people/templatetags/training.py
rename to khana/people/templatetags/training.py
diff --git a/src/people/tests_models.py b/khana/people/tests_models.py
similarity index 62%
rename from src/people/tests_models.py
rename to khana/people/tests_models.py
index 3bb7587..f082b8d 100644
--- a/src/people/tests_models.py
+++ b/khana/people/tests_models.py
@@ -10,28 +10,47 @@ def test_gymnast_tostring():
g = Gymnast(lastname="Pauchou", firstname="Fred")
assert str(g) == "Pauchou, Fred"
+
def test_gymnaste_get_age():
- g = Gymnast(lastname="Pauchou", firstname="Fred", birthdate=datetime.strptime('03/07/1985', '%d/%m/%Y'));
+ g = Gymnast(
+ lastname="Pauchou",
+ firstname="Fred",
+ birthdate=datetime.strptime("03/07/1985", "%d/%m/%Y"),
+ )
assert g.age == 35
+
def test_gymnaste_get_next_age():
- g = Gymnast(lastname="Pauchou", firstname="Fred", birthdate=datetime.strptime('03/07/1985', '%d/%m/%Y'));
+ g = Gymnast(
+ lastname="Pauchou",
+ firstname="Fred",
+ birthdate=datetime.strptime("03/07/1985", "%d/%m/%Y"),
+ )
assert g.next_age == 36
+
def test_gymnaste_next_birthday():
- g = Gymnast(lastname="Pauchou", firstname="Fred", birthdate=datetime.strptime('03/07/1985', '%d/%m/%Y'));
- assert g.next_birthday == datetime.strptime('03/07/2021', '%d/%m/%Y')
+ g = Gymnast(
+ lastname="Pauchou",
+ firstname="Fred",
+ birthdate=datetime.strptime("03/07/1985", "%d/%m/%Y"),
+ )
+ assert g.next_birthday == datetime.strptime("03/07/2021", "%d/%m/%Y")
+
def test_gymnast_known_skills():
# @Fred : Comment tester cela ?
pass
+
def test_gymnast_actual_year_of_pratice():
# @Fred : Comment tester cela ?
pass
+
# class AccidentTestCase():
+
def test_accident_tostring():
timing = date.today()
g = Gymnast(lastname="Pauchou", firstname="Fred")
diff --git a/src/people/urls.py b/khana/people/urls.py
similarity index 100%
rename from src/people/urls.py
rename to khana/people/urls.py
diff --git a/src/people/views.py b/khana/people/views.py
similarity index 99%
rename from src/people/views.py
rename to khana/people/views.py
index c66d145..414f660 100644
--- a/src/people/views.py
+++ b/khana/people/views.py
@@ -29,7 +29,8 @@ def gymnast_listing(request):
if pattern:
gymnasts_list = Gymnast.objects.filter(
- Q(user__last_name__icontains=pattern) | Q(user__first_name__icontains=pattern)
+ Q(user__last_name__icontains=pattern)
+ | Q(user__first_name__icontains=pattern)
)
else:
gymnasts_list = Gymnast.objects.filter(user__is_active=True)
diff --git a/src/planning/ExpertSystem.md b/khana/planning/ExpertSystem.md
similarity index 100%
rename from src/planning/ExpertSystem.md
rename to khana/planning/ExpertSystem.md
diff --git a/src/planning/README.md b/khana/planning/README.md
similarity index 100%
rename from src/planning/README.md
rename to khana/planning/README.md
diff --git a/src/planning/migrations/__init__.py b/khana/planning/__init__.py
similarity index 100%
rename from src/planning/migrations/__init__.py
rename to khana/planning/__init__.py
diff --git a/src/planning/admin.py b/khana/planning/admin.py
similarity index 100%
rename from src/planning/admin.py
rename to khana/planning/admin.py
diff --git a/khana/planning/apps.py b/khana/planning/apps.py
new file mode 100644
index 0000000..37b04e1
--- /dev/null
+++ b/khana/planning/apps.py
@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class PlanningConfig(AppConfig):
+ name = "khana.planning"
diff --git a/src/planning/forms.py b/khana/planning/forms.py
similarity index 100%
rename from src/planning/forms.py
rename to khana/planning/forms.py
index 9d2efb4..89a80ae 100644
--- a/src/planning/forms.py
+++ b/khana/planning/forms.py
@@ -1,4 +1,3 @@
-
from datetime import date
from django import forms
@@ -7,6 +6,7 @@ from django.contrib.admin.widgets import FilteredSelectMultiple
from people.models import Gymnast
from .models import Unavailability, Event, PlanningLine
+
class UnavailabilityForm(forms.ModelForm):
class Meta:
model = Unavailability
diff --git a/src/planning/migrations/0001_initial.py b/khana/planning/migrations/0001_initial.py
similarity index 100%
rename from src/planning/migrations/0001_initial.py
rename to khana/planning/migrations/0001_initial.py
diff --git a/src/planning/migrations/0002_course_season.py b/khana/planning/migrations/0002_course_season.py
similarity index 100%
rename from src/planning/migrations/0002_course_season.py
rename to khana/planning/migrations/0002_course_season.py
diff --git a/src/planning/migrations/0003_auto_20190316_1857.py b/khana/planning/migrations/0003_auto_20190316_1857.py
similarity index 100%
rename from src/planning/migrations/0003_auto_20190316_1857.py
rename to khana/planning/migrations/0003_auto_20190316_1857.py
diff --git a/src/planning/migrations/0004_auto_20190317_0722.py b/khana/planning/migrations/0004_auto_20190317_0722.py
similarity index 100%
rename from src/planning/migrations/0004_auto_20190317_0722.py
rename to khana/planning/migrations/0004_auto_20190317_0722.py
diff --git a/src/planning/migrations/0005_auto_20190318_0855.py b/khana/planning/migrations/0005_auto_20190318_0855.py
similarity index 100%
rename from src/planning/migrations/0005_auto_20190318_0855.py
rename to khana/planning/migrations/0005_auto_20190318_0855.py
diff --git a/src/planning/migrations/0006_auto_20190321_1739.py b/khana/planning/migrations/0006_auto_20190321_1739.py
similarity index 100%
rename from src/planning/migrations/0006_auto_20190321_1739.py
rename to khana/planning/migrations/0006_auto_20190321_1739.py
diff --git a/src/planning/migrations/0007_round_is_important.py b/khana/planning/migrations/0007_round_is_important.py
similarity index 100%
rename from src/planning/migrations/0007_round_is_important.py
rename to khana/planning/migrations/0007_round_is_important.py
diff --git a/src/planning/migrations/0008_auto_20190402_2032.py b/khana/planning/migrations/0008_auto_20190402_2032.py
similarity index 100%
rename from src/planning/migrations/0008_auto_20190402_2032.py
rename to khana/planning/migrations/0008_auto_20190402_2032.py
diff --git a/src/planning/migrations/0009_auto_20190402_2035.py b/khana/planning/migrations/0009_auto_20190402_2035.py
similarity index 100%
rename from src/planning/migrations/0009_auto_20190402_2035.py
rename to khana/planning/migrations/0009_auto_20190402_2035.py
diff --git a/src/planning/migrations/0010_auto_20190512_1401.py b/khana/planning/migrations/0010_auto_20190512_1401.py
similarity index 100%
rename from src/planning/migrations/0010_auto_20190512_1401.py
rename to khana/planning/migrations/0010_auto_20190512_1401.py
diff --git a/src/planning/migrations/0011_auto_20190512_1428.py b/khana/planning/migrations/0011_auto_20190512_1428.py
similarity index 100%
rename from src/planning/migrations/0011_auto_20190512_1428.py
rename to khana/planning/migrations/0011_auto_20190512_1428.py
diff --git a/src/planning/migrations/0012_round_coachid.py b/khana/planning/migrations/0012_round_coachid.py
similarity index 100%
rename from src/planning/migrations/0012_round_coachid.py
rename to khana/planning/migrations/0012_round_coachid.py
diff --git a/src/planning/migrations/0013_auto_20190525_0524.py b/khana/planning/migrations/0013_auto_20190525_0524.py
similarity index 100%
rename from src/planning/migrations/0013_auto_20190525_0524.py
rename to khana/planning/migrations/0013_auto_20190525_0524.py
diff --git a/src/planning/migrations/0014_auto_20190525_0526.py b/khana/planning/migrations/0014_auto_20190525_0526.py
similarity index 100%
rename from src/planning/migrations/0014_auto_20190525_0526.py
rename to khana/planning/migrations/0014_auto_20190525_0526.py
diff --git a/src/planning/migrations/0015_auto_20190525_0606.py b/khana/planning/migrations/0015_auto_20190525_0606.py
similarity index 100%
rename from src/planning/migrations/0015_auto_20190525_0606.py
rename to khana/planning/migrations/0015_auto_20190525_0606.py
diff --git a/src/planning/migrations/0016_auto_20190525_1453.py b/khana/planning/migrations/0016_auto_20190525_1453.py
similarity index 100%
rename from src/planning/migrations/0016_auto_20190525_1453.py
rename to khana/planning/migrations/0016_auto_20190525_1453.py
diff --git a/src/planning/migrations/0017_auto_20190525_1544.py b/khana/planning/migrations/0017_auto_20190525_1544.py
similarity index 100%
rename from src/planning/migrations/0017_auto_20190525_1544.py
rename to khana/planning/migrations/0017_auto_20190525_1544.py
diff --git a/src/planning/migrations/0018_remove_event_gymnasts.py b/khana/planning/migrations/0018_remove_event_gymnasts.py
similarity index 100%
rename from src/planning/migrations/0018_remove_event_gymnasts.py
rename to khana/planning/migrations/0018_remove_event_gymnasts.py
diff --git a/src/planning/migrations/0019_event_participation.py b/khana/planning/migrations/0019_event_participation.py
similarity index 100%
rename from src/planning/migrations/0019_event_participation.py
rename to khana/planning/migrations/0019_event_participation.py
diff --git a/src/planning/migrations/0020_event_gymnasts.py b/khana/planning/migrations/0020_event_gymnasts.py
similarity index 100%
rename from src/planning/migrations/0020_event_gymnasts.py
rename to khana/planning/migrations/0020_event_gymnasts.py
diff --git a/khana/planning/migrations/0021_auto_20210513_1058.py b/khana/planning/migrations/0021_auto_20210513_1058.py
new file mode 100644
index 0000000..0986456
--- /dev/null
+++ b/khana/planning/migrations/0021_auto_20210513_1058.py
@@ -0,0 +1,33 @@
+# Generated by Django 3.2.2 on 2021-05-13 10:58
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("planning", "0020_event_gymnasts"),
+ ]
+
+ operations = [
+ migrations.RenameField(
+ model_name="course", old_name="information", new_name="content",
+ ),
+ migrations.RenameField(
+ model_name="event", old_name="information", new_name="content",
+ ),
+ migrations.RenameField(
+ model_name="planningline", old_name="information", new_name="content",
+ ),
+ migrations.RenameField(
+ model_name="round", old_name="information", new_name="content",
+ ),
+ migrations.RenameField(
+ model_name="unavailability", old_name="information", new_name="content",
+ ),
+ migrations.AlterField(
+ model_name="group",
+ name="season",
+ field=models.CharField(default="2021-2022", max_length=9),
+ ),
+ ]
diff --git a/src/planning/tests/__init__.py b/khana/planning/migrations/__init__.py
similarity index 100%
rename from src/planning/tests/__init__.py
rename to khana/planning/migrations/__init__.py
diff --git a/khana/planning/models.py b/khana/planning/models.py
new file mode 100644
index 0000000..ddabf7e
--- /dev/null
+++ b/khana/planning/models.py
@@ -0,0 +1,507 @@
+from datetime import datetime, date, time, timedelta
+
+from django.contrib.auth.models import User
+from django.db import models
+from django.utils import timezone
+
+import pendulum
+
+from khana.base.models import Markdownizable
+from khana.location.models import Club
+from khana.people.models import Gymnast
+
+
+def get_week(a_date):
+ """
+
+ Remarks:
+ Je ne comprends pas trop cette fonction...
+ Tu pars d'une date, et tu récupères le lundi et le samedi de la semaine correspondant ?
+ """
+ the_date = pendulum.parse(a_date)
+ day = the_date.weekday()
+ monday = the_date - timedelta(days=day)
+ sunday = the_date + timedelta(days=(6 - day))
+ return monday, sunday
+
+
+def get_number_of_weeks_between(start, stop):
+ """
+ Renvoie le nombre de semaines entre deux dates.
+ Par extension, cela permet de connaitre le nombre d'occurence d'un
+ évènement (entraînement, par exemple) hebdromadaire entre deux dates
+ et ainsi pouvoir plannifier.
+
+ :param start: date de début de la période
+ :type start: datetime.date
+ :param stop: date de fin de la période
+ :type stop: datetime.date
+ :return: Le nombre de semaines entre les deux dates.
+
+ Remarks:
+ Proposition d'utiliser isocalendar() sur une date.
+ L'indice 1 de la valeur de retour donne la semaine correspondant.
+
+ Eg.
+ >>> from datetime import date
+ >>> d = date(2020, 9, 27)
+ >>> d.isocalendar()
+ (2020, 39, 7)
+
+ -> Est-ce qu'il ne suffirait pas de faire la différence ?
+ """
+
+ tmp = stop - start
+ number_of_days = abs(tmp.days)
+ number_of_week = int((number_of_days + 1) / 7)
+
+ if ((number_of_days + 1) % 7) > 0:
+ number_of_week += 1
+
+ if tmp.days < 0:
+ number_of_week *= -1
+
+ return number_of_week
+
+
+class TemporizableQuerySet(models.QuerySet):
+ """
+ Classe permettant de spécifier le `QuerySet` de la classe `Temporizable`.
+ """
+
+ def next(self, limit):
+ """
+ Renvoie la liste des prochains "temporizable" (par rapport à la date du jour).
+
+ :param limit: nombre d'éléments désirés.
+ :type limit: int
+ :return: une liste de `limit` éléments temporizables.
+ """
+ return self.filter(datebegin__gte=timezone.now()).order_by("datebegin")[0:limit]
+
+ def last(self, limit):
+ """
+ Renvoie la liste des derniers "temporizable" (par rapport à la date du jour).
+
+ :param limit: nombre d'éléments désirés.
+ :type limit: int
+ :return: une liste de `limit` éléments temporizables
+ """
+ return self.filter(dateend__lte=timezone.now()).order_by("-dateend")[0:limit]
+
+ # def get(self, date_string):
+ # """
+ # """
+ # try:
+ # selected_object = self.get(datebegin__lte=date_string, dateend__gte=date_string)
+ # except self.DoesNotExist:
+ # return None
+ # except self.MultipleObjectsReturned:
+ # return None
+
+ # return selected_object
+
+
+class Temporizable(models.Model):
+ """Classe abstraite définissant une période comprise entre deux dates.
+
+ """
+
+ class Meta:
+ abstract = True
+
+ datebegin = models.DateTimeField(verbose_name="Début")
+ dateend = models.DateTimeField(blank=True, verbose_name="Fin")
+
+ objects = models.Manager.from_queryset(TemporizableQuerySet)()
+
+ def get_total_occurence(self):
+ """
+ Renvoie le nombre de semaines entre les deux dates d'une instance de la
+ classe `Temporizable`.
+
+ :return: nombre de semaines.
+ """
+ return get_number_of_weeks_between(self.datebegin.date(), self.dateend.date())
+
+ def get_number_of_occurence_to_event(self, the_date):
+ """
+ Renvoie le nombre semaines entre une date choisie et le début
+ (datebegin) d'une instance de la classe `Temporizable`.
+
+ :param the_date: date par rapport à laquelle le calcul sera fait.
+ :type the_date: datetime.date
+ :return: nombre de semaines.
+ """
+ return get_number_of_weeks_between(the_date, self.datebegin.date())
+
+ def get_number_of_occurence_inbetween(self, the_date, rest=True):
+ """
+ Renvoie le nombre semaines entre une date choisie et une instance de la
+ classe `Temporizable`. Le calcul peut se faire soit entre la date
+ choisie et le date de fin d'une occurence de la classe, soit entre la
+ date de début d'une occurence de la classe et la date choisie.
+
+ :param the_date: date par rapport à laquelle le calcul sera fait.
+ :type the_date: datetime.date
+ :param rest: paramètre définissant s'il faut calculer le reste des
+ occurences à venir (depuis `the_date` jusqu'à la date de fin) ou
+ les occurences déjà passées (depuis la date de début jusqu'à
+ `the_date`)
+ :type rest: booléen
+ :return: nombre de semaines.
+ """
+ if rest:
+ return get_number_of_weeks_between(the_date, self.dateend.date())
+ else:
+ return get_number_of_weeks_between(self.datebegin.date(), the_date)
+
+
+class Season(Temporizable):
+ """
+ Classe représentant une saison. Une saison est déinie par :
+ - un id,
+ - un label,
+ - une date de début et
+ - une date de fin.
+
+ La date de début est très souvent le : 01/09/xxxx
+ La date de fin est très souvent le : 31/08/xxxy
+ exemple : 1/9/2015 - 31/8/2016
+ """
+
+ class Meta:
+ verbose_name = "Season"
+ verbose_name_plural = "Seasons"
+
+ label = models.CharField(max_length=11, verbose_name="Label")
+ # active ou default = models.BooleanField(verbose_name='Défaut')
+
+ def __str__(self):
+ return "%s" % (self.label)
+
+ def week_number_from_begin(self, target_date):
+ return get_number_of_weeks_between(self.datebegin.date(), target_date)
+
+
+class EventType(models.Model):
+ """
+ Classe représentant les types d'évènements.
+ C'est un dictionnaire fini :
+ - compétiton qualificative,
+ - compétition finale,
+ - démonstration,
+ - …
+ """
+
+ class Meta:
+ verbose_name = "Event Type"
+ verbose_name_plural = "Event Types"
+
+ name = models.CharField(max_length=255, verbose_name="Nom")
+ acronym = models.CharField(max_length=5, verbose_name="Acronyme")
+
+ def __str__(self):
+ return "%s (%s)" % (self.name, self.acronym)
+
+
+class Event(Markdownizable, Temporizable):
+ """Classe représentant les évènements.
+
+ Un évènement est caractérisé par :
+ * un nom,
+ * un lieu (place),
+ * un type (compétition, démonstration, …),
+ * des gymnastes (participation prévue).
+ Je ne me rapelle plus à quoi sert le club.
+ """
+
+ class Meta:
+ verbose_name = "Event"
+ verbose_name_plural = "Event"
+
+ place = models.ForeignKey(
+ "location.Place", verbose_name="Lieu", on_delete=models.CASCADE, default=None
+ )
+ eventtype = models.ForeignKey(
+ EventType, verbose_name="Type", on_delete=models.CASCADE, default=None
+ )
+ name = models.CharField(max_length=255, verbose_name="Nom")
+ # club = models.ManyToManyField('location.Club', related_name="concernate_by", blank=True)
+ gymnasts = models.ManyToManyField(
+ "people.Gymnast",
+ through="Event_Participation",
+ related_name="participate_to",
+ verbose_name="Participants",
+ )
+
+ def __str__(self):
+ return "%s (à %s)" % (self.name, self.place.city)
+
+ def save(self, *args, **kwargs):
+ self.checkdates()
+ super().save(*args, **kwargs)
+
+ def checkdates(self):
+ """
+ Fonction assignant la date de fin d'un évènement à la date de début, si la date
+ de fin n'est pas définie, l'heure de fin est par défaut 18h00.
+ """
+ if self.dateend is None and self.datebegin is not None:
+ self.dateend = datetime.combine(self.datebegin.date(), time(18, 0))
+
+ @property
+ def number_of_week_from_today(self):
+ today = pendulum.now().date()
+ return get_number_of_weeks_between(today, self.datebegin.date())
+
+
+class Event_Participation(models.Model):
+ """
+ """
+
+ event = models.ForeignKey(Event, on_delete=models.CASCADE)
+ gymnast = models.ForeignKey("people.Gymnast", on_delete=models.CASCADE)
+ rank = models.PositiveSmallIntegerField(default=0)
+
+
+class Course(Markdownizable, Temporizable):
+ """Classe représentant les cours.
+
+ Un cours est défini par :
+ * une heure de début et une heure de fin,
+ * une date de début et une date de fin (un cours est considéré comme donné hebdromadairement entre
+ ces deux dates) (hérite de la classe `Temporizable`)
+ * est associé à un ou plusieurs entraineurs,
+ * est associé à un club
+ * est associé à un jour de la semaine (numéro du jour dans la semaine : 0 = lundi, 6 = dimanche).
+ """
+
+ class Meta:
+ verbose_name = "Course"
+ verbose_name_plural = "Courses"
+
+ DAY_CHOICE = (
+ (1, "Lundi"),
+ (2, "Mardi"),
+ (3, "Mercredi"),
+ (4, "Jeudi"),
+ (5, "Vendredi"),
+ (6, "Samedi"),
+ (7, "Dimanche"),
+ )
+
+ club = models.ForeignKey(
+ "location.Club", verbose_name="Club", on_delete=models.CASCADE, default=None
+ )
+ iso_day_number = models.PositiveSmallIntegerField(
+ choices=DAY_CHOICE, verbose_name="Jour"
+ )
+ hour_begin = models.TimeField(verbose_name="Heure de début")
+ hour_end = models.TimeField(verbose_name="Heure de fin")
+ season = models.ForeignKey(Season, on_delete=models.SET_NULL, null=True)
+ trainers = models.ManyToManyField(
+ User, verbose_name="Coach(es)", related_name="trainee"
+ )
+ gymnasts = models.ManyToManyField(
+ Gymnast, verbose_name="Gymnasts", related_name="courses"
+ )
+
+ def __str__(self):
+ return "%s (%s à %s)" % (
+ self.get_iso_day_number_display(),
+ self.hour_begin.strftime("%H:%M"),
+ self.hour_end.strftime("%H:%M"),
+ )
+
+ @property
+ def duration(self):
+ """
+ Renvoie la durée d'un cours en heures
+ """
+ date_begin = pendulum.datetime(
+ 2000, 1, 1, self.hour_begin.hour, self.hour_begin.minute
+ )
+ date_end = pendulum.datetime(
+ 2000, 1, 1, self.hour_end.hour, self.hour_end.minute
+ )
+ return date_end.diff(date_begin).in_hours()
+
+
+class Group(models.Model):
+ """Classe représentant les groupes (Loisir, D1, D2, A, B, …).
+
+ Un groupe appartient à un club.
+ """
+
+ class Meta:
+ verbose_name = "Group"
+ verbose_name_plural = "Groups"
+
+ club = models.ForeignKey("location.Club", on_delete=models.CASCADE, default=None)
+ name = models.CharField(max_length=255)
+ acronym = models.CharField(max_length=50)
+ active = models.BooleanField(default=1)
+ season = models.CharField(
+ max_length=9,
+ default=str(timezone.now().year) + "-" + str(timezone.now().year + 1),
+ )
+
+ def __str__(self):
+ return "%s (%s)" % (self.name, self.acronym)
+
+
+class Subgroup(models.Model):
+ """Classe représentant les sous-groupes.
+
+ Un sous-groupe appartient à un groupe (lui-même lié à un club).
+
+ De cette manière, quand un gymnaste est mis dans un sous-groupe, en remontant via le groupe,
+ nous pouvons connaître le(s) club(s) du gymnaste pour chaque saison.
+ """
+
+ class Meta:
+ verbose_name = "Subgroup"
+ verbose_name_plural = "Subgroups"
+
+ name = models.CharField(max_length=255)
+ acronym = models.CharField(max_length=50)
+ group = models.ForeignKey(Group, on_delete=models.CASCADE, default=None)
+ courses = models.ManyToManyField(Course, related_name="to_subgroup")
+ gymnasts = models.ManyToManyField(
+ "people.Gymnast", related_name="to_gym", blank=True
+ )
+ active = models.BooleanField(default=1)
+
+ def __str__(self):
+ return "%s (%s)" % (self.name, self.group.name)
+
+
+class UnavailabilityManager(models.Manager):
+ """Classe représentant le manager de la classe `Unavailability`.
+ """
+
+ def next(self, count):
+ return self.filter(datebegin__gte=timezone.now()).order_by("datebegin")[0:count]
+
+ def last(self, count):
+ return self.filter(dateend__lte=timezone.now()).order_by("-dateend")[0:count]
+
+
+class Unavailability(Markdownizable, Temporizable):
+ """Classe représentant les indisponibilités.
+ """
+
+ class Meta:
+ verbose_name = "Indisponibilité"
+ verbose_name_plural = "Indisponibilités"
+
+ course = models.ManyToManyField(Course, related_name="unavailability")
+
+ objects = UnavailabilityManager()
+
+ def __str__(self):
+ return "du %s au %s" % (self.datebegin, self.dateend)
+
+ def save(self, *args, **kwargs):
+ self.checkdates()
+
+ super().save(*args, **kwargs)
+
+ def checkdates(self):
+ if self.dateend is None and self.datebegin is not None:
+ self.dateend = self.datebegin
+
+
+class Training(models.Model):
+ """Classe représentant les entraînements.
+
+ Un entraînement est une occurence d'un cours pendant lequel des gmnastes sont présents.
+
+ Un objet de cette classe lie donc un cours et un gymnaste à une date donnée.
+ """
+
+ class Meta:
+ verbose_name = "Training"
+ verbose_name_plural = "Trainings"
+
+ gymnast = models.ForeignKey(
+ "people.Gymnast",
+ verbose_name="Gymnast",
+ on_delete=models.CASCADE,
+ default=None,
+ related_name="trainings",
+ )
+ course = models.ForeignKey(
+ Course, verbose_name="Course", on_delete=models.CASCADE, default=None
+ )
+ trainingdate = models.DateField(verbose_name="Date")
+
+ def __str__(self):
+ return "%s - %s, %s" % (self.trainingdate, self.course, self.gymnast)
+
+ @staticmethod
+ def create(gymnast, course, trainingdate):
+ t = Training()
+ t.gymnast = gymnast
+ t.course = course
+ t.trainingdate = trainingdate
+ t.save()
+ return t
+
+
+class Round(Markdownizable):
+ """Classe représentant les passages des élèves lors d'un entrainement.
+
+ Chaque record représente un passage. Il est donc lié à un record de la classe `Training`.
+ """
+
+ class Meta:
+ verbose_name = "Round"
+ verbose_name_plural = "Rounds"
+
+ EVALUATION_CHOICES = (
+ (0, "- -"),
+ (1, "- +"),
+ (2, "+ -"),
+ (3, "+ +"),
+ )
+
+ training = models.ForeignKey(
+ Training, on_delete=models.CASCADE, default=None, related_name="rounds"
+ )
+ educative = models.ForeignKey(
+ "objective.Educative",
+ on_delete=models.CASCADE,
+ default=None,
+ blank=True,
+ null=True,
+ )
+ round_information = models.CharField(max_length=255, blank=True, null=True)
+ round_number = models.PositiveSmallIntegerField(blank=True, null=True)
+ gymnast_evaluation = models.PositiveSmallIntegerField(
+ choices=EVALUATION_CHOICES, blank=True, null=True
+ )
+ coach_evaluation = models.PositiveSmallIntegerField(blank=True, null=True)
+ coachid = models.ForeignKey(User, blank=True, null=True, on_delete=models.SET_NULL)
+ nb_of_realisation = models.PositiveSmallIntegerField(blank=True, null=True)
+ nb_of_success = models.PositiveSmallIntegerField(blank=True, null=True)
+ is_important = models.BooleanField(default=False)
+
+ def __str__(self):
+ return "%s" % (self.round_number)
+
+
+class PlanningLine(Markdownizable):
+ """Classe représentant les passages prévisionnels (incubating idea).
+ """
+
+ class Meta:
+ verbose_name = "Planning Line"
+ verbose_name_plural = "Planning lines"
+ # ordering = ['gymnast', 'date', 'order']
+
+ gymnast = models.ForeignKey(Gymnast, on_delete=models.CASCADE, default=None)
+ date = models.DateField(verbose_name="Date")
+ order = models.PositiveSmallIntegerField()
+ todo = models.CharField(max_length=255)
diff --git a/src/profile/__init__.py b/khana/planning/tests/__init__.py
similarity index 100%
rename from src/profile/__init__.py
rename to khana/planning/tests/__init__.py
diff --git a/src/planning/tests/tests_models.py b/khana/planning/tests/tests_models.py
similarity index 99%
rename from src/planning/tests/tests_models.py
rename to khana/planning/tests/tests_models.py
index 3416ed2..202bed7 100644
--- a/src/planning/tests/tests_models.py
+++ b/khana/planning/tests/tests_models.py
@@ -1,4 +1,3 @@
-
from datetime import datetime
from django.test import TestCase
from ..models import get_number_of_weeks_between, Season
diff --git a/src/planning/urls.py b/khana/planning/urls.py
similarity index 99%
rename from src/planning/urls.py
rename to khana/planning/urls.py
index 73400a7..9cde8bf 100644
--- a/src/planning/urls.py
+++ b/khana/planning/urls.py
@@ -1,4 +1,3 @@
-
from django.urls import path, re_path
from . import views
diff --git a/src/planning/views.py b/khana/planning/views.py
similarity index 99%
rename from src/planning/views.py
rename to khana/planning/views.py
index 2fdd02c..72bc178 100644
--- a/src/planning/views.py
+++ b/khana/planning/views.py
@@ -1,4 +1,3 @@
-
from django.shortcuts import render, get_object_or_404
from django.http import (
HttpResponseRedirect,
@@ -82,8 +81,6 @@ def event_create_or_update(request, eventid=None):
complètement le GET du POST.
"""
-
-
if request.method == "POST":
form = EventForm(request.POST, instance=event)
@@ -1302,7 +1299,7 @@ def planningline_update(request, planninglineid=None):
else:
form = PlanningLineForm(
initial={
- "gymnast": planningline.gymnast.id,
+ "gymnast": planningline.gymnast.id,
"gymnast_related": planningline.gymnast,
"date": planningline.date,
"order": planningline.order,
diff --git a/src/profile/migrations/__init__.py b/khana/profile/__init__.py
similarity index 100%
rename from src/profile/migrations/__init__.py
rename to khana/profile/__init__.py
diff --git a/src/profile/admin.py b/khana/profile/admin.py
similarity index 100%
rename from src/profile/admin.py
rename to khana/profile/admin.py
diff --git a/src/profile/apps.py b/khana/profile/apps.py
similarity index 71%
rename from src/profile/apps.py
rename to khana/profile/apps.py
index 9c0b232..e48706e 100644
--- a/src/profile/apps.py
+++ b/khana/profile/apps.py
@@ -2,4 +2,4 @@ from django.apps import AppConfig
class ProfileConfig(AppConfig):
- name = "profile"
+ name = "khana.profile"
diff --git a/src/profile/forms.py b/khana/profile/forms.py
similarity index 100%
rename from src/profile/forms.py
rename to khana/profile/forms.py
diff --git a/src/profile/migrations/0001_initial.py b/khana/profile/migrations/0001_initial.py
similarity index 100%
rename from src/profile/migrations/0001_initial.py
rename to khana/profile/migrations/0001_initial.py
diff --git a/src/profile/migrations/0002_auto_20190321_1739.py b/khana/profile/migrations/0002_auto_20190321_1739.py
similarity index 100%
rename from src/profile/migrations/0002_auto_20190321_1739.py
rename to khana/profile/migrations/0002_auto_20190321_1739.py
diff --git a/src/profile/migrations/0003_auto_20190330_0920.py b/khana/profile/migrations/0003_auto_20190330_0920.py
similarity index 100%
rename from src/profile/migrations/0003_auto_20190330_0920.py
rename to khana/profile/migrations/0003_auto_20190330_0920.py
diff --git a/src/profile/migrations/0004_auto_20190402_2032.py b/khana/profile/migrations/0004_auto_20190402_2032.py
similarity index 100%
rename from src/profile/migrations/0004_auto_20190402_2032.py
rename to khana/profile/migrations/0004_auto_20190402_2032.py
diff --git a/src/profile/migrations/0005_auto_20190402_2035.py b/khana/profile/migrations/0005_auto_20190402_2035.py
similarity index 100%
rename from src/profile/migrations/0005_auto_20190402_2035.py
rename to khana/profile/migrations/0005_auto_20190402_2035.py
diff --git a/src/profile/migrations/0006_profile_picture.py b/khana/profile/migrations/0006_profile_picture.py
similarity index 100%
rename from src/profile/migrations/0006_profile_picture.py
rename to khana/profile/migrations/0006_profile_picture.py
diff --git a/src/profile/migrations/0007_auto_20190413_1014.py b/khana/profile/migrations/0007_auto_20190413_1014.py
similarity index 100%
rename from src/profile/migrations/0007_auto_20190413_1014.py
rename to khana/profile/migrations/0007_auto_20190413_1014.py
diff --git a/src/profile/migrations/0008_profile_is_sidebar_minified.py b/khana/profile/migrations/0008_profile_is_sidebar_minified.py
similarity index 100%
rename from src/profile/migrations/0008_profile_is_sidebar_minified.py
rename to khana/profile/migrations/0008_profile_is_sidebar_minified.py
diff --git a/src/tools/__init__.py b/khana/profile/migrations/__init__.py
similarity index 100%
rename from src/tools/__init__.py
rename to khana/profile/migrations/__init__.py
diff --git a/src/profile/models.py b/khana/profile/models.py
similarity index 100%
rename from src/profile/models.py
rename to khana/profile/models.py
diff --git a/src/profile/urls.py b/khana/profile/urls.py
similarity index 100%
rename from src/profile/urls.py
rename to khana/profile/urls.py
diff --git a/src/profile/views.py b/khana/profile/views.py
similarity index 98%
rename from src/profile/views.py
rename to khana/profile/views.py
index 0cb8af9..ef90c6b 100644
--- a/src/profile/views.py
+++ b/khana/profile/views.py
@@ -82,5 +82,7 @@ def profile_update(request):
else:
form = ProfileForm(instance=profile)
- context = {"form": form,}
+ context = {
+ "form": form,
+ }
return render(request, "profile_create.html", context)
diff --git a/src/tools/templatetags/__init__.py b/khana/tools/__init__.py
similarity index 100%
rename from src/tools/templatetags/__init__.py
rename to khana/tools/__init__.py
diff --git a/khana/tools/templatetags/__init__.py b/khana/tools/templatetags/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/src/tools/templatetags/menuitems.py b/khana/tools/templatetags/menuitems.py
similarity index 100%
rename from src/tools/templatetags/menuitems.py
rename to khana/tools/templatetags/menuitems.py
diff --git a/src/manage.py b/manage.py
similarity index 71%
rename from src/manage.py
rename to manage.py
index 87919cc..5ec273e 100755
--- a/src/manage.py
+++ b/manage.py
@@ -3,7 +3,7 @@ import os
import sys
if __name__ == "__main__":
- os.environ.setdefault("DJANGO_SETTINGS_MODULE", "khana.settings")
+ os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings")
from django.core.management import execute_from_command_line
diff --git a/src/pytest.ini b/pytest.ini
similarity index 100%
rename from src/pytest.ini
rename to pytest.ini
diff --git a/src/Makefile b/src/Makefile
deleted file mode 100644
index 85222af..0000000
--- a/src/Makefile
+++ /dev/null
@@ -1,192 +0,0 @@
-# Makefile for Sphinx documentation
-#
-
-# You can set these variables from the command line.
-SPHINXOPTS =
-SPHINXBUILD = sphinx-build
-PAPER =
-BUILDDIR = build
-
-# User-friendly check for sphinx-build
-ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
-$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
-endif
-
-# Internal variables.
-PAPEROPT_a4 = -D latex_paper_size=a4
-PAPEROPT_letter = -D latex_paper_size=letter
-ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
-# the i18n builder cannot share the environment and doctrees with the others
-I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
-
-.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext
-
-help:
- @echo "Please use \`make ' where is one of"
- @echo " html to make standalone HTML files"
- @echo " dirhtml to make HTML files named index.html in directories"
- @echo " singlehtml to make a single large HTML file"
- @echo " pickle to make pickle files"
- @echo " json to make JSON files"
- @echo " htmlhelp to make HTML files and a HTML help project"
- @echo " qthelp to make HTML files and a qthelp project"
- @echo " applehelp to make an Apple Help Book"
- @echo " devhelp to make HTML files and a Devhelp project"
- @echo " epub to make an epub"
- @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
- @echo " latexpdf to make LaTeX files and run them through pdflatex"
- @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
- @echo " text to make text files"
- @echo " man to make manual pages"
- @echo " texinfo to make Texinfo files"
- @echo " info to make Texinfo files and run them through makeinfo"
- @echo " gettext to make PO message catalogs"
- @echo " changes to make an overview of all changed/added/deprecated items"
- @echo " xml to make Docutils-native XML files"
- @echo " pseudoxml to make pseudoxml-XML files for display purposes"
- @echo " linkcheck to check all external links for integrity"
- @echo " doctest to run all doctests embedded in the documentation (if enabled)"
- @echo " coverage to run coverage check of the documentation (if enabled)"
-
-clean:
- rm -rf $(BUILDDIR)/*
-
-html:
- $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
- @echo
- @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
-
-dirhtml:
- $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
- @echo
- @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
-
-singlehtml:
- $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
- @echo
- @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
-
-pickle:
- $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
- @echo
- @echo "Build finished; now you can process the pickle files."
-
-json:
- $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
- @echo
- @echo "Build finished; now you can process the JSON files."
-
-htmlhelp:
- $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
- @echo
- @echo "Build finished; now you can run HTML Help Workshop with the" \
- ".hhp project file in $(BUILDDIR)/htmlhelp."
-
-qthelp:
- $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
- @echo
- @echo "Build finished; now you can run "qcollectiongenerator" with the" \
- ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
- @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Khana.qhcp"
- @echo "To view the help file:"
- @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Khana.qhc"
-
-applehelp:
- $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
- @echo
- @echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
- @echo "N.B. You won't be able to view it unless you put it in" \
- "~/Library/Documentation/Help or install it in your application" \
- "bundle."
-
-devhelp:
- $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
- @echo
- @echo "Build finished."
- @echo "To view the help file:"
- @echo "# mkdir -p $$HOME/.local/share/devhelp/Khana"
- @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Khana"
- @echo "# devhelp"
-
-epub:
- $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
- @echo
- @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
-
-latex:
- $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
- @echo
- @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
- @echo "Run \`make' in that directory to run these through (pdf)latex" \
- "(use \`make latexpdf' here to do that automatically)."
-
-latexpdf:
- $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
- @echo "Running LaTeX files through pdflatex..."
- $(MAKE) -C $(BUILDDIR)/latex all-pdf
- @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
-
-latexpdfja:
- $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
- @echo "Running LaTeX files through platex and dvipdfmx..."
- $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
- @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
-
-text:
- $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
- @echo
- @echo "Build finished. The text files are in $(BUILDDIR)/text."
-
-man:
- $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
- @echo
- @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
-
-texinfo:
- $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
- @echo
- @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
- @echo "Run \`make' in that directory to run these through makeinfo" \
- "(use \`make info' here to do that automatically)."
-
-info:
- $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
- @echo "Running Texinfo files through makeinfo..."
- make -C $(BUILDDIR)/texinfo info
- @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
-
-gettext:
- $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
- @echo
- @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
-
-changes:
- $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
- @echo
- @echo "The overview file is in $(BUILDDIR)/changes."
-
-linkcheck:
- $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
- @echo
- @echo "Link check complete; look for any errors in the above output " \
- "or in $(BUILDDIR)/linkcheck/output.txt."
-
-doctest:
- $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
- @echo "Testing of doctests in the sources finished, look at the " \
- "results in $(BUILDDIR)/doctest/output.txt."
-
-coverage:
- $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
- @echo "Testing of coverage in the sources finished, look at the " \
- "results in $(BUILDDIR)/coverage/python.txt."
-
-xml:
- $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
- @echo
- @echo "Build finished. The XML files are in $(BUILDDIR)/xml."
-
-pseudoxml:
- $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
- @echo
- @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
diff --git a/src/communication/migrations/0003_auto_20210513_1058.py b/src/communication/migrations/0003_auto_20210513_1058.py
deleted file mode 100644
index 32937c0..0000000
--- a/src/communication/migrations/0003_auto_20210513_1058.py
+++ /dev/null
@@ -1,65 +0,0 @@
-# Generated by Django 3.2.2 on 2021-05-13 10:58
-
-from django.conf import settings
-from django.db import migrations, models
-import django.db.models.deletion
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- migrations.swappable_dependency(settings.AUTH_USER_MODEL),
- ('communication', '0002_auto_20190413_1028'),
- ]
-
- operations = [
- migrations.RenameField(
- model_name='message',
- old_name='message_body',
- new_name='body',
- ),
- migrations.RenameField(
- model_name='message',
- old_name='date_of_reading',
- new_name='read_at',
- ),
- migrations.RenameField(
- model_name='message',
- old_name='message_title',
- new_name='title',
- ),
- migrations.RenameField(
- model_name='message',
- old_name='date_of_writing',
- new_name='written_at',
- ),
- migrations.RemoveField(
- model_name='message',
- name='is_read',
- ),
- migrations.RemoveField(
- model_name='message',
- name='reader',
- ),
- migrations.RemoveField(
- model_name='message',
- name='writer',
- ),
- migrations.AddField(
- model_name='message',
- name='content',
- field=models.TextField(blank=True, help_text='Seul le MarkDown simple est accepté', null=True, verbose_name='Comments'),
- ),
- migrations.AddField(
- model_name='message',
- name='recipient',
- field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, related_name='received_messages', to='auth.user'),
- preserve_default=False,
- ),
- migrations.AddField(
- model_name='message',
- name='sender',
- field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, related_name='sent_messages', to='auth.user'),
- preserve_default=False,
- ),
- ]
diff --git a/src/communication/views.py b/src/communication/views.py
deleted file mode 100644
index 0f726b0..0000000
--- a/src/communication/views.py
+++ /dev/null
@@ -1,89 +0,0 @@
-"""Vues et fonctions pour tout ce qui touche à la communication entre plusieurs utilisateurs."""
-
-from datetime import datetime
-
-from django.contrib.auth.decorators import login_required
-from django.http import HttpResponse, HttpResponseRedirect
-from django.shortcuts import render, get_object_or_404
-from django.views.decorators.http import require_http_methods
-from django.urls import reverse
-
-from .forms import MessageForm
-from .models import Message
-
-
-
-@login_required
-def get_number_of_unread_message(request):
- """Récupère le nombre de messages non lus associés à l'utilisateur en session.
- """
- return Message.objects.filter(recipient=request.user).filter(read_at__isnull=True).count()
-
-
-@login_required
-@require_http_methods(["GET"])
-def get_received_messages(request):
- """Récupère des messages recus pour l'utilisateur connecté.
- """
- return request.user.received_messages.all()
-
-
-@login_required
-@require_http_methods(["GET"])
-def get_sent_messages(request):
- """Récupère des messages envoyés par l'utilisateur connecté.
- """
- return request.user.sent_messages.all()
-
-
-@login_required
-@require_http_methods(["GET"])
-def get_message_details(request, messageid):
- """Récupère les détails (l'affichage ?) d'un message.
- """
- message = get_object_or_404(Message, pk=messageid)
- if not message.read_at and message.recipient == request.user.id:
- message.read_at = datetime.now()
- message.save()
-
- context = {"message": message, "type": None}
- return render(request, "message_details.html", context)
-
-
-@login_required
-@require_http_methods(["POST"])
-def delete_message(request, messageid):
- """Supprime le message dont la clé est passée en paramètre.
- """
- try:
- message = Message.objects.get(pk=messageid)
-
- if message.sender == request.user or message.recipient == request.user :
- message.delete()
- else:
- return HttpResponse(401)
- except:
- return HttpResponse(400)
-
- return HttpResponse(200)
-
-
-@login_required
-@require_http_methods(["GET", "POST"])
-def compose_message(request):
- """Permet à l'utilisateur connecté de rédiger un nouveau message.
- """
-
- if request.method == "POST":
- form = MessageForm(request.POST)
-
- if form.is_valid():
- form.save()
- return HttpResponseRedirect(reverse("sent_messages"))
-
- print("Invalid form")
- else:
- form = MessageForm()
-
- context = {"form": form, "writer": request.user.id}
- return render(request, "message_create.html", context)
diff --git a/src/media/Lucasljpg b/src/media/Lucasljpg
deleted file mode 100644
index 9281951..0000000
Binary files a/src/media/Lucasljpg and /dev/null differ
diff --git a/src/media/Nell_blog.jpg b/src/media/Nell_blog.jpg
deleted file mode 100644
index ce6eba5..0000000
Binary files a/src/media/Nell_blog.jpg and /dev/null differ
diff --git a/src/media/image.jpeg b/src/media/image.jpeg
deleted file mode 100644
index 58db042..0000000
Binary files a/src/media/image.jpeg and /dev/null differ
diff --git a/src/media/image_JjsR0hO.jpeg b/src/media/image_JjsR0hO.jpeg
deleted file mode 100644
index 041ee75..0000000
Binary files a/src/media/image_JjsR0hO.jpeg and /dev/null differ
diff --git a/src/media/image_p95XIFd.jpeg b/src/media/image_p95XIFd.jpeg
deleted file mode 100644
index d00f8f9..0000000
Binary files a/src/media/image_p95XIFd.jpeg and /dev/null differ
diff --git a/src/media/noelia.jpg b/src/media/noelia.jpg
deleted file mode 100644
index 5230bd4..0000000
Binary files a/src/media/noelia.jpg and /dev/null differ
diff --git a/src/objective/migrations/0017_auto_20210620_1618.py b/src/objective/migrations/0017_auto_20210620_1618.py
deleted file mode 100644
index c704b3f..0000000
--- a/src/objective/migrations/0017_auto_20210620_1618.py
+++ /dev/null
@@ -1,85 +0,0 @@
-# Generated by Django 3.2.2 on 2021-06-20 16:18
-
-from django.db import migrations
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('objective', '0016_rename_information_educative_content'),
- ]
-
- operations = [
- migrations.RenameModel(
- old_name='Routine_Skill',
- new_name='RoutineSkill',
- ),
- migrations.AlterModelOptions(
- name='educative',
- options={'ordering': ['label', 'short_label'], 'verbose_name': 'Educatif', 'verbose_name_plural': 'Educatifs'},
- ),
- migrations.AlterModelOptions(
- name='touchposition',
- options={'ordering': ['label', 'short_label', 'is_default', 'allowed_in_competition'], 'verbose_name': 'Landing', 'verbose_name_plural': 'Landings'},
- ),
- migrations.RenameField(
- model_name='educative',
- old_name='ageBoy',
- new_name='age_boy',
- ),
- migrations.RenameField(
- model_name='educative',
- old_name='ageGirl',
- new_name='age_girl',
- ),
- migrations.RenameField(
- model_name='educative',
- old_name='educative',
- new_name='educatives',
- ),
- migrations.RenameField(
- model_name='educative',
- old_name='longLabel',
- new_name='label',
- ),
- migrations.RenameField(
- model_name='educative',
- old_name='prerequisite',
- new_name='prerequisites',
- ),
- migrations.RenameField(
- model_name='educative',
- old_name='shortLabel',
- new_name='short_label',
- ),
- migrations.RenameField(
- model_name='skill',
- old_name='rotationType',
- new_name='rotation_type',
- ),
- migrations.RenameField(
- model_name='skill',
- old_name='simplyNotation',
- new_name='simplified_notation',
- ),
- migrations.RenameField(
- model_name='touchposition',
- old_name='competition',
- new_name='allowed_in_competition',
- ),
- migrations.RenameField(
- model_name='touchposition',
- old_name='default',
- new_name='is_default',
- ),
- migrations.RenameField(
- model_name='touchposition',
- old_name='longLabel',
- new_name='label',
- ),
- migrations.RenameField(
- model_name='touchposition',
- old_name='shortLabel',
- new_name='short_label',
- ),
- ]
diff --git a/src/people/admin.py b/src/people/admin.py
deleted file mode 100644
index 2c6c21e..0000000
--- a/src/people/admin.py
+++ /dev/null
@@ -1,126 +0,0 @@
-"""Administration des gymnastes et des personnes.
-
-Remarks:
- * Je ne pense pas qu'il faille encore passer par `ForeignKeyAutocompleteAdmin`.
- https://docs.djangoproject.com/fr/3.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin.autocomplete_fields
-"""
-
-from django.contrib import admin
-
-from django_extensions.admin import ForeignKeyAutocompleteAdmin
-
-from .models import (
- Gymnast,
- Accident,
- CanDoRelation,
- ToDoRelation,
- GymnastHasRoutine,
-)
-
-class CanDoRelationAdmin(ForeignKeyAutocompleteAdmin):
- model = CanDoRelation
-
- list_display = ("date", "gymnast", "educative")
- list_filter = ("gymnast",)
- search_fields = ("gymnast", "educative")
- autocomplete_fields = ("gymnast",)
-
- # related_search_fields = {
- # 'gymnast': ('lastname', 'firstname'),
- # }
-
-
-class InlineCanDoRelation(admin.TabularInline):
- model = CanDoRelation
-
-
-class ToDoRelationAdmin(ForeignKeyAutocompleteAdmin):
- model = ToDoRelation
-
- list_display = ("date", "gymnast", "educative")
- list_filter = ("gymnast",)
- search_fields = ("gymnast", "educative")
- autocomplete_fields = ("gymnast",)
-
- # related_search_fields = {
- # 'gymnast': ('lastname', 'firstname'),
- # # 'educative': ('longLabel', 'shortLabel'), # TO_FRED : Pq ca marche pas ca ?
- # }
-
-
-class GymnastHasRoutineAdmin(ForeignKeyAutocompleteAdmin):
- model = GymnastHasRoutine
-
- list_display = ("gymnast", "routine", "routine_type", "datebegin", "dateend")
- list_filter = ("gymnast", "routine_type")
- search_fields = ("gymnast", "routine")
- autocomplete_fields = ("gymnast", "routine")
-
-
-class InlineToDoRelation(admin.TabularInline):
- model = ToDoRelation
-
-
-class GymnastAdmin(admin.ModelAdmin):
- model = Gymnast
-
- def lastname(self, obj):
- return obj.user.last_name
-
- def firstname(self, obj):
- return obj.user.first_name
-
- def email(self, obj):
- return obj.user.email
-
- def is_active(self, obj):
- return obj.user.is_active
-
- fields = (
- # "lastname",
- # "firstname",
- "birthdate",
- "gender",
- "club",
- "niss",
- "address",
- "postal",
- "city",
- "phone",
- "gsm",
- # "user__email",
- "fedid",
- "year_of_practice",
- "gsm_mother",
- "email_mother",
- "gsm_father",
- "email_father",
- # "user.is_active",
- "orientation",
- "trainer",
- "picture",
- "content",
- )
-
- list_display = ("lastname", "firstname", "birthdate", "age", "is_active")
- list_filter = ("gender", "user__is_active")
- search_fields = ("lastname", "firstname", "email")
- inlines = [InlineToDoRelation, InlineCanDoRelation]
- autocomplete_fields = ("club",)
-
-
-class AccidentAdmin(admin.ModelAdmin):
- model = Accident
-
- fields = ("date", "gymnast", "educative", "information")
- list_display = ("date", "gymnast", "educative")
- list_filter = ("date",)
- search_fields = ("date", "gymnast", "educative")
- autocomplete_fields = ["gymnast", "educative"]
-
-
-admin.site.register(Gymnast, GymnastAdmin)
-admin.site.register(Accident, AccidentAdmin)
-admin.site.register(CanDoRelation, CanDoRelationAdmin)
-admin.site.register(ToDoRelation, ToDoRelationAdmin)
-admin.site.register(GymnastHasRoutine, GymnastHasRoutineAdmin)
diff --git a/src/people/forms.py b/src/people/forms.py
deleted file mode 100644
index 8816f52..0000000
--- a/src/people/forms.py
+++ /dev/null
@@ -1,174 +0,0 @@
-"""Formulaires de gestion des données entrantes pour les gymnastes et accidents."""
-
-from django import forms
-
-from .models import (
- Accident,
- Gymnast,
- GymnastHasRoutine,
-)
-
-from django.contrib.auth.models import User
-
-
-class AccidentForm(forms.ModelForm):
- class Meta:
- model = Accident
- fields = ("gymnast", "educative", "date", "content")
- widgets = {
- "date": forms.DateInput(
- attrs={
- "class": "form-control datepicker",
- # "value": date.today().strftime("%Y-%m-%d"),
- }
- ),
- "gymnast": forms.HiddenInput(),
- "educative": forms.HiddenInput(),
- "content": forms.Textarea(
- attrs={
- "class": "form-control",
- "placeholder": "Informations about accident: context (why, where, …), consequencies, …",
- }
- ),
- }
-
- gymnast_related = forms.CharField(
- widget=forms.TextInput(
- attrs={
- "class": "form-control",
- "placeholder": "Searching gymnast…",
- "data-ref": "#id_gymnast",
- }
- )
- )
- educative_related = forms.CharField(
- widget=forms.TextInput(
- attrs={
- "class": "form-control",
- "placeholder": "Searching skill…",
- "data-ref": "#id_educative",
- }
- )
- )
-
-
-class UserForm(forms.ModelForm):
- class Meta:
- model = User
- fields = (
- "last_name",
- "first_name",
- "email",
- "is_active",
- "username",
- )
-
-
-class GymnastForm(forms.ModelForm):
-
- lastname = forms.CharField(
- widget = forms.TextInput(
- attrs={
- "class": "form-control",
- "placeholder":"Lastname"
- }
- )
- )
- firstname = forms.CharField(
- widget = forms.TextInput(
- attrs={
- "class": "form-control",
- "placeholder":"Firstname"
- }
- )
- )
- email = forms.EmailField()
- # is_active = forms.CheckboxInput()
-
- class Meta:
- model = Gymnast
- fields = (
- "id",
- "birthdate",
- "gender",
- "address",
- "postal",
- "city",
- "phone",
- "gsm",
- "gsm_main_responsible",
- "email_main_responsible",
- "gsm_second_responsible",
- "email_second_responsible",
- "orientation",
- "picture",
- "content",
- )
-
- widgets = {
- "id": forms.HiddenInput(),
- "lastname": forms.TextInput(attrs={"class": "form-control", "placeholder":"Lastname"}),
- "firstname": forms.TextInput(attrs={"class": "form-control", "placeholder":"Firstname"}),
- "birthdate": forms.DateInput(attrs={"class": "form-control datepicker"}),
- "gender": forms.Select(attrs={"class": "form-control"}),
- "address": forms.TextInput(attrs={"class": "form-control"}),
- "postal": forms.TextInput(attrs={"class": "form-control"}),
- "city": forms.TextInput(attrs={"class": "form-control"}),
- "phone": forms.TextInput(attrs={"class": "form-control"}),
- "gsm": forms.TextInput(attrs={"class": "form-control"}),
- "email": forms.EmailInput(attrs={"class": "form-control"}),
- "gsm_main_responsible": forms.TextInput(attrs={"class": "form-control"}),
- "email_main_responsible": forms.EmailInput(attrs={"class": "form-control"}),
- "gsm_second_responsible": forms.TextInput(attrs={"class": "form-control"}),
- "email_second_responsible": forms.EmailInput(attrs={"class": "form-control"}),
- # "is_active": forms.CheckboxInput(
- # attrs={
- # "class": "bootstrap-switch mt-0",
- # "data-on-label": "",
- # "data-off-label": "",
- # }
- # ),
- "orientation": forms.Select(attrs={"class": "form-control"}),
- "picture": forms.Select(attrs={"class": "form-control"}),
- "content": forms.Textarea(
- attrs={
- "class": "form-control",
- "placeholder": "Informations about the gymnast.",
- }
- ),
- }
-
-
-class GymnastHasRoutineForm(forms.ModelForm):
- """
- """
-
- class Meta:
- model = GymnastHasRoutine
- fields = ("gymnast", "routine", "routine_type", "datebegin", "dateend")
- widgets = {
- "gymnast": forms.HiddenInput(),
- "routine": forms.HiddenInput(),
- "routine_type": forms.Select(attrs={"class": "form-control"}),
- "datebegin": forms.DateInput(attrs={"class": "form-control datepicker",}),
- "dateend": forms.DateInput(attrs={"class": "form-control datepicker",}),
- }
-
- gymnast_related = forms.CharField(
- widget=forms.TextInput(
- attrs={
- "class": "form-control",
- "placeholder": "Searching gymnast…",
- "data-ref": "#id_gymnast",
- }
- )
- )
- routine_related = forms.CharField(
- widget=forms.TextInput(
- attrs={
- "class": "form-control",
- "placeholder": "Searching routine…",
- "data-ref": "#id_routine",
- }
- )
- )
diff --git a/src/people/migrations/0015_auto_20210514_1619.py b/src/people/migrations/0015_auto_20210514_1619.py
deleted file mode 100644
index 4a119d4..0000000
--- a/src/people/migrations/0015_auto_20210514_1619.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# Generated by Django 3.2.2 on 2021-05-14 16:19
-
-from django.db import migrations
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('people', '0014_auto_20210513_1058'),
- ]
-
- operations = [
- migrations.AlterModelOptions(
- name='gymnast',
- options={'ordering': ['user__last_name', 'user__first_name'], 'verbose_name': 'Gymnast', 'verbose_name_plural': 'Gymnasts'},
- ),
- migrations.RemoveField(
- model_name='gymnast',
- name='email',
- ),
- migrations.RemoveField(
- model_name='gymnast',
- name='firstname',
- ),
- migrations.RemoveField(
- model_name='gymnast',
- name='lastname',
- ),
- ]
diff --git a/src/people/migrations/0016_auto_20210515_0800.py b/src/people/migrations/0016_auto_20210515_0800.py
deleted file mode 100644
index 60b2456..0000000
--- a/src/people/migrations/0016_auto_20210515_0800.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# Generated by Django 3.2.2 on 2021-05-15 08:00
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('people', '0015_auto_20210514_1619'),
- ]
-
- operations = [
- migrations.RemoveField(
- model_name='gymnast',
- name='active',
- ),
- migrations.AlterField(
- model_name='gymnast',
- name='fedid',
- field=models.CharField(blank=True, max_length=10, null=True, verbose_name='Federation ID'),
- ),
- migrations.AlterField(
- model_name='gymnast',
- name='orientation',
- field=models.PositiveSmallIntegerField(blank=True, choices=[(None, 'Unknown'), (0, 'Left'), (1, 'Right')], null=True, verbose_name='Twist side'),
- ),
- migrations.AlterField(
- model_name='gymnast',
- name='phone',
- field=models.CharField(blank=True, max_length=9, null=True, verbose_name='Phond'),
- ),
- ]
diff --git a/src/people/migrations/0019_auto_20210621_1809.py b/src/people/migrations/0019_auto_20210621_1809.py
deleted file mode 100644
index 2bc2775..0000000
--- a/src/people/migrations/0019_auto_20210621_1809.py
+++ /dev/null
@@ -1,43 +0,0 @@
-# Generated by Django 3.2.2 on 2021-06-21 18:09
-
-from django.db import migrations
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('people', '0018_auto_20210621_1804'),
- ]
-
- operations = [
- migrations.RenameField(
- model_name='gymnast',
- old_name='cando',
- new_name='can_do',
- ),
- migrations.RenameField(
- model_name='gymnast',
- old_name='email_father',
- new_name='email_main_responsible',
- ),
- migrations.RenameField(
- model_name='gymnast',
- old_name='email_mother',
- new_name='email_second_responsible',
- ),
- migrations.RenameField(
- model_name='gymnast',
- old_name='gsm_mother',
- new_name='gsm_main_responsible',
- ),
- migrations.RenameField(
- model_name='gymnast',
- old_name='gsm_father',
- new_name='gsm_second_responsible',
- ),
- migrations.RenameField(
- model_name='gymnast',
- old_name='haveToDo',
- new_name='have_to_do',
- ),
- ]
diff --git a/src/people/models.py b/src/people/models.py
deleted file mode 100644
index 6adc6e7..0000000
--- a/src/people/models.py
+++ /dev/null
@@ -1,353 +0,0 @@
-"""Modélisation des gymnastes, accidents et relations à faire/faites.
-
-Notes:
- Est-ce qu'il ne faudrait pas refactoriser les GSM père/mère ?
- Avec une table d'association, et un champ qui indique la qualité du contact ?
- Du coup, cela permettrait se débarasser des champs phone, gsm, gsm_father et gsm_mother.
-
- Comment sont gérées les évolutions ? Changement de clubs, de fédération,
-
- A quoi correspond le champ `year_of_practice` ?
- Comment se comportera-t-il dans un an ? Dans deux ans ?
- Est-ce qu'il ne faudrait pas une date de début, plutôt ?
-
- Idem pour la méthode `actual_year_of_pratice`.
- Comme elle se base sur le champ `created_at`, il suffit que l'enregistrement ne soit pas
- réalisé correctement pour que la méthode retourne une mauvaise information.
-
- Que signifie qu'un gymnaste soit actif ou inactif ? Est-ce que cela ne devrait pas plutôt
- être géré au niveau des utilisateurs ?
-
- Au niveau des utilisateurs, comme un User Django a déjà les champs lastname/firstname
- pourquoi ne pas les réutiliser ? On garde la clé OneToOne, mais on déplace dans l'autre
- classe les champs qui peuvent l'être. `Email` s'y retrouve également.
-
- Les relations `cando`, `haveToDo` et `have_routine` ne sont pas correctement nommées.
- Si tu as une instance de `Gymnast`, tu devrais faire ceci :
-
- >>> gregg = Gymnast.objects.first()
- >>> gregg.have_routine <-- pas bien
- >>> gregg.routines <-- ok
-
- Idéalement, cela pourrait même être une indirection.
-
- >>> gregg.routines <-- retourne la relation de type `have_routine`
- >>> gregg.educatives.can_do <-- retourne les éducatifs qu'il **peut** faire
- >>> gregg.educatives.must_do <-- retourne les éducatifs qu'il **doit** faire
- (j'avoue ne pas tout à fait comprendre la nuance entre les deux)
-
- Tu as des fonctions qui ne sont pas du tout utilisées et qui pourrissent un peu le fichier.
- >>> next_age() ? N'est appelé nulle part ailleurs.
- >>> known_skills() <-- peut être récupéré directement via l'attribut `cando`
- (du coup, tu as sans doute une piste de renommage ;-))
-"""
-
-from datetime import date
-
-from django.contrib.auth.models import User
-from django.db import models
-
-import pendulum
-
-from base.models import Markdownizable
-
-
-class Gymnast(Markdownizable):
- """Représente un gymnaste.
-
- En plus de sa signalétique (nom, prénom, date de naissance, ...),
- un gymnaste aura une photo et une orientation (de vrille).
-
- Un gymnaste peut être actif ou inactif.
- """
-
- class Meta:
- verbose_name = "Gymnast"
- verbose_name_plural = "Gymnasts"
- ordering = ["user__last_name", "user__first_name"]
-
- GENDER_CHOICES = ((0, "Male"), (1, "Female"))
- ORIENTATION_CHOICES = ((None, "Unknown"), (0, "Left"), (1, "Right"))
-
- birthdate = models.DateField(verbose_name="Date de naissance")
- gender = models.PositiveSmallIntegerField(
- choices=GENDER_CHOICES, verbose_name="Sexe"
- )
- niss = models.CharField(max_length=11, null=True, blank=True)
- address = models.CharField(max_length=255, null=True, blank=True)
- postal = models.CharField(max_length=6, null=True, blank=True)
- city = models.CharField(max_length=150, null=True, blank=True)
- phone = models.CharField(
- max_length=9, null=True, blank=True, verbose_name="Phond"
- )
- gsm = models.CharField(max_length=10, null=True, blank=True)
- federation_id = models.CharField(
- max_length=10, null=True, blank=True, verbose_name="Federation ID"
- )
- gsm_main_responsible = models.CharField(
- max_length=10, null=True, blank=True, verbose_name="GSM mère"
- )
- email_main_responsible = models.EmailField(max_length=255, null=True, blank=True)
- gsm_second_responsible= models.CharField(
- max_length=10, null=True, blank=True, verbose_name="GSM père"
- )
- email_second_responsible = models.EmailField(max_length=255, null=True, blank=True)
- orientation = models.PositiveSmallIntegerField(
- choices=ORIENTATION_CHOICES,
- null=True,
- blank=True,
- verbose_name="Twist side",
- )
- user = models.OneToOneField(
- User, on_delete=models.CASCADE, related_name="gymnast"
- )
- trainer = models.ForeignKey(
- User, null=True, on_delete=models.SET_NULL, related_name="gymnasts"
- )
- club = models.ForeignKey(
- "location.Club", null=True, on_delete=models.SET_NULL, related_name="gymnasts"
- )
- can_do = models.ManyToManyField(
- "objective.Educative",
- through="CanDoRelation",
- related_name="isdoneby", # related_name to change
- )
- have_to_do = models.ManyToManyField(
- "objective.Educative",
- through="ToDoRelation",
- related_name="mustBeDoneBy", # related_name to change
- )
- routine = models.ManyToManyField(
- "objective.Routine",
- through="GymnastHasRoutine",
- related_name="doneBy", # related_name to change
- )
- picture = models.ImageField(upload_to="gymnasts", null=True, blank=True)
- year_of_practice = models.PositiveSmallIntegerField(default=0)
- created_at = models.DateTimeField(auto_now_add=True)
-
- def __str__(self):
- return u"%s, %s" % (self.user.last_name, self.user.first_name)
-
- @property
- def next_birthday(self):
- """Définit la prochaine date (de fête) d'anniversaire pour cette personne.
-
- Returns:
- Soit le jour/mois pour cette année
- Soit le jour/mois pour l'année prochaine.
-
- Examples: en supposant qu'on soit le 23/05/2019
- >>> from datetime import date
- >>> gregg = People(name='Tru', firstname='Gregg', birthdate=date(1982, 2, 5)
- >>> gregg.next_birthday()
- Date(2020, 2, 5)
- """
-
- now = pendulum.now()
-
- this_year_birthday = pendulum.date(
- now.year, self.birthdate.month, self.birthdate.day
- )
-
- if this_year_birthday.is_past():
- return pendulum.date(now.year + 1, self.birthdate.month, self.birthdate.day)
- return this_year_birthday
-
- @property
- def next_birthday_in_days(self):
- now = pendulum.now()
- return self.next_birthday.diff(now).in_days()
-
- @property
- def age(self):
- """ Renvoie l'âge d'un gymnaste. """
- today = date.today()
- return (
- today.year
- - self.birthdate.year
- - ((today.month, today.day) < (self.birthdate.month, self.birthdate.day))
- )
-
- @property
- def next_age(self):
- """ Renvoie l'âge prochain du gymnaste. """
- return (self.age) + 1
-
- @property
- def known_skills(self):
- """ Renvoie la liste des objectifs qu'un gymnaste sait faire. """
- return CanDoRelation.objects.filter(gymnast=self.id)
-
- @property
- def actual_year_of_pratice(self):
- """
- Renvoie le nombre d'année de pratique du gymnaste en se basant sur le
- nombre d'année qu'il avait déjà lors de son introduction dans le
- système + le nombre d'année qu'il est dans le système.
- """
- period = pendulum.now() - pendulum.instance(self.created_at, "Europe/Brussels")
- return int(self.year_of_practice + period.in_years())
-
-
-class Accident(Markdownizable):
- """La classe `Accident` permet d'indiquer qu'un gymnaste est tombé durant un saut.
- """
-
- class Meta:
- verbose_name = "Accident"
- verbose_name_plural = "Accidents"
- # ordering = ["date", "gymnast"]
-
- gymnast = models.ForeignKey(
- Gymnast,
- verbose_name="Gymnast",
- related_name="accident",
- on_delete=models.CASCADE,
- )
- educative = models.ForeignKey(
- "objective.Skill",
- verbose_name="Skill",
- related_name="accident",
- on_delete=models.CASCADE,
- )
- date = models.DateField(verbose_name="Date")
-
- def __str__(self):
- return "%s, %s (%s)" % (
- self.gymnast.lastname,
- self.gymnast.firstname,
- self.date,
- )
-
-
-class CanDoRelation(models.Model):
- """
- Représente les objectifs qu'un gymnaste sait faire (à partir d'une date donnée).
- """
-
- class Meta:
- verbose_name = "CanDo"
- verbose_name_plural = "CanDos"
- ordering = ["date", "educative", "gymnast"]
- unique_together = ("gymnast", "educative")
-
- # TO_FRED : puis-je avoir ton avis là-dessus ?
- #
- # JE VAIS INDIQUER QUE DES ELEVES SAVENT FAIRE DES FIGURES (SKILL)
- #
- #
- # QUESTIONS
- # ---------
- #
- # 1) Cela ne dervait pas être deux relations ManyToMany dans chacune des tables GYMNAST et EDUCATIVE (ou SKILL) ?
- # Un élève saura faire plusieurs figures.
- # Et une figure pourra savoir être faite par plusieurs élèves... Donc, ?
- #
- # 2) Dans un premier temps, même si je l'appelle EDUCATIVE mon champs, pour être pérenne,
- # je n'associerai QUE des figures à un élève. Je voudrais donc, dans l'admin, que mon champs
- # ne soit populer qu'avec les éléments de la table SKILL et non pas tous les éléments de la
- # table EDUCATIVE.
- gymnast = models.ForeignKey(
- Gymnast,
- verbose_name="Gymnast",
- related_name="toObjective",
- on_delete=models.CASCADE,
- )
- educative = models.ForeignKey(
- "objective.Educative",
- verbose_name="Skill",
- related_name="cando",
- on_delete=models.CASCADE,
- )
- date = models.DateField(default=date.today, verbose_name="Date")
-
- def __str__(self):
- return "%s, %s - %s" % (
- self.gymnast.user.last_name,
- self.gymnast.user.first_name,
- self.educative.shortLabel,
- )
-
- @staticmethod
- def create(gymnast, skill, linkdate):
- c = CanDoRelation()
- c.gymnast = gymnast
- c.educative = skill
- c.date = linkdate
- c.save()
- return c
-
-
-class ToDoRelation(models.Model):
- """
- Classe représentant les objectifs qu'une gymnaste devra savoir faire pour une date donnée.
- """
-
- class Meta:
- verbose_name = "ToDo"
- verbose_name_plural = "ToDos"
- ordering = ["date", "educative", "gymnast"]
- unique_together = ("gymnast", "educative")
-
- gymnast = models.ForeignKey(
- Gymnast, verbose_name="Gymnast", related_name="todo", on_delete=models.CASCADE
- )
- educative = models.ForeignKey(
- "objective.Educative",
- verbose_name="Skill",
- related_name="isInToDo",
- on_delete=models.CASCADE,
- )
- date = models.DateField(default=date.today, verbose_name="Date")
-
- def __str__(self):
- return "%s, %s - %s" % (
- self.gymnast.lastname,
- self.gymnast.firstname,
- self.educative.shortLabel,
- )
-
-
-class GymnastHasRoutine(models.Model):
- """
- Classe représentant le lien entre les gymnastes et leurs séries.
- """
-
- class Meta:
- verbose_name = "Gymnast Has Routine"
- verbose_name_plural = "Gymnast Has Routines"
-
- ROUTINETYPE_CHOICE = (
- (1, "L1"),
- (2, "L2"),
- (3, "L3"),
- (4, "L4"),
- (5, "L1S"),
- (6, "L2S"),
- (7, "L3S"),
- (8, "L4S"),
- )
-
- gymnast = models.ForeignKey(
- Gymnast,
- verbose_name="Gymnast",
- related_name="has_routine",
- on_delete=models.CASCADE,
- )
- routine = models.ForeignKey(
- "objective.Routine",
- verbose_name="Routine",
- related_name="used_by_gymnast",
- on_delete=models.CASCADE,
- )
- routine_type = models.PositiveSmallIntegerField(
- choices=ROUTINETYPE_CHOICE, verbose_name="Type", default="1"
- )
- datebegin = models.DateField(default=date.today, verbose_name="Date begin")
- dateend = models.DateField(
- default=date.today, verbose_name="Date end", null=True, blank=True
- )
-
- def __str__(self):
- return "%s - %s : %s" % (self.gymnast, self.routine_type, self.routine)
diff --git a/src/planning/migrations/0021_auto_20210513_1058.py b/src/planning/migrations/0021_auto_20210513_1058.py
deleted file mode 100644
index ad43a23..0000000
--- a/src/planning/migrations/0021_auto_20210513_1058.py
+++ /dev/null
@@ -1,43 +0,0 @@
-# Generated by Django 3.2.2 on 2021-05-13 10:58
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('planning', '0020_event_gymnasts'),
- ]
-
- operations = [
- migrations.RenameField(
- model_name='course',
- old_name='information',
- new_name='content',
- ),
- migrations.RenameField(
- model_name='event',
- old_name='information',
- new_name='content',
- ),
- migrations.RenameField(
- model_name='planningline',
- old_name='information',
- new_name='content',
- ),
- migrations.RenameField(
- model_name='round',
- old_name='information',
- new_name='content',
- ),
- migrations.RenameField(
- model_name='unavailability',
- old_name='information',
- new_name='content',
- ),
- migrations.AlterField(
- model_name='group',
- name='season',
- field=models.CharField(default='2021-2022', max_length=9),
- ),
- ]
diff --git a/src/planning/models.py b/src/planning/models.py
deleted file mode 100644
index 393a8f4..0000000
--- a/src/planning/models.py
+++ /dev/null
@@ -1,508 +0,0 @@
-
-from datetime import datetime, date, time, timedelta
-
-from django.contrib.auth.models import User
-from django.db import models
-from django.utils import timezone
-
-import pendulum
-
-from base.models import Markdownizable
-from location.models import Club
-from people.models import Gymnast
-
-
-def get_week(a_date):
- """
-
- Remarks:
- Je ne comprends pas trop cette fonction...
- Tu pars d'une date, et tu récupères le lundi et le samedi de la semaine correspondant ?
- """
- the_date = pendulum.parse(a_date)
- day = the_date.weekday()
- monday = the_date - timedelta(days=day)
- sunday = the_date + timedelta(days=(6 - day))
- return monday, sunday
-
-
-def get_number_of_weeks_between(start, stop):
- """
- Renvoie le nombre de semaines entre deux dates.
- Par extension, cela permet de connaitre le nombre d'occurence d'un
- évènement (entraînement, par exemple) hebdromadaire entre deux dates
- et ainsi pouvoir plannifier.
-
- :param start: date de début de la période
- :type start: datetime.date
- :param stop: date de fin de la période
- :type stop: datetime.date
- :return: Le nombre de semaines entre les deux dates.
-
- Remarks:
- Proposition d'utiliser isocalendar() sur une date.
- L'indice 1 de la valeur de retour donne la semaine correspondant.
-
- Eg.
- >>> from datetime import date
- >>> d = date(2020, 9, 27)
- >>> d.isocalendar()
- (2020, 39, 7)
-
- -> Est-ce qu'il ne suffirait pas de faire la différence ?
- """
-
- tmp = stop - start
- number_of_days = abs(tmp.days)
- number_of_week = int((number_of_days + 1) / 7)
-
- if ((number_of_days + 1) % 7) > 0:
- number_of_week += 1
-
- if tmp.days < 0:
- number_of_week *= -1
-
- return number_of_week
-
-
-class TemporizableQuerySet(models.QuerySet):
- """
- Classe permettant de spécifier le `QuerySet` de la classe `Temporizable`.
- """
-
- def next(self, limit):
- """
- Renvoie la liste des prochains "temporizable" (par rapport à la date du jour).
-
- :param limit: nombre d'éléments désirés.
- :type limit: int
- :return: une liste de `limit` éléments temporizables.
- """
- return self.filter(datebegin__gte=timezone.now()).order_by("datebegin")[0:limit]
-
- def last(self, limit):
- """
- Renvoie la liste des derniers "temporizable" (par rapport à la date du jour).
-
- :param limit: nombre d'éléments désirés.
- :type limit: int
- :return: une liste de `limit` éléments temporizables
- """
- return self.filter(dateend__lte=timezone.now()).order_by("-dateend")[0:limit]
-
- # def get(self, date_string):
- # """
- # """
- # try:
- # selected_object = self.get(datebegin__lte=date_string, dateend__gte=date_string)
- # except self.DoesNotExist:
- # return None
- # except self.MultipleObjectsReturned:
- # return None
-
- # return selected_object
-
-
-class Temporizable(models.Model):
- """Classe abstraite définissant une période comprise entre deux dates.
-
- """
-
- class Meta:
- abstract = True
-
- datebegin = models.DateTimeField(verbose_name="Début")
- dateend = models.DateTimeField(blank=True, verbose_name="Fin")
-
- objects = models.Manager.from_queryset(TemporizableQuerySet)()
-
- def get_total_occurence(self):
- """
- Renvoie le nombre de semaines entre les deux dates d'une instance de la
- classe `Temporizable`.
-
- :return: nombre de semaines.
- """
- return get_number_of_weeks_between(self.datebegin.date(), self.dateend.date())
-
- def get_number_of_occurence_to_event(self, the_date):
- """
- Renvoie le nombre semaines entre une date choisie et le début
- (datebegin) d'une instance de la classe `Temporizable`.
-
- :param the_date: date par rapport à laquelle le calcul sera fait.
- :type the_date: datetime.date
- :return: nombre de semaines.
- """
- return get_number_of_weeks_between(the_date, self.datebegin.date())
-
- def get_number_of_occurence_inbetween(self, the_date, rest=True):
- """
- Renvoie le nombre semaines entre une date choisie et une instance de la
- classe `Temporizable`. Le calcul peut se faire soit entre la date
- choisie et le date de fin d'une occurence de la classe, soit entre la
- date de début d'une occurence de la classe et la date choisie.
-
- :param the_date: date par rapport à laquelle le calcul sera fait.
- :type the_date: datetime.date
- :param rest: paramètre définissant s'il faut calculer le reste des
- occurences à venir (depuis `the_date` jusqu'à la date de fin) ou
- les occurences déjà passées (depuis la date de début jusqu'à
- `the_date`)
- :type rest: booléen
- :return: nombre de semaines.
- """
- if rest:
- return get_number_of_weeks_between(the_date, self.dateend.date())
- else:
- return get_number_of_weeks_between(self.datebegin.date(), the_date)
-
-
-class Season(Temporizable):
- """
- Classe représentant une saison. Une saison est déinie par :
- - un id,
- - un label,
- - une date de début et
- - une date de fin.
-
- La date de début est très souvent le : 01/09/xxxx
- La date de fin est très souvent le : 31/08/xxxy
- exemple : 1/9/2015 - 31/8/2016
- """
-
- class Meta:
- verbose_name = "Season"
- verbose_name_plural = "Seasons"
-
- label = models.CharField(max_length=11, verbose_name="Label")
- # active ou default = models.BooleanField(verbose_name='Défaut')
-
- def __str__(self):
- return "%s" % (self.label)
-
- def week_number_from_begin(self, target_date):
- return get_number_of_weeks_between(self.datebegin.date(), target_date)
-
-
-class EventType(models.Model):
- """
- Classe représentant les types d'évènements.
- C'est un dictionnaire fini :
- - compétiton qualificative,
- - compétition finale,
- - démonstration,
- - …
- """
-
- class Meta:
- verbose_name = "Event Type"
- verbose_name_plural = "Event Types"
-
- name = models.CharField(max_length=255, verbose_name="Nom")
- acronym = models.CharField(max_length=5, verbose_name="Acronyme")
-
- def __str__(self):
- return "%s (%s)" % (self.name, self.acronym)
-
-
-class Event(Markdownizable, Temporizable):
- """Classe représentant les évènements.
-
- Un évènement est caractérisé par :
- * un nom,
- * un lieu (place),
- * un type (compétition, démonstration, …),
- * des gymnastes (participation prévue).
- Je ne me rapelle plus à quoi sert le club.
- """
-
- class Meta:
- verbose_name = "Event"
- verbose_name_plural = "Event"
-
- place = models.ForeignKey(
- "location.Place", verbose_name="Lieu", on_delete=models.CASCADE, default=None
- )
- eventtype = models.ForeignKey(
- EventType, verbose_name="Type", on_delete=models.CASCADE, default=None
- )
- name = models.CharField(max_length=255, verbose_name="Nom")
- # club = models.ManyToManyField('location.Club', related_name="concernate_by", blank=True)
- gymnasts = models.ManyToManyField(
- "people.Gymnast",
- through="Event_Participation",
- related_name="participate_to",
- verbose_name="Participants",
- )
-
- def __str__(self):
- return "%s (à %s)" % (self.name, self.place.city)
-
- def save(self, *args, **kwargs):
- self.checkdates()
- super().save(*args, **kwargs)
-
- def checkdates(self):
- """
- Fonction assignant la date de fin d'un évènement à la date de début, si la date
- de fin n'est pas définie, l'heure de fin est par défaut 18h00.
- """
- if self.dateend is None and self.datebegin is not None:
- self.dateend = datetime.combine(self.datebegin.date(), time(18, 0))
-
- @property
- def number_of_week_from_today(self):
- today = pendulum.now().date()
- return get_number_of_weeks_between(today, self.datebegin.date())
-
-
-class Event_Participation(models.Model):
- """
- """
-
- event = models.ForeignKey(Event, on_delete=models.CASCADE)
- gymnast = models.ForeignKey("people.Gymnast", on_delete=models.CASCADE)
- rank = models.PositiveSmallIntegerField(default=0)
-
-
-class Course(Markdownizable, Temporizable):
- """Classe représentant les cours.
-
- Un cours est défini par :
- * une heure de début et une heure de fin,
- * une date de début et une date de fin (un cours est considéré comme donné hebdromadairement entre
- ces deux dates) (hérite de la classe `Temporizable`)
- * est associé à un ou plusieurs entraineurs,
- * est associé à un club
- * est associé à un jour de la semaine (numéro du jour dans la semaine : 0 = lundi, 6 = dimanche).
- """
-
- class Meta:
- verbose_name = "Course"
- verbose_name_plural = "Courses"
-
- DAY_CHOICE = (
- (1, "Lundi"),
- (2, "Mardi"),
- (3, "Mercredi"),
- (4, "Jeudi"),
- (5, "Vendredi"),
- (6, "Samedi"),
- (7, "Dimanche"),
- )
-
- club = models.ForeignKey(
- "location.Club", verbose_name="Club", on_delete=models.CASCADE, default=None
- )
- iso_day_number = models.PositiveSmallIntegerField(
- choices=DAY_CHOICE, verbose_name="Jour"
- )
- hour_begin = models.TimeField(verbose_name="Heure de début")
- hour_end = models.TimeField(verbose_name="Heure de fin")
- season = models.ForeignKey(Season, on_delete=models.SET_NULL, null=True)
- trainers = models.ManyToManyField(
- User, verbose_name="Coach(es)", related_name="trainee"
- )
- gymnasts = models.ManyToManyField(
- Gymnast, verbose_name="Gymnasts", related_name="courses"
- )
-
- def __str__(self):
- return "%s (%s à %s)" % (
- self.get_iso_day_number_display(),
- self.hour_begin.strftime("%H:%M"),
- self.hour_end.strftime("%H:%M"),
- )
-
- @property
- def duration(self):
- """
- Renvoie la durée d'un cours en heures
- """
- date_begin = pendulum.datetime(
- 2000, 1, 1, self.hour_begin.hour, self.hour_begin.minute
- )
- date_end = pendulum.datetime(
- 2000, 1, 1, self.hour_end.hour, self.hour_end.minute
- )
- return date_end.diff(date_begin).in_hours()
-
-
-class Group(models.Model):
- """Classe représentant les groupes (Loisir, D1, D2, A, B, …).
-
- Un groupe appartient à un club.
- """
-
- class Meta:
- verbose_name = "Group"
- verbose_name_plural = "Groups"
-
- club = models.ForeignKey("location.Club", on_delete=models.CASCADE, default=None)
- name = models.CharField(max_length=255)
- acronym = models.CharField(max_length=50)
- active = models.BooleanField(default=1)
- season = models.CharField(
- max_length=9,
- default=str(timezone.now().year) + "-" + str(timezone.now().year + 1),
- )
-
- def __str__(self):
- return "%s (%s)" % (self.name, self.acronym)
-
-
-class Subgroup(models.Model):
- """Classe représentant les sous-groupes.
-
- Un sous-groupe appartient à un groupe (lui-même lié à un club).
-
- De cette manière, quand un gymnaste est mis dans un sous-groupe, en remontant via le groupe,
- nous pouvons connaître le(s) club(s) du gymnaste pour chaque saison.
- """
-
- class Meta:
- verbose_name = "Subgroup"
- verbose_name_plural = "Subgroups"
-
- name = models.CharField(max_length=255)
- acronym = models.CharField(max_length=50)
- group = models.ForeignKey(Group, on_delete=models.CASCADE, default=None)
- courses = models.ManyToManyField(Course, related_name="to_subgroup")
- gymnasts = models.ManyToManyField(
- "people.Gymnast", related_name="to_gym", blank=True
- )
- active = models.BooleanField(default=1)
-
- def __str__(self):
- return "%s (%s)" % (self.name, self.group.name)
-
-
-class UnavailabilityManager(models.Manager):
- """Classe représentant le manager de la classe `Unavailability`.
- """
-
- def next(self, count):
- return self.filter(datebegin__gte=timezone.now()).order_by("datebegin")[0:count]
-
- def last(self, count):
- return self.filter(dateend__lte=timezone.now()).order_by("-dateend")[0:count]
-
-
-class Unavailability(Markdownizable, Temporizable):
- """Classe représentant les indisponibilités.
- """
-
- class Meta:
- verbose_name = "Indisponibilité"
- verbose_name_plural = "Indisponibilités"
-
- course = models.ManyToManyField(Course, related_name="unavailability")
-
- objects = UnavailabilityManager()
-
- def __str__(self):
- return "du %s au %s" % (self.datebegin, self.dateend)
-
- def save(self, *args, **kwargs):
- self.checkdates()
-
- super().save(*args, **kwargs)
-
- def checkdates(self):
- if self.dateend is None and self.datebegin is not None:
- self.dateend = self.datebegin
-
-
-class Training(models.Model):
- """Classe représentant les entraînements.
-
- Un entraînement est une occurence d'un cours pendant lequel des gmnastes sont présents.
-
- Un objet de cette classe lie donc un cours et un gymnaste à une date donnée.
- """
-
- class Meta:
- verbose_name = "Training"
- verbose_name_plural = "Trainings"
-
- gymnast = models.ForeignKey(
- "people.Gymnast",
- verbose_name="Gymnast",
- on_delete=models.CASCADE,
- default=None,
- related_name="trainings",
- )
- course = models.ForeignKey(
- Course, verbose_name="Course", on_delete=models.CASCADE, default=None
- )
- trainingdate = models.DateField(verbose_name="Date")
-
- def __str__(self):
- return "%s - %s, %s" % (self.trainingdate, self.course, self.gymnast)
-
- @staticmethod
- def create(gymnast, course, trainingdate):
- t = Training()
- t.gymnast = gymnast
- t.course = course
- t.trainingdate = trainingdate
- t.save()
- return t
-
-
-class Round(Markdownizable):
- """Classe représentant les passages des élèves lors d'un entrainement.
-
- Chaque record représente un passage. Il est donc lié à un record de la classe `Training`.
- """
-
- class Meta:
- verbose_name = "Round"
- verbose_name_plural = "Rounds"
-
- EVALUATION_CHOICES = (
- (0, "- -"),
- (1, "- +"),
- (2, "+ -"),
- (3, "+ +"),
- )
-
- training = models.ForeignKey(
- Training, on_delete=models.CASCADE, default=None, related_name="rounds"
- )
- educative = models.ForeignKey(
- "objective.Educative",
- on_delete=models.CASCADE,
- default=None,
- blank=True,
- null=True,
- )
- round_information = models.CharField(max_length=255, blank=True, null=True)
- round_number = models.PositiveSmallIntegerField(blank=True, null=True)
- gymnast_evaluation = models.PositiveSmallIntegerField(
- choices=EVALUATION_CHOICES, blank=True, null=True
- )
- coach_evaluation = models.PositiveSmallIntegerField(blank=True, null=True)
- coachid = models.ForeignKey(User, blank=True, null=True, on_delete=models.SET_NULL)
- nb_of_realisation = models.PositiveSmallIntegerField(blank=True, null=True)
- nb_of_success = models.PositiveSmallIntegerField(blank=True, null=True)
- is_important = models.BooleanField(default=False)
-
- def __str__(self):
- return "%s" % (self.round_number)
-
-
-class PlanningLine(Markdownizable):
- """Classe représentant les passages prévisionnels (incubating idea).
- """
-
- class Meta:
- verbose_name = "Planning Line"
- verbose_name_plural = "Planning lines"
- # ordering = ['gymnast', 'date', 'order']
-
- gymnast = models.ForeignKey(Gymnast, on_delete=models.CASCADE, default=None)
- date = models.DateField(verbose_name="Date")
- order = models.PositiveSmallIntegerField()
- todo = models.CharField(max_length=255)
diff --git a/src/static/css/app2.css b/static/css/app2.css
similarity index 100%
rename from src/static/css/app2.css
rename to static/css/app2.css
diff --git a/src/static/css/application.css b/static/css/application.css
similarity index 100%
rename from src/static/css/application.css
rename to static/css/application.css
diff --git a/src/static/css/black-dashboard.css b/static/css/black-dashboard.css
similarity index 100%
rename from src/static/css/black-dashboard.css
rename to static/css/black-dashboard.css
diff --git a/src/static/css/black-dashboard.css.map b/static/css/black-dashboard.css.map
similarity index 100%
rename from src/static/css/black-dashboard.css.map
rename to static/css/black-dashboard.css.map
diff --git a/src/static/css/black-dashboard.min.css b/static/css/black-dashboard.min.css
similarity index 100%
rename from src/static/css/black-dashboard.min.css
rename to static/css/black-dashboard.min.css
diff --git a/src/static/css/nucleo-icons.css b/static/css/nucleo-icons.css
similarity index 100%
rename from src/static/css/nucleo-icons.css
rename to static/css/nucleo-icons.css
diff --git a/src/static/fonts/nucleo.eot b/static/fonts/nucleo.eot
similarity index 100%
rename from src/static/fonts/nucleo.eot
rename to static/fonts/nucleo.eot
diff --git a/src/static/fonts/nucleo.ttf b/static/fonts/nucleo.ttf
similarity index 100%
rename from src/static/fonts/nucleo.ttf
rename to static/fonts/nucleo.ttf
diff --git a/src/static/fonts/nucleo.woff b/static/fonts/nucleo.woff
similarity index 100%
rename from src/static/fonts/nucleo.woff
rename to static/fonts/nucleo.woff
diff --git a/src/static/fonts/nucleo.woff2 b/static/fonts/nucleo.woff2
similarity index 100%
rename from src/static/fonts/nucleo.woff2
rename to static/fonts/nucleo.woff2
diff --git a/src/static/img/AU.png b/static/img/AU.png
similarity index 100%
rename from src/static/img/AU.png
rename to static/img/AU.png
diff --git a/src/static/img/BR.png b/static/img/BR.png
similarity index 100%
rename from src/static/img/BR.png
rename to static/img/BR.png
diff --git a/src/static/img/DE.png b/static/img/DE.png
similarity index 100%
rename from src/static/img/DE.png
rename to static/img/DE.png
diff --git a/src/static/img/GB.png b/static/img/GB.png
similarity index 100%
rename from src/static/img/GB.png
rename to static/img/GB.png
diff --git a/src/static/img/RO.png b/static/img/RO.png
similarity index 100%
rename from src/static/img/RO.png
rename to static/img/RO.png
diff --git a/src/static/img/US.png b/static/img/US.png
similarity index 100%
rename from src/static/img/US.png
rename to static/img/US.png
diff --git a/src/static/img/apple-icon.png b/static/img/apple-icon.png
similarity index 100%
rename from src/static/img/apple-icon.png
rename to static/img/apple-icon.png
diff --git a/src/static/img/asc.gif b/static/img/asc.gif
similarity index 100%
rename from src/static/img/asc.gif
rename to static/img/asc.gif
diff --git a/src/static/img/bg.gif b/static/img/bg.gif
similarity index 100%
rename from src/static/img/bg.gif
rename to static/img/bg.gif
diff --git a/src/static/img/bg1.jpg b/static/img/bg1.jpg
similarity index 100%
rename from src/static/img/bg1.jpg
rename to static/img/bg1.jpg
diff --git a/src/static/img/bg13.jpg b/static/img/bg13.jpg
similarity index 100%
rename from src/static/img/bg13.jpg
rename to static/img/bg13.jpg
diff --git a/src/static/img/bg14.jpg b/static/img/bg14.jpg
similarity index 100%
rename from src/static/img/bg14.jpg
rename to static/img/bg14.jpg
diff --git a/src/static/img/bg15.jpg b/static/img/bg15.jpg
similarity index 100%
rename from src/static/img/bg15.jpg
rename to static/img/bg15.jpg
diff --git a/src/static/img/bg16.jpg b/static/img/bg16.jpg
similarity index 100%
rename from src/static/img/bg16.jpg
rename to static/img/bg16.jpg
diff --git a/src/static/img/bg3.jpg b/static/img/bg3.jpg
similarity index 100%
rename from src/static/img/bg3.jpg
rename to static/img/bg3.jpg
diff --git a/src/static/img/bg5.jpg b/static/img/bg5.jpg
similarity index 100%
rename from src/static/img/bg5.jpg
rename to static/img/bg5.jpg
diff --git a/src/static/img/card-danger.png b/static/img/card-danger.png
similarity index 100%
rename from src/static/img/card-danger.png
rename to static/img/card-danger.png
diff --git a/src/static/img/card-info.png b/static/img/card-info.png
similarity index 100%
rename from src/static/img/card-info.png
rename to static/img/card-info.png
diff --git a/src/static/img/card-primary.png b/static/img/card-primary.png
similarity index 100%
rename from src/static/img/card-primary.png
rename to static/img/card-primary.png
diff --git a/src/static/img/card-success.png b/static/img/card-success.png
similarity index 100%
rename from src/static/img/card-success.png
rename to static/img/card-success.png
diff --git a/src/static/img/card-warning.png b/static/img/card-warning.png
similarity index 100%
rename from src/static/img/card-warning.png
rename to static/img/card-warning.png
diff --git a/src/static/img/default-avatar.png b/static/img/default-avatar.png
similarity index 100%
rename from src/static/img/default-avatar.png
rename to static/img/default-avatar.png
diff --git a/src/static/img/desc.gif b/static/img/desc.gif
similarity index 100%
rename from src/static/img/desc.gif
rename to static/img/desc.gif
diff --git a/src/static/img/emilyz.jpg b/static/img/emilyz.jpg
similarity index 100%
rename from src/static/img/emilyz.jpg
rename to static/img/emilyz.jpg
diff --git a/src/static/img/favicon.png b/static/img/favicon.png
similarity index 100%
rename from src/static/img/favicon.png
rename to static/img/favicon.png
diff --git a/src/static/img/gucci.png b/static/img/gucci.png
similarity index 100%
rename from src/static/img/gucci.png
rename to static/img/gucci.png
diff --git a/src/static/img/header.jpg b/static/img/header.jpg
similarity index 100%
rename from src/static/img/header.jpg
rename to static/img/header.jpg
diff --git a/src/static/img/image_placeholder.jpg b/static/img/image_placeholder.jpg
similarity index 100%
rename from src/static/img/image_placeholder.jpg
rename to static/img/image_placeholder.jpg
diff --git a/src/static/img/img_3115.jpg b/static/img/img_3115.jpg
similarity index 100%
rename from src/static/img/img_3115.jpg
rename to static/img/img_3115.jpg
diff --git a/src/static/img/jacket.png b/static/img/jacket.png
similarity index 100%
rename from src/static/img/jacket.png
rename to static/img/jacket.png
diff --git a/src/static/img/james.jpg b/static/img/james.jpg
similarity index 100%
rename from src/static/img/james.jpg
rename to static/img/james.jpg
diff --git a/src/static/img/jana.jpg b/static/img/jana.jpg
similarity index 100%
rename from src/static/img/jana.jpg
rename to static/img/jana.jpg
diff --git a/src/static/img/lora.jpg b/static/img/lora.jpg
similarity index 100%
rename from src/static/img/lora.jpg
rename to static/img/lora.jpg
diff --git a/src/static/img/mike.jpg b/static/img/mike.jpg
similarity index 100%
rename from src/static/img/mike.jpg
rename to static/img/mike.jpg
diff --git a/src/static/img/placeholder.jpg b/static/img/placeholder.jpg
similarity index 100%
rename from src/static/img/placeholder.jpg
rename to static/img/placeholder.jpg
diff --git a/src/static/img/robi.jpg b/static/img/robi.jpg
similarity index 100%
rename from src/static/img/robi.jpg
rename to static/img/robi.jpg
diff --git a/src/static/img/saint-laurent.jpg b/static/img/saint-laurent.jpg
similarity index 100%
rename from src/static/img/saint-laurent.jpg
rename to static/img/saint-laurent.jpg
diff --git a/src/static/img/t-shirt.png b/static/img/t-shirt.png
similarity index 100%
rename from src/static/img/t-shirt.png
rename to static/img/t-shirt.png
diff --git a/src/static/img/tania.jpg b/static/img/tania.jpg
similarity index 100%
rename from src/static/img/tania.jpg
rename to static/img/tania.jpg
diff --git a/src/static/js/black-dashboard.js b/static/js/black-dashboard.js
similarity index 100%
rename from src/static/js/black-dashboard.js
rename to static/js/black-dashboard.js
diff --git a/src/static/js/black-dashboard.js.map b/static/js/black-dashboard.js.map
similarity index 100%
rename from src/static/js/black-dashboard.js.map
rename to static/js/black-dashboard.js.map
diff --git a/src/static/js/black-dashboard.min.js b/static/js/black-dashboard.min.js
similarity index 100%
rename from src/static/js/black-dashboard.min.js
rename to static/js/black-dashboard.min.js
diff --git a/src/static/js/core/bootstrap.min.js b/static/js/core/bootstrap.min.js
similarity index 100%
rename from src/static/js/core/bootstrap.min.js
rename to static/js/core/bootstrap.min.js
diff --git a/src/static/js/core/jquery.min.js b/static/js/core/jquery.min.js
similarity index 100%
rename from src/static/js/core/jquery.min.js
rename to static/js/core/jquery.min.js
diff --git a/src/static/js/core/popper.min.js b/static/js/core/popper.min.js
similarity index 100%
rename from src/static/js/core/popper.min.js
rename to static/js/core/popper.min.js
diff --git a/src/static/js/courseAdmin.js b/static/js/courseAdmin.js
similarity index 100%
rename from src/static/js/courseAdmin.js
rename to static/js/courseAdmin.js
diff --git a/src/static/js/plugins/bootstrap-datetimepicker.js b/static/js/plugins/bootstrap-datetimepicker.js
similarity index 100%
rename from src/static/js/plugins/bootstrap-datetimepicker.js
rename to static/js/plugins/bootstrap-datetimepicker.js
diff --git a/src/static/js/plugins/bootstrap-notify.js b/static/js/plugins/bootstrap-notify.js
similarity index 100%
rename from src/static/js/plugins/bootstrap-notify.js
rename to static/js/plugins/bootstrap-notify.js
diff --git a/src/static/js/plugins/bootstrap-selectpicker.js b/static/js/plugins/bootstrap-selectpicker.js
similarity index 100%
rename from src/static/js/plugins/bootstrap-selectpicker.js
rename to static/js/plugins/bootstrap-selectpicker.js
diff --git a/src/static/js/plugins/bootstrap-switch.js b/static/js/plugins/bootstrap-switch.js
similarity index 100%
rename from src/static/js/plugins/bootstrap-switch.js
rename to static/js/plugins/bootstrap-switch.js
diff --git a/src/static/js/plugins/bootstrap-tagsinput.js b/static/js/plugins/bootstrap-tagsinput.js
similarity index 100%
rename from src/static/js/plugins/bootstrap-tagsinput.js
rename to static/js/plugins/bootstrap-tagsinput.js
diff --git a/src/static/js/plugins/chartjs.min.js b/static/js/plugins/chartjs.min.js
similarity index 100%
rename from src/static/js/plugins/chartjs.min.js
rename to static/js/plugins/chartjs.min.js
diff --git a/src/static/js/plugins/fullcalendar.min.js b/static/js/plugins/fullcalendar.min.js
similarity index 100%
rename from src/static/js/plugins/fullcalendar.min.js
rename to static/js/plugins/fullcalendar.min.js
diff --git a/src/static/js/plugins/jasny-bootstrap.min.js b/static/js/plugins/jasny-bootstrap.min.js
similarity index 100%
rename from src/static/js/plugins/jasny-bootstrap.min.js
rename to static/js/plugins/jasny-bootstrap.min.js
diff --git a/src/static/js/plugins/jquery-jvectormap.js b/static/js/plugins/jquery-jvectormap.js
similarity index 100%
rename from src/static/js/plugins/jquery-jvectormap.js
rename to static/js/plugins/jquery-jvectormap.js
diff --git a/src/static/js/plugins/jquery.bootstrap-wizard.js b/static/js/plugins/jquery.bootstrap-wizard.js
similarity index 100%
rename from src/static/js/plugins/jquery.bootstrap-wizard.js
rename to static/js/plugins/jquery.bootstrap-wizard.js
diff --git a/src/static/js/plugins/jquery.dataTables.min.js b/static/js/plugins/jquery.dataTables.min.js
similarity index 100%
rename from src/static/js/plugins/jquery.dataTables.min.js
rename to static/js/plugins/jquery.dataTables.min.js
diff --git a/src/static/js/plugins/jquery.tablesorter.js b/static/js/plugins/jquery.tablesorter.js
similarity index 100%
rename from src/static/js/plugins/jquery.tablesorter.js
rename to static/js/plugins/jquery.tablesorter.js
diff --git a/src/static/js/plugins/jquery.validate.min.js b/static/js/plugins/jquery.validate.min.js
similarity index 100%
rename from src/static/js/plugins/jquery.validate.min.js
rename to static/js/plugins/jquery.validate.min.js
diff --git a/src/static/js/plugins/jqueryui/images/ui-bg_diagonals-thick_90_eeeeee_40x40.png b/static/js/plugins/jqueryui/images/ui-bg_diagonals-thick_90_eeeeee_40x40.png
similarity index 100%
rename from src/static/js/plugins/jqueryui/images/ui-bg_diagonals-thick_90_eeeeee_40x40.png
rename to static/js/plugins/jqueryui/images/ui-bg_diagonals-thick_90_eeeeee_40x40.png
diff --git a/src/static/js/plugins/jqueryui/images/ui-bg_glass_100_e4f1fb_1x400.png b/static/js/plugins/jqueryui/images/ui-bg_glass_100_e4f1fb_1x400.png
similarity index 100%
rename from src/static/js/plugins/jqueryui/images/ui-bg_glass_100_e4f1fb_1x400.png
rename to static/js/plugins/jqueryui/images/ui-bg_glass_100_e4f1fb_1x400.png
diff --git a/src/static/js/plugins/jqueryui/images/ui-bg_glass_50_3baae3_1x400.png b/static/js/plugins/jqueryui/images/ui-bg_glass_50_3baae3_1x400.png
similarity index 100%
rename from src/static/js/plugins/jqueryui/images/ui-bg_glass_50_3baae3_1x400.png
rename to static/js/plugins/jqueryui/images/ui-bg_glass_50_3baae3_1x400.png
diff --git a/src/static/js/plugins/jqueryui/images/ui-bg_glass_80_d7ebf9_1x400.png b/static/js/plugins/jqueryui/images/ui-bg_glass_80_d7ebf9_1x400.png
similarity index 100%
rename from src/static/js/plugins/jqueryui/images/ui-bg_glass_80_d7ebf9_1x400.png
rename to static/js/plugins/jqueryui/images/ui-bg_glass_80_d7ebf9_1x400.png
diff --git a/src/static/js/plugins/jqueryui/images/ui-bg_highlight-hard_100_f2f5f7_1x100.png b/static/js/plugins/jqueryui/images/ui-bg_highlight-hard_100_f2f5f7_1x100.png
similarity index 100%
rename from src/static/js/plugins/jqueryui/images/ui-bg_highlight-hard_100_f2f5f7_1x100.png
rename to static/js/plugins/jqueryui/images/ui-bg_highlight-hard_100_f2f5f7_1x100.png
diff --git a/src/static/js/plugins/jqueryui/images/ui-bg_highlight-hard_70_000000_1x100.png b/static/js/plugins/jqueryui/images/ui-bg_highlight-hard_70_000000_1x100.png
similarity index 100%
rename from src/static/js/plugins/jqueryui/images/ui-bg_highlight-hard_70_000000_1x100.png
rename to static/js/plugins/jqueryui/images/ui-bg_highlight-hard_70_000000_1x100.png
diff --git a/src/static/js/plugins/jqueryui/images/ui-bg_highlight-soft_100_deedf7_1x100.png b/static/js/plugins/jqueryui/images/ui-bg_highlight-soft_100_deedf7_1x100.png
similarity index 100%
rename from src/static/js/plugins/jqueryui/images/ui-bg_highlight-soft_100_deedf7_1x100.png
rename to static/js/plugins/jqueryui/images/ui-bg_highlight-soft_100_deedf7_1x100.png
diff --git a/src/static/js/plugins/jqueryui/images/ui-bg_highlight-soft_25_ffef8f_1x100.png b/static/js/plugins/jqueryui/images/ui-bg_highlight-soft_25_ffef8f_1x100.png
similarity index 100%
rename from src/static/js/plugins/jqueryui/images/ui-bg_highlight-soft_25_ffef8f_1x100.png
rename to static/js/plugins/jqueryui/images/ui-bg_highlight-soft_25_ffef8f_1x100.png
diff --git a/src/static/js/plugins/jqueryui/images/ui-icons_2694e8_256x240.png b/static/js/plugins/jqueryui/images/ui-icons_2694e8_256x240.png
similarity index 100%
rename from src/static/js/plugins/jqueryui/images/ui-icons_2694e8_256x240.png
rename to static/js/plugins/jqueryui/images/ui-icons_2694e8_256x240.png
diff --git a/src/static/js/plugins/jqueryui/images/ui-icons_2e83ff_256x240.png b/static/js/plugins/jqueryui/images/ui-icons_2e83ff_256x240.png
similarity index 100%
rename from src/static/js/plugins/jqueryui/images/ui-icons_2e83ff_256x240.png
rename to static/js/plugins/jqueryui/images/ui-icons_2e83ff_256x240.png
diff --git a/src/static/js/plugins/jqueryui/images/ui-icons_3d80b3_256x240.png b/static/js/plugins/jqueryui/images/ui-icons_3d80b3_256x240.png
similarity index 100%
rename from src/static/js/plugins/jqueryui/images/ui-icons_3d80b3_256x240.png
rename to static/js/plugins/jqueryui/images/ui-icons_3d80b3_256x240.png
diff --git a/src/static/js/plugins/jqueryui/images/ui-icons_72a7cf_256x240.png b/static/js/plugins/jqueryui/images/ui-icons_72a7cf_256x240.png
similarity index 100%
rename from src/static/js/plugins/jqueryui/images/ui-icons_72a7cf_256x240.png
rename to static/js/plugins/jqueryui/images/ui-icons_72a7cf_256x240.png
diff --git a/src/static/js/plugins/jqueryui/images/ui-icons_ffffff_256x240.png b/static/js/plugins/jqueryui/images/ui-icons_ffffff_256x240.png
similarity index 100%
rename from src/static/js/plugins/jqueryui/images/ui-icons_ffffff_256x240.png
rename to static/js/plugins/jqueryui/images/ui-icons_ffffff_256x240.png
diff --git a/src/static/js/plugins/jqueryui/index.html b/static/js/plugins/jqueryui/index.html
similarity index 100%
rename from src/static/js/plugins/jqueryui/index.html
rename to static/js/plugins/jqueryui/index.html
diff --git a/src/static/js/plugins/jqueryui/jquery-ui.css b/static/js/plugins/jqueryui/jquery-ui.css
similarity index 100%
rename from src/static/js/plugins/jqueryui/jquery-ui.css
rename to static/js/plugins/jqueryui/jquery-ui.css
diff --git a/src/static/js/plugins/jqueryui/jquery-ui.js b/static/js/plugins/jqueryui/jquery-ui.js
similarity index 100%
rename from src/static/js/plugins/jqueryui/jquery-ui.js
rename to static/js/plugins/jqueryui/jquery-ui.js
diff --git a/src/static/js/plugins/jqueryui/jquery-ui.min.css b/static/js/plugins/jqueryui/jquery-ui.min.css
similarity index 100%
rename from src/static/js/plugins/jqueryui/jquery-ui.min.css
rename to static/js/plugins/jqueryui/jquery-ui.min.css
diff --git a/src/static/js/plugins/jqueryui/jquery-ui.min.js b/static/js/plugins/jqueryui/jquery-ui.min.js
similarity index 100%
rename from src/static/js/plugins/jqueryui/jquery-ui.min.js
rename to static/js/plugins/jqueryui/jquery-ui.min.js
diff --git a/src/static/js/plugins/jqueryui/jquery-ui.structure.css b/static/js/plugins/jqueryui/jquery-ui.structure.css
similarity index 100%
rename from src/static/js/plugins/jqueryui/jquery-ui.structure.css
rename to static/js/plugins/jqueryui/jquery-ui.structure.css
diff --git a/src/static/js/plugins/jqueryui/jquery-ui.structure.min.css b/static/js/plugins/jqueryui/jquery-ui.structure.min.css
similarity index 100%
rename from src/static/js/plugins/jqueryui/jquery-ui.structure.min.css
rename to static/js/plugins/jqueryui/jquery-ui.structure.min.css
diff --git a/src/static/js/plugins/jqueryui/jquery-ui.theme.css b/static/js/plugins/jqueryui/jquery-ui.theme.css
similarity index 100%
rename from src/static/js/plugins/jqueryui/jquery-ui.theme.css
rename to static/js/plugins/jqueryui/jquery-ui.theme.css
diff --git a/src/static/js/plugins/jqueryui/jquery-ui.theme.min.css b/static/js/plugins/jqueryui/jquery-ui.theme.min.css
similarity index 100%
rename from src/static/js/plugins/jqueryui/jquery-ui.theme.min.css
rename to static/js/plugins/jqueryui/jquery-ui.theme.min.css
diff --git a/src/static/js/plugins/moment.min.js b/static/js/plugins/moment.min.js
similarity index 100%
rename from src/static/js/plugins/moment.min.js
rename to static/js/plugins/moment.min.js
diff --git a/src/static/js/plugins/nouislider.min.js b/static/js/plugins/nouislider.min.js
similarity index 100%
rename from src/static/js/plugins/nouislider.min.js
rename to static/js/plugins/nouislider.min.js
diff --git a/src/static/js/plugins/pdfmake.min.js.map b/static/js/plugins/pdfmake.min.js.map
similarity index 100%
rename from src/static/js/plugins/pdfmake.min.js.map
rename to static/js/plugins/pdfmake.min.js.map
diff --git a/src/static/js/plugins/perfect-scrollbar.jquery.min.js b/static/js/plugins/perfect-scrollbar.jquery.min.js
similarity index 100%
rename from src/static/js/plugins/perfect-scrollbar.jquery.min.js
rename to static/js/plugins/perfect-scrollbar.jquery.min.js
diff --git a/src/static/js/plugins/sweetalert2.min.js b/static/js/plugins/sweetalert2.min.js
similarity index 100%
rename from src/static/js/plugins/sweetalert2.min.js
rename to static/js/plugins/sweetalert2.min.js
diff --git a/src/static/js/routine.js b/static/js/routine.js
similarity index 100%
rename from src/static/js/routine.js
rename to static/js/routine.js
diff --git a/src/static/js/seasonAdmin.js b/static/js/seasonAdmin.js
similarity index 100%
rename from src/static/js/seasonAdmin.js
rename to static/js/seasonAdmin.js
diff --git a/src/static/js/skill.js b/static/js/skill.js
similarity index 100%
rename from src/static/js/skill.js
rename to static/js/skill.js
diff --git a/src/static/reglement/Sans titre.rtf b/static/reglement/Sans titre.rtf
similarity index 100%
rename from src/static/reglement/Sans titre.rtf
rename to static/reglement/Sans titre.rtf
diff --git a/src/static/reglement/info.rtf b/static/reglement/info.rtf
similarity index 100%
rename from src/static/reglement/info.rtf
rename to static/reglement/info.rtf
diff --git a/src/templates/accident_create.html b/templates/accident_create.html
similarity index 100%
rename from src/templates/accident_create.html
rename to templates/accident_create.html
diff --git a/src/templates/accident_details.html b/templates/accident_details.html
similarity index 100%
rename from src/templates/accident_details.html
rename to templates/accident_details.html
diff --git a/src/templates/accident_list.html b/templates/accident_list.html
similarity index 100%
rename from src/templates/accident_list.html
rename to templates/accident_list.html
diff --git a/src/templates/attendance.html b/templates/attendance.html
similarity index 100%
rename from src/templates/attendance.html
rename to templates/attendance.html
diff --git a/src/templates/base.html b/templates/base.html
similarity index 100%
rename from src/templates/base.html
rename to templates/base.html
diff --git a/src/templates/calendar.html b/templates/calendar.html
similarity index 100%
rename from src/templates/calendar.html
rename to templates/calendar.html
diff --git a/src/templates/chrono_create.html b/templates/chrono_create.html
similarity index 100%
rename from src/templates/chrono_create.html
rename to templates/chrono_create.html
diff --git a/src/templates/chrono_list.html b/templates/chrono_list.html
similarity index 100%
rename from src/templates/chrono_list.html
rename to templates/chrono_list.html
diff --git a/src/templates/club_statistics.html b/templates/club_statistics.html
similarity index 100%
rename from src/templates/club_statistics.html
rename to templates/club_statistics.html
diff --git a/src/templates/course_details.html b/templates/course_details.html
similarity index 100%
rename from src/templates/course_details.html
rename to templates/course_details.html
diff --git a/src/templates/event_create.html b/templates/event_create.html
similarity index 100%
rename from src/templates/event_create.html
rename to templates/event_create.html
diff --git a/src/templates/event_details.html b/templates/event_details.html
similarity index 100%
rename from src/templates/event_details.html
rename to templates/event_details.html
diff --git a/src/templates/event_list.html b/templates/event_list.html
similarity index 100%
rename from src/templates/event_list.html
rename to templates/event_list.html
diff --git a/src/templates/gymnast_accident.html b/templates/gymnast_accident.html
similarity index 100%
rename from src/templates/gymnast_accident.html
rename to templates/gymnast_accident.html
diff --git a/src/templates/gymnast_chrono.html b/templates/gymnast_chrono.html
similarity index 100%
rename from src/templates/gymnast_chrono.html
rename to templates/gymnast_chrono.html
diff --git a/src/templates/gymnast_create.html b/templates/gymnast_create.html
similarity index 100%
rename from src/templates/gymnast_create.html
rename to templates/gymnast_create.html
diff --git a/src/templates/gymnast_details.html b/templates/gymnast_details.html
similarity index 100%
rename from src/templates/gymnast_details.html
rename to templates/gymnast_details.html
diff --git a/src/templates/gymnast_display_level.html b/templates/gymnast_display_level.html
similarity index 100%
rename from src/templates/gymnast_display_level.html
rename to templates/gymnast_display_level.html
diff --git a/src/templates/gymnast_event.html b/templates/gymnast_event.html
similarity index 100%
rename from src/templates/gymnast_event.html
rename to templates/gymnast_event.html
diff --git a/src/templates/gymnast_event_accident.html b/templates/gymnast_event_accident.html
similarity index 100%
rename from src/templates/gymnast_event_accident.html
rename to templates/gymnast_event_accident.html
diff --git a/src/templates/gymnast_list.html b/templates/gymnast_list.html
similarity index 100%
rename from src/templates/gymnast_list.html
rename to templates/gymnast_list.html
diff --git a/src/templates/gymnast_objective.html b/templates/gymnast_objective.html
similarity index 100%
rename from src/templates/gymnast_objective.html
rename to templates/gymnast_objective.html
diff --git a/src/templates/gymnast_program.html b/templates/gymnast_program.html
similarity index 100%
rename from src/templates/gymnast_program.html
rename to templates/gymnast_program.html
diff --git a/src/templates/gymnast_rounds.html b/templates/gymnast_rounds.html
similarity index 100%
rename from src/templates/gymnast_rounds.html
rename to templates/gymnast_rounds.html
diff --git a/src/templates/gymnast_routine.html b/templates/gymnast_routine.html
similarity index 100%
rename from src/templates/gymnast_routine.html
rename to templates/gymnast_routine.html
diff --git a/src/templates/gymnast_scores.html b/templates/gymnast_scores.html
similarity index 100%
rename from src/templates/gymnast_scores.html
rename to templates/gymnast_scores.html
diff --git a/src/templates/gymnast_scores_chrono.html b/templates/gymnast_scores_chrono.html
similarity index 100%
rename from src/templates/gymnast_scores_chrono.html
rename to templates/gymnast_scores_chrono.html
diff --git a/src/templates/gymnast_statistics.html b/templates/gymnast_statistics.html
similarity index 100%
rename from src/templates/gymnast_statistics.html
rename to templates/gymnast_statistics.html
diff --git a/src/templates/gymnast_to_routine.html b/templates/gymnast_to_routine.html
similarity index 100%
rename from src/templates/gymnast_to_routine.html
rename to templates/gymnast_to_routine.html
diff --git a/src/templates/index.html b/templates/index.html
similarity index 100%
rename from src/templates/index.html
rename to templates/index.html
diff --git a/src/templates/judge_training_diff.html b/templates/judge_training_diff.html
similarity index 100%
rename from src/templates/judge_training_diff.html
rename to templates/judge_training_diff.html
diff --git a/src/templates/listing.html b/templates/listing.html
similarity index 100%
rename from src/templates/listing.html
rename to templates/listing.html
diff --git a/src/templates/login.html b/templates/login.html
similarity index 100%
rename from src/templates/login.html
rename to templates/login.html
diff --git a/src/templates/message_create.html b/templates/message_create.html
similarity index 100%
rename from src/templates/message_create.html
rename to templates/message_create.html
diff --git a/src/templates/message_details.html b/templates/message_details.html
similarity index 100%
rename from src/templates/message_details.html
rename to templates/message_details.html
diff --git a/src/templates/message_list.html b/templates/message_list.html
similarity index 100%
rename from src/templates/message_list.html
rename to templates/message_list.html
diff --git a/src/templates/place_create.html b/templates/place_create.html
similarity index 100%
rename from src/templates/place_create.html
rename to templates/place_create.html
diff --git a/src/templates/place_details.html b/templates/place_details.html
similarity index 100%
rename from src/templates/place_details.html
rename to templates/place_details.html
diff --git a/src/templates/place_list.html b/templates/place_list.html
similarity index 100%
rename from src/templates/place_list.html
rename to templates/place_list.html
diff --git a/src/templates/planningline_create.html b/templates/planningline_create.html
similarity index 100%
rename from src/templates/planningline_create.html
rename to templates/planningline_create.html
diff --git a/src/templates/profile_create.html b/templates/profile_create.html
similarity index 100%
rename from src/templates/profile_create.html
rename to templates/profile_create.html
diff --git a/src/templates/program.html b/templates/program.html
similarity index 100%
rename from src/templates/program.html
rename to templates/program.html
diff --git a/src/templates/program_day.html b/templates/program_day.html
similarity index 100%
rename from src/templates/program_day.html
rename to templates/program_day.html
diff --git a/src/templates/program_list.html b/templates/program_list.html
similarity index 100%
rename from src/templates/program_list.html
rename to templates/program_list.html
diff --git a/src/templates/program_old.html b/templates/program_old.html
similarity index 100%
rename from src/templates/program_old.html
rename to templates/program_old.html
diff --git a/src/templates/results.html b/templates/results.html
similarity index 100%
rename from src/templates/results.html
rename to templates/results.html
diff --git a/src/templates/routine_compose.html b/templates/routine_compose.html
similarity index 100%
rename from src/templates/routine_compose.html
rename to templates/routine_compose.html
diff --git a/src/templates/routine_create.html b/templates/routine_create.html
similarity index 100%
rename from src/templates/routine_create.html
rename to templates/routine_create.html
diff --git a/src/templates/routine_details.html b/templates/routine_details.html
similarity index 100%
rename from src/templates/routine_details.html
rename to templates/routine_details.html
diff --git a/src/templates/routine_list.html b/templates/routine_list.html
similarity index 100%
rename from src/templates/routine_list.html
rename to templates/routine_list.html
diff --git a/src/templates/score_create.html b/templates/score_create.html
similarity index 100%
rename from src/templates/score_create.html
rename to templates/score_create.html
diff --git a/src/templates/score_list.html b/templates/score_list.html
similarity index 100%
rename from src/templates/score_list.html
rename to templates/score_list.html
diff --git a/src/templates/skill_details.html b/templates/skill_details.html
similarity index 100%
rename from src/templates/skill_details.html
rename to templates/skill_details.html
diff --git a/src/templates/skill_list.html b/templates/skill_list.html
similarity index 100%
rename from src/templates/skill_list.html
rename to templates/skill_list.html
diff --git a/src/templates/training_detail.html b/templates/training_detail.html
similarity index 100%
rename from src/templates/training_detail.html
rename to templates/training_detail.html
diff --git a/src/templates/unavailability_create.html b/templates/unavailability_create.html
similarity index 100%
rename from src/templates/unavailability_create.html
rename to templates/unavailability_create.html
diff --git a/src/templates/unavailability_details.html b/templates/unavailability_details.html
similarity index 100%
rename from src/templates/unavailability_details.html
rename to templates/unavailability_details.html
diff --git a/src/templates/unavailability_list.html b/templates/unavailability_list.html
similarity index 100%
rename from src/templates/unavailability_list.html
rename to templates/unavailability_list.html