def finish_review_workflow(sender, instance, signal, **kwargs): # pylint: disable=unused-argument """ Updates the attempt status based on the review status Also notifies support about suspicious reviews. """ review = instance attempt_obj, is_archived = locate_attempt_by_attempt_code(review.attempt_code) attempt = api.ProctoredExamStudentAttemptSerializer(attempt_obj).data # we could have gotten a review for an archived attempt # this should *not* cause an update in our credit # eligibility table if review.review_status in SoftwareSecureReviewStatus.passing_statuses: attempt_status = ProctoredExamStudentAttemptStatus.verified elif review.reviewed_by or not constants.REQUIRE_FAILURE_SECOND_REVIEWS: # reviews from the django admin have a reviewer set. They should be allowed to # reject an attempt attempt_status = ProctoredExamStudentAttemptStatus.rejected else: # if we are not allowed to store 'rejected' on this # code path, then put status into 'second_review_required' attempt_status = ProctoredExamStudentAttemptStatus.second_review_required if review.review_status in SoftwareSecureReviewStatus.notify_support_for_status: instructor_service = api.get_runtime_service('instructor') request = get_current_request() if instructor_service and request: course_id = attempt['proctored_exam']['course_id'] exam_id = attempt['proctored_exam']['id'] review_url = request.build_absolute_uri( u'{}?attempt={}'.format( reverse('edx_proctoring:instructor_dashboard_exam', args=[course_id, exam_id]), attempt['external_id'] )) instructor_service.send_support_notification( course_id=attempt['proctored_exam']['course_id'], exam_name=attempt['proctored_exam']['exam_name'], student_username=attempt['user']['username'], review_status=review.review_status, review_url=review_url, ) if not is_archived: # updating attempt status will trigger workflow # (i.e. updating credit eligibility table) # archived attempts should not trigger the workflow api.update_attempt_status( attempt['proctored_exam']['id'], attempt['user']['id'], attempt_status, raise_if_not_found=False ) # emit an event for 'review_received' data = { 'review_attempt_code': review.attempt_code, 'review_status': review.review_status, } emit_event(attempt['proctored_exam'], 'review_received', attempt=attempt, override_data=data)
def finish_review_workflow(sender, instance, signal, **kwargs): # pylint: disable=unused-argument """ Updates the attempt status based on the review status """ review = instance attempt_obj, is_archived = locate_attempt_by_attempt_code( review.attempt_code) attempt = api.ProctoredExamStudentAttemptSerializer(attempt_obj).data backend = get_backend_provider(attempt['proctored_exam']) # we could have gotten a review for an archived attempt # this should *not* cause an update in our credit # eligibility table if review.is_passing: attempt_status = ProctoredExamStudentAttemptStatus.verified elif review.review_status == SoftwareSecureReviewStatus.not_reviewed: attempt_status = ProctoredExamStudentAttemptStatus.error elif review.reviewed_by or not constants.REQUIRE_FAILURE_SECOND_REVIEWS: # reviews from the django admin have a reviewer set. They should be allowed to # reject an attempt attempt_status = ProctoredExamStudentAttemptStatus.rejected elif backend and backend.supports_onboarding and attempt[ 'is_sample_attempt']: attempt_status = ProctoredExamStudentAttemptStatus.rejected else: # if we are not allowed to store 'rejected' on this # code path, then put status into 'second_review_required' attempt_status = ProctoredExamStudentAttemptStatus.second_review_required if not is_archived: # updating attempt status will trigger workflow # (i.e. updating credit eligibility table) # archived attempts should not trigger the workflow api.update_attempt_status(attempt['proctored_exam']['id'], attempt['user']['id'], attempt_status, raise_if_not_found=False, update_attributable_to=review.reviewed_by or None) # emit an event for 'review_received' data = { 'review_attempt_code': review.attempt_code, 'review_status': review.review_status, } emit_event(attempt['proctored_exam'], 'review_received', attempt=attempt, override_data=data)