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)
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
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') )
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)
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 ) ]
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, ) ]
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)
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)
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)