diff --git a/lms/djangoapps/lti_provider/apps.py b/lms/djangoapps/lti_provider/apps.py index a9d94ae21c..8d271688af 100644 --- a/lms/djangoapps/lti_provider/apps.py +++ b/lms/djangoapps/lti_provider/apps.py @@ -13,4 +13,4 @@ class LtiProviderConfig(AppConfig): def ready(self): # Import the tasks module to ensure that signal handlers are registered. - from . import tasks # pylint: disable=unused-import + from . import signals # pylint: disable=unused-import diff --git a/lms/djangoapps/lti_provider/signals.py b/lms/djangoapps/lti_provider/signals.py new file mode 100644 index 0000000000..ff7eaceb19 --- /dev/null +++ b/lms/djangoapps/lti_provider/signals.py @@ -0,0 +1,69 @@ +""" +Signals handlers for the lti_provider Django app. +""" +from __future__ import absolute_import +import logging + +from django.conf import settings +from django.dispatch import receiver + +import lti_provider.outcomes as outcomes +from lms.djangoapps.grades.signals.signals import PROBLEM_WEIGHTED_SCORE_CHANGED +from lti_provider.views import parse_course_and_usage_keys +from xmodule.modulestore.django import modulestore +from .tasks import send_composite_outcome, send_leaf_outcome + +log = logging.getLogger(__name__) + + +def increment_assignment_versions(course_key, usage_key, user_id): + """ + Update the version numbers for all assignments that are affected by a score + change event. Returns a list of all affected assignments. + """ + problem_descriptor = modulestore().get_item(usage_key) + # Get all assignments involving the current problem for which the campus LMS + # is expecting a grade. There may be many possible graded assignments, if + # a problem has been added several times to a course at different + # granularities (such as the unit or the vertical). + assignments = outcomes.get_assignments_for_problem( + problem_descriptor, user_id, course_key + ) + for assignment in assignments: + assignment.version_number += 1 + assignment.save() + return assignments + + +@receiver(PROBLEM_WEIGHTED_SCORE_CHANGED) +def score_changed_handler(sender, **kwargs): # pylint: disable=unused-argument + """ + Consume signals that indicate score changes. See the definition of + PROBLEM_WEIGHTED_SCORE_CHANGED for a description of the signal. + """ + points_possible = kwargs.get('weighted_possible', None) + points_earned = kwargs.get('weighted_earned', None) + user_id = kwargs.get('user_id', None) + course_id = kwargs.get('course_id', None) + usage_id = kwargs.get('usage_id', None) + + if None not in (points_earned, points_possible, user_id, course_id): + course_key, usage_key = parse_course_and_usage_keys(course_id, usage_id) + assignments = increment_assignment_versions(course_key, usage_key, user_id) + for assignment in assignments: + if assignment.usage_key == usage_key: + send_leaf_outcome.delay( + assignment.id, points_earned, points_possible + ) + else: + send_composite_outcome.apply_async( + (user_id, course_id, assignment.id, assignment.version_number), + countdown=settings.LTI_AGGREGATE_SCORE_PASSBACK_DELAY + ) + else: + log.error( + "Outcome Service: Required signal parameter is None. " + "points_possible: %s, points_earned: %s, user_id: %s, " + "course_id: %s, usage_id: %s", + points_possible, points_earned, user_id, course_id, usage_id + ) diff --git a/lms/djangoapps/lti_provider/tasks.py b/lms/djangoapps/lti_provider/tasks.py index 549c38afb4..6839ef154f 100644 --- a/lms/djangoapps/lti_provider/tasks.py +++ b/lms/djangoapps/lti_provider/tasks.py @@ -4,73 +4,16 @@ Asynchronous tasks for the LTI provider app. import logging -from django.conf import settings from django.contrib.auth.models import User -from django.dispatch import receiver from opaque_keys.edx.keys import CourseKey import lti_provider.outcomes as outcomes from lms import CELERY_APP from lms.djangoapps.grades.course_grade_factory import CourseGradeFactory -from lms.djangoapps.grades.signals.signals import PROBLEM_WEIGHTED_SCORE_CHANGED from lti_provider.models import GradedAssignment -from lti_provider.views import parse_course_and_usage_keys from xmodule.modulestore.django import modulestore -log = logging.getLogger("edx.lti_provider") - - -@receiver(PROBLEM_WEIGHTED_SCORE_CHANGED) -def score_changed_handler(sender, **kwargs): # pylint: disable=unused-argument - """ - Consume signals that indicate score changes. See the definition of - PROBLEM_WEIGHTED_SCORE_CHANGED for a description of the signal. - """ - points_possible = kwargs.get('weighted_possible', None) - points_earned = kwargs.get('weighted_earned', None) - user_id = kwargs.get('user_id', None) - course_id = kwargs.get('course_id', None) - usage_id = kwargs.get('usage_id', None) - - if None not in (points_earned, points_possible, user_id, course_id): - course_key, usage_key = parse_course_and_usage_keys(course_id, usage_id) - assignments = increment_assignment_versions(course_key, usage_key, user_id) - for assignment in assignments: - if assignment.usage_key == usage_key: - send_leaf_outcome.delay( - assignment.id, points_earned, points_possible - ) - else: - send_composite_outcome.apply_async( - (user_id, course_id, assignment.id, assignment.version_number), - countdown=settings.LTI_AGGREGATE_SCORE_PASSBACK_DELAY - ) - else: - log.error( - "Outcome Service: Required signal parameter is None. " - "points_possible: %s, points_earned: %s, user_id: %s, " - "course_id: %s, usage_id: %s", - points_possible, points_earned, user_id, course_id, usage_id - ) - - -def increment_assignment_versions(course_key, usage_key, user_id): - """ - Update the version numbers for all assignments that are affected by a score - change event. Returns a list of all affected assignments. - """ - problem_descriptor = modulestore().get_item(usage_key) - # Get all assignments involving the current problem for which the campus LMS - # is expecting a grade. There may be many possible graded assignments, if - # a problem has been added several times to a course at different - # granularities (such as the unit or the vertical). - assignments = outcomes.get_assignments_for_problem( - problem_descriptor, user_id, course_key - ) - for assignment in assignments: - assignment.version_number += 1 - assignment.save() - return assignments +log = logging.getLogger(__name__) @CELERY_APP.task(name='lti_provider.tasks.send_composite_outcome')