Commit 41475d46 by Sarina Canelake

Merge pull request #6876 from Stanford-Online/giulio/course-price-upstream

Add cosmetic price field to studio & logic
parents 6fa7815f 560ce558
...@@ -183,6 +183,15 @@ class CourseFields(object): ...@@ -183,6 +183,15 @@ class CourseFields(object):
default=DEFAULT_START_DATE, default=DEFAULT_START_DATE,
scope=Scope.settings) scope=Scope.settings)
end = Date(help="Date that this class ends", 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( advertised_start = String(
display_name=_("Course Advertised Start Date"), display_name=_("Course Advertised Start Date"),
help=_( help=_(
......
...@@ -155,6 +155,7 @@ class AdvancedSettingsPage(CoursePage): ...@@ -155,6 +155,7 @@ class AdvancedSettingsPage(CoursePage):
'certificates_display_behavior', 'certificates_display_behavior',
'cohort_config', 'cohort_config',
'course_image', 'course_image',
'cosmetic_display_price',
'advertised_start', 'advertised_start',
'announcement', 'announcement',
'display_name', 'display_name',
......
...@@ -199,6 +199,24 @@ class ViewsTestCase(TestCase): ...@@ -199,6 +199,24 @@ class ViewsTestCase(TestCase):
mock_course.id = self.course_key mock_course.id = self.course_key
self.assertTrue(views.registered_for_course(mock_course, self.user)) 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): def test_jump_to_invalid(self):
# TODO add a test for invalid location # TODO add a test for invalid location
# TODO add a test for no data * # TODO add a test for no data *
......
...@@ -739,6 +739,25 @@ def registered_for_course(course, user): ...@@ -739,6 +739,25 @@ def registered_for_course(course, user):
return False 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 @ensure_csrf_cookie
@cache_if_anonymous() @cache_if_anonymous()
def course_about(request, course_id): def course_about(request, course_id):
...@@ -795,6 +814,8 @@ 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_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()) 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 # Used to provide context to message to student if enrollment not allowed
can_enroll = has_access(request.user, 'enroll', course) can_enroll = has_access(request.user, 'enroll', course)
invitation_only = course.invitation_only invitation_only = course.invitation_only
...@@ -817,8 +838,8 @@ def course_about(request, course_id): ...@@ -817,8 +838,8 @@ def course_about(request, course_id):
'studio_url': studio_url, 'studio_url': studio_url,
'registered': registered, 'registered': registered,
'course_target': course_target, 'course_target': course_target,
'registration_price': registration_price, 'is_cosmetic_price_enabled': settings.FEATURES.get('ENABLE_COSMETIC_DISPLAY_PRICE'),
'currency_symbol': settings.PAID_COURSE_REGISTRATION_CURRENCY[1], 'course_price': course_price,
'in_cart': in_cart, 'in_cart': in_cart,
'reg_then_add_to_cart_link': reg_then_add_to_cart_link, 'reg_then_add_to_cart_link': reg_then_add_to_cart_link,
'show_courseware_link': show_courseware_link, 'show_courseware_link': show_courseware_link,
......
...@@ -220,6 +220,9 @@ FEATURES = { ...@@ -220,6 +220,9 @@ FEATURES = {
# Enable flow for payments for course registration (DIFFERENT from verified student flow) # Enable flow for payments for course registration (DIFFERENT from verified student flow)
'ENABLE_PAID_COURSE_REGISTRATION': False, '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 # Automatically approve student identity verification attempts
'AUTOMATIC_VERIFY_STUDENT_IDENTITY_FOR_TESTING': False, 'AUTOMATIC_VERIFY_STUDENT_IDENTITY_FOR_TESTING': False,
......
...@@ -157,7 +157,7 @@ from edxmako.shortcuts import marketing_link ...@@ -157,7 +157,7 @@ from edxmako.shortcuts import marketing_link
## so that they can register and become a real user that can enroll. ## so that they can register and become a real user that can enroll.
% elif not is_shib_course and not can_enroll: % elif not is_shib_course and not can_enroll:
<span class="register disabled">${_("Enrollment is Closed")}</span> <span class="register disabled">${_("Enrollment is Closed")}</span>
%elif is_shopping_cart_enabled and registration_price: %elif is_shopping_cart_enabled and course_price:
<% <%
if user.is_authenticated(): if user.is_authenticated():
reg_href = "#" reg_href = "#"
...@@ -167,14 +167,13 @@ from edxmako.shortcuts import marketing_link ...@@ -167,14 +167,13 @@ from edxmako.shortcuts import marketing_link
reg_element_id = "reg_then_add_to_cart" reg_element_id = "reg_then_add_to_cart"
%> %>
<a href="${reg_href}" class="add-to-cart" id="${reg_element_id}"> <a href="${reg_href}" class="add-to-cart" id="${reg_element_id}">
${_("Add {course.display_number_with_default} to Cart ({currency_symbol}{cost})")\ ${_("Add {course_name} to Cart ({price})")\
.format(course=course, currency_symbol=settings.PAID_COURSE_REGISTRATION_CURRENCY[1], .format(course_name=course.display_number_with_default, price=course_price)}
cost=registration_price)}
</a> </a>
<div id="register_error"></div> <div id="register_error"></div>
%else: %else:
<a href="#" class="register"> <a href="#" class="register">
${_("Register for {course.display_number_with_default}").format(course=course) | h} ${_("Register for {course_name}").format(course_name=course.display_number_with_default) | h}
</a> </a>
<div id="register_error"></div> <div id="register_error"></div>
%endif %endif
...@@ -311,13 +310,13 @@ from edxmako.shortcuts import marketing_link ...@@ -311,13 +310,13 @@ from edxmako.shortcuts import marketing_link
##<li class="important-dates-item"><i class="icon fa fa-clock-o"></i><p class="important-dates-item-title">${_('Course Length')}</p><span class="important-dates-item-text course-length">${_('{number} weeks').format(number=15)}</span></li> ##<li class="important-dates-item"><i class="icon fa fa-clock-o"></i><p class="important-dates-item-title">${_('Course Length')}</p><span class="important-dates-item-text course-length">${_('{number} weeks').format(number=15)}</span></li>
%if is_shopping_cart_enabled and registration_price: %if course_price and (is_shopping_cart_enabled or is_cosmetic_price_enabled):
<li class="important-dates-item"> <li class="important-dates-item">
<i class="icon fa fa-money"></i> <i class="icon fa fa-money"></i>
<p class="important-dates-item-title">${_("Price")}</p> <p class="important-dates-item-title">${_("Price")}</p>
<span class="important-dates-item-text">${_("{currency_symbol}{cost}").format(currency_symbol=currency_symbol, cost=registration_price)}</span> <span class="important-dates-item-text">${course_price}</span>
</li> </li>
% endif %endif
% if pre_requisite_courses: % if pre_requisite_courses:
<% prc_target = reverse('about_course', args=[unicode(pre_requisite_courses[0]['key'])]) %> <% prc_target = reverse('about_course', args=[unicode(pre_requisite_courses[0]['key'])]) %>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment