Add course flag and service for grade override
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
This module contains various configuration settings via
|
||||
waffle switches for the Grades app.
|
||||
"""
|
||||
from openedx.core.djangoapps.waffle_utils import WaffleSwitchNamespace
|
||||
from openedx.core.djangoapps.waffle_utils import WaffleSwitchNamespace, WaffleFlagNamespace, CourseWaffleFlag
|
||||
|
||||
# Namespace
|
||||
WAFFLE_NAMESPACE = u'grades'
|
||||
@@ -12,9 +12,27 @@ WRITE_ONLY_IF_ENGAGED = u'write_only_if_engaged'
|
||||
ASSUME_ZERO_GRADE_IF_ABSENT = u'assume_zero_grade_if_absent'
|
||||
ESTIMATE_FIRST_ATTEMPTED = u'estimate_first_attempted'
|
||||
|
||||
# Course Flags
|
||||
REJECTED_EXAM_OVERRIDES_GRADE = u'rejected_exam_overrides_grade'
|
||||
|
||||
|
||||
def waffle():
|
||||
"""
|
||||
Returns the namespaced, cached, audited Waffle class for Grades.
|
||||
"""
|
||||
return WaffleSwitchNamespace(name=WAFFLE_NAMESPACE, log_prefix=u'Grades: ')
|
||||
|
||||
|
||||
def waffle_flags():
|
||||
"""
|
||||
Returns the namespaced, cached, audited Waffle flags dictionary for Grades.
|
||||
"""
|
||||
namespace = WaffleFlagNamespace(name=WAFFLE_NAMESPACE, log_prefix=u'Grades: ')
|
||||
return {
|
||||
# By default, enable rejected exam grade overrides. Can be disabled on a course-by-course basis.
|
||||
REJECTED_EXAM_OVERRIDES_GRADE: CourseWaffleFlag(
|
||||
namespace,
|
||||
REJECTED_EXAM_OVERRIDES_GRADE,
|
||||
flag_undefined_default=True
|
||||
)
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ from opaque_keys.edx.keys import CourseKey, UsageKey
|
||||
from track.event_transaction_utils import create_new_event_transaction_id, set_event_transaction_type
|
||||
from util.date_utils import to_timestamp
|
||||
|
||||
from .config.waffle import waffle_flags, REJECTED_EXAM_OVERRIDES_GRADE
|
||||
from .constants import ScoreDatabaseTableEnum
|
||||
from .models import PersistentSubsectionGrade, PersistentSubsectionGradeOverride
|
||||
|
||||
@@ -141,3 +142,7 @@ class GradesService(object):
|
||||
score_db_table=ScoreDatabaseTableEnum.overrides
|
||||
)
|
||||
)
|
||||
|
||||
def should_override_grade_on_rejected_exam(self, course_key):
|
||||
"""Convienence function to return the state of the CourseWaffleFlag REJECTED_EXAM_OVERRIDES_GRADE"""
|
||||
return waffle_flags()[REJECTED_EXAM_OVERRIDES_GRADE].is_enabled(course_key)
|
||||
|
||||
@@ -12,9 +12,18 @@ from util.date_utils import to_timestamp
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
|
||||
|
||||
from ..config.waffle import REJECTED_EXAM_OVERRIDES_GRADE
|
||||
from ..constants import ScoreDatabaseTableEnum
|
||||
|
||||
|
||||
class MockWaffleFlag():
|
||||
def __init__(self, state):
|
||||
self.state = state
|
||||
|
||||
def is_enabled(self, course_key):
|
||||
return self.state
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class GradesServiceTests(ModuleStoreTestCase):
|
||||
"""
|
||||
@@ -44,11 +53,17 @@ class GradesServiceTests(ModuleStoreTestCase):
|
||||
self.mock_create_id.return_value = 1
|
||||
self.type_patcher = patch('lms.djangoapps.grades.services.set_event_transaction_type')
|
||||
self.mock_set_type = self.type_patcher.start()
|
||||
self.flag_patcher = patch('lms.djangoapps.grades.services.waffle_flags')
|
||||
self.mock_waffle_flags = self.flag_patcher.start()
|
||||
self.mock_waffle_flags.return_value = {
|
||||
REJECTED_EXAM_OVERRIDES_GRADE: MockWaffleFlag(True)
|
||||
}
|
||||
|
||||
def tearDown(self):
|
||||
self.recalc_patcher.stop()
|
||||
self.id_patcher.stop()
|
||||
self.type_patcher.stop()
|
||||
self.flag_patcher.stop()
|
||||
|
||||
def subsection_grade_to_dict(self, grade):
|
||||
return {
|
||||
@@ -218,3 +233,10 @@ class GradesServiceTests(ModuleStoreTestCase):
|
||||
@ddt.unpack
|
||||
def test_get_key(self, input_key, output_key, key_cls):
|
||||
self.assertEqual(_get_key(input_key, key_cls), output_key)
|
||||
|
||||
def test_should_override_grade_on_rejected_exam(self):
|
||||
self.assertTrue(self.service.should_override_grade_on_rejected_exam('course-v1:edX+DemoX+Demo_Course'))
|
||||
self.mock_waffle_flags.return_value = {
|
||||
REJECTED_EXAM_OVERRIDES_GRADE: MockWaffleFlag(False)
|
||||
}
|
||||
self.assertFalse(self.service.should_override_grade_on_rejected_exam('course-v1:edX+DemoX+Demo_Course'))
|
||||
|
||||
Reference in New Issue
Block a user