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
12 changes: 12 additions & 0 deletions lms/envs/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -3293,3 +3293,15 @@ def _should_send_certificate_events(settings):
SSL_AUTH_DN_FORMAT_STRING = (
"/C=US/ST=Massachusetts/O=Massachusetts Institute of Technology/OU=Client CA v1/CN={0}/emailAddress={1}"
)

# .. setting_name: OPEN_EDX_FILTERS_CONFIG
# .. setting_default: {}
# .. setting_description: Configuration dict for openedx-filters pipeline steps.
# Keys are filter type strings; values are dicts with 'fail_silently' (bool) and
# 'pipeline' (list of dotted-path strings to PipelineStep subclasses).
OPEN_EDX_FILTERS_CONFIG = {
"org.openedx.learning.discount.eligibility.check.requested.v1": {
"fail_silently": True,
"pipeline": ["enterprise.filters.discounts.DiscountEligibilityStep"],
},
}
21 changes: 11 additions & 10 deletions openedx/features/discounts/applicability.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from django.utils import timezone
from django.utils.dateparse import parse_datetime
from edx_toggles.toggles import WaffleFlag
from openedx_filters.learning.filters import DiscountEligibilityCheckRequested

from common.djangoapps.course_modes.models import CourseMode
from common.djangoapps.entitlements.models import CourseEntitlement
Expand Down Expand Up @@ -124,11 +125,11 @@ def can_show_streak_discount_coupon(user, course):
if not is_mode_upsellable(user, enrollment):
return False

# We can't import this at Django load time within the openedx tests settings context
from openedx.features.enterprise_support.utils import is_enterprise_learner

# Don't give discount to enterprise users
if is_enterprise_learner(user):
# Allow plugins to mark this user as ineligible for the discount.
_user, _course_key, is_eligible = DiscountEligibilityCheckRequested.run_filter(
user=user, course_key=course.id, is_eligible=True
)
if not is_eligible:
return False

return True
Expand Down Expand Up @@ -179,11 +180,11 @@ def can_receive_discount(user, course, discount_expiration_date=None):
if CourseEntitlement.objects.filter(user=user).exists():
return False

# We can't import this at Django load time within the openedx tests settings context
from openedx.features.enterprise_support.utils import is_enterprise_learner

# Don't give discount to enterprise users
if is_enterprise_learner(user):
# Allow plugins to mark this user as ineligible for the discount.
_user, _course_key, is_eligible = DiscountEligibilityCheckRequested.run_filter(
user=user, course_key=course.id, is_eligible=True
)
if not is_eligible:
return False

# Turn holdback on
Expand Down
30 changes: 16 additions & 14 deletions openedx/features/discounts/tests/test_applicability.py
Original file line number Diff line number Diff line change
@@ -1,31 +1,29 @@
"""Tests of openedx.features.discounts.applicability"""


from datetime import datetime, timedelta
from unittest.mock import Mock, patch
from zoneinfo import ZoneInfo

import ddt
import pytest
from django.contrib.sites.models import Site
from django.utils.timezone import now
from edx_toggles.toggles.testutils import override_waffle_flag
from enterprise.models import EnterpriseCustomer, EnterpriseCustomerUser

from common.djangoapps.course_modes.models import CourseMode
from common.djangoapps.course_modes.tests.factories import CourseModeFactory
from common.djangoapps.entitlements.tests.factories import CourseEntitlementFactory
from common.djangoapps.student.tests.factories import CourseEnrollmentFactory, UserFactory
from lms.djangoapps.experiments.models import ExperimentData
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
from openedx.features.discounts.models import DiscountRestrictionConfig
from openedx.features.discounts.utils import REV1008_EXPERIMENT_ID
from xmodule.modulestore.tests.django_utils import (
ModuleStoreTestCase, # pylint: disable=wrong-import-order
)
from xmodule.modulestore.tests.factories import CourseFactory # pylint: disable=wrong-import-order
from xmodule.modulestore.tests.django_utils import \
ModuleStoreTestCase # lint-amnesty, pylint: disable=wrong-import-order
from xmodule.modulestore.tests.factories import CourseFactory # lint-amnesty, pylint: disable=wrong-import-order

from ..applicability import DISCOUNT_APPLICABILITY_FLAG, _is_in_holdback_and_bucket, can_receive_discount

Check failure on line 26 in openedx/features/discounts/tests/test_applicability.py

View workflow job for this annotation

GitHub Actions / Quality Others (ubuntu-24.04, 3.12, 20)

ruff (I001)

openedx/features/discounts/tests/test_applicability.py:4:1: I001 Import block is un-sorted or un-formatted help: Organize imports


@ddt.ddt
Expand All @@ -52,6 +50,14 @@
self.mock_holdback = holdback_patcher.start()
self.addCleanup(holdback_patcher.stop)

# By default, the filter passes eligibility through unchanged.
discount_filter_patcher = patch(
'openedx.features.discounts.applicability.DiscountEligibilityCheckRequested.run_filter',
side_effect=lambda user, course_key, is_eligible: (user, course_key, is_eligible),
)
self.mock_discount_filter = discount_filter_patcher.start()
self.addCleanup(discount_filter_patcher.stop)

def test_can_receive_discount(self):
# Right now, no one should be able to receive the discount
applicability = can_receive_discount(user=self.user, course=self.course)
Expand Down Expand Up @@ -136,17 +142,13 @@
assert applicability == (entitlement_mode is None)

@override_waffle_flag(DISCOUNT_APPLICABILITY_FLAG, active=True)
def test_can_receive_discount_false_enterprise(self):
def test_can_receive_discount_false_when_filter_marks_ineligible(self):
"""
Ensure that enterprise users do not receive the discount.
Ensure that when the eligibility filter marks the user as ineligible,
no discount is received.
"""
enterprise_customer = EnterpriseCustomer.objects.create(
name='Test EnterpriseCustomer',
site=self.site
)
EnterpriseCustomerUser.objects.create(
user_id=self.user.id,
enterprise_customer=enterprise_customer
self.mock_discount_filter.side_effect = lambda user, course_key, is_eligible: (
user, course_key, False
)

applicability = can_receive_discount(user=self.user, course=self.course)
Expand Down
Loading