From a78aff9f9db08856aea9e891d9f1a3708902085d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Mogu=C3=A9rou?= Date: Mon, 6 May 2024 23:33:50 +0200 Subject: [PATCH] Add datetime support --- colloscope/icalexport.py | 4 +- ...lle_options_alter_slot_options_and_more.py | 255 ++++++++++++++++++ .../0014_alter_group_options_slot_type.py | 24 ++ .../0015_rename_lycee_class_school.py | 18 ++ .../migrations/0016_alter_colle_groups.py | 18 ++ ..._options_alter_subject_options_and_more.py | 47 ++++ colloscope/models.py | 14 +- colloscope/pdfexport.py | 4 +- colloscope/serializers.py | 14 +- colloscope/templates/dashboard.html | 2 +- colloscope/templates/marketplace.html | 2 +- colloscope/views.py | 6 +- colloscope/viewsets.py | 9 +- kholles_web/urls.py | 5 +- 14 files changed, 401 insertions(+), 21 deletions(-) create mode 100644 colloscope/migrations/0013_alter_colle_options_alter_slot_options_and_more.py create mode 100644 colloscope/migrations/0014_alter_group_options_slot_type.py create mode 100644 colloscope/migrations/0015_rename_lycee_class_school.py create mode 100644 colloscope/migrations/0016_alter_colle_groups.py create mode 100644 colloscope/migrations/0017_alter_slot_options_alter_subject_options_and_more.py diff --git a/colloscope/icalexport.py b/colloscope/icalexport.py index 912fab0..7c43899 100644 --- a/colloscope/icalexport.py +++ b/colloscope/icalexport.py @@ -36,7 +36,7 @@ def to_calendar(student, term, include_EDT: bool = True): summary = f"Colle {colle.slot.subject} ({colle.slot.colleur})" event.add("summary", summary) - start = colle.datetime() + start = colle.datetime fin = start + colle.slot.duration event.add("dtstart", start, parameters={"tzid": LOCAL_TZ}) @@ -56,7 +56,7 @@ def to_calendar(student, term, include_EDT: bool = True): event.add("organizer", organizer) for e in colle.final_group(): - attendee = vCalAddress("mailto:{emailize(e.name, first_name=e.first_name)}") + attendee = vCalAddress(f"mailto:{emailize(e.last_name, first_name=e.first_name)}") attendee.params["role"] = vText("Etudiant") attendee.params["cn"] = vText(str(e)) diff --git a/colloscope/migrations/0013_alter_colle_options_alter_slot_options_and_more.py b/colloscope/migrations/0013_alter_colle_options_alter_slot_options_and_more.py new file mode 100644 index 0000000..3da9669 --- /dev/null +++ b/colloscope/migrations/0013_alter_colle_options_alter_slot_options_and_more.py @@ -0,0 +1,255 @@ +# Generated by Django 5.0.4 on 2024-05-02 20:00 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('colloscope', '0012_rename_lycee_school_rename_creneau_slot_and_more'), + ] + + operations = [ + migrations.AlterModelOptions( + name='colle', + options={'ordering': ['slot__term__cls', 'slot__subject__description', 'slot__colleur__name', 'date', 'slot__time']}, + ), + migrations.AlterModelOptions( + name='slot', + options={'verbose_name_plural': 'slots'}, + ), + migrations.AlterModelOptions( + name='student', + options={'ordering': ['cls', 'last_name', 'first_name']}, + ), + migrations.AlterModelOptions( + name='term', + options={'ordering': ['begin']}, + ), + migrations.RemoveConstraint( + model_name='calendarlink', + name='unique_etudiant_periode_combination', + ), + migrations.RenameField( + model_name='calendarlink', + old_name='code', + new_name='key', + ), + migrations.RenameField( + model_name='calendarlink', + old_name='etudiant', + new_name='student', + ), + migrations.RenameField( + model_name='calendarlink', + old_name='periode', + new_name='term', + ), + migrations.RenameField( + model_name='class', + old_name='jour_zero', + new_name='day_zero', + ), + migrations.RenameField( + model_name='class', + old_name='libelle', + new_name='description', + ), + migrations.RenameField( + model_name='class', + old_name='annee', + new_name='year', + ), + migrations.RenameField( + model_name='colle', + old_name='groupes', + new_name='groups', + ), + migrations.RenameField( + model_name='colle', + old_name='creneau', + new_name='slot', + ), + migrations.RenameField( + model_name='colleur', + old_name='civilite', + new_name='gender', + ), + migrations.RenameField( + model_name='colleur', + old_name='nom', + new_name='name', + ), + migrations.RenameField( + model_name='group', + old_name='libelle', + new_name='description', + ), + migrations.RenameField( + model_name='group', + old_name='membres', + new_name='members', + ), + migrations.RenameField( + model_name='group', + old_name='periode', + new_name='term', + ), + migrations.RenameField( + model_name='group', + old_name='critere', + new_name='type', + ), + migrations.RenameField( + model_name='grouptype', + old_name='libelle', + new_name='description', + ), + migrations.RenameField( + model_name='grouptype', + old_name='periode', + new_name='term', + ), + migrations.RenameField( + model_name='member', + old_name='groupe', + new_name='group', + ), + migrations.RenameField( + model_name='member', + old_name='etudiant', + new_name='student', + ), + migrations.RenameField( + model_name='profile', + old_name='etudiant', + new_name='student', + ), + migrations.RenameField( + model_name='profile', + old_name='utilisateur', + new_name='user', + ), + migrations.RenameField( + model_name='school', + old_name='libelle', + new_name='description', + ), + migrations.RenameField( + model_name='school', + old_name='vacances', + new_name='vacation', + ), + migrations.RenameField( + model_name='slot', + old_name='capacite', + new_name='capacity', + ), + migrations.RenameField( + model_name='slot', + old_name='jour', + new_name='day', + ), + migrations.RenameField( + model_name='slot', + old_name='duree', + new_name='duration', + ), + migrations.RenameField( + model_name='slot', + old_name='salle', + new_name='room', + ), + migrations.RenameField( + model_name='slot', + old_name='matiere', + new_name='subject', + ), + migrations.RenameField( + model_name='slot', + old_name='periode', + new_name='term', + ), + migrations.RenameField( + model_name='slot', + old_name='heure', + new_name='time', + ), + migrations.RenameField( + model_name='student', + old_name='nom', + new_name='last_name', + ), + migrations.RenameField( + model_name='student', + old_name='groupes', + new_name='groups', + ), + migrations.RenameField( + model_name='student', + old_name='prenom', + new_name='first_name', + ), + migrations.RenameField( + model_name='subject', + old_name='libelle', + new_name='description', + ), + migrations.RenameField( + model_name='swap', + old_name='rotation', + new_name='colle', + ), + migrations.RenameField( + model_name='swap', + old_name='est_positif', + new_name='enroll', + ), + migrations.RenameField( + model_name='swap', + old_name='etudiant', + new_name='student', + ), + migrations.RenameField( + model_name='term', + old_name='debut', + new_name='begin', + ), + migrations.RenameField( + model_name='term', + old_name='libelle', + new_name='description', + ), + migrations.RenameField( + model_name='term', + old_name='fin', + new_name='end', + ), + migrations.RemoveField( + model_name='slot', + name='est_colle', + ), + + migrations.RenameField( + model_name='student', + old_name='classe', + new_name='cls', + ), + migrations.RenameField( + model_name='subject', + old_name='classe', + new_name='cls', + ), + migrations.RenameField( + model_name='term', + old_name='classe', + new_name='cls', + ), + + + migrations.AddConstraint( + model_name='calendarlink', + constraint=models.UniqueConstraint(fields=('student', 'term'), name='unique_student_term_combination'), + ), + ] diff --git a/colloscope/migrations/0014_alter_group_options_slot_type.py b/colloscope/migrations/0014_alter_group_options_slot_type.py new file mode 100644 index 0000000..0fef7c3 --- /dev/null +++ b/colloscope/migrations/0014_alter_group_options_slot_type.py @@ -0,0 +1,24 @@ +# Generated by Django 5.0.4 on 2024-05-02 21:40 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('colloscope', '0013_alter_colle_options_alter_slot_options_and_more'), + ] + + operations = [ + migrations.AlterModelOptions( + name='group', + options={'ordering': ['term__cls__description', 'term__description', 'description']}, + ), + migrations.AddField( + model_name='slot', + name='type', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='colloscope.grouptype'), + preserve_default=False, + ), + ] diff --git a/colloscope/migrations/0015_rename_lycee_class_school.py b/colloscope/migrations/0015_rename_lycee_class_school.py new file mode 100644 index 0000000..3c53543 --- /dev/null +++ b/colloscope/migrations/0015_rename_lycee_class_school.py @@ -0,0 +1,18 @@ +# Generated by Django 5.0.4 on 2024-05-02 21:46 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('colloscope', '0014_alter_group_options_slot_type'), + ] + + operations = [ + migrations.RenameField( + model_name='class', + old_name='lycee', + new_name='school', + ), + ] diff --git a/colloscope/migrations/0016_alter_colle_groups.py b/colloscope/migrations/0016_alter_colle_groups.py new file mode 100644 index 0000000..83649c2 --- /dev/null +++ b/colloscope/migrations/0016_alter_colle_groups.py @@ -0,0 +1,18 @@ +# Generated by Django 5.0.4 on 2024-05-05 07:41 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('colloscope', '0015_rename_lycee_class_school'), + ] + + operations = [ + migrations.AlterField( + model_name='colle', + name='groups', + field=models.ManyToManyField(blank=True, to='colloscope.group'), + ), + ] diff --git a/colloscope/migrations/0017_alter_slot_options_alter_subject_options_and_more.py b/colloscope/migrations/0017_alter_slot_options_alter_subject_options_and_more.py new file mode 100644 index 0000000..de10e83 --- /dev/null +++ b/colloscope/migrations/0017_alter_slot_options_alter_subject_options_and_more.py @@ -0,0 +1,47 @@ +# Generated by Django 5.0.4 on 2024-05-06 20:22 + + +from datetime import datetime +from pytz import timezone + +from django.db import migrations, models +from django.db.migrations import RunPython + + +def replace_date_with_datetime(apps, schema_editor): + model = apps.get_model('colloscope', 'Colle') + + for colle in model.objects.all(): + print(colle.slot.time, end="-->") + colle.datetime = datetime.combine(colle.date, colle.slot.time) + colle.datetime = timezone("Europe/Paris").localize(colle.datetime) + print(colle.datetime) + colle.save() + + +class Migration(migrations.Migration): + + dependencies = [ + ('colloscope', '0016_alter_colle_groups'), + ] + + operations = [ + migrations.AlterModelOptions( + name='slot', + options={'ordering': ['subject', 'colleur', 'day', 'time'], 'verbose_name_plural': 'slots'}, + ), + migrations.AlterModelOptions( + name='subject', + options={'ordering': ['description']}, + ), + migrations.AddField( + model_name='colle', + name='datetime', + field=models.DateTimeField(default=datetime(1970, 1, 1, 0, 0, 0)), + ), + migrations.RunPython(replace_date_with_datetime), + migrations.RemoveField( + model_name='colle', + name='date', + ) + ] diff --git a/colloscope/models.py b/colloscope/models.py index d59492e..74ba3e8 100644 --- a/colloscope/models.py +++ b/colloscope/models.py @@ -149,7 +149,7 @@ class Term(models.Model): .annotate(swap_plus=Count("swap", filter=Q(swap__enroll=1), distinct=True)) .annotate(swap_minus=Count("swap", filter=Q(swap__enroll=0), distinct=True)) .annotate(volume=F("base_vol") + F("swap_plus") - F("swap_minus")) - .order_by("date", "slot__time")) + .order_by("datetime", "slot__time")) def query_colles_of_student(self, student) -> QuerySet: has_student = ((Q(groups__student=student) @@ -174,7 +174,7 @@ class Term(models.Model): | Q(swap__enroll=1, swap__student=student)) return (self.query_colles() - .filter(volume__lt=F("slot__capacity"), date__gte=date.today()) + .filter(volume__lt=F("slot__capacity"), datetime__gte=date.today()) .exclude(has_student)) def __str__(self) -> str: @@ -308,12 +308,11 @@ class Slot(models.Model): class Colle(models.Model): class Meta: - ordering = ["slot__term__cls", "slot__subject__description", "slot__colleur__name", "date", - "slot__time"] + ordering = ["slot__term__cls", "slot__subject__description", "slot__colleur__name", "datetime"] slot = models.ForeignKey(Slot, on_delete=models.CASCADE) groups = models.ManyToManyField(Group, blank=True) - date = models.DateField() + datetime = models.DateTimeField() def initial_group(self): """ @@ -385,10 +384,7 @@ class Colle(models.Model): # func() def __str__(self): - return f"Colle {self.slot.subject} ({self.slot.colleur}); {self.date} {self.slot.time} {self.slot.room}. Groupe(s) {{{'; '.join(str(groupe) for groupe in self.groups.all())}}}" - - def datetime(self): - return datetime.combine(self.date, self.slot.time, tzinfo=timezone("Europe/Paris")) + return f"Colle {self.slot.subject} ({self.slot.colleur}); {self.datetime} {self.slot.time} {self.slot.room}. Groupe(s) {{{'; '.join(str(groupe) for groupe in self.groups.all())}}}" class Swap(models.Model): diff --git a/colloscope/pdfexport.py b/colloscope/pdfexport.py index 4d249ec..cd6b509 100644 --- a/colloscope/pdfexport.py +++ b/colloscope/pdfexport.py @@ -75,8 +75,8 @@ class PDF(FPDF): for s in weeks: lundi = term.cls.week_beginning_date(s) - if Colle.objects.filter(slot=c, date__gte=lundi, date__lt=lundi + timedelta(weeks=1)).exists(): - r = Colle.objects.get(slot=c, date__gte=lundi, date__lt=lundi + timedelta(weeks=1)) + if Colle.objects.filter(slot=c, datetime__gte=lundi, datetime__lt=lundi + timedelta(weeks=1)).exists(): + r = Colle.objects.get(slot=c, datetime__gte=lundi, datetime__lt=lundi + timedelta(weeks=1)) groups = r.groups content = ", ".join(g.description for g in groups.all()) diff --git a/colloscope/serializers.py b/colloscope/serializers.py index 57dbf64..a9befc9 100644 --- a/colloscope/serializers.py +++ b/colloscope/serializers.py @@ -1,3 +1,4 @@ +from rest_framework import serializers from rest_framework.serializers import ModelSerializer from colloscope.models import * @@ -61,10 +62,21 @@ class SlotSerializer(ModelSerializer): fields = ["id", "term", "day", "time", "duration", "room", "subject", "colleur", "type", "capacity"] +class SwapSerializer(ModelSerializer): + class Meta: + model = Swap + fields = ["enroll", "colle", "student"] + + class ColleSerializer(ModelSerializer): + base_vol = serializers.IntegerField() + volume = serializers.IntegerField() + slot = SlotSerializer() + swaps = SwapSerializer(source="swap_set", many=True) + class Meta: model = Colle - fields = ["id", "slot", "groups", "date"] + fields = ["id", "slot", "groups", "datetime", "base_vol", "volume", "swaps"] class CalendarLinkSerializer(ModelSerializer): diff --git a/colloscope/templates/dashboard.html b/colloscope/templates/dashboard.html index 0a0a61b..b6c9e7f 100644 --- a/colloscope/templates/dashboard.html +++ b/colloscope/templates/dashboard.html @@ -31,7 +31,7 @@ Bienvenue {{ student }}. Votre lycée est {{ term.cls.school.description }}, et
{{ colle.slot.subject }} ({{ colle.slot.colleur }})