Commit 6f983c33 by Simon Chen

Merge pull request #12484 from edx/schen/ECOM-4007

ECOM-4007 Add new cert status "unverified" to handle no active user ID verification
parents 18cddf6e e6137dd6
...@@ -15,6 +15,7 @@ from xmodule.modulestore.tests.factories import CourseFactory ...@@ -15,6 +15,7 @@ from xmodule.modulestore.tests.factories import CourseFactory
from student.tests.factories import UserFactory, CourseEnrollmentFactory from student.tests.factories import UserFactory, CourseEnrollmentFactory
from certificates.tests.factories import GeneratedCertificateFactory # pylint: disable=import-error from certificates.tests.factories import GeneratedCertificateFactory # pylint: disable=import-error
from certificates.api import get_certificate_url # pylint: disable=import-error from certificates.api import get_certificate_url # pylint: disable=import-error
from certificates.models import CertificateStatuses # pylint: disable=import-error
from course_modes.models import CourseMode from course_modes.models import CourseMode
from student.models import LinkedInAddToProfileConfiguration from student.models import LinkedInAddToProfileConfiguration
...@@ -111,6 +112,17 @@ class CertificateDisplayTest(SharedModuleStoreTestCase): ...@@ -111,6 +112,17 @@ class CertificateDisplayTest(SharedModuleStoreTestCase):
self.assertContains(response, u'View Test_Certificate') self.assertContains(response, u'View Test_Certificate')
self.assertContains(response, test_url) self.assertContains(response, test_url)
@ddt.data('verified', 'honor', 'professional')
def test_unverified_certificate_message(self, enrollment_mode):
cert = self._create_certificate(enrollment_mode)
cert.status = CertificateStatuses.unverified
cert.save()
response = self.client.get(reverse('dashboard'))
self.assertContains(
response,
u'do not have a current verified identity with {platform_name}'
.format(platform_name=settings.PLATFORM_NAME))
def test_post_to_linkedin_invisibility(self): def test_post_to_linkedin_invisibility(self):
""" """
Verifies that the post certificate to linked button Verifies that the post certificate to linked button
......
...@@ -319,6 +319,7 @@ def _cert_info(user, course_overview, cert_status, course_mode): # pylint: disa ...@@ -319,6 +319,7 @@ def _cert_info(user, course_overview, cert_status, course_mode): # pylint: disa
CertificateStatuses.auditing: 'auditing', CertificateStatuses.auditing: 'auditing',
CertificateStatuses.audit_passing: 'auditing', CertificateStatuses.audit_passing: 'auditing',
CertificateStatuses.audit_notpassing: 'auditing', CertificateStatuses.audit_notpassing: 'auditing',
CertificateStatuses.unverified: 'unverified',
} }
default_status = 'processing' default_status = 'processing'
...@@ -350,7 +351,7 @@ def _cert_info(user, course_overview, cert_status, course_mode): # pylint: disa ...@@ -350,7 +351,7 @@ def _cert_info(user, course_overview, cert_status, course_mode): # pylint: disa
'can_unenroll': status not in DISABLE_UNENROLL_CERT_STATES, 'can_unenroll': status not in DISABLE_UNENROLL_CERT_STATES,
} }
if (status in ('generating', 'ready', 'notpassing', 'restricted', 'auditing') and if (status in ('generating', 'ready', 'notpassing', 'restricted', 'auditing', 'unverified') and
course_overview.end_of_course_survey_url is not None): course_overview.end_of_course_survey_url is not None):
status_dict.update({ status_dict.update({
'show_survey_button': True, 'show_survey_button': True,
...@@ -394,7 +395,7 @@ def _cert_info(user, course_overview, cert_status, course_mode): # pylint: disa ...@@ -394,7 +395,7 @@ def _cert_info(user, course_overview, cert_status, course_mode): # pylint: disa
cert_status['download_url'] cert_status['download_url']
) )
if status in ('generating', 'ready', 'notpassing', 'restricted', 'auditing'): if status in ('generating', 'ready', 'notpassing', 'restricted', 'auditing', 'unverified'):
if 'grade' not in cert_status: if 'grade' not in cert_status:
# Note: as of 11/20/2012, we know there are students in this state-- cs169.1x, # Note: as of 11/20/2012, we know there are students in this state-- cs169.1x,
# who need to be regraded (we weren't tracking 'notpassing' at first). # who need to be regraded (we weren't tracking 'notpassing' at first).
......
...@@ -231,21 +231,21 @@ class TestFieldOverrideMongoPerformance(FieldOverridePerformanceTestCase): ...@@ -231,21 +231,21 @@ class TestFieldOverrideMongoPerformance(FieldOverridePerformanceTestCase):
# # of mongo queries, # # of mongo queries,
# # of xblocks # # of xblocks
# ) # )
('no_overrides', 1, True, False): (47, 1, 6, 13), ('no_overrides', 1, True, False): (48, 1, 6, 13),
('no_overrides', 2, True, False): (119, 16, 6, 84), ('no_overrides', 2, True, False): (120, 16, 6, 84),
('no_overrides', 3, True, False): (399, 81, 6, 335), ('no_overrides', 3, True, False): (400, 81, 6, 335),
('ccx', 1, True, False): (47, 1, 6, 13), ('ccx', 1, True, False): (48, 1, 6, 13),
('ccx', 2, True, False): (119, 16, 6, 84), ('ccx', 2, True, False): (120, 16, 6, 84),
('ccx', 3, True, False): (399, 81, 6, 335), ('ccx', 3, True, False): (400, 81, 6, 335),
('ccx', 1, True, True): (47, 1, 6, 13), ('ccx', 1, True, True): (47, 1, 6, 13),
('ccx', 2, True, True): (119, 16, 6, 84), ('ccx', 2, True, True): (119, 16, 6, 84),
('ccx', 3, True, True): (399, 81, 6, 335), ('ccx', 3, True, True): (399, 81, 6, 335),
('no_overrides', 1, False, False): (47, 1, 6, 13), ('no_overrides', 1, False, False): (48, 1, 6, 13),
('no_overrides', 2, False, False): (119, 16, 6, 84), ('no_overrides', 2, False, False): (120, 16, 6, 84),
('no_overrides', 3, False, False): (399, 81, 6, 335), ('no_overrides', 3, False, False): (400, 81, 6, 335),
('ccx', 1, False, False): (47, 1, 6, 13), ('ccx', 1, False, False): (48, 1, 6, 13),
('ccx', 2, False, False): (119, 16, 6, 84), ('ccx', 2, False, False): (120, 16, 6, 84),
('ccx', 3, False, False): (399, 81, 6, 335), ('ccx', 3, False, False): (400, 81, 6, 335),
('ccx', 1, False, True): (47, 1, 6, 13), ('ccx', 1, False, True): (47, 1, 6, 13),
('ccx', 2, False, True): (119, 16, 6, 84), ('ccx', 2, False, True): (119, 16, 6, 84),
('ccx', 3, False, True): (399, 81, 6, 335), ('ccx', 3, False, True): (399, 81, 6, 335),
...@@ -260,22 +260,22 @@ class TestFieldOverrideSplitPerformance(FieldOverridePerformanceTestCase): ...@@ -260,22 +260,22 @@ class TestFieldOverrideSplitPerformance(FieldOverridePerformanceTestCase):
__test__ = True __test__ = True
TEST_DATA = { TEST_DATA = {
('no_overrides', 1, True, False): (47, 1, 4, 9), ('no_overrides', 1, True, False): (48, 1, 4, 9),
('no_overrides', 2, True, False): (119, 16, 19, 54), ('no_overrides', 2, True, False): (120, 16, 19, 54),
('no_overrides', 3, True, False): (399, 81, 84, 215), ('no_overrides', 3, True, False): (400, 81, 84, 215),
('ccx', 1, True, False): (47, 1, 4, 9), ('ccx', 1, True, False): (48, 1, 4, 9),
('ccx', 2, True, False): (119, 16, 19, 54), ('ccx', 2, True, False): (120, 16, 19, 54),
('ccx', 3, True, False): (399, 81, 84, 215), ('ccx', 3, True, False): (400, 81, 84, 215),
('ccx', 1, True, True): (49, 1, 4, 13), ('ccx', 1, True, True): (50, 1, 4, 13),
('ccx', 2, True, True): (121, 16, 19, 84), ('ccx', 2, True, True): (122, 16, 19, 84),
('ccx', 3, True, True): (401, 81, 84, 335), ('ccx', 3, True, True): (402, 81, 84, 335),
('no_overrides', 1, False, False): (47, 1, 4, 9), ('no_overrides', 1, False, False): (48, 1, 4, 9),
('no_overrides', 2, False, False): (119, 16, 19, 54), ('no_overrides', 2, False, False): (120, 16, 19, 54),
('no_overrides', 3, False, False): (399, 81, 84, 215), ('no_overrides', 3, False, False): (400, 81, 84, 215),
('ccx', 1, False, False): (47, 1, 4, 9), ('ccx', 1, False, False): (48, 1, 4, 9),
('ccx', 2, False, False): (119, 16, 19, 54), ('ccx', 2, False, False): (120, 16, 19, 54),
('ccx', 3, False, False): (399, 81, 84, 215), ('ccx', 3, False, False): (400, 81, 84, 215),
('ccx', 1, False, True): (47, 1, 4, 9), ('ccx', 1, False, True): (47, 1, 4, 9),
('ccx', 2, False, True): (119, 16, 19, 54), ('ccx', 2, False, True): (119, 16, 19, 54),
('ccx', 3, False, True): (399, 81, 84, 215), ('ccx', 3, False, True): (400, 81, 84, 215),
} }
...@@ -225,6 +225,7 @@ def certificate_downloadable_status(student, course_key): ...@@ -225,6 +225,7 @@ def certificate_downloadable_status(student, course_key):
'is_downloadable': False, 'is_downloadable': False,
'is_generating': True if current_status['status'] in [CertificateStatuses.generating, 'is_generating': True if current_status['status'] in [CertificateStatuses.generating,
CertificateStatuses.error] else False, CertificateStatuses.error] else False,
'is_unverified': True if current_status['status'] == CertificateStatuses.unverified else False,
'download_url': None, 'download_url': None,
'uuid': None, 'uuid': None,
} }
......
...@@ -88,6 +88,7 @@ class CertificateStatuses(object): ...@@ -88,6 +88,7 @@ class CertificateStatuses(object):
auditing = 'auditing' auditing = 'auditing'
audit_passing = 'audit_passing' audit_passing = 'audit_passing'
audit_notpassing = 'audit_notpassing' audit_notpassing = 'audit_notpassing'
unverified = 'unverified'
readable_statuses = { readable_statuses = {
downloadable: "already received", downloadable: "already received",
...@@ -466,6 +467,9 @@ def certificate_status_for_student(student, course_id): ...@@ -466,6 +467,9 @@ def certificate_status_for_student(student, course_id):
should not be issued a certificate. This will should not be issued a certificate. This will
be set if allow_certificate is set to False in be set if allow_certificate is set to False in
the userprofile table the userprofile table
unverified - The student is in verified enrollment track and
the student did not have their identity verified,
even though they should be eligible for the cert otherwise.
If the status is "downloadable", the dictionary also contains If the status is "downloadable", the dictionary also contains
"download_url". "download_url".
......
...@@ -263,7 +263,7 @@ class XQueueCertInterface(object): ...@@ -263,7 +263,7 @@ class XQueueCertInterface(object):
user_is_verified = SoftwareSecurePhotoVerification.user_is_verified(student) user_is_verified = SoftwareSecurePhotoVerification.user_is_verified(student)
cert_mode = enrollment_mode cert_mode = enrollment_mode
is_eligible_for_certificate = is_whitelisted or CourseMode.is_eligible_for_certificate(enrollment_mode) is_eligible_for_certificate = is_whitelisted or CourseMode.is_eligible_for_certificate(enrollment_mode)
unverified = False
# For credit mode generate verified certificate # For credit mode generate verified certificate
if cert_mode == CourseMode.CREDIT_MODE: if cert_mode == CourseMode.CREDIT_MODE:
cert_mode = CourseMode.VERIFIED cert_mode = CourseMode.VERIFIED
...@@ -274,7 +274,10 @@ class XQueueCertInterface(object): ...@@ -274,7 +274,10 @@ class XQueueCertInterface(object):
template_pdf = "certificate-template-{id.org}-{id.course}-verified.pdf".format(id=course_id) template_pdf = "certificate-template-{id.org}-{id.course}-verified.pdf".format(id=course_id)
elif mode_is_verified and not user_is_verified: elif mode_is_verified and not user_is_verified:
template_pdf = "certificate-template-{id.org}-{id.course}.pdf".format(id=course_id) template_pdf = "certificate-template-{id.org}-{id.course}.pdf".format(id=course_id)
cert_mode = GeneratedCertificate.MODES.honor if CourseMode.mode_for_course(course_id, CourseMode.HONOR):
cert_mode = GeneratedCertificate.MODES.honor
else:
unverified = True
else: else:
# honor code and audit students # honor code and audit students
template_pdf = "certificate-template-{id.org}-{id.course}.pdf".format(id=course_id) template_pdf = "certificate-template-{id.org}-{id.course}.pdf".format(id=course_id)
...@@ -388,6 +391,20 @@ class XQueueCertInterface(object): ...@@ -388,6 +391,20 @@ class XQueueCertInterface(object):
) )
return cert return cert
if unverified:
cert.status = status.unverified
cert.save()
LOGGER.info(
(
u"User %s has a verified enrollment in course %s "
u"but is missing ID verification. "
u"Certificate status has been set to unverified"
),
student.id,
unicode(course_id),
)
return cert
# Finally, generate the certificate and send it off. # Finally, generate the certificate and send it off.
return self._generate_cert(cert, course, student, grade_contents, template_pdf, generate_pdf) return self._generate_cert(cert, course, student, grade_contents, template_pdf, generate_pdf)
......
...@@ -117,6 +117,7 @@ class CertificateDownloadableStatusTests(WebCertificateTestMixin, ModuleStoreTes ...@@ -117,6 +117,7 @@ class CertificateDownloadableStatusTests(WebCertificateTestMixin, ModuleStoreTes
{ {
'is_downloadable': False, 'is_downloadable': False,
'is_generating': True, 'is_generating': True,
'is_unverified': False,
'download_url': None, 'download_url': None,
'uuid': None, 'uuid': None,
} }
...@@ -135,6 +136,7 @@ class CertificateDownloadableStatusTests(WebCertificateTestMixin, ModuleStoreTes ...@@ -135,6 +136,7 @@ class CertificateDownloadableStatusTests(WebCertificateTestMixin, ModuleStoreTes
{ {
'is_downloadable': False, 'is_downloadable': False,
'is_generating': True, 'is_generating': True,
'is_unverified': False,
'download_url': None, 'download_url': None,
'uuid': None 'uuid': None
} }
...@@ -146,6 +148,7 @@ class CertificateDownloadableStatusTests(WebCertificateTestMixin, ModuleStoreTes ...@@ -146,6 +148,7 @@ class CertificateDownloadableStatusTests(WebCertificateTestMixin, ModuleStoreTes
{ {
'is_downloadable': False, 'is_downloadable': False,
'is_generating': False, 'is_generating': False,
'is_unverified': False,
'download_url': None, 'download_url': None,
'uuid': None, 'uuid': None,
} }
...@@ -169,6 +172,7 @@ class CertificateDownloadableStatusTests(WebCertificateTestMixin, ModuleStoreTes ...@@ -169,6 +172,7 @@ class CertificateDownloadableStatusTests(WebCertificateTestMixin, ModuleStoreTes
{ {
'is_downloadable': True, 'is_downloadable': True,
'is_generating': False, 'is_generating': False,
'is_unverified': False,
'download_url': 'www.google.com', 'download_url': 'www.google.com',
'uuid': cert.verify_uuid 'uuid': cert.verify_uuid
} }
...@@ -194,6 +198,7 @@ class CertificateDownloadableStatusTests(WebCertificateTestMixin, ModuleStoreTes ...@@ -194,6 +198,7 @@ class CertificateDownloadableStatusTests(WebCertificateTestMixin, ModuleStoreTes
{ {
'is_downloadable': True, 'is_downloadable': True,
'is_generating': False, 'is_generating': False,
'is_unverified': False,
'download_url': '/certificates/user/{user_id}/course/{course_id}'.format( 'download_url': '/certificates/user/{user_id}/course/{course_id}'.format(
user_id=self.student.id, # pylint: disable=no-member user_id=self.student.id, # pylint: disable=no-member
course_id=self.course.id, course_id=self.course.id,
......
...@@ -1367,7 +1367,7 @@ class ProgressPageTests(ModuleStoreTestCase): ...@@ -1367,7 +1367,7 @@ class ProgressPageTests(ModuleStoreTestCase):
self.assertContains(resp, u"Download Your Certificate") self.assertContains(resp, u"Download Your Certificate")
@ddt.data( @ddt.data(
*itertools.product(((41, 4, True), (41, 4, False)), (True, False)) *itertools.product(((42, 4, True), (42, 4, False)), (True, False))
) )
@ddt.unpack @ddt.unpack
def test_query_counts(self, (sql_calls, mongo_calls, self_paced), self_paced_enabled): def test_query_counts(self, (sql_calls, mongo_calls, self_paced), self_paced_enabled):
...@@ -1382,22 +1382,32 @@ class ProgressPageTests(ModuleStoreTestCase): ...@@ -1382,22 +1382,32 @@ class ProgressPageTests(ModuleStoreTestCase):
'grade': 'Pass', 'percent': 0.75, 'section_breakdown': [], 'grade_breakdown': [] 'grade': 'Pass', 'percent': 0.75, 'section_breakdown': [], 'grade_breakdown': []
})) }))
@ddt.data( @ddt.data(
(CourseMode.AUDIT, False), *itertools.product(
(CourseMode.HONOR, True), (
(CourseMode.VERIFIED, True), CourseMode.AUDIT,
(CourseMode.PROFESSIONAL, True), CourseMode.HONOR,
(CourseMode.NO_ID_PROFESSIONAL_MODE, True), CourseMode.VERIFIED,
(CourseMode.CREDIT_MODE, True), CourseMode.PROFESSIONAL,
CourseMode.NO_ID_PROFESSIONAL_MODE,
CourseMode.CREDIT_MODE
),
(True, False)
)
) )
@ddt.unpack @ddt.unpack
def test_show_certificate_request_button(self, course_mode, show_button): def test_show_certificate_request_button(self, course_mode, user_verified):
"""Verify that the Request Certificate is not displayed in audit mode.""" """Verify that the Request Certificate is not displayed in audit mode."""
CertificateGenerationConfiguration(enabled=True).save() CertificateGenerationConfiguration(enabled=True).save()
certs_api.set_cert_generation_enabled(self.course.id, True) certs_api.set_cert_generation_enabled(self.course.id, True)
CourseEnrollment.enroll(self.user, self.course.id, mode=course_mode) CourseEnrollment.enroll(self.user, self.course.id, mode=course_mode)
with patch(
resp = views.progress(self.request, course_id=unicode(self.course.id)) 'lms.djangoapps.verify_student.models.SoftwareSecurePhotoVerification.user_is_verified'
self.assertEqual(show_button, 'Request Certificate' in resp.content) ) as user_verify:
user_verify.return_value = user_verified
resp = views.progress(self.request, course_id=unicode(self.course.id))
self.assertEqual(
course_mode is not CourseMode.AUDIT and user_verified,
'Request Certificate' in resp.content)
@attr('shard_1') @attr('shard_1')
......
...@@ -66,6 +66,7 @@ from courseware.url_helpers import get_redirect_url, get_redirect_url_for_global ...@@ -66,6 +66,7 @@ from courseware.url_helpers import get_redirect_url, get_redirect_url_for_global
from courseware.user_state_client import DjangoXBlockUserStateClient from courseware.user_state_client import DjangoXBlockUserStateClient
from edxmako.shortcuts import render_to_response, render_to_string, marketing_link from edxmako.shortcuts import render_to_response, render_to_string, marketing_link
from instructor.enrollment import uses_shib from instructor.enrollment import uses_shib
from lms.djangoapps.verify_student.models import SoftwareSecurePhotoVerification
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
from openedx.core.djangoapps.coursetalk.helpers import inject_coursetalk_keys_into_context from openedx.core.djangoapps.coursetalk.helpers import inject_coursetalk_keys_into_context
from openedx.core.djangoapps.credit.api import ( from openedx.core.djangoapps.credit.api import (
...@@ -736,6 +737,7 @@ def _progress(request, course_key, student_id): ...@@ -736,6 +737,7 @@ def _progress(request, course_key, student_id):
'passed': is_course_passed(course, grade_summary), 'passed': is_course_passed(course, grade_summary),
'show_generate_cert_btn': show_generate_cert_btn, 'show_generate_cert_btn': show_generate_cert_btn,
'credit_course_requirements': _credit_course_requirements(course_key, student), 'credit_course_requirements': _credit_course_requirements(course_key, student),
'is_id_verified': SoftwareSecurePhotoVerification.user_is_verified(student)
} }
if show_generate_cert_btn: if show_generate_cert_btn:
......
...@@ -80,6 +80,13 @@ from django.utils.http import urlquote_plus ...@@ -80,6 +80,13 @@ from django.utils.http import urlquote_plus
<p class="copy">${_("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.")}</p> <p class="copy">${_("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.")}</p>
</div> </div>
<div class="msg-actions"></div> <div class="msg-actions"></div>
%elif not is_id_verified or is_unverified:
<div class="msg-content">
## Translators: This message appears to users when the users have not completed identity verification.
<h2 class="title">${_("Certificate unavailable")}</h2>
<p class="copy">${_("You have not received a certificate because you do not have a current {platform_name} verified identity. ").format(platform_name=settings.PLATFORM_NAME)} <a href="${reverse('verify_student_reverify')}"> ${_("Verify your identity now.")}</a></p>
</div>
<div class="msg-actions"></div>
%else: %else:
<div class="msg-content"> <div class="msg-content">
<h2 class="title">${_("Congratulations, you qualified for a certificate!")}</h2> <h2 class="title">${_("Congratulations, you qualified for a certificate!")}</h2>
......
<%page expression_filter="h" args="cert_status, course_overview, enrollment" /> <%page expression_filter="h" args="cert_status, course_overview, enrollment, reverify_link" />
<%! <%!
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
...@@ -30,7 +30,7 @@ else: ...@@ -30,7 +30,7 @@ else:
<div class="message message-status ${status_css_class} is-shown"> <div class="message message-status ${status_css_class} is-shown">
% if cert_status['status'] == 'processing': % if cert_status['status'] == 'processing':
<p class="message-copy">${_("Final course details are being wrapped up at this time. Your final standing will be available shortly.")}</p> <p class="message-copy">${_("Final course details are being wrapped up at this time. Your final standing will be available shortly.")}</p>
% elif cert_status['status'] in ('generating', 'ready', 'notpassing', 'restricted', 'auditing'): % elif cert_status['status'] in ('generating', 'ready', 'notpassing', 'restricted', 'auditing', 'unverified'):
<p class="message-copy">${_("Your final grade:")} <p class="message-copy">${_("Your final grade:")}
<span class="grade-value">${"{0:.0f}%".format(float(cert_status['grade'])*100)}</span>. <span class="grade-value">${"{0:.0f}%".format(float(cert_status['grade'])*100)}</span>.
% if cert_status['status'] == 'notpassing': % if cert_status['status'] == 'notpassing':
...@@ -48,6 +48,11 @@ else: ...@@ -48,6 +48,11 @@ else:
<p class="message-copy"> <p class="message-copy">
${Text(_("Your {cert_name_long} is being held pending confirmation that the issuance of your {cert_name_short} is in compliance with strict U.S. embargoes on Iran, Cuba, Syria and Sudan. If you think our system has mistakenly identified you as being connected with one of those countries, please let us know by contacting {email}.")).format(email=HTML('<a class="contact-link" href="mailto:{email}">{email}</a>.').format(email=settings.CONTACT_EMAIL), cert_name_short=cert_name_short, cert_name_long=cert_name_long)} ${Text(_("Your {cert_name_long} is being held pending confirmation that the issuance of your {cert_name_short} is in compliance with strict U.S. embargoes on Iran, Cuba, Syria and Sudan. If you think our system has mistakenly identified you as being connected with one of those countries, please let us know by contacting {email}.")).format(email=HTML('<a class="contact-link" href="mailto:{email}">{email}</a>.').format(email=settings.CONTACT_EMAIL), cert_name_short=cert_name_short, cert_name_long=cert_name_long)}
</p> </p>
% elif cert_status['status'] == 'unverified':
<p class="message-copy">
${Text(_("Your certificate was not issued because you do not have a current verified identity with {platform_name}. ")).format(platform_name=settings.PLATFORM_NAME)}
<a href="${reverify_link}"> ${Text(_("Verify your identity now."))}</a>
</p>
% endif % endif
</p> </p>
% endif % endif
......
...@@ -21,6 +21,7 @@ from student.helpers import ( ...@@ -21,6 +21,7 @@ from student.helpers import (
%> %>
<% <%
reverify_link = reverse('verify_student_reverify')
cert_name_short = course_overview.cert_name_short cert_name_short = course_overview.cert_name_short
if cert_name_short == "": if cert_name_short == "":
cert_name_short = settings.CERT_NAME_SHORT cert_name_short = settings.CERT_NAME_SHORT
...@@ -280,7 +281,7 @@ from student.helpers import ( ...@@ -280,7 +281,7 @@ from student.helpers import (
<footer class="wrapper-messages-primary"> <footer class="wrapper-messages-primary">
<ul class="messages-list"> <ul class="messages-list">
% if course_overview.may_certify() and cert_status: % if course_overview.may_certify() and cert_status:
<%include file='_dashboard_certificate_information.html' args='cert_status=cert_status,course_overview=course_overview, enrollment=enrollment'/> <%include file='_dashboard_certificate_information.html' args='cert_status=cert_status,course_overview=course_overview, enrollment=enrollment, reverify_link=reverify_link'/>
% endif % endif
% if credit_status is not None: % if credit_status is not None:
......
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