Beispiel #1
0
def enqueue_subsection_update(sender, **kwargs):  # pylint: disable=unused-argument
    """
    Handles the PROBLEM_WEIGHTED_SCORE_CHANGED or SUBSECTION_OVERRIDE_CHANGED signals by
    enqueueing a subsection update operation to occur asynchronously.
    """
    events.grade_updated(**kwargs)
    context_key = LearningContextKey.from_string(kwargs['course_id'])
    if not context_key.is_course:
        return  # If it's not a course, it has no subsections, so skip the subsection grading update
    recalculate_subsection_grade_v3.apply_async(
        kwargs=dict(
            user_id=kwargs['user_id'],
            anonymous_user_id=kwargs.get('anonymous_user_id'),
            course_id=kwargs['course_id'],
            usage_id=kwargs['usage_id'],
            only_if_higher=kwargs.get('only_if_higher'),
            expected_modified_time=to_timestamp(kwargs['modified']),
            score_deleted=kwargs.get('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=kwargs['score_db_table'],
            force_update_subsections=kwargs.get('force_update_subsections', False),
        ),
        countdown=RECALCULATE_GRADE_DELAY_SECONDS,
    )
Beispiel #2
0
    def handle(self, *args, **options):
        if 'modified_start' not in options:
            raise CommandError('modified_start must be provided.')

        if 'modified_end' not in options:
            raise CommandError('modified_end must be provided.')

        modified_start = utc.localize(
            datetime.strptime(options['modified_start'], DATE_FORMAT))
        modified_end = utc.localize(
            datetime.strptime(options['modified_end'], DATE_FORMAT))
        event_transaction_id = create_new_event_transaction_id()
        set_event_transaction_type(PROBLEM_SUBMITTED_EVENT_TYPE)
        kwargs = {
            'modified__range': (modified_start, modified_end),
            'module_type': 'problem'
        }
        for record in StudentModule.objects.filter(**kwargs):
            if not record.course_id.is_course:
                # This is not a course, so we don't store subsection grades for it.
                continue
            task_args = {
                "user_id": record.student_id,
                "course_id": six.text_type(record.course_id),
                "usage_id": six.text_type(record.module_state_key),
                "only_if_higher": False,
                "expected_modified_time": to_timestamp(record.modified),
                "score_deleted": False,
                "event_transaction_id": six.text_type(event_transaction_id),
                "event_transaction_type": PROBLEM_SUBMITTED_EVENT_TYPE,
                "score_db_table":
                ScoreDatabaseTableEnum.courseware_student_module,
            }
            recalculate_subsection_grade_v3.apply_async(kwargs=task_args)

        kwargs = {'created_at__range': (modified_start, modified_end)}
        for record in Submission.objects.filter(**kwargs):
            if not record.student_item.course_id.is_course:
                # This is not a course, so ignore it
                continue
            task_args = {
                "user_id":
                user_by_anonymous_id(record.student_item.student_id).id,
                "anonymous_user_id": record.student_item.student_id,
                "course_id": six.text_type(record.student_item.course_id),
                "usage_id": six.text_type(record.student_item.item_id),
                "only_if_higher": False,
                "expected_modified_time": to_timestamp(record.created_at),
                "score_deleted": False,
                "event_transaction_id": six.text_type(event_transaction_id),
                "event_transaction_type": PROBLEM_SUBMITTED_EVENT_TYPE,
                "score_db_table": ScoreDatabaseTableEnum.submissions,
            }
            recalculate_subsection_grade_v3.apply_async(kwargs=task_args)
    def handle(self, *args, **options):
        if 'modified_start' not in options:
            raise CommandError('modified_start must be provided.')

        if 'modified_end' not in options:
            raise CommandError('modified_end must be provided.')

        modified_start = utc.localize(datetime.strptime(options['modified_start'], DATE_FORMAT))
        modified_end = utc.localize(datetime.strptime(options['modified_end'], DATE_FORMAT))
        event_transaction_id = create_new_event_transaction_id()
        set_event_transaction_type(PROBLEM_SUBMITTED_EVENT_TYPE)
        kwargs = {'modified__range': (modified_start, modified_end), 'module_type': 'problem'}
        for record in StudentModule.objects.filter(**kwargs):
            task_args = {
                "user_id": record.student_id,
                "course_id": unicode(record.course_id),
                "usage_id": unicode(record.module_state_key),
                "only_if_higher": False,
                "expected_modified_time": to_timestamp(record.modified),
                "score_deleted": False,
                "event_transaction_id": unicode(event_transaction_id),
                "event_transaction_type": PROBLEM_SUBMITTED_EVENT_TYPE,
                "score_db_table": ScoreDatabaseTableEnum.courseware_student_module,
            }
            recalculate_subsection_grade_v3.apply_async(kwargs=task_args)

        kwargs = {'created_at__range': (modified_start, modified_end)}
        for record in Submission.objects.filter(**kwargs):
            task_args = {
                "user_id": user_by_anonymous_id(record.student_item.student_id).id,
                "anonymous_user_id": record.student_item.student_id,
                "course_id": unicode(record.student_item.course_id),
                "usage_id": unicode(record.student_item.item_id),
                "only_if_higher": False,
                "expected_modified_time": to_timestamp(record.created_at),
                "score_deleted": False,
                "event_transaction_id": unicode(event_transaction_id),
                "event_transaction_type": PROBLEM_SUBMITTED_EVENT_TYPE,
                "score_db_table": ScoreDatabaseTableEnum.submissions,
            }
            recalculate_subsection_grade_v3.apply_async(kwargs=task_args)
Beispiel #4
0
    def test_recalculate_subsection_grade_v3(self, freeze_flag_value, end_date_adjustment, mock_log):
        self.set_up_course(course_end=timezone.now() - timedelta(end_date_adjustment))
        for user in self.users:
            CourseEnrollment.enroll(user, self.course.id)

        with override_waffle_flag(self.freeze_grade_flag, active=freeze_flag_value):
            modified_datetime = datetime.utcnow().replace(tzinfo=pytz.UTC) - timedelta(days=1)
            with patch('lms.djangoapps.grades.tasks._has_db_updated_with_new_score') as mock_has_db_updated:
                result = recalculate_subsection_grade_v3.apply_async(kwargs=self.recalculate_subsection_grade_kwargs)
                self._assert_for_freeze_grade_flag(
                    result,
                    freeze_flag_value,
                    end_date_adjustment,
                    mock_log,
                    mock_has_db_updated,
                    '_recalculate_subsection_grade'
                )
Beispiel #5
0
    def test_recalculate_subsection_grade_v3(self, freeze_flag_value, end_date_adjustment, mock_log):
        self.set_up_course(course_end=timezone.now() - timedelta(end_date_adjustment))
        for user in self.users:
            CourseEnrollment.enroll(user, self.course.id)

        with override_waffle_flag(self.freeze_grade_flag, active=freeze_flag_value):
            modified_datetime = datetime.utcnow().replace(tzinfo=pytz.UTC) - timedelta(days=1)
            with patch(
                'lms.djangoapps.grades.tasks.GradesService',
                return_value=MockGradesService(mocked_return_value=MagicMock(modified=modified_datetime))
            ) as mock_grade_service:
                result = recalculate_subsection_grade_v3.apply_async(kwargs=self.recalculate_subsection_grade_kwargs)
                self._assert_for_freeze_grade_flag(
                    result,
                    freeze_flag_value,
                    end_date_adjustment,
                    mock_log,
                    mock_grade_service,
                    '_recalculate_subsection_grade'
                )
Beispiel #6
0
    def test_recalculate_subsection_grade_v3(self, freeze_flag_value,
                                             end_date_adjustment, mock_log):
        self.set_up_course(course_end=timezone.now() -
                           timedelta(end_date_adjustment))
        for user in self.users:
            CourseEnrollment.enroll(user, self.course.id)

        with override_waffle_flag(self.freeze_grade_flag,
                                  active=freeze_flag_value):
            modified_datetime = datetime.utcnow().replace(
                tzinfo=pytz.UTC) - timedelta(days=1)
            with patch('lms.djangoapps.grades.api',
                       return_value=MockGradesService(
                           mocked_return_value=MagicMock(
                               modified=modified_datetime))
                       ) as mock_grade_service:
                result = recalculate_subsection_grade_v3.apply_async(
                    kwargs=self.recalculate_subsection_grade_kwargs)
                self._assert_for_freeze_grade_flag(
                    result, freeze_flag_value, end_date_adjustment, mock_log,
                    mock_grade_service, '_recalculate_subsection_grade')