diff --git a/lms/djangoapps/instructor/tests/test_tools.py b/lms/djangoapps/instructor/tests/test_tools.py index b7c539eb0b..722b57a81c 100644 --- a/lms/djangoapps/instructor/tests/test_tools.py +++ b/lms/djangoapps/instructor/tests/test_tools.py @@ -199,11 +199,18 @@ class TestSetDueDateExtension(ModuleStoreTestCase): def test_set_due_date_extension(self): extended = datetime.datetime(2013, 12, 25, 0, 0, tzinfo=utc) - tools.set_due_date_extension(self.course, self.week1, self.user, - extended) + tools.set_due_date_extension(self.course, self.week1, self.user, extended) self.assertEqual(self.extended_due(self.week1), extended) self.assertEqual(self.extended_due(self.homework), extended) + def test_set_due_date_extension_create_studentmodule(self): + extended = datetime.datetime(2013, 12, 25, 0, 0, tzinfo=utc) + user = UserFactory.create() # No student modules for this user + tools.set_due_date_extension(self.course, self.week1, user, extended) + extended_due = functools.partial(get_extended_due, self.course, student=user) + self.assertEqual(extended_due(self.week1), extended) + self.assertEqual(extended_due(self.homework), extended) + def test_reset_due_date_extension(self): tools.set_due_date_extension(self.course, self.week1, self.user, None) self.assertEqual(self.extended_due(self.week1), None) diff --git a/lms/djangoapps/instructor/views/tools.py b/lms/djangoapps/instructor/views/tools.py index 4b6a621b97..d195db7a4c 100644 --- a/lms/djangoapps/instructor/views/tools.py +++ b/lms/djangoapps/instructor/views/tools.py @@ -173,13 +173,30 @@ def set_due_date_extension(course, unit, student, due_date): course_id=course.id, module_state_key=node.location ) - state = json.loads(student_module.state) - state['extended_due'] = DATE_FIELD.to_json(due_date) - student_module.state = json.dumps(state) - student_module.save() + except StudentModule.DoesNotExist: - pass + # Normally, a StudentModule is created as a side effect of assigning + # a value to a property in an XModule or XBlock which has a scope + # of 'Scope.user_state'. Here, we want to alter user state but + # can't use the standard XModule/XBlock machinery to do so, because + # it fails to take into account that the state being altered might + # belong to a student other than the one currently logged in. As a + # result, in our work around, we need to detect whether the + # StudentModule has been created for the given student on the given + # unit and create it if it is missing, so we can use it to store + # the extended due date. + student_module = StudentModule.objects.create( + student_id=student.id, + course_id=course.id, + module_state_key=node.location, + module_type=node.category + ) + state = {} + + state['extended_due'] = DATE_FIELD.to_json(due_date) + student_module.state = json.dumps(state) + student_module.save() for child in node.get_children(): set_due_date(child)