I think this started with 12.41.
- We have evidence from several sites that it's been happening before that, but those records are very old so I'll discount them. I think it was introduced in 12.41. On the sites I'm investigating, the update was very clearly when the problem started.
- It's seen in self-enrolment and audience enrolment at least. While the enrolment is performed and recorded, the 'Time enrolled’ is not recorded and therefore not available to key reports.
- It's intermittent - sometimes it happens and sometimes it doesn't, which explains why it's hard to reproduce. It feels like the process just doesn't complete.
- This can be a serious legal issue for clients where completion of compliance training once assigned must be accurate.
I understand that the missing enrol date is course_completion.timeenrolled, as opposed to the time the user was enrolled in the course.
The observable effect is:
- The enrolment date/time is being recorded in the logs and can be seen from the front end in the Completion Editor in the course
- In the logs there is a date-time record of ‘Enrolled via cohort’ and ‘Learner role assigned’
- But the ‘Time enrolled’ record is ‘Time enrolled: Not set (0)’. If the user was enrolled it would be like this ‘Time enrolled: 10 May 2022, 10:32 (1652178728)’, and that matches the date/time of the enrolment.
- What it means is that the ‘Date enrolled’ doesn’t appear in Course Completion or Record of Learning Reports.
TL-33158 Fixed the handling of incorrect course enrolment timestamps when creating course completion records
Previously, the course completion module set the enrolment date to the
current time when there were no user enrolment records. This led to the
problem where reports that used the completion data showed the wrong
enrolment dates.
This patch changes this; now the enrolment time is zero when the course
completion record is created for unenrolled users. It is only when the user
actually enrols in a course that the timeenrolled value in the completion
record is updated.
These code extracts appears to be relevant (I'm not a developer but these were reported to me as part of a developer's investigation):
* completion_completion->_save() now records the status as COMPLETION_STATUS_NOTYETSTARTED (10) when no timeenrolled, timestarted and timecompleted is provided. Previously, it resulted in status 0 which has no corresponding constant and is therefore invalid. Any customisations which rely on status 0 should be redesigned around this change.
This code is in the completion_completion->_save() function (referred to above)
$sql = "
SELECT
ue.timestart
FROM
{user_enrolments} ue
JOIN
{enrol} e
ON (e.id = ue.enrolid AND e.courseid = :courseid)
WHERE
ue.userid = :userid
AND ue.status = :active
AND e.status = :enabled
AND (
ue.timeend = 0
OR ue.timeend > :now
)
AND ue.timestart < :now2
ORDER BY
ue.timestart ASC
";
$params = array(
'enabled' => ENROL_INSTANCE_ENABLED,
'active' => ENROL_USER_ACTIVE,
'userid' => $this->userid,
'courseid' => $this->course,
'now' => $now,
'now2' => $now
);
if ($enrolments = $DB->get_record_sql($sql, $params, IGNORE_MULTIPLE)) {
$this->timeenrolled = $enrolments->timestart;
} else {
$this->timeenrolled = 0;
}
}