from datetime import datetime from django.core.exceptions import PermissionDenied from django.utils.timezone import localdate, localtime 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 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, ) from ..models import Documentation from .participation_status import ParticipationStatusType class DocumentationType(PermissionsTypeMixin, DjangoFilterMixin, DjangoObjectType): class Meta: model = Documentation fields = ( "id", "course", "amends", "subject", "topic", "homework", "group_note", "datetime_start", "datetime_end", "date_start", "date_end", "teachers", "participations", ) filter_fields = { "id": ["exact", "lte", "gte"], "course__name": ["exact"], } course = graphene.Field(CourseType, required=False) amends = graphene.Field(lambda: LessonEventType, required=False) subject = graphene.Field(SubjectType, required=False) participations = graphene.List(ParticipationStatusType, required=False) future_notice = graphene.Boolean(required=False) old_id = graphene.ID(required=False) @staticmethod def resolve_teachers(root: Documentation, info, **kwargs): if not str(root.pk).startswith("DUMMY") and hasattr(root, "teachers"): return root.teachers elif root.amends.amends: if root.amends.teachers: return root.amends.teachers else: 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) 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): class Arguments: input = graphene.List(DocumentationInputType) documentations = graphene.List(DocumentationType) @classmethod def create_or_update(cls, info, doc): _id = doc.id # Sadly, we can't use the update_or_create method since create_defaults # is only introduced in Django 5.0 if _id.startswith("DUMMY"): return Documentation.create_from_lesson_event( info.context.user, *Documentation.parse_dummy(_id), ) else: 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 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 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)