vbv/server/vbv_lernwelt/duedate/models.py

158 lines
4.7 KiB
Python

import datetime
from django.db import models
from django.utils import timezone
from wagtail.models import Page
from vbv_lernwelt.core.models import User
from vbv_lernwelt.course.models import CourseSession
class DueDate(models.Model):
start = models.DateTimeField(
null=True, db_index=True, help_text="Startdatum ist Pflicht"
)
end = models.DateTimeField(
null=True, blank=True, db_index=True, help_text="Enddatum ist optional"
)
manual_override_fields = models.BooleanField(
default=False,
help_text="Nur aktivieren, wenn man die Felder manuell überschreiben will",
)
title = models.CharField(
default="",
max_length=1024,
help_text="Title wird standarmässig vom LearningContent übernommen",
)
assignment_type_translation_key = models.CharField(
default="",
blank=True,
max_length=1024,
help_text="Translation Key aus dem Frontend",
)
date_type_translation_key = models.CharField(
default="",
blank=True,
max_length=1024,
help_text="Translation Key aus dem Frontend",
)
subtitle = models.TextField(
default="",
blank=True,
help_text="Überschreibt den Untertitel bei `assignment_type_translation_key` und `date_type_translation_key`",
)
url = models.CharField(
default="",
blank=True,
max_length=1024,
help_text="URL wird vom LearningContent übernommen (sichtbar für Member/Teilnehmer)",
)
url_expert = models.CharField(
default="",
blank=True,
max_length=1024,
help_text="URL wird aus dem LearningContent generiert (sichtbar für den Experten/Trainer)",
)
course_session = models.ForeignKey(
"course.CourseSession",
on_delete=models.CASCADE,
blank=True,
)
page = models.ForeignKey(Page, on_delete=models.SET_NULL, null=True, blank=True)
circle_data = models.JSONField(default=dict, blank=True)
class Meta:
ordering = ["start", "end"]
def __str__(self):
if self.is_undefined:
return f"{self.title} undefined"
# Convert the UTC datetime to local time
local_start = timezone.localtime(self.start) if self.start else None
start_str = local_start.strftime("%Y-%m-%d %H:%M") if local_start else "-"
result = f"{self.title} {start_str}"
if self.end:
local_end = timezone.localtime(self.end) if self.end else None
end_str = local_end.strftime("%Y-%m-%d %H:%M") if local_end else "-"
result += f" - {end_str}"
return result
def save(self, *args, **kwargs):
try:
circle = self.get_circle()
# prefetch circle data, because loading it dynamically is too slow
if circle:
self.circle_data = {
"id": str(circle.id),
"title": circle.title,
"slug": circle.slug,
}
except Exception:
# noop
pass
super().save(*args, **kwargs)
@property
def display_subtitle(self):
result = ""
if self.subtitle and self.manual_override_fields:
result = self.subtitle
result = self.assignment_type_translation_key
if self.date_type_translation_key:
result += ": " + self.date_type_translation_key
return result
@property
def is_undefined(self):
return self.start is None
@property
def duration(self):
if self.end is None:
return datetime.timedelta(0)
return self.end - self.start
def get_circle(self):
try:
return self.page.specific.get_circle()
except Exception:
# noop
return None
@classmethod
def get_users_next_events_qs(
cls, user: User, course_session: CourseSession = None, limit=10
):
"""
Returns a queryset of all due dates that are relevant for the given user.
If course_session is given, only due dates for that course_session are returned.
The user is determined by via a course session user of a course_assignment.
"""
qs = cls.get_next_due_dates_qs()
if course_session:
qs = qs.filter(
course_session=course_session,
course_session__course_assignment__user=user,
)
else:
qs = qs.filter(course_session__course_assignment__user=user)
qs = qs.order_by("start")[:limit]
return qs
@classmethod
def get_next_due_dates_qs(cls):
now = timezone.now()
qs = cls.objects.filter(start__gte=now)
return qs