def _listen_for_id_verification_status_changed(sender, user, **kwargs): # pylint: disable=unused-argument """ Catches a track change signal, determines user status, calls fire_ungenerated_certificate_task for passing grades """ if not auto_certificate_generation_enabled(): return user_enrollments = CourseEnrollment.enrollments_for_user(user=user) grade_factory = CourseGradeFactory() expected_verification_status = IDVerificationService.user_status(user) expected_verification_status = expected_verification_status['status'] for enrollment in user_enrollments: if grade_factory.read(user=user, course=enrollment.course_overview).passed: if fire_ungenerated_certificate_task(user, enrollment.course_id, expected_verification_status): message = ( u'Certificate generation task initiated for {user} : {course} via track change ' + u'with verification status of {status}' ) log.info(message.format( user=user.id, course=enrollment.course_id, status=expected_verification_status ))
def _listen_for_id_verification_status_changed(sender, user, **kwargs): # pylint: disable=unused-argument """ Listen for a signal indicating that the user's id verification status has changed. If needed, generate a certificate task. """ if not auto_certificate_generation_enabled(): return user_enrollments = CourseEnrollment.enrollments_for_user(user=user) grade_factory = CourseGradeFactory() expected_verification_status = IDVerificationService.user_status(user) expected_verification_status = expected_verification_status['status'] for enrollment in user_enrollments: if can_generate_certificate_task(user, enrollment.course_id): log.info( f'{enrollment.course_id} is using V2 certificates. Attempt will be made to generate a V2 ' f'certificate for {user.id}. Id verification status is {expected_verification_status}' ) generate_certificate_task(user, enrollment.course_id) elif grade_factory.read(user=user, course=enrollment.course_overview).passed: if _fire_ungenerated_certificate_task( user, enrollment.course_id, expected_verification_status): message = ( 'Certificate generation task initiated for {user} : {course} via track change ' + 'with verification status of {status}') log.info( message.format(user=user.id, course=enrollment.course_id, status=expected_verification_status))
def _listen_for_id_verification_status_changed(sender, user, **kwargs): # pylint: disable=unused-argument """ Catches a track change signal, determines user status, calls _fire_ungenerated_certificate_task for passing grades """ if not auto_certificate_generation_enabled(): return user_enrollments = CourseEnrollment.enrollments_for_user(user=user) grade_factory = CourseGradeFactory() expected_verification_status = IDVerificationService.user_status(user) expected_verification_status = expected_verification_status['status'] for enrollment in user_enrollments: if is_using_certificate_allowlist_and_is_on_allowlist( user, enrollment.course_id): log.info( f'{enrollment.course_id} is using allowlist certificates, and the user {user.id} is on its ' f'allowlist. Attempt will be made to generate an allowlist certificate. Id verification status ' f'is {expected_verification_status}') generate_allowlist_certificate_task(user, enrollment.course_id) elif grade_factory.read(user=user, course=enrollment.course_overview).passed: if _fire_ungenerated_certificate_task( user, enrollment.course_id, expected_verification_status): message = ( u'Certificate generation task initiated for {user} : {course} via track change ' + u'with verification status of {status}') log.info( message.format(user=user.id, course=enrollment.course_id, status=expected_verification_status))
def test_auto_certificate_generation_enabled(self, self_paced_enabled, instructor_paced_enabled): expected_value = self_paced_enabled or instructor_paced_enabled with configure_waffle_namespace(self_paced_enabled, instructor_paced_enabled): self.assertEqual(expected_value, api.auto_certificate_generation_enabled())
def listen_for_passing_grade(sender, user, course_id, **kwargs): # pylint: disable=unused-argument """ Listen for a signal indicating that the user has passed a course run. If needed, generate a certificate task. """ if not auto_certificate_generation_enabled(): return if can_generate_certificate_task(user, course_id): cert = GeneratedCertificate.certificate_for_student(user, course_id) if cert is not None and CertificateStatuses.is_passing_status( cert.status): log.info( f'{course_id} is using V2 certificates, and the cert status is already passing for user ' f'{user.id}. Passing grade signal will be ignored.') return log.info( f'{course_id} is using V2 certificates. Attempt will be made to generate a V2 certificate for ' f'{user.id} as a passing grade was received.') return generate_certificate_task(user, course_id) if _fire_ungenerated_certificate_task(user, course_id): log.info( 'Certificate generation task initiated for {user} : {course} via passing grade' .format(user=user.id, course=course_id))
def _listen_for_certificate_whitelist_append(sender, instance, **kwargs): # lint-amnesty, pylint: disable=missing-function-docstring, unused-argument if not auto_certificate_generation_enabled(): return if fire_ungenerated_certificate_task(instance.user, instance.course_id): log.info( u'Certificate generation task initiated for {user} : {course} via whitelist' .format(user=instance.user.id, course=instance.course_id))
def _listen_for_certificate_whitelist_append(sender, instance, **kwargs): # pylint: disable=unused-argument course = CourseOverview.get_from_id(instance.course_id) if not auto_certificate_generation_enabled(): return fire_ungenerated_certificate_task(instance.user, instance.course_id) log.info( u'Certificate generation task initiated for {user} : {course} via whitelist' .format(user=instance.user.id, course=instance.course_id))
def _listen_for_certificate_whitelist_append(sender, instance, **kwargs): # pylint: disable=unused-argument course = CourseOverview.get_from_id(instance.course_id) if not auto_certificate_generation_enabled(): return fire_ungenerated_certificate_task(instance.user, instance.course_id) log.info(u'Certificate generation task initiated for {user} : {course} via whitelist'.format( user=instance.user.id, course=instance.course_id ))
def _listen_for_certificate_whitelist_append(sender, instance, **kwargs): # pylint: disable=unused-argument """ Listen for a user being added to or modified on the whitelist (allowlist) """ if not auto_certificate_generation_enabled(): return if fire_ungenerated_certificate_task(instance.user, instance.course_id): log.info( u'Certificate generation task initiated for {user} : {course} via whitelist' .format(user=instance.user.id, course=instance.course_id))
def _can_generate_allowlist_certificate(user, course_key): """ Check if an allowlist certificate can be generated (created if it doesn't already exist, or updated if it does exist) for this user, in this course run. """ if not is_using_certificate_allowlist(course_key): # This course run is not using the allowlist feature log.info( f'{course_key} is not using the certificate allowlist. Allowlist certificate cannot be generated' f'for {user.id}.') return False if not _is_on_certificate_allowlist(user, course_key): log.info( f'{user.id} : {course_key} is not on the certificate allowlist. Allowlist certificate cannot be ' f'generated.') return False if not auto_certificate_generation_enabled(): # Automatic certificate generation is globally disabled log.info( f'Automatic certificate generation is globally disabled. Allowlist certificate cannot be generated' f'for {user.id} : {course_key}.') return False if CertificateInvalidation.has_certificate_invalidation(user, course_key): # The invalidation list overrides the allowlist log.info( f'{user.id} : {course_key} is on the certificate invalidation list. Allowlist certificate cannot be ' f'generated.') return False enrollment_mode, __ = CourseEnrollment.enrollment_mode_for_user( user, course_key) if enrollment_mode is None: log.info( f'{user.id} : {course_key} does not have an enrollment. Allowlist certificate cannot be generated.' ) return False if not modes_api.is_eligible_for_certificate(enrollment_mode): log.info( f'{user.id} : {course_key} has an enrollment mode of {enrollment_mode}, which is not eligible for an ' f'allowlist certificate. Certificate cannot be generated.') return False if not IDVerificationService.user_is_verified(user): log.info( f'{user.id} does not have a verified id. Allowlist certificate cannot be generated for {course_key}.' ) return False log.info(f'{user.id} : {course_key} is on the certificate allowlist') return _can_generate_allowlist_certificate_for_status(user, course_key)
def listen_for_passing_grade(sender, user, course_id, **kwargs): # pylint: disable=unused-argument """ Listen for a learner passing a course, send cert generation task, downstream signal from COURSE_GRADE_CHANGED """ if not auto_certificate_generation_enabled(): return if fire_ungenerated_certificate_task(user, course_id): log.info( u'Certificate generation task initiated for {user} : {course} via passing grade' .format(user=user.id, course=course_id))
def can_generate_allowlist_certificate(user, course_key): """ Check if an allowlist certificate can be generated (created if it doesn't already exist, or updated if it does exist) for this user, in this course run. """ if not is_using_certificate_allowlist(course_key): # This course run is not using the allowlist feature log.info( '{course} is not using the certificate allowlist. Certificate cannot be generated.'.format( course=course_key )) return False if not auto_certificate_generation_enabled(): # Automatic certificate generation is globally disabled log.info('Automatic certificate generation is globally disabled. Certificate cannot be generated.') return False if CertificateInvalidation.has_certificate_invalidation(user, course_key): # The invalidation list overrides the allowlist log.info( '{user} : {course} is on the certificate invalidation list. Certificate cannot be generated.'.format( user=user.id, course=course_key )) return False enrollment_mode, __ = CourseEnrollment.enrollment_mode_for_user(user, course_key) if enrollment_mode is None: log.info('{user} : {course} does not have an enrollment. Certificate cannot be generated.'.format( user=user.id, course=course_key )) return False if not IDVerificationService.user_has_ever_been_verified(user): log.info(f'{user.id} has not ever had a verified id. Certificate cannot be generated.') return False if not _is_on_certificate_allowlist(user, course_key): log.info('{user} : {course} is not on the certificate allowlist. Certificate cannot be generated.'.format( user=user.id, course=course_key )) return False log.info('{user} : {course} is on the certificate allowlist'.format( user=user.id, course=course_key )) cert = GeneratedCertificate.certificate_for_student(user, course_key) return _can_generate_allowlist_certificate_for_status(cert)
def _listen_for_passing_grade(sender, user, course_id, **kwargs): # pylint: disable=unused-argument """ Listen for a learner passing a course, send cert generation task, downstream signal from COURSE_GRADE_CHANGED """ course = CourseOverview.get_from_id(course_id) if not auto_certificate_generation_enabled(): return if fire_ungenerated_certificate_task(user, course_id): log.info(u'Certificate generation task initiated for {user} : {course} via passing grade'.format( user=user.id, course=course_id ))
def _listen_for_track_change(sender, user, **kwargs): # pylint: disable=unused-argument """ Catches a track change signal, determines user status, calls fire_ungenerated_certificate_task for passing grades """ if not auto_certificate_generation_enabled(): return user_enrollments = CourseEnrollment.enrollments_for_user(user=user) grade_factory = CourseGradeFactory() for enrollment in user_enrollments: if grade_factory.read(user=user, course=enrollment.course_overview).passed: if fire_ungenerated_certificate_task(user, enrollment.course_id): log.info(u'Certificate generation task initiated for {user} : {course} via track change'.format( user=user.id, course=enrollment.course_id ))
def _listen_for_certificate_whitelist_append(sender, instance, **kwargs): # pylint: disable=unused-argument """ Listen for a user being added to or modified on the whitelist (allowlist) """ if not auto_certificate_generation_enabled(): return if is_using_certificate_allowlist_and_is_on_allowlist(instance.user, instance.course_id): log.info(f'{instance.course_id} is using allowlist certificates, and the user {instance.user.id} is now on ' f'its allowlist. Attempt will be made to generate an allowlist certificate.') return generate_allowlist_certificate_task(instance.user, instance.course_id) if _fire_ungenerated_certificate_task(instance.user, instance.course_id): log.info('Certificate generation task initiated for {user} : {course} via whitelist'.format( user=instance.user.id, course=instance.course_id ))
def _listen_for_track_change(sender, user, **kwargs): # pylint: disable=unused-argument """ Catches a track change signal, determines user status, calls fire_ungenerated_certificate_task for passing grades """ if not auto_certificate_generation_enabled(): return user_enrollments = CourseEnrollment.enrollments_for_user(user=user) grade_factory = CourseGradeFactory() for enrollment in user_enrollments: if grade_factory.read(user=user, course=enrollment.course_overview).passed: if fire_ungenerated_certificate_task(user, enrollment.course_id): log.info( u'Certificate generation task initiated for {user} : {course} via track change' .format(user=user.id, course=enrollment.course_id))
def listen_for_passing_grade(sender, user, course_id, **kwargs): # pylint: disable=unused-argument """ Listen for a learner passing a course, send cert generation task, downstream signal from COURSE_GRADE_CHANGED """ if not auto_certificate_generation_enabled(): return if can_generate_certificate_task(user, course_id): log.info(f'{course_id} is using V2 certificates. Attempt will be made to generate a V2 certificate for ' f'{user.id} as a passing grade was received.') return generate_certificate_task(user, course_id) if _fire_ungenerated_certificate_task(user, course_id): log.info('Certificate generation task initiated for {user} : {course} via passing grade'.format( user=user.id, course=course_id ))
def _can_generate_certificate_common(user, course_key): """ Check if a course certificate can be generated (created if it doesn't already exist, or updated if it does exist) for this user, in this course run. This method contains checks that are common to both allowlist and V2 regular course certificates. """ if not auto_certificate_generation_enabled(): # Automatic certificate generation is globally disabled log.info(f'Automatic certificate generation is globally disabled. Certificate cannot be generated for ' f'{user.id} : {course_key}.') return False if CertificateInvalidation.has_certificate_invalidation(user, course_key): # The invalidation list prevents certificate generation log.info(f'{user.id} : {course_key} is on the certificate invalidation list. Certificate cannot be generated.') return False enrollment_mode, __ = CourseEnrollment.enrollment_mode_for_user(user, course_key) if enrollment_mode is None: 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): 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 not IDVerificationService.user_is_verified(user): log.info(f'{user.id} does not have a verified id. Certificate cannot be generated for {course_key}.') return False if not _can_generate_certificate_for_status(user, course_key): return False course = _get_course(course_key) if not has_html_certificates_enabled(course): log.info(f'{course_key} does not have HTML certificates enabled. Certificate cannot be generated for ' f'{user.id}.') return False return True
def _listen_for_id_verification_status_changed(sender, user, **kwargs): # pylint: disable=unused-argument """ Catches a track change signal, determines user status, calls fire_ungenerated_certificate_task for passing grades """ if not auto_certificate_generation_enabled(): return user_enrollments = CourseEnrollment.enrollments_for_user(user=user) grade_factory = CourseGradeFactory() expected_verification_status = IDVerificationService.user_status(user) for enrollment in user_enrollments: if grade_factory.read(user=user, course=enrollment.course_overview).passed: if fire_ungenerated_certificate_task(user, enrollment.course_id, expected_verification_status): message = ( u'Certificate generation task initiated for {user} : {course} via track change ' + u'with verification status of {status}' ) log.info(message.format( user=user.id, course=enrollment.course_id, status=expected_verification_status['status'] ))
def test_auto_certificate_generation_enabled(self, feature_enabled): with configure_waffle_namespace(feature_enabled): self.assertEqual(feature_enabled, api.auto_certificate_generation_enabled())
def test_auto_certificate_generation_enabled(self, feature_enabled): with configure_waffle_namespace(feature_enabled): assert feature_enabled == api.auto_certificate_generation_enabled()
def _can_generate_v2_certificate(user, course_key): """ Check if a v2 course certificate can be generated (created if it doesn't already exist, or updated if it does exist) for this user, in this course run. """ if not _is_using_v2_course_certificates(course_key): # This course run is not using the v2 course certificate feature log.info( f'{course_key} is not using v2 course certificates. Certificate cannot be generated.' ) return False if not auto_certificate_generation_enabled(): # Automatic certificate generation is globally disabled log.info( f'Automatic certificate generation is globally disabled. Certificate cannot be generated for ' f'{user.id} : {course_key}.') return False if CertificateInvalidation.has_certificate_invalidation(user, course_key): # The invalidation list prevents certificate generation log.info( f'{user.id} : {course_key} is on the certificate invalidation list. Certificate cannot be generated.' ) return False enrollment_mode, __ = CourseEnrollment.enrollment_mode_for_user( user, course_key) if enrollment_mode is None: 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): log.info( f'{user.id} : {course_key} has an enrollment mode of {enrollment_mode}, which is not eligible for an ' f'allowlist certificate. Certificate cannot be generated.') return False if not IDVerificationService.user_is_verified(user): log.info( f'{user.id} does not have a verified id. Certificate cannot be generated for {course_key}.' ) return False if _is_ccx_course(course_key): log.info( f'{course_key} is a CCX course. Certificate cannot be generated for {user.id}.' ) return False course = modulestore().get_course(course_key, depth=0) if _is_beta_tester(user, course): log.info( f'{user.id} is a beta tester in {course_key}. Certificate cannot be generated.' ) return False if not _has_passing_grade(user, course): log.info( f'{user.id} does not have a passing grade in {course_key}. Certificate cannot be generated.' ) return False if not _can_generate_certificate_for_status(user, course_key): return False log.info(f'V2 certificate can be generated for {user.id} : {course_key}') return True