diff --git a/aleksis/apps/alsijil/models.py b/aleksis/apps/alsijil/models.py index 4f7e90a06ae91cc6864146b69c95f385e17d2ba4..dfae4a37271b81a2804597c30524a29efcbcb91b 100644 --- a/aleksis/apps/alsijil/models.py +++ b/aleksis/apps/alsijil/models.py @@ -2,6 +2,7 @@ from datetime import date, datetime from typing import Optional, Union from urllib.parse import urlparse +from django.core.exceptions import PermissionDenied from django.db import models from django.db.models import QuerySet from django.db.models.constraints import CheckConstraint @@ -10,6 +11,7 @@ from django.http import HttpRequest from django.urls import reverse from django.utils.formats import date_format from django.utils.translation import gettext_lazy as _ +from django.contrib.auth.models import User from calendarweek import CalendarWeek from colorfield.fields import ColorField @@ -595,6 +597,90 @@ class Documentation(CalendarEvent): return Documentation.get_documentations_for_events(events, incomplete) + @classmethod + def parse_dummy( + cls, + id: string, + ) -> tuple: + """Parse dummy id string into lesson_event, datetime_start, datetime_end. + """ + dummy, lesson_event_id, datetime_start_iso, datetime_end_iso = _id.split(";") + lesson_event = LessonEvent.objects.get(id=lesson_event_id) + + datetime_start = datetime.fromisoformat(datetime_start_iso).astimezone( + lesson_event.timezone + ) + datetime_end = datetime.fromisoformat(datetime_end_iso).astimezone( + lesson_event.timezone + ) + return (lesson_event, datetime_start, datetime_end) + + @classmethod + def create_from_lesson_event( + cls, + user: User, + lesson_event: LessonEvent, + datetime_start: datetime, + datetime_end: datetime, + ) -> Documentation: + """ Create a documentation from a lesson_event with start and end datetime. + User is needed for permission checking. + """ + if user.has_perm( + "alsijil.add_documentation_for_lesson_event_rule", lesson_event + ) and ( + get_site_preferences()["alsijil__allow_edit_future_documentations"] == "all" + or ( + get_site_preferences()["alsijil__allow_edit_future_documentations"] + == "current_day" + and datetime_start.date() <= localdate() + ) + or ( + get_site_preferences()["alsijil__allow_edit_future_documentations"] + == "current_time" + and datetime_start <= localtime() + ) + ): + if lesson_event.amends: + if lesson_event.course: + course = lesson_event.course + else: + course = lesson_event.amends.course + + if lesson_event.subject: + subject = lesson_event.subject + else: + subject = lesson_event.amends.subject + + if lesson_event.teachers: + teachers = lesson_event.teachers + else: + teachers = lesson_event.amends.teachers + else: + course, subject, teachers = ( + lesson_event.course, + lesson_event.subject, + lesson_event.teachers, + ) + + obj = cls.objects.create( + datetime_start=datetime_start, + datetime_end=datetime_end, + amends=lesson_event, + course=course, + subject=subject, + topic=doc.topic or "", + homework=doc.homework or "", + group_note=doc.group_note or "", + ) + if doc.teachers is not None: + obj.teachers.add(*doc.teachers) + else: + obj.teachers.set(teachers.all()) + obj.save() + return obj + raise PermissionDenied() + class ParticipationStatus(CalendarEvent): """A participation or absence record about a single person. diff --git a/aleksis/apps/alsijil/schema/absences.py b/aleksis/apps/alsijil/schema/absences.py index 55aa8ecf5774c352743408bde86e2a0ee7cef9f6..bb02c4bb2327bf0f467a9f7990c2287f601e5816 100644 --- a/aleksis/apps/alsijil/schema/absences.py +++ b/aleksis/apps/alsijil/schema/absences.py @@ -37,19 +37,17 @@ class AbsencesBatchCreateMutation(graphene.Mutation): # Create doc for dummies that are already in the past future = false for dummy in dummies: - # TODO/MAYBE: This in past logic could be somewhere else OR shared. - # The next 5 lines are shared with DocumentationBatchCreateOrUpdateMutation - # & could be deduplicated - dummy, lesson_event_id, datetime_start_iso, datetime_end_iso = _id.split(";") - lesson_event = LessonEvent.objects.get(id=lesson_event_id) - start = datetime.fromisoformat(datetime_start_iso).astimezone( - lesson_event.timezone - ) + lesson_event, dummy_start, dummy_end = Documentation.parse_dummy(dummy.id) - if start < datetime.now(): + if dummy_start < datetime.now(): # In the past -> Create a Documentation docs.append( - DocumentationBatchCreateOrUpdateMutation.create_or_update(info, dummy) + Documentation.create_from_lesson_event( + info.context.user, + lesson_event, + dummy_start, + dummy_end, + ) ) else: future = true diff --git a/aleksis/apps/alsijil/schema/documentation.py b/aleksis/apps/alsijil/schema/documentation.py index 3225db34e7c146c4eadcf34efcc11936f5df7311..9d3ea2b4b5c3286b6deaa811dbffe11e1322c3f6 100644 --- a/aleksis/apps/alsijil/schema/documentation.py +++ b/aleksis/apps/alsijil/schema/documentation.py @@ -9,7 +9,6 @@ from guardian.shortcuts import get_objects_for_user from reversion import create_revision, set_comment, set_user from aleksis.apps.alsijil.util.predicates import can_edit_documentation, is_in_allowed_time_range -from aleksis.apps.chronos.models import LessonEvent from aleksis.apps.chronos.schema import LessonEventType from aleksis.apps.cursus.models import Subject from aleksis.apps.cursus.schema import CourseType, SubjectType @@ -18,7 +17,6 @@ from aleksis.core.schema.base import ( DjangoFilterMixin, PermissionsTypeMixin, ) -from aleksis.core.util.core_helpers import get_site_preferences from ..models import Documentation @@ -100,70 +98,10 @@ class DocumentationBatchCreateOrUpdateMutation(graphene.Mutation): # Sadly, we can't use the update_or_create method since create_defaults # is only introduced in Django 5.0 if _id.startswith("DUMMY"): - dummy, lesson_event_id, datetime_start_iso, datetime_end_iso = _id.split(";") - lesson_event = LessonEvent.objects.get(id=lesson_event_id) - - datetime_start = datetime.fromisoformat(datetime_start_iso).astimezone( - lesson_event.timezone - ) - datetime_end = datetime.fromisoformat(datetime_end_iso).astimezone( - lesson_event.timezone + return Documentation.create_from_lesson_event( + info.context.user, + *Documentation.parse_dummy(_id), ) - - if info.context.user.has_perm( - "alsijil.add_documentation_for_lesson_event_rule", lesson_event - ) and ( - get_site_preferences()["alsijil__allow_edit_future_documentations"] == "all" - or ( - get_site_preferences()["alsijil__allow_edit_future_documentations"] - == "current_day" - and datetime_start.date() <= localdate() - ) - or ( - get_site_preferences()["alsijil__allow_edit_future_documentations"] - == "current_time" - and datetime_start <= localtime() - ) - ): - if lesson_event.amends: - if lesson_event.course: - course = lesson_event.course - else: - course = lesson_event.amends.course - - if lesson_event.subject: - subject = lesson_event.subject - else: - subject = lesson_event.amends.subject - - if lesson_event.teachers: - teachers = lesson_event.teachers - else: - teachers = lesson_event.amends.teachers - else: - course, subject, teachers = ( - lesson_event.course, - lesson_event.subject, - lesson_event.teachers, - ) - - obj = Documentation.objects.create( - datetime_start=datetime_start, - datetime_end=datetime_end, - amends=lesson_event, - course=course, - subject=subject, - topic=doc.topic or "", - homework=doc.homework or "", - group_note=doc.group_note or "", - ) - if doc.teachers is not None: - obj.teachers.add(*doc.teachers) - else: - obj.teachers.set(teachers.all()) - obj.save() - return obj - raise PermissionDenied() else: obj = Documentation.objects.get(id=_id)