Commit 20800ea5 by Zia Fazal

refactored code to make certificate PDF generation optional

improved coverage

refactoring based on feedback

fixed quality violations

changes based on feedback
parent f118505d
...@@ -6,8 +6,11 @@ rather than importing Django models directly. ...@@ -6,8 +6,11 @@ rather than importing Django models directly.
""" """
import logging import logging
from django.conf import settings
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from xmodule.modulestore.django import modulestore
from certificates.models import ( from certificates.models import (
CertificateStatuses as cert_status, CertificateStatuses as cert_status,
certificate_status_for_student, certificate_status_for_student,
...@@ -21,7 +24,7 @@ from certificates.queue import XQueueCertInterface ...@@ -21,7 +24,7 @@ from certificates.queue import XQueueCertInterface
log = logging.getLogger("edx.certificate") log = logging.getLogger("edx.certificate")
def generate_user_certificates(student, course_key, course=None): def generate_user_certificates(student, course_key, course=None, insecure=False):
""" """
It will add the add-cert request into the xqueue. It will add the add-cert request into the xqueue.
...@@ -36,9 +39,41 @@ def generate_user_certificates(student, course_key, course=None): ...@@ -36,9 +39,41 @@ def generate_user_certificates(student, course_key, course=None):
Keyword Arguments: Keyword Arguments:
course (Course): Optionally provide the course object; if not provided course (Course): Optionally provide the course object; if not provided
it will be loaded. it will be loaded.
insecure - (Boolean)
""" """
xqueue = XQueueCertInterface() xqueue = XQueueCertInterface()
xqueue.add_cert(student, course_key, course=course) if insecure:
xqueue.use_https = False
generate_pdf = not has_html_certificates_enabled(course_key, course)
return xqueue.add_cert(student, course_key, course=course, generate_pdf=generate_pdf)
def regenerate_user_certificates(student, course_key, course=None,
forced_grade=None, template_file=None, insecure=False):
"""
It will add the regen-cert request into the xqueue.
A new record will be created to track the certificate
generation task. If an error occurs while adding the certificate
to the queue, the task will have status 'error'.
Args:
student (User)
course_key (CourseKey)
Keyword Arguments:
course (Course): Optionally provide the course object; if not provided
it will be loaded.
grade_value - The grade string, such as "Distinction"
template_file - The template file used to render this certificate
insecure - (Boolean)
"""
xqueue = XQueueCertInterface()
if insecure:
xqueue.use_https = False
generate_pdf = not has_html_certificates_enabled(course_key, course)
return xqueue.regen_cert(student, course_key, course, forced_grade, template_file, generate_pdf)
def certificate_downloadable_status(student, course_key): def certificate_downloadable_status(student, course_key):
...@@ -156,6 +191,18 @@ def generate_example_certificates(course_key): ...@@ -156,6 +191,18 @@ def generate_example_certificates(course_key):
xqueue.add_example_cert(cert) xqueue.add_example_cert(cert)
def has_html_certificates_enabled(course_key, course=None):
"""
It determines if course has html certificates enabled
"""
html_certificates_enabled = False
if settings.FEATURES.get('CERTIFICATES_HTML_VIEW', False):
course = course if course else modulestore().get_course(course_key, depth=0)
if get_active_web_certificate(course) is not None:
html_certificates_enabled = True
return html_certificates_enabled
def example_certificates_status(course_key): def example_certificates_status(course_key):
"""Check the status of example certificates for a course. """Check the status of example certificates for a course.
......
...@@ -9,9 +9,8 @@ from opaque_keys import InvalidKeyError ...@@ -9,9 +9,8 @@ from opaque_keys import InvalidKeyError
from opaque_keys.edx.keys import CourseKey from opaque_keys.edx.keys import CourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey from opaque_keys.edx.locations import SlashSeparatedCourseKey
from xmodule.modulestore.django import modulestore from xmodule.modulestore.django import modulestore
from certificates.queue import XQueueCertInterface
from certificates.models import BadgeAssertion from certificates.models import BadgeAssertion
from certificates.api import regenerate_user_certificates
LOGGER = logging.getLogger(__name__) LOGGER = logging.getLogger(__name__)
...@@ -107,14 +106,11 @@ class Command(BaseCommand): ...@@ -107,14 +106,11 @@ class Command(BaseCommand):
) )
# Add the certificate request to the queue # Add the certificate request to the queue
xqueue_interface = XQueueCertInterface() ret = regenerate_user_certificates(
if options['insecure']:
xqueue_interface.use_https = False
ret = xqueue_interface.regen_cert(
student, course_id, course=course, student, course_id, course=course,
forced_grade=options['grade_value'], forced_grade=options['grade_value'],
template_file=options['template_file'] template_file=options['template_file'],
insecure=options['insecure']
) )
try: try:
......
...@@ -7,7 +7,7 @@ import datetime ...@@ -7,7 +7,7 @@ import datetime
from pytz import UTC from pytz import UTC
from django.core.management.base import BaseCommand, CommandError from django.core.management.base import BaseCommand, CommandError
from certificates.models import certificate_status_for_student from certificates.models import certificate_status_for_student
from certificates.queue import XQueueCertInterface from certificates.api import generate_user_certificates
from django.contrib.auth.models import User from django.contrib.auth.models import User
from optparse import make_option from optparse import make_option
from opaque_keys import InvalidKeyError from opaque_keys import InvalidKeyError
...@@ -108,9 +108,6 @@ class Command(BaseCommand): ...@@ -108,9 +108,6 @@ class Command(BaseCommand):
courseenrollment__course_id=course_key courseenrollment__course_id=course_key
) )
xq = XQueueCertInterface()
if options['insecure']:
xq.use_https = False
total = enrolled_students.count() total = enrolled_students.count()
count = 0 count = 0
start = datetime.datetime.now(UTC) start = datetime.datetime.now(UTC)
...@@ -144,7 +141,12 @@ class Command(BaseCommand): ...@@ -144,7 +141,12 @@ class Command(BaseCommand):
if not options['noop']: if not options['noop']:
# Add the certificate request to the queue # Add the certificate request to the queue
ret = xq.add_cert(student, course_key, course=course) ret = generate_user_certificates(
student,
course_key,
course=course,
insecure=options['insecure']
)
if ret == 'generating': if ret == 'generating':
LOGGER.info( LOGGER.info(
......
...@@ -104,7 +104,7 @@ class XQueueCertInterface(object): ...@@ -104,7 +104,7 @@ class XQueueCertInterface(object):
self.restricted = UserProfile.objects.filter(allow_certificate=False) self.restricted = UserProfile.objects.filter(allow_certificate=False)
self.use_https = True self.use_https = True
def regen_cert(self, student, course_id, course=None, forced_grade=None, template_file=None): def regen_cert(self, student, course_id, course=None, forced_grade=None, template_file=None, generate_pdf=True):
"""(Re-)Make certificate for a particular student in a particular course """(Re-)Make certificate for a particular student in a particular course
Arguments: Arguments:
...@@ -154,7 +154,7 @@ class XQueueCertInterface(object): ...@@ -154,7 +154,7 @@ class XQueueCertInterface(object):
except GeneratedCertificate.DoesNotExist: except GeneratedCertificate.DoesNotExist:
pass pass
return self.add_cert(student, course_id, course, forced_grade, template_file) return self.add_cert(student, course_id, course, forced_grade, template_file, generate_pdf)
def del_cert(self, student, course_id): def del_cert(self, student, course_id):
...@@ -173,7 +173,9 @@ class XQueueCertInterface(object): ...@@ -173,7 +173,9 @@ class XQueueCertInterface(object):
raise NotImplementedError raise NotImplementedError
def add_cert(self, student, course_id, course=None, forced_grade=None, template_file=None, title='None'): # pylint: disable=too-many-statements
def add_cert(self, student, course_id, course=None, forced_grade=None, template_file=None,
title='None', generate_pdf=True):
""" """
Request a new certificate for a student. Request a new certificate for a student.
...@@ -183,6 +185,7 @@ class XQueueCertInterface(object): ...@@ -183,6 +185,7 @@ class XQueueCertInterface(object):
forced_grade - a string indicating a grade parameter to pass with forced_grade - a string indicating a grade parameter to pass with
the certificate request. If this is given, grading the certificate request. If this is given, grading
will be skipped. will be skipped.
generate_pdf - Boolean should a message be sent in queue to generate certificate PDF
Will change the certificate status to 'generating'. Will change the certificate status to 'generating'.
...@@ -340,35 +343,36 @@ class XQueueCertInterface(object): ...@@ -340,35 +343,36 @@ class XQueueCertInterface(object):
} }
if template_file: if template_file:
contents['template_pdf'] = template_file contents['template_pdf'] = template_file
new_status = status.generating new_status = status.generating if generate_pdf else status.downloadable
cert.status = new_status cert.status = new_status
cert.save() cert.save()
try: if generate_pdf:
self._send_to_xqueue(contents, key) try:
except XQueueAddToQueueError as exc: self._send_to_xqueue(contents, key)
new_status = ExampleCertificate.STATUS_ERROR except XQueueAddToQueueError as exc:
cert.status = new_status new_status = ExampleCertificate.STATUS_ERROR
cert.error_reason = unicode(exc) cert.status = new_status
cert.save() cert.error_reason = unicode(exc)
LOGGER.critical( cert.save()
( LOGGER.critical(
u"Could not add certificate task to XQueue. " (
u"The course was '%s' and the student was '%s'." u"Could not add certificate task to XQueue. "
u"The certificate task status has been marked as 'error' " u"The course was '%s' and the student was '%s'."
u"and can be re-submitted with a management command." u"The certificate task status has been marked as 'error' "
), student.id, course_id u"and can be re-submitted with a management command."
) ), course_id, student.id
else: )
LOGGER.info( else:
( LOGGER.info(
u"The certificate status has been set to '%s'. " (
u"Sent a certificate grading task to the XQueue " u"The certificate status has been set to '%s'. "
u"with the key '%s'. " u"Sent a certificate grading task to the XQueue "
), u"with the key '%s'. "
key, ),
new_status new_status,
) key
)
else: else:
new_status = status.notpassing new_status = status.notpassing
cert.status = new_status cert.status = new_status
......
...@@ -4,6 +4,7 @@ import ddt ...@@ -4,6 +4,7 @@ import ddt
from django.test import TestCase, RequestFactory from django.test import TestCase, RequestFactory
from django.test.utils import override_settings from django.test.utils import override_settings
from django.conf import settings
from mock import patch from mock import patch
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
...@@ -25,6 +26,9 @@ from certificates.models import ( ...@@ -25,6 +26,9 @@ from certificates.models import (
from certificates.queue import XQueueCertInterface, XQueueAddToQueueError from certificates.queue import XQueueCertInterface, XQueueAddToQueueError
from certificates.tests.factories import GeneratedCertificateFactory from certificates.tests.factories import GeneratedCertificateFactory
FEATURES_WITH_CERTS_ENABLED = settings.FEATURES.copy()
FEATURES_WITH_CERTS_ENABLED['CERTIFICATES_HTML_VIEW'] = True
@attr('shard_1') @attr('shard_1')
class CertificateDownloadableStatusTests(ModuleStoreTestCase): class CertificateDownloadableStatusTests(ModuleStoreTestCase):
...@@ -134,7 +138,7 @@ class GenerateUserCertificatesTest(ModuleStoreTestCase): ...@@ -134,7 +138,7 @@ class GenerateUserCertificatesTest(ModuleStoreTestCase):
# Verify that the certificate has status 'generating' # Verify that the certificate has status 'generating'
cert = GeneratedCertificate.objects.get(user=self.student, course_id=self.course.id) cert = GeneratedCertificate.objects.get(user=self.student, course_id=self.course.id)
self.assertEqual(cert.status, 'generating') self.assertEqual(cert.status, CertificateStatuses.generating)
def test_xqueue_submit_task_error(self): def test_xqueue_submit_task_error(self):
with self._mock_passing_grade(): with self._mock_passing_grade():
...@@ -146,6 +150,19 @@ class GenerateUserCertificatesTest(ModuleStoreTestCase): ...@@ -146,6 +150,19 @@ class GenerateUserCertificatesTest(ModuleStoreTestCase):
self.assertEqual(cert.status, 'error') self.assertEqual(cert.status, 'error')
self.assertIn(self.ERROR_REASON, cert.error_reason) self.assertIn(self.ERROR_REASON, cert.error_reason)
@override_settings(FEATURES=FEATURES_WITH_CERTS_ENABLED)
def test_new_cert_requests_returns_generating_for_html_certificate(self):
"""
Test no message sent to Xqueue if HTML certificate view is enabled
"""
self._setup_course_certificate()
with self._mock_passing_grade():
certs_api.generate_user_certificates(self.student, self.course.id)
# Verify that the certificate has status 'downloadable'
cert = GeneratedCertificate.objects.get(user=self.student, course_id=self.course.id)
self.assertEqual(cert.status, CertificateStatuses.downloadable)
@contextmanager @contextmanager
def _mock_passing_grade(self): def _mock_passing_grade(self):
"""Mock the grading function to always return a passing grade. """ """Mock the grading function to always return a passing grade. """
...@@ -166,6 +183,26 @@ class GenerateUserCertificatesTest(ModuleStoreTestCase): ...@@ -166,6 +183,26 @@ class GenerateUserCertificatesTest(ModuleStoreTestCase):
yield mock_send_to_queue yield mock_send_to_queue
def _setup_course_certificate(self):
"""
Creates certificate configuration for course
"""
certificates = [
{
'id': 1,
'name': 'Test Certificate Name',
'description': 'Test Certificate Description',
'course_title': 'tes_course_title',
'org_logo_path': '/t4x/orgX/testX/asset/org-logo.png',
'signatories': [],
'version': 1,
'is_active': True
}
]
self.course.certificates = {'certificates': certificates}
self.course.save()
self.store.update_item(self.course, self.user.id)
@attr('shard_1') @attr('shard_1')
@ddt.ddt @ddt.ddt
......
"""Tests for the resubmit_error_certificates management command. """ """Tests for the resubmit_error_certificates management command. """
import ddt import ddt
from contextlib import contextmanager
from django.core.management.base import CommandError from django.core.management.base import CommandError
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from django.test.utils import override_settings from django.test.utils import override_settings
...@@ -10,7 +11,7 @@ from certificates.tests.factories import BadgeAssertionFactory ...@@ -10,7 +11,7 @@ from certificates.tests.factories import BadgeAssertionFactory
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory, check_mongo_calls from xmodule.modulestore.tests.factories import CourseFactory, check_mongo_calls
from student.tests.factories import UserFactory, CourseEnrollmentFactory from student.tests.factories import UserFactory, CourseEnrollmentFactory
from certificates.management.commands import resubmit_error_certificates, regenerate_user from certificates.management.commands import resubmit_error_certificates, regenerate_user, ungenerated_certs
from certificates.models import GeneratedCertificate, CertificateStatuses, BadgeAssertion from certificates.models import GeneratedCertificate, CertificateStatuses, BadgeAssertion
...@@ -157,7 +158,7 @@ class RegenerateCertificatesTest(CertificateManagementTest): ...@@ -157,7 +158,7 @@ class RegenerateCertificatesTest(CertificateManagementTest):
self.course = self.courses[0] self.course = self.courses[0]
@override_settings(CERT_QUEUE='test-queue') @override_settings(CERT_QUEUE='test-queue')
@patch('certificates.management.commands.regenerate_user.XQueueCertInterface', spec=True) @patch('certificates.api.XQueueCertInterface', spec=True)
def test_clear_badge(self, xqueue): def test_clear_badge(self, xqueue):
""" """
Given that I have a user with a badge Given that I have a user with a badge
...@@ -174,6 +175,72 @@ class RegenerateCertificatesTest(CertificateManagementTest): ...@@ -174,6 +175,72 @@ class RegenerateCertificatesTest(CertificateManagementTest):
grade_value=None grade_value=None
) )
xqueue.return_value.regen_cert.assert_called_with( xqueue.return_value.regen_cert.assert_called_with(
self.user, key, course=self.course, forced_grade=None, template_file=None self.user, key, self.course, None, None, True
) )
self.assertFalse(BadgeAssertion.objects.filter(user=self.user, course_id=key)) self.assertFalse(BadgeAssertion.objects.filter(user=self.user, course_id=key))
@override_settings(CERT_QUEUE='test-queue')
@patch('capa.xqueue_interface.XQueueInterface.send_to_queue', spec=True)
def test_regenerating_certificate(self, mock_send_to_queue):
"""
Given that I have a user who has not passed course
If I run regeneration for that user
Then certificate generation will be not be requested
"""
key = self.course.location.course_key
self._create_cert(key, self.user, CertificateStatuses.downloadable)
self._run_command(
username=self.user.email, course=unicode(key), noop=False, insecure=True, template_file=None,
grade_value=None
)
certificate = GeneratedCertificate.objects.get(
user=self.user,
course_id=key
)
self.assertEqual(certificate.status, CertificateStatuses.notpassing)
self.assertFalse(mock_send_to_queue.called)
@attr('shard_1')
class UngenerateCertificatesTest(CertificateManagementTest):
"""
Tests for generating certificates.
"""
command = ungenerated_certs
def setUp(self):
"""
We just need one course here.
"""
super(UngenerateCertificatesTest, self).setUp()
self.course = self.courses[0]
@override_settings(CERT_QUEUE='test-queue')
@patch('capa.xqueue_interface.XQueueInterface.send_to_queue', spec=True)
def test_ungenerated_certificate(self, mock_send_to_queue):
"""
Given that I have ended course
If I run ungenerated certs command
Then certificates should be generated for all users who passed course
"""
mock_send_to_queue.return_value = (0, "Successfully queued")
key = self.course.location.course_key
self._create_cert(key, self.user, CertificateStatuses.unavailable)
with self._mock_passing_grade():
self._run_command(
course=unicode(key), noop=False, insecure=True, force=False
)
self.assertTrue(mock_send_to_queue.called)
certificate = GeneratedCertificate.objects.get(
user=self.user,
course_id=key
)
self.assertEqual(certificate.status, CertificateStatuses.generating)
@contextmanager
def _mock_passing_grade(self):
"""Mock the grading function to always return a passing grade. """
symbol = 'courseware.grades.grade'
with patch(symbol) as mock_grade:
mock_grade.return_value = {'grade': 'Pass', 'percent': 0.75}
yield
...@@ -54,6 +54,17 @@ class XQueueCertInterfaceAddCertificateTest(ModuleStoreTestCase): ...@@ -54,6 +54,17 @@ class XQueueCertInterfaceAddCertificateTest(ModuleStoreTestCase):
actual_header = json.loads(kwargs['header']) actual_header = json.loads(kwargs['header'])
self.assertIn('https://edx.org/update_certificate?key=', actual_header['lms_callback_url']) self.assertIn('https://edx.org/update_certificate?key=', actual_header['lms_callback_url'])
def test_no_create_action_in_queue_for_html_view_certs(self):
"""
Tests there is no certificate create message in the queue if generate_pdf is False
"""
with patch('courseware.grades.grade', Mock(return_value={'grade': 'Pass', 'percent': 0.75})):
with patch.object(XQueueInterface, 'send_to_queue') as mock_send:
self.xqueue.add_cert(self.user, self.course.id, generate_pdf=False)
# Verify that add_cert method does not add message to queue
self.assertFalse(mock_send.called)
@attr('shard_1') @attr('shard_1')
@override_settings(CERT_QUEUE='certificates') @override_settings(CERT_QUEUE='certificates')
......
...@@ -4,6 +4,7 @@ import json ...@@ -4,6 +4,7 @@ import json
import ddt import ddt
from uuid import uuid4 from uuid import uuid4
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from mock import patch
from django.conf import settings from django.conf import settings
from django.core.cache import cache from django.core.cache import cache
...@@ -14,13 +15,20 @@ from django.test.utils import override_settings ...@@ -14,13 +15,20 @@ from django.test.utils import override_settings
from opaque_keys.edx.locator import CourseLocator from opaque_keys.edx.locator import CourseLocator
from openedx.core.lib.tests.assertions.events import assert_event_matches from openedx.core.lib.tests.assertions.events import assert_event_matches
from student.tests.factories import UserFactory from student.tests.factories import UserFactory, CourseEnrollmentFactory
from track.tests import EventTrackingTestCase from track.tests import EventTrackingTestCase
from xmodule.modulestore.tests.factories import CourseFactory from xmodule.modulestore.tests.factories import CourseFactory
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from certificates.api import get_certificate_url from certificates.api import get_certificate_url
from certificates.models import ExampleCertificateSet, ExampleCertificate, GeneratedCertificate, BadgeAssertion from certificates.models import (
ExampleCertificateSet,
ExampleCertificate,
GeneratedCertificate,
BadgeAssertion,
CertificateStatuses
)
from certificates.tests.factories import ( from certificates.tests.factories import (
CertificateHtmlViewConfigurationFactory, CertificateHtmlViewConfigurationFactory,
LinkedInAddToProfileConfigurationFactory, LinkedInAddToProfileConfigurationFactory,
...@@ -210,6 +218,10 @@ class CertificatesViewsTests(ModuleStoreTestCase, EventTrackingTestCase): ...@@ -210,6 +218,10 @@ class CertificatesViewsTests(ModuleStoreTestCase, EventTrackingTestCase):
mode='honor', mode='honor',
name=self.user.profile.name, name=self.user.profile.name,
) )
CourseEnrollmentFactory.create(
user=self.user,
course_id=self.course_id
)
CertificateHtmlViewConfigurationFactory.create() CertificateHtmlViewConfigurationFactory.create()
LinkedInAddToProfileConfigurationFactory.create() LinkedInAddToProfileConfigurationFactory.create()
...@@ -453,6 +465,31 @@ class CertificatesViewsTests(ModuleStoreTestCase, EventTrackingTestCase): ...@@ -453,6 +465,31 @@ class CertificatesViewsTests(ModuleStoreTestCase, EventTrackingTestCase):
self.get_event() self.get_event()
) )
@override_settings(FEATURES=FEATURES_WITH_CERTS_DISABLED)
def test_request_certificate_without_passing(self):
self.cert.status = CertificateStatuses.unavailable
self.cert.save()
request_certificate_url = reverse('certificates.views.request_certificate')
response = self.client.post(request_certificate_url, {'course_id': unicode(self.course.id)})
self.assertEqual(response.status_code, 200)
response_json = json.loads(response.content)
self.assertEqual(CertificateStatuses.notpassing, response_json['add_status'])
@override_settings(FEATURES=FEATURES_WITH_CERTS_DISABLED)
@override_settings(CERT_QUEUE='test-queue')
def test_request_certificate_after_passing(self):
self.cert.status = CertificateStatuses.unavailable
self.cert.save()
request_certificate_url = reverse('certificates.views.request_certificate')
with patch('capa.xqueue_interface.XQueueInterface.send_to_queue') as mock_queue:
mock_queue.return_value = (0, "Successfully queued")
with patch('courseware.grades.grade') as mock_grade:
mock_grade.return_value = {'grade': 'Pass', 'percent': 0.75}
response = self.client.post(request_certificate_url, {'course_id': unicode(self.course.id)})
self.assertEqual(response.status_code, 200)
response_json = json.loads(response.content)
self.assertEqual(CertificateStatuses.generating, response_json['add_status'])
class TrackShareRedirectTest(ModuleStoreTestCase, EventTrackingTestCase): class TrackShareRedirectTest(ModuleStoreTestCase, EventTrackingTestCase):
""" """
......
...@@ -16,7 +16,7 @@ from django.views.decorators.csrf import csrf_exempt ...@@ -16,7 +16,7 @@ from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST from django.views.decorators.http import require_POST
from capa.xqueue_interface import XQUEUE_METRIC_NAME from capa.xqueue_interface import XQUEUE_METRIC_NAME
from certificates.api import get_active_web_certificate, get_certificate_url from certificates.api import get_active_web_certificate, get_certificate_url, generate_user_certificates
from certificates.models import ( from certificates.models import (
certificate_status_for_student, certificate_status_for_student,
CertificateStatuses, CertificateStatuses,
...@@ -56,7 +56,6 @@ def request_certificate(request): ...@@ -56,7 +56,6 @@ def request_certificate(request):
""" """
if request.method == "POST": if request.method == "POST":
if request.user.is_authenticated(): if request.user.is_authenticated():
xqci = XQueueCertInterface()
username = request.user.username username = request.user.username
student = User.objects.get(username=username) student = User.objects.get(username=username)
course_key = SlashSeparatedCourseKey.from_deprecated_string(request.POST.get('course_id')) course_key = SlashSeparatedCourseKey.from_deprecated_string(request.POST.get('course_id'))
...@@ -66,7 +65,7 @@ def request_certificate(request): ...@@ -66,7 +65,7 @@ def request_certificate(request):
if status in [CertificateStatuses.unavailable, CertificateStatuses.notpassing, CertificateStatuses.error]: if status in [CertificateStatuses.unavailable, CertificateStatuses.notpassing, CertificateStatuses.error]:
log_msg = u'Grading and certification requested for user %s in course %s via /request_certificate call' log_msg = u'Grading and certification requested for user %s in course %s via /request_certificate call'
logger.info(log_msg, username, course_key) logger.info(log_msg, username, course_key)
status = xqci.add_cert(student, course_key, course=course) status = generate_user_certificates(student, course_key, course=course)
return HttpResponse(json.dumps({'add_status': status}), mimetype='application/json') return HttpResponse(json.dumps({'add_status': status}), mimetype='application/json')
return HttpResponse(json.dumps({'add_status': 'ERRORANONYMOUSUSER'}), mimetype='application/json') return HttpResponse(json.dumps({'add_status': 'ERRORANONYMOUSUSER'}), mimetype='application/json')
......
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