Merge pull request #21341 from edx/mroytman/EDUCATOR-4432-make-course-grade-filter-more-robust

make course grade filter robust against missing minimum filter as wel…
This commit is contained in:
Michael Roytman
2019-08-14 14:14:21 -04:00
committed by GitHub
2 changed files with 78 additions and 13 deletions

View File

@@ -583,25 +583,26 @@ class GradebookView(GradeViewMixin, PaginatedAPIView):
if request.GET.get('course_grade_min') or request.GET.get('course_grade_max'):
grade_conditions = {}
q_object = Q()
if request.GET.get('course_grade_min'):
course_grade_min = request.GET.get('course_grade_min')
if course_grade_min:
course_grade_min = float(request.GET.get('course_grade_min')) / 100
grade_conditions['percent_grade__gte'] = course_grade_min
if course_grade_min == 0:
subquery_grade_absent = ~Exists(
PersistentCourseGrade.objects.filter(
course_id=OuterRef('course'),
user_id=OuterRef('user_id'),
)
)
annotations['course_grade_absent'] = subquery_grade_absent
q_object |= Q(course_grade_absent=True)
if request.GET.get('course_grade_max'):
course_grade_max = float(request.GET.get('course_grade_max')) / 100
grade_conditions['percent_grade__lte'] = course_grade_max
if not course_grade_min or course_grade_min == 0:
subquery_grade_absent = ~Exists(
PersistentCourseGrade.objects.filter(
course_id=OuterRef('course'),
user_id=OuterRef('user_id'),
)
)
annotations['course_grade_absent'] = subquery_grade_absent
q_object |= Q(course_grade_absent=True)
subquery_grade_in_range = Exists(
PersistentCourseGrade.objects.filter(
course_id=OuterRef('course'),

View File

@@ -1152,7 +1152,7 @@ class GradebookViewTest(GradebookViewTestBase):
['login_course_staff', 5]
)
@ddt.unpack
def test_filter_course_grade_absent(self, login_method, num_enrollments):
def test_filter_course_grade_absent_with_min(self, login_method, num_enrollments):
with patch('lms.djangoapps.grades.course_grade_factory.CourseGradeFactory.read') as mock_grade:
# even though we're creating actual PersistentCourseGrades below, we still need
# mocked subsection grades
@@ -1210,6 +1210,70 @@ class GradebookViewTest(GradebookViewTestBase):
self.assertEqual(actual_data['total_users_count'], num_enrollments)
self.assertEqual(actual_data['filtered_users_count'], num_enrollments)
@ddt.data(
['login_staff', 4],
['login_course_admin', 5],
['login_course_staff', 5]
)
@ddt.unpack
def test_filter_course_grade_absent_without_min(self, login_method, num_enrollments):
with patch('lms.djangoapps.grades.course_grade_factory.CourseGradeFactory.read') as mock_grade:
# even though we're creating actual PersistentCourseGrades below, we still need
# mocked subsection grades
mock_grade.side_effect = [
self.mock_course_grade(self.student, passed=True, percent=0.0),
self.mock_course_grade(self.other_student, passed=False, percent=0.45),
self.mock_course_grade(self.program_student, passed=True, percent=0.75),
]
PersistentCourseGrade(
user_id=self.other_student.id,
course_id=self.course_key,
percent_grade=0.45
).save()
PersistentCourseGrade(
user_id=self.program_student.id,
course_id=self.course_key,
percent_grade=0.75
).save()
with override_waffle_flag(self.waffle_flag, active=True):
getattr(self, login_method)()
resp = self.client.get(
self.get_url(course_key=self.course.id) + '?course_grade_max=80'
)
expected_results = [
OrderedDict([
('user_id', self.student.id),
('username', self.student.username),
('email', ''),
('percent', 0.0),
('section_breakdown', self.expected_subsection_grades()),
]),
OrderedDict([
('user_id', self.other_student.id),
('username', self.other_student.username),
('email', ''),
('percent', 0.45),
('section_breakdown', self.expected_subsection_grades()),
]),
OrderedDict([
('user_id', self.program_student.id),
('username', self.program_student.username),
('email', ''),
('external_user_key', 'program_user_key_0'),
('percent', 0.75),
('section_breakdown', self.expected_subsection_grades()),
])
]
self.assertEqual(status.HTTP_200_OK, resp.status_code)
actual_data = dict(resp.data)
self.assertEqual(expected_results, actual_data['results'])
self.assertEqual(actual_data['total_users_count'], num_enrollments)
self.assertEqual(actual_data['filtered_users_count'], num_enrollments)
@ddt.ddt
class GradebookBulkUpdateViewTest(GradebookViewTestBase):