Merge pull request #24864 from edx/ndalfonso/AA-196-course-celebration-cert

AA-196 course celebration cert.
This commit is contained in:
Dillon Dumesnil
2020-10-02 06:37:31 -07:00
committed by GitHub
11 changed files with 151 additions and 31 deletions

View File

@@ -4,6 +4,7 @@ Course API Serializers. Representing course catalog data
from rest_framework import serializers
from lms.djangoapps.course_home_api.progress.v1.serializers import CertificateDataSerializer
from openedx.core.lib.api.fields import AbsoluteURLField
@@ -90,6 +91,10 @@ class CourseInfoSerializer(serializers.Serializer): # pylint: disable=abstract-
notes = serializers.DictField()
marketing_url = serializers.CharField()
celebrations = serializers.DictField()
user_has_passing_grade = serializers.BooleanField()
course_exit_page_is_active = serializers.BooleanField()
certificate_data = CertificateDataSerializer()
verify_identity_url = AbsoluteURLField()
def __init__(self, *args, **kwargs):
"""

View File

@@ -8,6 +8,7 @@ import ddt
import mock
from completion.test_utils import CompletionWaffleTestMixin, submit_completions_for_testing
from django.conf import settings
from django.urls import reverse
from lms.djangoapps.courseware.access_utils import ACCESS_DENIED, ACCESS_GRANTED
from lms.djangoapps.courseware.tabs import ExternalLinkCourseTab
@@ -105,6 +106,20 @@ class CourseApiTestViews(BaseCoursewareTests):
if tab['url'] == 'http://zombo.com':
found = True
assert found, 'external link not in course tabs'
assert not response.data['user_has_passing_grade']
if enrollment_mode == 'audit':
# This message comes from AUDIT_PASSING_CERT_DATA in lms/djangoapps/courseware/views/views.py
expected_audit_message = ('You are enrolled in the audit track for this course. '
'The audit track does not include a certificate.')
assert response.data['certificate_data']['msg'] == expected_audit_message
assert response.data['verify_identity_url'] is None
else:
# Not testing certificate data for verified learner here. That is tested elsewhere
assert response.data['certificate_data'] is None
expected_verify_identity_url = reverse('verify_student_verify_now', args=[self.course.id])
# The response contains an absolute URL so this is only checking the path of the final
assert expected_verify_identity_url in response.data['verify_identity_url']
elif enable_anonymous and not logged_in:
# multiple checks use this handler
check_public_access.assert_called()

View File

@@ -30,9 +30,12 @@ from lms.djangoapps.courseware.courses import check_course_access, get_course_by
from lms.djangoapps.courseware.masquerade import setup_masquerade
from lms.djangoapps.courseware.module_render import get_module_by_usage_id
from lms.djangoapps.courseware.tabs import get_course_tab_list
from lms.djangoapps.courseware.toggles import REDIRECT_TO_COURSEWARE_MICROFRONTEND
from lms.djangoapps.courseware.toggles import REDIRECT_TO_COURSEWARE_MICROFRONTEND, course_exit_page_is_active
from lms.djangoapps.courseware.utils import can_show_verified_upgrade
from lms.djangoapps.courseware.utils import verified_upgrade_deadline_link
from lms.djangoapps.courseware.views.views import get_cert_data
from lms.djangoapps.grades.api import CourseGradeFactory
from lms.djangoapps.verify_student.services import IDVerificationService
from openedx.core.lib.api.view_utils import DeveloperErrorViewMixin
from openedx.features.course_experience import DISPLAY_COURSE_SOCK_FLAG
from openedx.features.content_type_gating.models import ContentTypeGatingConfig
@@ -55,18 +58,16 @@ class CoursewareMeta:
username or request.user.username,
course_key,
)
self.effective_user = self.overview.effective_user
self.original_user_is_staff = has_access(request.user, 'staff', self.overview).has_access
self.course_key = course_key
self.enrollment_object = CourseEnrollment.get_enrollment(self.effective_user, self.course_key,
select_related=['celebration'])
course_masquerade, user = setup_masquerade(
self.course_masquerade, self.effective_user = setup_masquerade(
request,
course_key,
staff_access=self.original_user_is_staff,
)
self.is_staff = has_access(user, 'staff', self.overview).has_access
self.course_masquerade = course_masquerade
self.is_staff = has_access(self.effective_user, 'staff', self.overview).has_access
self.enrollment_object = CourseEnrollment.get_enrollment(self.effective_user, self.course_key,
select_related=['celebration'])
def __getattr__(self, name):
return getattr(self.overview, name)
@@ -104,14 +105,12 @@ class CoursewareMeta:
"""
Return enrollment information.
"""
if self.effective_user.is_anonymous:
if self.effective_user.is_anonymous or not self.enrollment_object:
mode = None
is_active = False
else:
mode, is_active = CourseEnrollment.enrollment_mode_for_user(
self.effective_user,
self.course_key
)
mode = self.enrollment_object.mode
is_active = self.enrollment_object.is_active
return {'mode': mode, 'is_active': is_active}
@property
@@ -208,6 +207,43 @@ class CoursewareMeta:
'first_section': CourseEnrollmentCelebration.should_celebrate_first_section(self.enrollment_object),
}
@property
def user_has_passing_grade(self):
""" Returns a boolean on if the effective_user has a passing grade in the course """
course = get_course_by_id(self.course_key)
user_grade = CourseGradeFactory().read(self.effective_user, course).percent
return user_grade >= course.lowest_passing_grade
@property
def course_exit_page_is_active(self):
""" Returns a boolean on if the course exit page is active """
return course_exit_page_is_active(self.course_key)
@property
def certificate_data(self):
"""
Returns certificate data if the effective_user is enrolled.
Note: certificate data can be None depending on learner and/or course state.
"""
course = get_course_by_id(self.course_key)
if self.enrollment_object:
return get_cert_data(self.effective_user, course, self.enrollment_object.mode)
@property
def verify_identity_url(self):
"""
Returns a String to the location to verify a learner's identity
Note: This might return an absolute URL (if the verification MFE is enabled) or a relative
URL. The serializer will make the relative URL absolute so any consumers can treat this
as a full URL.
"""
if self.enrollment_object and self.enrollment_object.mode in CourseMode.VERIFIED_MODES:
verification_status = IDVerificationService.user_status(self.effective_user)['status']
if verification_status == 'must_reverify':
return IDVerificationService.get_verify_location('verify_student_reverify')
else:
return IDVerificationService.get_verify_location('verify_student_verify_now', self.course_key)
class CoursewareInformation(RetrieveAPIView):
"""
@@ -252,6 +288,12 @@ class CoursewareInformation(RetrieveAPIView):
* can_load_course: Whether the user can view the course (AccessResponse object)
* is_staff: Whether the effective user has staff access to the course
* original_user_is_staff: Whether the original user has staff access to the course
* user_has_passing_grade: Whether or not the effective user's grade is equal to or above the courses minimum
passing grade
* course_exit_page_is_active: Flag for the learning mfe on whether or not the course exit page should display
* certificate_data: data regarding the effective user's certificate for the given course
* verify_identity_url: URL for a learner to verify their identity. Only returned for learners enrolled in a
verified mode. Will update to reverify URL if necessary.
**Parameters:**