Owns the learning domain for a website: enrolments, module status progress and completion, expiry, renewal, and completion actions such as certificates and reward points. Registered in the application context as learningManager and reached from server-side Java code via C(LearningManager.class); most methods are plain service calls rather than GraalJS-exported functions, with newModuleStatusBuilder() as the exception. On startup it launches a background daemon thread that asynchronously persists SCORM/xAPI module status field updates so frequent progress pings do not block the request thread.
Group: Managers
Implements: StartableService
Properties
| Property | Returns | Description |
|---|---|---|
| certificates | List<Certificate> | All certificates defined for the current tenant's admin organisation. Never null; empty if none have been created. |
| enrolements | List<Enrolement> | All enrolments for the current tenant, up to 1000 records. Never null; empty if there are no enrolments. |
Methods
saveModuleField(String fname, String fvalue, ModuleStatus ms, ModuleFolder mf) · saveModuleFieldImmediate(String fname, String fvalue, ModuleStatus ms) · getEnrolements() · getCertificates() · findModuleCalendarEvents(Profile p, ModuleFolder mf) · findComingModuleCalendarEvents(Profile p, ModuleFolder mf) · findLatestDueDate(Profile p, ModuleFolder mf) · enrolInProgram(Group group, Website website, String programCode, boolean completable) · unenroleFromProgram(Group group, Website website, String programCode, boolean completable) · findModuleStatuses(Organisation team) · modulesList(BaseEntity entity) · numModulesComplete(Organisation team) · programs(Website website) · programs(Website website, Branch branch) · acceptSubmision(int scorePerc, ModuleStatus ms, Profile currentUser) · rejectSubmission(ModuleStatus ms, Profile currentUser) · deleteModuleStatus(ModuleStatus ms) · findEnrolementsForUser(Profile profile, Website website, String programCode, String courseCode) · findEnrolements(Website website, String programCode, String courseCode) · resetModuleStatus(ModuleStatus ms) · processModuleExpiry(ModuleStatus ms) · processModuleExpiry(ModuleStatus ms, boolean processEvents) · processModuleRenewal(ModuleStatus ms) · processModuleRenewal(ModuleStatus ms, boolean processEvents) · getModuleStatus(ModuleFolder mf, boolean autocreate, Profile curUser, boolean force) · setComplete(ModuleStatus ms, ModuleFolder mf) · setComplete(ModuleStatus ms, ModuleFolder mf, boolean isComplete, Profile user, boolean force) · submitAssessmentRequest(ModuleFolder mf, ModuleStatus ms, Profile user) · doSelfPacedCompletion(ModuleFolder mf, ModuleStatus ms, Profile user) · onModuleComplete(ModuleStatus moduleStatus, RootFolder rf, Date now) · getModuleCalEvents(ModuleStatus ms) · calcExpiryDate(ModuleFolder mf, ModuleStatus ms, Date lastRun) · calcModuleScore(ModuleFolder mf, ModuleStatus ms) · processModuleCompleteAction(ModuleFolder mf, ModuleCompleteAction a, UserResource userResource, ModuleStatus ms) · createCertificate(Certificate c, Double numberOfCpdPoints, String moduleTitle, ModuleStatus moduleStatus) · calcPercentComplete(ModuleFolder mf, String currentPage) · createEnrolment(Website website, Group group, String programName, String courseName, boolean completable) · loadLearningResourceFolders(Website website, String programCode, String courseCode, String moduleCode) · newModuleStatusBuilder()
saveModuleField(String fname, String fvalue, ModuleStatus ms, ModuleFolder mf)
Returns: void
Records a single SCORM/xAPI field value against a module status. Fields that drive workflow state (lesson/completion status, progress measure, or raw score) are saved immediately and synchronously so completion side effects such as certificates and events fire straight away; all other fields are queued and written asynchronously by the background field-update thread to avoid blocking playback.
| Parameter | Description |
|---|---|
fname | the SCORM/xAPI field name, e.g. "cmi.core.lesson_status" or "cmi.progress_measure" |
fvalue | the raw field value as reported by the module player |
ms | the module status the field belongs to |
mf | the module folder the module status is for |
saveModuleFieldImmediate(String fname, String fvalue, ModuleStatus ms)
Returns: void
Writes a single field value directly onto the module status, bypassing the async queue used by saveModuleField. Used for workflow fields that must apply straight away, and by the background field-update thread when it flushes a queued update.
| Parameter | Description |
|---|---|
fname | the SCORM/xAPI field name to set |
fvalue | the raw field value to store |
ms | the module status to update |
getEnrolements()
Returns: List<Enrolement>
All enrolments for the current tenant, up to 1000 records. Never null; empty if there are no enrolments.
getCertificates()
Returns: List<Certificate>
All certificates defined for the current tenant's admin organisation. Never null; empty if none have been created.
findModuleCalendarEvents(Profile p, ModuleFolder mf)
Returns: List<ModuleCalEvent>
Finds the calendar events for a module that the given profile is eligible to attend, based on cohort membership. Includes past and future events; use findComingModuleCalendarEvents to restrict to events that have not yet ended.
| Parameter | Description |
|---|---|
p | the profile whose cohort membership is checked |
mf | the module folder whose calendar events are searched |
findComingModuleCalendarEvents(Profile p, ModuleFolder mf)
Returns: List<ModuleCalEvent>
Finds the calendar events for a module that are still current (end date after now) and that the given profile is eligible to attend, based on cohort membership.
| Parameter | Description |
|---|---|
p | the profile whose cohort membership is checked |
mf | the module folder whose calendar events are searched |
findLatestDueDate(Profile p, ModuleFolder mf)
Returns: Date
Finds the start date of the latest upcoming calendar event the profile can attend for a module, used as the due date shown to the learner. Returns null if there are no current events for the profile's cohort.
| Parameter | Description |
|---|---|
p | the profile whose cohort membership is checked |
mf | the module folder whose calendar events are searched |
enrolInProgram(Group group, Website website, String programCode, boolean completable)
Returns: void
Enrols a group in a program, creating an enrolment record that grants members access to the program's courses and modules.
| Parameter | Description |
|---|---|
group | the group to enrol |
website | the website the program belongs to |
programCode | the code of the program to enrol the group in |
completable | true if members of the group can complete modules and receive awards |
unenroleFromProgram(Group group, Website website, String programCode, boolean completable)
Returns: void
Removes a group's enrolment in a program.
| Parameter | Description |
|---|---|
group | the group to unenrol |
website | the website the program belongs to |
programCode | the code of the program to unenrol the group from |
completable | not currently used |
findModuleStatuses(Organisation team)
Returns: List<ModuleStatus>
Finds all module statuses for users within the given organisation, scoped to the current tenant.
| Parameter | Description |
|---|---|
team | the organisation whose users' module statuses are found |
modulesList(BaseEntity entity)
Returns: ModulesList
Builds a list of module statuses for the given entity, scoped to the current tenant. If the entity is an organisation, includes the module statuses of all users within it; otherwise it is treated as a profile and only that user's module statuses are included.
| Parameter | Description |
|---|---|
entity | the organisation or profile to find module statuses for |
numModulesComplete(Organisation team)
Returns: long
Counts the module statuses for users within the given organisation that are currently active and complete, as at now, scoped to the current tenant.
| Parameter | Description |
|---|---|
team | the organisation whose users' module statuses are counted |
programs(Website website)
Returns: ProgramsModel
Loads the program structure for a website's live branch.
| Parameter | Description |
|---|---|
website | the website to load programs for |
programs(Website website, Branch branch)
Returns: ProgramsModel
Loads the program structure for a website on the given branch, by walking to the website's "programs" folder and collecting its program folders.
| Parameter | Description |
|---|---|
website | the website to load programs for |
branch | the branch to read content from; the website's live branch is used if null |
acceptSubmision(int scorePerc, ModuleStatus ms, Profile currentUser)
Returns: void
Accepts a learner's submitted assessment: marks the module status complete with the given score, calculates its expiry and renewal dates, and fires a module-complete event. Throws if the module status has already been assessed.
| Parameter | Description |
|---|---|
scorePerc | the score percentage to record for the submission |
ms | the module status being assessed |
currentUser | the profile of the assessor, used for logging |
rejectSubmission(ModuleStatus ms, Profile currentUser)
Returns: void
Rejects a learner's submitted assessment: clears the submitted and assessed dates and marks the module status incomplete, so the learner can resubmit.
| Parameter | Description |
|---|---|
ms | the module status to reject |
currentUser | not currently used |
deleteModuleStatus(ModuleStatus ms)
Returns: void
Permanently deletes a module status and everything derived from it: field values, quiz attempts, CPD awards and reward entries. Throws if the module status does not belong to the current tenant.
| Parameter | Description |
|---|---|
ms | the module status to delete |
findEnrolementsForUser(Profile profile, Website website, String programCode, String courseCode)
Returns: List<Enrolement>
Finds the enrolments on a website that apply to a given profile, optionally filtered by program and course code. An enrolment applies to the profile if it has no enroled group, or if the profile is a member of the enroled group and, when the enrolment is linked to a promotion, is eligible for that promotion.
| Parameter | Description |
|---|---|
profile | the profile to find applicable enrolments for |
website | the website to search enrolments on |
programCode | the program code to filter by, or null/blank to match any program |
courseCode | the course code to filter by, or null/blank to match any course |
findEnrolements(Website website, String programCode, String courseCode)
Returns: List
Finds the enrolments on a website, optionally filtered by program and course code, without regard to any particular profile.
| Parameter | Description |
|---|---|
website | the website to search enrolments on |
programCode | the program code to filter by, or null/blank to match any program |
courseCode | the course code to filter by, or null/blank to match any course |
resetModuleStatus(ModuleStatus ms)
Returns: void
Resets a module status to incomplete, with no expiry date, no progress and no score. Also deletes its quiz attempts and field values, and fires an expiry event so listeners such as journeys can react.
| Parameter | Description |
|---|---|
ms | the module status to reset |
processModuleExpiry(ModuleStatus ms)
Returns: void
Processes the expiry of a module status, firing expiry events.
| Parameter | Description |
|---|---|
ms | the module status to process |
processModuleExpiry(ModuleStatus ms, boolean processEvents)
Returns: void
Processes the expiry of a module status: if it is complete, resets it and, when requested, fires the events that trigger dependent journeys and reindexing. Does nothing if the module status is not currently complete.
| Parameter | Description |
|---|---|
ms | the module status to process |
processEvents | true to fire expiry events, e.g. to trigger journeys; false to reset silently |
processModuleRenewal(ModuleStatus ms)
Returns: void
Processes the renewal of a module status, firing renewal events.
| Parameter | Description |
|---|---|
ms | the module status to process |
processModuleRenewal(ModuleStatus ms, boolean processEvents)
Returns: void
Processes the renewal of a module status: if it is not already in the renewal state, clears its quiz attempts and marks it as due for renewal, and, when requested, fires the events that trigger dependent journeys and reindexing.
| Parameter | Description |
|---|---|
ms | the module status to process |
processEvents | true to fire renewal events, e.g. to trigger journeys; false to renew silently |
getModuleStatus(ModuleFolder mf, boolean autocreate, Profile curUser, boolean force)
Returns: ModuleStatus
Finds the module status for a user and module folder, optionally creating one if none exists yet. A new module status is only created when the module is completable and, unless force is true, startable for the user; a newly started module fires a module-started event.
| Parameter | Description |
|---|---|
mf | the module folder to find or create a module status for |
autocreate | true to create a new module status when none exists |
curUser | the profile the module status belongs to |
force | true to create a module status even if the module is not currently startable |
setComplete(ModuleStatus ms, ModuleFolder mf)
Returns: void
Makes a module status complete for its owning profile, triggering completion actions such as awarding points and certificates.
| Parameter | Description |
|---|---|
ms | the module status to complete |
mf | the module folder for the module |
setComplete(ModuleStatus ms, ModuleFolder mf, boolean isComplete, Profile user, boolean force)
Returns: void
Completes or validates completion of a module status, taking a pessimistic lock to prevent concurrent completions. Submits an assessment request for instructor-led or assignment modules, or completes self-paced modules immediately; does nothing if already complete and not in renewal.
| Parameter | Description |
|---|---|
ms | the module status to complete; must not be null |
mf | the module folder for the module |
isComplete | must be true; false always throws, uncompleting a module is not supported |
user | the profile completing the module, used for logging |
force | not currently used |
submitAssessmentRequest(ModuleFolder mf, ModuleStatus ms, Profile user)
Returns: void
Submits an instructor-led or assignment module for assessment, linking it to the calendar event the user is registered and acknowledged for, and fires a submitted event. Throws if the module has already been submitted, or if an instructor-led module has no linked, acknowledged event.
| Parameter | Description |
|---|---|
mf | the module folder being submitted |
ms | the module status being submitted |
user | the profile submitting the module |
doSelfPacedCompletion(ModuleFolder mf, ModuleStatus ms, Profile user)
Returns: void
Completes a self-paced module immediately: calculates its score and expiry/renewal dates, marks it complete, logs progress, runs any configured completion actions such as certificates or reward points, and finally fires a module-complete event.
| Parameter | Description |
|---|---|
mf | the module folder being completed |
ms | the module status being completed |
user | the profile whose module is being completed |
onModuleComplete(ModuleStatus moduleStatus, RootFolder rf, Date now)
Returns: void
Records a completion entry in the learning log for a module status.
| Parameter | Description |
|---|---|
moduleStatus | the module status that has completed |
rf | the root folder the module belongs to |
now | the date to record the completion against |
getModuleCalEvents(ModuleStatus ms)
Returns: List<ModuleCalEvent>
Finds the calendar events for a module status's program, course and module, on the current website.
| Parameter | Description |
|---|---|
ms | the module status to find calendar events for |
calcExpiryDate(ModuleFolder mf, ModuleStatus ms, Date lastRun)
Returns: Date
Calculates the date a module status will expire, by adding the module's configured expiry frequency and multiple to the given reference date, in the organisation's timezone.
| Parameter | Description |
|---|---|
mf | the module folder whose expiry settings are used |
ms | the module status whose organisation's timezone is used |
lastRun | the reference date the expiry period is added to |
calcModuleScore(ModuleFolder mf, ModuleStatus ms)
Returns: int
Calculates a module status's score as the average of the most recent quiz attempt on each quiz page in the module. Returns 100 if the module has no scored quiz attempts.
| Parameter | Description |
|---|---|
mf | the module folder whose quiz pages are scored |
ms | the module status to calculate the score for |
processModuleCompleteAction(ModuleFolder mf, ModuleCompleteAction a, UserResource userResource, ModuleStatus ms)
Returns: void
Applies a single module-complete action to a user, such as awarding a certificate or reward points. Does nothing if the action is restricted to a group the user is not a member of. Throws if a reward action refers to a reward from a different organisation.
| Parameter | Description |
|---|---|
mf | the module folder the action is configured on |
a | the module-complete action to apply |
userResource | the resource for the user the action applies to |
ms | the module status that triggered the action |
createCertificate(Certificate c, Double numberOfCpdPoints, String moduleTitle, ModuleStatus moduleStatus)
Returns: CpdAward
Creates a CPD award for a module status against a certificate, or returns the existing award if one already exists for that certificate and module status.
| Parameter | Description |
|---|---|
c | the certificate the award is issued under |
numberOfCpdPoints | the number of CPD points to award |
moduleTitle | the title of the module the award is for |
moduleStatus | the module status the award is issued against |
calcPercentComplete(ModuleFolder mf, String currentPage)
Returns: Integer
Calculates how far through a module's pages the given page is, as a percentage, based on the page's position in the module's ordered list of module and quiz pages.
| Parameter | Description |
|---|---|
mf | the module folder whose pages are counted |
currentPage | the name of the page to calculate progress for |
createEnrolment(Website website, Group group, String programName, String courseName, boolean completable)
Returns: Enrolement
Creates an enrolment linking a group to a program, or to a course within a program, on a website. Any existing enrolment for the same group, program and course is removed first.
| Parameter | Description |
|---|---|
website | the website the enrolment applies to |
group | the group to enrol |
programName | the program code to enrol the group in |
courseName | the course code to enrol the group in, or blank to enrol in the whole program |
completable | true if members of the group can complete modules and receive awards |
loadLearningResourceFolders(Website website, String programCode, String courseCode, String moduleCode)
Returns: Map<String,Object>
Returns a Map containing ProgramFolder, CourseFolder, and ModuleFolders for the provided learning resource. If the resource code is null, the resource and its children will be ignored.
| Parameter | Description |
|---|---|
website | {@code Website} If null, the function returns null immediately. |
programCode | {@code String} If null, the function returns null immediately. |
courseCode | {@code String} If null, the function will stop checking the module. |
moduleCode | {@code String} |
newModuleStatusBuilder()
Returns: ModuleStatusBuilder
Returns a builder to create or update ModuleStatus.