Browse Source

Fix #189 Add ability to mark sessions using a csv import. (#489)

Thanks to jonathanchan2 for initial work on this.
nwp90-nwp90-allsessionsreport
Dan Marsden 4 years ago
committed by GitHub
parent
commit
fc6aa93e2c
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 97
      classes/form/import/marksessions.php
  2. 132
      classes/form/import/marksessions_confirm.php
  3. 302
      classes/import/marksessions.php
  4. 29
      classes/structure.php
  5. 122
      import/marksessions.php
  6. 179
      lang/en/attendance.php
  7. 9
      locallib.php
  8. 10
      renderer.php

97
classes/form/import/marksessions.php

@ -0,0 +1,97 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// 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 <http://www.gnu.org/licenses/>.
/**
* This file contains the form used to upload a csv attendance file to automatically update attendance records.
*
* @package mod_attendance
* @copyright 2019 Jonathan Chan <jonathan.chan@sta.uwi.edu>
* @copyright based on work by 2012 NetSpot {@link http://www.netspot.com.au}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */
namespace mod_attendance\form\import;
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
use core_text;
use moodleform;
require_once($CFG->libdir.'/formslib.php');
/**
* Class for displaying the csv upload form.
*
* @package mod_attendance
* @copyright 2019 Jonathan Chan <jonathan.chan@sta.uwi.edu>
* @copyright based on work by 2012 NetSpot {@link http://www.netspot.com.au}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class marksessions extends moodleform {
/**
* Called to define this moodle form
*
* @return void
*/
public function definition() {
global $COURSE;
$mform = $this->_form;
$params = $this->_customdata;
$mform->addElement('header', 'uploadattendance', get_string('uploadattendance', 'attendance'));
$fileoptions = array('subdirs' => 0,
'maxbytes' => $COURSE->maxbytes,
'accepted_types' => 'csv',
'maxfiles' => 1);
$mform->addElement('filepicker', 'attendancefile', get_string('uploadafile'), null, $fileoptions);
$mform->addRule('attendancefile', get_string('uploadnofilefound'), 'required', null, 'client');
$mform->addHelpButton('attendancefile', 'attendancefile', 'attendance');
$encodings = core_text::get_encodings();
$mform->addElement('select', 'encoding', get_string('encoding', 'grades'), $encodings);
$mform->addHelpButton('encoding', 'encoding', 'grades');
$radio = array();
$radio[] = $mform->createElement('radio', 'separator', null, get_string('septab', 'grades'), 'tab');
$radio[] = $mform->createElement('radio', 'separator', null, get_string('sepcomma', 'grades'), 'comma');
$radio[] = $mform->createElement('radio', 'separator', null, get_string('sepcolon', 'grades'), 'colon');
$radio[] = $mform->createElement('radio', 'separator', null, get_string('sepsemicolon', 'grades'), 'semicolon');
$mform->addGroup($radio, 'separator', get_string('separator', 'grades'), ' ', false);
$mform->addHelpButton('separator', 'separator', 'grades');
$mform->setDefault('separator', 'comma');
$mform->addElement('hidden', 'id', $params['id']);
$mform->setType('id', PARAM_INT);
$mform->addElement('hidden', 'sessionid', $params['sessionid']);
$mform->setType('sessionid', PARAM_INT);
$mform->addElement('hidden', 'grouptype', $params['grouptype']);
$mform->setType('grouptype', PARAM_INT);
$mform->addElement('hidden', 'confirm', 0);
$mform->setType('confirm', PARAM_BOOL);
$this->add_action_buttons(true, get_string('uploadattendance', 'attendance'));
}
/**
* Display an error on the import form.
*
* @param string $msg
*/
public function set_import_error($msg) {
$mform = $this->_form;
$mform->setElementError('attendancefile', $msg);
}
}

132
classes/form/import/marksessions_confirm.php

@ -0,0 +1,132 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// 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 <http://www.gnu.org/licenses/>.
/**
* This file contains the form used to upload a csv attendance file to automatically update attendance records.
*
* @package mod_attendance
* @copyright 2020 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */
namespace mod_attendance\form\import;
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
use core_text;
use moodleform;
require_once($CFG->libdir.'/formslib.php');
/**
* Mark attendance sessions confirm csv upload.
*
* @package mod_attendance
* @copyright 2020 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class marksessions_confirm extends moodleform {
/**
* Called to define this moodle form
*
* @return void
*/
public function definition() {
$params = $this->_customdata;
$importer = $this->_customdata['importer'];
$mform = $this->_form;
$mform->addElement('hidden', 'confirm', 1);
$mform->setType('confirm', PARAM_BOOL);
$foundheaders = $importer->list_found_headers();
// Add user mapping.
$mform->addElement('select', 'userfrom', get_string('userimportfield', 'attendance'), $foundheaders);
$mform->addHelpButton('userfrom', 'userimportfield', 'attendance');
// This allows the user to choose which field in the user database the identifying column will map to.
$useroptions = array(
'userid' => get_string('userid', 'attendance'),
'username' => get_string('username'),
'idnumber' => get_string('idnumber'),
'email' => get_string('email')
);
$mform->addElement('select', 'userto', get_string('userimportto', 'attendance'), $useroptions);
// Check if we can set an easy default value.
foreach (array_keys($useroptions) as $o) {
if (in_array($o, $foundheaders)) {
$mform->setDefault('userto', $o);
$mform->setDefault('userfrom', $o);
break;
}
}
$mform->addHelpButton('userto', 'userimportto', 'attendance');
// Below options need a "none" option in the headers.
$foundheaders[- 1] = get_string('notset', 'mod_attendance');
ksort($foundheaders);
// Add scan time mapping.
$mform->addElement('select', 'scantime', get_string('scantime', 'attendance'), $foundheaders);
$mform->addHelpButton('scantime', 'scantime', 'attendance');
$mform->setDefault('scantime', -1);
// Add status mapping.
$mform->addElement('select', 'status', get_string('importstatus', 'attendance'), $foundheaders);
$mform->addHelpButton('status', 'importstatus', 'attendance');
$mform->disabledif('status', 'scantime', 'noteq', -1);
$mform->disabledif('scantime', 'status', 'noteq', -1);
// Try to set a useful default value for scantime or status.
$key = array_search('status', $foundheaders);
if ($key !== false) {
// Status is passed in CSV - set that as default.
$mform->setDefault('status', $key);
$mform->setDefault('scantime', -1);
} else {
$keyscan = array_search('scantime', $foundheaders);
if ($keyscan !== false) {
// The Scantime var exists in the csv.
$mform->setDefault('status', -1);
$mform->setDefault('scantime', $keyscan);
} else {
$mform->setDefault('status', -1);
$mform->setDefault('scantime', -1);
}
}
foreach (array_keys($useroptions) as $o) {
if (in_array($o, $foundheaders)) {
$mform->setDefault('userto', $o);
$mform->setDefault('userfrom', $o);
break;
}
}
$mform->addElement('hidden', 'id', $params['id']);
$mform->setType('id', PARAM_INT);
$mform->addElement('hidden', 'sessionid', $params['sessionid']);
$mform->setType('sessionid', PARAM_INT);
$mform->addElement('hidden', 'grouptype', $params['grouptype']);
$mform->setType('grouptype', PARAM_INT);
$mform->addElement('hidden', 'importid', $importer->get_importid());
$mform->setType('importid', PARAM_INT);
$mform->setConstant('importid', $importer->get_importid());
$this->add_action_buttons(true, get_string('uploadattendance', 'attendance'));
}
}

302
classes/import/marksessions.php

@ -0,0 +1,302 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// 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 <http://www.gnu.org/licenses/>.
/**
* Import attendance sessions class.
*
* @package mod_attendance
* @copyright 2020 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_attendance\import;
defined('MOODLE_INTERNAL') || die();
use csv_import_reader;
use mod_attendance_notifyqueue;
use mod_attendance_structure;
use stdClass;
/**
* Import attendance sessions.
*
* @package mod_attendance
* @copyright 2020 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class marksessions {
/** @var string $error The errors message from reading the xml */
protected $error = '';
/** @var array $sessions The sessions info */
protected $sessions = array();
/** @var array $mappings The mappings info */
protected $mappings = array();
/** @var int The id of the csv import */
protected $importid = 0;
/** @var csv_import_reader|null $importer */
protected $importer = null;
/** @var array $foundheaders */
protected $foundheaders = array();
/** @var bool $useprogressbar Control whether importing should use progress bars or not. */
protected $useprogressbar = false;
/** @var \core\progress\display_if_slow|null $progress The progress bar instance. */
protected $progress = null;
/** @var mod_attendance_structure $att - the mod_attendance_structure class */
private $att;
/**
* Store an error message for display later
*
* @param string $msg
*/
public function fail($msg) {
$this->error = $msg;
return false;
}
/**
* Get the CSV import id
*
* @return string The import id.
*/
public function get_importid() {
return $this->importid;
}
/**
* Get the list of headers found in the import.
*
* @return array The found headers (names from import)
*/
public function list_found_headers() {
return $this->foundheaders;
}
/**
* Read the data from the mapping form.
*
* @param array $data The mapping data.
*/
protected function read_mapping_data($data) {
if ($data) {
return array(
'user' => $data->userfrom,
'scantime' => $data->scantime,
'status' => $data->status
);
} else {
return array(
'user' => 0,
'scantime' => 1,
'status' => 2
);
}
}
/**
* Get the a column from the imported data.
*
* @param array $row The imported raw row
* @param int $index The column index we want
* @return string The column data.
*/
protected function get_column_data($row, $index) {
if ($index < 0) {
return '';
}
return isset($row[$index]) ? $row[$index] : '';
}
/**
* Constructor - parses the raw text for sanity.
*
* @param string $text The raw csv text.
* @param mod_attendance_structure $att The current assignment
* @param string $encoding The encoding of the csv file.
* @param string $delimiter The specified delimiter for the file.
* @param string $importid The id of the csv import.
* @param array $mappingdata The mapping data from the import form.
* @param bool $useprogressbar Whether progress bar should be displayed, to avoid html output on CLI.
*/
public function __construct($text = null, $att, $encoding = null, $delimiter = null, $importid = 0,
$mappingdata = null, $useprogressbar = false) {
global $CFG, $USER;
require_once($CFG->libdir . '/csvlib.class.php');
$type = 'marksessions';
$this->att = $att;
if (! $importid) {
if ($text === null) {
return;
}
$this->importid = csv_import_reader::get_new_iid($type);
$this->importer = new csv_import_reader($this->importid, $type);
if (! $this->importer->load_csv_content($text, $encoding, $delimiter)) {
$this->fail(get_string('invalidimportfile', 'attendance'));
$this->importer->cleanup();
echo $text;
return;
}
} else {
$this->importid = $importid;
$this->importer = new csv_import_reader($this->importid, $type);
}
if (! $this->importer->init()) {
$this->fail(get_string('invalidimportfile', 'attendance'));
$this->importer->cleanup();
return;
}
$this->foundheaders = $this->importer->get_columns();
$this->useprogressbar = $useprogressbar;
$sesslog = array();
$validusers = $this->att->get_users($this->att->pageparams->grouptype, 0);
$users = array();
// Re-key validusers based on the identifier used by import.
if (!empty($mappingdata) && $mappingdata->userto !== 'id') {
foreach ($validusers as $u) {
if (!empty($u->{$mappingdata->userto})) {
$users[$u->{$mappingdata->userto}] = $u;
}
}
} else {
$users = $validusers;
}
$statuses = $this->att->get_statuses();
$statusmap = array();
foreach ($statuses as $st) {
$statusmap[$st->acronym] = $st->id;
}
$sessioninfo = $this->att->get_session_info($this->att->pageparams->sessionid);
while ($row = $this->importer->next()) {
// This structure mimics what the UI form returns.
if (empty($mappingdata)) {
// Precheck - just return for now - would be nice to look at adding preview option in future.
return;
}
$mapping = $this->read_mapping_data($mappingdata);
// Get user.
$extuser = $this->get_column_data($row, $mapping['user']);
if (empty($users[$extuser])) {
$a = new \stdClass();
$a->extuser = $extuser;
$a->userfield = $mappingdata->userto;
\mod_attendance_notifyqueue::notify_problem(get_string('error:usernotfound', 'attendance', $a));
continue;
}
$userid = $users[$extuser]->id;
if (isset($sesslog[$userid])) {
\mod_attendance_notifyqueue::notify_problem(get_string('error:userduplicate', 'attendance', $extuser));
continue;
}
$sesslog[$userid] = new stdClass();
$sesslog[$userid]->studentid = $userid;
$sesslog[$userid]->statusset = $statuses;
$sesslog[$userid]->remarks = '';
$sesslog[$userid]->sessionid = $this->att->pageparams->sessionid;
$sesslog[$userid]->timetaken = time();
$sesslog[$userid]->takenby = $USER->id;
$scantime = $this->get_column_data($row, $mapping['scantime']);
if (!empty($scantime)) {
$t = strtotime($scantime);
if ($t === false) {
$a = new \stdClass();
$a->extuser = $extuser;
$a->scantime = $scantime;
\mod_attendance_notifyqueue::notify_problem(get_string('error:timenotreadable', 'attendance', $a));
continue;
}
$sesslog[$userid]->statusid = attendance_session_get_highest_status($this->att, $sessioninfo, $t);
} else {
$status = $this->get_column_data($row, $mapping['status']);
if (!empty($statusmap[$status])) {
$sesslog[$userid]->statusid = $statusmap[$status];
} else {
$a = new \stdClass();
$a->extuser = $extuser;
$a->status = $status;
\mod_attendance_notifyqueue::notify_problem(get_string('error:statusnotfound', 'attendance', $a));
continue;
}
}
}
$this->sessions = $sesslog;
$this->importer->close();
if (empty($sesslog)) {
$this->fail(get_string('invalidimportfile', 'attendance'));
return;
} else {
raise_memory_limit(MEMORY_EXTRA);
// We are calling from browser, display progress bar.
if ($this->useprogressbar === true) {
$this->progress = new \core\progress\display_if_slow(get_string('processingfile', 'attendance'));
$this->progress->start_html();
} else {
$this->progress = new \core\progress\none();
}
$this->progress->start_progress('', count($this->sessions));
$this->progress->end_progress();
}
}
/**
* Get parse errors.
*
* @return array of errors from parsing the xml.
*/
public function get_error() {
return $this->error;
}
/**
* Create sessions using the CSV data.
*
* @return void
*/
public function import() {
$this->att->save_log($this->sessions);
\mod_attendance_notifyqueue::notify_success(get_string('sessionsupdated', 'mod_attendance'));
}
}

29
classes/structure.php

@ -703,16 +703,18 @@ class mod_attendance_structure {
/**
* Take attendance from form data.
*
* @param stdClass $formdata
* @param stdClass $data
*/
public function take_from_form_data($formdata) {
global $DB, $USER;
// TODO: WARNING - $formdata is unclean - comes from direct $_POST - ideally needs a rewrite but we do some cleaning below.
// This whole function could do with a nice clean up.
public function take_from_form_data($data) {
global $USER;
// WARNING - $data is unclean - comes from direct $_POST - ideally needs a rewrite but we do some cleaning below.
$statuses = implode(',', array_keys( (array)$this->get_statuses() ));
$now = time();
$sesslog = array();
$formdata = (array)$formdata;
$formdata = (array)$data;
foreach ($formdata as $key => $value) {
// Look at Remarks field because the user options may not be passed if empty.
if (substr($key, 0, 7) == 'remarks') {
@ -732,6 +734,19 @@ class mod_attendance_structure {
$sesslog[$sid]->takenby = $USER->id;
}
}
$this->save_log($sesslog);
}
/**
* Helper function to save attendance and trigger events.
*
* @param array $sesslog
* @throws coding_exception
* @throws dml_exception
*/
public function save_log($sesslog) {
global $DB, $USER;
// Get existing session log.
$dbsesslog = $this->get_session_log($this->pageparams->sessionid);
foreach ($sesslog as $log) {
@ -754,7 +769,7 @@ class mod_attendance_structure {
}
$session = $this->get_session_info($this->pageparams->sessionid);
$session->lasttaken = $now;
$session->lasttaken = time();
$session->lasttakenby = $USER->id;
$DB->update_record('attendance_sessions', $session);

122
import/marksessions.php

@ -0,0 +1,122 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// 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 <http://www.gnu.org/licenses/>.
/**
* Mark attendance sessions using a csv import.
*
* @package mod_attendance
* @author Dan Marsden
* @copyright 2020 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define('NO_OUTPUT_BUFFERING', true);
require(__DIR__ . '/../../../config.php');
require_once($CFG->dirroot . '/mod/attendance/lib.php');
require_once($CFG->dirroot . '/mod/attendance/locallib.php');
$pageparams = new mod_attendance_take_page_params();
$id = required_param('id', PARAM_INT);
$pageparams->sessionid = required_param('sessionid', PARAM_INT);
$pageparams->grouptype = optional_param('grouptype', null, PARAM_INT);
$pageparams->page = optional_param('page', 1, PARAM_INT);
$importid = optional_param('importid', null, PARAM_INT);
$cm = get_coursemodule_from_id('attendance', $id, 0, false, MUST_EXIST);
$course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST);
$att = $DB->get_record('attendance', array('id' => $cm->instance), '*', MUST_EXIST);
// Check this is a valid session for this attendance.
$session = $DB->get_record('attendance_sessions', array('id' => $pageparams->sessionid, 'attendanceid' => $att->id),
'*', MUST_EXIST);
require_login($course, true, $cm);
$context = context_module::instance($cm->id);
require_capability('mod/attendance:takeattendances', $context);
$pageparams->init($course->id);
$PAGE->set_context($context);
$url = new moodle_url('/mod/attendance/import/marksessions.php');
$PAGE->set_url($url);
$PAGE->set_title($course->shortname. ": ".$att->name);
$PAGE->set_heading($course->fullname);
$PAGE->set_cacheable(true);
$PAGE->navbar->add($att->name);
$att = new mod_attendance_structure($att, $cm, $course, $PAGE->context, $pageparams);
// Form processing and displaying is done here.
$output = $PAGE->get_renderer('mod_attendance');
$formparams = ['id' => $cm->id,
'sessionid' => $pageparams->sessionid,
'grouptype' => $pageparams->grouptype];
$form = null;
if (optional_param('needsconfirm', 0, PARAM_BOOL)) {
$form = new \mod_attendance\form\import\marksessions($url->out(false), $formparams);
} else if (optional_param('confirm', 0, PARAM_BOOL)) {
$importer = new \mod_attendance\import\marksessions(null, $att, null, null, $importid);
$formparams['importer'] = $importer;
$form = new \mod_attendance\form\import\marksessions_confirm(null, $formparams);
} else {
$form = new \mod_attendance\form\import\marksessions($url->out(false), $formparams);
}
if ($form->is_cancelled()) {
redirect(new moodle_url('/mod/attendance/take.php',
array('id' => $cm->id,
'sessionid' => $pageparams->sessionid,
'grouptype' => $pageparams->grouptype)));
return;
} else if ($data = $form->get_data()) {
if ($data->confirm) {
$importid = $data->importid;
$importer = new \mod_attendance\import\marksessions(null, $att, null, null, $importid, $data, true);
$error = $importer->get_error();
if ($error) {
$form = new \mod_attendance\form\import\marksessions($url->out(false), $formparams);
$form->set_import_error($error);
} else {
echo $output->header();
$sessions = $importer->import();
mod_attendance_notifyqueue::show();
$url = new moodle_url('/mod/attendance/manage.php', array('id' => $att->cmid));
echo $output->continue_button($url);
echo $output->footer();
die();
}
} else {
$text = $form->get_file_content('attendancefile');
$encoding = $data->encoding;
$delimiter = $data->separator;
$importer = new \mod_attendance\import\marksessions($text, $att, $encoding, $delimiter, 0, null, true);
$formparams['importer'] = $importer;
$confirmform = new \mod_attendance\form\import\marksessions_confirm(null, $formparams);
$form = $confirmform;
$pagetitle = get_string('confirmcolumnmappings', 'attendance');
}
}
// Output for the file upload form starts here.
echo $output->header();
echo $output->heading(get_string('attendanceforthecourse', 'attendance') . ' :: ' . format_string($course->fullname));
echo $output->box(get_string('marksessionimportcsvhelp', 'attendance'));
mod_attendance_notifyqueue::show();
$form->display();
echo $output->footer();

179
lang/en/attendance.php

@ -30,13 +30,15 @@ $string['Lacronym'] = 'L';
$string['Lfull'] = 'Late';
$string['Pacronym'] = 'P';
$string['Pfull'] = 'Present';
$string['acronym'] = 'Acronym';
$string['absenteereport'] = 'Absentee report';
$string['acronym'] = 'Acronym';
$string['add'] = 'Add';
$string['addedrecip'] = 'Added {$a} new recipient';
$string['addedrecips'] = 'Added {$a} new recipients';
$string['addmultiplesessions'] = 'Multiple sessions';
$string['addwarning'] = 'Add warning';
$string['addsession'] = 'Add session';
$string['adduser'] = 'Add user';
$string['addwarning'] = 'Add warning';
$string['all'] = 'All';
$string['allcourses'] = 'All courses';
$string['allpast'] = 'All past';
@ -54,7 +56,10 @@ $string['attendance:viewreports'] = 'Viewing Reports';
$string['attendance:viewsummaryreports'] = 'View course summary reports';
$string['attendance:warningemails'] = 'Can be subscribed to emails with absentee users';
$string['attendance_already_submitted'] = 'Your attendance has already been set.';
$string['attendance_no_status'] = 'No valid status was available - you may be too late to record attendance.';
$string['attendancedata'] = 'Attendance data';
$string['attendancefile'] = 'Attendance file (csv format)';
$string['attendancefile_help'] = 'The file must be a CSV file with a header row and fields for identifying the user and the time attendance was recorded eg (email,scantime) or (username,time)';
$string['attendanceforthecourse'] = 'Attendance for the course';
$string['attendancegrade'] = 'Attendance grade';
$string['attendancenotset'] = 'You must set your attendance';
@ -67,16 +72,20 @@ $string['attendancesuccess'] = 'Attendance has been successfully taken';
$string['attendanceupdated'] = 'Attendance successfully updated';
$string['attforblockdirstillexists'] = 'old mod/attforblock directory still exists - you must delete this directory on your server before running this upgrade.';
$string['attrecords'] = 'Attendances records';
$string['autoassignstatus'] = 'Automatically select highest status available';
$string['autoassignstatus_help'] = 'If this is selected, students will automatically be assigned the highest available grade.';
$string['automark'] = 'Automatic marking';
$string['automarkall'] = 'Yes';
$string['automarkclose'] = 'Set unmarked at end of session';
$string['automark_help'] = 'Allows marking to be completed automatically.
If "Yes" students will be automatically marked depending on their first access to the course.
If "Set unmarked at end of session" any students who have not marked their attendance will be set to the unmarked status selected.';
$string['automarkall'] = 'Yes';
$string['automarkclose'] = 'Set unmarked at end of session';
$string['automarktask'] = 'Check for attendance sessions that require auto marking';
$string['autorecorded'] = 'system auto recorded';
$string['averageattendance'] = 'Average attendance';
$string['averageattendancegraded'] = 'Average attendance';
$string['backtoparticipants'] = 'Back to participants list';
$string['below'] = 'Below {$a}%';
$string['calclose'] = 'Close';
$string['calendarevent'] = 'Create calendar event for session';
$string['calendarevent_help'] = 'If enabled, a calendar event will be created for this session.
@ -96,6 +105,8 @@ $string['changesession'] = 'Change session';
$string['checkweekdays'] = 'Select weekdays that fall within your selected session date range.';
$string['closed'] = 'This session is not currently available for self-marking';
$string['column'] = 'column';
$string['columnmap'] = 'Column mapping';
$string['columnmap_help'] = 'For each of the fields presented, select the corresponding column in the csv file.';
$string['columns'] = 'columns';
$string['commonsession'] = 'All students';
$string['commonsessions'] = 'All students';
@ -106,6 +117,7 @@ $string['confirmdeleteuser'] = 'Are you sure you want to delete user \'{$a->full
$string['copyfrom'] = 'Copy attendance data from';
$string['countofselected'] = 'Count of selected';
$string['course'] = 'Course';
$string['coursemessage'] = 'Message course users';
$string['courseshortname'] = 'Course shortname';
$string['coursesummary'] = 'Course summary report';
$string['createmultiplesessions'] = 'Create multiple sessions';
@ -116,16 +128,12 @@ The sessions begin on the date of the base session and continue until the \'repe
* <strong>Repeat every</strong>: This allows for a frequency setting. If your class will meet every week, select 1; if it will meet every other week, select 2; every 3rd week, select 3, etc.
* <strong>Repeat until</strong>: Select the last day of class (the last day you want to take attendance).
';
$string['autoassignstatus'] = 'Automatically select highest status available';
$string['autoassignstatus_help'] = 'If this is selected, students will automatically be assigned the highest available grade.';
$string['createonesession'] = 'Create one session for the course';
$string['csvdelimiter'] = 'CSV delimiter';
$string['currentlyselectedusers'] = 'Currently selected users';
$string['date'] = 'Date';
$string['days'] = 'Days';
$string['defaultdisplaymode'] = 'Default display mode';
$string['defaultwarnings'] = 'Default warning set';
$string['defaultwarningsettings'] = 'Default warning settings';
$string['defaultwarningsettings_help'] = 'These settings define the defaults for all new warnings';
$string['defaults'] = 'Defaults';
$string['defaultsessionsettings'] = 'Default session settings';
$string['defaultsessionsettings_help'] = 'These settings define the defaults for all new sessions';
@ -136,16 +144,19 @@ $string['defaultsubnet'] = 'Default network address';
$string['defaultsubnet_help'] = 'Attendance recording may be restricted to particular subnets by specifying a comma-separated list of partial or full IP addresses. This is the default value used when creating new sessions.';
$string['defaultview'] = 'Default view on login';
$string['defaultview_desc'] = 'This is the default view shown to teachers on first login.';
$string['defaultwarnings'] = 'Default warning set';
$string['defaultwarningsettings'] = 'Default warning settings';
$string['defaultwarningsettings_help'] = 'These settings define the defaults for all new warnings';
$string['delete'] = 'Delete';
$string['deletewarningconfirm'] = 'Are you sure you want to delete this warning?';
$string['deletedgroup'] = 'The group associated with this session has been deleted';
$string['deletecheckfull'] = 'Are you absolutely sure you want to completely delete the {$a}, including all user data?';
$string['deletedgroup'] = 'The group associated with this session has been deleted';
$string['deletehiddensessions'] = 'Delete all hidden sessions';
$string['deletelogs'] = 'Delete attendance data';
$string['deleteselected'] = 'Delete selected';
$string['deletesession'] = 'Delete session';
$string['deletesessions'] = 'Delete all sessions';
$string['deleteuser'] = 'Delete user';
$string['deletewarningconfirm'] = 'Are you sure you want to delete this warning?';
$string['deletingsession'] = 'Deleting session for the course';
$string['deletingstatus'] = 'Deleting status for the course';
$string['description'] = 'Description';
@ -158,11 +169,11 @@ $string['downloadtext'] = 'Download in text format';
$string['duration'] = 'Duration';
$string['editsession'] = 'Edit Session';
$string['edituser'] = 'Edit user';
$string['emailcontent'] = 'Email content';
$string['emailcontent_default'] = 'Hi %userfirstname%,
Your attendance in %coursename% %attendancename% has dropped below %warningpercent% and is currently %percent% - we hope you are ok!
To get the most out of this course you should improve your attendance, please get in touch if you require any further support.';
$string['emailcontent'] = 'Email content';
$string['emailcontent_help'] = 'When a warning is sent to a student, it takes the email content from this field. The following wildcards can be used:
<ul>
<li>%coursename%</li>
@ -177,10 +188,9 @@ $string['emailcontent_help'] = 'When a warning is sent to a student, it takes th
<li>%maxpoints%</li>
<li>%percent%</li>
</ul>';
$string['emailsubject'] = 'Email subject';
$string['emailsubject_help'] = 'When a warning is sent to a student, it takes the email subject from this field.';
$string['emailsubject_default'] = 'Attendance warning';
$string['emailsubject_help'] = 'When a warning is sent to a student, it takes the email subject from this field.';
$string['emailuser'] = 'Email user';
$string['emailuser_help'] = 'If checked, a warning will be sent to the student.';
$string['emptyacronym'] = 'Empty acronyms are not allowed. Status record not updated.';
@ -190,18 +200,24 @@ $string['enablecalendar_desc'] = 'If enabled, a calendar event will be created f
$string['enablewarnings'] = 'Enable warnings';
$string['enablewarnings_desc'] = 'This allows a warning set to be defined for an attendance and email notifications to users when attendance drops below the configured threshold. <br/><strong>WARNING: This is a new feature and has not been tested extensively. Please use at your own-risk and provide feeback in the moodle forums if you find it works well.</strong>';
$string['encoding'] = 'Encoding';
$string['encoding_help'] = 'This refers to the type of barcode encoding used on the students\' id card. Typical types of barcode encoding schemes include Code-39, Code-128 and UPC-A.';
$string['endofperiod'] = 'End of period';
$string['endtime'] = 'Session end time';
$string['enrolmentend'] = 'User enrolment ends {$a}';
$string['enrolmentstart'] = 'User enrolment starts {$a}';
$string['enrolmentsuspended'] = 'Enrolment suspended';
$string['error:coursenotfound'] = 'A course with the short name {$a} can not be found.';
$string['enterpassword'] = 'Enter password';
$string['error:coursehasnoattendance'] = 'The course with the short name {$a} has no attendance activities.';
$string['error:coursenotfound'] = 'A course with the short name {$a} can not be found.';
$string['error:qrcode'] = 'Allow students to record own attendance must be enabled to use QR code! Skipping.';
$string['error:sessioncourseinvalid'] = 'A session course is invalid! Skipping.';
$string['error:sessiondateinvalid'] = 'A session date is invalid! Skipping.';
$string['error:sessionendinvalid'] = 'A session end time is invalid! Skipping.';
$string['error:sessionstartinvalid'] = 'A session start time is invalid! Skipping.';
$string['error:qrcode'] = 'Allow students to record own attendance must be enabled to use QR code! Skipping.';
$string['error:statusnotfound'] = 'User: {$a->extuser} has a status value that could not be found: {$a->status}';
$string['error:timenotreadable'] = 'User: {$a->extuser} has a scantime that could not be converted by strtotime: {$a->scantime}';
$string['error:userduplicate'] = 'User {$a} was found twice in the import. please only include one record per user.';
$string['error:usernotfound'] = 'A user with the {$a->userfield} set to {$a->extuser} could not be found';
$string['errorgroupsnotselected'] = 'Select one or more groups';
$string['errorinaddingsession'] = 'Error in adding session';
$string['erroringeneratingsessions'] = 'Error in generating sessions ';
@ -211,8 +227,8 @@ $string['eventscreated'] = 'Calendar events created';
$string['eventsdeleted'] = 'Calendar events deleted';
$string['eventsessionadded'] = 'Session added';
$string['eventsessiondeleted'] = 'Session deleted';
$string['eventsessionsimported'] = 'Sessions imported';
$string['eventsessionipshared'] = 'Attendance self-marking IP conflict';
$string['eventsessionsimported'] = 'Sessions imported';
$string['eventsessionupdated'] = 'Session updated';
$string['eventstatusadded'] = 'Status added';
$string['eventstatusupdated'] = 'Status updated';
@ -221,11 +237,13 @@ $string['eventtaken'] = 'Attendance taken';
$string['eventtakenbystudent'] = 'Attendance taken by student';
$string['export'] = 'Export';
$string['extrarestrictions'] = 'Extra restrictions';
$string['formattexttype'] = 'Formatting';
$string['from'] = 'from:';
$string['gradebookexplanation'] = 'Grade in gradebook';
$string['gradebookexplanation_help'] = 'The Attendance module displays your current attendance grade based on the number of points you have earned to date and the number of points that could have been earned to date; it does not include class periods in the future. In the gradebook, your attendance grade is based on your current attendance percentage and the number of points that can be earned over the entire duration of the course, including future class periods. As such, your attendance grades displayed in the Attendance module and in the gradebook may not be the same number of points but they are the same percentage.
For example, if you have earned 8 of 10 points to date (80% attendance) and attendance for the entire course is worth 50 points, the Attendance module will display 8/10 and the gradebook will display 40/50. You have not yet earned 40 points but 40 is the equivalent point value to your current attendance percentage of 80%. The point value you have earned in the Attendance module can never decrease, as it is based only on attendance to date; however, the attendance point value shown in the gradebook may increase or decrease depending on your future attendance, as it is based on attendance for the entire course.';
$string['graded'] = 'Graded sessions';
$string['gridcolumns'] = 'Grid columns';
$string['group'] = 'Group';
$string['groups'] = 'Groups';
@ -237,20 +255,18 @@ You can use this feature to hide older sessions instead of deleting them. Only v
$string['hiddensessionsdeleted'] = 'All hidden sessions were delete';
$string['hideextrauserdetails'] = 'Hide extra user details';
$string['hidensessiondetails'] = 'Hide session details';
$string['identifyby'] = 'Identify student by';
$string['import'] = 'Import';
$string['importfile'] = 'Import file';
$string['importfile_help'] = 'Import file';
$string['importsessions'] = 'Import Sessions';
$string['identifyby'] = 'Identify student by';
$string['importstatus'] = 'Status field';
$string['importstatus_help'] = 'This allows a status value to be included in the import - eg values like P, L, or A';
$string['includeabsentee'] = 'Include session when calculating absentee report';
$string['includeabsentee_help'] = 'If checked this session will be included in the absentee report calculations.';
$string['includeall'] = 'Select all sessions';
$string['includenottaken'] = 'Include not taken sessions';
$string['includeqrcode'] = 'Include QR code';
$string['rotateqrcode'] = 'Rotate QR code';
$string['rotateqrcodeinterval'] = 'Rotate QR code/password interval (seconds)';
$string['rotateqrcodeinterval_desc'] = 'Time interval (seconds) to rotate QR code/password by.';
$string['rotateqrcodeexpirymargin'] = 'Rotate QR code/password expiry margin (seconds)';
$string['rotateqrcodeexpirymargin_desc'] = 'Time interval (seconds) to allow expired QR code/password by.';
$string['rotateqrcode_cleartemppass_task'] = 'Task to clear temporary passwords generated by rotate QR code functionality.';
$string['includeremarks'] = 'Include remarks';
$string['incorrectpassword'] = 'You have entered an incorrect password and your attendance has not been recorded, please enter the correct password.';
$string['incorrectpasswordshort'] = 'Incorrect password, attendance not recorded.';
@ -263,7 +279,8 @@ $string['invalidsessionendtime'] = 'The end time must be greater than start time
$string['invalidstatus'] = 'You have selected an invalid status, please try again';
$string['iptimemissing'] = 'Invalid minutes to release';
$string['jumpto'] = 'Jump to';
$string['below'] = 'Below {$a}%';
$string['keepsearching'] = 'Keep searching';
$string['marksessionimportcsvhelp'] = 'This form allows you to upload a csv file containing a user identifier and a status - the status field can be the status acronym or the time that attendance was recorded for that user. If a time value is passed then it will try to assign the status value with the highest grade available at that time.';
$string['maxpossible'] = 'Maximum possible';
$string['maxpossible_help'] = 'Shows the score each user can reach if they receive the maximum points in each session not yet taken (past and future):
<ul>
@ -300,8 +317,8 @@ $string['newduration'] = 'New duration';
$string['newstatusset'] = 'New set of statuses';
$string['noabsentstatusset'] = 'The status set in use does not have a status to use when not marked.';
$string['noattendanceusers'] = 'It is not possible to export any data as there are no students enrolled in the course.';
$string['noautomark'] = 'Disabled';
$string['noattforuser'] = 'No attendance records exist for the user';
$string['noautomark'] = 'Disabled';
$string['nodescription'] = 'Regular class session';
$string['noeventstoreset'] = 'There are no calendar events that require an update.';
$string['nogroups'] = 'You can\'t add group sessions. No groups exists in course.';
@ -313,14 +330,10 @@ $string['noofdayspresent'] = 'No of days present';
$string['nosessiondayselected'] = 'No Session day selected';
$string['nosessionexists'] = 'No Session exists for this course';
$string['nosessionsselected'] = 'No sessions selected';
$string['warningdeleted'] = 'Warning deleted';
$string['warningdesc'] = 'These warnings will be automatically added to any new attendance activities. If more than one warning is triggered at exactly the same time, only the warning with the lower warning threshold will be sent.';
$string['warningdesc_course'] = 'Warnings thresholds set here affect the absentee report and allow students and third parties to be notified. If more than one warning is triggered at exactly the same time, only the warning with the lower warning threshold will be sent.';
$string['warnings'] = 'Warnings set';
$string['warningupdated'] = 'Updated warnings';
$string['notifytask'] = 'Send warnings to users';
$string['notfound'] = 'Attendance activity not found in this course!';
$string['notifytask'] = 'Send warnings to users';
$string['notmember'] = 'not&nbsp;member';
$string['notset'] = 'not set';
$string['noupgradefromthisversion'] = 'The Attendance module cannot upgrade from the version of attforblock you have installed. - please delete attforblock or upgrade it to the latest version before isntalling the new attendance module';
$string['numsessions'] = 'Number of sessions';
$string['olddate'] = 'Old date';
@ -342,7 +355,6 @@ $string['oversessionstaken_help'] = 'Shows statistics for sessions where attenda
$string['pageof'] = 'Page {$a->page} of {$a->numpages}';
$string['participant'] = 'Participant';
$string['password'] = 'Password';
$string['enterpassword'] = 'Enter password';
$string['passwordgrp'] = 'Student password';
$string['passwordgrp_help'] = 'If set students will be required to enter this password before they can set their own attendance status for the session. If empty, no password is required.';
$string['passwordrequired'] = 'You must enter the session password before you can submit your attendance';
@ -355,13 +367,37 @@ $string['points'] = 'Points';
$string['pointsallsessions'] = 'Points over all sessions';
$string['pointssessionscompleted'] = 'Points over taken sessions';
$string['preferences_desc'] = 'Changes to status sets will affect existing attendance sessions and may affect grading.';
$string['preventsharederror'] = 'Self-marking has been disabled for a session because this device appears to have been used to record attendance for another student.';
$string['preventsharedip'] = 'Prevent students sharing IP address';
$string['preventsharedip_help'] = 'Prevent students from using the same device (identified using IP address) to take attendance for other students.';
$string['preventsharediptime'] = 'Time to allow re-use of IP address (minutes)';
$string['preventsharediptime_help'] = 'Allow an IP address to be re-used for taking attendance in this session after this time has elapsed.';
$string['preventsharederror'] = 'Self-marking has been disabled for a session because this device appears to have been used to record attendance for another student.';
$string['preview'] = 'File preview';
$string['previewhtml'] = 'HTML format preview';
$string['priorto'] = 'The session date is prior to the course start date ({$a}) so that the new sessions scheduled before this date will be hidden (not accessible). You can change the course start date at any time (see course settings) in order to have access to earlier sessions.<br><br>Please change the session date or just click the "Add session" button again to confirm?';
$string['privacy:metadata:attendancelog'] = 'Log of user attendances recorded.';
$string['privacy:metadata:attendancesessions'] = 'Sessions to which attendance will be recorded.';
$string['privacy:metadata:attendancewarningdone'] = 'Log of warnings sent to users over their attendance record.';
$string['privacy:metadata:duration'] = 'Session duration in seconds';
$string['privacy:metadata:groupid'] = 'Group ID associated with session.';
$string['privacy:metadata:ipaddress'] = 'IP address attendance was marked from.';
$string['privacy:metadata:lasttaken'] = 'Timestamp of when session attendance was last taken.';
$string['privacy:metadata:lasttakenby'] = 'User ID of the last user to take attendance in this session';
$string['privacy:metadata:notifyid'] = 'ID of attendance session warning is associated with.';
$string['privacy:metadata:remarks'] = 'Comments about the user\'s attendance.';
$string['privacy:metadata:sessdate'] = 'Timestamp of when session starts.';
$string['privacy:metadata:sessionid'] = 'Attendance session ID.';
$string['privacy:metadata:statusid'] = 'ID of student\'s attendance status.';
$string['privacy:metadata:statusset'] = 'Status set to which status ID belongs.';
$string['privacy:metadata:studentid'] = 'ID of student having attendance recorded.';
$string['privacy:metadata:takenby'] = 'User ID of the user who took attendance for the student.';
$string['privacy:metadata:timemodified'] = 'Timestamp of when session was last modified';
$string['privacy:metadata:timesent'] = 'Timestamp when warning was sent.';
$string['privacy:metadata:timetaken'] = 'Timestamp of when attendance was taken for the student.';
$string['privacy:metadata:userid'] = 'ID of user to send warning to.';
$string['processingfile'] = 'Processing file';
$string['qr_cookie_error'] = 'QR session has expired.';
$string['qr_pass_wrong'] = 'QR password is wrong or has expired.';
$string['qrcode'] = 'QR Code';
$string['randompassword'] = 'Random password';
$string['remark'] = 'Remark for: {$a}';
@ -409,15 +445,23 @@ $string['requiredentry_help'] = '<p align="center"><b>Attendance</b></p>
<p align="left"><strong>Temporay user will be deleted in all cases after merge action</strong></p>';
$string['requiresubnet'] = 'Require network address';
$string['requiresubnet_help'] = 'Attendance recording may be restricted to particular subnets by specifying a comma-separated list of partial or full IP addresses.';
$string['resetcalendar'] = 'Reset calendar';
$string['resetcaledarcreate'] = 'Calendar events have been enabled but a number of existing sessions do not have events. Do you want to create calendar events for all existing sessions?';
$string['resetcaledardelete'] = 'Calendar events have been disabled but a number of existing sessions have events that should be deleted. Do you want to delete all existing events?';
$string['resetcalendar'] = 'Reset calendar';
$string['resetdescription'] = 'Remember that deleting attendance data will erase information from database. You can just hide older sessions having changed start date of course!';
$string['resetstatuses'] = 'Reset statuses to default';
$string['restoredefaults'] = 'Restore defaults';
$string['resultsperpage'] = 'Results per page';
$string['resultsperpage_desc'] = 'Number of students displayed on a page';
$string['rotateqrcode'] = 'Rotate QR code';
$string['rotateqrcode_cleartemppass_task'] = 'Task to clear temporary passwords generated by rotate QR code functionality.';
$string['rotateqrcodeexpirymargin'] = 'Rotate QR code/password expiry margin (seconds)';
$string['rotateqrcodeexpirymargin_desc'] = 'Time interval (seconds) to allow expired QR code/password by.';
$string['rotateqrcodeinterval'] = 'Rotate QR code/password interval (seconds)';
$string['rotateqrcodeinterval_desc'] = 'Time interval (seconds) to rotate QR code/password by.';
$string['save'] = 'Save attendance';
$string['scantime'] = 'Scan time';
$string['scantime_help'] = 'This allows a timestamp to be included in the import file - it will attempt to convert the timestamp passed using the PHP strtotime function and then use attendance status settings to decide which status to set for the user';
$string['search:activity'] = 'Attendance - activity information';
$string['session'] = 'Session';
$string['session_help'] = 'Session';
@ -429,7 +473,6 @@ $string['sessiondeleted'] = 'Session successfully deleted';
$string['sessionduplicate'] = 'A duplicate session exists for course: {$a->course} in attendance: {$a->activity}';
$string['sessionexist'] = 'Session not added (already exists)!';
$string['sessiongenerated'] = 'One session was successfully generated';
$string['sessionunknowngroup'] = 'A session specifies unknown group(s): {$a}';
$string['sessions'] = 'Sessions';
$string['sessionscompleted'] = 'Taken sessions';
$string['sessionsgenerated'] = '{$a} sessions were successfully generated';
@ -437,14 +480,16 @@ $string['sessionsids'] = 'IDs of sessions: ';
$string['sessionsnotfound'] = 'There is no sessions in the selected timespan';
$string['sessionstartdate'] = 'Session start date';
$string['sessionstotal'] = 'Total number of sessions';
$string['sessionsupdated'] = 'Sessions updated';
$string['sessiontype'] = 'Type';
$string['sessiontype_help'] = 'You can add sessions for all students or for a group of students. Ability to add different types depends on activity group mode.
* In group mode "No groups" you can add only sessions for all students.
* In group mode "Separate groups" you can add only sessions for a group of students.
* In group mode "Visible groups" you can add both types of sessions.
';
$string['sessiontype'] = 'Type';
$string['sessiontypeshort'] = 'Type';
$string['sessionunknowngroup'] = 'A session specifies unknown group(s): {$a}';
$string['sessionupdated'] = 'Session successfully updated';
$string['set_by_student'] = 'Self-recorded';
$string['setallstatuses'] = 'Set status for';
@ -457,20 +502,20 @@ $string['showdefaults'] = 'Show defaults';
$string['showduration'] = 'Show duration';
$string['showextrauserdetails'] = 'Show extra user details';
$string['showqrcode'] = 'Show QR Code';
$string['showsessiondetails'] = 'Show session details';
$string['showsessiondescriptiononreport'] = 'Show session description in report';
$string['showsessiondescriptiononreport_desc'] = 'Show the session description in the attendance report listing.';
$string['showsessiondetails'] = 'Show session details';
$string['somedisabledstatus'] = '(Some options have been removed as the session has started.)';
$string['sortedgrid'] = 'Sorted grid';
$string['sortedlist'] = 'Sorted list';
$string['startofperiod'] = 'Start of period';
$string['starttime'] = 'Start time';
$string['status'] = 'Status';
$string['statusall'] = 'all';
$string['statusdeleted'] = 'Status deleted';
$string['statuses'] = 'Statuses';
$string['statusset'] = 'Status set {$a}';
$string['statussetsettings'] = 'Status set';
$string['statusall'] = 'all';
$string['statusunselected'] = 'unselected';
$string['strftimedm'] = '%b %d';
$string['strftimedmy'] = '%d %b %Y';
@ -483,6 +528,7 @@ $string['studentavailability'] = 'Available for students (minutes)';
$string['studentavailability_help'] = 'When students are marking their own attendance, the number of minutes after session starts that this status is available.
<br/>If empty, this status will always be available, If set to 0 it will always be hidden to students.';
$string['studentid'] = 'Student ID';
$string['studentmarked'] = 'Your attendance in this session has been recorded.';
$string['studentmarking'] = 'Student recording';
$string['studentpassword'] = 'Student password';
$string['studentrecordingexpanded'] = 'Student recording expanded';
@ -494,9 +540,9 @@ $string['studentscanmarksessiontime'] = 'Students record attendance during sessi
$string['studentscanmarksessiontime_desc'] = 'If checked students can only record their attendance during the session.';
$string['studentscanmarksessiontimeend'] = 'Session end (minutes)';
$string['studentscanmarksessiontimeend_desc'] = 'If the session does not have an end time, how many minutes should the session be available for students to record their attendance.';
$string['submit'] = 'Submit';
$string['submitattendance'] = 'Submit attendance';
$string['submitpassword'] = 'Submit password';
$string['submit'] = 'Submit';
$string['subnet'] = 'Subnet';
$string['subnetactivitylevel'] = 'Allow subnet config at activity level';
$string['subnetactivitylevel_desc'] = 'If enabled, teachers can override the default subnet at the activity level when creating an attendance. Otherwise the site default will be used when creating a session.';
@ -515,11 +561,11 @@ $string['tempusermerge'] = 'Merge temporary user';
$string['tempusers'] = 'Temporary users';
$string['tempusersedit'] = 'Edit temporary user';
$string['tempuserslist'] = 'Temporary users';
$string['thirdpartyemails'] = 'Notify other users';
$string['thirdpartyemails_help'] = 'List of other users who will be notified. (requires the capability mod/attendance:viewreports)';
$string['thirdpartyemailsubject'] = 'Attendance warning';
$string['thirdpartyemailtext'] = '{$a->firstname} {$a->lastname} attendance within {$a->coursename} {$a->aname} is lower than {$a->warningpercent} ({$a->percent})';
$string['thirdpartyemailtextfooter'] = 'You are receiving this because the teacher of this course has added your email to the recipient’s list';
$string['thirdpartyemails'] = 'Notify other users';
$string['thirdpartyemails_help'] = 'List of other users who will be notified. (requires the capability mod/attendance:viewreports)';
$string['thiscourse'] = 'This course';
$string['time'] = 'Time';
$string['timeahead'] = 'Multiple sessions that exceed one year cannot be created, please adjust the start and end dates.';
@ -527,12 +573,18 @@ $string['to'] = 'to:';
$string['triggered'] = 'First notified';
$string['tuseremail'] = 'Email';
$string['tusername'] = 'Full name';
$string['graded'] = 'Graded sessions';
$string['ungraded'] = 'Ungraded sessions';
$string['unknowngroup'] = 'Unknown group';
$string['update'] = 'Update';
$string['uploadattendance'] = 'Upload attendance by CSV';
$string['usedefaultsubnet'] = 'Use default';
$string['usemessageform'] = 'or use the form below to send a message to the selected students';
$string['userexists'] = 'There is already a real user with this email address';
$string['userid'] = 'User ID';
$string['userimportfield'] = 'External user field';
$string['userimportfield_help'] = 'Field from uploaded CSV that contains user identifier';
$string['userimportto'] = 'Moodle user field';
$string['userimportto_help'] = 'Moodle field that matches the data from the CSV export';
$string['users'] = 'Users to export';
$string['usestatusset'] = 'Status set';
$string['variable'] = 'variable';
@ -541,46 +593,15 @@ $string['versionforprinting'] = 'version for printing';
$string['viewmode'] = 'View mode';
$string['warnafter'] = 'Number of sessions taken before warning';
$string['warnafter_help'] = 'Warnings will only be triggered when the user has had their attendance taken for at least this number of sessions.';
$string['warningdeleted'] = 'Warning deleted';
$string['warningdesc'] = 'These warnings will be automatically added to any new attendance activities. If more than one warning is triggered at exactly the same time, only the warning with the lower warning threshold will be sent.';
$string['warningdesc_course'] = 'Warnings thresholds set here affect the absentee report and allow students and third parties to be notified. If more than one warning is triggered at exactly the same time, only the warning with the lower warning threshold will be sent.';
$string['warningfailed'] = 'You cannot create a warning that uses the same percentage and number of sessions.';
$string['warningpercent'] = 'Warn if percentage falls under';
$string['warningpercent_help'] = 'A warning will be triggered when the overall percentage falls below this number.';
$string['warnings'] = 'Warnings set';
$string['warningthreshold'] = 'Warning threshold';
$string['warningupdated'] = 'Updated warnings';
$string['week'] = 'week(s)';
$string['weeks'] = 'Weeks';
$string['youcantdo'] = 'You can\'t do anything';
$string['includeabsentee'] = 'Include session when calculating absentee report';
$string['includeabsentee_help'] = 'If checked this session will be included in the absentee report calculations.';
$string['attendance_no_status'] = 'No valid status was available - you may be too late to record attendance.';
$string['studentmarked'] = 'Your attendance in this session has been recorded.';
$string['qr_cookie_error'] = 'QR session has expired.';
$string['qr_pass_wrong'] = 'QR password is wrong or has expired.';
$string['privacy:metadata:sessionid'] = 'Attendance session ID.';
$string['privacy:metadata:studentid'] = 'ID of student having attendance recorded.';
$string['privacy:metadata:statusid'] = 'ID of student\'s attendance status.';
$string['privacy:metadata:statusset'] = 'Status set to which status ID belongs.';
$string['privacy:metadata:timetaken'] = 'Timestamp of when attendance was taken for the student.';
$string['privacy:metadata:takenby'] = 'User ID of the user who took attendance for the student.';
$string['privacy:metadata:remarks'] = 'Comments about the user\'s attendance.';
$string['privacy:metadata:ipaddress'] = 'IP address attendance was marked from.';
$string['privacy:metadata:groupid'] = 'Group ID associated with session.';
$string['privacy:metadata:sessdate'] = 'Timestamp of when session starts.';
$string['privacy:metadata:duration'] = 'Session duration in seconds';
$string['privacy:metadata:lasttaken'] = 'Timestamp of when session attendance was last taken.';
$string['privacy:metadata:lasttakenby'] = 'User ID of the last user to take attendance in this session';
$string['privacy:metadata:timemodified'] = 'Timestamp of when session was last modified';
$string['privacy:metadata:notifyid'] = 'ID of attendance session warning is associated with.';
$string['privacy:metadata:userid'] = 'ID of user to send warning to.';
$string['privacy:metadata:timesent'] = 'Timestamp when warning was sent.';
$string['privacy:metadata:attendancelog'] = 'Log of user attendances recorded.';
$string['privacy:metadata:attendancesessions'] = 'Sessions to which attendance will be recorded.';
$string['privacy:metadata:attendancewarningdone'] = 'Log of warnings sent to users over their attendance record.';
$string['coursemessage'] = 'Message course users';
$string['addedrecip'] = 'Added {$a} new recipient';
$string['addedrecips'] = 'Added {$a} new recipients';
$string['keepsearching'] = 'Keep searching';
$string['formattexttype'] = 'Formatting';
$string['currentlyselectedusers'] = 'Currently selected users';
$string['usemessageform'] = 'or use the form below to send a message to the selected students';
$string['backtoparticipants'] = 'Back to participants list';
$string['previewhtml'] = 'HTML format preview';

9
locallib.php

@ -967,26 +967,29 @@ function attendance_template_variables($record) {
*
* @param mod_attendance_structure $att attendance structure
* @param stdclass $attforsession attendance_session record.
* @param int $scantime - time that session should be recorded against.
* @return bool/int
*/
function attendance_session_get_highest_status(mod_attendance_structure $att, $attforsession) {
function attendance_session_get_highest_status(mod_attendance_structure $att, $attforsession, $scantime = null) {
// Find the status to set here.
$statuses = $att->get_statuses();
$highestavailablegrade = 0;
$highestavailablestatus = new stdClass();
// Override time used in status recording.
$scantime = empty($scantime) ? time() : $scantime;
foreach ($statuses as $status) {
if ($status->studentavailability === '0') {
// This status is never available to students.
continue;
}
if (!empty($status->studentavailability)) {
$toolateforstatus = (($attforsession->sessdate + ($status->studentavailability * 60)) < time());
$toolateforstatus = (($attforsession->sessdate + ($status->studentavailability * 60)) < $scantime);
if ($toolateforstatus) {
continue;
}
}
// This status is available to the student.
if ($status->grade > $highestavailablegrade) {
if ($status->grade >= $highestavailablegrade) {
// This is the most favourable grade so far; save it.
$highestavailablegrade = $status->grade;
$highestavailablestatus = $status;

10
renderer.php

@ -468,13 +468,21 @@ class mod_attendance_renderer extends plugin_renderer_base {
* @return string
*/
protected function render_attendance_take_controls(attendance_take_data $takedata) {
$urlparams = array('id' => $takedata->cm->id,
'sessionid' => $takedata->pageparams->sessionid,
'grouptype' => $takedata->pageparams->grouptype);
$url = new moodle_url('/mod/attendance/import/marksessions.php', $urlparams);
$return = $this->output->single_button($url, get_string('uploadattendance', 'attendance'));
$table = new html_table();
$table->attributes['class'] = ' ';
$table->data[0][] = $this->construct_take_session_info($takedata);
$table->data[0][] = $this->construct_take_controls($takedata);
return $this->output->container(html_writer::table($table), 'generalbox takecontrols');
$return .= $this->output->container(html_writer::table($table), 'generalbox takecontrols');
return $return;
}
/**

Loading…
Cancel
Save