Skip to content
Draft
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
3 changes: 3 additions & 0 deletions enterprise/filters/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"""
Filter pipeline step implementations for edx-enterprise openedx-filters integrations.
"""
39 changes: 39 additions & 0 deletions enterprise/filters/grades.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"""
Pipeline step for enriching grade analytics event context.
"""
from openedx_filters.filters import PipelineStep

from enterprise.models import EnterpriseCourseEnrollment


class GradeEventContextEnricher(PipelineStep):
"""
Enriches a grade analytics event context dict with the learner's enterprise UUID.

This step is intended to be registered as a pipeline step for the
``org.openedx.learning.grade.context.requested.v1`` filter.

If the user is enrolled in the given course through an enterprise, the enterprise
UUID is added to the context under the key ``"enterprise_uuid"``. If the user has
no enterprise course enrollment, the context is returned unchanged.
"""

def run_filter(self, context, user_id, course_id): # pylint: disable=arguments-differ
"""
Add enterprise UUID to the event context if the user has an enterprise enrollment.

Arguments:
context (dict): the event tracking context dict.
user_id (int): the ID of the user whose grade event is being emitted.
course_id (str or CourseKey): the course key for the grade event.

Returns:
dict: updated pipeline data with the enriched ``context`` dict.
"""
uuids = EnterpriseCourseEnrollment.get_enterprise_uuids_with_user_and_course(
str(user_id),
str(course_id),
)
if uuids:
return {"context": {**context, "enterprise_uuid": str(uuids[0])}}
return {"context": context}
1 change: 1 addition & 0 deletions requirements/base.in
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ jsondiff
jsonfield
openedx-atlas
openedx-events
openedx-filters
paramiko
path.py
pillow
Expand Down
2 changes: 2 additions & 0 deletions requirements/test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,8 @@ openedx-atlas==0.7.0
# via -r requirements/test-master.txt
openedx-events==10.5.0
# via -r requirements/test-master.txt
openedx-filters==2.1.0
# via -r requirements/base.in
packaging==25.0
# via
# -r requirements/test-master.txt
Expand Down
1 change: 1 addition & 0 deletions tests/filters/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Tests for enterprise filter pipeline steps."""
74 changes: 74 additions & 0 deletions tests/filters/test_grades.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
"""
Tests for enterprise.filters.grades pipeline step.
"""
import uuid
from unittest.mock import patch

from django.test import TestCase

from enterprise.filters.grades import GradeEventContextEnricher


class TestGradeEventContextEnricher(TestCase):
"""
Tests for GradeEventContextEnricher pipeline step.
"""

def _make_step(self):
return GradeEventContextEnricher(
"org.openedx.learning.grade.context.requested.v1",
[],
)

@patch(
"enterprise.filters.grades.EnterpriseCourseEnrollment"
".get_enterprise_uuids_with_user_and_course"
)
def test_enriches_context_when_enterprise_enrollment_found(self, mock_get_uuids):
"""
When an enterprise course enrollment exists, enterprise_uuid is added to context.
"""
enterprise_uuid = uuid.uuid4()
mock_get_uuids.return_value = [enterprise_uuid]

step = self._make_step()
context = {"org": "TestOrg", "course_id": "course-v1:org+course+run"}
result = step.run_filter(context=context, user_id=7, course_id="course-v1:org+course+run")

assert result == {"context": {**context, "enterprise_uuid": str(enterprise_uuid)}}
mock_get_uuids.assert_called_once_with("7", "course-v1:org+course+run")

@patch(
"enterprise.filters.grades.EnterpriseCourseEnrollment"
".get_enterprise_uuids_with_user_and_course"
)
def test_returns_unchanged_context_when_no_enterprise_enrollment(self, mock_get_uuids):
"""
When no enterprise course enrollment exists, context is returned unchanged.
"""
mock_get_uuids.return_value = []

step = self._make_step()
context = {"org": "TestOrg"}
result = step.run_filter(context=context, user_id=99, course_id="course-v1:org+course+run")

assert result == {"context": context}
assert "enterprise_uuid" not in result["context"]

@patch(
"enterprise.filters.grades.EnterpriseCourseEnrollment"
".get_enterprise_uuids_with_user_and_course"
)
def test_uses_first_uuid_when_multiple_enrollments(self, mock_get_uuids):
"""
When multiple enterprise enrollments exist, only the first UUID is used.
"""
first_uuid = uuid.uuid4()
second_uuid = uuid.uuid4()
mock_get_uuids.return_value = [first_uuid, second_uuid]

step = self._make_step()
context = {}
result = step.run_filter(context=context, user_id=1, course_id="course-v1:x+y+z")

assert result["context"]["enterprise_uuid"] == str(first_uuid)