feat: mentor invite

This commit is contained in:
Reto Aebersold 2023-12-11 12:03:17 +01:00
parent 16a6334802
commit cfb38cc9fe
5 changed files with 70 additions and 12 deletions

View File

@ -1,3 +1,5 @@
from unittest.mock import patch
from django.urls import reverse from django.urls import reverse
from rest_framework import status from rest_framework import status
from rest_framework.test import APITestCase from rest_framework.test import APITestCase
@ -9,6 +11,8 @@ from vbv_lernwelt.course.creators.test_utils import (
create_user, create_user,
) )
from vbv_lernwelt.course.models import CourseSessionUser from vbv_lernwelt.course.models import CourseSessionUser
from vbv_lernwelt.learning_mentor.models import MentorInvitation
from vbv_lernwelt.notify.email.email_services import EmailTemplate
class LearningMentorInvitationTest(APITestCase): class LearningMentorInvitationTest(APITestCase):
@ -31,10 +35,11 @@ class LearningMentorInvitationTest(APITestCase):
# THEN # THEN
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
def test_create_invitation(self) -> None: @patch("vbv_lernwelt.learning_mentor.views.send_email")
def test_create_invitation(self, mock_send_mail) -> None:
# GIVEN # GIVEN
self.client.force_login(self.participant) self.client.force_login(self.participant)
add_course_session_user( participant_cs_user = add_course_session_user(
self.course_session, self.course_session,
self.participant, self.participant,
role=CourseSessionUser.Role.MEMBER, role=CourseSessionUser.Role.MEMBER,
@ -42,9 +47,44 @@ class LearningMentorInvitationTest(APITestCase):
invite_url = reverse( invite_url = reverse(
"create_invitation", kwargs={"course_session_id": self.course_session.id} "create_invitation", kwargs={"course_session_id": self.course_session.id}
) )
email = "test@example.com"
# WHEN # WHEN
response = self.client.post(invite_url, data={"email": "test@example.com"}) response = self.client.post(invite_url, data={"email": email})
# THEN # THEN
invitation_id = response.data["invitation"]
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertTrue(
MentorInvitation.objects.filter(
id=invitation_id,
).exists()
)
mock_send_mail.assert_called_once_with(
recipient_email=email,
template=EmailTemplate.LEARNING_MENTOR_INVITATION,
template_data={
"inviter_name": f"{self.participant.first_name} {self.participant.last_name}",
"inviter_email": self.participant.email,
"target_url": f"https://my.vbv-afa.ch/lernbegleitung/{self.course_session.id}/invitation/{invitation_id}",
},
template_language=self.participant.language,
fail_silently=True,
)
def test_accept_invitation(self) -> None:
# GIVEN
invitee = create_user("invitee")
self.client.force_login(invitee)
accept_url = reverse(
"create_invitation", kwargs={"course_session_id": self.course_session.id}
)
# WHEN
response = self.client.get(accept_url)
# THEN
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)

View File

@ -5,4 +5,5 @@ from . import views
urlpatterns = [ urlpatterns = [
path("summary", views.mentor_summary, name="mentor_summary"), path("summary", views.mentor_summary, name="mentor_summary"),
path("invite", views.create_invitation, name="create_invitation"), path("invite", views.create_invitation, name="create_invitation"),
path("accept", views.accept_invitation, name="accept_invitation"),
] ]

View File

@ -1,4 +1,3 @@
from django.shortcuts import redirect
from rest_framework import permissions from rest_framework import permissions
from rest_framework.decorators import api_view, permission_classes from rest_framework.decorators import api_view, permission_classes
from rest_framework.generics import get_object_or_404 from rest_framework.generics import get_object_or_404
@ -14,6 +13,7 @@ from vbv_lernwelt.learning_mentor.content.praxis_assignment import (
from vbv_lernwelt.learning_mentor.models import LearningMentor, MentorInvitation from vbv_lernwelt.learning_mentor.models import LearningMentor, MentorInvitation
from vbv_lernwelt.learning_mentor.serializers import PraxisAssignmentStatusSerializer from vbv_lernwelt.learning_mentor.serializers import PraxisAssignmentStatusSerializer
from vbv_lernwelt.learnpath.models import Circle from vbv_lernwelt.learnpath.models import Circle
from vbv_lernwelt.notify.email.email_services import EmailTemplate, send_email
@api_view(["GET"]) @api_view(["GET"])
@ -59,26 +59,40 @@ def list_invitations(request, course_session_id: int):
@api_view(["POST"]) @api_view(["POST"])
@permission_classes([IsAuthenticated, CourseSessionMember]) @permission_classes([IsAuthenticated, CourseSessionMember])
def create_invitation(request, course_session_id: int): def create_invitation(request, course_session_id: int):
user = request.user
course_session = get_object_or_404(CourseSession, id=course_session_id) course_session = get_object_or_404(CourseSession, id=course_session_id)
course_session_user = get_object_or_404( course_session_user = get_object_or_404(
CourseSessionUser, user=request.user, course_session=course_session CourseSessionUser, user=user, course_session=course_session
) )
email = request.data.get("email") email = request.data.get("email")
if not email: if not email:
return Response({"error": "email is required"}, status=400) return Response({"error": "email is required"}, status=400)
invitation = MentorInvitation.objects.get_or_create( invitation, _ = MentorInvitation.objects.get_or_create(
email=email, email=email,
participant=course_session_user, participant=course_session_user,
) )
return Response({}) target_url = f"/lernbegleitung/{course_session_id}/invitation/{invitation.id}"
send_email(
recipient_email=email,
template=EmailTemplate.LEARNING_MENTOR_INVITATION,
template_data={
"inviter_name": f"{user.first_name} {user.last_name}",
"inviter_email": user.email,
"target_url": f"https://my.vbv-afa.ch{target_url}",
},
template_language=request.user.language,
fail_silently=True,
)
return Response({"invitation": invitation.id})
@api_view(["GET"]) @api_view(["POST"])
@permission_classes([IsAuthenticated])
def accept_invitation(request, course_session_id: int): def accept_invitation(request, course_session_id: int):
if not request.user.is_authenticated: return Response({})
return redirect(f"/onboarding/vv/account/create?next={request.path}")
# Validate invitation

View File

@ -62,6 +62,9 @@ class EmailTemplate(Enum):
# VBV - Neues Feedback für Circle # VBV - Neues Feedback für Circle
NEW_FEEDBACK = {"de": "d-40fb94d5149949e7b8e7ddfcf0fcfdde"} NEW_FEEDBACK = {"de": "d-40fb94d5149949e7b8e7ddfcf0fcfdde"}
# VBV - Lernbegleitung Einladung
LEARNING_MENTOR_INVITATION = {"de": "", "fr": "", "it": ""}
def send_email( def send_email(
recipient_email: str, recipient_email: str,