From 0432c6e6d1260890c5ce1ba44922a4a0e4a00d70 Mon Sep 17 00:00:00 2001 From: Alex Yeung Date: Tue, 6 Feb 2024 14:33:22 +0000 Subject: [PATCH] CTP-3030 Improve notification email --- classes/manager.php | 22 ++++--- classes/task/adhoctask.php | 4 +- classes/taskmanager.php | 95 +++++++++++++++------------ db/install.xml | 3 +- db/upgrade.php | 15 +++++ lang/en/local_sitsgradepush.php | 20 ++++-- settings.php | 9 +++ templates/notification_email.mustache | 67 +++++++++++++++++++ version.php | 2 +- 9 files changed, 176 insertions(+), 61 deletions(-) create mode 100644 templates/notification_email.mustache diff --git a/classes/manager.php b/classes/manager.php index 7c9202e..1ace78a 100644 --- a/classes/manager.php +++ b/classes/manager.php @@ -701,11 +701,12 @@ public function get_students_from_sits(\stdClass $componentgrade): mixed { * * @param \stdClass $assessmentmapping * @param int $userid + * @param int|null $taskid * @return bool * @throws \dml_exception * @throws \moodle_exception */ - public function push_grade_to_sits(\stdClass $assessmentmapping, int $userid): bool { + public function push_grade_to_sits(\stdClass $assessmentmapping, int $userid, int $taskid = null): bool { try { // Check if last push was succeeded, exit if succeeded. if ($this->last_push_succeeded($assessmentmapping->id, $userid, self::PUSH_GRADE)) { @@ -730,7 +731,7 @@ public function push_grade_to_sits(\stdClass $assessmentmapping, int $userid): b $this->check_response($response, $request); // Save transfer log. - $this->save_transfer_log(self::PUSH_GRADE, $assessmentmapping->id, $userid, $request, $response); + $this->save_transfer_log(self::PUSH_GRADE, $assessmentmapping->id, $userid, $request, $response, $taskid); return true; } @@ -747,10 +748,11 @@ public function push_grade_to_sits(\stdClass $assessmentmapping, int $userid): b * * @param \stdClass $assessmentmapping * @param int $userid + * @param int|null $taskid * @return bool * @throws \dml_exception */ - public function push_submission_log_to_sits(\stdClass $assessmentmapping, int $userid): bool { + public function push_submission_log_to_sits(\stdClass $assessmentmapping, int $userid, ?int $taskid = null): bool { try { // Check if submission log push is enabled. if (!get_config('local_sitsgradepush', 'sublogpush')) { @@ -778,12 +780,12 @@ public function push_submission_log_to_sits(\stdClass $assessmentmapping, int $u // Save push log. $this->save_transfer_log( - self::PUSH_SUBMISSION_LOG, $assessmentmapping->id, $userid, $request, $response); + self::PUSH_SUBMISSION_LOG, $assessmentmapping->id, $userid, $request, $response, $taskid); return true; } } catch (\moodle_exception $e) { - $this->mark_push_as_failed(self::PUSH_SUBMISSION_LOG, $assessmentmapping->id, $userid, $e); + $this->mark_push_as_failed(self::PUSH_SUBMISSION_LOG, $assessmentmapping->id, $userid, $taskid, $e); return false; } @@ -1364,12 +1366,14 @@ public function get_data_for_page_update($courseid, $couresmoduleid = 0): array * @param int $userid * @param mixed $request * @param array $response + * @param int|null $taskid * @param int|null $errorlogid * @return void * @throws \dml_exception */ private function save_transfer_log( - string $type, int $assessmentmappingid, int $userid, mixed $request, array $response, int $errorlogid = null): void { + string $type, int $assessmentmappingid, int $userid, mixed $request, array $response, ?int $taskid, int $errorlogid = null) + : void { global $USER, $DB; $insert = new \stdClass(); $insert->type = $type; @@ -1379,6 +1383,7 @@ private function save_transfer_log( $insert->requestbody = ($request instanceof irequest) ? $request->get_request_body() : null; $insert->response = json_encode($response); $insert->errlogid = $errorlogid; + $insert->taskid = $taskid; $insert->usermodified = $USER->id; $insert->timecreated = time(); @@ -1453,12 +1458,13 @@ private function check_response(mixed $response, irequest $request): void { * @param string $requestidentifier * @param int $assessmentmappingid * @param int $userid + * @param int|null $taskid * @param \moodle_exception $exception * @return void * @throws \dml_exception */ private function mark_push_as_failed( - string $requestidentifier, int $assessmentmappingid, int $userid, \moodle_exception $exception): void { + string $requestidentifier, int $assessmentmappingid, int $userid, ?int $taskid, \moodle_exception $exception): void { // Failed response. $response = [ "code" => "-1", @@ -1469,6 +1475,6 @@ private function mark_push_as_failed( $errorlogid = $exception->debuginfo ?: null; // Add failed transfer log. - $this->save_transfer_log($requestidentifier, $assessmentmappingid, $userid, null, $response, intval($errorlogid)); + $this->save_transfer_log($requestidentifier, $assessmentmappingid, $userid, null, $response, $taskid, intval($errorlogid)); } } diff --git a/classes/task/adhoctask.php b/classes/task/adhoctask.php index 62b9857..38b6330 100644 --- a/classes/task/adhoctask.php +++ b/classes/task/adhoctask.php @@ -51,7 +51,7 @@ public function execute() { // Run task. taskmanager::run_task($data->taskid); - taskmanager::send_email_notification($data->taskid, true); + taskmanager::send_email_notification($data->taskid); } catch (\Exception $e) { // Log error. $errlogid = logger::log('Push task failed: ' . $e->getMessage()); @@ -60,7 +60,7 @@ public function execute() { taskmanager::update_task_status($data->taskid, taskmanager::PUSH_TASK_STATUS_FAILED, $errlogid); // Email the user. - taskmanager::send_email_notification($data->taskid, false); + taskmanager::send_email_notification($data->taskid); } } } diff --git a/classes/taskmanager.php b/classes/taskmanager.php index 67f5aa6..dfaa7a6 100644 --- a/classes/taskmanager.php +++ b/classes/taskmanager.php @@ -84,8 +84,8 @@ public static function run_task(int $taskid) { $i = 0; // Push mark and submission log for each student in the mapping. foreach ($mapping->students as $student) { - $manager->push_grade_to_sits($mapping, $student->userid); - $manager->push_submission_log_to_sits($mapping, $student->userid); + $manager->push_grade_to_sits($mapping, $student->userid, $task->id); + $manager->push_submission_log_to_sits($mapping, $student->userid, $task->id); $i++; // Calculate progress. @@ -328,64 +328,73 @@ public static function get_pending_task_in_queue(int $assessmentmappingid): bool * Email user the result of the task. * * @param int $taskid - * @param bool $success * @return void * @throws \coding_exception * @throws \dml_exception * @throws \moodle_exception */ - public static function send_email_notification($taskid, bool $success) : void { - global $DB, $PAGE; - - // Define email object for the subject and content. - $email = new \stdClass(); - $email->status = $success ? get_string('task:status:completed', 'local_sitsgradepush') : - get_string('task:status:failed', 'local_sitsgradepush'); - $email->activityname = get_string('email:unknown', 'local_sitsgradepush'); - $email->mab = get_string('email:unknown', 'local_sitsgradepush'); - - // Get the task first. - if (!$task = $DB->get_record(manager::TABLE_TASKS, ['id' => $taskid])) { - throw new \moodle_exception('error:tasknotfound', 'local_sitsgradepush'); - } + public static function send_email_notification(int $taskid) : void { + global $DB, $PAGE, $OUTPUT; // Get the content of the task. - $sql = 'SELECT am.id, am.coursemoduleid, CONCAT(cg.mapcode, "-", cg.mabseq) AS mab - FROM {' . manager::TABLE_ASSESSMENT_MAPPING . '} am + $sql = 'SELECT + t.id as taskid, + t.userid, + am.id as assessmentmappingid, + am.coursemoduleid, + CONCAT(cg.mapcode, "-", cg.mabseq) AS mab, + cg.mabname + FROM {' . manager::TABLE_TASKS . '} t + JOIN {' . manager::TABLE_ASSESSMENT_MAPPING . '} am ON t.assessmentmappingid = am.id JOIN {' . manager::TABLE_COMPONENT_GRADE . '} cg ON am.componentgradeid = cg.id - WHERE am.id = :assessmentmappingid'; + WHERE t.id = :taskid'; $params = [ - 'assessmentmappingid' => $task->assessmentmappingid, + 'taskid' => $taskid, ]; // Task content found. if ($result = $DB->get_record_sql($sql, $params)) { + // Get the course module information. $coursemodule = get_coursemodule_from_id(null, $result->coursemoduleid); - $email->mab = $result->mab; - $email->activityname = $coursemodule->name; - $url = new \moodle_url( - '/local/sitsgradepush/index.php', - ['id' => $coursemodule->id] - ); - $email->link = $url->out(false); - } - // Email user the result of the task. - if ($success) { - $content = get_string('email:content:success', 'local_sitsgradepush', $email); + // Transfer history page link. + $url = new \moodle_url('/local/sitsgradepush/index.php', ['id' => $coursemodule->id]); + + // Get the user who scheduled the task. + $user = $DB->get_record('user', ['id' => $result->userid]); + $PAGE->set_context(context_user::instance($user->id)); + + // Get transfer records for the task. + $transferrecords = $DB->get_records(manager::TABLE_TRANSFER_LOG, ['taskid' => $taskid, 'type' => manager::PUSH_GRADE]); + + // Separate succeeded and failed transfer records. + $succeededcount = 0; + $failedcount = 0; + foreach ($transferrecords as $transferrecord) { + $transfer = new \stdClass(); + $response = json_decode($transferrecord->response); + if ($response->code == "0") { + $succeededcount++; + } else { + $failedcount++; + } + } + + // Render the email content. + $content = $OUTPUT->render_from_template('local_sitsgradepush/notification_email', [ + 'user_name' => fullname($user), + 'activity_name' => $coursemodule->name, + 'map_code' => $result->mab, + 'sits_assessment' => $result->mabname, + 'activity_url' => $url->out(false), + 'support_url' => get_config('local_sitsgradepush', 'suppuort_page_url') ?? '', + 'succeeded_count' => $succeededcount, + 'failed_count' => $failedcount, + ]); + email_to_user($user, $user, get_string('email:subject', 'local_sitsgradepush'), $content); } else { - $content = get_string('email:content:fail', 'local_sitsgradepush', $email); + throw new \moodle_exception('error:tasknotfound', 'local_sitsgradepush'); } - - // Make status' first letter uppercase for subject. - $email->status = ucfirst($email->status); - $subject = get_string('email:subject', 'local_sitsgradepush', $email); - - // Get the user who scheduled the task. - $user = $DB->get_record('user', ['id' => $task->userid]); - - $PAGE->set_context(context_user::instance($user->id)); - email_to_user($user, $user, $subject, $content); } } diff --git a/db/install.xml b/db/install.xml index 0e9c431..cb5841d 100644 --- a/db/install.xml +++ b/db/install.xml @@ -1,5 +1,5 @@ - @@ -54,6 +54,7 @@ + diff --git a/db/upgrade.php b/db/upgrade.php index 0bb218a..c8d8b95 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -381,5 +381,20 @@ function xmldb_local_sitsgradepush_upgrade($oldversion) { upgrade_plugin_savepoint(true, 2023121900, 'local', 'sitsgradepush'); } + if ($oldversion < 2024020100) { + + // Define field taskid to be added to local_sitsgradepush_tfr_log. + $table = new xmldb_table('local_sitsgradepush_tfr_log'); + $field = new xmldb_field('taskid', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'usermodified'); + + // Conditionally launch add field taskid. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Sitsgradepush savepoint reached. + upgrade_plugin_savepoint(true, 2024020100, 'local', 'sitsgradepush'); + } + return true; } diff --git a/lang/en/local_sitsgradepush.php b/lang/en/local_sitsgradepush.php index 866186e..2b2b368 100644 --- a/lang/en/local_sitsgradepush.php +++ b/lang/en/local_sitsgradepush.php @@ -50,6 +50,8 @@ $string['settings:userprofilefield:desc'] = 'User profile field for export staff'; $string['settings:sync_threshold'] = 'Sync Threshold'; $string['settings:sync_threshold:desc'] = 'The threshold to allow for running synchronous mark transfer task'; +$string['settings:support_page_url'] = 'Support Page URL'; +$string['settings:support_page_url:desc'] = 'Used in the notification email to provide a link to the support page'; $string['label:gradepushassessmentselect'] = 'Select SITS assessment to link to'; $string['label:jumpto'] = 'Jump to'; $string['label:pushall'] = 'Transfer All'; @@ -99,7 +101,6 @@ $string['dashboard:transfermarks'] = 'Transfer marks'; $string['dashboard:changesource'] = 'Change Source'; $string['dashboard:marks_transfer_in_progress'] = 'Marks transfer in progress'; -$string['dashboard:activity_button_label'] = '{$a} activity'; // Select source page. $string['selectsource:header'] = 'Select Source'; @@ -115,7 +116,6 @@ $string['existingactivity:no_match_row'] = 'No matching rows found.'; $string['existingactivity:navbar'] = 'Existing Activity'; - // Error strings. $string['error:assessmentmapping'] = 'Assessment mapping is not found. ID: {$a}'; $string['error:assessmentisnotmapped'] = 'This activity is not mapped to any assessment component.'; @@ -185,10 +185,18 @@ $string['privacy:metadata:local_sitsgradepush_tasks:info'] = 'Additional information about the transfer task.'; // Email strings. -$string['email:subject'] = 'Marks Transfer Task {$a->status}: {$a->activityname} - {$a->mab}'; -$string['email:content:success'] = 'Marks Transfer Task from {$a->activityname} to {$a->mab} has been {$a->status}.

You can check the marks transfer history for this task here: {$a->activityname} - {$a->mab}'; -$string['email:content:fail'] = 'Marks Transfer Task from {$a->activityname} to {$a->mab} has been {$a->status}.

Please try again later.'; -$string['email:unknown'] = 'unknown'; +$string['email:subject'] = 'Marks Transfer Completed'; +$string['email:username'] = 'Dear {$a},'; +$string['email:part_one'] = 'The marks transfer task has been completed. Below are the details of the task:'; +$string['email:activity_name'] = 'Activity name:'; +$string['email:map_code'] = 'Map code:'; +$string['email:sits_assessment'] = 'SITS assessment:'; +$string['email:summary'] = 'Summary:'; +$string['email:no_of_succeeded_transfers'] = 'Number of succeeded transfers: {$a}'; +$string['email:no_of_failed_transfers'] = 'Number of failed transfers: {$a}'; +$string['email:transfer_history_text'] = 'Click here to see the marks transfer records.'; +$string['email:support_text'] = 'To get more information or assistance related to marks transfer, please visit our Support Page.'; +$string['email:best_regards'] = 'Best regards,
DLE Team'; // Confirmation Modal strings. $string['confirmmodal:header'] = 'Confirm mark transfer?'; diff --git a/settings.php b/settings.php index 3b8dfb7..55f6ff9 100644 --- a/settings.php +++ b/settings.php @@ -131,6 +131,15 @@ '', $options) ); + + // Set the support page URL. + $settings->add(new admin_setting_configtext('local_sitsgradepush/suppuort_page_url', + get_string('settings:support_page_url', 'local_sitsgradepush'), + get_string('settings:support_page_url:desc', 'local_sitsgradepush'), + 'https://wiki.ucl.ac.uk/pages/viewpage.action?pageId=306185189', + PARAM_URL, + 50 + )); } $subplugins = core_plugin_manager::instance()->get_plugins_of_type('sitsapiclient'); diff --git a/templates/notification_email.mustache b/templates/notification_email.mustache new file mode 100644 index 0000000..9d1a444 --- /dev/null +++ b/templates/notification_email.mustache @@ -0,0 +1,67 @@ +{{! + This file is part the Local SITS Grade Push plugin for Moodle + Moodle is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Moodle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Moodle. If not, see . +}} +{{! + @template local_sitsgradepush/email_notification + + Template for notification email. + + Classes required for JS: + * none + + Data attributes required for JS: + * none + + Context variables required for this template: + * user_name - String, User who initiated the transfer. + * activity_name - String, moodle activity name. + * map_code - String, SITS map code & sequence number. + * sits_assessment - String, SITS assessment component name. + * activity_url - String, moodle activity's URL. + * support_url - String, support page's URL. + * succeededcount - Integer, number of succeeded transfers. + * failedcount - Integer, number of failed transfers. + + Example context (json): + { + "user_name": "Romanoff Natasha", + "activity_name": "Coursework 4000 word written case studies (50%)", + "map_code": "PHAY0063A7P-001", + "sits_assessment": "Coursework 4000 word written case studies (50%)", + "activity_url": "https://localhost/moodle/mod/assign/view.php?id=2", + "support_url": "https://wiki.ucl.ac.uk/markstransfer/support.php", + "succeeded_count": 10, + "failed_count": 2 + } +}} + +
+

{{#str}} email:subject, local_sitsgradepush {{/str}}

+

{{#str}} email:username, local_sitsgradepush, {{user_name}} {{/str}}

+

{{#str}} email:part_one, local_sitsgradepush {{/str}}

+
    +
  • {{#str}} email:activity_name, local_sitsgradepush {{/str}} {{activity_name}}
  • +
  • {{#str}} email:map_code, local_sitsgradepush {{/str}} {{map_code}}
  • +
  • {{#str}} email:sits_assessment, local_sitsgradepush {{/str}} {{sits_assessment}}
  • +
+

{{#str}} email:summary, local_sitsgradepush {{/str}}

+
    +
  • {{#str}} email:no_of_succeeded_transfers, local_sitsgradepush, {{succeeded_count}} {{/str}}
  • +
  • {{#str}} email:no_of_failed_transfers, local_sitsgradepush, {{failed_count}} {{/str}}
  • +
+

{{#str}} email:transfer_history_text, local_sitsgradepush, {{activity_url}} {{/str}}

+

{{#str}} email:support_text, local_sitsgradepush, {{support_url}} {{/str}}

+

{{#str}} email:best_regards, local_sitsgradepush {{/str}}

+
diff --git a/version.php b/version.php index 48a07b2..8d3ca75 100644 --- a/version.php +++ b/version.php @@ -27,7 +27,7 @@ $plugin->component = 'local_sitsgradepush'; $plugin->release = '0.1.0'; -$plugin->version = 2023122200; +$plugin->version = 2024020100; $plugin->requires = 2023100900; $plugin->maturity = MATURITY_ALPHA; $plugin->dependencies = [