From 509c2fde9b05251a9ef9a4634aaeb53c295805fd Mon Sep 17 00:00:00 2001 From: Troy Sankey Date: Tue, 16 Apr 2024 15:47:49 -0700 Subject: [PATCH] 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')