From 509c2fde9b05251a9ef9a4634aaeb53c295805fd Mon Sep 17 00:00:00 2001 From: Troy Sankey Date: Tue, 16 Apr 2024 15:47:49 -0700 Subject: [PATCH 1/2] fix: support `force_enrollment` in serializers used by bulk enrollment ENT-8788 --- CHANGELOG.rst | 4 ++ enterprise/__init__.py | 2 +- enterprise/api/v1/serializers.py | 4 ++ tests/test_enterprise/api/test_views.py | 51 +++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 622f671132..7001af1e5a 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -15,6 +15,10 @@ Change Log Unreleased ---------- +[4.15.11] +--------- +* fix: support `force_enrollment` in serializers used by bulk enrollment (ENT-8788) + [4.15.10] --------- * fix: set default langauge for all learners linked with an enteprise customer diff --git a/enterprise/__init__.py b/enterprise/__init__.py index fa9c7d255c..bb768c7a2f 100644 --- a/enterprise/__init__.py +++ b/enterprise/__init__.py @@ -2,4 +2,4 @@ Your project description goes here. """ -__version__ = "4.15.10" +__version__ = "4.15.11" diff --git a/enterprise/api/v1/serializers.py b/enterprise/api/v1/serializers.py index b17a6864c2..3cfec2e1d1 100644 --- a/enterprise/api/v1/serializers.py +++ b/enterprise/api/v1/serializers.py @@ -1426,6 +1426,10 @@ class EnrollmentsInfoSerializer(serializers.Serializer): course_run_key = serializers.CharField(required=True) license_uuid = serializers.CharField(required=False) transaction_id = serializers.CharField(required=False) + force_enrollment = serializers.BooleanField( + required=False, + help_text='Enroll even if enrollment deadline is expired.', + ) def create(self, validated_data): return validated_data diff --git a/tests/test_enterprise/api/test_views.py b/tests/test_enterprise/api/test_views.py index 0c9d5695b1..4cb4de9fca 100644 --- a/tests/test_enterprise/api/test_views.py +++ b/tests/test_enterprise/api/test_views.py @@ -4645,6 +4645,57 @@ def test_bulk_enrollment_in_bulk_courses_existing_users( assert mock_update_or_create_enrollment.call_count == 2 + @mock.patch('enterprise.api.v1.views.enterprise_customer.get_best_mode_from_course_key') + @mock.patch('enterprise.utils.lms_update_or_create_enrollment') + @mock.patch('enterprise.api.v1.views.enterprise_customer.track_enrollment', mock.MagicMock()) + def test_bulk_enrollment_force_enrollment( + self, + mock_update_or_create_enrollment, + mock_get_course_mode, + ): + """ + Ensure bulk enrollment passes force_enrollment hints into lower level functions. + """ + mock_update_or_create_enrollment.return_value = True + + user_one = factories.UserFactory(is_active=True) + user_two = factories.UserFactory(is_active=True) + + factories.EnterpriseCustomerFactory( + uuid=FAKE_UUIDS[0], + name="test_enterprise" + ) + + permission = Permission.objects.get(name='Can add Enterprise Customer') + self.user.user_permissions.add(permission) + mock_get_course_mode.return_value = VERIFIED_SUBSCRIPTION_COURSE_MODE + + self.assertEqual(len(PendingEnrollment.objects.all()), 0) + body = { + 'enrollments_info': [ + { + 'user_id': user_one.id, + 'course_run_key': 'course-v1:edX+DemoX+Demo_Course', + 'license_uuid': '5a88bdcade7c4ecb838f8111b68e18ac', + # For this enrollment, force_enrollment should fallback to False. + }, + { + 'email': user_two.email, + 'course_run_key': 'course-v1:edX+DemoX+Demo_Course', + 'license_uuid': '2c58acdade7c4ede838f7111b42e18ac', + 'force_enrollment': True, + }, + ] + } + response = self.client.post( + settings.TEST_SERVER + ENTERPRISE_CUSTOMER_BULK_ENROLL_LEARNERS_IN_COURSES_ENDPOINT, + data=json.dumps(body), + content_type='application/json', + ) + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + assert mock_update_or_create_enrollment.mock_calls[0].kwargs['force_enrollment'] is False + assert mock_update_or_create_enrollment.mock_calls[1].kwargs['force_enrollment'] is True + @mock.patch('enterprise.api.v1.views.enterprise_customer.get_best_mode_from_course_key') @mock.patch('enterprise.api.v1.views.enterprise_customer.track_enrollment') @mock.patch('enterprise.models.EnterpriseCustomer.notify_enrolled_learners') From 8face76f719caaeaed57a758db332aeab2e5bc36 Mon Sep 17 00:00:00 2001 From: Troy Sankey Date: Thu, 18 Apr 2024 09:45:57 -0700 Subject: [PATCH 2/2] chore: run make upgrade --- requirements/celery53.txt | 2 +- requirements/ci.txt | 2 +- requirements/dev.txt | 6 +++--- requirements/doc.txt | 4 ++-- requirements/edx-platform-constraints.txt | 12 ++++++------ requirements/js_test.txt | 2 +- requirements/test-master.txt | 2 +- requirements/test.txt | 2 +- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/requirements/celery53.txt b/requirements/celery53.txt index b3a9bf658d..0fd605edca 100644 --- a/requirements/celery53.txt +++ b/requirements/celery53.txt @@ -1,6 +1,6 @@ amqp==5.2.0 billiard==4.2.0 -celery==5.3.6 +celery==5.4.0 click==8.1.7 click-didyoumean==0.3.1 click-repl==0.3.0 diff --git a/requirements/ci.txt b/requirements/ci.txt index 33562f47e6..91f601b1d4 100644 --- a/requirements/ci.txt +++ b/requirements/ci.txt @@ -26,5 +26,5 @@ tox==3.28.0 # via # -c requirements/constraints.txt # -r requirements/ci.in -virtualenv==20.25.1 +virtualenv==20.25.3 # via tox diff --git a/requirements/dev.txt b/requirements/dev.txt index 028e609557..320e4d4eb9 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -96,7 +96,7 @@ bleach==6.1.0 # -r requirements/test.txt build==1.2.1 # via pip-tools -celery==5.3.6 +celery==5.4.0 # via # -c requirements/constraints.txt # -r requirements/doc.txt @@ -405,7 +405,7 @@ factory-boy==3.3.0 # -c requirements/constraints.txt # -r requirements/doc.txt # -r requirements/test.txt -faker==24.9.0 +faker==24.11.0 # via # -r requirements/doc.txt # -r requirements/test.txt @@ -976,7 +976,7 @@ vine==5.1.0 # amqp # celery # kombu -virtualenv==20.25.1 +virtualenv==20.25.3 # via tox wcwidth==0.2.13 # via diff --git a/requirements/doc.txt b/requirements/doc.txt index c03288db57..9f4ecbc49c 100644 --- a/requirements/doc.txt +++ b/requirements/doc.txt @@ -60,7 +60,7 @@ billiard==4.2.0 # celery bleach==6.1.0 # via -r requirements/test-master.txt -celery==5.3.6 +celery==5.4.0 # via # -c requirements/constraints.txt # -r requirements/test-master.txt @@ -245,7 +245,7 @@ factory-boy==3.3.0 # via # -c requirements/constraints.txt # -r requirements/doc.in -faker==24.9.0 +faker==24.11.0 # via factory-boy filelock==3.13.1 # via diff --git a/requirements/edx-platform-constraints.txt b/requirements/edx-platform-constraints.txt index d35dc09ade..f5c41be742 100644 --- a/requirements/edx-platform-constraints.txt +++ b/requirements/edx-platform-constraints.txt @@ -401,7 +401,7 @@ drf-yasg==1.21.5 # -c requirements/edx/../constraints.txt # django-user-tasks # edx-api-doc-tools -edx-ace==1.7.0 +edx-ace==1.8.0 # via -r requirements/edx/kernel.in edx-api-doc-tools==1.8.0 # via @@ -420,7 +420,7 @@ edx-bulk-grades==1.0.2 # via # -r requirements/edx/kernel.in # staff-graded-xblock -edx-ccx-keys==1.2.1 +edx-ccx-keys==1.3.0 # via # -r requirements/edx/kernel.in # lti-consumer-xblock @@ -431,7 +431,7 @@ edx-celeryutils==1.3.0 # super-csv edx-codejail==3.3.3 # via -r requirements/edx/kernel.in -edx-completion==4.5.0 +edx-completion==4.6.0 # via -r requirements/edx/kernel.in edx-django-release-util==1.4.0 # via @@ -469,7 +469,7 @@ edx-drf-extensions==10.2.0 # edx-when # edxval # openedx-learning -edx-enterprise==4.15.2 +edx-enterprise==4.15.3 # via # -c requirements/edx/../constraints.txt # -r requirements/edx/kernel.in @@ -766,7 +766,7 @@ openedx-django-pyfs==3.6.0 # xblock openedx-django-require==2.1.0 # via -r requirements/edx/kernel.in -openedx-django-wiki==2.0.3 +openedx-django-wiki==2.1.0 # via -r requirements/edx/kernel.in openedx-events==9.5.2 # via @@ -1201,7 +1201,7 @@ webob==1.8.7 # xblock wrapt==1.16.0 # via -r requirements/edx/paver.txt -xblock[django]==2.0.0 +xblock[django]==3.1.0 # via # -r requirements/edx/kernel.in # acid-xblock diff --git a/requirements/js_test.txt b/requirements/js_test.txt index 24c1609778..21d460dcd8 100644 --- a/requirements/js_test.txt +++ b/requirements/js_test.txt @@ -10,7 +10,7 @@ attrs==23.2.0 # trio autocommand==2.2.2 # via jaraco-text -backports-tarfile==1.0.0 +backports-tarfile==1.1.0 # via jaraco-context certifi==2024.2.2 # via selenium diff --git a/requirements/test-master.txt b/requirements/test-master.txt index 021ba539de..481948a7dc 100644 --- a/requirements/test-master.txt +++ b/requirements/test-master.txt @@ -47,7 +47,7 @@ bleach==6.1.0 # via # -c requirements/edx-platform-constraints.txt # -r requirements/base.in -celery==5.3.6 +celery==5.4.0 # via # -c requirements/constraints.txt # -r requirements/base.in diff --git a/requirements/test.txt b/requirements/test.txt index 7339904323..a22c76fd71 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -228,7 +228,7 @@ factory-boy==3.3.0 # via # -c requirements/constraints.txt # -r requirements/test.in -faker==24.9.0 +faker==24.11.0 # via factory-boy filelock==3.13.1 # via