Files
edx-platform/lms/djangoapps/gating/tasks.py

68 lines
2.7 KiB
Python

"""
This file contains celery tasks related to course content gating.
"""
import logging
from celery import shared_task
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user
from edx_django_utils.monitoring import set_code_owner_attribute
from opaque_keys.edx.keys import CourseKey, UsageKey
from lms.djangoapps.course_blocks.api import get_course_blocks
from lms.djangoapps.gating import api as gating_api
from xmodule.modulestore.django import modulestore # lint-amnesty, pylint: disable=wrong-import-order
log = logging.getLogger(__name__)
@shared_task
@set_code_owner_attribute
def task_evaluate_subsection_completion_milestones(course_id, block_id, user_id):
"""
Updates users' milestones related to completion of a subsection.
Args:
course_id(str): Course id which triggered a completion event
block_id(str): Id of the completed block
user_id(int): Id of the user who completed a block
"""
store = modulestore()
course_key = CourseKey.from_string(course_id)
with store.bulk_operations(course_key):
course = store.get_course(course_key)
if not course or not course.enable_subsection_gating:
log.debug(
"Gating: ignoring evaluation of completion milestone because it disabled for course [%s]", course_id
)
else:
try:
user = User.objects.get(id=user_id)
course_structure = get_course_blocks(user, store.make_course_usage_key(course_key))
completed_block_usage_key = UsageKey.from_string(block_id).map_into_course(course.id)
subsection_block = _get_subsection_of_block(completed_block_usage_key, course_structure)
subsection = course_structure[subsection_block]
log.debug(
"Gating: Evaluating completion milestone for subsection [%s] and user [%s]",
str(subsection.location), user.id
)
gating_api.evaluate_prerequisite(course, subsection, user)
except KeyError:
log.error("Gating: Given prerequisite subsection [%s] not found in course structure", block_id)
def _get_subsection_of_block(usage_key, block_structure):
"""
Finds subsection of a block by recursively iterating over its parents
:param usage_key: key of the block
:param block_structure: block structure
:return: sequential block
"""
parents = block_structure.get_parents(usage_key)
if parents:
for parent_block in parents:
if parent_block.block_type == 'sequential':
return parent_block
else:
return _get_subsection_of_block(parent_block, block_structure)