Commit e72a5629 by Eric Fischer Committed by GitHub

Add passing_users to course summary (#170)

EDU-153
parent 5a85c451
...@@ -8,3 +8,4 @@ Gabe Mulley <gabe@edx.org> ...@@ -8,3 +8,4 @@ Gabe Mulley <gabe@edx.org>
Jason Bau <jbau@stanford.edu> Jason Bau <jbau@stanford.edu>
John Jarvis <jarv@edx.org> John Jarvis <jarv@edx.org>
Dmitry Viskov <dmitry.viskov@webenterprise.ru> Dmitry Viskov <dmitry.viskov@webenterprise.ru>
Eric Fischer <efischer@edx.org>
...@@ -161,15 +161,17 @@ class Command(BaseCommand): ...@@ -161,15 +161,17 @@ class Command(BaseCommand):
progress.update(1) progress.update(1)
date = date + datetime.timedelta(days=1) date = date + datetime.timedelta(days=1)
for mode, ratio in enrollment_mode_ratios.iteritems(): for index, (mode, ratio) in enumerate(enrollment_mode_ratios.iteritems()):
count = int(ratio * daily_total) count = int(ratio * daily_total)
pass_rate = min(random.normalvariate(.45 + (.1 * index), .15), 1.0)
cumulative_count = count + random.randint(0, 100) cumulative_count = count + random.randint(0, 100)
models.CourseMetaSummaryEnrollment.objects.create( models.CourseMetaSummaryEnrollment.objects.create(
course_id=course_id, catalog_course_title='Demo Course', catalog_course='Demo_Course', course_id=course_id, catalog_course_title='Demo Course', catalog_course='Demo_Course',
start_time=timezone.now() - datetime.timedelta(weeks=6), start_time=timezone.now() - datetime.timedelta(weeks=6),
end_time=timezone.now() + datetime.timedelta(weeks=10), end_time=timezone.now() + datetime.timedelta(weeks=10),
pacing_type='self_paced', availability='Starting Soon', enrollment_mode=mode, count=count, pacing_type='self_paced', availability='Starting Soon', enrollment_mode=mode, count=count,
cumulative_count=cumulative_count, count_change_7_days=random.randint(-50, 50)) cumulative_count=cumulative_count, count_change_7_days=random.randint(-50, 50),
passing_users=int(cumulative_count * pass_rate))
models.CourseProgramMetadata.objects.create(course_id=course_id, program_id='Demo_Program', models.CourseProgramMetadata.objects.create(course_id=course_id, program_id='Demo_Program',
program_type='Demo', program_title='Demo Program') program_type='Demo', program_title='Demo Program')
......
...@@ -78,6 +78,7 @@ class CourseMetaSummaryEnrollment(BaseCourseModel): ...@@ -78,6 +78,7 @@ class CourseMetaSummaryEnrollment(BaseCourseModel):
count = models.IntegerField(null=False) count = models.IntegerField(null=False)
cumulative_count = models.IntegerField(null=False) cumulative_count = models.IntegerField(null=False)
count_change_7_days = models.IntegerField(default=0) count_change_7_days = models.IntegerField(default=0)
passing_users = models.IntegerField(default=0)
class Meta(BaseCourseModel.Meta): class Meta(BaseCourseModel.Meta):
db_table = 'course_meta_summary_enrollment' db_table = 'course_meta_summary_enrollment'
......
...@@ -561,6 +561,7 @@ class CourseMetaSummaryEnrollmentSerializer(ModelSerializerWithCreatedField, Dyn ...@@ -561,6 +561,7 @@ class CourseMetaSummaryEnrollmentSerializer(ModelSerializerWithCreatedField, Dyn
count = serializers.IntegerField(default=0) count = serializers.IntegerField(default=0)
cumulative_count = serializers.IntegerField(default=0) cumulative_count = serializers.IntegerField(default=0)
count_change_7_days = serializers.IntegerField(default=0) count_change_7_days = serializers.IntegerField(default=0)
passing_users = serializers.IntegerField(default=0)
enrollment_modes = serializers.SerializerMethodField() enrollment_modes = serializers.SerializerMethodField()
programs = serializers.SerializerMethodField() programs = serializers.SerializerMethodField()
......
...@@ -36,7 +36,7 @@ class CourseSummariesViewTests(VerifyCourseIdMixin, TestCaseWithAuthentication, ...@@ -36,7 +36,7 @@ class CourseSummariesViewTests(VerifyCourseIdMixin, TestCaseWithAuthentication,
start_time=datetime.datetime(2016, 10, 11, tzinfo=pytz.utc), start_time=datetime.datetime(2016, 10, 11, tzinfo=pytz.utc),
end_time=datetime.datetime(2016, 12, 18, tzinfo=pytz.utc), end_time=datetime.datetime(2016, 12, 18, tzinfo=pytz.utc),
pacing_type='instructor', availability=kwargs['availability'], enrollment_mode=mode, pacing_type='instructor', availability=kwargs['availability'], enrollment_mode=mode,
count=5, cumulative_count=10, count_change_7_days=1, create=self.now,) count=5, cumulative_count=10, count_change_7_days=1, passing_users=1, create=self.now,)
if 'programs' in kwargs and kwargs['programs']: if 'programs' in kwargs and kwargs['programs']:
# Create a link from this course to a program # Create a link from this course to a program
G(models.CourseProgramMetadata, course_id=model_id, program_id=CourseSamples.program_ids[0], G(models.CourseProgramMetadata, course_id=model_id, program_id=CourseSamples.program_ids[0],
...@@ -70,6 +70,7 @@ class CourseSummariesViewTests(VerifyCourseIdMixin, TestCaseWithAuthentication, ...@@ -70,6 +70,7 @@ class CourseSummariesViewTests(VerifyCourseIdMixin, TestCaseWithAuthentication,
('count', count_factor * num_modes), ('count', count_factor * num_modes),
('cumulative_count', cumulative_count_factor * num_modes), ('cumulative_count', cumulative_count_factor * num_modes),
('count_change_7_days', count_change_factor * num_modes), ('count_change_7_days', count_change_factor * num_modes),
('passing_users', count_change_factor * num_modes),
('enrollment_modes', {}), ('enrollment_modes', {}),
]) ])
summary['enrollment_modes'].update({ summary['enrollment_modes'].update({
...@@ -77,6 +78,7 @@ class CourseSummariesViewTests(VerifyCourseIdMixin, TestCaseWithAuthentication, ...@@ -77,6 +78,7 @@ class CourseSummariesViewTests(VerifyCourseIdMixin, TestCaseWithAuthentication,
'count': count_factor, 'count': count_factor,
'cumulative_count': cumulative_count_factor, 'cumulative_count': cumulative_count_factor,
'count_change_7_days': count_change_factor, 'count_change_7_days': count_change_factor,
'passing_users': count_change_factor,
} for mode in modes } for mode in modes
}) })
summary['enrollment_modes'].update({ summary['enrollment_modes'].update({
...@@ -84,6 +86,7 @@ class CourseSummariesViewTests(VerifyCourseIdMixin, TestCaseWithAuthentication, ...@@ -84,6 +86,7 @@ class CourseSummariesViewTests(VerifyCourseIdMixin, TestCaseWithAuthentication,
'count': 0, 'count': 0,
'cumulative_count': 0, 'cumulative_count': 0,
'count_change_7_days': 0, 'count_change_7_days': 0,
'passing_users': 0,
} for mode in set(enrollment_modes.ALL) - set(modes) } for mode in set(enrollment_modes.ALL) - set(modes)
}) })
no_prof = summary['enrollment_modes'].pop(enrollment_modes.PROFESSIONAL_NO_ID) no_prof = summary['enrollment_modes'].pop(enrollment_modes.PROFESSIONAL_NO_ID)
...@@ -92,6 +95,7 @@ class CourseSummariesViewTests(VerifyCourseIdMixin, TestCaseWithAuthentication, ...@@ -92,6 +95,7 @@ class CourseSummariesViewTests(VerifyCourseIdMixin, TestCaseWithAuthentication,
'count': prof['count'] + no_prof['count'], 'count': prof['count'] + no_prof['count'],
'cumulative_count': prof['cumulative_count'] + no_prof['cumulative_count'], 'cumulative_count': prof['cumulative_count'] + no_prof['cumulative_count'],
'count_change_7_days': prof['count_change_7_days'] + no_prof['count_change_7_days'], 'count_change_7_days': prof['count_change_7_days'] + no_prof['count_change_7_days'],
'passing_users': prof['passing_users'] + no_prof['passing_users'],
}) })
if programs: if programs:
summary['programs'] = [CourseSamples.program_ids[0]] summary['programs'] = [CourseSamples.program_ids[0]]
...@@ -159,3 +163,10 @@ class CourseSummariesViewTests(VerifyCourseIdMixin, TestCaseWithAuthentication, ...@@ -159,3 +163,10 @@ class CourseSummariesViewTests(VerifyCourseIdMixin, TestCaseWithAuthentication,
response = self.authenticated_get(self.path(exclude=self.always_exclude[:1], programs=['True'])) response = self.authenticated_get(self.path(exclude=self.always_exclude[:1], programs=['True']))
self.assertEquals(response.status_code, 200) self.assertEquals(response.status_code, 200)
self.assertItemsEqual(response.data, self.all_expected_results(programs=True)) self.assertItemsEqual(response.data, self.all_expected_results(programs=True))
@ddt.data('passing_users', )
def test_exclude(self, field):
self.generate_data()
response = self.authenticated_get(self.path(exclude=[field]))
self.assertEquals(response.status_code, 200)
self.assertEquals(str(response.data).count(field), 0)
...@@ -54,7 +54,8 @@ class CourseSummariesView(APIListView): ...@@ -54,7 +54,8 @@ class CourseSummariesView(APIListView):
model = models.CourseMetaSummaryEnrollment model = models.CourseMetaSummaryEnrollment
model_id_field = 'course_id' model_id_field = 'course_id'
programs_model = models.CourseProgramMetadata programs_model = models.CourseProgramMetadata
count_fields = ('count', 'cumulative_count', 'count_change_7_days') # are initialized to 0 by default count_fields = ('count', 'cumulative_count', 'count_change_7_days',
'passing_users') # are initialized to 0 by default
summary_meta_fields = ['catalog_course_title', 'catalog_course', 'start_time', 'end_time', summary_meta_fields = ['catalog_course_title', 'catalog_course', 'start_time', 'end_time',
'pacing_type', 'availability'] # fields to extract from summary model 'pacing_type', 'availability'] # fields to extract from summary model
...@@ -120,6 +121,10 @@ class CourseSummariesView(APIListView): ...@@ -120,6 +121,10 @@ class CourseSummariesView(APIListView):
# don't do expensive looping for programs if we are just going to throw it away # don't do expensive looping for programs if we are just going to throw it away
field_dict = self.add_programs(field_dict) field_dict = self.add_programs(field_dict)
for field in self.exclude:
for mode in field_dict['enrollment_modes']:
_ = field_dict['enrollment_modes'][mode].pop(field, None)
return field_dict return field_dict
def add_programs(self, field_dict): def add_programs(self, field_dict):
......
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