feat: update/create notifiction pref while sending notifications (#32665)

* feat: update user pref while sending notifications

* feat: added flag and bulk create in task
This commit is contained in:
Ahtisham Shahid
2023-07-11 18:46:41 +05:00
committed by GitHub
parent cd0f925187
commit cd7e48c5d7
2 changed files with 119 additions and 1 deletions

View File

@@ -11,7 +11,12 @@ from edx_django_utils.monitoring import set_code_owner_attribute
from pytz import UTC
from common.djangoapps.student.models import CourseEnrollment
from openedx.core.djangoapps.notifications.models import CourseNotificationPreference, Notification
from openedx.core.djangoapps.notifications.config.waffle import ENABLE_NOTIFICATIONS
from openedx.core.djangoapps.notifications.models import (
CourseNotificationPreference,
Notification,
get_course_notification_preference_config_version
)
logger = get_task_logger(__name__)
@@ -78,6 +83,8 @@ def send_notifications(user_ids, course_key, app_name, notification_type, contex
"""
Send notifications to the users.
"""
if not ENABLE_NOTIFICATIONS.is_enabled(course_key):
return
user_ids = list(set(user_ids))
# check if what is preferences of user and make decision to send notification or not
@@ -85,8 +92,10 @@ def send_notifications(user_ids, course_key, app_name, notification_type, contex
user_id__in=user_ids,
course_id=course_key,
)
preferences = create_notification_pref_if_not_exists(user_ids, preferences, course_key)
notifications = []
for preference in preferences:
preference = update_user_preference(preference, preference.user, course_key)
if preference and preference.get_web_config(app_name, notification_type):
notifications.append(Notification(
user_id=preference.user_id,
@@ -98,3 +107,34 @@ def send_notifications(user_ids, course_key, app_name, notification_type, contex
))
# send notification to users but use bulk_create
Notification.objects.bulk_create(notifications)
def update_user_preference(preference: CourseNotificationPreference, user, course_id):
"""
Update user preference if config version is changed.
"""
current_version = get_course_notification_preference_config_version()
if preference.config_version != current_version:
return preference.get_updated_user_course_preferences(user, course_id)
return preference
def create_notification_pref_if_not_exists(user_ids, preferences, course_id):
"""
Create notification preference if not exist.
"""
new_preferences = []
for user_id in user_ids:
if not any(preference.user_id == user_id for preference in preferences):
new_preferences.append(CourseNotificationPreference(
user_id=user_id,
course_id=course_id,
))
logger.info('Creating new notification preference for user because it does not exist.')
if new_preferences:
# ignoring conflicts because it is possible that preference is already created by another process
# conflicts may arise because of constraint on user_id and course_id fields in model
CourseNotificationPreference.objects.bulk_create(new_preferences, ignore_conflicts=True)
preferences = preferences + new_preferences
return preferences

View File

@@ -0,0 +1,78 @@
"""
Tests for notifications tasks.
"""
from unittest.mock import patch
from edx_toggles.toggles.testutils import override_waffle_flag
from common.djangoapps.student.tests.factories import UserFactory
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory
from ..config.waffle import ENABLE_NOTIFICATIONS
from ..models import CourseNotificationPreference
from ..tasks import create_notification_pref_if_not_exists, update_user_preference
@patch('openedx.core.djangoapps.notifications.models.COURSE_NOTIFICATION_CONFIG_VERSION', 1)
class TestNotificationsTasks(ModuleStoreTestCase):
"""
Tests for notifications tasks.
"""
def setUp(self):
"""
Create a course and users for the course.
"""
super().setUp()
self.user = UserFactory()
self.user_1 = UserFactory()
self.user_2 = UserFactory()
self.course_1 = CourseFactory.create(
org='testorg',
number='testcourse',
run='testrun'
)
self.course_2 = CourseFactory.create(
org='testorg',
number='testcourse_2',
run='testrun'
)
self.preference_v1 = CourseNotificationPreference.objects.create(
user_id=self.user.id,
course_id=self.course_1.id,
config_version=0,
)
self.preference_v2 = CourseNotificationPreference.objects.create(
user_id=self.user.id,
course_id=self.course_2.id,
config_version=1,
)
def test_update_user_preference(self):
"""
Test whether update_user_preference updates the preference with the latest config version.
"""
# Test whether update_user_preference updates the preference with a different config version
updated_preference = update_user_preference(self.preference_v1, self.user, self.course_1.id)
self.assertEqual(updated_preference.config_version, 1)
# Test whether update_user_preference does not update the preference if the config version is the same
updated_preference = update_user_preference(self.preference_v2, self.user, self.course_2.id)
self.assertEqual(updated_preference.config_version, 1)
@override_waffle_flag(ENABLE_NOTIFICATIONS, active=True)
def test_create_notification_pref_if_not_exists(self):
"""
Test whether create_notification_pref_if_not_exists creates a new preference if it doesn't exist.
"""
# Test whether create_notification_pref_if_not_exists creates a new preference if it doesn't exist
user_ids = [self.user.id, self.user_1.id, self.user_2.id]
preferences = [self.preference_v2]
updated_preferences = create_notification_pref_if_not_exists(user_ids, preferences, self.course_2.id)
self.assertEqual(len(updated_preferences), 3) # Should have created two new preferences
# Test whether create_notification_pref_if_not_exists doesn't create a new preference if it already exists
updated_preferences = create_notification_pref_if_not_exists(user_ids, preferences, self.course_2.id)
self.assertEqual(len(updated_preferences), 3) # No new preferences should be created this time