MICROBA-1055 Listen for course enrollment mode change (#27029)
This commit is contained in:
@@ -7,8 +7,10 @@ import logging
|
||||
from django.db.models.signals import post_save
|
||||
from django.dispatch import receiver
|
||||
|
||||
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 common.djangoapps.student.signals import ENROLLMENT_TRACK_UPDATED
|
||||
from lms.djangoapps.certificates.generation_handler import (
|
||||
generate_allowlist_certificate_task,
|
||||
is_using_certificate_allowlist_and_is_on_allowlist
|
||||
@@ -145,6 +147,22 @@ def _listen_for_id_verification_status_changed(sender, user, **kwargs): # pylin
|
||||
))
|
||||
|
||||
|
||||
@receiver(ENROLLMENT_TRACK_UPDATED)
|
||||
def _listen_for_enrollment_mode_change(sender, user, course_key, mode, **kwargs): # pylint: disable=unused-argument
|
||||
"""
|
||||
Listen for the signal indicating that a user's enrollment mode has changed.
|
||||
|
||||
If possible, grant the user a course certificate. Note that we intentionally do not revoke certificates here, even
|
||||
if the user has moved to the audit track.
|
||||
"""
|
||||
if modes_api.is_eligible_for_certificate(mode):
|
||||
if is_using_certificate_allowlist_and_is_on_allowlist(user, course_key):
|
||||
log.info(f'{course_key} is using allowlist certificates, and the user {user.id} is on its allowlist. '
|
||||
f'Attempt will be made to generate an allowlist certificate since the enrollment mode is now '
|
||||
f'{mode}.')
|
||||
generate_allowlist_certificate_task(user, course_key)
|
||||
|
||||
|
||||
def _fire_ungenerated_certificate_task(user, course_key, expected_verification_status=None):
|
||||
"""
|
||||
Helper function to fire certificate generation task.
|
||||
|
||||
@@ -58,9 +58,9 @@ class SelfGeneratedCertsSignalTest(ModuleStoreTestCase):
|
||||
assert not cert_generation_enabled(course.id)
|
||||
|
||||
|
||||
class WhitelistGeneratedCertificatesTest(ModuleStoreTestCase):
|
||||
class AllowlistGeneratedCertificatesTest(ModuleStoreTestCase):
|
||||
"""
|
||||
Tests for whitelisted student auto-certificate generation
|
||||
Tests for allowlisted student auto-certificate generation
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
@@ -573,3 +573,63 @@ class CertificateGenerationTaskTest(ModuleStoreTestCase):
|
||||
_fire_ungenerated_certificate_task(self.user, self.course.id)
|
||||
task_created = mock_generate_certificate_apply_async.called
|
||||
assert task_created == should_create
|
||||
|
||||
|
||||
@override_waffle_flag(CERTIFICATES_USE_ALLOWLIST, active=True)
|
||||
@override_waffle_flag(AUTO_CERTIFICATE_GENERATION_SWITCH, active=True)
|
||||
class EnrollmentModeChangeCertsTest(ModuleStoreTestCase):
|
||||
"""
|
||||
Tests for certificate generation task firing when the user's enrollment mode changes
|
||||
"""
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.user = UserFactory.create()
|
||||
self.verified_course = CourseFactory.create(
|
||||
self_paced=True,
|
||||
)
|
||||
self.verified_course_key = self.verified_course.id # pylint: disable=no-member
|
||||
self.verified_enrollment = CourseEnrollmentFactory(
|
||||
user=self.user,
|
||||
course_id=self.verified_course_key,
|
||||
is_active=True,
|
||||
mode='verified',
|
||||
)
|
||||
CertificateWhitelistFactory(
|
||||
user=self.user,
|
||||
course_id=self.verified_course_key
|
||||
)
|
||||
|
||||
self.audit_course = CourseFactory.create(self_paced=False)
|
||||
self.audit_course_key = self.audit_course.id # pylint: disable=no-member
|
||||
self.audit_enrollment = CourseEnrollmentFactory(
|
||||
user=self.user,
|
||||
course_id=self.audit_course_key,
|
||||
is_active=True,
|
||||
mode='audit',
|
||||
)
|
||||
CertificateWhitelistFactory(
|
||||
user=self.user,
|
||||
course_id=self.audit_course_key
|
||||
)
|
||||
|
||||
def test_audit_to_verified(self):
|
||||
"""
|
||||
Test that we try to generate a certificate when the user switches from audit to verified
|
||||
"""
|
||||
with mock.patch(
|
||||
'lms.djangoapps.certificates.signals.generate_allowlist_certificate_task',
|
||||
return_value=None
|
||||
) as mock_allowlist_task:
|
||||
self.audit_enrollment.change_mode('verified')
|
||||
mock_allowlist_task.assert_called_with(self.user, self.audit_course_key)
|
||||
|
||||
def test_verified_to_audit(self):
|
||||
"""
|
||||
Test that we do not try to generate a certificate when the user switches from verified to audit
|
||||
"""
|
||||
with mock.patch(
|
||||
'lms.djangoapps.certificates.signals.generate_allowlist_certificate_task',
|
||||
return_value=None
|
||||
) as mock_allowlist_task:
|
||||
self.verified_enrollment.change_mode('audit')
|
||||
mock_allowlist_task.assert_not_called()
|
||||
|
||||
Reference in New Issue
Block a user