import graphene import structlog from graphene.types.generic import GenericScalar from graphene_django.types import ErrorType from vbv_lernwelt.course.models import CourseCompletionStatus, CourseSession from vbv_lernwelt.course.permissions import has_course_session_access from vbv_lernwelt.course.services import mark_course_completion from vbv_lernwelt.feedback.graphql.types import ( FeedbackResponseObjectType as FeedbackResponseType, ) from vbv_lernwelt.feedback.models import FeedbackResponse from vbv_lernwelt.feedback.serializers import CourseFeedbackSerializer from vbv_lernwelt.learnpath.models import LearningContentFeedback logger = structlog.get_logger(__name__) # https://medium.com/open-graphql/jsonfield-models-in-graphene-django-308ae43d14ee class SendFeedbackMutation(graphene.Mutation): feedback_response = graphene.Field(FeedbackResponseType) errors = graphene.List( ErrorType, description="May contain more than one error for same field." ) class Arguments: course_session_id = graphene.ID(required=True) learning_content_page_id = graphene.ID(required=True) data = GenericScalar() submitted = graphene.Boolean(required=False, default_value=False) @classmethod def mutate( cls, root, info, course_session_id, learning_content_page_id, data, submitted, ): feedback_user_id = info.context.user.id learning_content = LearningContentFeedback.objects.get( id=learning_content_page_id ) circle = learning_content.get_circle() course_session = CourseSession.objects.get(id=course_session_id) if not has_course_session_access( info.context.user, course_session.id, ): return SendFeedbackMutation( errors=[ ErrorType( field="send_feedback", messages=["Insufficient permissions"] ) ] ) logger.info( "creating feedback", label="feedback", feedback_user_id=feedback_user_id, circle_title=circle.title, course_session_id=course_session_id, ) serializer = CourseFeedbackSerializer(data=data) if not serializer.is_valid(): logger.error( "creating feedback serializer invalid", error_list=serializer.errors, label="feedback", ) errors = [ ErrorType(field=field, messages=msgs) for field, msgs in serializer.errors.items() ] return SendFeedbackMutation(errors=errors) feedback_response, _ = FeedbackResponse.objects.get_or_create( feedback_user_id=feedback_user_id, circle_id=circle.id, course_session=course_session, ) original_data = feedback_response.data updated_data = serializer.validated_data initial_data = { "satisfaction": None, "goal_attainment": None, "proficiency": None, "preparation_task_clarity": None, "instructor_competence": None, "instructor_respect": None, "instructor_open_feedback": "", "would_recommend": None, "course_negative_feedback": "", "course_positive_feedback": "", } merged_data = initial_data | { key: updated_data[key] if updated_data.get(key, "") != "" else original_data.get(key) for key in initial_data.keys() } feedback_response.data = merged_data if submitted: feedback_response.submitted = submitted feedback_response.save() if submitted: mark_course_completion( user=info.context.user, page=learning_content, course_session=course_session, completion_status=CourseCompletionStatus.SUCCESS.value, ) logger.info( "feedback successfully created", label="feedback", feedback_user_id=feedback_user_id, circle_title=circle.title, course_session_id=course_session_id, ) return SendFeedbackMutation(feedback_response=feedback_response) class FeedbackMutation(object): send_feedback = SendFeedbackMutation.Field()