From 63dcaaa264798ba46ac25302830260477e75e23d Mon Sep 17 00:00:00 2001 From: Jonathan Weth <git@jonathanweth.de> Date: Wed, 28 Feb 2024 19:59:11 +0100 Subject: [PATCH] Drop substitution models --- aleksis/apps/lesrooster/apps.py | 8 +- .../migrations/0016_remove_substitutions.py | 35 ++++ aleksis/apps/lesrooster/models.py | 197 ------------------ aleksis/apps/lesrooster/rules.py | 35 ---- .../apps/lesrooster/util/signal_handlers.py | 15 +- 5 files changed, 40 insertions(+), 250 deletions(-) create mode 100644 aleksis/apps/lesrooster/migrations/0016_remove_substitutions.py diff --git a/aleksis/apps/lesrooster/apps.py b/aleksis/apps/lesrooster/apps.py index 7f07c184..17c326c2 100644 --- a/aleksis/apps/lesrooster/apps.py +++ b/aleksis/apps/lesrooster/apps.py @@ -26,13 +26,11 @@ class DefaultConfig(AppConfig): # Configure change tracking for models to sync changes with LessonEvent in Chronos from .models import ( Lesson, - Substitution, Supervision, - SupervisionSubstitution, ValidityRange, ) - models = [Lesson, Supervision, Substitution, SupervisionSubstitution] + models = [Lesson, Supervision] for model in models: signals.post_save.connect( @@ -53,10 +51,6 @@ class DefaultConfig(AppConfig): m2m_changed_handler, sender=Supervision.rooms.through, ) - signals.m2m_changed.connect( - m2m_changed_handler, - sender=Substitution.rooms.through, - ) signals.post_save.connect(create_time_grid_for_new_validity_range, sender=ValidityRange) diff --git a/aleksis/apps/lesrooster/migrations/0016_remove_substitutions.py b/aleksis/apps/lesrooster/migrations/0016_remove_substitutions.py new file mode 100644 index 00000000..d070033c --- /dev/null +++ b/aleksis/apps/lesrooster/migrations/0016_remove_substitutions.py @@ -0,0 +1,35 @@ +# Generated by Django 4.2.10 on 2024-02-28 18:58 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('lesrooster', '0015_drop_site'), + ] + + operations = [ + migrations.RemoveField( + model_name='supervisionsubstitution', + name='subject', + ), + migrations.RemoveField( + model_name='supervisionsubstitution', + name='supervision', + ), + migrations.RemoveField( + model_name='supervisionsubstitution', + name='supervision_event', + ), + migrations.RemoveField( + model_name='supervisionsubstitution', + name='teachers', + ), + migrations.DeleteModel( + name='Substitution', + ), + migrations.DeleteModel( + name='SupervisionSubstitution', + ), + ] diff --git a/aleksis/apps/lesrooster/models.py b/aleksis/apps/lesrooster/models.py index e4007c2d..a87c4de4 100644 --- a/aleksis/apps/lesrooster/models.py +++ b/aleksis/apps/lesrooster/models.py @@ -469,203 +469,6 @@ class Supervision(TeacherPropertiesMixin, RoomPropertiesMixin, ExtensibleModel): return supervision_event -class Substitution(RoomPropertiesMixin, TeacherPropertiesMixin, ExtensibleModel): - """A substitution is a lesson that is changed.""" - - lesson_event = models.OneToOneField( - LessonEvent, - on_delete=models.SET_NULL, - related_name="substitution", - verbose_name=_("Linked lesson event"), - blank=True, - null=True, - ) - - lesson = models.ForeignKey(Lesson, models.CASCADE, "substitutions", verbose_name=_("Lesson")) - - date = models.DateField(verbose_name=_("Date")) - - rooms = models.ManyToManyField( - Room, - verbose_name=_("Rooms"), - related_name="lr_substitutions", - blank=True, - ) - teachers = models.ManyToManyField( - Person, - verbose_name=_("Teachers"), - related_name="lr_substitutions", - blank=True, - ) - subject = models.ForeignKey( - Subject, - on_delete=models.CASCADE, - verbose_name=_("Subject"), - related_name="substitutions", - blank=True, - null=True, - ) - - cancelled = models.BooleanField(default=False, verbose_name=_("Cancelled?")) - - comment = models.TextField(verbose_name=_("Comment"), blank=True) - - def get_teachers(self) -> QuerySet[Person]: - return self.teachers.all() - - def get_rooms(self) -> QuerySet[Room]: - return self.rooms.all() - - def clean(self) -> None: - if self.subject and self.cancelled: - raise ValidationError(_("Lessons can only be either substituted or cancelled.")) - - @property - def time_range(self) -> (timezone.datetime, timezone.datetime): - """Get the time range of this substitution.""" - return timezone.datetime.combine( - self.date, self.lesson_period.period.time_start - ), timezone.datetime.combine(self.date, self.lesson_period.period.time_end) - - def __str__(self): - return f"{self.lesson}, {date_format(self.date)}" - - def sync(self) -> LessonEvent: - """Sync the lesson with its lesson event.""" - week = CalendarWeek.from_date(self.date) - if not self.lesson.lesson_event: - return None - - lesson_event = self.lesson_event if self.lesson_event else LessonEvent() - - lesson_event.amends = self.lesson.lesson_event - lesson_event.course = self.lesson.course - lesson_event.subject = self.subject - lesson_event.datetime_start = self.lesson.slot_start.get_datetime_start(week) - lesson_event.datetime_end = self.lesson.slot_end.get_datetime_end(week) - lesson_event.cancelled = self.cancelled - lesson_event.comment = self.comment - lesson_event.save() - - lesson_event.groups.set(self.lesson.course.groups.all()) - lesson_event.teachers.set(self.teachers.all()) - lesson_event.rooms.set(self.rooms.all()) - - if self.lesson_event != lesson_event: - self.lesson_event = lesson_event - self.save() - - return lesson_event - - class Meta: - ordering = [ - "date", - "lesson__slot_start__weekday", - "lesson__slot_start__period", - ] - constraints = [ - models.CheckConstraint( - check=~Q(cancelled=True, subject__isnull=False), - name="lr_either_substituted_or_cancelled", - ), - models.UniqueConstraint(fields=["lesson", "date"], name="unique_lesson_per_date"), - ] - indexes = [ - models.Index(fields=["date"], name="substitution_date"), - models.Index(fields=["lesson"], name="substitution_lesson"), - ] - verbose_name = _("Substitution") - verbose_name_plural = _("Substitutions") - - -class SupervisionSubstitution(TeacherPropertiesMixin, ExtensibleModel): - """A supervision substitution is a supervision that is changed.""" - - supervision_event = models.OneToOneField( - SupervisionEvent, - on_delete=models.SET_NULL, - related_name="supervision_substitution", - verbose_name=_("Linked supervision event"), - blank=True, - null=True, - ) - - supervision = models.ForeignKey( - Supervision, models.CASCADE, "substitutions", verbose_name=_("Supervision") - ) - - date = models.DateField(verbose_name=_("Date")) - - teachers = models.ManyToManyField( - Person, - verbose_name=_("Teachers"), - related_name="lr_supervision_substitutions", - blank=True, - ) - subject = models.ForeignKey( - Subject, - on_delete=models.CASCADE, - verbose_name=_("Subject"), - related_name="lr_supervision_substitutions", - blank=True, - null=True, - ) - - cancelled = models.BooleanField(default=False, verbose_name=_("Cancelled?")) - - comment = models.TextField(verbose_name=_("Comment"), blank=True) - - def get_teachers(self) -> QuerySet[Person]: - return self.teachers.all() - - @property - def time_range(self) -> (timezone.datetime, timezone.datetime): - """Get the time range of this supervision.""" - return timezone.datetime.combine( - self.date, self.supervision.break_slot.period.time_start - ), timezone.datetime.combine(self.date, self.supervision.break_slot.period.time_end) - - def __str__(self): - return f"{self.supervision}, {date_format(self.date)}" - - def sync(self): - """Sync the supervision with its supervision event.""" - week = CalendarWeek.from_date(self.date) - if not self.supervision.supervision_event: - return None - - supervision_event = self.supervision_event if self.supervision_event else SupervisionEvent() - - supervision_event.amends = self.supervision.supervision_event - supervision_event.datetime_start = self.supervision.break_slot.get_datetime_start(week) - supervision_event.datetime_end = self.supervision.break_slot.get_datetime_end(week) - supervision_event.cancelled = self.cancelled - supervision_event.comment = self.comment - supervision_event.subject = self.subject - supervision_event.save() - - supervision_event.teachers.set(self.teachers.all()) - - if self.supervision_event != supervision_event: - self.supervision_event = supervision_event - self.save() - - return supervision_event - - class Meta: - ordering = [ - "date", - "supervision__break_slot__weekday", - "supervision__break_slot__period", - ] - indexes = [ - models.Index(fields=["date"], name="super_substitution_date"), - models.Index(fields=["supervision"], name="super_substitution_supervision"), - ] - verbose_name = _("Supervision Substitution") - verbose_name_plural = _("Supervision Substitutions") - - class TimeboundCourseConfig(ExtensibleModel): """A timebound course config is the specific configuration of a course. diff --git a/aleksis/apps/lesrooster/rules.py b/aleksis/apps/lesrooster/rules.py index 13146da9..416deee4 100644 --- a/aleksis/apps/lesrooster/rules.py +++ b/aleksis/apps/lesrooster/rules.py @@ -12,7 +12,6 @@ from .models import ( Lesson, Slot, Supervision, - SupervisionSubstitution, TimeboundCourseConfig, TimeGrid, ValidityRange, @@ -162,40 +161,6 @@ delete_supervision_predicate = view_supervision_predicate & ( add_perm("lesrooster.delete_supervision_rule", delete_supervision_predicate) -# Supervision substitutions -view_supervision_substitutions_predicate = has_person & ( - has_global_perm("lesrooster.view_supervisionsubstitution") - | has_any_object("lesrooster.view_supervisionsubstitution", SupervisionSubstitution) -) -add_perm("lesrooster.view_supervisionsubstitutions_rule", view_supervision_substitutions_predicate) - -view_supervision_substitution_predicate = has_person & ( - has_global_perm("lesrooster.view_supervisionsubstitution") - | has_object_perm("lesrooster.view_supervisionsubstitution") -) -add_perm("lesrooster.view_supervisionsubstitution_rule", view_supervision_substitution_predicate) - -create_supervision_substitution_predicate = has_person & has_global_perm( - "lesrooster.add_supervisionsubstitution" -) -add_perm( - "lesrooster.create_supervisionsubstitution_rule", create_supervision_substitution_predicate -) - -edit_supervision_substitution_predicate = view_supervision_substitution_predicate & ( - has_global_perm("lesrooster.change_supervisionsubstitution") - | has_object_perm("lesrooster.change_supervisionsubstitution") -) -add_perm("lesrooster.edit_supervisionsubstitution_rule", edit_supervision_substitution_predicate) - -delete_supervision_substitution_predicate = view_supervision_substitution_predicate & ( - has_global_perm("lesrooster.delete_supervisionsubstitution") - | has_object_perm("lesrooster.delete_supervisionsubstitution") -) -add_perm( - "lesrooster.delete_supervisionsubstitution_rule", delete_supervision_substitution_predicate -) - # Timebound course configs view_timebound_course_configs_predicate = has_person & ( diff --git a/aleksis/apps/lesrooster/util/signal_handlers.py b/aleksis/apps/lesrooster/util/signal_handlers.py index 43e424f7..6240a524 100644 --- a/aleksis/apps/lesrooster/util/signal_handlers.py +++ b/aleksis/apps/lesrooster/util/signal_handlers.py @@ -38,19 +38,12 @@ def create_time_grid_for_new_validity_range(sender, instance, created, **kwargs) def publish_validity_range(sender, instance, created, **kwargs): - from ..models import Lesson, Substitution, Supervision, SupervisionSubstitution + from ..models import Lesson, Supervision # FIXME Move this to a background job - objs_to_update = ( - list(Lesson.objects.filter(slot_start__time_grid__validity_range=instance)) - + list(Supervision.objects.filter(break_slot__time_grid__validity_range=instance)) - + list(Substitution.objects.filter(lesson__slot_start__time_grid__validity_range=instance)) - + list( - SupervisionSubstitution.objects.filter( - supervision__break_slot__time_grid__validity_range=instance - ) - ) - ) + objs_to_update = list( + Lesson.objects.filter(slot_start__time_grid__validity_range=instance) + ) + list(Supervision.objects.filter(break_slot__time_grid__validity_range=instance)) for obj in objs_to_update: logging.info(f"Syncing object {obj} ({type(obj)}, {obj.pk})") obj.sync() -- GitLab