From 4da5add25ab9e1172900a022456e0980cb83a8dc Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Wed, 26 Jun 2019 09:57:16 -0700 Subject: [PATCH 1/9] Move `choices_length` to shared folder --- gestioncof/models.py | 2 +- kfet/models.py | 6 +----- petitscours/models.py | 7 +------ shared/utils.py | 5 +++++ 4 files changed, 8 insertions(+), 12 deletions(-) create mode 100644 shared/utils.py diff --git a/gestioncof/models.py b/gestioncof/models.py index e4975fc4..c2c71660 100644 --- a/gestioncof/models.py +++ b/gestioncof/models.py @@ -5,7 +5,7 @@ from django.dispatch import receiver from django.utils.translation import ugettext_lazy as _ from bda.models import Spectacle -from petitscours.models import choices_length +from shared.utils import choices_length TYPE_COMMENT_FIELD = (("text", _("Texte long")), ("char", _("Texte court"))) diff --git a/kfet/models.py b/kfet/models.py index 5d8ad3cb..a2d776b9 100644 --- a/kfet/models.py +++ b/kfet/models.py @@ -1,6 +1,5 @@ import re from datetime import date -from functools import reduce from django.contrib.auth.models import User from django.core.validators import RegexValidator @@ -11,6 +10,7 @@ from django.utils import timezone from django.utils.translation import ugettext_lazy as _ from gestioncof.models import CofProfile +from shared.utils import choices_length from . import KFET_DELETED_TRIGRAMME from .auth import KFET_GENERIC_TRIGRAMME @@ -19,10 +19,6 @@ from .config import kfet_config from .utils import to_ukf -def choices_length(choices): - return reduce(lambda m, choice: max(m, len(choice[0])), choices, 0) - - def default_promo(): now = date.today() return now.month <= 8 and now.year - 1 or now.year diff --git a/petitscours/models.py b/petitscours/models.py index cc518675..27b5e931 100644 --- a/petitscours/models.py +++ b/petitscours/models.py @@ -1,15 +1,10 @@ -from functools import reduce - from django.contrib.auth.models import User from django.db import models from django.db.models import Min from django.utils.functional import cached_property from django.utils.translation import ugettext_lazy as _ - -def choices_length(choices): - return reduce(lambda m, choice: max(m, len(choice[0])), choices, 0) - +from shared.utils import choices_length LEVELS_CHOICES = ( ("college", _("Collège")), diff --git a/shared/utils.py b/shared/utils.py new file mode 100644 index 00000000..ea4aa0dd --- /dev/null +++ b/shared/utils.py @@ -0,0 +1,5 @@ +from functools import reduce + + +def choices_length(choices): + return reduce(lambda m, choice: max(m, len(choice[0])), choices, 0) From bc7c30e2ee3d0eda3f37c006c95e0b6049bad881 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Wed, 17 Jul 2019 14:34:18 +0200 Subject: [PATCH 2/9] Init app + models MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le modèle de profil BDS est le seul utile pour l'instant ; c'est un mix entre `CofProfile` et les modèles de Sport@Ulm. --- bds/__init__.py | 0 bds/admin.py | 1 + bds/apps.py | 5 ++ bds/migrations/__init__.py | 0 bds/models.py | 93 ++++++++++++++++++++++++++++++++++++++ bds/views.py | 1 + 6 files changed, 100 insertions(+) create mode 100644 bds/__init__.py create mode 100644 bds/admin.py create mode 100644 bds/apps.py create mode 100644 bds/migrations/__init__.py create mode 100644 bds/models.py create mode 100644 bds/views.py diff --git a/bds/__init__.py b/bds/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/bds/admin.py b/bds/admin.py new file mode 100644 index 00000000..846f6b40 --- /dev/null +++ b/bds/admin.py @@ -0,0 +1 @@ +# Register your models here. diff --git a/bds/apps.py b/bds/apps.py new file mode 100644 index 00000000..db0cafcb --- /dev/null +++ b/bds/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class BdsConfig(AppConfig): + name = "bds" diff --git a/bds/migrations/__init__.py b/bds/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/bds/models.py b/bds/models.py new file mode 100644 index 00000000..0b73c964 --- /dev/null +++ b/bds/models.py @@ -0,0 +1,93 @@ +from datetime import date +from os.path import splitext + +from django.contrib.auth import get_user_model +from django.db import models +from django.utils.translation import ugettext_lazy as _ + +from shared.utils import choices_length + +User = get_user_model() + + +class BDSProfile(models.Model): + OCCUPATION_CHOICES = ( + ("EXT", "Extérieur"), + ("1A", "1A"), + ("2A", "2A"), + ("3A", "3A"), + ("4A", "4A"), + ("MAG", "Magistérien"), + ("ARC", "Archicube"), + ("DOC", "Doctorant"), + ("CST", "CST"), + ("PER", "Personnel ENS"), + ) + + TYPE_COTIZ_CHOICES = ( + ("ETU", "Étudiant"), + ("NOR", "Normalien"), + ("EXT", "Extérieur"), + ("ARC", "Archicube"), + ) + + COTIZ_DURATION_CHOICES = ( + ("ANN", "Année"), + ("SE1", "Premier semestre"), + ("SE2", "Deuxième semestre"), + ("NO", "Aucune"), + ) + + def get_certificate_filename(instance, filename): + _, ext = splitext(filename) # récupère l'extension du fichier + year = str(date.now().year) + return "certifs/{username}-{year}.{ext}".format( + username=instance.user.username, year=year, ext=ext + ) + + user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="bds") + phone = models.CharField(_("Téléphone"), max_length=20, blank=True) + occupation = models.CharField( + _("Occupation"), + default="1A", + choices=OCCUPATION_CHOICES, + max_length=choices_length(OCCUPATION_CHOICES), + ) + departement = models.CharField(_("Département"), max_length=50, blank=True) + birthdate = models.DateField( + auto_now_add=False, + auto_now=False, + verbose_name="Date de naissance", + blank=True, + null=True, + ) + + mails_bds = models.BooleanField(_("Recevoir les mails du BDS"), default=False) + is_buro = models.BooleanField(_("Membre du Burô du BDS"), default=False) + + has_certificate = models.BooleanField(_("Certificat médical"), default=False) + certificate_file = models.FileField( + _("Fichier de certificat médical"), + upload_to=get_certificate_filename, + blank=True, + ) + + ASPSL_number = models.CharField( + "Numéro AS PSL", max_length=50, blank=True, null=True + ) + FFSU_number = models.CharField("Numéro FFSU", max_length=50, blank=True, null=True) + + cotisation_period = models.CharField( + "Inscription", default="NO", choices=COTIZ_DURATION_CHOICES, max_length=3 + ) + + registration_date = models.DateField( + auto_now_add=True, verbose_name="Date d'inscription" + ) + + class Meta: + verbose_name = "Profil BDS" + verbose_name_plural = "Profils BDS" + + def __str__(self): + return self.user.username diff --git a/bds/views.py b/bds/views.py new file mode 100644 index 00000000..60f00ef0 --- /dev/null +++ b/bds/views.py @@ -0,0 +1 @@ +# Create your views here. From b3e7b599033f918bd0a44ad8c054c213410b248f Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Wed, 17 Jul 2019 17:50:53 +0200 Subject: [PATCH 3/9] Migrations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Une migration pour les modèles, et une pour créer le groupe du Burô du BDS --- bds/migrations/0001_initial.py | 141 +++++++++++++++++++++++++++++++ bds/migrations/0002_bds_group.py | 30 +++++++ cof/settings/common.py | 1 + 3 files changed, 172 insertions(+) create mode 100644 bds/migrations/0001_initial.py create mode 100644 bds/migrations/0002_bds_group.py diff --git a/bds/migrations/0001_initial.py b/bds/migrations/0001_initial.py new file mode 100644 index 00000000..fe721897 --- /dev/null +++ b/bds/migrations/0001_initial.py @@ -0,0 +1,141 @@ +# Generated by Django 2.2 on 2019-07-17 12:48 + +import bds.models +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [migrations.swappable_dependency(settings.AUTH_USER_MODEL)] + + operations = [ + migrations.CreateModel( + name="BDSProfile", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "phone", + models.CharField( + blank=True, max_length=20, verbose_name="Téléphone" + ), + ), + ( + "occupation", + models.CharField( + choices=[ + ("EXT", "Extérieur"), + ("1A", "1A"), + ("2A", "2A"), + ("3A", "3A"), + ("4A", "4A"), + ("MAG", "Magistérien"), + ("ARC", "Archicube"), + ("DOC", "Doctorant"), + ("CST", "CST"), + ("PER", "Personnel ENS"), + ], + default="1A", + max_length=3, + verbose_name="Occupation", + ), + ), + ( + "departement", + models.CharField( + blank=True, max_length=50, verbose_name="Département" + ), + ), + ( + "birthdate", + models.DateField( + blank=True, null=True, verbose_name="Date de naissance" + ), + ), + ( + "mails_bds", + models.BooleanField( + default=False, verbose_name="Recevoir les mails du BDS" + ), + ), + ( + "is_buro", + models.BooleanField( + default=False, verbose_name="Membre du Burô du BDS" + ), + ), + ( + "has_certificate", + models.BooleanField( + default=False, verbose_name="Certificat médical" + ), + ), + ( + "certificate_file", + models.FileField( + blank=True, + upload_to=bds.models.BDSProfile.get_certificate_filename, + verbose_name="Fichier de certificat médical", + ), + ), + ( + "ASPSL_number", + models.CharField( + blank=True, + max_length=50, + null=True, + verbose_name="Numéro AS PSL", + ), + ), + ( + "FFSU_number", + models.CharField( + blank=True, max_length=50, null=True, verbose_name="Numéro FFSU" + ), + ), + ( + "cotisation_period", + models.CharField( + choices=[ + ("ANN", "Année"), + ("SE1", "Premier semestre"), + ("SE2", "Deuxième semestre"), + ("NO", "Aucune"), + ], + default="NO", + max_length=3, + verbose_name="Inscription", + ), + ), + ( + "registration_date", + models.DateField( + auto_now_add=True, verbose_name="Date d'inscription" + ), + ), + ( + "user", + models.OneToOneField( + on_delete=django.db.models.deletion.CASCADE, + related_name="bds", + to=settings.AUTH_USER_MODEL, + ), + ), + ], + options={ + "verbose_name": "Profil BDS", + "verbose_name_plural": "Profils BDS", + }, + ) + ] diff --git a/bds/migrations/0002_bds_group.py b/bds/migrations/0002_bds_group.py new file mode 100644 index 00000000..9b54d35c --- /dev/null +++ b/bds/migrations/0002_bds_group.py @@ -0,0 +1,30 @@ +# Generated by Django 2.2 on 2019-07-17 14:56 + +from django.contrib.auth.management import create_permissions +from django.db import migrations +from django.db.models import Q + + +def create_bds_buro_group(apps, schema_editor): + for app_config in apps.get_app_configs(): + create_permissions(app_config, apps=apps, verbosity=0) + + Group = apps.get_model("auth", "Group") + Permission = apps.get_model("auth", "Permission") + group, created = Group.objects.get_or_create(name="Burô du BDS") + if created: + perms = Permission.objects.filter( + Q(content_type__app_label="bds") + | Q(content_type__app_label="auth") & Q(content_type__model="user") + ) + group.permissions.set(perms) + group.save() + + +class Migration(migrations.Migration): + + dependencies = [("bds", "0001_initial")] + + operations = [ + migrations.RunPython(create_bds_buro_group, migrations.RunPython.noop) + ] diff --git a/cof/settings/common.py b/cof/settings/common.py index 1b6f3bd1..dc59d0f1 100644 --- a/cof/settings/common.py +++ b/cof/settings/common.py @@ -103,6 +103,7 @@ INSTALLED_APPS = [ "kfet.auth", "kfet.cms", "gestioncof.cms", + "bds", ] From 53ea6f24ee453133997b5ce4b9bb3e57bc9af12a Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Thu, 18 Jul 2019 15:43:03 +0200 Subject: [PATCH 4/9] Isort setup --- bds/migrations/0001_initial.py | 3 ++- setup.cfg | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/bds/migrations/0001_initial.py b/bds/migrations/0001_initial.py index fe721897..b52027d4 100644 --- a/bds/migrations/0001_initial.py +++ b/bds/migrations/0001_initial.py @@ -1,10 +1,11 @@ # Generated by Django 2.2 on 2019-07-17 12:48 -import bds.models import django.db.models.deletion from django.conf import settings from django.db import migrations, models +import bds.models + class Migration(migrations.Migration): diff --git a/setup.cfg b/setup.cfg index 350ceb20..7695596d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,7 @@ [coverage:run] source = bda + bds cof events gestioncof @@ -35,7 +36,7 @@ default_section = THIRDPARTY force_grid_wrap = 0 include_trailing_comma = true known_django = django -known_first_party = bda,cof,events,gestioncof,kfet,petitscours,shared,utils +known_first_party = bda,bds,cof,events,gestioncof,kfet,petitscours,shared,utils line_length = 88 multi_line_output = 3 not_skip = __init__.py From 53efb4b5420eaf5fe4634ddcb17f42b958adfbcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Sun, 6 Oct 2019 18:43:58 +0200 Subject: [PATCH 5/9] Enable bds checks in CI --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 4cc57807..8fcf9966 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -52,9 +52,9 @@ linters: - pip install --upgrade black isort flake8 script: - black --check . - - isort --recursive --check-only --diff bda cof events gestioncof kfet petitscours provisioning shared utils + - isort --recursive --check-only --diff bda bds cof events gestioncof kfet petitscours provisioning shared utils # Print errors only - - flake8 --exit-zero bda cof events gestioncof kfet petitscours provisioning shared utils + - flake8 --exit-zero bda bds cof events gestioncof kfet petitscours provisioning shared utils cache: key: linters paths: From e2a7e1f6de7ccd6f509d537244ef2add110c5f8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Sun, 6 Oct 2019 18:48:37 +0200 Subject: [PATCH 6/9] BDSProfile: enable the default admin --- bds/admin.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/bds/admin.py b/bds/admin.py index 846f6b40..e7181670 100644 --- a/bds/admin.py +++ b/bds/admin.py @@ -1 +1,5 @@ -# Register your models here. +from django.contrib import admin + +from bds.models import BDSProfile + +admin.site.register(BDSProfile) From f9aee86a1cdb04fc82987f0d47cc7609e6307fd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Sun, 6 Oct 2019 18:54:32 +0200 Subject: [PATCH 7/9] Only enable the bds app in development --- cof/settings/common.py | 1 - cof/settings/dev.py | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/cof/settings/common.py b/cof/settings/common.py index dc59d0f1..1b6f3bd1 100644 --- a/cof/settings/common.py +++ b/cof/settings/common.py @@ -103,7 +103,6 @@ INSTALLED_APPS = [ "kfet.auth", "kfet.cms", "gestioncof.cms", - "bds", ] diff --git a/cof/settings/dev.py b/cof/settings/dev.py index 0920e538..db7a52cb 100644 --- a/cof/settings/dev.py +++ b/cof/settings/dev.py @@ -15,9 +15,9 @@ DEBUG = True if TESTING: PASSWORD_HASHERS = ["django.contrib.auth.hashers.MD5PasswordHasher"] -# Only in development mode as long as the events app is not -# ready for production -INSTALLED_APPS += ["events"] +# As long as these apps are not ready for production, they are only available +# in development mode +INSTALLED_APPS += ["events", "bds"] # --- From 98fe68d0be1801d8a40744ad1084bb05d13c87e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Sun, 6 Oct 2019 19:03:19 +0200 Subject: [PATCH 8/9] Translation fixes in bds.models - the 'u' in ugettext_lazy in a legacy of python2, we can drop it now - translate all verbose names - start field verbose names with a lowercase letter --- bds/migrations/0001_initial.py | 24 ++++++++++++------------ bds/models.py | 32 +++++++++++++++++--------------- 2 files changed, 29 insertions(+), 27 deletions(-) diff --git a/bds/migrations/0001_initial.py b/bds/migrations/0001_initial.py index b52027d4..e6fe5377 100644 --- a/bds/migrations/0001_initial.py +++ b/bds/migrations/0001_initial.py @@ -29,7 +29,7 @@ class Migration(migrations.Migration): ( "phone", models.CharField( - blank=True, max_length=20, verbose_name="Téléphone" + blank=True, max_length=20, verbose_name="téléphone" ), ), ( @@ -49,37 +49,37 @@ class Migration(migrations.Migration): ], default="1A", max_length=3, - verbose_name="Occupation", + verbose_name="occupation", ), ), ( "departement", models.CharField( - blank=True, max_length=50, verbose_name="Département" + blank=True, max_length=50, verbose_name="département" ), ), ( "birthdate", models.DateField( - blank=True, null=True, verbose_name="Date de naissance" + blank=True, null=True, verbose_name="date de naissance" ), ), ( "mails_bds", models.BooleanField( - default=False, verbose_name="Recevoir les mails du BDS" + default=False, verbose_name="recevoir les mails du BDS" ), ), ( "is_buro", models.BooleanField( - default=False, verbose_name="Membre du Burô du BDS" + default=False, verbose_name="membre du Burô du BDS" ), ), ( "has_certificate", models.BooleanField( - default=False, verbose_name="Certificat médical" + default=False, verbose_name="certificat médical" ), ), ( @@ -87,7 +87,7 @@ class Migration(migrations.Migration): models.FileField( blank=True, upload_to=bds.models.BDSProfile.get_certificate_filename, - verbose_name="Fichier de certificat médical", + verbose_name="fichier de certificat médical", ), ), ( @@ -96,13 +96,13 @@ class Migration(migrations.Migration): blank=True, max_length=50, null=True, - verbose_name="Numéro AS PSL", + verbose_name="numéro AS PSL", ), ), ( "FFSU_number", models.CharField( - blank=True, max_length=50, null=True, verbose_name="Numéro FFSU" + blank=True, max_length=50, null=True, verbose_name="numéro FFSU" ), ), ( @@ -116,13 +116,13 @@ class Migration(migrations.Migration): ], default="NO", max_length=3, - verbose_name="Inscription", + verbose_name="inscription", ), ), ( "registration_date", models.DateField( - auto_now_add=True, verbose_name="Date d'inscription" + auto_now_add=True, verbose_name="date d'inscription" ), ), ( diff --git a/bds/models.py b/bds/models.py index 0b73c964..f262ee26 100644 --- a/bds/models.py +++ b/bds/models.py @@ -3,7 +3,7 @@ from os.path import splitext from django.contrib.auth import get_user_model from django.db import models -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from shared.utils import choices_length @@ -46,48 +46,50 @@ class BDSProfile(models.Model): ) user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="bds") - phone = models.CharField(_("Téléphone"), max_length=20, blank=True) + phone = models.CharField(_("téléphone"), max_length=20, blank=True) occupation = models.CharField( - _("Occupation"), + _("occupation"), default="1A", choices=OCCUPATION_CHOICES, max_length=choices_length(OCCUPATION_CHOICES), ) - departement = models.CharField(_("Département"), max_length=50, blank=True) + departement = models.CharField(_("département"), max_length=50, blank=True) birthdate = models.DateField( auto_now_add=False, auto_now=False, - verbose_name="Date de naissance", + verbose_name=_("date de naissance"), blank=True, null=True, ) - mails_bds = models.BooleanField(_("Recevoir les mails du BDS"), default=False) - is_buro = models.BooleanField(_("Membre du Burô du BDS"), default=False) + mails_bds = models.BooleanField(_("recevoir les mails du BDS"), default=False) + is_buro = models.BooleanField(_("membre du Burô du BDS"), default=False) - has_certificate = models.BooleanField(_("Certificat médical"), default=False) + has_certificate = models.BooleanField(_("certificat médical"), default=False) certificate_file = models.FileField( - _("Fichier de certificat médical"), + _("fichier de certificat médical"), upload_to=get_certificate_filename, blank=True, ) ASPSL_number = models.CharField( - "Numéro AS PSL", max_length=50, blank=True, null=True + _("numéro AS PSL"), max_length=50, blank=True, null=True + ) + FFSU_number = models.CharField( + _("numéro FFSU"), max_length=50, blank=True, null=True ) - FFSU_number = models.CharField("Numéro FFSU", max_length=50, blank=True, null=True) cotisation_period = models.CharField( - "Inscription", default="NO", choices=COTIZ_DURATION_CHOICES, max_length=3 + _("inscription"), default="NO", choices=COTIZ_DURATION_CHOICES, max_length=3 ) registration_date = models.DateField( - auto_now_add=True, verbose_name="Date d'inscription" + auto_now_add=True, verbose_name=_("date d'inscription") ) class Meta: - verbose_name = "Profil BDS" - verbose_name_plural = "Profils BDS" + verbose_name = _("Profil BDS") + verbose_name_plural = _("Profils BDS") def __str__(self): return self.user.username From e94015a1421dd8a9bee7d1b1372b8f9c76ca26a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Sun, 6 Oct 2019 19:06:30 +0200 Subject: [PATCH 9/9] Update changelog --- CHANGELOG | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 3d787bf1..81b06df9 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ -* Le FUTUR ! +* Le FUTUR ! (pas prêt pour la prod) -- Nouveau module de gestion des événements (début d'implem, désactivé en prod) +- Nouveau module de gestion des événements +- Nouveau module BDS * Version 0.3 - ???