check course end date and verified mode for first purchase offer
This commit is contained in:
@@ -196,7 +196,7 @@ def get_first_purchase_offer_banner_fragment(user, course):
|
|||||||
if (FIRST_PURCHASE_OFFER_BANNER_DISPLAY.is_enabled() and
|
if (FIRST_PURCHASE_OFFER_BANNER_DISPLAY.is_enabled() and
|
||||||
user and
|
user and
|
||||||
course and
|
course and
|
||||||
can_receive_discount(user=user, course_key_string=unicode(course.id))):
|
can_receive_discount(user=user, course=course)):
|
||||||
# Translator: xgettext:no-python-format
|
# Translator: xgettext:no-python-format
|
||||||
offer_message = _(u'{banner_open}{percentage}% off your first upgrade.{span_close}'
|
offer_message = _(u'{banner_open}{percentage}% off your first upgrade.{span_close}'
|
||||||
u' Discount automatically applied.{div_close}')
|
u' Discount automatically applied.{div_close}')
|
||||||
|
|||||||
@@ -2,7 +2,13 @@
|
|||||||
"""
|
"""
|
||||||
Contains code related to computing discount percentage
|
Contains code related to computing discount percentage
|
||||||
and discount applicability.
|
and discount applicability.
|
||||||
|
|
||||||
|
WARNING:
|
||||||
|
Keep in mind that the code in this file only applies to discounts controlled in the lms like the first purchase offer,
|
||||||
|
not other discounts like coupons or enterprise/program offers configured in ecommerce.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
from course_modes.models import CourseMode
|
||||||
from openedx.core.djangoapps.waffle_utils import WaffleFlag, WaffleFlagNamespace
|
from openedx.core.djangoapps.waffle_utils import WaffleFlag, WaffleFlagNamespace
|
||||||
|
|
||||||
# .. feature_toggle_name: discounts.enable_discounting
|
# .. feature_toggle_name: discounts.enable_discounting
|
||||||
@@ -23,7 +29,7 @@ DISCOUNT_APPLICABILITY_FLAG = WaffleFlag(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def can_receive_discount(user, course_key_string): # pylint: disable=unused-argument
|
def can_receive_discount(user, course): # pylint: disable=unused-argument
|
||||||
"""
|
"""
|
||||||
Check all the business logic about whether this combination of user and course
|
Check all the business logic about whether this combination of user and course
|
||||||
can receive a discount.
|
can receive a discount.
|
||||||
@@ -34,6 +40,16 @@ def can_receive_discount(user, course_key_string): # pylint: disable=unused-arg
|
|||||||
|
|
||||||
# TODO: Add additional conditions to return False here
|
# TODO: Add additional conditions to return False here
|
||||||
|
|
||||||
|
# Course end date needs to be in the future
|
||||||
|
if course.has_ended():
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Course needs to have a non-expired verified mode
|
||||||
|
modes_dict = CourseMode.modes_for_course_dict(course=course, include_expired=False)
|
||||||
|
verified_mode = modes_dict.get('verified', None)
|
||||||
|
if not verified_mode:
|
||||||
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,16 @@
|
|||||||
"""Tests of openedx.features.discounts.applicability"""
|
"""Tests of openedx.features.discounts.applicability"""
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from datetime import timedelta
|
||||||
|
from django.utils.timezone import now
|
||||||
|
|
||||||
|
from course_modes.tests.factories import CourseModeFactory
|
||||||
|
from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_flag
|
||||||
from student.tests.factories import UserFactory
|
from student.tests.factories import UserFactory
|
||||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||||
from xmodule.modulestore.tests.factories import CourseFactory
|
from xmodule.modulestore.tests.factories import CourseFactory
|
||||||
|
|
||||||
from ..applicability import can_receive_discount
|
from ..applicability import can_receive_discount, DISCOUNT_APPLICABILITY_FLAG
|
||||||
|
|
||||||
|
|
||||||
class TestApplicability(ModuleStoreTestCase):
|
class TestApplicability(ModuleStoreTestCase):
|
||||||
@@ -18,8 +23,25 @@ class TestApplicability(ModuleStoreTestCase):
|
|||||||
super(TestApplicability, self).setUp()
|
super(TestApplicability, self).setUp()
|
||||||
self.user = UserFactory.create()
|
self.user = UserFactory.create()
|
||||||
self.course = CourseFactory.create(run='test', display_name='test')
|
self.course = CourseFactory.create(run='test', display_name='test')
|
||||||
|
CourseModeFactory.create(course_id=self.course.id, mode_slug='verified')
|
||||||
|
|
||||||
def test_can_receive_discount(self):
|
def test_can_receive_discount(self):
|
||||||
# Right now, no one should be able to receive the discount
|
# Right now, no one should be able to receive the discount
|
||||||
applicability = can_receive_discount(user=self.user, course_key_string=self.course.id)
|
applicability = can_receive_discount(user=self.user, course=self.course)
|
||||||
|
self.assertEqual(applicability, False)
|
||||||
|
|
||||||
|
@override_waffle_flag(DISCOUNT_APPLICABILITY_FLAG, active=True)
|
||||||
|
def test_can_receive_discount_course_requirements(self):
|
||||||
|
"""
|
||||||
|
Ensure first purchase offer banner only displays for courses with a non-expired verified mode
|
||||||
|
"""
|
||||||
|
applicability = can_receive_discount(user=self.user, course=self.course)
|
||||||
|
self.assertEqual(applicability, True)
|
||||||
|
|
||||||
|
no_verified_mode_course = CourseFactory(end=now() + timedelta(days=30))
|
||||||
|
applicability = can_receive_discount(user=self.user, course=no_verified_mode_course)
|
||||||
|
self.assertEqual(applicability, False)
|
||||||
|
|
||||||
|
course_that_has_ended = CourseFactory(end=now() - timedelta(days=30))
|
||||||
|
applicability = can_receive_discount(user=self.user, course=course_that_has_ended)
|
||||||
self.assertEqual(applicability, False)
|
self.assertEqual(applicability, False)
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ The Discount API Views should return information about discounts that apply to t
|
|||||||
from edx_rest_framework_extensions.auth.jwt.authentication import JwtAuthentication
|
from edx_rest_framework_extensions.auth.jwt.authentication import JwtAuthentication
|
||||||
from edx_rest_framework_extensions.auth.session.authentication import SessionAuthenticationAllowInactiveUser
|
from edx_rest_framework_extensions.auth.session.authentication import SessionAuthenticationAllowInactiveUser
|
||||||
|
|
||||||
|
from opaque_keys.edx.keys import CourseKey
|
||||||
|
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
|
||||||
from openedx.core.djangoapps.cors_csrf.decorators import ensure_csrf_cookie_cross_domain
|
from openedx.core.djangoapps.cors_csrf.decorators import ensure_csrf_cookie_cross_domain
|
||||||
from openedx.core.djangoapps.oauth_dispatch.jwt import create_jwt_for_user
|
from openedx.core.djangoapps.oauth_dispatch.jwt import create_jwt_for_user
|
||||||
from openedx.core.lib.api.authentication import OAuth2AuthenticationAllowInactiveUser
|
from openedx.core.lib.api.authentication import OAuth2AuthenticationAllowInactiveUser
|
||||||
@@ -65,7 +67,9 @@ class CourseUserDiscount(DeveloperErrorViewMixin, APIView):
|
|||||||
"""
|
"""
|
||||||
Return the discount percent, if the user has appropriate permissions.
|
Return the discount percent, if the user has appropriate permissions.
|
||||||
"""
|
"""
|
||||||
discount_applicable = can_receive_discount(user=request.user, course_key_string=course_key_string)
|
course_key = CourseKey.from_string(course_key_string)
|
||||||
|
course = CourseOverview.get_from_id(course_key)
|
||||||
|
discount_applicable = can_receive_discount(user=request.user, course=course)
|
||||||
discount_percent = discount_percentage()
|
discount_percent = discount_percentage()
|
||||||
payload = {'discount_applicable': discount_applicable, 'discount_percent': discount_percent}
|
payload = {'discount_applicable': discount_applicable, 'discount_percent': discount_percent}
|
||||||
return Response({
|
return Response({
|
||||||
|
|||||||
Reference in New Issue
Block a user