diff --git a/common/lib/xmodule/xmodule/course_module.py b/common/lib/xmodule/xmodule/course_module.py index 0c10e1ad0a..cb91fe4b6b 100644 --- a/common/lib/xmodule/xmodule/course_module.py +++ b/common/lib/xmodule/xmodule/course_module.py @@ -183,6 +183,15 @@ class CourseFields(object): default=DEFAULT_START_DATE, scope=Scope.settings) end = Date(help="Date that this class ends", scope=Scope.settings) + cosmetic_display_price = Integer( + display_name=_("Cosmetic Course Display Price"), + help=_( + "The cost displayed to students for enrolling in the course. If a paid course registration price is " + "set by an administrator in the database, that price will be displayed instead of this one." + ), + default=0, + scope=Scope.settings, + ) advertised_start = String( display_name=_("Course Advertised Start Date"), help=_( diff --git a/lms/djangoapps/courseware/tests/test_views.py b/lms/djangoapps/courseware/tests/test_views.py index 419e8acaf2..0eaec7a384 100644 --- a/lms/djangoapps/courseware/tests/test_views.py +++ b/lms/djangoapps/courseware/tests/test_views.py @@ -199,6 +199,24 @@ class ViewsTestCase(TestCase): mock_course.id = self.course_key self.assertTrue(views.registered_for_course(mock_course, self.user)) + @override_settings(PAID_COURSE_REGISTRATION_CURRENCY=["USD", "$"]) + def test_get_cosmetic_display_price(self): + """ + Check that get_cosmetic_display_price() returns the correct price given its inputs. + """ + registration_price = 99 + self.course.cosmetic_display_price = 10 + # Since registration_price is set, it overrides the cosmetic_display_price and should be returned + self.assertEqual(views.get_cosmetic_display_price(self.course, registration_price), "$99") + + registration_price = 0 + # Since registration_price is not set, cosmetic_display_price should be returned + self.assertEqual(views.get_cosmetic_display_price(self.course, registration_price), "$10") + + self.course.cosmetic_display_price = 0 + # Since both prices are not set, there is no price, thus "Free" + self.assertEqual(views.get_cosmetic_display_price(self.course, registration_price), "Free") + def test_jump_to_invalid(self): # TODO add a test for invalid location # TODO add a test for no data * diff --git a/lms/djangoapps/courseware/views.py b/lms/djangoapps/courseware/views.py index e6c871733e..3858d5a111 100644 --- a/lms/djangoapps/courseware/views.py +++ b/lms/djangoapps/courseware/views.py @@ -739,6 +739,25 @@ def registered_for_course(course, user): return False +def get_cosmetic_display_price(course, registration_price): + """ + Return Course Price as a string preceded by correct currency, or 'Free' + """ + currency_symbol = settings.PAID_COURSE_REGISTRATION_CURRENCY[1] + + price = course.cosmetic_display_price + if registration_price > 0: + price = registration_price + + if price: + # Translators: This will look like '$50', where {currency_symbol} is a symbol such as '$' and {price} is a + # numerical amount in that currency. Adjust this display as needed for your language. + return _("{currency_symbol}{price}").format(currency_symbol=currency_symbol, price=price) + else: + # Translators: This refers to the cost of the course. In this case, the course costs nothing so it is free. + return _('Free') + + @ensure_csrf_cookie @cache_if_anonymous() def course_about(request, course_id): @@ -795,6 +814,8 @@ def course_about(request, course_id): reg_then_add_to_cart_link = "{reg_url}?course_id={course_id}&enrollment_action=add_to_cart".format( reg_url=reverse('register_user'), course_id=course.id.to_deprecated_string()) + course_price = get_cosmetic_display_price(course, registration_price) + # Used to provide context to message to student if enrollment not allowed can_enroll = has_access(request.user, 'enroll', course) invitation_only = course.invitation_only @@ -817,8 +838,8 @@ def course_about(request, course_id): 'studio_url': studio_url, 'registered': registered, 'course_target': course_target, - 'registration_price': registration_price, - 'currency_symbol': settings.PAID_COURSE_REGISTRATION_CURRENCY[1], + 'is_cosmetic_price_enabled': settings.FEATURES.get('ENABLE_COSMETIC_DISPLAY_PRICE'), + 'course_price': course_price, 'in_cart': in_cart, 'reg_then_add_to_cart_link': reg_then_add_to_cart_link, 'show_courseware_link': show_courseware_link, diff --git a/lms/envs/common.py b/lms/envs/common.py index f609758535..1e5b45f62c 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -220,6 +220,9 @@ FEATURES = { # Enable flow for payments for course registration (DIFFERENT from verified student flow) 'ENABLE_PAID_COURSE_REGISTRATION': False, + # Enable the display of cosmetic course price display (set in course advanced settings) + 'ENABLE_COSMETIC_DISPLAY_PRICE': False, + # Automatically approve student identity verification attempts 'AUTOMATIC_VERIFY_STUDENT_IDENTITY_FOR_TESTING': False, diff --git a/lms/templates/courseware/course_about.html b/lms/templates/courseware/course_about.html index c337544576..0b3e58e239 100644 --- a/lms/templates/courseware/course_about.html +++ b/lms/templates/courseware/course_about.html @@ -157,7 +157,7 @@ from edxmako.shortcuts import marketing_link ## so that they can register and become a real user that can enroll. % elif not is_shib_course and not can_enroll: ${_("Enrollment is Closed")} - %elif is_shopping_cart_enabled and registration_price: + %elif is_shopping_cart_enabled and course_price: <% if user.is_authenticated(): reg_href = "#" @@ -167,14 +167,13 @@ from edxmako.shortcuts import marketing_link reg_element_id = "reg_then_add_to_cart" %> - ${_("Add {course.display_number_with_default} to Cart ({currency_symbol}{cost})")\ - .format(course=course, currency_symbol=settings.PAID_COURSE_REGISTRATION_CURRENCY[1], - cost=registration_price)} + ${_("Add {course_name} to Cart ({price})")\ + .format(course_name=course.display_number_with_default, price=course_price)}
%else: - ${_("Register for {course.display_number_with_default}").format(course=course) | h} + ${_("Register for {course_name}").format(course_name=course.display_number_with_default) | h}
%endif @@ -311,13 +310,13 @@ from edxmako.shortcuts import marketing_link ##
  • ${_('Course Length')}

    ${_('{number} weeks').format(number=15)}
  • - %if is_shopping_cart_enabled and registration_price: + %if course_price and (is_shopping_cart_enabled or is_cosmetic_price_enabled):
  • ${_("Price")}

    - ${_("{currency_symbol}{cost}").format(currency_symbol=currency_symbol, cost=registration_price)} + ${course_price}
  • - % endif + %endif % if pre_requisite_courses: