Example #1
0
def handle_course_cert_changed(sender, user, course_key, mode, status, **kwargs):
    """
        If a learner is awarded a course certificate,
        schedule a celery task to process that course certificate

        Args:
            sender:
                class of the object instance that sent this signal
            user:
                django.contrib.auth.User - the user to whom a cert was awarded
            course_key:
                refers to the course run for which the cert was awarded
            mode:
                mode / certificate type, e.g. "verified"
            status:
                "downloadable"

        Returns:
            None

        """
    # Import here instead of top of file since this module gets imported before
    # the credentials app is loaded, resulting in a Django deprecation warning.
    from openedx.core.djangoapps.credentials.models import CredentialsApiConfig

    verbose = kwargs.get('verbose', False)
    if verbose:
        msg = u"Starting handle_course_cert_changed with params: "\
            u"sender [{sender}], "\
            u"user [{username}], "\
            u"course_key [{course_key}], "\
            u"mode [{mode}], "\
            u"status [{status}], "\
            u"kwargs [{kw}]"\
            .format(
                sender=sender,
                username=getattr(user, 'username', None),
                course_key=str(course_key),
                mode=mode,
                status=status,
                kw=kwargs
            )

        LOGGER.info(msg)

    # Avoid scheduling new tasks if certification is disabled.
    if not CredentialsApiConfig.current().is_learner_issuance_enabled:
        if verbose:
            LOGGER.info("Skipping send cert: is_learner_issuance_enabled False")
        return

    # Avoid scheduling new tasks if learner records are disabled for this site (right now, course certs are only
    # used for learner records -- when that changes, we can remove this bit and always send course certs).
    if not is_learner_records_enabled_for_org(course_key.org):
        if verbose:
            LOGGER.info(
                u"Skipping send cert: ENABLE_LEARNER_RECORDS False for org [{org}]".format(
                    org=course_key.org
                )
            )
        return

    # schedule background task to process
    LOGGER.debug(
        u'handling COURSE_CERT_CHANGED: username=%s, course_key=%s, mode=%s, status=%s',
        user,
        course_key,
        mode,
        status,
    )
    # import here, because signal is registered at startup, but items in tasks are not yet able to be loaded
    from openedx.core.djangoapps.programs.tasks import award_course_certificate
    award_course_certificate.delay(user.username, str(course_key))
Example #2
0
def send_grade_if_interesting(user,
                              course_run_key,
                              mode,
                              status,
                              letter_grade,
                              percent_grade,
                              verbose=False):
    """ Checks if grade is interesting to Credentials and schedules a Celery task if so. """

    if verbose:
        msg = "Starting send_grade_if_interesting with params: "\
            "user [{username}], "\
            "course_run_key [{key}], "\
            "mode [{mode}], "\
            "status [{status}], "\
            "letter_grade [{letter_grade}], "\
            "percent_grade [{percent_grade}], "\
            "verbose [{verbose}]"\
            .format(
                username=getattr(user, 'username', None),
                key=str(course_run_key),
                mode=mode,
                status=status,
                letter_grade=letter_grade,
                percent_grade=percent_grade,
                verbose=verbose
            )
        logger.info(msg)
    # Avoid scheduling new tasks if certification is disabled. (Grades are a part of the records/cert story)
    if not CredentialsApiConfig.current().is_learner_issuance_enabled:
        if verbose:
            logger.info(
                "Skipping send grade: is_learner_issuance_enabled False")
        return

    # Avoid scheduling new tasks if learner records are disabled for this site.
    if not is_learner_records_enabled_for_org(course_run_key.org):
        if verbose:
            logger.info(
                "Skipping send grade: ENABLE_LEARNER_RECORDS False for org [{org}]"
                .format(org=course_run_key.org))
        return

    # Grab mode/status if we don't have them in hand
    if mode is None or status is None:
        try:
            cert = GeneratedCertificate.objects.get(user=user,
                                                    course_id=course_run_key)  # pylint: disable=no-member
            mode = cert.mode
            status = cert.status
        except GeneratedCertificate.DoesNotExist:
            # We only care about grades for which there is a certificate.
            if verbose:
                logger.info(
                    "Skipping send grade: no cert for user [{username}] & course_id [{course_id}]"
                    .format(username=getattr(user, 'username', None),
                            course_id=str(course_run_key)))
            return

    # Don't worry about whether it's available as well as awarded. Just awarded is good enough to record a verified
    # attempt at a course. We want even the grades that didn't pass the class because Credentials wants to know about
    # those too.
    if mode not in INTERESTING_MODES or status not in INTERESTING_STATUSES:
        if verbose:
            logger.info(
                "Skipping send grade: mode/status uninteresting for mode [{mode}] & status [{status}]"
                .format(mode=mode, status=status))
        return

    # If the course isn't in any program, don't bother telling Credentials about it. When Credentials grows support
    # for course records as well as program records, we'll need to open this up.
    if not is_course_run_in_a_program(course_run_key):
        if verbose:
            logger.info(
                f"Skipping send grade: course run not in a program. [{str(course_run_key)}]"
            )
        return

    # Grab grades if we don't have them in hand
    if letter_grade is None or percent_grade is None:
        grade = CourseGradeFactory().read(user,
                                          course_key=course_run_key,
                                          create_if_needed=False)
        if grade is None:
            if verbose:
                logger.info(
                    "Skipping send grade: No grade found for user [{username}] & course_id [{course_id}]"
                    .format(username=getattr(user, 'username', None),
                            course_id=str(course_run_key)))
            return
        letter_grade = grade.letter_grade
        percent_grade = grade.percent

    send_grade_to_credentials.delay(user.username, str(course_run_key), True,
                                    letter_grade, percent_grade)