Skip to content

Commit

Permalink
feat: add filter before certificate creation starts
Browse files Browse the repository at this point in the history
- Add filters interactions with code that used generate_certificate_task
- Add unit-testing for filters
- Upgrade to latest library update
  • Loading branch information
mariajgrimaldi committed May 6, 2022
1 parent 80f60ff commit e8fa890
Show file tree
Hide file tree
Showing 9 changed files with 473 additions and 11 deletions.
39 changes: 36 additions & 3 deletions lms/djangoapps/certificates/generation_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import logging
from django.conf import settings
from openedx_filters.learning.filters import CertificateCreationRequested

from common.djangoapps.course_modes import api as modes_api
from common.djangoapps.course_modes.models import CourseMode
Expand All @@ -28,6 +29,14 @@
log = logging.getLogger(__name__)


class GeneratedCertificateException(Exception):
pass


class CertificateGenerationNotAllowed(GeneratedCertificateException):
pass


def generate_certificate_task(user, course_key, generation_mode=None, delay_seconds=CERTIFICATE_DELAY_SECONDS):
"""
Create a task to generate a certificate for this user in this course run, if the user is eligible and a certificate
Expand Down Expand Up @@ -55,9 +64,19 @@ def generate_allowlist_certificate_task(user, course_key, generation_mode=None,
enrollment_mode = _get_enrollment_mode(user, course_key)
course_grade = _get_course_grade(user, course_key, send_course_grade_signals=False)
if _can_generate_allowlist_certificate(user, course_key, enrollment_mode):
return _generate_certificate_task(user=user, course_key=course_key, enrollment_mode=enrollment_mode,
course_grade=course_grade, generation_mode=generation_mode,
delay_seconds=delay_seconds)
try:
return _generate_certificate_task(
user=user, course_key=course_key, enrollment_mode=enrollment_mode, course_grade=course_grade,
generation_mode=generation_mode, delay_seconds=delay_seconds,
)
except CertificateGenerationNotAllowed:
# Catch exception to contain error message in console.
log.error(
"Certificate generation not allowed for user %s in course %s",
user.id,
course_key,
)
return False

status = _set_allowlist_cert_status(user, course_key, enrollment_mode, course_grade)
if status is not None:
Expand Down Expand Up @@ -94,6 +113,20 @@ def _generate_certificate_task(user, course_key, enrollment_mode, course_grade,

course_grade_val = _get_grade_value(course_grade)

try:
# .. filter_implemented_name: CertificateCreationRequested
# .. filter_type: org.openedx.learning.certificate.creation.requested.v1
user, course_key, enrollment_mode, status, course_grade, generation_mode = CertificateCreationRequested.run_filter( # pylint: disable=line-too-long
user=user,
course_key=course_key,
mode=enrollment_mode,
status=status,
grade=course_grade,
generation_mode=generation_mode,
)
except CertificateCreationRequested.PreventCertificateCreation as exc:
raise CertificateGenerationNotAllowed(str(exc)) from exc

kwargs = {
'student': str(user.id),
'course_key': str(course_key),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from django.core.management.base import BaseCommand, CommandError
from opaque_keys import InvalidKeyError
from opaque_keys.edx.keys import CourseKey
from lms.djangoapps.certificates.generation_handler import CertificateGenerationNotAllowed

from lms.djangoapps.certificates.generation_handler import generate_certificate_task
from lms.djangoapps.certificates.models import CertificateGenerationCommandConfiguration
Expand Down Expand Up @@ -96,4 +97,11 @@ def handle(self, *args, **options):
user=user.id,
course=course_key
))
generate_certificate_task(user, course_key)
try:
generate_certificate_task(user, course_key)
except CertificateGenerationNotAllowed as e:
log.exception(
"Certificate generation not allowed for user %s in course %s",
user.id,
course_key,
)
30 changes: 27 additions & 3 deletions lms/djangoapps/certificates/signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from common.djangoapps.student.models import CourseEnrollment
from common.djangoapps.student.signals import ENROLLMENT_TRACK_UPDATED
from lms.djangoapps.certificates.generation_handler import (
CertificateGenerationNotAllowed,
generate_allowlist_certificate_task,
generate_certificate_task,
is_on_certificate_allowlist
Expand Down Expand Up @@ -79,7 +80,15 @@ def listen_for_passing_grade(sender, user, course_id, **kwargs): # pylint: disa
return
log.info(f'Attempt will be made to generate a course certificate for {user.id} : {course_id} as a passing grade '
f'was received.')
return generate_certificate_task(user, course_id)
try:
return generate_certificate_task(user, course_id)
except CertificateGenerationNotAllowed as e:
log.exception(
"Certificate generation not allowed for user %s in course %s",
str(user),
course_id,
)
return False


@receiver(COURSE_GRADE_NOW_FAILED, dispatch_uid="new_failing_learner")
Expand Down Expand Up @@ -117,7 +126,14 @@ def _listen_for_id_verification_status_changed(sender, user, **kwargs): # pylin
for enrollment in user_enrollments:
log.info(f'Attempt will be made to generate a course certificate for {user.id} : {enrollment.course_id}. Id '
f'verification status is {expected_verification_status}')
generate_certificate_task(user, enrollment.course_id)
try:
generate_certificate_task(user, enrollment.course_id)
except CertificateGenerationNotAllowed as e:
log.exception(
"Certificate generation not allowed for user %s in course %s",
str(user),
enrollment.course_id,
)


@receiver(ENROLLMENT_TRACK_UPDATED)
Expand All @@ -131,4 +147,12 @@ def _listen_for_enrollment_mode_change(sender, user, course_key, mode, **kwargs)
if modes_api.is_eligible_for_certificate(mode):
log.info(f'Attempt will be made to generate a course certificate for {user.id} : {course_key} since the '
f'enrollment mode is now {mode}.')
generate_certificate_task(user, course_key)
try:
return generate_certificate_task(user, course_key)
except CertificateGenerationNotAllowed as e:
log.exception(
"Certificate generation not allowed for user %s in course %s",
str(user),
course_key,
)
return False
Loading

0 comments on commit e8fa890

Please sign in to comment.