feat: mentor invite

This commit is contained in:
Reto Aebersold 2023-12-11 13:39:17 +01:00
parent cfb38cc9fe
commit 86d3644ca6
5 changed files with 74 additions and 18 deletions

View File

@ -1,5 +1,7 @@
from rest_framework import serializers
from vbv_lernwelt.learning_mentor.models import MentorInvitation
class PraxisAssignmentCompletionSerializer(serializers.Serializer):
status = serializers.SerializerMethodField()
@ -17,3 +19,17 @@ class PraxisAssignmentStatusSerializer(serializers.Serializer):
circle_id = serializers.CharField()
pending_evaluations = serializers.IntegerField()
completions = PraxisAssignmentCompletionSerializer(many=True)
class InvitationSerializer(serializers.ModelSerializer):
class Meta:
model = MentorInvitation
fields = ["id", "email"]
read_only_fields = ["id"]
def create(self, validated_data):
participant = self.context["course_session_user"]
invitation, _ = MentorInvitation.objects.get_or_create(
email=validated_data["email"], defaults={"participant": participant}
)
return invitation

View File

@ -39,7 +39,7 @@ class LearningMentorInvitationTest(APITestCase):
def test_create_invitation(self, mock_send_mail) -> None:
# GIVEN
self.client.force_login(self.participant)
participant_cs_user = add_course_session_user(
add_course_session_user(
self.course_session,
self.participant,
role=CourseSessionUser.Role.MEMBER,
@ -53,7 +53,7 @@ class LearningMentorInvitationTest(APITestCase):
response = self.client.post(invite_url, data={"email": email})
# THEN
invitation_id = response.data["invitation"]
invitation_id = response.data["id"]
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertTrue(
@ -74,6 +74,32 @@ class LearningMentorInvitationTest(APITestCase):
fail_silently=True,
)
def test_list_invitations(self) -> None:
# GIVEN
self.client.force_login(self.participant)
participant_cs_user = add_course_session_user(
self.course_session,
self.participant,
role=CourseSessionUser.Role.MEMBER,
)
email = "test@exmaple.com"
MentorInvitation.objects.create(participant=participant_cs_user, email=email)
list_url = reverse(
"list_invitations", kwargs={"course_session_id": self.course_session.id}
)
# WHEN
response = self.client.get(list_url)
# THEN
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(
response.data,
[{"id": str(MentorInvitation.objects.get(email=email).id), "email": email}],
)
def test_accept_invitation(self) -> None:
# GIVEN
invitee = create_user("invitee")

View File

@ -4,6 +4,7 @@ from . import views
urlpatterns = [
path("summary", views.mentor_summary, name="mentor_summary"),
path("invite", views.create_invitation, name="create_invitation"),
path("accept", views.accept_invitation, name="accept_invitation"),
path("invitations", views.list_invitations, name="list_invitations"),
path("invitations/create", views.create_invitation, name="create_invitation"),
path("invitations/accept", views.accept_invitation, name="accept_invitation"),
]

View File

@ -1,4 +1,4 @@
from rest_framework import permissions
from rest_framework import permissions, status
from rest_framework.decorators import api_view, permission_classes
from rest_framework.generics import get_object_or_404
from rest_framework.permissions import IsAuthenticated
@ -11,7 +11,10 @@ from vbv_lernwelt.learning_mentor.content.praxis_assignment import (
get_praxis_assignments,
)
from vbv_lernwelt.learning_mentor.models import LearningMentor, MentorInvitation
from vbv_lernwelt.learning_mentor.serializers import PraxisAssignmentStatusSerializer
from vbv_lernwelt.learning_mentor.serializers import (
InvitationSerializer,
PraxisAssignmentStatusSerializer,
)
from vbv_lernwelt.learnpath.models import Circle
from vbv_lernwelt.notify.email.email_services import EmailTemplate, send_email
@ -51,9 +54,15 @@ class CourseSessionMember(permissions.BasePermission):
@api_view(["GET"])
@permission_classes([IsAuthenticated])
@permission_classes([IsAuthenticated, CourseSessionMember])
def list_invitations(request, course_session_id: int):
pass
course_session = get_object_or_404(CourseSession, id=course_session_id)
course_session_user = get_object_or_404(
CourseSessionUser, user=request.user, course_session=course_session
)
snippets = MentorInvitation.objects.filter(participant=course_session_user)
serializer = InvitationSerializer(snippets, many=True)
return Response(serializer.data)
@api_view(["POST"])
@ -66,19 +75,19 @@ def create_invitation(request, course_session_id: int):
CourseSessionUser, user=user, course_session=course_session
)
email = request.data.get("email")
if not email:
return Response({"error": "email is required"}, status=400)
invitation, _ = MentorInvitation.objects.get_or_create(
email=email,
participant=course_session_user,
serializer = InvitationSerializer(
data=request.data, context={"course_session_user": course_session_user}
)
if not serializer.is_valid():
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
invitation = serializer.save()
target_url = f"/lernbegleitung/{course_session_id}/invitation/{invitation.id}"
send_email(
recipient_email=email,
recipient_email=invitation.email,
template=EmailTemplate.LEARNING_MENTOR_INVITATION,
template_data={
"inviter_name": f"{user.first_name} {user.last_name}",
@ -89,7 +98,7 @@ def create_invitation(request, course_session_id: int):
fail_silently=True,
)
return Response({"invitation": invitation.id})
return Response(serializer.data)
@api_view(["POST"])

View File

@ -63,7 +63,11 @@ class EmailTemplate(Enum):
NEW_FEEDBACK = {"de": "d-40fb94d5149949e7b8e7ddfcf0fcfdde"}
# VBV - Lernbegleitung Einladung
LEARNING_MENTOR_INVITATION = {"de": "", "fr": "", "it": ""}
LEARNING_MENTOR_INVITATION = {
"de": "d-8c862afde62748b6b8410887eeee89d8",
"fr": "d-7451e3c858954c15a9f410fa9d92dc06",
"it": "d-30c6aa9accda4973a940dd25703cb4a9",
}
def send_email(