refactor: new logic for when to enable Gradebook bulk management (#28080)

Formerly, bulk management was enabled by sending feature feature
toggle to Gradebook which also checked for the presence of a 
master's track to enable the feature. This default enables for all
courses with a master's track and also allows selective enabling 
for courses with the feature flag.
This commit is contained in:
Nathan Sprenkle
2021-08-02 11:06:08 -04:00
committed by GitHub
parent 5fa4fcea5e
commit 121afd0c5f
4 changed files with 54 additions and 9 deletions

View File

@@ -16,7 +16,7 @@ from common.djangoapps.track.event_transaction_utils import create_new_event_tra
from lms.djangoapps.grades import constants, context, course_data, events
# Grades APIs that should NOT belong within the Grades subsystem
# TODO move Gradebook to be an external feature outside of core Grades
from lms.djangoapps.grades.config.waffle import gradebook_can_see_bulk_management, is_writable_gradebook_enabled
from lms.djangoapps.grades.config.waffle import gradebook_bulk_management_enabled, is_writable_gradebook_enabled
# Public Grades Factories
from lms.djangoapps.grades.course_grade_factory import CourseGradeFactory
from lms.djangoapps.grades.models_api import *

View File

@@ -150,10 +150,8 @@ def is_writable_gradebook_enabled(course_key):
return waffle_flags()[WRITABLE_GRADEBOOK].is_enabled(course_key)
def gradebook_can_see_bulk_management(course_key):
def gradebook_bulk_management_enabled(course_key):
"""
Returns whether bulk management features should be visible for the given course.
(provided that course contains a masters track, as of this writing)
Returns whether bulk management features should be specially enabled for a given course.
"""
return waffle_flags()[BULK_MANAGEMENT].is_enabled(course_key)

View File

@@ -21,7 +21,7 @@ from rest_framework.response import Response
from rest_framework.views import APIView
from common.djangoapps.student.auth import has_course_author_access
from common.djangoapps.student.models import CourseEnrollment, CourseAccessRole
from common.djangoapps.student.models import CourseAccessRole, CourseEnrollment, CourseMode
from common.djangoapps.student.roles import BulkRoleCache
from common.djangoapps.track.event_transaction_utils import (
create_new_event_transaction_id,
@@ -35,7 +35,7 @@ from lms.djangoapps.grades.api import CourseGradeFactory, clear_prefetched_cours
from lms.djangoapps.grades.api import constants as grades_constants
from lms.djangoapps.grades.api import context as grades_context
from lms.djangoapps.grades.api import events as grades_events
from lms.djangoapps.grades.api import gradebook_can_see_bulk_management as can_see_bulk_management
from lms.djangoapps.grades.api import gradebook_bulk_management_enabled
from lms.djangoapps.grades.api import is_writable_gradebook_enabled, prefetch_course_and_subsection_grades
from lms.djangoapps.grades.course_data import CourseData
from lms.djangoapps.grades.grade_utils import are_grades_frozen
@@ -56,6 +56,7 @@ from lms.djangoapps.grades.subsection_grade_factory import SubsectionGradeFactor
from lms.djangoapps.grades.tasks import recalculate_subsection_grade_v3
from lms.djangoapps.program_enrollments.api import get_external_key_by_user_and_course
from openedx.core.djangoapps.course_groups import cohorts
from openedx.core.djangoapps.enrollments.api import get_course_enrollment_details
from openedx.core.djangoapps.util.forms import to_bool
from openedx.core.lib.api.view_utils import (
DeveloperErrorViewMixin,
@@ -281,10 +282,19 @@ class CourseGradingView(BaseCourseView):
'assignment_types': self._get_assignment_types(course),
'subsections': self._get_subsections(course, graded_only),
'grades_frozen': are_grades_frozen(course_key),
'can_see_bulk_management': can_see_bulk_management(course_key),
'can_see_bulk_management': self.can_see_bulk_management(course_key),
}
return Response(results)
def can_see_bulk_management(self, course_key):
"""
Whether or not to show bulk management for this course. Currently, if a course has a
master's track or is enabled with the grades.bulk_management course waffle flag.
"""
course_modes = get_course_enrollment_details(str(course_key), include_expired=True).get('course_modes', [])
course_has_masters_track = any((course_mode['slug'] == CourseMode.MASTERS for course_mode in course_modes))
return course_has_masters_track or gradebook_bulk_management_enabled(course_key)
def _get_assignment_types(self, course):
"""
Helper function that returns a serialized dict of assignment types

View File

@@ -32,7 +32,7 @@ from common.djangoapps.student.tests.factories import InstructorFactory
from common.djangoapps.student.tests.factories import StaffFactory
from lms.djangoapps.certificates.data import CertificateStatuses
from lms.djangoapps.certificates.models import GeneratedCertificate
from lms.djangoapps.grades.config.waffle import WRITABLE_GRADEBOOK, waffle_flags
from lms.djangoapps.grades.config.waffle import BULK_MANAGEMENT, WRITABLE_GRADEBOOK, waffle_flags
from lms.djangoapps.grades.constants import GradeOverrideFeatureEnum
from lms.djangoapps.grades.course_data import CourseData
from lms.djangoapps.grades.course_grade import CourseGrade
@@ -245,6 +245,43 @@ class CourseGradingViewTest(SharedModuleStoreTestCase, APITestCase):
expected_data['grades_frozen'] = True
assert expected_data == resp.data
@patch('lms.djangoapps.grades.rest_api.v1.gradebook_views.get_course_enrollment_details')
def test_can_see_bulk_management_non_masters(self, mock_course_enrollment_details):
# Given a course without a master's track
mock_course_enrollment_details.return_value = {'course_modes': [{'slug': 'not-masters'}]}
# When getting course grading view
self.client.login(username=self.staff.username, password=self.password)
resp = self.client.get(self.get_url(self.course_key))
# Course staff should not be shown bulk management controls
assert resp.status_code == status.HTTP_200_OK
assert resp.data['can_see_bulk_management'] is False
@patch('lms.djangoapps.grades.rest_api.v1.gradebook_views.get_course_enrollment_details')
def test_can_see_bulk_management_masters(self, mock_course_enrollment_details):
# Given a course with a master's track
mock_course_enrollment_details.return_value = {'course_modes': [{'slug': 'not-masters'}, {'slug': 'masters'}]}
# When getting course grading view
self.client.login(username=self.staff.username, password=self.password)
resp = self.client.get(self.get_url(self.course_key))
# Course staff should be shown bulk management controls (default on for master's track courses)
assert resp.status_code == status.HTTP_200_OK
assert resp.data['can_see_bulk_management'] is True
@override_waffle_flag(waffle_flags()[BULK_MANAGEMENT], active=True)
def test_can_see_bulk_management_force_enabled(self):
# Given a course without (or with) a master's track where bulk management is enabled with the config flag
# When getting course grading view
self.client.login(username=self.staff.username, password=self.password)
resp = self.client.get(self.get_url(self.course_key))
# # Course staff should be able to see bulk management
assert resp.status_code == status.HTTP_200_OK
assert resp.data['can_see_bulk_management'] is True
class GradebookViewTestBase(GradeViewTestMixin, APITestCase):
"""