Commit f76d9925 by Sofiya Semenova

Initial commit

parent ca46bfcf
......@@ -278,7 +278,7 @@ class CourseGrade(CourseGradeBase):
def _get_subsection_grade(self, subsection):
if self.force_update_subsections:
return self._subsection_grade_factory.update(subsection)
return self._subsection_grade_factory.update(subsection, self.persist_after_track_change)
else:
# Pass read_only here so the subsection grades can be persisted in bulk at the end.
return self._subsection_grade_factory.create(subsection, read_only=True)
......
......@@ -57,6 +57,7 @@ class CourseGradeFactory(object):
course_structure=None,
course_key=None,
force_update_subsections=False,
enrollment_track_changed=False
):
"""
Computes, updates, and returns the CourseGrade for the given
......@@ -64,9 +65,19 @@ class CourseGradeFactory(object):
At least one of course, collected_block_structure, course_structure,
or course_key should be provided.
If the learner's enrollment track has changed, and the
subsection *only* contains track-specific problems that the
user has attempted, should force a re-grade for that section.
See EDUCATOR-1280.
"""
course_data = CourseData(user, course, collected_block_structure, course_structure, course_key)
return self._update(user, course_data, force_update_subsections=force_update_subsections)
return self._update(
user,
course_data,
force_update_subsections=force_update_subsections,
persist_after_track_change=enrollment_track_changed
)
def iter(
self,
......@@ -152,7 +163,7 @@ class CourseGradeFactory(object):
)
@staticmethod
def _update(user, course_data, force_update_subsections=False):
def _update(user, course_data, force_update_subsections=False, persist_after_track_change=False):
"""
Computes, saves, and returns a CourseGrade object for the
given user and course.
......@@ -164,10 +175,15 @@ class CourseGradeFactory(object):
if should_persist and force_update_subsections:
prefetch(user, course_data.course_key)
course_grade = CourseGrade(user, course_data, force_update_subsections=force_update_subsections)
course_grade = CourseGrade(
user,
course_data,
force_update_subsections=force_update_subsections,
persist_after_track_change=persist_after_track_change
)
course_grade = course_grade.update()
should_persist = should_persist and course_grade.attempted
should_persist = should_persist and (course_grade.attempted or persist_after_track_change)
if should_persist:
course_grade._subsection_grade_factory.bulk_create_unsaved()
PersistentCourseGrade.update_or_create(
......
......@@ -248,4 +248,9 @@ def recalculate_course_and_subsection_grades(sender, user, course_key, **kwargs)
"""
previous_course_grade = CourseGradeFactory().read(user, course_key=course_key)
if previous_course_grade and previous_course_grade.attempted:
CourseGradeFactory().update(user=user, course_key=course_key, force_update_subsections=True)
CourseGradeFactory().update(
user=user,
course_key=course_key,
force_update_subsections=True,
enrollment_track_changed=True
)
......@@ -230,11 +230,11 @@ class CreateSubsectionGrade(NonZeroSubsectionGrade):
super(CreateSubsectionGrade, self).__init__(subsection, all_total, graded_total)
def update_or_create_model(self, student, score_deleted=False):
def update_or_create_model(self, student, score_deleted=False, persist_after_track_change=False):
"""
Saves or updates the subsection grade in a persisted model.
"""
if self._should_persist_per_attempted(score_deleted):
if self._should_persist_per_attempted(score_deleted, persist_after_track_change=False):
return PersistentSubsectionGrade.update_or_create_grade(**self._persisted_model_params(student))
@classmethod
......@@ -250,17 +250,20 @@ class CreateSubsectionGrade(NonZeroSubsectionGrade):
]
return PersistentSubsectionGrade.bulk_create_grades(params, student.id, course_key)
def _should_persist_per_attempted(self, score_deleted=False):
def _should_persist_per_attempted(self, score_deleted=False, persist_after_track_change=False):
"""
Returns whether the SubsectionGrade's model should be
persisted based on settings and attempted status.
If the learner's score was just deleted, they will have
no attempts but the grade should still be persisted.
"""
return (
self.all_total.first_attempted is not None or
score_deleted
score_deleted or
persist_after_track_change
)
def _persisted_model_params(self, student):
......
......@@ -63,7 +63,7 @@ class SubsectionGradeFactory(object):
)
self._unsaved_subsection_grades.clear()
def update(self, subsection, only_if_higher=None, score_deleted=False):
def update(self, subsection, only_if_higher=None, score_deleted=False, persist_after_track_change=False):
"""
Updates the SubsectionGrade object for the student and subsection.
"""
......@@ -89,7 +89,10 @@ class SubsectionGradeFactory(object):
):
return orig_subsection_grade
grade_model = calculated_grade.update_or_create_model(self.student, score_deleted)
grade_model = calculated_grade.update_or_create_model(
self.student,
score_deleted,
persist_after_track_change)
self._update_saved_subsection_grade(subsection.location, grade_model)
return calculated_grade
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment