MDL-49257 grades: introduce calculation freeze
In order to prevent changes in the existing grades when we fix bugs we are introducing the gradebook code versioning. Each course may "freeze" the code version to the older date. Freezing is usually done during upgrade or restore and can be removed by the teacher by pressing the button and accepting potential grade changes. There is no visible setting and not possible to change the version back manually. See MDL-50432 and MDL-50522
This commit is contained in:
@@ -999,6 +999,13 @@ class backup_gradebook_structure_step extends backup_structure_step {
|
||||
$gradebook->add_child($grade_settings);
|
||||
$grade_settings->add_child($grade_setting);
|
||||
|
||||
// Add attribute with gradebook calculation freeze date if needed.
|
||||
$gradebookcalculationfreeze = get_config('core', 'gradebook_calculations_freeze_' . $this->get_courseid());
|
||||
if ($gradebookcalculationfreeze) {
|
||||
$gradebook->add_attributes(array('calculations_freeze'));
|
||||
$gradebook->get_attribute('calculations_freeze')->set_value($gradebookcalculationfreeze);
|
||||
}
|
||||
|
||||
// Define sources
|
||||
|
||||
//Include manual, category and the course grade item
|
||||
|
||||
@@ -142,6 +142,18 @@ class restore_gradebook_structure_step extends restore_structure_step {
|
||||
}
|
||||
|
||||
protected function process_gradebook($data) {
|
||||
// For non-merge restore types:
|
||||
// Unset 'gradebook_calculations_freeze_' in the course and replace with the one from the backup.
|
||||
$target = $this->get_task()->get_target();
|
||||
if ($target == backup::TARGET_CURRENT_DELETING || $target == backup::TARGET_EXISTING_DELETING) {
|
||||
set_config('gradebook_calculations_freeze_' . $this->get_courseid(), null);
|
||||
}
|
||||
if (!empty($data['calculations_freeze']) && $this->get_task()->get_target() == backup::TARGET_NEW_COURSE) {
|
||||
if ($target == backup::TARGET_NEW_COURSE || $target == backup::TARGET_CURRENT_DELETING ||
|
||||
$target == backup::TARGET_EXISTING_DELETING) {
|
||||
set_config('gradebook_calculations_freeze_' . $this->get_courseid(), $data['calculations_freeze']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function process_grade_item($data) {
|
||||
@@ -451,9 +463,24 @@ class restore_gradebook_structure_step extends restore_structure_step {
|
||||
}
|
||||
$rs->close();
|
||||
|
||||
// Freeze gradebook calculations if needed.
|
||||
$this->gradebook_calculation_freeze();
|
||||
|
||||
// Restore marks items as needing update. Update everything now.
|
||||
grade_regrade_final_grades($this->get_courseid());
|
||||
}
|
||||
|
||||
/**
|
||||
* Freeze gradebook calculation if needed.
|
||||
*
|
||||
* This is similar to various upgrade scripts that check if the freeze is needed.
|
||||
*/
|
||||
protected function gradebook_calculation_freeze() {
|
||||
global $CFG;
|
||||
$gradebookcalculationsfreeze = get_config('core', 'gradebook_calculations_freeze_' . $this->get_courseid());
|
||||
preg_match('/(\d{8})/', $this->get_task()->get_info()->moodle_release, $matches);
|
||||
$backupbuild = (int)$matches[1];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -515,6 +515,15 @@ function hide_aggregatesubcats_upgrade_notice($courseid) {
|
||||
unset_config('show_aggregatesubcats_upgrade_' . $courseid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide warning about changed grades due to bug fixes
|
||||
*
|
||||
* @param int $courseid The current course id.
|
||||
*/
|
||||
function hide_gradebook_calculations_freeze_notice($courseid) {
|
||||
unset_config('gradebook_calculations_freeze_' . $courseid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print warning about changed grades during upgrade to 2.8.
|
||||
*
|
||||
@@ -547,6 +556,9 @@ function print_natural_aggregation_upgrade_notice($courseid, $context, $thispage
|
||||
|
||||
$minmaxtouse = grade_get_setting($courseid, 'minmaxtouse', $CFG->grade_minmaxtouse);
|
||||
|
||||
$gradebookcalculationsfreeze = get_config('core', 'gradebook_calculations_freeze_' . $courseid);
|
||||
$acceptgradebookchanges = optional_param('acceptgradebookchanges', false, PARAM_BOOL) && confirm_sesskey();
|
||||
|
||||
// Hide the warning if the user told it to go away.
|
||||
if ($hidenaturalwarning) {
|
||||
hide_natural_aggregation_upgrade_notice($courseid);
|
||||
@@ -641,6 +653,39 @@ function print_natural_aggregation_upgrade_notice($courseid, $context, $thispage
|
||||
}
|
||||
}
|
||||
|
||||
if ($gradebookcalculationsfreeze) {
|
||||
if ($acceptgradebookchanges) {
|
||||
// Accept potential changes in grades caused by extra credit bug MDL-49257.
|
||||
hide_gradebook_calculations_freeze_notice($courseid);
|
||||
$courseitem = grade_item::fetch_course_item($courseid);
|
||||
$courseitem->force_regrading();
|
||||
grade_regrade_final_grades($courseid);
|
||||
|
||||
$html .= $OUTPUT->notification(get_string('gradebookcalculationsuptodate', 'grades'), 'notifysuccess');
|
||||
} else {
|
||||
// Show the warning that there may be extra credit weights problems.
|
||||
$a = new stdClass();
|
||||
$a->gradebookversion = $gradebookcalculationsfreeze;
|
||||
if (preg_match('/(\d{8,})/', $CFG->release, $matches)) {
|
||||
$a->currentversion = $matches[1];
|
||||
} else {
|
||||
$a->currentversion = $CFG->release;
|
||||
}
|
||||
$a->url = get_docs_url('Gradebook_calculations_changes');
|
||||
$message = get_string('gradebookcalculationswarning', 'grades', $a);
|
||||
|
||||
$fixmessage = get_string('gradebookcalculationsfixbutton', 'grades');
|
||||
$urlparams = array('id' => $courseid,
|
||||
'acceptgradebookchanges' => true,
|
||||
'sesskey' => sesskey());
|
||||
$fixurl = new moodle_url($thispage, $urlparams);
|
||||
$fixbutton = $OUTPUT->single_button($fixurl, $fixmessage, 'get');
|
||||
|
||||
$html .= $OUTPUT->notification($message, 'notifywarning');
|
||||
$html .= $fixbutton;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($html)) {
|
||||
$html = html_writer::tag('div', $html, array('class' => 'core_grades_notices'));
|
||||
}
|
||||
|
||||
@@ -158,4 +158,18 @@ class behat_grade extends behat_base {
|
||||
$steps[] = new Given('I click on "' . $this->escape($linktext) . '" "link"');
|
||||
return $steps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Step allowing to test before-the-fix behaviour of the gradebook
|
||||
*
|
||||
* @Given /^gradebook calculations for the course "(?P<coursename_string>(?:[^"]|\\")*)" are frozen at version "(?P<version_string>(?:[^"]|\\")*)"$/
|
||||
* @param string $coursename
|
||||
* @param string $version
|
||||
* @return Given
|
||||
*/
|
||||
public function gradebook_calculations_for_the_course_are_frozen_at_version($coursename, $version) {
|
||||
global $DB;
|
||||
$courseid = $DB->get_field('course', 'id', array('shortname' => $coursename), MUST_EXIST);
|
||||
set_config('gradebook_calculations_freeze_' . $courseid, $version);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,6 +239,9 @@ $string['gradeadministration'] = 'Grade administration';
|
||||
$string['gradealreadyupdated'] = '{$a} grades have not been imported because the grades in the import file are older than in the grader report. To proceed with the grade import anyway, use the force import option.';
|
||||
$string['gradeanalysis'] = 'Grade analysis';
|
||||
$string['gradebook'] = 'Gradebook';
|
||||
$string['gradebookcalculationsuptodate'] = 'The calculations in the gradebook are up to date. You may need to reload this page to see changes.';
|
||||
$string['gradebookcalculationsfixbutton'] = 'Accept the changes and recalculate grades';
|
||||
$string['gradebookcalculationswarning'] = 'Note: Some errors have been detected in gradebook calculations that affect this course. The errors have been fixed but the fix was not yet applied to this course since it may lead to the changes in existing grades. You can review the changes on <a href="{$a->url}">this documentation page</a>. Look for the changes between versions {$a->gradebookversion} and {$a->currentversion}';
|
||||
$string['gradebookhiddenerror'] = 'The gradebook is currently set to hide everything from students.';
|
||||
$string['gradebookhistories'] = 'Grade histories';
|
||||
$string['gradeboundary'] = 'Letter grade boundary';
|
||||
|
||||
Reference in New Issue
Block a user