Skip to content

Commit

Permalink
Merge pull request #2077 from openedx/ammar/set-default-lang-for-ente…
Browse files Browse the repository at this point in the history
…rprise-learners

fix: set default language for all learners linked with an enterprise customer
  • Loading branch information
muhammad-ammar authored Apr 22, 2024
2 parents 5648d58 + 850b9d9 commit 6692c94
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 25 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ Change Log
Unreleased
----------
[4.15.10]
---------
* fix: set default langauge for all learners linked with an enteprise customer

[4.15.9]
--------
* fix: return a 404 response for inactive CSOD customers while fetching courses
Expand Down
2 changes: 1 addition & 1 deletion enterprise/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
Your project description goes here.
"""

__version__ = "4.15.9"
__version__ = "4.15.10"
13 changes: 9 additions & 4 deletions enterprise/signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
NotConnectedToOpenEdX,
get_default_catalog_content_filter,
localized_utcnow,
unset_enterprise_learner_language,
set_enterprise_learner_language,
)
from integrated_channels.blackboard.models import BlackboardEnterpriseCustomerConfiguration
from integrated_channels.canvas.models import CanvasEnterpriseCustomerConfiguration
Expand Down Expand Up @@ -104,10 +104,15 @@ def update_lang_pref_of_all_learners(sender, instance, **kwargs): # pylint: dis
if instance.default_language:
prev_state = models.EnterpriseCustomer.objects.filter(uuid=instance.uuid).first()
if prev_state and prev_state.default_language != instance.default_language:
default_language = instance.default_language
# Unset the language preference of all the learners linked with the enterprise customer.
# The middleware in the enterprise will handle the cases for setting a proper language for the learner.
logger.info('Task triggered to update user preference for learners. Enterprise: [%s]', instance.uuid)
update_enterprise_learners_user_preference.delay(instance.uuid)
logger.info(
'[SET_ENT_LANG] Task triggered to update user preference.. Enterprise: [%s], Language: [%s]',
instance.uuid,
default_language
)
update_enterprise_learners_user_preference.delay(instance.uuid, default_language)


@receiver(pre_save, sender=models.EnterpriseCustomerBrandingConfiguration)
Expand Down Expand Up @@ -207,7 +212,7 @@ def update_learner_language_preference(sender, instance, created, **kwargs):
# Unset the language preference when a new learner is linked with the enterprise customer.
# The middleware in the enterprise will handle the cases for setting a proper language for the learner.
if created and instance.enterprise_customer.default_language:
unset_enterprise_learner_language(instance)
set_enterprise_learner_language(instance)


@receiver(post_save, sender=models.PendingEnterpriseCustomerAdminUser)
Expand Down
7 changes: 4 additions & 3 deletions enterprise/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from enterprise.utils import (
get_enterprise_customer,
send_email_notification_message,
unset_language_of_all_enterprise_learners,
set_language_of_all_enterprise_learners,
)

LOGGER = getLogger(__name__)
Expand Down Expand Up @@ -342,11 +342,12 @@ def send_group_membership_removal_notification(enterprise_customer_uuid, members

@shared_task
@set_code_owner_attribute
def update_enterprise_learners_user_preference(enterprise_customer_uuid):
def update_enterprise_learners_user_preference(enterprise_customer_uuid, default_language):
"""
Update the user preference `pref-lang` attribute for all enterprise learners linked with an enterprise.
Arguments:
* enterprise_customer_uuid (UUID): uuid of an enterprise customer
* default_language (str): new language code to set for all enterprise learners
"""
unset_language_of_all_enterprise_learners(enterprise_customer_uuid)
set_language_of_all_enterprise_learners(enterprise_customer_uuid, default_language)
27 changes: 18 additions & 9 deletions enterprise/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2218,34 +2218,43 @@ def get_platform_logo_url():
return urljoin(settings.LMS_ROOT_URL, logo_url)


def unset_language_of_all_enterprise_learners(enterprise_customer_uuid):
def set_language_of_all_enterprise_learners(enterprise_customer_uuid, default_language):
"""
Unset the language preference of all the learners belonging to the given enterprise customer.
Set the language preference of all the learners belonging to the given enterprise customer.
Arguments:
enterprise_customer_uuid (UUI): uuid of an enterprise customer
default_language (str): default language to set for all learners
"""
if UserPreference:
enterprise_customer = get_enterprise_customer(enterprise_customer_uuid)
user_ids = list(enterprise_customer.enterprise_customer_users.values_list('user_id', flat=True))

LOGGER.info('Update user preference started for learners. Enterprise: [%s]', enterprise_customer_uuid)
LOGGER.info(
'[SET_ENT_LANG] Update user preference started for learners. Enterprise: [%s], Language: [%s]',
enterprise_customer_uuid,
default_language
)

for chunk in batch(user_ids, batch_size=10000):
UserPreference.objects.filter(
key=LANGUAGE_KEY,
user_id__in=chunk
).update(
value=''
value=default_language
)
LOGGER.info('Updated user preference for learners. Batch Size: [%s]', len(chunk))
LOGGER.info('[SET_ENT_LANG] Updated user preference for learners. Batch Size: [%s]', len(chunk))

LOGGER.info('Update user preference completed for learners. Enterprise: [%s]', enterprise_customer_uuid)
LOGGER.info(
'[SET_ENT_LANG] Update user preference completed for learners. Enterprise: [%s], Language: [%s]',
enterprise_customer_uuid,
default_language
)


def unset_enterprise_learner_language(enterprise_customer_user):
def set_enterprise_learner_language(enterprise_customer_user):
"""
Unset the language preference of the given enterprise learners.
Set the language preference of the given enterprise learners.
Arguments:
enterprise_customer_user (EnterpriseCustomerUser): Instance of the enterprise customer user.
Expand All @@ -2254,7 +2263,7 @@ def unset_enterprise_learner_language(enterprise_customer_user):
UserPreference.objects.update_or_create(
key=LANGUAGE_KEY,
user_id=enterprise_customer_user.user_id,
defaults={'value': ''}
defaults={'value': enterprise_customer_user.enterprise_customer.default_language}
)


Expand Down
23 changes: 15 additions & 8 deletions tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -332,9 +332,9 @@ def test_catalog_contains_course_with_enterprise_customer_catalog(self, api_clie
wraps=update_enterprise_learners_user_preference
)
@mock.patch('enterprise.utils.UserPreference', return_value=mock.MagicMock())
def test_unset_language_of_all_enterprise_learners(self, user_preference_mock, mock_task):
def test_set_language_of_all_enterprise_learners(self, user_preference_mock, mock_task):
"""
Validate that unset_language_of_all_enterprise_learners is called whenever default_language changes.
Validate that set_language_of_all_enterprise_learners is called whenever default_language changes.
"""
user = factories.UserFactory(email='[email protected]')
enterprise_customer = factories.EnterpriseCustomerFactory()
Expand All @@ -345,22 +345,24 @@ def test_unset_language_of_all_enterprise_learners(self, user_preference_mock, m
enterprise_customer.default_language = 'es-419'
enterprise_customer.save()
mock_task.assert_called_once()
user_preference_mock.objects.filter.return_value.update.assert_called_with(value='es-419')
user_preference_mock.objects.filter.assert_called_once()

# Make sure `unset_language_of_all_enterprise_learners` is called each time `default_language` changes.
# Make sure `set_language_of_all_enterprise_learners` is called each time `default_language` changes.
enterprise_customer.default_language = 'es-417'
enterprise_customer.save()
assert mock_task.call_count == 2
user_preference_mock.objects.filter.return_value.update.assert_called_with(value='es-417')
assert user_preference_mock.objects.filter.call_count == 2

# make sure `unset_language_of_all_enterprise_learners` is not called if `default_language` is
# make sure `set_language_of_all_enterprise_learners` is not called if `default_language` is
# not changed.
enterprise_customer.default_language = 'es-417'
enterprise_customer.save()
assert mock_task.call_count == 2
assert user_preference_mock.objects.filter.call_count == 2

# Make sure `unset_language_of_all_enterprise_learners` is not called if `default_language` is
# Make sure `set_language_of_all_enterprise_learners` is not called if `default_language` is
# set to `None`.
enterprise_customer.default_language = None
enterprise_customer.save()
Expand Down Expand Up @@ -1006,15 +1008,20 @@ def test_soft_delete(self, method_name):
)

@mock.patch('enterprise.utils.UserPreference', return_value=mock.MagicMock())
def test_unset_enterprise_learner_language(self, user_preference_mock):
def test_set_enterprise_learner_language(self, user_preference_mock):
"""
Validate that unset_enterprise_learner_language is called whenever a nwe learner is linked to an enterprise
Validate that set_enterprise_learner_language is called whenever a nwe learner is linked to an enterprise
customer with Non-Null default language.
"""
enterprise_customer_user = factories.EnterpriseCustomerUserFactory()
user_preference_mock.objects.update_or_create.assert_called_once()
user_preference_mock.objects.update_or_create.assert_called_with(
key='pref-lang',
user_id=enterprise_customer_user.user_id,
defaults={'value': 'en'}
)

# Make sure `unset_enterprise_learner_language` is not called if the enterprise customer does not have a
# Make sure `set_enterprise_learner_language` is not called if the enterprise customer does not have a
# default_language.
enterprise_customer_user.enterprise_customer.default_language = None
enterprise_customer_user.enterprise_customer.save()
Expand Down

0 comments on commit 6692c94

Please sign in to comment.