Commit 6db3c4e5 by Zia Fazal

updated course metrics api to return additional fields

parent 37aea77e
...@@ -2338,7 +2338,7 @@ class CoursesApiTests(ModuleStoreTestCase): ...@@ -2338,7 +2338,7 @@ class CoursesApiTests(ModuleStoreTestCase):
self.assertEqual(response.status_code, 201) self.assertEqual(response.status_code, 201)
org_id = response.data['id'] org_id = response.data['id']
for i in xrange(1, 5): for i in xrange(1, users_to_add):
local_content_name = 'Video_Sequence{}'.format(i) local_content_name = 'Video_Sequence{}'.format(i)
local_content = ItemFactory.create( local_content = ItemFactory.create(
category="videosequence", category="videosequence",
...@@ -2357,6 +2357,9 @@ class CoursesApiTests(ModuleStoreTestCase): ...@@ -2357,6 +2357,9 @@ class CoursesApiTests(ModuleStoreTestCase):
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertEqual(response.data['users_enrolled'], users_to_add + USER_COUNT) self.assertEqual(response.data['users_enrolled'], users_to_add + USER_COUNT)
self.assertGreaterEqual(response.data['users_started'], 1) self.assertGreaterEqual(response.data['users_started'], 1)
self.assertEqual(response.data['users_not_started'], users_to_add + USER_COUNT - 1)
self.assertEqual(response.data['modules_completed'], users_to_add - 1)
self.assertEqual(response.data['users_completed'], 0)
self.assertIsNotNone(response.data['grade_cutoffs']) self.assertIsNotNone(response.data['grade_cutoffs'])
self.assertEqual(response.data['num_threads'], 5) self.assertEqual(response.data['num_threads'], 5)
self.assertEqual(response.data['num_active_threads'], 3) self.assertEqual(response.data['num_active_threads'], 3)
...@@ -2403,7 +2406,7 @@ class CoursesApiTests(ModuleStoreTestCase): ...@@ -2403,7 +2406,7 @@ class CoursesApiTests(ModuleStoreTestCase):
CourseEnrollmentFactory.create(user=user, course_id=self.course.id) CourseEnrollmentFactory.create(user=user, course_id=self.course.id)
# create course completions # create course completions
for user in users: for i, user in enumerate(users):
completions_uri = '{}/{}/completions/'.format(self.base_courses_uri, self.test_course_id) completions_uri = '{}/{}/completions/'.format(self.base_courses_uri, self.test_course_id)
completions_data = { completions_data = {
'content_id': unicode(self.course_content.scope_ids.usage_id), 'content_id': unicode(self.course_content.scope_ids.usage_id),
...@@ -2413,6 +2416,15 @@ class CoursesApiTests(ModuleStoreTestCase): ...@@ -2413,6 +2416,15 @@ class CoursesApiTests(ModuleStoreTestCase):
response = self.do_post(completions_uri, completions_data) response = self.do_post(completions_uri, completions_data)
self.assertEqual(response.status_code, 201) self.assertEqual(response.status_code, 201)
# mark two users a complete
if i % 2 == 0:
StudentGradebook.objects.get_or_create(
user=user,
course_id=self.course.id,
grade=0.9,
proforma_grade=0.91,
)
course_metrics_uri = '{}/{}/metrics/?groups={}'.format( course_metrics_uri = '{}/{}/metrics/?groups={}'.format(
self.base_courses_uri, self.base_courses_uri,
self.test_course_id, self.test_course_id,
...@@ -2422,6 +2434,9 @@ class CoursesApiTests(ModuleStoreTestCase): ...@@ -2422,6 +2434,9 @@ class CoursesApiTests(ModuleStoreTestCase):
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertEqual(response.data['users_enrolled'], 3) self.assertEqual(response.data['users_enrolled'], 3)
self.assertGreaterEqual(response.data['users_started'], 3) self.assertGreaterEqual(response.data['users_started'], 3)
self.assertEqual(response.data['users_not_started'], 0)
self.assertEqual(response.data['modules_completed'], 3)
self.assertEqual(response.data['users_completed'], 2)
def test_course_data_metrics_user_group_filter_for_multiple_groups_having_members(self): def test_course_data_metrics_user_group_filter_for_multiple_groups_having_members(self):
groups = GroupFactory.create_batch(2) groups = GroupFactory.create_batch(2)
...@@ -2453,6 +2468,9 @@ class CoursesApiTests(ModuleStoreTestCase): ...@@ -2453,6 +2468,9 @@ class CoursesApiTests(ModuleStoreTestCase):
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertEqual(response.data['users_enrolled'], 5) self.assertEqual(response.data['users_enrolled'], 5)
self.assertGreaterEqual(response.data['users_started'], 5) self.assertGreaterEqual(response.data['users_started'], 5)
self.assertEqual(response.data['users_not_started'], 0)
self.assertEqual(response.data['modules_completed'], 5)
self.assertEqual(response.data['users_completed'], 0)
def test_course_workgroups_list(self): def test_course_workgroups_list(self):
projects_uri = self.base_projects_uri projects_uri = self.base_projects_uri
......
...@@ -1561,9 +1561,20 @@ class CoursesMetrics(SecureAPIView): ...@@ -1561,9 +1561,20 @@ class CoursesMetrics(SecureAPIView):
exclude_users=exclude_users, exclude_users=exclude_users,
org_ids=org_ids, org_ids=org_ids,
group_ids=group_ids) group_ids=group_ids)
users_enrolled = users_enrolled_qs.distinct().count()
modules_completed = StudentProgress.get_total_completions(
course_key, exclude_users=exclude_users, org_ids=org_ids, group_ids=group_ids
)
users_completed = StudentGradebook.get_num_users_completed(
course_key, exclude_users=exclude_users, org_ids=org_ids, group_ids=group_ids
)
data = { data = {
'users_enrolled': users_enrolled_qs.distinct().count(), 'users_enrolled': users_enrolled,
'users_started': users_started, 'users_started': users_started,
'users_not_started': users_enrolled - users_started,
'modules_completed': modules_completed,
'users_completed': users_completed,
'grade_cutoffs': course_descriptor.grading_policy['GRADE_CUTOFFS'] 'grade_cutoffs': course_descriptor.grading_policy['GRADE_CUTOFFS']
} }
......
...@@ -2,10 +2,10 @@ ...@@ -2,10 +2,10 @@
Django database models supporting the gradebook app Django database models supporting the gradebook app
""" """
from django.utils import timezone from django.utils import timezone
from django.conf import settings
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.db import models from django.db import models
from django.db.models import Avg, Max, Min, Count from django.db.models import Avg, Max, Min, Count, F
from django.db.models.signals import post_save from django.db.models.signals import post_save
from django.dispatch import receiver from django.dispatch import receiver
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
...@@ -161,6 +161,27 @@ class StudentGradebook(models.Model): ...@@ -161,6 +161,27 @@ class StudentGradebook(models.Model):
return data return data
@classmethod
def get_num_users_completed(cls, course_key, exclude_users=None, org_ids=None, group_ids=None):
"""
Returns count of users those who completed given course.
"""
grade_complete_match_range = getattr(settings, 'GRADEBOOK_GRADE_COMPLETE_PROFORMA_MATCH_RANGE', 0.01)
queryset = cls.objects.filter(
course_id__exact=course_key,
user__is_active=True,
user__courseenrollment__is_active=True,
user__courseenrollment__course_id__exact=course_key,
proforma_grade__lte=F('grade') + grade_complete_match_range,
proforma_grade__gt=0
).exclude(user__id__in=exclude_users)
if org_ids:
queryset = queryset.filter(user__organizations__in=org_ids)
if group_ids:
queryset = queryset.filter(user__groups__in=group_ids)
return queryset.distinct().count()
class StudentGradebookHistory(TimeStampedModel): class StudentGradebookHistory(TimeStampedModel):
""" """
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment