REVEM-203 Add course and program info to dashboard metadata
This commit is contained in:
@@ -22,7 +22,7 @@ from six import text_type, iteritems
|
||||
|
||||
import track.views
|
||||
from bulk_email.models import BulkEmailFlag, Optout # pylint: disable=import-error
|
||||
from course_modes.models import CourseMode, get_cosmetic_display_price
|
||||
from course_modes.models import CourseMode
|
||||
from courseware.access import has_access
|
||||
from edxmako.shortcuts import render_to_response, render_to_string
|
||||
from entitlements.models import CourseEntitlement
|
||||
@@ -42,7 +42,7 @@ from openedx.core.djangoapps.waffle_utils import WaffleFlag, WaffleFlagNamespace
|
||||
from openedx.core.djangoapps.user_api.accounts.utils import is_secondary_email_feature_enabled_for_user
|
||||
from openedx.core.djangolib.markup import HTML, Text
|
||||
from openedx.features.enterprise_support.api import get_dashboard_consent_notification
|
||||
from lms.djangoapps.experiments.utils import get_experiment_dashboard_metadata_context
|
||||
from lms.djangoapps.experiments.utils import get_experiment_dashboard_metadata_context, get_dashboard_course_info
|
||||
from openedx.features.journals.api import journals_enabled
|
||||
from shoppingcart.api import order_history
|
||||
from shoppingcart.models import CourseRegistrationCode, DonationConfiguration
|
||||
@@ -60,12 +60,12 @@ from xmodule.modulestore.django import modulestore
|
||||
|
||||
log = logging.getLogger("edx.student")
|
||||
|
||||
# TODO START: Delete waffle flag as part of REVEM-204
|
||||
experiments_namespace = WaffleFlagNamespace(name=u'student.experiments')
|
||||
#TODO START: Delete waffle flag as part of REVEM-204.
|
||||
dashboard_metadata_flag = WaffleFlag(experiments_namespace,
|
||||
DASHBOARD_METADATA_FLAG = WaffleFlag(experiments_namespace,
|
||||
u'dashboard_metadata',
|
||||
flag_undefined_default=False)
|
||||
#TODO END: REVEM-204
|
||||
# TODO END: REVEM-204
|
||||
|
||||
|
||||
def get_org_black_and_whitelist_for_site():
|
||||
@@ -878,8 +878,11 @@ def student_dashboard(request):
|
||||
'recovery_email_activation_message': recovery_email_activation_message,
|
||||
# TODO START: Clean up REVEM-205 & REVEM-204.
|
||||
# The below context is for experiments in dashboard_metadata
|
||||
'course_prices': get_experiment_dashboard_metadata_context(course_enrollments) if dashboard_metadata_flag.is_enabled() else None,
|
||||
'course_prices': get_experiment_dashboard_metadata_context(course_enrollments) if DASHBOARD_METADATA_FLAG.is_enabled() else None,
|
||||
# TODO END: Clean up REVEM-205 & REVEM-204.
|
||||
# TODO START: clean up as part of REVEM-199 (START)
|
||||
'course_info': get_dashboard_course_info(user, course_enrollments),
|
||||
# TODO START: clean up as part of REVEM-199 (END)
|
||||
}
|
||||
|
||||
if ecommerce_service.is_enabled(request.user):
|
||||
|
||||
@@ -24,6 +24,8 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# TODO: clean up as part of REVEM-199 (START)
|
||||
experiments_namespace = WaffleFlagNamespace(name=u'experiments')
|
||||
|
||||
# .. feature_toggle_name: experiments.add_programs
|
||||
# .. feature_toggle_type: flag
|
||||
# .. feature_toggle_default: False
|
||||
@@ -36,7 +38,7 @@ logger = logging.getLogger(__name__)
|
||||
# .. feature_toggle_tickets: REVEM-63, REVEM-198
|
||||
# .. feature_toggle_status: supported
|
||||
PROGRAM_INFO_FLAG = WaffleFlag(
|
||||
waffle_namespace=WaffleFlagNamespace(name=u'experiments'),
|
||||
waffle_namespace=experiments_namespace,
|
||||
flag_name=u'add_programs',
|
||||
flag_undefined_default=False
|
||||
)
|
||||
@@ -54,11 +56,26 @@ PROGRAM_INFO_FLAG = WaffleFlag(
|
||||
# .. feature_toggle_tickets: REVEM-118, REVEM-206
|
||||
# .. feature_toggle_status: supported
|
||||
PROGRAM_PRICE_FLAG = WaffleFlag(
|
||||
waffle_namespace=WaffleFlagNamespace(name=u'experiments'),
|
||||
waffle_namespace=experiments_namespace,
|
||||
flag_name=u'add_program_price',
|
||||
flag_undefined_default=False
|
||||
)
|
||||
# TODO: clean up as part of REVEM-199 (END)
|
||||
|
||||
# .. feature_toggle_name: experiments.add_dashboard_info
|
||||
# .. feature_toggle_type: flag
|
||||
# .. feature_toggle_default: False
|
||||
# .. feature_toggle_description: Toggle for adding info about each course to the dashboard metadata
|
||||
# .. feature_toggle_category: experiments
|
||||
# .. feature_toggle_use_cases: monitored_rollout
|
||||
# .. feature_toggle_creation_date: 2019-3-28
|
||||
# .. feature_toggle_expiration_date: None
|
||||
# .. feature_toggle_warnings: None
|
||||
# .. feature_toggle_tickets: REVEM-118
|
||||
# .. feature_toggle_status: supported
|
||||
DASHBOARD_INFO_FLAG = WaffleFlag(experiments_namespace,
|
||||
u'add_dashboard_info',
|
||||
flag_undefined_default=False)
|
||||
# TODO END: clean up as part of REVEM-199 (End)
|
||||
|
||||
|
||||
def check_and_get_upgrade_link_and_date(user, enrollment=None, course=None):
|
||||
@@ -206,6 +223,27 @@ def is_enrolled_in_course_run(course_run, enrollment_course_ids):
|
||||
u'Unable to determine if user was enrolled since the course key {} is invalid'.format(key)
|
||||
)
|
||||
return False # Invalid course run key. Assume user is not enrolled.
|
||||
|
||||
|
||||
def get_dashboard_course_info(user, dashboard_enrollments):
|
||||
"""
|
||||
Given a list of enrollments shown on the dashboard, return a dict of course ids and experiment info for that course
|
||||
"""
|
||||
course_info = None
|
||||
if DASHBOARD_INFO_FLAG.is_enabled():
|
||||
# Get the enrollments here since the dashboard filters out those with completed entitlements
|
||||
user_enrollments = CourseEnrollment.objects.select_related('course').filter(user_id=user.id)
|
||||
audit_enrollments = user_enrollments.filter(mode='audit')
|
||||
|
||||
course_info = {
|
||||
str(dashboard_enrollment.course): get_base_experiment_metadata_context(dashboard_enrollment.course,
|
||||
user,
|
||||
dashboard_enrollment,
|
||||
user_enrollments,
|
||||
audit_enrollments)
|
||||
for dashboard_enrollment in dashboard_enrollments
|
||||
}
|
||||
return course_info
|
||||
# TODO: clean up as part of REVEM-199 (END)
|
||||
|
||||
|
||||
@@ -213,6 +251,7 @@ def get_experiment_user_metadata_context(course, user):
|
||||
"""
|
||||
Return a context dictionary with the keys used by the user_metadata.html.
|
||||
"""
|
||||
# TODO: call get_base_experiment_metadata_context(), and then add in the bits that are only needed by user_metadata
|
||||
enrollment_mode = None
|
||||
enrollment_time = None
|
||||
enrollment = None
|
||||
@@ -324,7 +363,93 @@ def get_experiment_user_metadata_context(course, user):
|
||||
}
|
||||
|
||||
|
||||
#TODO START: Clean up REVEM-205
|
||||
def get_base_experiment_metadata_context(course, user, enrollment, user_enrollments, audit_enrollments):
|
||||
"""
|
||||
Return a context dictionary with the keys used by dashboard_metadata.html.
|
||||
"""
|
||||
enrollment_mode = None
|
||||
enrollment_time = None
|
||||
# TODO: clean up as part of REVEM-199 (START)
|
||||
program_key = get_program_context(course, user_enrollments, audit_enrollments)
|
||||
# TODO: clean up as part of REVEM-199 (END)
|
||||
if enrollment.is_active:
|
||||
enrollment_mode = enrollment.mode
|
||||
enrollment_time = enrollment.created
|
||||
|
||||
# upgrade_link and upgrade_date should be None if user has passed their dynamic pacing deadline.
|
||||
upgrade_link, upgrade_date = check_and_get_upgrade_link_and_date(user, enrollment, course)
|
||||
|
||||
return {
|
||||
'upgrade_link': upgrade_link,
|
||||
'upgrade_price': unicode(get_cosmetic_verified_display_price(course)),
|
||||
'enrollment_mode': enrollment_mode,
|
||||
'enrollment_time': enrollment_time,
|
||||
'pacing_type': 'self_paced' if course.self_paced else 'instructor_paced',
|
||||
'upgrade_deadline': upgrade_date,
|
||||
'course_key': course.id,
|
||||
'course_start': course.start,
|
||||
'course_end': course.end,
|
||||
# TODO: clean up as part of REVEM-199 (START)
|
||||
'program_key_fields': program_key,
|
||||
# TODO: clean up as part of REVEM-199 (END)
|
||||
}
|
||||
|
||||
|
||||
# TODO: clean up as part of REVEM-199 (START)
|
||||
def get_program_context(course, user_enrollments, audit_enrollments):
|
||||
"""
|
||||
Return a context dictionary with program information.
|
||||
"""
|
||||
program_key = None
|
||||
if PROGRAM_INFO_FLAG.is_enabled():
|
||||
programs = get_programs(course=course.id)
|
||||
if programs:
|
||||
# A course can be in multiple programs, but we're just grabbing the first one
|
||||
program = programs[0]
|
||||
complete_enrollment = False
|
||||
has_courses_left_to_purchase = False
|
||||
total_courses = None
|
||||
courses = program.get('courses')
|
||||
courses_left_to_purchase_price = None
|
||||
courses_left_to_purchase_url = None
|
||||
program_uuid = program.get('uuid')
|
||||
is_eligible_for_one_click_purchase = program.get('is_program_eligible_for_one_click_purchase')
|
||||
if courses is not None:
|
||||
total_courses = len(courses)
|
||||
complete_enrollment = is_enrolled_in_all_courses(courses, user_enrollments)
|
||||
|
||||
# Get the price and purchase URL of the program courses the user has yet to purchase. Say a
|
||||
# program has 3 courses (A, B and C), and the user previously purchased a certificate for A.
|
||||
# The user is enrolled in audit mode for B. The "left to purchase price" should be the price of
|
||||
# B+C.
|
||||
non_audit_enrollments = [en for en in user_enrollments if en not in audit_enrollments]
|
||||
courses_left_to_purchase = get_unenrolled_courses(courses, non_audit_enrollments)
|
||||
if courses_left_to_purchase:
|
||||
has_courses_left_to_purchase = True
|
||||
if courses_left_to_purchase and is_eligible_for_one_click_purchase:
|
||||
courses_left_to_purchase_price, courses_left_to_purchase_skus = \
|
||||
get_program_price_and_skus(courses_left_to_purchase)
|
||||
if courses_left_to_purchase_skus:
|
||||
courses_left_to_purchase_url = EcommerceService().get_checkout_page_url(
|
||||
*courses_left_to_purchase_skus, program_uuid=program_uuid)
|
||||
|
||||
program_key = {
|
||||
'uuid': program_uuid,
|
||||
'title': program.get('title'),
|
||||
'marketing_url': program.get('marketing_url'),
|
||||
'status': program.get('status'),
|
||||
'is_eligible_for_one_click_purchase': is_eligible_for_one_click_purchase,
|
||||
'total_courses': total_courses,
|
||||
'complete_enrollment': complete_enrollment,
|
||||
'has_courses_left_to_purchase': has_courses_left_to_purchase,
|
||||
'courses_left_to_purchase_price': courses_left_to_purchase_price,
|
||||
'courses_left_to_purchase_url': courses_left_to_purchase_url,
|
||||
}
|
||||
return program_key
|
||||
# TODO: clean up as part of REVEM-199 (START)
|
||||
|
||||
|
||||
# TODO START: Clean up REVEM-205
|
||||
def get_experiment_dashboard_metadata_context(enrollments):
|
||||
"""
|
||||
Given a list of enrollments return a dict of course ids with their prices.
|
||||
@@ -333,7 +458,7 @@ def get_experiment_dashboard_metadata_context(enrollments):
|
||||
:return: dict of courses: course price for dashboard metadata
|
||||
"""
|
||||
return {str(enrollment.course): enrollment.course_price for enrollment in enrollments}
|
||||
#TODO END: Clean up REVEM-205
|
||||
# TODO END: Clean up REVEM-205
|
||||
|
||||
|
||||
def stable_bucketing_hash_group(group_name, group_count, username):
|
||||
|
||||
@@ -5,7 +5,7 @@ from openedx.core.djangolib.js_utils import dump_js_escaped_json
|
||||
|
||||
<!-- TODO START: Clean up REVEM-205.-->
|
||||
<%
|
||||
dashboard_metadata = { 'course_prices': course_prices }
|
||||
dashboard_metadata = { 'course_prices': course_prices, 'course_info': course_info}
|
||||
%>
|
||||
|
||||
<script type="application/json" id="dashboard-metadata">
|
||||
|
||||
@@ -384,4 +384,4 @@ from student.models import CourseEnrollment
|
||||
</section>
|
||||
|
||||
<%include file="dashboard/_dashboard_entitlement_unenrollment_modal.html"/>
|
||||
<%include file="/experiments/dashboard_metadata.html" args='course_prices=course_prices'/>
|
||||
<%include file="/experiments/dashboard_metadata.html" args='course_prices=course_prices, course_info=course_info'/>
|
||||
|
||||
Reference in New Issue
Block a user