From f3f7e78e24b71c7773aa762e872c96f5878ee902 Mon Sep 17 00:00:00 2001 From: Sofiya Semenova Date: Tue, 29 Aug 2017 16:19:53 -0400 Subject: [PATCH] educator-1101 view/request certificate button logic on progress page and dashboard --- lms/djangoapps/courseware/tests/test_views.py | 6 ++ lms/djangoapps/courseware/views/views.py | 88 +++++++++---------- lms/templates/courseware/progress.html | 4 +- 3 files changed, 51 insertions(+), 47 deletions(-) diff --git a/lms/djangoapps/courseware/tests/test_views.py b/lms/djangoapps/courseware/tests/test_views.py index 054e1608d9..499ff7c6b3 100644 --- a/lms/djangoapps/courseware/tests/test_views.py +++ b/lms/djangoapps/courseware/tests/test_views.py @@ -1565,6 +1565,7 @@ class ProgressPageTests(ProgressPageBaseTests): 'lms.djangoapps.grades.new.course_grade.CourseGrade.summary', PropertyMock(return_value={'grade': 'Pass', 'percent': 0.75, 'section_breakdown': [], 'grade_breakdown': {}}) ) + @patch('courseware.views.views.is_course_passed', PropertyMock(return_value=True)) def test_message_for_audit_mode(self): """ Verify that message appears on progress page, if learner is enrolled in audit mode. @@ -1579,6 +1580,7 @@ class ProgressPageTests(ProgressPageBaseTests): u'You are enrolled in the audit track for this course. The audit track does not include a certificate.' ) + @patch('courseware.views.views.is_course_passed', PropertyMock(return_value=True)) def test_invalidated_cert_data(self): """ Verify that invalidated cert data is returned if cert is invalidated. @@ -1597,6 +1599,7 @@ class ProgressPageTests(ProgressPageBaseTests): self.assertEqual(response.cert_status, 'invalidated') self.assertEqual(response.title, 'Your certificate has been invalidated') + @patch('courseware.views.views.is_course_passed', PropertyMock(return_value=True)) def test_downloadable_get_cert_data(self): """ Verify that downloadable cert data is returned if cert is downloadable. @@ -1611,6 +1614,7 @@ class ProgressPageTests(ProgressPageBaseTests): self.assertEqual(response.cert_status, 'downloadable') self.assertEqual(response.title, 'Your certificate is available') + @patch('courseware.views.views.is_course_passed', PropertyMock(return_value=True)) def test_generating_get_cert_data(self): """ Verify that generating cert data is returned if cert is generating. @@ -1625,6 +1629,7 @@ class ProgressPageTests(ProgressPageBaseTests): self.assertEqual(response.cert_status, 'generating') self.assertEqual(response.title, "We're working on it...") + @patch('courseware.views.views.is_course_passed', PropertyMock(return_value=True)) def test_unverified_get_cert_data(self): """ Verify that unverified cert data is returned if cert is unverified. @@ -1639,6 +1644,7 @@ class ProgressPageTests(ProgressPageBaseTests): self.assertEqual(response.cert_status, 'unverified') self.assertEqual(response.title, "Certificate unavailable") + @patch('courseware.views.views.is_course_passed', PropertyMock(return_value=True)) def test_request_get_cert_data(self): """ Verify that requested cert data is returned if cert is to be requested. diff --git a/lms/djangoapps/courseware/views/views.py b/lms/djangoapps/courseware/views/views.py index 545c325caa..992d41e12f 100644 --- a/lms/djangoapps/courseware/views/views.py +++ b/lms/djangoapps/courseware/views/views.py @@ -77,6 +77,7 @@ from openedx.core.djangoapps.credit.api import ( is_credit_course, is_user_eligible_for_credit ) +from openedx.core.djangoapps.certificates.config import waffle as certificates_waffle from openedx.core.djangoapps.models.course_details import CourseDetails from openedx.core.djangoapps.monitoring_utils import set_custom_metrics_for_course_key from openedx.core.djangoapps.plugin_api.views import EdxFragmentView @@ -888,9 +889,8 @@ def _progress(request, course_key, student_id): 'masquerade': masquerade, 'supports_preview_menu': True, 'student': student, - 'passed': is_course_passed(course, grade_summary), 'credit_course_requirements': _credit_course_requirements(course_key, student), - 'certificate_data': _get_cert_data(student, course, course_key, is_active, enrollment_mode), + 'certificate_data': _get_cert_data(student, course, course_key, is_active, enrollment_mode, grade_summary), } context.update( get_experiment_user_metadata_context( @@ -905,7 +905,7 @@ def _progress(request, course_key, student_id): return response -def _get_cert_data(student, course, course_key, is_active, enrollment_mode): +def _get_cert_data(student, course, course_key, is_active, enrollment_mode, grade_summary=None): """Returns students course certificate related data. Arguments: @@ -914,13 +914,14 @@ def _get_cert_data(student, course, course_key, is_active, enrollment_mode): course_key (CourseKey): Course identifier for course. is_active (Bool): Boolean value to check if course is active. enrollment_mode (String): Course mode in which student is enrolled. + grade_summary (dict): Student grade details. Returns: returns dict if course certificate is available else None. """ from lms.djangoapps.courseware.courses import get_course_by_id - if enrollment_mode == CourseMode.AUDIT: + if not CourseMode.is_eligible_for_certificate(enrollment_mode): return CertData( CertificateStatuses.audit_passing, _('Your enrollment: Audit track'), @@ -937,14 +938,22 @@ def _get_cert_data(student, course, course_key, is_active, enrollment_mode): course = get_course_by_id(course_key) may_view_certificate = course.self_paced or course.may_certify() - show_message = all([ - is_active, - CourseMode.is_eligible_for_certificate(enrollment_mode), - certs_api.cert_generation_enabled(course_key), - may_view_certificate - ]) + switches = certificates_waffle.waffle() + switches_enabled = (switches.is_enabled(certificates_waffle.SELF_PACED_ONLY) and + switches.is_enabled(certificates_waffle.INSTRUCTOR_PACED_ONLY)) + student_cert_generation_enabled = certs_api.cert_generation_enabled(course_key) if not switches_enabled else True - if not show_message: + # Don't show certificate information if: + # 1) the learner has not passed the course + # 2) the course is not active + # 3) auto-generated certs flags are not enabled, but student cert generation is not enabled either + # 4) the learner may not view the certificate, based on the course's advanced course settings. + if not all([ + is_course_passed(course, grade_summary), + is_active, + student_cert_generation_enabled, + may_view_certificate + ]): return None if certs_api.is_certificate_invalid(student, course_key): @@ -958,53 +967,44 @@ def _get_cert_data(student, course, course_key, is_active, enrollment_mode): cert_downloadable_status = certs_api.certificate_downloadable_status(student, course_key) + generating_certificate_message = CertData( + CertificateStatuses.generating, + _("We're working on it..."), + _( + "We're creating your certificate. You can keep working in your courses and a link " + "to it will appear here and on your Dashboard when it is ready." + ), + download_url=None, + cert_web_view_url=None + ) + if cert_downloadable_status['is_downloadable']: - cert_status = CertificateStatuses.downloadable - title = _('Your certificate is available') - msg = _("You've earned a certificate for this course.") if certs_api.has_html_certificates_enabled(course_key, course): if certs_api.get_active_web_certificate(course) is not None: - cert_web_view_url = certs_api.get_certificate_url( - course_id=course_key, uuid=cert_downloadable_status['uuid'] - ) return CertData( - cert_status, - title, - msg, + CertificateStatuses.downloadable, + _('Your certificate is available'), + _("You've earned a certificate for this course."), download_url=None, - cert_web_view_url=cert_web_view_url + cert_web_view_url=certs_api.get_certificate_url( + course_id=course_key, uuid=cert_downloadable_status['uuid'] + ) ) else: - return CertData( - CertificateStatuses.generating, - _("We're working on it..."), - _( - "We're creating your certificate. You can keep working in your courses and a link " - "to it will appear here and on your Dashboard when it is ready." - ), - download_url=None, - cert_web_view_url=None - ) + # If there is an error, the user should see the generating certificate message + # until a new certificate is generated. + return generating_certificate_message return CertData( - cert_status, - title, - msg, + CertificateStatuses.downloadable, + _('Your certificate is available'), + _("You've earned a certificate for this course."), download_url=cert_downloadable_status['download_url'], cert_web_view_url=None ) if cert_downloadable_status['is_generating']: - return CertData( - CertificateStatuses.generating, - _("We're working on it..."), - _( - "We're creating your certificate. You can keep working in your courses and a link to " - "it will appear here and on your Dashboard when it is ready." - ), - download_url=None, - cert_web_view_url=None - ) + return generating_certificate_message # If the learner is in verified modes and the student did not have # their ID verified, we need to show message to ask learner to verify their ID first diff --git a/lms/templates/courseware/progress.html b/lms/templates/courseware/progress.html index ce71201f62..1e10df5381 100644 --- a/lms/templates/courseware/progress.html +++ b/lms/templates/courseware/progress.html @@ -56,10 +56,9 @@ from django.utils.http import urlquote_plus ${_("Course Progress for Student '{username}' ({email})").format(username=student.username, email=student.email)} - %if certificate_data:
- %if passed: + %if certificate_data:
<% post_url = reverse('generate_user_cert', args=[unicode(course.id)]) %> @@ -80,7 +79,6 @@ from django.utils.http import urlquote_plus
%endif
- %endif %if not course.disable_progress_graph: