diff --git a/edx_exams/apps/core/api.py b/edx_exams/apps/core/api.py index d5c98791..11aac2ab 100644 --- a/edx_exams/apps/core/api.py +++ b/edx_exams/apps/core/api.py @@ -99,8 +99,11 @@ def update_attempt_status(attempt_id, to_status): if not allowed_to_start: raise ExamIllegalStatusTransition(error_msg) - attempt_obj.start_time = datetime.now(pytz.UTC) - attempt_obj.allowed_time_limit_mins = _calculate_allowed_mins(attempt_obj.user, attempt_obj.exam) + # Once start time, and end time by extension, has been set further transitions to started + # must not update this value + if not attempt_obj.start_time: + attempt_obj.start_time = datetime.now(pytz.UTC) + attempt_obj.allowed_time_limit_mins = _calculate_allowed_mins(attempt_obj.user, attempt_obj.exam) course_key = CourseKey.from_string(attempt_obj.exam.course_id) usage_key = UsageKey.from_string(attempt_obj.exam.content_id) diff --git a/edx_exams/apps/core/tests/test_api.py b/edx_exams/apps/core/tests/test_api.py index 718247ea..299697f7 100644 --- a/edx_exams/apps/core/tests/test_api.py +++ b/edx_exams/apps/core/tests/test_api.py @@ -407,6 +407,21 @@ def test_cannot_start_if_other_attempts_active(self): update_attempt_status(self.exam_attempt.id, ExamAttemptStatus.started) self.assertIn('another exam attempt is currently active!', str(exc.exception)) + def test_ready_to_submit_to_started(self): + """ + Test transition to started after initial start time has been set. This should not + alter the existing start time. + """ + with freeze_time(timezone.now()): + self.exam_attempt.status = ExamAttemptStatus.ready_to_submit + self.exam_attempt.start_time = timezone.now()-timedelta(minutes=10) + self.exam_attempt.allowed_time_limit_mins = 30 + self.exam_attempt.save() + + update_attempt_status(self.exam_attempt.id, ExamAttemptStatus.started) + self.exam_attempt.refresh_from_db() + self.assertEqual(self.exam_attempt.start_time, timezone.now()-timedelta(minutes=10)) + class TestGetAttemptById(ExamsAPITestCase): """