diff --git a/enterprise_access/apps/api_client/lms_client.py b/enterprise_access/apps/api_client/lms_client.py index 0f39dd3b..f3638c7e 100755 --- a/enterprise_access/apps/api_client/lms_client.py +++ b/enterprise_access/apps/api_client/lms_client.py @@ -11,8 +11,9 @@ from enterprise_access.apps.api_client.base_oauth import BaseOAuthClient from enterprise_access.apps.api_client.exceptions import FetchGroupMembersConflictingParamsException +from enterprise_access.apps.enterprise_groups.constants import GROUP_MEMBERSHIP_EMAIL_ERROR_STATUS from enterprise_access.cache_utils import versioned_cache_key -from enterprise_access.utils import should_send_email_to_pecu +from enterprise_access.utils import localized_utcnow, should_send_email_to_pecu logger = logging.getLogger(__name__) @@ -372,3 +373,26 @@ def get_pending_enterprise_group_memberships(self, enterprise_group_uuid): logger.exception('Incorrect data received from LMS. [%s]', url) return None + + def update_pending_learner_status(self, enterprise_group_uuid, learner_email): + """ + Partially updates learners + + Arguments: + enterprise_group_uuid (str): uuid of the enterprise group uuid + learner_email (str): email for learner + + """ + try: + url = f'{self.enterprise_group_membership_endpoint}' + ( + f'{enterprise_group_uuid}/learners/') + payload = {'learner': learner_email, + 'status': GROUP_MEMBERSHIP_EMAIL_ERROR_STATUS, + 'errored_at': localized_utcnow()} + response = self.client.patch(url, data=payload) + return response.json() + except requests.exceptions.HTTPError: + logger.exception('failed to update group membership status. URL: [%s].', url) + except KeyError: + logger.exception('failed to update group membership status. [%s]', url) + return None diff --git a/enterprise_access/apps/enterprise_groups/constants.py b/enterprise_access/apps/enterprise_groups/constants.py index 9b7f02aa..5056ea91 100644 --- a/enterprise_access/apps/enterprise_groups/constants.py +++ b/enterprise_access/apps/enterprise_groups/constants.py @@ -9,3 +9,5 @@ BRAZE_GROUPS_EMAIL_CAMPAIGNS_THIRD_REMINDER_DAY = 50 BRAZE_GROUPS_EMAIL_CAMPAIGNS_FOURTH_REMINDER_DAY = 65 BRAZE_GROUPS_EMAIL_CAMPAIGNS_FINAL_REMINDER_DAY = 85 + +GROUP_MEMBERSHIP_EMAIL_ERROR_STATUS = 'email_error' diff --git a/enterprise_access/apps/enterprise_groups/management/commands/groups_reminder_emails.py b/enterprise_access/apps/enterprise_groups/management/commands/groups_reminder_emails.py index 33c0eda1..c2e23c8d 100644 --- a/enterprise_access/apps/enterprise_groups/management/commands/groups_reminder_emails.py +++ b/enterprise_access/apps/enterprise_groups/management/commands/groups_reminder_emails.py @@ -59,5 +59,6 @@ def handle(self, *args, **options): ) pending_enterprise_customer_user["catalog_count"] = catalog_count pending_enterprise_customer_user["enterprise_customer_name"] = enterprise_customer_data["name"] + pending_enterprise_customer_user["enterprise_group_uuid"] = enterprise_group_uuid pecu_email_properties.append(pending_enterprise_customer_user) send_group_reminder_emails.delay(pecu_email_properties) diff --git a/enterprise_access/apps/enterprise_groups/tasks.py b/enterprise_access/apps/enterprise_groups/tasks.py index a64f4e6c..84242297 100644 --- a/enterprise_access/apps/enterprise_groups/tasks.py +++ b/enterprise_access/apps/enterprise_groups/tasks.py @@ -10,6 +10,7 @@ from django.conf import settings from enterprise_access.apps.api_client.braze_client import ENTERPRISE_BRAZE_ALIAS_LABEL, BrazeApiClient +from enterprise_access.apps.api_client.lms_client import LmsApiClient from enterprise_access.apps.enterprise_groups.constants import ( BRAZE_GROUPS_EMAIL_CAMPAIGNS_FINAL_REMINDER_DAY, BRAZE_GROUPS_EMAIL_CAMPAIGNS_FIRST_REMINDER_DAY, @@ -132,6 +133,7 @@ def send_group_reminder_emails(pending_enterprise_users): * pending_enterprise_users (list) """ braze_client_instance = BrazeApiClient() + lms_client = LmsApiClient() for pending_enterprise_user in pending_enterprise_users: pecu_email = pending_enterprise_user["user_email"] @@ -165,5 +167,8 @@ def send_group_reminder_emails(pending_enterprise_users): "Groups learner reminder email could not be sent " f"to {recipient} with braze properties {braze_properties}." ) + lms_client.update_pending_learner_status( + enterprise_group_uuid=pending_enterprise_user["enterprise_group_uuid"], + learner_email=pecu_email) logger.exception(message) raise exc diff --git a/enterprise_access/apps/enterprise_groups/tests/test_tasks.py b/enterprise_access/apps/enterprise_groups/tests/test_tasks.py index f0ef6f31..bf612bfe 100644 --- a/enterprise_access/apps/enterprise_groups/tests/test_tasks.py +++ b/enterprise_access/apps/enterprise_groups/tests/test_tasks.py @@ -6,7 +6,9 @@ from unittest import mock from uuid import uuid4 +from braze.exceptions import BrazeClientError from django.conf import settings +from pytest import raises from enterprise_access.apps.enterprise_groups.tasks import send_group_reminder_emails @@ -32,6 +34,7 @@ def setUp(self): "enterprise_customer_name": "test enterprise", "catalog_count": 5, "subsidy_expiration_datetime": "2060-03-25T20:46:28Z", + "enterprise_group_uuid": uuid4(), }) super().setUp() @@ -63,3 +66,22 @@ def test_send_group_reminder_emails(self, mock_braze_api_client): }, )] mock_braze_api_client().send_campaign_message.assert_has_calls(calls) + + @mock.patch('enterprise_access.apps.enterprise_groups.tasks.LmsApiClient', return_value=mock.MagicMock()) + @mock.patch('enterprise_access.apps.enterprise_groups.tasks.BrazeApiClient', return_value=mock.MagicMock()) + def test_fail_send_group_reminder_emails(self, mock_braze_api_client, mock_lms_client): + """ + Verify braze fails send email and calls update_pending_learner_status with correct params + """ + mock_braze_api_client().create_recipient_no_external_id.return_value = ( + self.pending_enterprise_customer_users[0]['user_email']) + mock_braze_api_client().send_campaign_message.side_effect = BrazeClientError( + "Any thing that happens during email") + + with raises(BrazeClientError): + send_group_reminder_emails( + self.pending_enterprise_customer_users) + mock_lms_client().update_pending_learner_status.assert_called_with( + enterprise_group_uuid=self.pending_enterprise_customer_users[0]["enterprise_group_uuid"], + learner_email=self.pending_enterprise_customer_users[0]['user_email'] + )