Skip to content
Snippets Groups Projects
documentation.py 5.32 KiB
Newer Older
Hangzhi Yu's avatar
Hangzhi Yu committed
from django.core.exceptions import PermissionDenied

import graphene
from graphene_django.types import DjangoObjectType
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):
        if not info.context.user.has_perm(
            "alsijil.view_participation_status_for_documentation_rule", root
        ):
            return []

        # A dummy documentation will not have any participations
        if str(root.pk).startswith("DUMMY") or not hasattr(root, "participations"):
            return []
        return root.participations.select_related("absence_reason", "base_absence").all()
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)


Julian's avatar
Julian committed
class LessonsForPersonType(graphene.ObjectType):
    id = graphene.ID()  # noqa
    lessons = graphene.List(DocumentationType)


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)


class TouchDocumentationMutation(graphene.Mutation):
    class Arguments:
        documentation_id = graphene.ID(required=True)

    documentation = graphene.Field(DocumentationType)

    def mutate(root, info, documentation_id):
        documentation, created = Documentation.get_or_create_by_id(
            documentation_id, info.context.user
        )

        if not info.context.user.has_perm(
            "alsijil.edit_participation_status_for_documentation_rule", documentation
        ):
            raise PermissionDenied()
Julian's avatar
Julian committed

        if not created:
            documentation.touch()
Julian's avatar
Julian committed

        return TouchDocumentationMutation(documentation=documentation)