From 9c769dd31174ebff103ed12d5dd96d453cbffe66 Mon Sep 17 00:00:00 2001 From: Jansen Kantor Date: Fri, 21 Apr 2023 13:57:59 -0400 Subject: [PATCH] feat: gradebook api real name for masters students (#32104) --- lms/djangoapps/grades/rest_api/serializers.py | 1 + .../grades/rest_api/v1/gradebook_views.py | 14 +++++- .../rest_api/v1/tests/test_gradebook_views.py | 45 +++++++++++++++++++ 3 files changed, 59 insertions(+), 1 deletion(-) diff --git a/lms/djangoapps/grades/rest_api/serializers.py b/lms/djangoapps/grades/rest_api/serializers.py index c370788a67..b5c757f31b 100644 --- a/lms/djangoapps/grades/rest_api/serializers.py +++ b/lms/djangoapps/grades/rest_api/serializers.py @@ -52,6 +52,7 @@ class StudentGradebookEntrySerializer(serializers.Serializer): """ user_id = serializers.IntegerField() username = serializers.CharField() + full_name = serializers.CharField(required=False) email = serializers.EmailField() external_user_key = serializers.CharField(required=False) percent = serializers.FloatField() diff --git a/lms/djangoapps/grades/rest_api/v1/gradebook_views.py b/lms/djangoapps/grades/rest_api/v1/gradebook_views.py index 6f2b45feae..6feedbf241 100644 --- a/lms/djangoapps/grades/rest_api/v1/gradebook_views.py +++ b/lms/djangoapps/grades/rest_api/v1/gradebook_views.py @@ -507,7 +507,19 @@ class GradebookView(GradeViewMixin, PaginatedAPIView): kwargs=dict(course_id=str(course.id), student_id=user.id) ) user_entry['user_id'] = user.id - user_entry['full_name'] = user.profile.name + + def is_masters_student(): + # If this is a multiple-user lookup (didn't use the username param) we insert + # user.enrollment_mode in _get_enrolled_users. If it is a single-user lookup + # (did use username) then we'll need to look up the single user's enrollment mode + if hasattr(user, 'enrollment_mode'): + return user.enrollment_mode == CourseMode.MASTERS + else: + mode, _ = CourseEnrollment.enrollment_mode_for_user(user, str(course.id)) + return mode == CourseMode.MASTERS + + if is_masters_student(): + user_entry['full_name'] = user.profile.name external_user_key = get_external_key_by_user_and_course(user, course.id) if external_user_key: diff --git a/lms/djangoapps/grades/rest_api/v1/tests/test_gradebook_views.py b/lms/djangoapps/grades/rest_api/v1/tests/test_gradebook_views.py index a6adfc3a3c..5d7c428c22 100644 --- a/lms/djangoapps/grades/rest_api/v1/tests/test_gradebook_views.py +++ b/lms/djangoapps/grades/rest_api/v1/tests/test_gradebook_views.py @@ -8,6 +8,7 @@ from collections import OrderedDict, namedtuple from contextlib import contextmanager from datetime import datetime from unittest.mock import MagicMock, patch +from common.djangoapps.student.models.course_enrollment import CourseEnrollment import ddt import pytest @@ -779,6 +780,7 @@ class GradebookViewTest(GradebookViewTestBase): OrderedDict([ ('user_id', self.program_masters_student.id), ('username', self.program_masters_student.username), + ('full_name', self.program_masters_student.profile.name), ('email', self.program_masters_student.email), ('external_user_key', 'program_user_key_0'), ('percent', 0.75), @@ -827,6 +829,7 @@ class GradebookViewTest(GradebookViewTestBase): OrderedDict([ ('user_id', self.program_masters_student.id), ('username', self.program_masters_student.username), + ('full_name', self.program_masters_student.profile.name), ('email', self.program_masters_student.email), ('external_user_key', 'program_user_key_0'), ('percent', 0.75), @@ -913,6 +916,7 @@ class GradebookViewTest(GradebookViewTestBase): OrderedDict([ ('user_id', self.program_masters_student.id), ('username', self.program_masters_student.username), + ('full_name', self.program_masters_student.profile.name), ('email', self.program_masters_student.email), ('external_user_key', 'program_user_key_0'), ('percent', 0.75), @@ -1462,6 +1466,47 @@ class GradebookViewTest(GradebookViewTestBase): ] ) + def test_full_name__full_course(self): + """ Test that masters students have full_name and that no one else in the course does. """ + self.login_course_staff() + with override_waffle_flag(self.waffle_flag, active=True): + with self._mock_all_course_grade_reads(): + response = self.client.get(self.get_url(course_key=self.course.id)) + + assert status.HTTP_200_OK == response.status_code + response_data = dict(response.data) + assert response_data['next'] is None + + usernames = set() + masters_students = set() + for row in response_data['results']: + username = row['username'] + usernames.add(username) + enrollment = CourseEnrollment.objects.get(user__username=username, course_id=self.course.id) + if enrollment.mode == CourseMode.MASTERS: + masters_students.add(username) + assert 'full_name' in row + assert row['full_name'] == enrollment.user.profile.name + else: + assert 'full_name' not in row + assert self.program_masters_student.username in masters_students + assert self.program_masters_student.username in usernames + + def test_full_name__single_student(self): + """ Test that a request for a masters student includes a full name """ + self.login_course_staff() + with override_waffle_flag(self.waffle_flag, active=True): + with patch('lms.djangoapps.grades.course_grade_factory.CourseGradeFactory.read') as mock_grade: + mock_grade.return_value = self.mock_course_grade(self.student, passed=True, percent=0.85) + response = self.client.get(self.get_url( + course_key=self.course.id, + username=self.program_masters_student.username + )) + + assert status.HTTP_200_OK == response.status_code + response_data = dict(response.data) + assert response_data['full_name'] == self.program_masters_student.profile.name + @ddt.ddt class GradebookBulkUpdateViewTest(GradebookViewTestBase):