Merge pull request #29410 from edx/jhynes/microba-1594_honor-certs-idv

fix: (MICROBA-1594) fix certificate generation logic for enrollment modes that don't require IDV but are cert eligible
This commit is contained in:
Justin Hynes
2021-12-01 14:58:06 -05:00
committed by GitHub
3 changed files with 67 additions and 4 deletions

View File

@@ -9,6 +9,7 @@ cannot be generated, a message is logged and no further action is taken.
import logging
from common.djangoapps.course_modes import api as modes_api
from common.djangoapps.course_modes.models import CourseMode
from common.djangoapps.student.models import CourseEnrollment
from lms.djangoapps.certificates.data import CertificateStatuses
from lms.djangoapps.certificates.models import (
@@ -170,14 +171,21 @@ def _can_generate_certificate_common(user, course_key, enrollment_mode):
log.info(f'{user.id} : {course_key} does not have an enrollment. Certificate cannot be generated.')
return False
if not modes_api.is_eligible_for_certificate(enrollment_mode):
is_eligible_for_cert = modes_api.is_eligible_for_certificate(enrollment_mode)
if not is_eligible_for_cert:
log.info(f'{user.id} : {course_key} has an enrollment mode of {enrollment_mode}, which is not eligible for a '
f'certificate. Certificate cannot be generated.')
return False
# If the IDV check fails we then check if the course-run requires ID verification. Honor and Professional-No-ID
# modes do not require IDV for certificate generation.
if _required_verification_missing(course_key, user):
log.info(f'{user.id} does not have a verified id. Certificate cannot be generated for {course_key}.')
return False
if enrollment_mode not in CourseMode.NON_VERIFIED_MODES:
log.info(f'{user.id} does not have a verified id. Certificate cannot be generated for {course_key}.')
return False
log.info(f'{user.id} : {course_key} is eligible for a certificate without requiring a verified ID. '
'Skipping results of the ID verification check.')
if not _can_generate_certificate_for_status(user, course_key, enrollment_mode):
return False

View File

@@ -5,6 +5,8 @@ import logging
from unittest import mock
import ddt
from django.conf import settings
from django.test import override_settings
from common.djangoapps.course_modes.models import CourseMode
from common.djangoapps.student.tests.factories import CourseEnrollmentFactory, UserFactory
@@ -330,6 +332,31 @@ class AllowlistTests(ModuleStoreTestCase):
assert _set_allowlist_cert_status(u, key, self.enrollment_mode, self.grade) is None
def test_generate_allowlist_honor_cert(self):
"""
Test that verifies we can generate an Honor cert for an Open edX installation configured to support Honor
certificates.
"""
course_run = CourseFactory()
course_run_key = course_run.id # pylint: disable=no-member
enrollment_mode = CourseMode.HONOR
CourseEnrollmentFactory(
user=self.user,
course_id=course_run_key,
is_active=True,
mode=enrollment_mode,
)
CertificateAllowlistFactory.create(course_id=course_run_key, user=self.user)
# Enable Honor Certificates and verify we can generate an AllowList certificate
with override_settings(FEATURES={**settings.FEATURES, 'DISABLE_HONOR_CERTIFICATES': False}):
assert _can_generate_allowlist_certificate(self.user, course_run_key, enrollment_mode)
# Disable Honor Certificates and verify we cannot generate an AllowList certificate
with override_settings(FEATURES={**settings.FEATURES, 'DISABLE_HONOR_CERTIFICATES': True}):
assert not _can_generate_allowlist_certificate(self.user, course_run_key, enrollment_mode)
@mock.patch(INTEGRITY_ENABLED_METHOD, mock.Mock(return_value=False))
@mock.patch(ID_VERIFIED_METHOD, mock.Mock(return_value=True))
@@ -741,3 +768,31 @@ class CertificateTests(ModuleStoreTestCase):
)
assert _set_regular_cert_status(u, key, self.enrollment_mode, self.grade) is None
def test_can_generate_honor_cert(self):
"""
Test that verifies we can generate an Honor cert for an Open edX installation configured to support Honor
certificates.
"""
course_run = CourseFactory()
course_run_key = course_run.id # pylint: disable=no-member
enrollment_mode = CourseMode.HONOR
grade = CourseGradeFactory().read(self.user, course_run)
CourseEnrollmentFactory(
user=self.user,
course_id=course_run_key,
is_active=True,
mode=enrollment_mode,
)
# Enable Honor Certificates and verify we can generate a certificate
with mock.patch(ID_VERIFIED_METHOD, return_value=False), \
mock.patch(PASSING_GRADE_METHOD, return_value=True), \
override_settings(FEATURES={**settings.FEATURES, 'DISABLE_HONOR_CERTIFICATES': False}):
assert _can_generate_regular_certificate(self.user, course_run_key, enrollment_mode, grade)
# Disable Honor Certificates and verify we cannot generate a certificate
with mock.patch(ID_VERIFIED_METHOD, return_value=False), \
mock.patch(PASSING_GRADE_METHOD, return_value=True), \
override_settings(FEATURES={**settings.FEATURES, 'DISABLE_HONOR_CERTIFICATES': True}):
assert not _can_generate_regular_certificate(self.user, course_run_key, enrollment_mode, grade)

View File

@@ -2081,7 +2081,7 @@ class TestCertificateGeneration(InstructorTaskModuleTestCase):
'failed': 0,
'skipped': 2
}
with self.assertNumQueries(77):
with self.assertNumQueries(82):
self.assertCertificatesGenerated(task_input, expected_results)
@ddt.data(