Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion openedx_filters/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
45 changes: 37 additions & 8 deletions openedx_filters/learning/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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]:
Comment thread
pwnage101 marked this conversation as resolved.
"""
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"]
22 changes: 12 additions & 10 deletions openedx_filters/learning/tests/test_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"],
)