From abd843c5203ed139421b49e3bece340b1b88f251 Mon Sep 17 00:00:00 2001 From: Hamzah Ullah Date: Tue, 8 Sep 2026 12:13:02 -0400 Subject: [PATCH] feat: replace enterprise support enrollment imports with filter call ENT-11574 Removes the direct openedx.features.enterprise_support imports and the _enterprise_course_enrollments_by_course_id helper from EnrollmentSupportListView, replacing them with a call to the new SupportEnrollmentDataRequested openedx-filter. Per pwnage101's review feedback on the sibling SupportContactContextRequested filter, run_filter now returns a tuple of all its inputs (enrollment_data, user) rather than a bare dict, matching the convention used by every other filter. No settings changes here: OPEN_EDX_FILTERS_CONFIG registration for the pipeline step lives in edx-enterprise's own plugin_settings() (enterprise/settings/common.py), per the ENT-11830 ownership handoff. The test now mocks the filter call at the view layer; the enterprise-specific pipeline step behavior is covered by edx-enterprise's own test suite. --- lms/djangoapps/support/tests/test_views.py | 71 +++++++-------------- lms/djangoapps/support/views/enrollments.py | 49 +++----------- 2 files changed, 32 insertions(+), 88 deletions(-) diff --git a/lms/djangoapps/support/tests/test_views.py b/lms/djangoapps/support/tests/test_views.py index 7e2e04ea1f68..62f34c8f1833 100644 --- a/lms/djangoapps/support/tests/test_views.py +++ b/lms/djangoapps/support/tests/test_views.py @@ -60,11 +60,6 @@ from openedx.core.djangoapps.oauth_dispatch.tests import factories from openedx.features.content_type_gating.models import ContentTypeGatingConfig from openedx.features.course_duration_limits.models import CourseDurationLimitConfig -from openedx.features.enterprise_support.api import enterprise_is_enabled -from openedx.features.enterprise_support.tests.factories import ( - EnterpriseCourseEnrollmentFactory, - EnterpriseCustomerUserFactory, -) from xmodule.modulestore.tests.django_utils import ( TEST_DATA_SPLIT_MODULESTORE, ModuleStoreTestCase, @@ -72,11 +67,6 @@ ) from xmodule.modulestore.tests.factories import CourseFactory -try: - from consent.models import DataSharingConsent -except ImportError: # pragma: no cover - pass - class SupportViewTestCase(ModuleStoreTestCase): """ @@ -359,7 +349,7 @@ def test_get_enrollments(self, search_string_type): ) assert {CourseMode.VERIFIED, CourseMode.AUDIT, CourseMode.HONOR, CourseMode.NO_ID_PROFESSIONAL_MODE, CourseMode.PROFESSIONAL, CourseMode.CREDIT_MODE} == {mode['slug'] for mode in data[0]['course_modes']} - assert 'enterprise_course_enrollments' not in data[0] + assert data[0]['enterprise_course_enrollments'] == [] assert data[0]['order_number'] == '' assert data[0]['source_system'] == '' @@ -400,52 +390,39 @@ def test_order_source_system_information(self): assert len(data) == 1 assert data[0]['source_system'] == 'commercetools' - @override_settings(ENABLE_ENTERPRISE_INTEGRATION=True) - @enterprise_is_enabled() - def test_get_enrollments_enterprise_enabled(self): + @patch('lms.djangoapps.support.views.enrollments.SupportEnrollmentDataRequested.run_filter') + def test_get_enrollments_with_enterprise_filter(self, mock_run_filter): + """ + Enterprise enrollment data returned by the SupportEnrollmentDataRequested filter + is threaded into each enrollment's 'enterprise_course_enrollments' key. + + The behavior of the filter's pipeline step (edx-enterprise's + SupportEnterpriseEnrollmentDataInjector) is covered by edx-enterprise's own test suite. + This view only needs to verify it wires the filter's return value through correctly. + """ + course_id = str(self.course.id) + mock_enterprise_enrollment = { + 'course_id': course_id, + 'enterprise_customer_name': 'Test Enterprise', + 'enterprise_customer_user_id': 42, + 'license': None, + 'saved_for_later': False, + 'data_sharing_consent': {'consent_provided': True}, + } + mock_run_filter.return_value = ({course_id: [mock_enterprise_enrollment]}, self.student) + url = reverse( 'support:enrollment_list', kwargs={'username_or_email': self.student.username} ) - - enterprise_customer_user = EnterpriseCustomerUserFactory( - user_id=self.student.id - ) - enterprise_course_enrollment = EnterpriseCourseEnrollmentFactory( - course_id=self.course.id, - enterprise_customer_user=enterprise_customer_user - ) - data_sharing_consent = DataSharingConsent( - course_id=self.course.id, - enterprise_customer=enterprise_customer_user.enterprise_customer, - username=self.student.username, - granted=True - ) - data_sharing_consent.save() - response = self.client.get(url) assert response.status_code == 200 data = json.loads(response.content.decode('utf-8')) assert len(data) == 1 + mock_run_filter.assert_called_once_with(enrollment_data={}, user=self.student) enterprise_course_enrollments_data = data[0]['enterprise_course_enrollments'] - assert len(enterprise_course_enrollments_data) == 1 - expected = { - 'course_id': str(enterprise_course_enrollment.course_id), - 'enterprise_customer_name': enterprise_customer_user.enterprise_customer.name, - 'enterprise_customer_user_id': enterprise_customer_user.id, - 'license': None, - 'saved_for_later': enterprise_course_enrollment.saved_for_later, - 'data_sharing_consent': { - 'username': self.student.username, - 'enterprise_customer_uuid': str(enterprise_customer_user.enterprise_customer_id), - 'exists': data_sharing_consent.exists, - 'consent_provided': data_sharing_consent.granted, - 'consent_required': data_sharing_consent.consent_required(), - 'course_id': str(enterprise_course_enrollment.course_id), - } - } - assert enterprise_course_enrollments_data[0] == expected + assert enterprise_course_enrollments_data == [mock_enterprise_enrollment] @ddt.data( (True, 'Self Paced'), diff --git a/lms/djangoapps/support/views/enrollments.py b/lms/djangoapps/support/views/enrollments.py index d2fde62ca3a7..2353f6550fcf 100644 --- a/lms/djangoapps/support/views/enrollments.py +++ b/lms/djangoapps/support/views/enrollments.py @@ -2,7 +2,6 @@ Support tool for changing course enrollments. """ import logging -from collections import defaultdict import markupsafe from django.contrib.auth.models import User # pylint: disable=imported-auth-user @@ -14,6 +13,7 @@ from django.views.generic import View from opaque_keys import InvalidKeyError from opaque_keys.edx.keys import CourseKey +from openedx_filters.learning.filters import SupportEnrollmentDataRequested from rest_framework.generics import GenericAPIView from common.djangoapps.course_modes.models import CourseMode @@ -34,12 +34,6 @@ from openedx.core.djangoapps.enrollments.api import get_enrollment_attributes, get_enrollments, update_enrollment from openedx.core.djangoapps.enrollments.errors import CourseModeNotFoundError from openedx.core.djangoapps.enrollments.serializers import ModeSerializer -from openedx.features.enterprise_support.api import ( - enterprise_enabled, - get_data_sharing_consents, - get_enterprise_course_enrollments, -) -from openedx.features.enterprise_support.serializers import EnterpriseCourseEnrollmentSerializer logger = logging.getLogger(__name__) @@ -70,35 +64,6 @@ class EnrollmentSupportListView(GenericAPIView): # does not specify a serializer class. exclude_from_schema = True - def _enterprise_course_enrollments_by_course_id(self, user): - """ - Returns a dict containing enterprise course enrollments data with - course ids as keys. - """ - enterprise_course_enrollments = get_enterprise_course_enrollments(user) - data_sharing_consents_for_user = get_data_sharing_consents(user) - - enterprise_enrollments_by_course_id = defaultdict(list) - consent_by_course_and_enterprise_customer_id = {} - - # Get data sharing consent for each enterprise enrollment - for consent in data_sharing_consents_for_user: - key = f'{consent.course_id}-{consent.enterprise_customer_id}' - consent_by_course_and_enterprise_customer_id[key] = consent.serialize() - - for enterprise_course_enrollment in enterprise_course_enrollments: - serialized_enterprise_course_enrollment = EnterpriseCourseEnrollmentSerializer( - enterprise_course_enrollment - ).data - course_id = enterprise_course_enrollment.course_id - enterprise_customer_id = enterprise_course_enrollment.enterprise_customer_user.enterprise_customer_id - key = f'{course_id}-{enterprise_customer_id}' - consent = consent_by_course_and_enterprise_customer_id.get(key) - serialized_enterprise_course_enrollment['data_sharing_consent'] = consent - enterprise_enrollments_by_course_id[course_id].append(serialized_enterprise_course_enrollment) - - return enterprise_enrollments_by_course_id - @method_decorator(require_support_permission) def get(self, request, username_or_email): """ @@ -126,11 +91,13 @@ def get(self, request, username_or_email): # Add manual enrollment history, if it exists enrollment['manual_enrollment'] = self.manual_enrollment_data(enrollment, course_key) - if enterprise_enabled(): - enterprise_enrollments_by_course_id = self._enterprise_course_enrollments_by_course_id(user) - for enrollment in enrollments: - enterprise_course_enrollments = enterprise_enrollments_by_course_id.get(enrollment['course_id'], []) - enrollment['enterprise_course_enrollments'] = enterprise_course_enrollments + enterprise_enrollments_by_course_id, _ = SupportEnrollmentDataRequested.run_filter( + enrollment_data={}, user=user + ) + for enrollment in enrollments: + enrollment['enterprise_course_enrollments'] = enterprise_enrollments_by_course_id.get( + enrollment['course_id'], [] + ) return JsonResponse(enrollments)