Student Roster Sync
Every student in OEC gets a Moodle account. No IT admin needs to create accounts manually, export CSVs, or maintain a separate Moodle user list. When a student is added, updated, or deactivated in the OEC SIS, Moodle mirrors the change automatically.
OEC is the single source of truth for student identity data. The sync runs on record save (via a write() hook and background job) and is swept up by the hourly cron for any records that were missed.
Fields Synced OEC → Moodle
The sync payload sent to core_user_create_users / core_user_update_users.
| OEC field | Moodle field | Notes |
|---|---|---|
partner_id.firstname | firstname | From res.partner linked to op.student |
partner_id.lastname | lastname | From res.partner |
partner_id.email | username + email | Email used as Moodle username |
id | idnumber | Pattern: oec_student_{id}; survives Moodle rebuilds |
company_id.name | institution | Institution name from OEC company record |
active (bool) | suspended (0/1) | Inactive OEC student → suspended=1 in Moodle |
(create only) | createpassword | =1 on create; Moodle emails password to student; stripped on update |
User Lookup Fallback Chain
Before creating an account, the sync checks whether a Moodle account already exists for this student. This chain handles fresh syncs, reconnected instances, and pre-existing accounts.
moodle.mapping table lookup
Query mapping by model=op.student + oec_record_id + instance. Fastest path if the record was previously synced.
Falls through if: No mapping row found
Moodle idnumber lookup
Call core_user_get_users_by_field with field=idnumber and value=oec_student_{id}. Finds accounts synced from this OEC instance on a fresh mapping table.
Falls through if: No idnumber match
Email lookup
Call core_user_get_users_by_field with field=email. Matches pre-existing accounts in Moodle that were created before OEC was connected.
Falls through if: No email match
Create new account
No existing account found. Call core_user_create_users. Moodle generates and emails a password (createpassword=1). Mapping row created.
Deactivation: Suspend, Never Delete
When a student graduates, withdraws, or is set to inactive in OEC, the next sync pushes suspended=1 to Moodle. The account is suspended (the student cannot log in) but the account and all associated data (grades, submissions, forum posts, quiz attempts) is preserved.
The integration never calls a delete API on Moodle. Deleting a Moodle user destroys all their grade history, an irreversible compliance risk. Suspended accounts retain full audit history.
Student graduates in OEC
→ Moodle account suspended
active=False triggers write() hook → queue_job → core_user_update_users with suspended=1
GDPR erasure request
→ Suspend + clear mappings
action_gdpr_erase_student() suspends in Moodle, removes OEC mapping rows. No delete API called. Moodle retains anonymized records.
Faculty accounts follow the same pattern
op.faculty records sync via the same SyncUsers service with idnumber pattern oec_faculty_{id}. After creating/updating the Moodle user, the service enrolls the faculty member as teacher in all Moodle courses for their faculty_subject_ids using enrol_manual_enrol_users with the configured teacher_role_id.
Want one login for both systems?
Student roster sync handles account provisioning, it does not unify passwords. For single sign-on (one set of credentials for both OEC and Moodle), see the SSO page which covers SAML 2.0, shared LDAP/Active Directory, and session sharing options.
Student Roster Sync, Frequently Asked Questions
How OEC drives Moodle account provisioning.
Ready to Transform Your Student Roster Sync?
See how OpenEduCat frees up time so every student gets the attention they deserve.
Try it free for 15 days. No credit card required.