+ % if offer_banner_fragment:
+ ${HTML(offer_banner_fragment.content)}
+ % endif
% if course_expiration_fragment:
${HTML(course_expiration_fragment.content)}
% endif
diff --git a/openedx/features/course_experience/tests/views/test_course_home.py b/openedx/features/course_experience/tests/views/test_course_home.py
index 3b179f894c..639b6756de 100644
--- a/openedx/features/course_experience/tests/views/test_course_home.py
+++ b/openedx/features/course_experience/tests/views/test_course_home.py
@@ -21,6 +21,7 @@ from waffle.testutils import override_flag
from course_modes.models import CourseMode
from course_modes.tests.factories import CourseModeFactory
from courseware.tests.helpers import get_expiration_banner_text
+
from django_comment_client.tests.factories import RoleFactory
from django_comment_common.models import (
FORUM_ROLE_ADMINISTRATOR,
@@ -48,6 +49,7 @@ from openedx.features.course_duration_limits.config import EXPERIMENT_DATA_HOLDB
from openedx.features.course_duration_limits.models import CourseDurationLimitConfig
from openedx.features.course_experience import (
COURSE_ENABLE_UNENROLLED_ACCESS_FLAG,
+ FIRST_PURCHASE_OFFER_BANNER_DISPLAY,
SHOW_REVIEWS_TOOL_FLAG,
SHOW_UPGRADE_MSG_ON_COURSE_HOME,
UNIFIED_COURSE_TAB_FLAG
@@ -409,6 +411,19 @@ class TestCourseHomePageAccess(CourseHomePageTestCase):
)
self.assertRedirects(response, expected_url)
+ @override_waffle_flag(FIRST_PURCHASE_OFFER_BANNER_DISPLAY, active=True)
+ def test_first_purchase_offer_banner(self):
+ """
+ Ensure first purchase offer banner displays correctly
+ """
+ user = self.create_user_for_course(self.course, CourseUserType.ENROLLED)
+ self.client.login(username=user.username, password=self.TEST_PASSWORD)
+ url = course_home_url(self.course)
+ response = self.client.get(url)
+ bannerText = u'''
+ 15% off your first upgrade. Discount automatically applied.
'''
+ self.assertContains(response, bannerText, html=True)
+
@mock.patch.dict(settings.FEATURES, {'DISABLE_START_DATES': False})
def test_course_does_not_expire_for_verified_user(self):
"""
diff --git a/openedx/features/course_experience/utils.py b/openedx/features/course_experience/utils.py
index 3637b4731b..f52a6479d1 100644
--- a/openedx/features/course_experience/utils.py
+++ b/openedx/features/course_experience/utils.py
@@ -2,11 +2,15 @@
Common utilities for the course experience, including course outline.
"""
from completion.models import BlockCompletion
+from django.utils.translation import ugettext as _
from lms.djangoapps.course_api.blocks.api import get_blocks
from lms.djangoapps.course_blocks.utils import get_student_module_as_dict
from opaque_keys.edx.keys import CourseKey
+from openedx.core.djangolib.markup import HTML
from openedx.core.lib.cache_utils import request_cached
+from openedx.features.course_experience import FIRST_PURCHASE_OFFER_BANNER_DISPLAY
+from web_fragments.fragment import Fragment
from xmodule.modulestore.django import modulestore
@@ -182,3 +186,17 @@ def get_resume_block(block):
if resume_block:
return resume_block
return block
+
+
+def get_first_purchase_offer_banner_fragment(user, course):
+ if FIRST_PURCHASE_OFFER_BANNER_DISPLAY.is_enabled() and user and course:
+ # Translator: xgettext:no-python-format
+ offer_message = _(u'{banner_open}15% off your first upgrade.{span_close}'
+ u' Discount automatically applied.{div_close}')
+ return Fragment(HTML(offer_message).format(
+ banner_open=HTML(
+ '
'
+ ),
+ span_close=HTML(''),
+ div_close=HTML('
')
+ ))
diff --git a/openedx/features/course_experience/views/course_home.py b/openedx/features/course_experience/views/course_home.py
index e740fd8cc5..8b4796ed90 100644
--- a/openedx/features/course_experience/views/course_home.py
+++ b/openedx/features/course_experience/views/course_home.py
@@ -31,6 +31,7 @@ from openedx.core.djangoapps.plugin_api.views import EdxFragmentView
from openedx.core.djangoapps.util.maintenance_banner import add_maintenance_banner
from openedx.features.course_duration_limits.access import generate_course_expired_fragment
from openedx.features.course_experience.course_tools import CourseToolsPluginManager
+from openedx.features.course_experience.utils import get_first_purchase_offer_banner_fragment
from student.models import CourseEnrollment
from util.views import ensure_valid_course_key
from xmodule.course_module import COURSE_VISIBILITY_PUBLIC, COURSE_VISIBILITY_PUBLIC_OUTLINE
@@ -139,6 +140,7 @@ class CourseHomeFragmentView(EdxFragmentView):
outline_fragment = None
update_message_fragment = None
course_sock_fragment = None
+ offer_banner_fragment = None
course_expiration_fragment = None
has_visited_course = None
resume_course_url = None
@@ -159,9 +161,14 @@ class CourseHomeFragmentView(EdxFragmentView):
course_sock_fragment = CourseSockFragmentView().render_to_fragment(request, course=course, **kwargs)
has_visited_course, resume_course_url = self._get_resume_course_info(request, course_id)
handouts_html = self._get_course_handouts(request, course)
+ course_overview = CourseOverview.get_from_id(course.id)
+ offer_banner_fragment = get_first_purchase_offer_banner_fragment(
+ request.user,
+ course_overview
+ )
course_expiration_fragment = generate_course_expired_fragment(
request.user,
- CourseOverview.get_from_id(course.id)
+ course_overview
)
elif allow_public_outline or allow_public:
outline_fragment = CourseOutlineFragmentView().render_to_fragment(
@@ -212,6 +219,7 @@ class CourseHomeFragmentView(EdxFragmentView):
'outline_fragment': outline_fragment,
'handouts_html': handouts_html,
'course_home_message_fragment': course_home_message_fragment,
+ 'offer_banner_fragment': offer_banner_fragment,
'course_expiration_fragment': course_expiration_fragment,
'has_visited_course': has_visited_course,
'resume_course_url': resume_course_url,