From b8accb0c62ff68a13b5b7a3b864d4ea8776d20d1 Mon Sep 17 00:00:00 2001 From: Livio Bieri Date: Thu, 7 Dec 2023 15:56:59 +0100 Subject: [PATCH] feat: send welcome mail vv --- .../notify/email/email_services.py | 7 +++++ server/vbv_lernwelt/shop/README.md | 24 ++++++++++------- .../shop/tests/test_datatrans_webhook.py | 24 +++++++++++++++-- server/vbv_lernwelt/shop/views.py | 26 ++++++++++++++++++- 4 files changed, 68 insertions(+), 13 deletions(-) diff --git a/server/vbv_lernwelt/notify/email/email_services.py b/server/vbv_lernwelt/notify/email/email_services.py index 66cb7b97..cd9dd7a0 100644 --- a/server/vbv_lernwelt/notify/email/email_services.py +++ b/server/vbv_lernwelt/notify/email/email_services.py @@ -62,6 +62,13 @@ class EmailTemplate(Enum): # VBV - Neues Feedback für Circle NEW_FEEDBACK = {"de": "d-40fb94d5149949e7b8e7ddfcf0fcfdde"} + # Versicherungsvermittler (after buying a course) + WELCOME_MAIL_VV = { + "de": "d-308a72c779b74c8487cdec03c772ad13", + "fr": "d-1a0958c7798c4dd18f730491e920eab5", + "it": "d-0882ec9c92f64312b9f358481a943c9a", + } + def send_email( recipient_email: str, diff --git a/server/vbv_lernwelt/shop/README.md b/server/vbv_lernwelt/shop/README.md index fc423a65..439869ae 100644 --- a/server/vbv_lernwelt/shop/README.md +++ b/server/vbv_lernwelt/shop/README.md @@ -5,20 +5,20 @@ In the Django shop app, create new products that should be available in the shop: - `vv-de` Price 30000 (300_00 -> 300.00 CHF), name & description can be anything. - - ONLY if `COURSE_VERSICHERUNGSVERMITTLERIN_ID` exists! + - ONLY if `COURSE_VERSICHERUNGSVERMITTLERIN_ID` exists! - `vv-fr` Price 30000 (300_00 -> 300.00 CHF), name & description can be anything. - - ONLY if `COURSE_VERSICHERUNGSVERMITTLERIN_ID_FR` exists! + - ONLY if `COURSE_VERSICHERUNGSVERMITTLERIN_ID_FR` exists! - `vv-it` Price 30000 (300_00 -> 300.00 CHF), name & description can be anything. - - ONLY if `COURSE_VERSICHERUNGSVERMITTLERIN_ID_IT` exists! + - ONLY if `COURSE_VERSICHERUNGSVERMITTLERIN_ID_IT` exists! ## Datatrans (Payment Provider) - Set `DATATRANS_BASIC_AUTH_KEY`: - - https://admin.sandbox.datatrans.com/MenuDispatch.jsp?main=1&sub=4 - - `echo -n "{merchantid}:{password}" | base64` + - https://admin.sandbox.datatrans.com/MenuDispatch.jsp?main=1&sub=4 + - `echo -n "{merchantid}:{password}" | base64` - Set `DATATRANS_HMAC_KEY`: - - https://admin.sandbox.datatrans.com/MerchSecurAdmin.jsp + - https://admin.sandbox.datatrans.com/MerchSecurAdmin.jsp For Production: @@ -47,14 +47,18 @@ For Production: Make sure that the following env vars are set: ### Caprover (VITEx) - Set `VITE_OAUTH_API_BASE_URL` in `caprover_deploy.sh` for `prod` environment. - - `OAUTH_SIGNIN_SERVER_METADATA_URL` should help to find the correct value. - - Should be the SSO Prod one from Lernnetz. -> TBD! + - `OAUTH_SIGNIN_SERVER_METADATA_URL` should help to find the correct value. + - Should be the SSO Prod one from Lernnetz. -> TBD! + +### send_vv_welcome_email() + +- Due to lack of access to Sendgrid, never tested actually sending the email. ## Testing Payment Flow - To get user into state for testing (e.g. test-student1@example.com so that he can buy the course): - - Remove all existing course session users for the user. - - Remove all existing checkout information for the user. + - Remove all existing course session users for the user. + - Remove all existing checkout information for the user. ### Cleanup diff --git a/server/vbv_lernwelt/shop/tests/test_datatrans_webhook.py b/server/vbv_lernwelt/shop/tests/test_datatrans_webhook.py index 0bc1a5b4..67abcc82 100644 --- a/server/vbv_lernwelt/shop/tests/test_datatrans_webhook.py +++ b/server/vbv_lernwelt/shop/tests/test_datatrans_webhook.py @@ -1,4 +1,4 @@ -from unittest.mock import patch +from unittest.mock import ANY, patch from django.urls import reverse from rest_framework import status @@ -8,6 +8,7 @@ from vbv_lernwelt.core.admin import User from vbv_lernwelt.course.consts import COURSE_VERSICHERUNGSVERMITTLERIN_ID from vbv_lernwelt.course.creators.test_utils import create_course, create_course_session from vbv_lernwelt.course.models import CourseSessionUser +from vbv_lernwelt.notify.email.email_services import EmailTemplate from vbv_lernwelt.shop.const import VV_DE_PRODUCT_SKU from vbv_lernwelt.shop.models import CheckoutInformation, CheckoutState, Product @@ -75,7 +76,10 @@ class DatatransWebhookTestCase(APITestCase): ) @patch("vbv_lernwelt.shop.views.is_signature_valid") - def test_webhook_settled_transmitted_paid(self, mock_is_signature_valid): + @patch("vbv_lernwelt.shop.views.send_email") + def test_webhook_settled_transmitted_paid( + self, mock_send_mail, mock_is_signature_valid + ): # GIVEN transaction_id = "1234567890" @@ -135,6 +139,22 @@ class DatatransWebhookTestCase(APITestCase): CourseSessionUser.objects.first().course_session.course.id, ) + self.assertEqual( + 1, + mock_send_mail.call_count, + ) + + mock_send_mail.assert_called_once_with( + template=EmailTemplate.WELCOME_MAIL_VV, + recipient_email=self.user.email, + template_data={ + "course": "Versicherungsvermittler/-in (Deutsch)", + "target_url": "https://my.vbv-afa.ch/", + }, + template_language=self.user.language, + fail_silently=ANY, + ) + @patch("vbv_lernwelt.shop.views.is_signature_valid") def test_webhook_updates_webhook_history(self, mock_is_signature_valid): # GIVEN diff --git a/server/vbv_lernwelt/shop/views.py b/server/vbv_lernwelt/shop/views.py index 37694d66..50f2169b 100644 --- a/server/vbv_lernwelt/shop/views.py +++ b/server/vbv_lernwelt/shop/views.py @@ -13,6 +13,7 @@ from vbv_lernwelt.course.consts import ( COURSE_VERSICHERUNGSVERMITTLERIN_IT_ID, ) from vbv_lernwelt.course.models import CourseSession, CourseSessionUser +from vbv_lernwelt.notify.email.email_services import EmailTemplate, send_email from vbv_lernwelt.shop.const import ( VV_DE_PRODUCT_SKU, VV_FR_PRODUCT_SKU, @@ -194,10 +195,29 @@ def update_checkout_state(checkout_info: CheckoutInformation, state: CheckoutSta checkout_info.save(update_fields=["state"]) +def send_vv_welcome_email(checkout_info: CheckoutInformation): + course_names = { + VV_DE_PRODUCT_SKU: "Versicherungsvermittler/-in (Deutsch)", + VV_FR_PRODUCT_SKU: "Intermédiaire d’assurance (Français)", + VV_IT_PRODUCT_SKU: "Intermediario/a assicurativo/a (Italiano)", + } + + send_email( + recipient_email=checkout_info.user.email, + template=EmailTemplate.WELCOME_MAIL_VV, + template_data={ + "course": course_names[checkout_info.product_sku], + "target_url": "https://my.vbv-afa.ch/", + }, + template_language=checkout_info.user.language, + fail_silently=True, + ) + + def create_vv_course_session_user(checkout_info: CheckoutInformation): logger.info("Creating VV course session user", user_id=checkout_info.user_id) - CourseSessionUser.objects.get_or_create( + _, created = CourseSessionUser.objects.get_or_create( user=checkout_info.user, role=CourseSessionUser.Role.MEMBER, course_session=CourseSession.objects.filter( @@ -205,6 +225,10 @@ def create_vv_course_session_user(checkout_info: CheckoutInformation): ).first(), ) + if created: + logger.info("VV course session user created", user_id=checkout_info.user_id) + send_vv_welcome_email(checkout_info) + def next_step_response( url: str,