Ejemplo n.º 1
0
    def test_passing_grade_allowlist(self):
        with override_waffle_switch(AUTO_CERTIFICATE_GENERATION, active=True):
            # User who is not on the allowlist
            GeneratedCertificateFactory(user=self.user,
                                        course_id=self.course.id,
                                        status=CertificateStatuses.error)
            with mock_passing_grade():
                with mock.patch(
                        'lms.djangoapps.certificates.signals.generate_certificate_task',
                        return_value=None) as mock_cert_task:
                    CourseGradeFactory().update(self.user, self.course)
                    mock_cert_task.assert_called_with(self.user,
                                                      self.course.id)

            # User who is on the allowlist
            u = UserFactory.create()
            c = CourseFactory()
            course_key = c.id  # pylint: disable=no-member
            CertificateAllowlistFactory(user=u, course_id=course_key)
            GeneratedCertificateFactory(user=u,
                                        course_id=course_key,
                                        status=CertificateStatuses.error)
            with mock_passing_grade():
                with mock.patch(
                        'lms.djangoapps.certificates.signals.generate_certificate_task',
                        return_value=None) as mock_cert_task:
                    CourseGradeFactory().update(u, c)
                    mock_cert_task.assert_called_with(u, course_key)
Ejemplo n.º 2
0
    def test_failing_grade_allowlist(self):
        # User who is not on the allowlist
        GeneratedCertificateFactory(
            user=self.user,
            course_id=self.course.id,
            status=CertificateStatuses.downloadable
        )
        CourseGradeFactory().update(self.user, self.course)
        cert = GeneratedCertificate.certificate_for_student(self.user, self.course.id)
        assert cert.status == CertificateStatuses.notpassing

        # User who is on the allowlist
        u = UserFactory.create()
        c = CourseFactory()
        course_key = c.id  # pylint: disable=no-member
        CertificateAllowlistFactory(
            user=u,
            course_id=course_key
        )
        GeneratedCertificateFactory(
            user=u,
            course_id=course_key,
            status=CertificateStatuses.downloadable
        )
        CourseGradeFactory().update(u, c)
        cert = GeneratedCertificate.certificate_for_student(u, course_key)
        assert cert.status == CertificateStatuses.downloadable
Ejemplo n.º 3
0
def course_grade(learner, course):
    """
    Compatibility function to retrieve course grades

    Returns the course grade for the specified learner and course
    """
    if RELEASE_LINE == 'ginkgo':
        return CourseGradeFactory().create(learner, course)
    else:  # Assume Hawthorn or greater
        return CourseGradeFactory().read(learner, course)
Ejemplo n.º 4
0
    def get(self, request, course_id):
        """
        Returns a gradebook entry/entries (i.e. both course and subsection-level grade data)
        for all users enrolled in a course, or a single user enrolled in a course
        if a `username` parameter is provided.

        Args:
            request: A Django request object.
            course_id: A string representation of a CourseKey object.
        """
        course_key = get_course_key(request, course_id)
        course = get_course_with_access(request.user,
                                        'staff',
                                        course_key,
                                        depth=None)

        if request.GET.get('username'):
            with self._get_user_or_raise(request, course_key) as grade_user:
                course_grade = CourseGradeFactory().read(grade_user, course)

            entry = self._gradebook_entry(grade_user, course, course_grade)
            serializer = StudentGradebookEntrySerializer(entry)
            return Response(serializer.data)
        else:
            filter_kwargs = {}
            related_models = []
            if request.GET.get('username_contains'):
                filter_kwargs['user__username__icontains'] = request.GET.get(
                    'username_contains')
                related_models.append('user')
            if request.GET.get('cohort_id'):
                cohort = cohorts.get_cohort_by_id(course_key,
                                                  request.GET.get('cohort_id'))
                if cohort:
                    filter_kwargs['user__in'] = cohort.users.all()
                else:
                    filter_kwargs['user__in'] = []
            if request.GET.get('enrollment_mode'):
                filter_kwargs['mode'] = request.GET.get('enrollment_mode')

            entries = []
            users = self._paginate_users(course_key, filter_kwargs,
                                         related_models)

            with bulk_gradebook_view_context(course_key, users):
                for user, course_grade, exc in CourseGradeFactory().iter(
                        users, course_key=course_key):
                    if not exc:
                        entries.append(
                            self._gradebook_entry(user, course, course_grade))

            serializer = StudentGradebookEntrySerializer(entries, many=True)
            return self.get_paginated_response(serializer.data)
Ejemplo n.º 5
0
    def get(self, request, course_id):
        """
        Returns a gradebook entry/entries (i.e. both course and subsection-level grade data)
        for all users enrolled in a course, or a single user enrolled in a course
        if a `username` parameter is provided.

        Args:
            request: A Django request object.
            course_id: A string representation of a CourseKey object.
        """
        course_key = get_course_key(request, course_id)
        course = get_course_with_access(request.user, 'staff', course_key, depth=None)

        # We fetch the entire course structure up-front, and use this when iterating
        # over users to determine their subsection grades.  We purposely avoid fetching
        # the user-specific course structure for each user, because that is very expensive.
        course_data = CourseData(user=None, course=course)
        graded_subsections = list(graded_subsections_for_course(course_data.collected_structure))

        if request.GET.get('username'):
            with self._get_user_or_raise(request, course_key) as grade_user:
                course_grade = CourseGradeFactory().read(grade_user, course)

            entry = self._gradebook_entry(grade_user, course, graded_subsections, course_grade)
            serializer = StudentGradebookEntrySerializer(entry)
            return Response(serializer.data)
        else:
            filter_kwargs = {}
            related_models = []
            if request.GET.get('username_contains'):
                filter_kwargs['user__username__icontains'] = request.GET.get('username_contains')
                related_models.append('user')
            if request.GET.get('cohort_id'):
                cohort = cohorts.get_cohort_by_id(course_key, request.GET.get('cohort_id'))
                if cohort:
                    filter_kwargs['user__in'] = cohort.users.all()
                else:
                    filter_kwargs['user__in'] = []
            if request.GET.get('enrollment_mode'):
                filter_kwargs['mode'] = request.GET.get('enrollment_mode')

            entries = []
            users = self._paginate_users(course_key, filter_kwargs, related_models)

            with bulk_gradebook_view_context(course_key, users):
                for user, course_grade, exc in CourseGradeFactory().iter(
                    users, course_key=course_key, collected_block_structure=course_data.collected_structure
                ):
                    if not exc:
                        entries.append(self._gradebook_entry(user, course, graded_subsections, course_grade))

            serializer = StudentGradebookEntrySerializer(entries, many=True)
            return self.get_paginated_response(serializer.data)
Ejemplo n.º 6
0
    def _get_single_user_grade(self, request, course_key):
        """
        Returns a grade response for the user object corresponding to the request's 'username' parameter,
        or the current request.user if no 'username' was provided.
        Args:
            request (Request): django request object to check for username or request.user object
            course_key (CourseLocator): The course to retrieve user grades for.

        Returns:
            A serializable list of grade responses
        """
        if 'username' in request.GET:
            username = request.GET.get('username')
        else:
            username = request.user.username

        grade_user = USER_MODEL.objects.get(username=username)

        if not enrollment_data.get_course_enrollment(username,
                                                     str(course_key)):
            raise CourseEnrollment.DoesNotExist

        course_grade = CourseGradeFactory().read(grade_user,
                                                 course_key=course_key)
        return Response(
            [self._make_grade_response(grade_user, course_key, course_grade)])
Ejemplo n.º 7
0
    def get(self, request, course_id):
        """
        Returns a gradebook entry/entries (i.e. both course and subsection-level grade data)
        for all users enrolled in a course, or a single user enrolled in a course
        if a `username` parameter is provided.

        Args:
            request: A Django request object.
            course_id: A string representation of a CourseKey object.
        """
        username = request.GET.get('username')
        course_key = get_course_key(request, course_id)
        course = get_course_with_access(request.user, 'staff', course_key, depth=None)

        if username:
            with self._get_user_or_raise(request, course_id) as grade_user:
                course_grade = CourseGradeFactory().read(grade_user, course)

            entry = self._gradebook_entry(grade_user, course, course_grade)
            serializer = StudentGradebookEntrySerializer(entry)
            return Response(serializer.data)
        else:
            # list gradebook data for all course enrollees
            entries = []
            for user, course_grade, exc in self._iter_user_grades(course_key):
                if not exc:
                    entries.append(self._gradebook_entry(user, course, course_grade))
            serializer = StudentGradebookEntrySerializer(entries, many=True)
            return self.get_paginated_response(serializer.data)
Ejemplo n.º 8
0
 def setUp(self):
     super(TestGradeUcursosExportView, self).setUp()
     self.grade_factory = CourseGradeFactory()
     with patch('student.models.cc.User.save'):
         # staff user
         self.client_instructor = Client()
         self.client_student = Client()
         self.client_anonymous = Client()
         self.user_instructor = UserFactory(
             username='******',
             password='******',
             email='*****@*****.**',
             is_staff=True)
         role = CourseInstructorRole(self.course.id)
         role.add_users(self.user_instructor)
         self.client_instructor.login(
             username='******', password='******')
         self.student = UserFactory(
             username='******',
             password='******',
             email='*****@*****.**')
         self.student_2 = UserFactory(
             username='******',
             password='******',
             email='*****@*****.**')
         # Enroll the student in the course
         CourseEnrollmentFactory(
             user=self.student, course_id=self.course.id, mode='honor')
         CourseEnrollmentFactory(
             user=self.student_2, course_id=self.course.id, mode='honor')
         self.client_student.login(
             username='******', password='******')
Ejemplo n.º 9
0
 def setUp(self):
     super(TestCorfoGenerateXBlock, self).setUp()        
     CorfoCodeMappingContent.objects.create(id_content=200, content='testtest')
     self.grade_factory = CourseGradeFactory()
     self.xblock = self.make_an_xblock()
     with patch('common.djangoapps.student.models.cc.User.save'):
         # staff user
         self.client = Client()
         user = UserFactory(
             username='******',
             password='******',
             email='*****@*****.**',
             is_staff=True)
         self.client.login(username='******', password='******')
         CourseEnrollmentFactory(
             user=user, course_id=self.course.id)
         # user student
         self.student_client = Client()
         self.student = UserFactory(
             username='******',
             password='******',
             email='*****@*****.**')
         CourseEnrollmentFactory(
             user=self.student, course_id=self.course.id)
         self.assertTrue(
             self.student_client.login(
                 username='******',
                 password='******'))
Ejemplo n.º 10
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 (int): Include course enrollment of this number of days.
        """
        persistent_course_grades = self.get_course_completions(
            lrs_configuration.enterprise_customer, days)
        users = self.prefetch_users(persistent_course_grades)
        course_overviews = self.prefetch_courses(persistent_course_grades)

        for persistent_course_grade in persistent_course_grades:
            try:
                user = users.get(persistent_course_grade.user_id)
                course_overview = course_overviews.get(
                    persistent_course_grade.course_id)
                course_grade = CourseGradeFactory().read(
                    user, course_key=persistent_course_grade.course_id)
                send_course_completion_statement(lrs_configuration, user,
                                                 course_overview, course_grade)
            except ClientError:
                LOGGER.exception(
                    'Client error while sending course completion to xAPI for'
                    ' enterprise customer {enterprise_customer}.'.format(
                        enterprise_customer=lrs_configuration.
                        enterprise_customer.name))
Ejemplo n.º 11
0
def get_user_course_response_task(users, course_str, depth, callback_url):
    """
    Get a list of users grades' for a course
    """
    user_grades = {}
    grades_schema = {}
    course_key = CourseKey.from_string(str(course_str))
    course = courses.get_course(course_key)
    for user in users:
        course_grade = CourseGradeFactory().update(user, course)
        if depth == "all":
            grades_schema = get_user_grades(user.id, course_str)
        else:
            grades_schema = "Showing course grade summary, specify depth=all in query params."
        user_grades[user.username] = {
            'name': "{} {}".format(user.first_name, user.last_name),
            'email': user.email,
            'start_date': course.start,
            'end_date':
            course.end if not None else "This course has no end date.",
            'all_grades': grades_schema,
            "passed": course_grade.passed,
            "percent": course_grade.percent
        }

    #requests.post(str(callback_url), data=user_grades)
    return user_grades
Ejemplo n.º 12
0
def get_course_grades(user, course):
    """
    Gets course grades for a given student
    """
    grades = CourseGradeFactory().read(user, course)

    return grades
Ejemplo n.º 13
0
    def _rows_for_users(self, context, users):
        """
        Returns a list of rows for the given users for this report.
        """
        with modulestore().bulk_operations(context.course_id):
            bulk_context = _CourseGradeBulkContext(context, users)

            success_rows, error_rows = [], []
            for user, course_grade, error in CourseGradeFactory().iter(
                users,
                course=context.course,
                collected_block_structure=context.course_structure,
                course_key=context.course_id,
            ):
                if not course_grade:
                    # An empty gradeset means we failed to grade a student.
                    error_rows.append([user.id, user.username, text_type(error)])
                else:
                    success_rows.append(
                        [user.id, user.email, user.username] +
                        self._user_grades(course_grade, context) +
                        self._user_cohort_group_names(user, context) +
                        self._user_experiment_group_names(user, context) +
                        self._user_team_names(user, bulk_context.teams) +
                        self._user_verification_mode(user, context, bulk_context.enrollments) +
                        self._user_certificate_info(user, context, course_grade, bulk_context.certs) +
                        [_user_enrollment_status(user, context.course_id)]
                    )
            return success_rows, error_rows
Ejemplo n.º 14
0
def get_user_course_response(course, users, course_str, depth):
    """
    Get a list of users grades' for a course
    """
    user_grades = {}
    grades_schema = {}

    for user in users:
        course_grade = CourseGradeFactory().update(user, course)
        if depth == "all":
            grades_schema = get_user_grades(user, course, course_str,
                                            course_grade)
        else:
            grades_schema = "Showing course grade summary, specify depth=all in query params."
        user_grades[user.username] = {
            'name':
            "{} {}".format(user.first_name, user.last_name),
            'email':
            user.email,
            'start_date':
            course.start,
            'end_date':
            course.end if not None else "This course has no end date.",
            'all_grades':
            grades_schema,
            "passed":
            course_grade.passed,
            "percent":
            course_grade.percent,
            "total_course_grade_raw":
            course_grade._compute_course_grade_total_raw(),
            "enrollment_date":
            str(CourseEnrollment.get_enrollment(user, course.id).created)
        }
    return user_grades
Ejemplo n.º 15
0
    def get(self, request, course_id):
        """
        Gets a course progress status.

        Args:
            request (Request): Django request object.
            course_id (string): URI element specifying the course location.

        Return:
            A JSON serialized representation of the requesting user's current grade status.
        """

        course = self._get_course(course_id, request.user, 'load')
        if isinstance(course, Response):
            # Returns a 404 if course_id is invalid, or request.user is not enrolled in the course
            return course

        grade_user = self._get_effective_user(request, course)
        if isinstance(grade_user, Response):
            # Returns a 403 if the request.user can't access grades for the requested user,
            # or a 404 if the requested user does not exist.
            return grade_user

        course_grade = CourseGradeFactory().read(grade_user, course)
        return Response([{
            'username': grade_user.username,
            'course_key': course_id,
            'passed': course_grade.passed,
            'percent': course_grade.percent,
            'letter_grade': course_grade.letter_grade,
        }])
Ejemplo n.º 16
0
    def __init__(self, site, user, enrollments=None, uuid=None):
        self.site = site
        self.user = user

        self.enrollments = enrollments or list(
            CourseEnrollment.enrollments_for_user(self.user))
        self.enrollments.sort(key=lambda e: e.created, reverse=True)

        self.enrolled_run_modes = {}
        self.course_run_ids = []
        for enrollment in self.enrollments:
            # enrollment.course_id is really a CourseKey (╯ಠ_ಠ)╯︵ ┻━┻
            enrollment_id = unicode(enrollment.course_id)
            mode = enrollment.mode
            if mode == CourseMode.NO_ID_PROFESSIONAL_MODE:
                mode = CourseMode.PROFESSIONAL
            self.enrolled_run_modes[enrollment_id] = mode
            # We can't use dict.keys() for this because the course run ids need to be ordered
            self.course_run_ids.append(enrollment_id)

        self.entitlements = list(
            CourseEntitlement.unexpired_entitlements_for_user(self.user))
        self.course_uuids = [
            str(entitlement.course_uuid) for entitlement in self.entitlements
        ]

        self.course_grade_factory = CourseGradeFactory()

        if uuid:
            self.programs = [get_programs(self.site, uuid=uuid)]
        else:
            self.programs = attach_program_detail_url(get_programs(self.site))
Ejemplo n.º 17
0
    def test_grade_changed(self, mock_send_grade_if_interesting):
        user = UserFactory()
        course = XModuleCourseFactory()

        self.assertFalse(mock_send_grade_if_interesting.called)
        CourseGradeFactory().update(user, course=course)
        self.assertTrue(mock_send_grade_if_interesting.called)
Ejemplo n.º 18
0
    def check_state(self, user, descriptor, expected_score, expected_max_score, expected_attempts=1):
        """
        Check that the StudentModule state contains the expected values.

        The student module is found for the test course, given the `username` and problem `descriptor`.

        Values checked include the number of attempts, the score, and the max score for a problem.
        """
        module = self.get_student_module(user.username, descriptor)
        self.assertEqual(module.grade, expected_score)
        self.assertEqual(module.max_grade, expected_max_score)
        state = json.loads(module.state)
        attempts = state['attempts']
        self.assertEqual(attempts, expected_attempts)
        if attempts > 0:
            self.assertIn('correct_map', state)
            self.assertIn('student_answers', state)
            self.assertGreater(len(state['correct_map']), 0)
            self.assertGreater(len(state['student_answers']), 0)

        # assume only one problem in the subsection and the grades
        # are in sync.
        expected_subsection_grade = expected_score

        course_grade = CourseGradeFactory().read(user, self.course)
        self.assertEquals(
            course_grade.graded_subsections_by_format['Homework'][self.problem_section.location].graded_total.earned,
            expected_subsection_grade,
        )
Ejemplo n.º 19
0
    def _iter_user_grades(self,
                          course_key,
                          course_enrollment_filter=None,
                          related_models=None):
        """
        Args:
            course_key (CourseLocator): The course to retrieve grades for.
            course_enrollment_filter: Optional dictionary of keyword arguments to pass
            to `CourseEnrollment.filter()`.
            related_models: Optional list of related models to join to the CourseEnrollment table.

        Returns:
            An iterator of CourseGrade objects for users enrolled in the given course.
        """
        filter_kwargs = {
            'course_id': course_key,
            'is_active': True,
        }
        filter_kwargs.update(course_enrollment_filter or {})
        enrollments_in_course = CourseEnrollment.objects.filter(
            **filter_kwargs)
        if related_models:
            enrollments_in_course = enrollments_in_course.select_related(
                *related_models)

        paged_enrollments = self.paginate_queryset(enrollments_in_course)
        users = (enrollment.user for enrollment in paged_enrollments)
        grades = CourseGradeFactory().iter(users, course_key=course_key)

        for user, course_grade, exc in grades:
            yield user, course_grade, exc
Ejemplo n.º 20
0
    def test_grade_changed(self, mock_send_grade_if_interesting):
        user = UserFactory()
        course = XModuleCourseFactory()

        assert not mock_send_grade_if_interesting.called
        CourseGradeFactory().update(user, course=course)
        assert mock_send_grade_if_interesting.called
Ejemplo n.º 21
0
def get_grade_book_page(request, course, course_key):
    """
    Get student records per page along with page information i.e current page, total pages and
    offset information.
    """
    # Unsanitized offset
    current_offset = request.GET.get('offset', 0)
    enrolled_students = User.objects.filter(
        courseenrollment__course_id=course_key,
        courseenrollment__is_active=1
    ).order_by('username').select_related("profile")

    total_students = enrolled_students.count()
    page = calculate_page_info(current_offset, total_students)
    offset = page["offset"]
    total_pages = page["total_pages"]

    if total_pages > 1:
        # Apply limit on queryset only if total number of students are greater then MAX_STUDENTS_PER_PAGE_GRADE_BOOK.
        enrolled_students = enrolled_students[offset: offset + MAX_STUDENTS_PER_PAGE_GRADE_BOOK]

    with modulestore().bulk_operations(course.location.course_key):
        student_info = [
            {
                'username': student.username,
                'id': student.id,
                'email': student.email,
                'grade_summary': CourseGradeFactory().create(student, course).summary
            }
            for student in enrolled_students
        ]
    return student_info, page
Ejemplo n.º 22
0
def get_course_info_for_application_review(courses, user):
    """
    Get courses info for application review page.

    Args:
        courses (list): List of courses
        user (User): User object

    Returns:
        dict: Contains course name and percent grade | status
    """
    courses_info = {}
    for course in courses:
        if not CourseEnrollment.is_enrolled(user, course.id):
            courses_info[course.display_name] = NOT_STARTED
            continue

        grade = CourseGradeFactory().read(user, course_key=course.id)
        if grade.passed:
            courses_info[
                course.
                display_name] = f'{convert_float_point_to_percentage(grade.percent)}%'
            continue

        courses_info[course.display_name] = IN_PROGRESS
    return courses_info
Ejemplo n.º 23
0
 def test_user_has_passing_grade(self):
     CourseEnrollment.enroll(self.user, self.course.id)
     self.course._grading_policy['GRADE_CUTOFFS']['Pass'] = 0  # pylint: disable=protected-access
     self.update_course(self.course, self.user.id)
     CourseGradeFactory().update(self.user, self.course)
     response = self.client.get(self.url)
     assert response.status_code == 200
     assert response.data['user_has_passing_grade'] is True
Ejemplo n.º 24
0
def _get_course_grade_passed(user, course_id):
    """
        Get 'passed' (Boolean representing whether the course has been
                passed according to the course's grading policy.)
    """
    course_key = CourseKey.from_string(course_id)
    course_grade = CourseGradeFactory().read(user, course_key=course_key)
    return course_grade.passed
Ejemplo n.º 25
0
 def _add_entrance_exam_to_context(self, courseware_context):
     """
     Adds entrance exam related information to the given context.
     """
     if course_has_entrance_exam(self.course) and getattr(self.chapter, 'is_entrance_exam', False):
         courseware_context['entrance_exam_passed'] = user_has_passed_entrance_exam(self.effective_user, self.course)
         courseware_context['entrance_exam_current_score'] = get_entrance_exam_score_ratio(
             CourseGradeFactory().create(self.effective_user, self.course),
             get_entrance_exam_usage_key(self.course),
         )
Ejemplo n.º 26
0
 def test_without_cert(self):
     with override_waffle_switch(AUTO_CERTIFICATE_GENERATION, active=True):
         with mock.patch(
                 'lms.djangoapps.certificates.signals.generate_certificate_task',
                 return_value=None) as mock_cert_task:
             grade_factory = CourseGradeFactory()
             with mock_passing_grade():
                 grade_factory.update(self.user, self.course)
                 mock_cert_task.assert_called_with(self.user,
                                                   self.course_key)
 def user_course_passed(self):
     from lms.djangoapps.grades.course_grade_factory import CourseGradeFactory
     from django.contrib.auth.models import User
     try:
         user = User.objects.get(id=self.scope_ids.user_id)
         response = CourseGradeFactory().read(user,
                                              course_key=self.course_id)
         return response.passed
     except User.DoesNotExist:
         return False
Ejemplo n.º 28
0
    def get_grade_data(self, user, course_key, grade_cutoffs):
        """
        Collects and formats the grades data for a particular user and course.

        Args:
            user (User)
            course_key (CourseKey)
            grade_cutoffs: # TODO: LEARNER-3854: Complete docstring if implementing Learner Analytics.
        """
        course_grade = CourseGradeFactory().read(user, course_key=course_key)
        grades = []
        total_earned = 0
        total_possible = 0
        # answered_percent seems to be unused and it does not take into account assignment type weightings
        answered_percent = None

        chapter_grades = course_grade.chapter_grades.values()

        for chapter in chapter_grades:
            # Note: this code exists on the progress page. We should be able to remove it going forward.
            if not chapter['display_name'] == "hidden":
                for subsection_grade in chapter['sections']:
                    log.info(subsection_grade.display_name)
                    possible = subsection_grade.graded_total.possible
                    earned = subsection_grade.graded_total.earned
                    passing_grade = math.ceil(possible * grade_cutoffs['Pass'])
                    grades.append({
                        'assignment_type':
                        subsection_grade.format,
                        'total_earned':
                        earned,
                        'total_possible':
                        possible,
                        'passing_grade':
                        passing_grade,
                        'display_name':
                        subsection_grade.display_name,
                        'location':
                        unicode(subsection_grade.location),
                        'assigment_url':
                        reverse('jump_to_id',
                                kwargs={
                                    'course_id':
                                    unicode(course_key),
                                    'module_id':
                                    unicode(subsection_grade.location),
                                })
                    })
                    if earned > 0:
                        total_earned += earned
                        total_possible += possible

        if total_possible > 0:
            answered_percent = float(total_earned) / total_possible
        return (grades, answered_percent, course_grade.percent)
Ejemplo n.º 29
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 (int): Include course enrollment of this number of days.
        """
        persistent_course_grades = self.get_course_completions(
            lrs_configuration.enterprise_customer, days)
        users = self.prefetch_users(persistent_course_grades)
        course_overviews = self.prefetch_courses(persistent_course_grades)

        for persistent_course_grade in persistent_course_grades:
            error_message = None
            user = users.get(persistent_course_grade.user_id)
            course_overview = course_overviews.get(
                persistent_course_grade.course_id)
            course_grade = CourseGradeFactory().read(
                user, course_key=persistent_course_grade.course_id)
            xapi_transmission_queryset = XAPILearnerDataTransmissionAudit.objects.filter(
                user=user, course_id=persistent_course_grade.course_id)
            if not xapi_transmission_queryset.exists():
                LOGGER.warning(
                    'XAPILearnerDataTransmissionAudit object does not exist for user: {username}, course: '
                    '{course_id} so skipping the course completion statement to xapi.'
                )
                continue
            try:
                send_course_completion_statement(lrs_configuration, user,
                                                 course_overview, course_grade)
            except ClientError:
                error_message = 'Client error while sending course completion to xAPI for ' \
                                'enterprise customer: {enterprise_customer}, user: {username} ' \
                                'and course: {course_id}'.format(
                                    enterprise_customer=lrs_configuration.enterprise_customer.name,
                                    username=user.username if user else '',
                                    course_id=persistent_course_grade.course_id
                                )
                LOGGER.exception(error_message)
                status = 500
            else:
                LOGGER.info(
                    'Successfully sent course completion to xAPI for user: {username} for course: {course_id}'
                    .format(username=user.username if user else '',
                            course_id=persistent_course_grade.course_id))
                status = 200
            fields = {'status': status, 'error_message': error_message}
            if status == 200:
                fields.update({
                    'grade': course_grade.percent,
                    'timestamp': course_grade.passed_timestamp
                })
            xapi_transmission_queryset.update(**fields)
Ejemplo n.º 30
0
def user_course_passed(user, course_key):
    """
       Get if user passed course with percert
    """
    response = CourseGradeFactory().read(user, course_key=course_key)
    if response is None:
        logger.error(
            'CorfoGenerateCode - Error to get CourseGradeFactory().read(...), user: {}, course: {}'
            .format(user, str(course_key)))
        return None, None
    return response.passed, response.percent