def send_xapi_statements(self, lrs_configuration, days):
        """
        Send xAPI analytics data of the enterprise learners to the given LRS.

        Arguments:
            lrs_configuration (XAPILRSConfiguration): Configuration object containing LRS configurations
                of the LRS where to send xAPI  learner analytics.
            days (int): Include course enrollment of this number of days.
        """
        course_enrollments = self.get_course_enrollments(
            lrs_configuration.enterprise_customer, days)
        course_catalog_client = get_course_catalog_api_service_client(
            site=lrs_configuration.enterprise_customer.site)
        for course_enrollment in course_enrollments:

            course_overview = course_enrollment.course
            courserun_id = six.text_type(course_overview.id)
            course_run_identifiers = course_catalog_client.get_course_run_identifiers(
                courserun_id)
            course_overview.course_key = course_run_identifiers['course_key']
            course_overview.course_uuid = course_run_identifiers['course_uuid']

            response_fields = Command.transmit_course_enrollment_statement(
                lrs_configuration, course_enrollment.user, course_overview)

            if is_success_response(response_fields):
                Command.transmit_courserun_enrollment_statement(
                    lrs_configuration, course_enrollment.user, course_overview)
示例#2
0
    def get_learner_assessment_data_records(
        self,
        enterprise_enrollment,
        assessment_grade_data,
    ):
        """
        Return a CanvasLearnerDataTransmissionAudit with the given enrollment and assessment level data.

        If there is no subsection grade then something has gone horribly wrong and it is recommended to look at the
        return value of platform's gradebook view.

        If no remote ID (enterprise user's email) can be found, return None as that is used to match the learner with
        their Canvas account.

        Parameters:
        -----------
            enterprise_enrollment (EnterpriseCourseEnrollment object):  Django model containing the enterprise
                customer, course ID, and enrollment source.
            assessment_grade_data (Dict): learner data retrieved from platform's gradebook api.
        """
        if enterprise_enrollment.enterprise_customer_user.user_email is None:
            # We need an email to find the user on Canvas.
            LOGGER.debug(
                'No learner data was sent for user [%s] because a Canvas user ID could not be found.',
                enterprise_enrollment.enterprise_customer_user.username)
            return None

        CanvasLearnerAssessmentDataTransmissionAudit = apps.get_model(  # pylint: disable=invalid-name
            'canvas', 'CanvasLearnerAssessmentDataTransmissionAudit')

        user_subsection_audits = []
        # Create an audit for each of the subsections exported.
        for subsection_name, subsection_data in assessment_grade_data.items():
            subsection_percent_grade = subsection_data.get('grade')
            subsection_id = subsection_data.get('subsection_id')
            # Sanity check for a grade to report
            if not subsection_percent_grade or not subsection_id:
                continue

            course_catalog_client = get_course_catalog_api_service_client(
                site=enterprise_enrollment.enterprise_customer_user.
                enterprise_customer.site)

            transmission_audit = CanvasLearnerAssessmentDataTransmissionAudit(
                enterprise_course_enrollment_id=enterprise_enrollment.id,
                canvas_user_email=enterprise_enrollment.
                enterprise_customer_user.user_email,
                course_id=course_catalog_client.get_course_id(
                    enterprise_enrollment.course_id),
                subsection_id=subsection_id,
                grade=subsection_percent_grade,
                grade_point_score=subsection_data.get('grade_point_score'),
                grade_points_possible=subsection_data.get(
                    'grade_points_possible'),
                subsection_name=subsection_name)
            user_subsection_audits.append(transmission_audit)

        return user_subsection_audits
示例#3
0
    def send_xapi_statements(self, lrs_configuration, days):
        """
        Send xAPI analytics data of the enterprise learners to the given LRS.

        Arguments:
            lrs_configuration (XAPILRSConfiguration): Configuration object containing LRS configurations
                of the LRS where to send xAPI  learner analytics.

            days (Numeric):  Deprecated.  Original implementation utilized a "days" parameter to limit
                the number of enrollments transmitted, but this proved to be more problematic than helpful.
        """
        enterprise_course_enrollments = self.get_enterprise_course_enrollments(lrs_configuration.enterprise_customer)
        enterprise_enrollment_ids = self.get_enterprise_enrollment_ids(enterprise_course_enrollments)
        xapi_transmission_queryset = self.get_xapi_transmission_queryset(enterprise_enrollment_ids)
        pertinent_enrollment_ids = self.get_pertinent_enrollment_ids(xapi_transmission_queryset)
        pertinent_enrollments = self.get_pertinent_enrollments(enterprise_course_enrollments, pertinent_enrollment_ids)
        enrollment_grades = self.get_course_completions(pertinent_enrollments)
        users = self.prefetch_users(enrollment_grades)
        course_overviews = self.prefetch_courses(enrollment_grades)
        course_catalog_client = get_course_catalog_api_service_client(site=lrs_configuration.enterprise_customer.site)

        for xapi_transmission in xapi_transmission_queryset:

            object_type = self.get_object_type(xapi_transmission)

            try:
                course_grade = enrollment_grades[xapi_transmission.enterprise_course_enrollment_id]
            except KeyError:
                continue

            user = users.get(course_grade.user_id)
            courserun_id = six.text_type(course_grade.course_id)
            course_overview = course_overviews.get(course_grade.course_id)
            course_run_identifiers = course_catalog_client.get_course_run_identifiers(courserun_id)
            course_overview.course_key = course_run_identifiers['course_key']
            course_overview.course_uuid = course_run_identifiers['course_uuid']

            default_error_message = 'Days argument has been deprecated.  Value: {days}'.format(days=days)
            response_fields = {'status': 500, 'error_message': default_error_message}
            response_fields = send_course_completion_statement(
                lrs_configuration,
                user,
                course_overview,
                course_grade,
                object_type,
                response_fields
            )

            if is_success_response(response_fields):
                self.save_xapi_learner_data_transmission_audit(
                    xapi_transmission,
                    course_grade.percent_grade,
                    1,
                    course_grade.passed_timestamp,
                    response_fields.get('status'),
                    response_fields.get('error_message')
                )
示例#4
0
    def get_learner_data_records(self,
                                 enterprise_enrollment,
                                 completed_date=None,
                                 grade=None,
                                 is_passing=False):
        """
        Return a SapSuccessFactorsLearnerDataTransmissionAudit with the given enrollment and course completion data.

        If completed_date is None and the learner isn't passing, then course completion has not been met.

        If no remote ID can be found, return None.
        """
        completed_timestamp = None
        course_completed = False
        if completed_date is not None:
            completed_timestamp = parse_datetime_to_epoch_millis(
                completed_date)
            course_completed = is_passing

        sapsf_user_id = enterprise_enrollment.enterprise_customer_user.get_remote_id(
        )

        if sapsf_user_id is not None:
            SapSuccessFactorsLearnerDataTransmissionAudit = apps.get_model(  # pylint: disable=invalid-name
                'sap_success_factors',
                'SapSuccessFactorsLearnerDataTransmissionAudit')
            # We return two records here, one with the course key and one with the course run id, to account for
            # uncertainty about the type of content (course vs. course run) that was sent to the integrated channel.
            course_catalog_client = get_course_catalog_api_service_client(
                site=enterprise_enrollment.enterprise_customer_user.
                enterprise_customer.site)
            return [
                SapSuccessFactorsLearnerDataTransmissionAudit(
                    enterprise_course_enrollment_id=enterprise_enrollment.id,
                    sapsf_user_id=sapsf_user_id,
                    course_id=course_catalog_client.get_course_id(
                        enterprise_enrollment.course_id),
                    course_completed=course_completed,
                    completed_timestamp=completed_timestamp,
                    grade=grade,
                ),
                SapSuccessFactorsLearnerDataTransmissionAudit(
                    enterprise_course_enrollment_id=enterprise_enrollment.id,
                    sapsf_user_id=sapsf_user_id,
                    course_id=enterprise_enrollment.course_id,
                    course_completed=course_completed,
                    completed_timestamp=completed_timestamp,
                    grade=grade,
                ),
            ]
        else:
            LOGGER.debug(
                '[Integrated Channel] No learner data was sent for user [%s] because an SAP SuccessFactors user ID'
                ' could not be found.',
                enterprise_enrollment.enterprise_customer_user.username)
示例#5
0
    def get_learner_data_records(
            self,
            enterprise_enrollment,
            completed_date=None,
            is_passing=False,
            **kwargs
    ):  # pylint: disable=arguments-differ,unused-argument
        """
        Return a CanvasLearnerDataTransmissionAudit with the given enrollment and course completion data.

        If completed_date is None, then course completion has not been met.

        If no remote ID can be found, return None.
        """
        if enterprise_enrollment.enterprise_customer_user.user_email is None:
            LOGGER.debug(
                'No learner data was sent for user [%s] because a Canvas user ID could not be found.',
                enterprise_enrollment.enterprise_customer_user.username
            )
            return None
        percent_grade = kwargs.get('grade_percent', None)
        completed_timestamp = completed_date.strftime("%F") if isinstance(completed_date, datetime) else None

        CanvasLearnerDataTransmissionAudit = apps.get_model(  # pylint: disable=invalid-name
            'canvas',
            'CanvasLearnerDataTransmissionAudit'
        )
        # We return two records here, one with the course key and one with the course run id, to account for
        # uncertainty about the type of content (course vs. course run) that was sent to the integrated channel.
        course_catalog_client = get_course_catalog_api_service_client(
            site=enterprise_enrollment.enterprise_customer_user.enterprise_customer.site
        )
        return [
            CanvasLearnerDataTransmissionAudit(
                enterprise_course_enrollment_id=enterprise_enrollment.id,
                canvas_user_email=enterprise_enrollment.enterprise_customer_user.user_email,
                course_id=course_catalog_client.get_course_id(enterprise_enrollment.course_id),
                course_completed=completed_date is not None and is_passing,
                completed_timestamp=completed_timestamp,
                grade=percent_grade
            ),
            CanvasLearnerDataTransmissionAudit(
                enterprise_course_enrollment_id=enterprise_enrollment.id,
                canvas_user_email=enterprise_enrollment.enterprise_customer_user.user_email,
                course_id=enterprise_enrollment.course_id,
                course_completed=completed_date is not None and is_passing,
                completed_timestamp=completed_timestamp,
                grade=percent_grade
            )
        ]
示例#6
0
    def get_learner_data_records(self,
                                 enterprise_enrollment,
                                 completed_date=None,
                                 is_passing=False,
                                 **kwargs):  # pylint: disable=arguments-differ,unused-argument
        """
        Return a BlackboardLearnerDataTransmissionAudit with the given enrollment and course completion data.
        If completed_date is None, then course completion has not been met.
        If no remote ID can be found, return None.
        """
        enterprise_customer = enterprise_enrollment.enterprise_customer_user
        completed_timestamp = None
        if completed_date is not None:
            completed_timestamp = parse_datetime_to_epoch_millis(
                completed_date)

        if enterprise_customer.user_email is None:
            LOGGER.debug(
                'No learner data was sent for user [%s] because a Blackboard user ID could not be found.',
                enterprise_customer.username)
            return None

        BlackboardLearnerDataTransmissionAudit = apps.get_model(  # pylint: disable=invalid-name
            'blackboard', 'BlackboardLearnerDataTransmissionAudit')

        course_catalog_client = get_course_catalog_api_service_client(
            site=enterprise_customer.enterprise_customer.site)

        percent_grade = kwargs.get('grade_percent', None)

        return [
            BlackboardLearnerDataTransmissionAudit(
                enterprise_course_enrollment_id=enterprise_enrollment.id,
                blackboard_user_email=enterprise_customer.user_email,
                course_id=course_catalog_client.get_course_id(
                    enterprise_enrollment.course_id),
                course_completed=completed_date is not None and is_passing,
                grade=percent_grade,
                completed_timestamp=completed_timestamp,
            ),
            BlackboardLearnerDataTransmissionAudit(
                enterprise_course_enrollment_id=enterprise_enrollment.id,
                blackboard_user_email=enterprise_customer.user_email,
                course_id=enterprise_enrollment.course_id,
                course_completed=completed_date is not None and is_passing,
                grade=percent_grade,
                completed_timestamp=completed_timestamp,
            )
        ]
示例#7
0
    def proxied_get(self, *args, **kwargs):
        """
        Perform the query and returns a single object matching the given keyword arguments.

        This customizes the queryset to return an instance of ``ProxyDataSharingConsent`` when
        the searched-for ``DataSharingConsent`` instance does not exist.
        """
        # TODO: ENT-2010
        original_kwargs = kwargs.copy()
        if 'course_id' in kwargs:
            try:
                # Check if we have a course ID or a course run ID
                course_run_key = str(CourseKey.from_string(
                    kwargs['course_id']))
            except InvalidKeyError:
                # The ID we have is for a course instead of a course run; fall through
                # to the second check.
                pass
            else:
                try:
                    # Try to get the record for the course run specifically
                    return self.get(*args, **kwargs)
                except DataSharingConsent.DoesNotExist:
                    # A record for the course run didn't exist, so modify the query
                    # parameters to look for just a course record on the second pass.

                    site = None
                    if 'enterprise_customer' in kwargs:
                        site = kwargs['enterprise_customer'].site

                    try:
                        course_id = get_course_catalog_api_service_client(
                            site=site).get_course_id(
                                course_identifier=course_run_key)
                        kwargs['course_id'] = course_id
                    except ImproperlyConfigured:
                        LOGGER.warning(
                            'CourseCatalogApiServiceClient is improperly configured.'
                        )

        try:
            return self.get(*args, **kwargs)
        except DataSharingConsent.DoesNotExist:
            return ProxyDataSharingConsent(**original_kwargs)
示例#8
0
def get_program_data_sharing_consent(username, program_uuid,
                                     enterprise_customer_uuid):
    """
    Get the data sharing consent object associated with a certain user of a customer for a program.

    :param username: The user that grants consent.
    :param program_uuid: The program for which consent is granted.
    :param enterprise_customer_uuid: The consent requester.
    :return: The data sharing consent object
    """
    enterprise_customer = get_enterprise_customer(enterprise_customer_uuid)
    discovery_client = get_course_catalog_api_service_client(
        enterprise_customer.site)
    course_ids = discovery_client.get_program_course_keys(program_uuid)
    child_consents = (get_data_sharing_consent(username,
                                               enterprise_customer_uuid,
                                               course_id=individual_course_id)
                      for individual_course_id in course_ids)
    return ProxyDataSharingConsent.from_children(program_uuid, *child_consents)
示例#9
0
    def get_learner_data_records(self,
                                 enterprise_enrollment,
                                 completed_date=None,
                                 grade=None,
                                 is_passing=False,
                                 grade_percent=None):
        """
        Return a CornerstoneLearnerDataTransmissionAudit with the given enrollment and course completion data.

        If completed_date is None, then course completion has not been met.

        CornerstoneLearnerDataTransmissionAudit object should exit already if not then return None.
        """
        course_completed = False
        if completed_date is not None:
            course_completed = True

        CornerstoneLearnerDataTransmissionAudit = apps.get_model(  # pylint: disable=invalid-name
            'cornerstone', 'CornerstoneLearnerDataTransmissionAudit')

        course_catalog_client = get_course_catalog_api_service_client(
            site=enterprise_enrollment.enterprise_customer_user.
            enterprise_customer.site)
        try:
            csod_learner_data_transmission = CornerstoneLearnerDataTransmissionAudit.objects.get(
                user_id=enterprise_enrollment.enterprise_customer_user.user.id,
                course_id=course_catalog_client.get_course_id(
                    enterprise_enrollment.course_id),
            )
            csod_learner_data_transmission.enterprise_course_enrollment_id = enterprise_enrollment.id
            csod_learner_data_transmission.grade = grade
            csod_learner_data_transmission.course_completed = course_completed
            csod_learner_data_transmission.completed_timestamp = completed_date
            return [csod_learner_data_transmission]
        except CornerstoneLearnerDataTransmissionAudit.DoesNotExist:
            LOGGER.info(
                'No learner data was sent for user [%s] because Cornerstone user ID could not be found '
                'for customer [%s]',
                enterprise_enrollment.enterprise_customer_user.username,
                enterprise_enrollment.enterprise_customer_user.
                enterprise_customer.name)