Skip to content
Snippets Groups Projects
documentation.py 6.29 KiB
Newer Older
from datetime import datetime, timezone
Hangzhi Yu's avatar
Hangzhi Yu committed

from django.core.exceptions import PermissionDenied

import graphene
from graphene_django.types import DjangoObjectType
from graphene_django_cud.mutations import (
    DjangoBatchCreateMutation,
    DjangoBatchPatchMutation,
    DjangoCreateMutation,
)
from guardian.shortcuts import get_objects_for_user

from aleksis.apps.chronos.models import LessonEvent
from aleksis.apps.cursus.schema import CourseType, SubjectType
from aleksis.core.schema.base import (
    DeleteMutation,
    DjangoFilterMixin,
    PermissionBatchPatchMixin,
    PermissionsTypeMixin,
)
Hangzhi Yu's avatar
Hangzhi Yu committed

from ..models import Documentation


class DocumentationType(PermissionsTypeMixin, DjangoFilterMixin, DjangoObjectType):
    class Meta:
        model = Documentation
Jonathan Weth's avatar
Jonathan Weth committed
        fields = (
            "id",
            "course",
            "lesson_event",
            "subject",
            "topic",
            "homework",
            "group_note",
            "datetime_start",
            "datetime_end",
            "date_start",
            "date_end",
Julian's avatar
Julian committed
            "teachers",
Jonathan Weth's avatar
Jonathan Weth committed
        )
        filter_fields = {
            "id": ["exact", "lte", "gte"],
            "course__name": ["exact"],
        }

    course = graphene.Field(CourseType, required=False)
    subject = graphene.Field(SubjectType, required=False)

Julian's avatar
Julian committed
    @staticmethod
    def resolve_teachers(root: Documentation, info, **kwargs):
        if not str(root.pk).startswith("DUMMY") and hasattr(root, "teachers"):
            return  root.teachers
        return root.course.teachers

    @classmethod
    def get_queryset(cls, queryset, info):
        return get_objects_for_user(info.context.user, "alsijil.view_documentation", queryset)


class DocumentationCreateMutation(DjangoCreateMutation):
    class Meta:
        model = Documentation
        only_fields = (
Jonathan Weth's avatar
Jonathan Weth committed
            "course",
            "lesson_event",
            "subject",
            "topic",
            "homework",
            "group_note",
            "datetime_start",
            "datetime_end",
            "date_start",
            "date_end",
        )
        optional_fields = (
            "course",
            "lesson_event",
            "subject",
            "topic",
            "homework",
            "group_note",
            "datetime_start",
            "datetime_end",
            "date_start",
            "date_end",
        )
        permissions = ("alsijil.add_documentation",)  # FIXME


class DocumentationBatchCreateMutation(DjangoBatchCreateMutation):
    class Meta:
        model = Documentation
        only_fields = (
Jonathan Weth's avatar
Jonathan Weth committed
            "id",
            "course",
            "lesson_event",
            "subject",
            "topic",
            "homework",
            "group_note",
            "datetime_start",
            "datetime_end",
            "date_start",
            "date_end",
        )
        permissions = ("alsijil.add_documentation",)  # FIXME


class DocumentationDeleteMutation(DeleteMutation):
    klass = Documentation
    permission_required = "alsijil.delete_documentation_rule"  # FIXME


class DocumentationBatchPatchMutation(PermissionBatchPatchMixin, DjangoBatchPatchMutation):
    class Meta:
        model = Documentation
        only_fields = (
Jonathan Weth's avatar
Jonathan Weth committed
            "id",
            "course",
            "lesson_event",
            "subject",
            "topic",
            "homework",
            "group_note",
            "datetime_start",
            "datetime_end",
            "date_start",
            "date_end",
        )
        permissions = ("alsijil.edit_documentation_rule",)  # FIXME


class DocumentationInputType(graphene.InputObjectType):
    id = graphene.ID(required=True)
    course = graphene.ID(required=False)
    subject = graphene.ID(required=False)
Julian's avatar
Julian committed
    teachers = graphene.List(graphene.ID, required=False)

    topic = graphene.String(required=False)
    homework = graphene.String(required=False)
    group_note = graphene.String(required=False)


class DocumentationBatchCreateOrUpdateMutation(graphene.Mutation):
        input = graphene.List(DocumentationInputType)
    documentations = graphene.List(DocumentationType)
    def create_or_update(cls, info, doc):
Hangzhi Yu's avatar
Hangzhi Yu committed
        _id = doc.id
Hangzhi Yu's avatar
Hangzhi Yu committed
        # 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, datetime_end = _id.split(";")
            lesson_event = LessonEvent.objects.get(id=lesson_event_id)
            if not info.context.user.has_perm(
Julian's avatar
Julian committed
                "alsijil.add_documentation_for_lesson_event_rule", lesson_event
            ):
                raise PermissionDenied()

Hangzhi Yu's avatar
Hangzhi Yu committed
            # Timezone removal is necessary due to ISO style offsets are no valid timezones.
            # Instead, we take the timezone from the lesson_event and save it in a dedicated field.
Julian's avatar
Julian committed
            obj = Documentation.objects.create(
                datetime_start=datetime.fromisoformat(datetime_start).replace(tzinfo=timezone.utc),
                datetime_end=datetime.fromisoformat(datetime_end).replace(tzinfo=timezone.utc),
                timezone=lesson_event.timezone,
                lesson_event=lesson_event,
                course=lesson_event.course,
                subject=lesson_event.subject,
                topic=doc.topic or "",
                homework=doc.homework or "",
                group_note=doc.group_note or "",
Julian's avatar
Julian committed
            if doc.teachers is not None:
                obj.teachers.add(*doc.teachers)
            else:
                obj.teachers.set(lesson_event.course.teachers)
            obj.save()
            return obj
        else:
Hangzhi Yu's avatar
Hangzhi Yu committed
            obj = Documentation.objects.get(id=_id)

            if not info.context.user.has_perm("alsijil.edit_documentation_rule", obj):
                raise PermissionDenied()

            if doc.topic is not None:
                obj.topic = doc.topic
            if doc.homework is not None:
                obj.homework = doc.homework
            if doc.group_note is not None:
                obj.group_note = doc.group_note

            obj.save()
            return obj

    @classmethod
Hangzhi Yu's avatar
Hangzhi Yu committed
    def mutate(cls, root, info, input):  # noqa
        objs = [cls.create_or_update(info, doc) for doc in input]

        return DocumentationBatchCreateOrUpdateMutation(documentations=objs)