From d0aee3694c578a005e19b7a7a4b045eb243d0678 Mon Sep 17 00:00:00 2001 From: Stefan Dworschak Date: Wed, 21 Feb 2024 13:20:16 +0000 Subject: [PATCH] Addin tasks to enable certs and configuring fdcc schedule --- cms/djangoapps/fdcc_utils/__init__.py | 0 cms/djangoapps/fdcc_utils/tasks.py | 86 +++++++++++++++++++++++++++ cms/djangoapps/fdcc_utils/utils.py | 21 +++++++ cms/envs/common.py | 1 + 4 files changed, 108 insertions(+) create mode 100644 cms/djangoapps/fdcc_utils/__init__.py create mode 100644 cms/djangoapps/fdcc_utils/tasks.py create mode 100644 cms/djangoapps/fdcc_utils/utils.py diff --git a/cms/djangoapps/fdcc_utils/__init__.py b/cms/djangoapps/fdcc_utils/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/cms/djangoapps/fdcc_utils/tasks.py b/cms/djangoapps/fdcc_utils/tasks.py new file mode 100644 index 00000000000..c1cba914527 --- /dev/null +++ b/cms/djangoapps/fdcc_utils/tasks.py @@ -0,0 +1,86 @@ +from datetime import date, timedelta +import logging +import os +import six + +from celery.task import task +from celery_utils.logged_task import LoggedTask +from django.contrib.auth.models import User +from django.core.management.base import CommandError + +from opaque_keys import InvalidKeyError +from opaque_keys.edx.keys import CourseKey +from xmodule.modulestore.django import modulestore +from contentstore.views.certificates import CertificateManager, _get_course_and_check_access +from contentstore.views.item import _get_xblock, _save_xblock +from fdcc_utils.utils import get_sections +from lms.djangoapps.certificates.api import set_cert_generation_enabled + +log = logging.getLogger(__name__) + + +@task(base=LoggedTask) +def configure_fdcc_certificate(course_id=None, cert_is_active=None, self_generation_enabled=None): + log.info("Configuring Certificate for course %s - cert_is_active: %s - self_generation_enabled: %s", + course_id, cert_is_active, self_generation_enabled) + + if not cert_is_active and self_generation_enabled is True: + raise CommandError(("Enabling certificate self generation without activating the certificate " + "will not make the certificate available to students.")) + + try: + course_key = CourseKey.from_string(course_id) + except InvalidKeyError: + raise CommandError(u"Invalid course_key: '%s'." % course_id) + + store = modulestore() + if not store.get_course(course_key): + raise CommandError(u"Course with %s key not found." % course_id) + + # De-/activate Certificate + fdcc_admin = User.objects.get(username=os.getenv('FDCC_ADMIN_USERNAME')) + course = _get_course_and_check_access(course_key, fdcc_admin) + certificates = CertificateManager.get_certificates(course) + if not certificates: + raise CommandError(u"No certificates found for course: '%s' ." % course_id) + + for certificate in certificates: + certificate['is_active'] = cert_is_active is True + break + + store.update_item(course, fdcc_admin.id) + is_active, certificates = CertificateManager.is_activated(course) + if not is_active and cert_is_active is True: + raise CommandError(u"There was an error activating the certificate for course '%s'." % course_id) + + cert_event_type = 'activated' if cert_is_active else 'deactivated' + CertificateManager.track_event(cert_event_type, {'course_id': six.text_type(course.id)}) + + # Dis-/enable certificate self generation + set_cert_generation_enabled(course_key, self_generation_enabled) + + log.info("Configured Certificate for course %s - cert_is_active: %s - self_generation_enabled: %s", + course_id, cert_is_active, self_generation_enabled) + + +@task(base=LoggedTask) +def schedule_fdcc_module(course_id=None, only_visible=None): + log.info(u"Configuring schedule for course %s (only visible: %s)", course_id, only_visible) + start_date = date.today() + # If not run on a Monday, make start_date to be the Monday of the current week + if date.today().weekday() != 0: + start_date = start_date - timedelta(days=start_date.weekday()) + + fdcc_admin = User.objects.get(username=os.getenv('FDCC_ADMIN_USERNAME')) + sections = get_sections(course_id, (only_visible is True)) + for i, section_xblock in enumerate(sections): + day_increment = min(i, 4) # Max 4 days which brings it to Friday + start_time = (start_date + timedelta(days=day_increment)).strftime('%Y-%m-%d') + 'T05:00:00Z' + log.info(u"Setting start time for section '%s' to %s", section_xblock.display_name, start_time) + _save_xblock(fdcc_admin, section_xblock, metadata={'start': start_time}) + for lesson in section_xblock.children: + lesson_xblock = _get_xblock(lesson, fdcc_admin) + log.info(u"Setting start time for lesson '%s' to %s", lesson_xblock.display_name, start_time) + _save_xblock(fdcc_admin, lesson_xblock, metadata={'start': start_time}) + + log.info(u"Configured schedule for course %s (only visible: %s)", course_id, only_visible) diff --git a/cms/djangoapps/fdcc_utils/utils.py b/cms/djangoapps/fdcc_utils/utils.py new file mode 100644 index 00000000000..cac0e113963 --- /dev/null +++ b/cms/djangoapps/fdcc_utils/utils.py @@ -0,0 +1,21 @@ +from opaque_keys.edx.keys import CourseKey +from xmodule.modulestore.django import modulestore + + +def get_children(parent): + if not hasattr(parent, 'children'): + return [] + else: + return parent.children + + +def get_sections(course_id, only_visible=True): + course_key = CourseKey.from_string(course_id) + store = modulestore() + course = store.get_course(course_key, depth=2) + children = [store.get_item(child_usage_key) for child_usage_key in get_children(course)] + if only_visible: + return [c for c in children if not c.visible_to_staff_only and not c.hide_from_toc] + + return children + diff --git a/cms/envs/common.py b/cms/envs/common.py index ed98a91ba10..af048477b2d 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -1498,6 +1498,7 @@ 'openedx.core.djangoapps.content.learning_sequences.apps.LearningSequencesConfig', 'module_importexport', + 'cms.djangoapps.fdcc_utils', ]