'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(
$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);
$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);
}
$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) {
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');
}
/**
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;
}
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));
$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;
mtrace($numsentthird ." thirdparty emails sent");
}
}
-
- set_config('notifylastrun', $now, 'mod_attendance');
}
}
\ No newline at end of file
<FIELD NAME="idnumber" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="attendance id or other id relating to this warning."/>
<FIELD NAME="warningpercent" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="Percentage that triggers this warning."/>
<FIELD NAME="warnafter" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="Start warning after this number of taken sessions."/>
+ <FIELD NAME="maxwarn" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="Maximum number of warnings to send."/>
<FIELD NAME="emailuser" TYPE="int" LENGTH="4" NOTNULL="true" SEQUENCE="false" COMMENT="Should the user be notified at this level."/>
<FIELD NAME="emailsubject" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="Email subject line for emails going to user"/>
<FIELD NAME="emailcontent" TYPE="text" NOTNULL="true" SEQUENCE="false" COMMENT="The html-formatted text that should be sent to the user"/>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
</KEYS>
<INDEXES>
- <INDEX NAME="notifyid_userid" UNIQUE="true" FIELDS="notifyid, userid"/>
+ <INDEX NAME="notifyid_userid" UNIQUE="false" FIELDS="notifyid, userid"/>
</INDEXES>
</TABLE>
</TABLES>
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;
}
</ul>';
$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.
* 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)) {
$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);
$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
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);
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) {
}
} 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');
$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));
*/
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';
$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'];
$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'];