diff --git a/aleksis/apps/chronos/models.py b/aleksis/apps/chronos/models.py index 6ef485cd304cc29bfdf350dd75b99870abbee828..97f0ee3628e6f9c791882905634bf9e2b4f9dfd0 100644 --- a/aleksis/apps/chronos/models.py +++ b/aleksis/apps/chronos/models.py @@ -2,6 +2,7 @@ from __future__ import annotations +import os from datetime import date, datetime, time, timedelta from typing import Any, Dict, Iterable, Iterator, List, Optional, Tuple, Union @@ -1121,14 +1122,9 @@ class ExtraLesson( indexes = [models.Index(fields=["week", "year"], name="extra_lesson_week_year")] -@receiver(substitutions_changed) -def automatic_plan_signal_receiver(sender: Revision, versions: Iterable[Version], **kwargs): - """Check all automatic plans for updates after substitutions changed.""" - for automatic_plan in AutomaticPlan.objects.all(): - automatic_plan.check_update(sender, versions) - - class AutomaticPlan(ExtensibleModel): + """Model for configuring automatically updated PDF substitution plans.""" + slug = models.SlugField( verbose_name=_("Slug"), help_text=_("This will be used for the name of the PDF file with the generated plan."), @@ -1144,7 +1140,6 @@ class AutomaticPlan(ExtensibleModel): verbose_name=_("Show header box"), help_text=_("The header box shows affected teachers/groups."), ) - last_revision = models.ForeignKey( to=Revision, on_delete=models.SET_NULL, @@ -1152,13 +1147,13 @@ class AutomaticPlan(ExtensibleModel): null=True, verbose_name=_("Revision which triggered the last update"), ) + last_update = models.DateTimeField( blank=True, null=True, verbose_name=_("Date and time of the last update") ) last_update_triggered_manually = models.BooleanField( default=False, verbose_name=_("Was the last update triggered manually?") ) - current_file = models.FileField( upload_to="chronos/plan_pdfs/", null=True, blank=True, verbose_name=_("Current file") ) @@ -1175,7 +1170,7 @@ class AutomaticPlan(ExtensibleModel): def get_context_data(self) -> Dict[str, Any]: """Get context data for generating the substitutions PDF.""" - from aleksis.apps.chronos.views import get_substitutions_context_data + from aleksis.apps.chronos.views import get_substitutions_context_data # noqa context = get_substitutions_context_data( request=None, @@ -1237,12 +1232,15 @@ class AutomaticPlan(ExtensibleModel): @property def path(self) -> str: """Get the relative path of the PDF file in the media directory.""" - return f"chronos/plans/{self.filename}" + return os.path.join("chronos", "plans", self.filename) @property def local_path(self) -> str: """Get the full path under which the PDF file can accessed on the local system.""" - return default_storage.path(self.path) + try: + return default_storage.path(self.path) + except NotImplementedError: + return self.path def save(self, *args, **kwargs): super().save(*args, **kwargs) @@ -1258,6 +1256,13 @@ class AutomaticPlan(ExtensibleModel): constraints = [models.UniqueConstraint(fields=["site_id", "slug"], name="site_slug")] +@receiver(substitutions_changed) +def automatic_plan_signal_receiver(sender: Revision, versions: Iterable[Version], **kwargs): + """Check all automatic plans for updates after substitutions changed.""" + for automatic_plan in AutomaticPlan.objects.all(): + automatic_plan.check_update(sender, versions) + + class ChronosGlobalPermissions(GlobalPermissionModel): class Meta: managed = False