Skip to content
Snippets Groups Projects
documentation.py 4.67 KiB
Newer Older
Jonathan Weth's avatar
Jonathan Weth committed
from datetime import datetime
Hangzhi Yu's avatar
Hangzhi Yu committed

from django.core.exceptions import PermissionDenied
from django.utils.timezone import localdate, localtime
Hangzhi Yu's avatar
Hangzhi Yu committed

import graphene
from graphene_django.types import DjangoObjectType
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
magicfelix's avatar
magicfelix committed
from aleksis.apps.chronos.schema import LessonEventType
from aleksis.apps.cursus.models import Subject
from aleksis.apps.cursus.schema import CourseType, SubjectType
from aleksis.core.models import Person
from aleksis.core.schema.base import (
    DjangoFilterMixin,
    PermissionsTypeMixin,
)
Hangzhi Yu's avatar
Hangzhi Yu committed

from ..models import Documentation
Julian's avatar
Julian committed
from .participation_status import ParticipationStatusType


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

    course = graphene.Field(CourseType, required=False)
magicfelix's avatar
magicfelix committed
    amends = graphene.Field(lambda: LessonEventType, required=False)
    subject = graphene.Field(SubjectType, required=False)
    participations = graphene.List(ParticipationStatusType, required=False)
    old_id = graphene.ID(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"):
Hangzhi Yu's avatar
Hangzhi Yu committed
            return root.teachers
        elif root.amends.amends:
            if root.amends.teachers:
                return root.amends.teachers
                return root.amends.amends.teachers
        return root.amends.teachers
    @staticmethod
    def resolve_future_notice(root: Documentation, info, **kwargs):
        """Show whether the user can't edit the documentation because it's in the future."""
        return not is_in_allowed_time_range(info.context.user, root) and can_edit_documentation(
            info.context.user, root
        )

    @staticmethod
    def resolve_participations(root: Documentation, info, **kwargs):
        # TODO: probably check for permission

        # A dummy documentation will not have any participations
        if str(root.pk).startswith("DUMMY") or not hasattr(root, "participations"):
            return []
        return root.participations.all()

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

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
        obj = Documentation.get_or_create_by_id(_id, info.context.user)
        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
        if doc.subject is not None:
            obj.subject = Subject.objects.get(pk=doc.subject)
        if doc.teachers is not None:
            obj.teachers.set(Person.objects.filter(pk__in=doc.teachers))
        obj.save()
        return obj

    @classmethod
Hangzhi Yu's avatar
Hangzhi Yu committed
    def mutate(cls, root, info, input):  # noqa
        with create_revision():
            set_user(info.context.user)
            set_comment("Updated in coursebook")
            objs = [cls.create_or_update(info, doc) for doc in input]

        return DocumentationBatchCreateOrUpdateMutation(documentations=objs)