Discovery: Read-only Grades after Course End Date
Ticket: - EDUCATOR-3500Getting issue details... STATUS
Notes
Here are the places where grades get updated:
PersistentCourseGrade.update_or_create CourseGradeFactory._update CourseGradeFactory().update 1. CourseGradeFactory().iter if force_update compute_grades_for_course (** TASK) * management command: compute_grades * compute_all_grades_for_course GRADING_POLICY_CHANGED (handle_grading_policy_changed) 2. SUBSECTION_SCORE_CHANGED (recalculate_course_grade_only) recalculate_subsection_grade_v3 (** TASK **) PROBLEM_WEIGHTED_SCORE_CHANGED (enqueue_subsection_update) SUBSECTION_OVERRIDE_CHANGED (enqueue_subsection_update) management command: recalculate_subsection_grades 3. recalculate_course_and_subsection_grades_for_user (** TASK **) ENROLLMENT_TRACK_UPDATED (recalculate_course_and_subsection_grades) COHORT_MEMBERSHIP_UPDATED (recalculate_course_and_subsection_grades) management command: recalculate_learner_grades GradesService.override_subsection_grade GradesService.undo_override_subsection_grade SUBSECTION_OVERRIDE_CHANGED (enqueue_subsection_update)
Questions
- Are we Ok with the CoursewareStudentModule and Submissions tables being updated, but not the grades?
- Are we Ok with the Subsection Grades getting updated, but not the Course grades?
- Are we Ok with the Course Grading policy getting updated, but not the grades?
- Are we Ok for
self-paced
course grades being update if it sets acourse_end_date
? - What is
GRADING_POLICY_COUNTDOWN_SECONDS
lock? - What happens when someone changes the end date of the course to be a later date?
- Can they trigger the regrading manually?
- Note: course_overview.signals._check_for_course_date_changes
- Can they trigger the regrading manually?
- Where to place the helper method? There is signal handler in CMS for course grade update and there are signal handlers in LMS for subsection grade changes when learner attempts to score a problem.
Thoughts
- We can either
- update each of the celery tasks that update grades, or
- just raise an exception within the write methods of PersistentCourseGrade and PersistentSubsectionGrade, or
- update grades.config.should_persist_grades to check for the course's end date.
- The latter, however, will require accessing course date information at a lower layer.
- Have 2 points of defense:
- At the grades core level - possibly in the celery tasks.
- Eventually, also at the higher layers - possibly in the Django Signal handlers.
- We do not want this to be enabled for all courses (right away or even long term?)
- So use a CourseWaffleFlag for now.
- Maybe eventually make it an advanced setting (or a date setting).
- So use a CourseWaffleFlag for now.
Decisions
- Continue to update Subsection Grades - only if it's easier to implement this way - otherwise, it's preferable to not update subsection grades as well.
- In the future, if we want to automatically update course grades when Course End changes, we can do so easily with the updated subsection grades.
- Stop updating Course Grades 1 month after Course End.
- Get the Course End date from the CourseOverview model.
- For self-paced courses, we will just use the Course End date as well.
- If a course has no Course End date, then continue updating the grade(s).
- Put this change behind a CourseWaffleFlag since some courses will want to opt-out of this.
- Record whenever the course end date changes → tracking logs + Splunk.
MVP
- Create CourseWaffleFlag for this change.
- Update grades-related celery tasks to exit when now > (Course End + 1 month).
- If simpler, do this for all tasks - including update of Subsection grades.
- Add log message when course end date changes.
- Possibly in course_overview.signals._check_for_course_date_changes.
Technical Details
Helper method
from datetime import timedelta from django.utils import timezone def should_update_grades(course_key): some_waffle_switch = True // Some waffle switch which we can pull information from for active/inactive? course = CourseOverview.get_from_id(course_key) if some_waffle_switch and course.end: // Not sure if we are ok for self paced courses with ends dates to be the part of the change grade_update_offset = course.end + timedelta(30) // There should some good place to store `30`. A config model/settings/static variable? now = timezone.now() if now > offset: return False return True