Commit 19ab698f by Awais

ECOM-1284 enabling re-generate certs.

parent 6eaeddc3
...@@ -206,7 +206,8 @@ class XQueueCertInterface(object): ...@@ -206,7 +206,8 @@ class XQueueCertInterface(object):
status.unavailable, status.unavailable,
status.deleted, status.deleted,
status.error, status.error,
status.notpassing status.notpassing,
status.downloadable
] ]
cert_status = certificate_status_for_student(student, course_id)['status'] cert_status = certificate_status_for_student(student, course_id)['status']
...@@ -257,13 +258,23 @@ class XQueueCertInterface(object): ...@@ -257,13 +258,23 @@ class XQueueCertInterface(object):
if forced_grade: if forced_grade:
grade['grade'] = forced_grade grade['grade'] = forced_grade
cert, __ = GeneratedCertificate.objects.get_or_create(user=student, course_id=course_id) cert, created = GeneratedCertificate.objects.get_or_create(user=student, course_id=course_id)
if not created:
LOGGER.info(
u"Regenerate certificate for user %s in course %s "
u"with status %s, download_uuid %s, "
u"and download_url %s",
cert.user.id, unicode(cert.course_id),
cert.status, cert.download_uuid, cert.download_url
)
cert.mode = cert_mode cert.mode = cert_mode
cert.user = student cert.user = student
cert.grade = grade['percent'] cert.grade = grade['percent']
cert.course_id = course_id cert.course_id = course_id
cert.name = profile_name cert.name = profile_name
cert.download_url = ''
# Strip HTML from grade range label # Strip HTML from grade range label
grade_contents = grade.get('grade', None) grade_contents = grade.get('grade', None)
try: try:
......
...@@ -937,21 +937,44 @@ class GenerateUserCertTests(ModuleStoreTestCase): ...@@ -937,21 +937,44 @@ class GenerateUserCertTests(ModuleStoreTestCase):
) )
resp = self.client.post(self.url) resp = self.client.post(self.url)
self.assertEqual(resp.status_code, HttpResponseBadRequest.status_code) self.assertEqual(resp.status_code, HttpResponseBadRequest.status_code)
self.assertIn("Certificate is already being created.", resp.content) self.assertIn("Certificate is being created.", resp.content)
@patch('courseware.grades.grade', Mock(return_value={'grade': 'Pass', 'percent': 0.75})) @patch('courseware.grades.grade', Mock(return_value={'grade': 'Pass', 'percent': 0.75}))
@override_settings(CERT_QUEUE='certificates', SEGMENT_IO_LMS_KEY="foobar", FEATURES={'SEGMENT_IO_LMS': True})
def test_user_with_passing_existing_downloadable_cert(self): def test_user_with_passing_existing_downloadable_cert(self):
# If user has passing grade but also has existing downloadable cert # If user has already downloadable certificate then he can again re-generate the
# then json will return cert generating message with bad request code # the cert.
GeneratedCertificateFactory.create( GeneratedCertificateFactory.create(
user=self.student, user=self.student,
course_id=self.course.id, course_id=self.course.id,
status=CertificateStatuses.downloadable, status=CertificateStatuses.downloadable,
mode='verified' mode='verified'
) )
resp = self.client.post(self.url)
self.assertEqual(resp.status_code, HttpResponseBadRequest.status_code) analytics_patcher = patch('courseware.views.analytics')
self.assertIn("Certificate has already been created.", resp.content) mock_tracker = analytics_patcher.start()
self.addCleanup(analytics_patcher.stop)
with patch('capa.xqueue_interface.XQueueInterface.send_to_queue') as mock_send_to_queue:
mock_send_to_queue.return_value = (0, "Successfully queued")
resp = self.client.post(self.url)
self.assertEqual(resp.status_code, 200)
#Verify Google Analytics event fired after generating certificate
mock_tracker.track.assert_called_once_with( # pylint: disable=no-member
self.student.id, # pylint: disable=no-member
'edx.bi.user.certificate.generate',
{
'category': 'certificates',
'label': unicode(self.course.id)
},
context={
'Google Analytics':
{'clientId': None}
}
)
mock_tracker.reset_mock()
def test_user_with_non_existing_course(self): def test_user_with_non_existing_course(self):
# If try to access a course with valid key pattern then it will return # If try to access a course with valid key pattern then it will return
......
...@@ -1348,10 +1348,8 @@ def generate_user_cert(request, course_id): ...@@ -1348,10 +1348,8 @@ def generate_user_cert(request, course_id):
certificate_status = certs_api.certificate_downloadable_status(student, course.id) certificate_status = certs_api.certificate_downloadable_status(student, course.id)
if certificate_status["is_downloadable"]: if certificate_status["is_generating"]:
return HttpResponseBadRequest(_("Certificate has already been created.")) return HttpResponseBadRequest(_("Certificate is being created."))
elif certificate_status["is_generating"]:
return HttpResponseBadRequest(_("Certificate is already being created."))
else: else:
# If the certificate is not already in-process or completed, # If the certificate is not already in-process or completed,
# then create a new certificate generation task. # then create a new certificate generation task.
......
$(document).ready(function() { $(document).ready(function() {
'use strict'; 'use strict';
$("#btn_generate_cert").click(function(e){ $(".generate_certs").click(function(e){
e.preventDefault(); e.preventDefault();
var post_url = $("#btn_generate_cert").data("endpoint"); var post_url = $(".generate_certs").data("endpoint");
$('#btn_generate_cert').prop("disabled", true); $(".generate_certs").attr("disabled", true).addClass('is-disabled').attr('aria-disabled', true);
$.ajax({ $.ajax({
type: "POST", type: "POST",
url: post_url, url: post_url,
...@@ -14,7 +14,7 @@ $(document).ready(function() { ...@@ -14,7 +14,7 @@ $(document).ready(function() {
}, },
error: function(jqXHR, textStatus, errorThrown) { error: function(jqXHR, textStatus, errorThrown) {
$('#errors-info').html(jqXHR.responseText); $('#errors-info').html(jqXHR.responseText);
$('#btn_generate_cert').prop("disabled", false); $(".generate_certs").attr("disabled", false).removeClass('is-disabled').attr('aria-disabled', false);
} }
}); });
}); });
......
<%! from django.utils.translation import ugettext as _ %> <%!
from django.utils.translation import ugettext as _
from django.core.urlresolvers import reverse
%>
<%inherit file="/main.html" /> <%inherit file="/main.html" />
<%namespace name='static' file='/static_content.html'/> <%namespace name='static' file='/static_content.html'/>
...@@ -59,10 +62,16 @@ from django.utils.http import urlquote_plus ...@@ -59,10 +62,16 @@ from django.utils.http import urlquote_plus
<div class="auto-cert-message" id="course-success"> <div class="auto-cert-message" id="course-success">
<div class="has-actions"> <div class="has-actions">
%if passed: %if passed:
% if is_downloadable and download_url: % if is_downloadable and download_url:
<% post_url = reverse('generate_user_cert', args=[unicode(course.id)]) %>
<div class="msg-content"> <div class="msg-content">
<h2 class="title">${_("Your certificate is available")}</h2> <h2 class="title">${_("Your certificate is available")}</h2>
<p class="copy">${_("You can now download your certificate as a PDF. If you keep working and receive a higher grade, you can request an updated certificate.")}</p> <p class="copy">${_(
"You can now download your certificate as a PDF. If you keep working and receive a higher grade,you can request an {link_start} updated certificate {link_end}.").format(
link_start=u"<a class='generate_certs' href='#' data-endpoint={}>".format(post_url) ,link_end=u"</a>")}
</p>
</div> </div>
<div class="msg-actions"> <div class="msg-actions">
<a class="btn" href="${download_url}" target="_blank" title="${_('PDF will open in a new browser window or tab.')}"> <a class="btn" href="${download_url}" target="_blank" title="${_('PDF will open in a new browser window or tab.')}">
...@@ -81,7 +90,7 @@ from django.utils.http import urlquote_plus ...@@ -81,7 +90,7 @@ from django.utils.http import urlquote_plus
<p class="copy">${_("You can keep working for a higher grade, or request your certificate now.")}</p> <p class="copy">${_("You can keep working for a higher grade, or request your certificate now.")}</p>
</div> </div>
<div class="msg-actions"> <div class="msg-actions">
<button class="btn" data-endpoint="${reverse('generate_user_cert', args=[unicode(course.id)])}" id="btn_generate_cert">${_('Request Certificate')}</button> <button class="btn generate_certs" data-endpoint="${reverse('generate_user_cert', args=[unicode(course.id)])}" id="btn_generate_cert">${_('Request Certificate')}</button>
</div> </div>
%endif %endif
</div> </div>
......
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