Add datetime support
This commit is contained in:
parent
0afc683c5b
commit
a78aff9f9d
|
@ -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))
|
||||
|
||||
|
|
|
@ -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'),
|
||||
),
|
||||
]
|
|
@ -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,
|
||||
),
|
||||
]
|
|
@ -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',
|
||||
),
|
||||
]
|
|
@ -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'),
|
||||
),
|
||||
]
|
|
@ -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',
|
||||
)
|
||||
]
|
|
@ -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):
|
||||
|
|
|
@ -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())
|
||||
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -31,7 +31,7 @@ Bienvenue {{ student }}. Votre lycée est {{ term.cls.school.description }}, et
|
|||
<div class="colle">
|
||||
<span class="summary">{{ colle.slot.subject }} ({{ colle.slot.colleur }})</span>
|
||||
<ul>
|
||||
<li><i class="fa-solid fa-clock"></i> Le {{ colle.date }} à {{ colle.slot.time }}</li>
|
||||
<li><i class="fa-solid fa-clock"></i> Le {{ colle.datetime|date:"l" }} {{ colle.datetime|date:"DATETIME_FORMAT" }}</li>
|
||||
<li><i class="fa-solid fa-users"></i> {{ colle.groups.all | print_manager | safe }} ({{ colle.volume }} / {{ colle.slot.capacity }})</li>
|
||||
<li><i class="fa-solid fa-earth-americas"></i> {{ colle.slot.room }}</li>
|
||||
<li><i class="fa-solid fa-circle-exclamation"></i>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<div class="colle">
|
||||
<span class="summary">{{ colle.slot.subject }} ({{ colle.slot.colleur }})</span>
|
||||
<ul>
|
||||
<li><i class="fa-solid fa-clock"></i> Le {{ colle.date }} à {{ colle.slot.time }}</li>
|
||||
<li><i class="fa-solid fa-clock"></i> Le {{ colle.datetime|date:"l" }} {{ colle.datetime|date:"DATETIME_FORMAT" }}</li>
|
||||
<li><i class="fa-solid fa-users"></i> {{ colle.groups.all | print_manager | safe }} ({{ colle.volume }} / {{ colle.slot.capacity }})</li>
|
||||
<li><i class="fa-solid fa-earth-americas"></i> {{ colle.slot.room }}</li>
|
||||
<li><i class="fa-solid fa-circle-exclamation"></i>
|
||||
|
|
|
@ -85,8 +85,8 @@ def dashboard(request):
|
|||
colles_per_sem = [None] * len(term.range_weeks())
|
||||
for k, n in enumerate(term.range_weeks()):
|
||||
lundi = term.cls.week_beginning_date(n)
|
||||
colles_per_sem[k] = n, lundi, colles.filter(date__gte=max(lundi, date.today()),
|
||||
date__lt=lundi + timedelta(weeks=1))
|
||||
colles_per_sem[k] = n, lundi, colles.filter(datetime__gte=max(lundi, date.today()),
|
||||
datetime__lt=lundi + timedelta(weeks=1))
|
||||
|
||||
template = loader.get_template("dashboard.html")
|
||||
calendar_link = get_calendar_link(student, term)
|
||||
|
@ -179,7 +179,7 @@ def colloscope(request):
|
|||
for sem in weeks:
|
||||
lundi = term.cls.week_beginning_date(sem)
|
||||
|
||||
rot = Colle.objects.filter(slot=c, date__gte=lundi, date__lt=lundi + timedelta(weeks=1))
|
||||
rot = Colle.objects.filter(slot=c, datetime__gte=lundi, datetime__lt=lundi + timedelta(weeks=1))
|
||||
exists = rot.exists()
|
||||
|
||||
if exists:
|
||||
|
|
|
@ -83,7 +83,14 @@ class ColleViewset(ReadOnlyModelViewSet):
|
|||
permission_classes = [IsAuthenticated]
|
||||
|
||||
def get_queryset(self):
|
||||
return Colle.objects.all()
|
||||
return (Colle.objects
|
||||
.select_related("slot", "slot__term")
|
||||
.prefetch_related("swap_set")
|
||||
.annotate(base_vol=Count("groups__members"))
|
||||
.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("datetime", "slot__time"))
|
||||
|
||||
|
||||
class CalendarLinkViewset(ReadOnlyModelViewSet):
|
||||
|
|
|
@ -16,6 +16,7 @@ Including another URLconf
|
|||
"""
|
||||
from django.contrib import admin, auth
|
||||
from django.urls import include, path
|
||||
from django.shortcuts import redirect
|
||||
from django.contrib.staticfiles import views as vstatic
|
||||
from rest_framework import routers
|
||||
from rest_framework_simplejwt.views import (
|
||||
|
@ -47,7 +48,9 @@ urlpatterns = [
|
|||
path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
|
||||
path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
|
||||
path('api/schema/', SpectacularAPIView.as_view(), name='schema'),
|
||||
path('api/doc/', SpectacularSwaggerView.as_view(url_name='schema'), name='api-doc'),
|
||||
path('api/documentation/', SpectacularSwaggerView.as_view(url_name='schema'), name='api-doc'),
|
||||
path("api/", lambda request: redirect("api-doc")),
|
||||
path("api/doc/", lambda request: redirect("api-doc")),
|
||||
path("api/", include(router.urls)),
|
||||
|
||||
path("oauth2/", include('oauth2_provider.urls', namespace='oauth2_provider')),
|
||||
|
|
Loading…
Reference in New Issue