diff --git a/backup/moodle2/backup_attendance_stepslib.php b/backup/moodle2/backup_attendance_stepslib.php
index 9275784..8c10d11 100644
--- a/backup/moodle2/backup_attendance_stepslib.php
+++ b/backup/moodle2/backup_attendance_stepslib.php
@@ -51,8 +51,8 @@ class backup_attendance_activity_structure_step extends backup_activity_structur
'acronym', 'description', 'grade', 'studentavailability', 'setunmarked', 'visible', 'deleted', 'setnumber'));
$warnings = new backup_nested_element('warnings');
- $warning = new backup_nested_element('warning', array('id'), array(
- 'warningpercent', 'warnafter', 'emailuser', 'emailsubject', 'emailcontent', 'emailcontentformat', 'thirdpartyemails'));
+ $warning = new backup_nested_element('warning', array('id'), array('warningpercent', 'warnafter',
+ 'maxwarn', 'emailuser', 'emailsubject', 'emailcontent', 'emailcontentformat', 'thirdpartyemails'));
$sessions = new backup_nested_element('sessions');
$session = new backup_nested_element('session', array('id'), array(
diff --git a/classes/add_warning_form.php b/classes/add_warning_form.php
index f337ce8..c21ad5e 100644
--- a/classes/add_warning_form.php
+++ b/classes/add_warning_form.php
@@ -60,6 +60,11 @@ class mod_attendance_add_warning_form extends moodleform {
$mform->setType('warnafter', PARAM_INT);
$mform->setDefault('warnafter', $config->warnafter);
+ $mform->addElement('select', 'maxwarn', get_string('maxwarn', 'mod_attendance'), $options);
+ $mform->addHelpButton('maxwarn', 'maxwarn', 'mod_attendance');
+ $mform->setType('maxwarn', PARAM_INT);
+ $mform->setDefault('maxwarn', $config->maxwarn);
+
$mform->addElement('checkbox', 'emailuser', get_string('emailuser', 'mod_attendance'));
$mform->addHelpButton('emailuser', 'emailuser', 'mod_attendance');
$mform->setDefault('emailuser', $config->emailuser);
diff --git a/classes/structure.php b/classes/structure.php
index d517ccf..3fce0d1 100644
--- a/classes/structure.php
+++ b/classes/structure.php
@@ -647,14 +647,21 @@ class mod_attendance_structure {
$sesslog[$sid]->takenby = $USER->id;
}
}
-
+ // Get existing session log.
$dbsesslog = $this->get_session_log($this->pageparams->sessionid);
foreach ($sesslog as $log) {
// Don't save a record if no statusid or remark.
if (!empty($log->statusid) || !empty($log->remarks)) {
if (array_key_exists($log->studentid, $dbsesslog)) {
- $log->id = $dbsesslog[$log->studentid]->id;
- $DB->update_record('attendance_log', $log);
+ // Check if anything important has changed before updating record.
+ // Don't update timetaken/takenby records if nothing has changed.
+ if ($dbsesslog[$log->studentid]->remarks <> $log->remarks ||
+ $dbsesslog[$log->studentid]->statusid <> $log->statusid ||
+ $dbsesslog[$log->studentid]->statusset <> $log->statusset) {
+
+ $log->id = $dbsesslog[$log->studentid]->id;
+ $DB->update_record('attendance_log', $log);
+ }
} else {
$DB->insert_record('attendance_log', $log, false);
}
@@ -664,6 +671,7 @@ class mod_attendance_structure {
$session = $this->get_session_info($this->pageparams->sessionid);
$session->lasttaken = $now;
$session->lasttakenby = $USER->id;
+
$DB->update_record('attendance_sessions', $session);
if ($this->grade != 0) {
@@ -967,7 +975,7 @@ class mod_attendance_structure {
public function get_session_log($sessionid) {
global $DB;
- return $DB->get_records('attendance_log', array('sessionid' => $sessionid), '', 'studentid,statusid,remarks,id');
+ return $DB->get_records('attendance_log', array('sessionid' => $sessionid), '', 'studentid,statusid,remarks,id,statusset');
}
/**
diff --git a/classes/task/notify.php b/classes/task/notify.php
index 0c9f80f..138097c 100644
--- a/classes/task/notify.php
+++ b/classes/task/notify.php
@@ -44,16 +44,14 @@ class notify extends \core\task\scheduled_task {
return; // Warnings not enabled.
}
$now = time(); // Store current time to use in queries so they all match nicely.
- $lastrun = get_config('mod_attendance', 'notifylastrun');
- if (empty($lastrun)) {
- $lastrun = 0;
- }
- if (!empty($lastrun)) {
- mtrace("Get warnings to send for sessions that have ended since: ".userdate($lastrun));
- }
$orderby = 'ORDER BY cm.id, atl.studentid, n.warningpercent ASC';
- $records = attendance_get_users_to_notify(array(), $orderby, $lastrun, true);
+
+ // Get records for attendance sessions that have been updated since last time this task ran.
+ // Note: this returns all users for these sessions - even if the users attendance wasn't changed
+ // since last time we ran, before sending a notification we check to see if the users have
+ // updated attendance logs since last time they were notified.
+ $records = attendance_get_users_to_notify(array(), $orderby, true);
$sentnotifications = array();
$thirdpartynotifications = array();
$numsentusers = 0;
@@ -64,8 +62,22 @@ class notify extends \core\task\scheduled_task {
}
if (!empty($record->emailuser)) {
- // Only send one warning to this user from each attendance in this run. - flag any higher percent notifications as sent.
+ // Only send one warning to this user from each attendance in this run.
+ // Flag any higher percent notifications as sent.
if (empty($sentnotifications[$record->userid]) || !in_array($record->aid, $sentnotifications[$record->userid])) {
+
+ // If has previously been sent a warning, check to see if this user has
+ // attendance updated since the last time the notification was sent.
+ if (!empty($record->timesent)) {
+ $sql = "SELECT *
+ FROM {attendance_log} l
+ JOIN {attendance_sessions} s ON s.id = l.sessionid
+ WHERE s.attendanceid = ? AND studentid = ? AND timetaken > ?";
+ if (!$DB->record_exists_sql($sql, array($record->aid, $record->userid, $record->timesent))) {
+ continue; // Skip this record and move to the next user.
+ }
+ }
+
// Convert variables in emailcontent.
$record = attendance_template_variables($record);
$user = $DB->get_record('user', array('id' => $record->userid));
@@ -91,14 +103,14 @@ class notify extends \core\task\scheduled_task {
$thirdpartynotifications[$senduser] = array();
}
if (!isset($thirdpartynotifications[$senduser][$record->aid . '_' . $record->userid])) {
- $thirdpartynotifications[$senduser][$record->aid . '_' . $record->userid] = get_string('thirdpartyemailtext', 'attendance', $record);
+ $thirdpartynotifications[$senduser][$record->aid . '_' . $record->userid]
+ = get_string('thirdpartyemailtext', 'attendance', $record);
}
} else {
mtrace("user".$senduser. "does not have capablity in cm".$record->cmid);
}
}
}
-
$notify = new \stdClass();
$notify->userid = $record->userid;
$notify->notifyid = $record->notifyid;
@@ -125,7 +137,5 @@ class notify extends \core\task\scheduled_task {
mtrace($numsentthird ." thirdparty emails sent");
}
}
-
- set_config('notifylastrun', $now, 'mod_attendance');
}
}
\ No newline at end of file
diff --git a/db/install.xml b/db/install.xml
index 482b8e0..efd9c6c 100644
--- a/db/install.xml
+++ b/db/install.xml
@@ -119,6 +119,7 @@
+
@@ -141,7 +142,7 @@
-
+
diff --git a/db/upgrade.php b/db/upgrade.php
index 0917366..68f9f5a 100644
--- a/db/upgrade.php
+++ b/db/upgrade.php
@@ -408,5 +408,31 @@ function xmldb_attendance_upgrade($oldversion=0) {
upgrade_mod_savepoint(true, 2017071305, 'attendance');
}
+ if ($oldversion < 2017071800) {
+ // Define field setunmarked to be added to attendance_statuses.
+ $table = new xmldb_table('attendance_warning');
+ $field = new xmldb_field('maxwarn', XMLDB_TYPE_INTEGER, '10', null, true, null, '1', 'warnafter');
+
+ // Conditionally launch add field automark.
+ if (!$dbman->field_exists($table, $field)) {
+ $dbman->add_field($table, $field);
+ }
+ // Attendance savepoint reached.
+ upgrade_mod_savepoint(true, 2017071800, 'attendance');
+ }
+
+ if ($oldversion < 2017071802) {
+ // Define field setunmarked to be added to attendance_statuses.
+ $table = new xmldb_table('attendance_warning_done');
+
+ $index = new xmldb_index('notifyid_userid', XMLDB_INDEX_UNIQUE, array('notifyid', 'userid'));
+ $dbman->drop_index($table, $index);
+
+ $index = new xmldb_index('notifyid', XMLDB_INDEX_NOTUNIQUE, array('notifyid', 'userid'));
+ $dbman->add_index($table, $index);
+
+ // Attendance savepoint reached.
+ upgrade_mod_savepoint(true, 2017071802, 'attendance');
+ }
return $result;
}
diff --git a/lang/en/attendance.php b/lang/en/attendance.php
index 1eb0354..9f0391d 100644
--- a/lang/en/attendance.php
+++ b/lang/en/attendance.php
@@ -227,6 +227,8 @@ $string['maxpossible_help'] = 'Shows the score each user can reach if they recei
';
$string['maxpossiblepercentage'] = 'Maximum possible percentage';
$string['maxpossiblepoints'] = 'Maximum possible points';
+$string['maxwarn'] = 'Maximum number of e-mail warnings';
+$string['maxwarn_help'] = 'The maximum number of times a warning should be sent (only one warning per session is sent)';
$string['mergeuser'] = 'Merge user';
$string['modulename'] = 'Attendance';
$string['modulename_help'] = 'The attendance activity module enables a teacher to take attendance during class and students to view their own attendance record.
diff --git a/locallib.php b/locallib.php
index 7f663bf..52ae86e 100644
--- a/locallib.php
+++ b/locallib.php
@@ -716,15 +716,15 @@ SELECT a.id, a.course as courseid, c.fullname as coursename, atl.studentid AS us
* Generates a list of users flagged at-risk.
*
* @param array $courseids optional list of courses to return
- * @param array $sincetime optional allows a list to be calculated for cron processing.
* @param bool $allfornotify get notification list for scheduled task.
* @return stdClass
*/
-function attendance_get_users_to_notify($courseids = array(), $orderby = '', $sincetime = 0, $allfornotify = false) {
+function attendance_get_users_to_notify($courseids = array(), $orderby = '', $allfornotify = false) {
global $DB;
$joingroup = 'LEFT JOIN {groups_members} gm ON (gm.userid = atl.studentid AND gm.groupid = ats.groupid)';
$where = ' AND (ats.groupid = 0 or gm.id is NOT NULL)';
+ $having = '';
$params = array();
if (!empty($courseids)) {
@@ -733,8 +733,8 @@ function attendance_get_users_to_notify($courseids = array(), $orderby = '', $si
$params = array_merge($params, $inparams);
}
if ($allfornotify) {
- // Exclude warnings that have already been sent.
- $where .= ' AND ns.id IS NULL ';
+ // Exclude warnings that have already sent the max num.
+ $having .= ' AND n.maxwarn > COUNT(DISTINCT ns.id) ';
}
$unames = get_all_user_name_fields(true);
@@ -743,8 +743,9 @@ function attendance_get_users_to_notify($courseids = array(), $orderby = '', $si
$idfield = $DB->sql_concat('cm.id', 'atl.studentid', 'n.id');
$sql = "SELECT {$idfield} as uniqueid, a.id as aid, {$unames2}, a.name as aname, cm.id as cmid, c.id as courseid,
c.fullname as coursename, atl.studentid AS userid, n.id as notifyid, n.warningpercent, n.emailsubject,
- n.emailcontent, n.emailcontentformat, n.emailuser, n.thirdpartyemails, ns.timesent, n.warnafter,
+ n.emailcontent, n.emailcontentformat, n.emailuser, n.thirdpartyemails, n.warnafter, n.maxwarn,
COUNT(DISTINCT ats.id) AS numtakensessions, SUM(stg.grade) AS points, SUM(stm.maxgrade) AS maxpoints,
+ COUNT(DISTINCT ns.id) as nscount, MAX(ns.timesent) as timesent,
SUM(stg.grade) / SUM(stm.maxgrade) AS percent
FROM {attendance_sessions} ats
JOIN {attendance} a ON a.id = ats.attendanceid
@@ -763,21 +764,22 @@ function attendance_get_users_to_notify($courseids = array(), $orderby = '', $si
GROUP BY attendanceid, setnumber) stm
ON (stm.setnumber = ats.statusset AND stm.attendanceid = ats.attendanceid)
{$joingroup}
- WHERE ats.lasttaken >= {$sincetime} {$where}
+ WHERE 1 = 1 {$where}
GROUP BY uniqueid, a.id, a.name, a.course, c.fullname, atl.studentid, n.id, n.warningpercent,
- n.emailsubject, n.emailcontent, n.emailcontentformat, n.warnafter,
- n.emailuser, n.thirdpartyemails, ns.timesent, cm.id, c.id, {$unames2}
+ n.emailsubject, n.emailcontent, n.emailcontentformat, n.warnafter, n.maxwarn,
+ n.emailuser, n.thirdpartyemails, cm.id, c.id, {$unames2}, ns.userid
HAVING n.warnafter <= COUNT(DISTINCT ats.id) AND n.warningpercent > ((SUM(stg.grade) / SUM(stm.maxgrade)) * 100)
+ {$having}
{$orderby}";
if (!$allfornotify) {
$idfield = $DB->sql_concat('cmid', 'userid');
// Only show one record per attendance for teacher reports.
- $sql = "SELECT {$idfield} as id, {$unames}, aid, cmid, courseid, aname, coursename, userid, MIN(warningpercent),
- numtakensessions, points, maxpoints, percent, timesent
+ $sql = "SELECT DISTINCT {$idfield} as id, {$unames}, aid, cmid, courseid, aname, coursename, userid,
+ numtakensessions, percent, MAX(timesent) as timesent
FROM ({$sql}) as m
- GROUP BY id, aid, cmid, courseid, aname, userid, numtakensessions, points, maxpoints,
- percent, coursename, timesent, {$unames} {$orderby}";
+ GROUP BY id, aid, cmid, courseid, aname, userid, numtakensessions,
+ percent, coursename, {$unames} {$orderby}";
}
return $DB->get_records_sql($sql, $params);
diff --git a/renderer.php b/renderer.php
index b7a6bb8..3c2bcb7 100644
--- a/renderer.php
+++ b/renderer.php
@@ -949,7 +949,8 @@ class mod_attendance_renderer extends plugin_renderer_base {
get_string('pointssessionscompleted', 'attendance'),
get_string('percentagesessionscompleted', 'attendance'));
$table->align = array('left', 'left', 'center', 'center', 'center');
- $table->colclasses = array('colcourse', 'colatt', 'colsessionscompleted', 'colpointssessionscompleted', 'colpercentagesessionscompleted');
+ $table->colclasses = array('colcourse', 'colatt', 'colsessionscompleted',
+ 'colpointssessionscompleted', 'colpercentagesessionscompleted');
$totalattendance = 0;
$totalpercentage = 0;
foreach ($userdata->coursesatts as $ca) {
diff --git a/resetcalendar.php b/resetcalendar.php
index be8b598..3632078 100644
--- a/resetcalendar.php
+++ b/resetcalendar.php
@@ -70,7 +70,8 @@ if (get_config('attendance', 'enablecalendar')) {
}
} else {
if ($action == 'delete' && confirm_sesskey()) {
- $caleventids = $DB->get_records_select_menu('attendance_sessions', 'caleventid > 0', array(), '', 'caleventid, caleventid as id2');
+ $caleventids = $DB->get_records_select_menu('attendance_sessions', 'caleventid > 0', array(),
+ '', 'caleventid, caleventid as id2');
$DB->delete_records_list('event', 'id', $caleventids);
$DB->execute("UPDATE {attendance_sessions} set caleventid = 0");
echo $OUTPUT->notification(get_string('eventsdeleted', 'mod_attendance'), 'notifysuccess');
diff --git a/settings.php b/settings.php
index fc99010..d89f3ad 100644
--- a/settings.php
+++ b/settings.php
@@ -125,6 +125,9 @@ if ($ADMIN->fulltree) {
$settings->add(new admin_setting_configselect('attendance/warnafter',
get_string('warnafter', 'attendance'), get_string('warnafter_help', 'attendance'), 5, $options));
+ $settings->add(new admin_setting_configselect('attendance/maxwarn',
+ get_string('maxwarn', 'attendance'), get_string('maxwarn_help', 'attendance'), 1, $options));
+
$settings->add(new admin_setting_configcheckbox('attendance/emailuser',
get_string('emailuser', 'attendance'), get_string('emailuser_help', 'attendance'), 1));
diff --git a/version.php b/version.php
index cc73377..527ec38 100644
--- a/version.php
+++ b/version.php
@@ -23,9 +23,9 @@
*/
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2017071305;
+$plugin->version = 2017071802;
$plugin->requires = 2017042100;
-$plugin->release = '3.3.9';
+$plugin->release = '3.3.10';
$plugin->maturity = MATURITY_ALPHA;
$plugin->cron = 0;
$plugin->component = 'mod_attendance';
diff --git a/warnings.php b/warnings.php
index eaa3bba..0716575 100644
--- a/warnings.php
+++ b/warnings.php
@@ -84,6 +84,7 @@ if ($data = $mform->get_data()) {
$notify->warningpercent = $data->warningpercent;
$notify->warnafter = $data->warnafter;
+ $notify->maxwarn = $data->maxwarn;
$notify->emailuser = empty($data->emailuser) ? 0 : $data->emailuser;
$notify->emailsubject = $data->emailsubject;
$notify->emailcontent = $data->emailcontent['text'];
@@ -113,6 +114,7 @@ if ($data = $mform->get_data()) {
$notify->idnumber = $data->idnumber;
$notify->warningpercent = $data->warningpercent;
$notify->warnafter = $data->warnafter;
+ $notify->maxwarn = $data->maxwarn;
$notify->emailuser = empty($data->emailuser) ? 0 : $data->emailuser;
$notify->emailsubject = $data->emailsubject;
$notify->emailcontentformat = $data->emailcontent['format'];