From af40ac0feb774db1c592de6062505b70dbef09c6 Mon Sep 17 00:00:00 2001 From: Ahtisham Shahid Date: Wed, 16 Apr 2025 15:39:22 +0500 Subject: [PATCH] feat: update preference config when version is changed (#36518) --- .../core/djangoapps/notifications/models.py | 29 ++++++++++++ .../notifications/tests/test_models.py | 44 +++++++++++++++++++ .../core/djangoapps/notifications/views.py | 3 +- 3 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 openedx/core/djangoapps/notifications/tests/test_models.py diff --git a/openedx/core/djangoapps/notifications/models.py b/openedx/core/djangoapps/notifications/models.py index e3bad0016e..8a397ff8e5 100644 --- a/openedx/core/djangoapps/notifications/models.py +++ b/openedx/core/djangoapps/notifications/models.py @@ -172,6 +172,35 @@ class CourseNotificationPreference(TimeStampedModel): log.error(f'Unable to update notification preference to new config. {e}') return preferences + @staticmethod + def get_user_notification_preferences(user): + """ + Checks if all user preferences have updated versions and returns the user preferences. + Updates any preferences that need to be updated to the latest config version. + """ + preferences = CourseNotificationPreference.objects.filter(user=user, is_active=True) + email_opt_out = UserPreference.objects.filter(user_id=user.id, key=ONE_CLICK_EMAIL_UNSUB_KEY).exists() + current_config_version = get_course_notification_preference_config_version() + preferences_to_update = [] + + try: + for preference in preferences: + if preference.config_version != current_config_version: + current_prefs = preference.notification_preference_config + new_prefs = NotificationPreferenceSyncManager.update_preferences(current_prefs, email_opt_out) + preference.config_version = current_config_version + preference.notification_preference_config = new_prefs + preferences_to_update.append(preference) + if preferences_to_update: + CourseNotificationPreference.objects.bulk_update( + preferences_to_update, + ['config_version', 'notification_preference_config'] + ) + except Exception as e: # pylint: disable=broad-exception-caught + log.error(f'Unable to update notification preference to new config: {str(e)}') + + return preferences + @staticmethod def get_updated_user_course_preferences(user, course_id): return CourseNotificationPreference.get_user_course_preference(user.id, course_id) diff --git a/openedx/core/djangoapps/notifications/tests/test_models.py b/openedx/core/djangoapps/notifications/tests/test_models.py new file mode 100644 index 0000000000..fed0ab2e36 --- /dev/null +++ b/openedx/core/djangoapps/notifications/tests/test_models.py @@ -0,0 +1,44 @@ +""" +Test the notification app models +""" +import unittest +from unittest import mock + +import pytest + +from common.djangoapps.student.tests.factories import UserFactory +from openedx.core.djangoapps.notifications.base_notification import NotificationAppManager +from openedx.core.djangoapps.notifications.models import CourseNotificationPreference, \ + COURSE_NOTIFICATION_CONFIG_VERSION + + +@pytest.mark.django_db +class TestPreferenceModel(unittest.TestCase): + """ + Test the CourseNotificationPreference model. + """ + + def test_get_user_notification_preferences_method(self): + """ + Test the get_user_notification_preferences method. and check if version is updated properly. + """ + # Create a mock user and notification preference + user = UserFactory() + CourseNotificationPreference.objects.create( + user_id=user.id, + course_id='course-v1:edX+DemoX+Demo_Course', + is_active=True, + notification_preference_config=NotificationAppManager().get_notification_app_preferences(True) + ) + # Check if the notification preference is created + preference = CourseNotificationPreference.objects.get(user_id=user.id) + self.assertIsNotNone(preference) + self.assertTrue(preference.is_active) + + with mock.patch( + 'openedx.core.djangoapps.notifications.models.COURSE_NOTIFICATION_CONFIG_VERSION', + COURSE_NOTIFICATION_CONFIG_VERSION + 1 + ): + updated_preferences = preference.get_user_notification_preferences(user) + for updated_preference in updated_preferences: + assert updated_preference.config_version == COURSE_NOTIFICATION_CONFIG_VERSION + 1 diff --git a/openedx/core/djangoapps/notifications/views.py b/openedx/core/djangoapps/notifications/views.py index da969cc507..805145bf68 100644 --- a/openedx/core/djangoapps/notifications/views.py +++ b/openedx/core/djangoapps/notifications/views.py @@ -591,8 +591,7 @@ class AggregatedNotificationPreferences(APIView): """ API view for getting the aggregate notification preferences for the current user. """ - notification_preferences = CourseNotificationPreference.objects.filter(user=request.user, is_active=True) - + notification_preferences = CourseNotificationPreference.get_user_notification_preferences(request.user) if not notification_preferences.exists(): return Response({ 'status': 'error',