Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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