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
45 changes: 45 additions & 0 deletions openedx_filters/learning/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -1445,3 +1445,48 @@ def run_filter(cls, schedules: QuerySet) -> QuerySet | None:
"""
data = super().run_pipeline(schedules=schedules)
return data.get("schedules")


class DiscountEligibilityCheckRequested(OpenEdxPublicFilter):
"""
Filter used to allow plugins to mark a user as ineligible for a course discount.

Purpose:
This filter is triggered during discount applicability checks, just before the
final eligibility decision is returned to the caller. Pipeline steps may set
``is_eligible`` to ``False`` to exclude a user from receiving a discount.

Filter Type:
org.openedx.learning.discount.eligibility.check.requested.v1

Trigger:
- Repository: openedx/edx-platform
- Path: openedx/features/discounts/applicability.py
- Function or Method: can_receive_discount, can_show_streak_discount_coupon
"""

filter_type = "org.openedx.learning.discount.eligibility.check.requested.v1"

@classmethod
def run_filter(
cls,
user: Any,
course_key: Any,
is_eligible: bool,
) -> tuple:
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make type more explicit.

"""
Process the inputs using the configured pipeline steps.

Arguments:
user (User): the Django User being checked for discount eligibility.
course_key (CourseKey or course object): identifies the course.
is_eligible (bool): the current eligibility status before plugin evaluation.

Returns:
tuple[User, CourseKey, bool]:
- User: the Django User object (unchanged).
- CourseKey: the course key (unchanged).
- bool: the (possibly overridden) eligibility flag.
"""
data = super().run_pipeline(user=user, course_key=course_key, is_eligible=is_eligible)
return data.get("user"), data.get("course_key"), data.get("is_eligible")
29 changes: 29 additions & 0 deletions openedx_filters/learning/tests/test_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
CourseRunAPIRenderStarted,
CourseUnenrollmentStarted,
DashboardRenderStarted,
DiscountEligibilityCheckRequested,
IDVPageURLRequested,
InstructorDashboardRenderStarted,
ORASubmissionViewRenderStarted,
Expand Down Expand Up @@ -801,3 +802,31 @@ def test_schedule_requested(self):
result = ScheduleQuerySetRequested.run_filter(schedules)

self.assertEqual(schedules, result)


class TestDiscountEligibilityCheckRequestedFilter(TestCase):
"""
Tests for the DiscountEligibilityCheckRequested filter.
"""

def test_filter_type(self):
self.assertEqual(
DiscountEligibilityCheckRequested.filter_type,
"org.openedx.learning.discount.eligibility.check.requested.v1",
)

def test_run_filter_returns_false_when_pipeline_sets_ineligible(self):
user = Mock()
course_key = Mock()

with patch(
"openedx_filters.tooling.OpenEdxPublicFilter.run_pipeline",
return_value={"user": user, "course_key": course_key, "is_eligible": False},
):
returned_user, returned_course_key, is_eligible = DiscountEligibilityCheckRequested.run_filter(
user=user, course_key=course_key, is_eligible=True
)

self.assertFalse(is_eligible)
self.assertIs(returned_user, user)
self.assertIs(returned_course_key, course_key)