Commit 38a25446 by Awais Qureshi Committed by GitHub

Merge pull request #12773 from edx/tasawer/story/ecom-4199/inconsistancy-of-invalidate-certs

Mark the invalidation entry as inactive If support user re-generates the cert.
parents 132d576e 7ae64b4f
......@@ -9,13 +9,18 @@ from django.conf import settings
from django.core.urlresolvers import reverse
from django.test.utils import override_settings
from certificates.models import (
CertificateInvalidation,
CertificateStatuses,
GeneratedCertificate
)
from certificates.tests.factories import CertificateInvalidationFactory
from opaque_keys.edx.keys import CourseKey
from student.tests.factories import UserFactory
from student.models import CourseEnrollment
from student.roles import GlobalStaff, SupportStaffRole
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory
from certificates.models import GeneratedCertificate, CertificateStatuses
FEATURES_WITH_CERTS_ENABLED = settings.FEATURES.copy()
FEATURES_WITH_CERTS_ENABLED['CERTIFICATES_HTML_VIEW'] = True
......@@ -326,6 +331,33 @@ class CertificateRegenerateTests(CertificateSupportTestCase):
num_certs = GeneratedCertificate.eligible_certificates.filter(user=self.student).count()
self.assertEqual(num_certs, 1)
def test_regenerate_cert_with_invalidated_record(self):
""" If the certificate is marked as invalid, regenerate the certificate
and verify the invalidate entry is deactivated. """
# mark certificate as invalid
self._invalidate_certificate(self.cert)
self.assertInvalidatedCertExists()
# after invalidation certificate status become un-available.
self.assertGeneratedCertExists(
user=self.student, status=CertificateStatuses.unavailable
)
# Should be able to regenerate
response = self._regenerate(
course_key=self.CERT_COURSE_KEY,
username=self.STUDENT_USERNAME
)
self.assertEqual(response.status_code, 200)
self.assertInvalidatedCertDoesNotExist()
# Check that the user's certificate was updated
# Since the student hasn't actually passed the course,
# we'd expect that the certificate status will be "notpassing"
self.assertGeneratedCertExists(
user=self.student, status=CertificateStatuses.notpassing
)
def _regenerate(self, course_key=None, username=None):
"""Call the regeneration end-point and return the response. """
url = reverse("certificates:regenerate_certificate_for_user")
......@@ -339,6 +371,41 @@ class CertificateRegenerateTests(CertificateSupportTestCase):
return self.client.post(url, params)
def _invalidate_certificate(self, certificate):
""" Dry method to mark certificate as invalid. """
CertificateInvalidationFactory.create(
generated_certificate=certificate,
invalidated_by=self.support,
active=True
)
# Invalidate user certificate
certificate.invalidate()
self.assertFalse(certificate.is_valid())
def assertInvalidatedCertExists(self):
""" Dry method to check certificate invalidated entry exists. """
self.assertTrue(
CertificateInvalidation.objects.filter(
generated_certificate__user=self.student, active=True
).exists()
)
def assertInvalidatedCertDoesNotExist(self):
""" Dry method to check certificate invalidated entry does not exists. """
self.assertFalse(
CertificateInvalidation.objects.filter(
generated_certificate__user=self.student, active=True
).exists()
)
def assertGeneratedCertExists(self, user, status):
""" Dry method to check if certificate exists. """
self.assertTrue(
GeneratedCertificate.objects.filter( # pylint: disable=no-member
user=user, status=status
).exists()
)
@ddt.ddt
class CertificateGenerateTests(CertificateSupportTestCase):
......
......@@ -19,15 +19,16 @@ from django.db import transaction
from django.db.models import Q
from django.utils.translation import ugettext as _
from certificates import api
from certificates.models import CertificateInvalidation
from courseware.access import has_access
from instructor_task.api import generate_certificates_for_students
from opaque_keys import InvalidKeyError
from opaque_keys.edx.keys import CourseKey
from xmodule.modulestore.django import modulestore
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
from student.models import User, CourseEnrollment
from courseware.access import has_access
from util.json_request import JsonResponse
from certificates import api
from instructor_task.api import generate_certificates_for_students
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
from xmodule.modulestore.django import modulestore
log = logging.getLogger(__name__)
......@@ -196,7 +197,7 @@ def regenerate_certificate_for_user(request):
# Attempt to regenerate certificates
try:
api.regenerate_user_certificates(params["user"], params["course_key"], course=course)
certificate = api.regenerate_user_certificates(params["user"], params["course_key"], course=course)
except: # pylint: disable=bare-except
# We are pessimistic about the kinds of errors that might get thrown by the
# certificates API. This may be overkill, but we're logging everything so we can
......@@ -208,6 +209,9 @@ def regenerate_certificate_for_user(request):
)
return HttpResponseServerError(_("An unexpected error occurred while regenerating certificates."))
# Deactivate certificate invalidation by setting active to False.
_deactivate_invalidation(certificate)
log.info(
"Started regenerating certificates for user %s in course %s from the support page.",
params["user"].id, params["course_key"]
......@@ -267,3 +271,25 @@ def generate_certificate_for_user(request):
specific_student_id=params["user"].id
)
return HttpResponse(200)
def _deactivate_invalidation(certificate):
"""
Deactivate certificate invalidation by setting active to False.
Arguments:
certificate : The student certificate object
Return:
None
"""
try:
# Fetch CertificateInvalidation object
certificate_invalidation = CertificateInvalidation.objects.get(
generated_certificate=certificate,
active=True
)
# Deactivate certificate invalidation if it was fetched successfully.
certificate_invalidation.deactivate()
except CertificateInvalidation.DoesNotExist: # pylint: disable=bare-except
pass
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