from datetime import datetime, timezone 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, ) from ..models import Documentation class DocumentationType(PermissionsTypeMixin, DjangoFilterMixin, DjangoObjectType): class Meta: model = Documentation fields = ( "id", "course", "lesson_event", "subject", "topic", "homework", "group_note", "datetime_start", "datetime_end", "date_start", "date_end", ) filter_fields = { "id": ["exact", "lte", "gte"], "course__name": ["exact"], } course = graphene.Field(CourseType, required=False) subject = graphene.Field(SubjectType, required=False) @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 = ( "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 = ( "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 = ( "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) 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"): 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( "alsijil.add_documentation_for_lesson_event_rule", lesson_event ): raise PermissionDenied() # 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. return 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 "", ) 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 obj.save() return obj @classmethod def mutate(cls, root, info, input): # noqa objs = [cls.create_or_update(info, doc) for doc in input] return DocumentationBatchCreateOrUpdateMutation(documentations=objs)