diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 75e44224..40b5006b 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -34,6 +34,18 @@ Unreleased .. scriv-insert-here +.. _changelog-3.13.0: + +[3.13.0] - 2026-09-11 +---------------------- + +Changed +~~~~~~~ + +* Changed ``SupportEnrollmentDataRequested`` to accept/return the full enrollments list instead of + an empty placeholder dict keyed by course_id, so pipeline steps can augment each enrollment + record in place rather than being limited to bolting on a single hard-coded key + .. _changelog-3.12.0: [3.12.0] - 2026-09-08 diff --git a/openedx_filters/__init__.py b/openedx_filters/__init__.py index aa5338ff..f5647791 100644 --- a/openedx_filters/__init__.py +++ b/openedx_filters/__init__.py @@ -6,7 +6,7 @@ from openedx_filters.filters import * -__version__ = "3.12.0" +__version__ = "3.13.0" if sys.version_info < (3, 12): # pragma: no cover warnings.warn( diff --git a/openedx_filters/learning/filters.py b/openedx_filters/learning/filters.py index 78f0d2e7..6848e72f 100644 --- a/openedx_filters/learning/filters.py +++ b/openedx_filters/learning/filters.py @@ -1979,7 +1979,8 @@ class SupportEnrollmentDataRequested(OpenEdxPublicFilter): Purpose: This filter is triggered when the support enrollment view fetches enrollment data for - a user. Pipeline steps can inject additional enrollment records or augment existing ones. + a user. Pipeline steps can augment each enrollment record in the list in place — e.g. + attach additional course-specific data — before the enrollment list is returned. Filter Type: org.openedx.learning.support.enrollment.data.requested.v1 @@ -1993,18 +1994,46 @@ class SupportEnrollmentDataRequested(OpenEdxPublicFilter): filter_type = "org.openedx.learning.support.enrollment.data.requested.v1" @classmethod - def run_filter(cls, enrollment_data: dict, user: Any) -> tuple[dict, Any]: + def run_filter(cls, enrollments_data: list[dict], user: Any) -> tuple[list[dict], Any]: """ - Process the enrollment data dict through the configured pipeline steps. + Process the enrollments list through the configured pipeline steps. Arguments: - enrollment_data (dict): dict mapping course_id to list of enrollment records. + enrollments_data (list[dict]): list of enrollment record dicts, one per course the + user is enrolled in, e.g.: + + [ + { + "course_id": "course-v1:edX+DemoX+Demo_Course", + "mode": "audit", + "is_active": True, + "user": "staff", + "course_start": "2024-01-01T00:00:00Z", + "course_end": "2024-06-01T00:00:00Z", + "enrollment_start": "2023-12-01T00:00:00Z", + "enrollment_end": "2024-01-15T00:00:00Z", + "course_modes": [{"slug": "audit", "name": "Audit", ...}], + "verified_price": 149, + "verified_upgrade_deadline": "2024-01-08T00:00:00Z", + "verification_deadline": None, + "order_number": "", + "source_system": "", + "manual_enrollment": {}, + }, + ... + ] + + Built from openedx.core.djangoapps.enrollments.api.get_enrollments and then + augmented by EnrollmentSupportListView.get (see Trigger above) before this + filter runs. See + https://github.com/openedx/edx-platform/blob/master/lms/djangoapps/support/views/enrollments.py + for the authoritative, up-to-date shape. user (User): the user whose enrollment data is being fetched. Returns: - tuple[dict, Any]: - - dict: the (possibly enriched) enrollment data dict. + tuple[list[dict], Any]: + - list[dict]: the (possibly augmented) enrollments list. - Any: the Django User object (unchanged). """ - data = super().run_pipeline(enrollment_data=enrollment_data, user=user) - return data["enrollment_data"], data["user"] + data = super().run_pipeline(enrollments_data=enrollments_data, user=user) + return data["enrollments_data"], data["user"] diff --git a/openedx_filters/learning/tests/test_filters.py b/openedx_filters/learning/tests/test_filters.py index 93cc1bf9..e0f6eca6 100644 --- a/openedx_filters/learning/tests/test_filters.py +++ b/openedx_filters/learning/tests/test_filters.py @@ -1217,31 +1217,33 @@ def test_filter_type(self): == "org.openedx.learning.support.enrollment.data.requested.v1" ) - def test_run_filter_returns_enrollment_data_unchanged_when_no_pipeline(self): + def test_run_filter_returns_enrollments_unchanged_when_no_pipeline(self): """ - With no pipeline steps configured, the enrollment_data dict and user are returned unchanged. + With no pipeline steps configured, the enrollments list and user are returned unchanged. """ - enrollment_data = {} + enrollments_data = [{"course_id": "some-id"}] user = Mock() - result = SupportEnrollmentDataRequested.run_filter(enrollment_data=enrollment_data, user=user) + result = SupportEnrollmentDataRequested.run_filter(enrollments_data=enrollments_data, user=user) - assert result == (enrollment_data, user) + assert result == (enrollments_data, user) @patch( "openedx_filters.tooling.OpenEdxPublicFilter.run_pipeline", return_value={ - "enrollment_data": {"course-v1:edX+DemoX+Demo_Course": [{"course_id": "some-id"}]}, + "enrollments_data": [{"course_id": "some-id", "enterprise_course_enrollments": []}], "user": Mock(), }, ) - def test_run_filter_returns_enrollment_data_from_pipeline(self, mock_run_pipeline): + def test_run_filter_returns_enrollments_from_pipeline(self, mock_run_pipeline): """ - The (possibly enriched) enrollment_data dict returned by the pipeline is passed through. + The (possibly augmented) enrollments list returned by the pipeline is passed through. """ - result = SupportEnrollmentDataRequested.run_filter(enrollment_data={}, user=Mock()) + result = SupportEnrollmentDataRequested.run_filter( + enrollments_data=[{"course_id": "some-id"}], user=Mock() + ) assert result == ( - {"course-v1:edX+DemoX+Demo_Course": [{"course_id": "some-id"}]}, + mock_run_pipeline.return_value["enrollments_data"], mock_run_pipeline.return_value["user"], )