From 4957b981a43c6bb149270fdc094fb8bbddb45015 Mon Sep 17 00:00:00 2001 From: Matt Hughes Date: Fri, 13 Sep 2019 10:24:07 -0400 Subject: [PATCH] Only delete latest grade override if it came from proctoring ... on proctored exam attempt deletion JIRA:EDUCATOR-4642 --- lms/djangoapps/grades/api.py | 9 +++++-- lms/djangoapps/grades/constants.py | 1 + lms/djangoapps/grades/tests/test_services.py | 25 +++++++++++++++++++- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/lms/djangoapps/grades/api.py b/lms/djangoapps/grades/api.py index 4a9e624550..88011448b1 100644 --- a/lms/djangoapps/grades/api.py +++ b/lms/djangoapps/grades/api.py @@ -65,6 +65,7 @@ def override_subsection_grade( requesting_user=overrider, subsection_grade_model=grade, feature=feature, + system=feature, earned_all_override=earned_all, earned_graded_override=earned_graded, ) @@ -93,6 +94,10 @@ def undo_override_subsection_grade(user_id, course_key_or_id, usage_key_or_id, f Fires off a recalculate_subsection_grade async task to update the PersistentSubsectionGrade table. If the override does not exist, no error is raised, it just triggers the recalculation. + + feature: if specified, the deletion will only occur if the + override to be deleted was created by the corresponding + subsystem """ course_key = _get_key(course_key_or_id, CourseKey) usage_key = _get_key(usage_key_or_id, UsageKey) @@ -102,8 +107,8 @@ def undo_override_subsection_grade(user_id, course_key_or_id, usage_key_or_id, f except ObjectDoesNotExist: return - # Older rejected exam attempts that transition to verified might not have an override created - if override is not None: + if override is not None and ( + not feature or feature == override.system): override.delete(feature=feature) # Cache a new event id and event type which the signal handler will use to emit a tracking log event. diff --git a/lms/djangoapps/grades/constants.py b/lms/djangoapps/grades/constants.py index 47f74ba5ed..d38d6b80d8 100644 --- a/lms/djangoapps/grades/constants.py +++ b/lms/djangoapps/grades/constants.py @@ -15,3 +15,4 @@ class ScoreDatabaseTableEnum(object): class GradeOverrideFeatureEnum(object): proctoring = 'PROCTORING' gradebook = 'GRADEBOOK' + grade_import = 'grade-import' diff --git a/lms/djangoapps/grades/tests/test_services.py b/lms/djangoapps/grades/tests/test_services.py index 846172ebdf..27be6bf319 100644 --- a/lms/djangoapps/grades/tests/test_services.py +++ b/lms/djangoapps/grades/tests/test_services.py @@ -259,7 +259,10 @@ class GradesServiceTests(ModuleStoreTestCase): @freeze_time('2017-01-01') def test_undo_override_subsection_grade(self): - override, _ = PersistentSubsectionGradeOverride.objects.update_or_create(grade=self.grade) + override, _ = PersistentSubsectionGradeOverride.objects.update_or_create( + grade=self.grade, + system=GradeOverrideFeatureEnum.proctoring + ) override_id = override.id self.service.undo_override_subsection_grade( user_id=self.user.id, @@ -286,6 +289,26 @@ class GradesServiceTests(ModuleStoreTestCase): override_history = PersistentSubsectionGradeOverrideHistory.objects.filter(override_id=override_id).first() self._verify_override_history(override_history, PersistentSubsectionGradeOverrideHistory.DELETE) + def test_undo_override_subsection_grade_across_features(self): + """ + Test that deletion of subsection grade overrides requested by + one feature doesn't delete overrides created by another + feature. + """ + override, _ = PersistentSubsectionGradeOverride.objects.update_or_create( + grade=self.grade, + system=GradeOverrideFeatureEnum.gradebook + ) + self.service.undo_override_subsection_grade( + user_id=self.user.id, + course_key_or_id=self.course.id, + usage_key_or_id=self.subsection.location, + feature=GradeOverrideFeatureEnum.proctoring, + ) + + override = self.service.get_subsection_grade_override(self.user.id, self.course.id, self.subsection.location) + self.assertIsNotNone(override) + @freeze_time('2018-01-01') def test_undo_override_subsection_grade_without_grade(self): """