def test_grade_override(self):
     grade = PersistentSubsectionGrade.create_grade(**self.params)
     override = PersistentSubsectionGradeOverride(grade=grade, earned_all_override=0.0, earned_graded_override=0.0)
     override.save()
     grade = PersistentSubsectionGrade.update_or_create_grade(**self.params)
     self.assertEqual(grade.earned_all, 0.0)
     self.assertEqual(grade.earned_graded, 0.0)
Beispiel #2
0
    def test_get_subsection_grade_percentage_with_override(self):
        user = self.request.user
        subsection_key = self.sequence.location

        with mock_get_score(3, 3):
            # this update() call creates a persistent grade
            self.subsection_grade_factory.update(self.sequence)

            # there should only be one persistent grade
            persistent_grade = PersistentSubsectionGrade.objects.first()

            PersistentSubsectionGradeOverride.update_or_create_override(
                UserFactory(
                ),  # it doesn't matter to us who created the override
                persistent_grade,
                earned_graded_override=0,
                earned_all_override=0,
                possible_graded_override=3,
                feature=GradeOverrideFeatureEnum.gradebook,
            )

            # it's important that we stay in the mock_get_score() context here,
            # since get_subsection_grade_percentage() creates its own SubsectionGradeFactory,
            # which will in turn make calls to get_score().
            grade_percentage = gating_api.get_subsection_grade_percentage(
                subsection_key, user)
            assert 0 == grade_percentage
Beispiel #3
0
    def test_get_subsection_grade_percentage_with_override(self):
        user = self.request.user
        subsection_key = self.sequence.location

        with mock_get_score(3, 3):
            # this update() call creates a persistent grade
            self.subsection_grade_factory.update(self.sequence)

            # there should only be one persistent grade
            persistent_grade = PersistentSubsectionGrade.objects.first()

            PersistentSubsectionGradeOverride.update_or_create_override(
                UserFactory(),  # it doesn't matter to us who created the override
                persistent_grade,
                earned_graded_override=0,
                earned_all_override=0,
                possible_graded_override=3,
                feature=PersistentSubsectionGradeOverrideHistory.GRADEBOOK,
            )

            # it's important that we stay in the mock_get_score() context here,
            # since get_subsection_grade_percentage() creates its own SubsectionGradeFactory,
            # which will in turn make calls to get_score().
            grade_percentage = gating_api.get_subsection_grade_percentage(subsection_key, user)
            assert 0 == grade_percentage
Beispiel #4
0
 def test_grade_override(self):
     grade = PersistentSubsectionGrade.update_or_create_grade(**self.params)
     override = PersistentSubsectionGradeOverride(
         grade=grade, earned_all_override=0.0, earned_graded_override=0.0)
     override.save()
     grade = PersistentSubsectionGrade.update_or_create_grade(**self.params)
     self.assertEqual(grade.earned_all, 0.0)
     self.assertEqual(grade.earned_graded, 0.0)
Beispiel #5
0
    def _create_override(self, request_user, subsection_grade_model, **override_data):
        """
        Helper method to create a `PersistentSubsectionGradeOverride` object
        and send a `SUBSECTION_OVERRIDE_CHANGED` signal.
        """
        override = PersistentSubsectionGradeOverride.update_or_create_override(
            requesting_user=request_user,
            subsection_grade_model=subsection_grade_model,
            feature=grades_constants.GradeOverrideFeatureEnum.gradebook,
            **override_data
        )

        set_event_transaction_type(grades_events.SUBSECTION_GRADE_CALCULATED)
        create_new_event_transaction_id()

        recalculate_subsection_grade_v3.apply(
            kwargs=dict(
                user_id=subsection_grade_model.user_id,
                anonymous_user_id=None,
                course_id=text_type(subsection_grade_model.course_id),
                usage_id=text_type(subsection_grade_model.usage_key),
                only_if_higher=False,
                expected_modified_time=to_timestamp(override.modified),
                score_deleted=False,
                event_transaction_id=six.text_type(get_event_transaction_id()),
                event_transaction_type=six.text_type(get_event_transaction_type()),
                score_db_table=grades_constants.ScoreDatabaseTableEnum.overrides,
                force_update_subsections=True,
            )
        )
        # Emit events to let our tracking system to know we updated subsection grade
        grades_events.subsection_grade_calculated(subsection_grade_model)
        return override
Beispiel #6
0
    def test_grade_override(self):
        """
        Creating a subsection grade override should NOT change the score values
        of the related PersistentSubsectionGrade.
        """
        grade = PersistentSubsectionGrade.update_or_create_grade(**self.params)
        override = PersistentSubsectionGradeOverride.update_or_create_override(
            requesting_user=self.user,
            subsection_grade_model=grade,
            earned_all_override=0.0,
            earned_graded_override=0.0,
            feature=PersistentSubsectionGradeOverrideHistory.GRADEBOOK,
        )

        grade = PersistentSubsectionGrade.update_or_create_grade(**self.params)
        self.assertEqual(self.params['earned_all'], grade.earned_all)
        self.assertEqual(self.params['earned_graded'], grade.earned_graded)

        # Any score values that aren't specified should use the values from grade as defaults
        self.assertEqual(0, override.earned_all_override)
        self.assertEqual(0, override.earned_graded_override)
        self.assertEqual(grade.possible_all, override.possible_all_override)
        self.assertEqual(grade.possible_graded,
                         override.possible_graded_override)

        # An override history record should be created
        self.assertEqual(
            1,
            PersistentSubsectionGradeOverrideHistory.objects.filter(
                override_id=override.id).count())
    def _create_override(self, request_user, subsection_grade_model,
                         **override_data):
        """
        Helper method to create a `PersistentSubsectionGradeOverride` object
        and send a `SUBSECTION_OVERRIDE_CHANGED` signal.
        """
        override_data[
            'system'] = grades_constants.GradeOverrideFeatureEnum.gradebook
        override = PersistentSubsectionGradeOverride.update_or_create_override(
            requesting_user=request_user,
            subsection_grade_model=subsection_grade_model,
            feature=grades_constants.GradeOverrideFeatureEnum.gradebook,
            **override_data)

        set_event_transaction_type(grades_events.SUBSECTION_GRADE_CALCULATED)
        create_new_event_transaction_id()

        recalculate_subsection_grade_v3.apply(kwargs=dict(
            user_id=subsection_grade_model.user_id,
            anonymous_user_id=None,
            course_id=text_type(subsection_grade_model.course_id),
            usage_id=text_type(subsection_grade_model.usage_key),
            only_if_higher=False,
            expected_modified_time=to_timestamp(override.modified),
            score_deleted=False,
            event_transaction_id=six.text_type(get_event_transaction_id()),
            event_transaction_type=six.text_type(get_event_transaction_type()),
            score_db_table=grades_constants.ScoreDatabaseTableEnum.overrides,
            force_update_subsections=True,
        ))
        # Emit events to let our tracking system to know we updated subsection grade
        grades_events.subsection_grade_calculated(subsection_grade_model)
        return override
Beispiel #8
0
    def test_grade_override(self):
        """
        Creating a subsection grade override should NOT change the score values
        of the related PersistentSubsectionGrade.
        """
        grade = PersistentSubsectionGrade.update_or_create_grade(**self.params)
        override = PersistentSubsectionGradeOverride.update_or_create_override(
            requesting_user=self.user,
            subsection_grade_model=grade,
            earned_all_override=0.0,
            earned_graded_override=0.0,
            feature=GradeOverrideFeatureEnum.gradebook,
        )

        grade = PersistentSubsectionGrade.update_or_create_grade(**self.params)
        self.assertEqual(self.params['earned_all'], grade.earned_all)
        self.assertEqual(self.params['earned_graded'], grade.earned_graded)
        history = override.get_history()
        self.assertEqual(1, len(list(history)))
        self.assertEqual('+', list(history)[0].history_type)
        # Any score values that aren't specified should use the values from grade as defaults
        self.assertEqual(0, override.earned_all_override)
        self.assertEqual(0, override.earned_graded_override)
        self.assertEqual(grade.possible_all, override.possible_all_override)
        self.assertEqual(grade.possible_graded, override.possible_graded_override)
Beispiel #9
0
    def test_grade_override(self):
        """
        Creating a subsection grade override should NOT change the score values
        of the related PersistentSubsectionGrade.
        """
        grade = PersistentSubsectionGrade.update_or_create_grade(**self.params)
        override = PersistentSubsectionGradeOverride.update_or_create_override(
            requesting_user=self.user,
            subsection_grade_model=grade,
            earned_all_override=0.0,
            earned_graded_override=0.0,
            feature=GradeOverrideFeatureEnum.gradebook,
        )

        grade = PersistentSubsectionGrade.update_or_create_grade(**self.params)
        assert self.params['earned_all'] == grade.earned_all
        assert self.params['earned_graded'] == grade.earned_graded
        history = override.get_history()
        assert 1 == len(list(history))
        assert '+' == list(history)[0].history_type
        # Any score values that aren't specified should use the values from grade as defaults
        assert 0 == override.earned_all_override
        assert 0 == override.earned_graded_override
        assert grade.possible_all == override.possible_all_override
        assert grade.possible_graded == override.possible_graded_override
Beispiel #10
0
def update_or_create_override(grade, **kwargs):
    """
    Update or creates a subsection override.
    """
    kwargs['subsection_grade_model'] = grade
    return _PersistentSubsectionGradeOverride.update_or_create_override(
        **kwargs)
Beispiel #11
0
    def test_grade_override(self):
        """
        Creating a subsection grade override should NOT change the score values
        of the related PersistentSubsectionGrade.
        """
        grade = PersistentSubsectionGrade.update_or_create_grade(**self.params)
        override = PersistentSubsectionGradeOverride.update_or_create_override(
            requesting_user=self.user,
            subsection_grade_model=grade,
            earned_all_override=0.0,
            earned_graded_override=0.0,
            feature=PersistentSubsectionGradeOverrideHistory.GRADEBOOK,
        )

        grade = PersistentSubsectionGrade.update_or_create_grade(**self.params)
        self.assertEqual(self.params['earned_all'], grade.earned_all)
        self.assertEqual(self.params['earned_graded'], grade.earned_graded)

        # Any score values that aren't specified should use the values from grade as defaults
        self.assertEqual(0, override.earned_all_override)
        self.assertEqual(0, override.earned_graded_override)
        self.assertEqual(grade.possible_all, override.possible_all_override)
        self.assertEqual(grade.possible_graded, override.possible_graded_override)

        # An override history record should be created
        self.assertEqual(1, PersistentSubsectionGradeOverrideHistory.objects.filter(override_id=override.id).count())
Beispiel #12
0
    def test_override_is_visible(self):
        with persistent_grades_feature_flags(global_flag=True):
            chapter = ItemFactory(parent=self.course, category='chapter')
            subsection = ItemFactory.create(parent=chapter,
                                            category="sequential",
                                            display_name="Subsection")

            CourseEnrollment.enroll(self.user, self.course.id)

            params = {
                "user_id": self.user.id,
                "usage_key": subsection.location,
                "course_version": self.course.course_version,
                "subtree_edited_timestamp": "2016-08-01 18:53:24.354741Z",
                "earned_all": 6.0,
                "possible_all": 12.0,
                "earned_graded": 6.0,
                "possible_graded": 8.0,
                "visible_blocks": [],
                "first_attempted": datetime.now(),
            }

            created_grade = PersistentSubsectionGrade.update_or_create_grade(
                **params)
            proctoring_failure_comment = "Failed Test Proctoring"
            PersistentSubsectionGradeOverride.update_or_create_override(
                requesting_user=self.staff_user,
                subsection_grade_model=created_grade,
                earned_all_override=0.0,
                earned_graded_override=0.0,
                system=GradeOverrideFeatureEnum.proctoring,
                feature=GradeOverrideFeatureEnum.proctoring,
                comment=proctoring_failure_comment)

            response = self.client.get(self.url)
            assert response.status_code == 200

            sections = response.data['section_scores']
            overridden_subsection = sections[1]['subsections'][0]
            override_entry = overridden_subsection["override"]

            assert override_entry[
                'system'] == GradeOverrideFeatureEnum.proctoring
            assert override_entry['reason'] == proctoring_failure_comment
Beispiel #13
0
def get_subsection_grade_override(user_id, course_key_or_id, usage_key_or_id):
    """
    Finds the subsection grade for user and returns the override for that grade if it exists

    If override does not exist, returns None. If subsection grade does not exist, will raise an exception.
    """
    usage_key = _get_key(usage_key_or_id, UsageKey)

    # Verify that a corresponding subsection grade exists for the given user and usage_key
    # Raises PersistentSubsectionGrade.DoesNotExist if it does not exist.
    _ = get_subsection_grade(user_id, course_key_or_id, usage_key_or_id)

    return _PersistentSubsectionGradeOverride.get_override(user_id, usage_key)
def prefetch_grade_overrides_and_visible_blocks(user, course_key):
    _PersistentSubsectionGradeOverride.prefetch(user.id, course_key)
    _VisibleBlocks.bulk_read(user.id, course_key)