Moodle Quiz & Exam Import
Quiz results and assignment grades from Moodle flow into OEC's exam management module automatically. The integration pulls the best quiz attempt per student, not every attempt, and writes it to the correct OEC exam record. Assignment submission grades come through a separate pull that fetches the final graded score.
Both quiz and assignment pulls run as part of the same grade pull cron (every 15 minutes by default) as the gradebook sync. SHA-256 hashing on the grade value means already-imported scores are skipped until something changes.
What Gets Imported
Two Moodle activity types (quizzes and assignments) each with their own WS function and OEC mapping.
Moodle Quiz best-grade
Discovery WS function
mod_quiz_get_quizzes_by_coursesGrade pull WS function
mod_quiz_get_user_best_gradeOEC target
op.exam.attendees (community) / gradebook.line (enterprise)ID handling
+1,000,000 on quiz ID
Best attempt only. All other attempts discarded. ID offset prevents hash collision with gradebook grade items.
Moodle Assignment submission grade
Discovery WS function
mod_assign_get_assignmentsGrade pull WS function
mod_assign_get_gradesOEC target
op.exam.attendees (community) / gradebook.line (enterprise)ID handling
None (uses assignment ID directly)
Full pull with since=0 (no incremental filter). Null/empty grades are skipped, absence does not write a 0.
Why the +1,000,000 ID Offset for Quizzes
Moodle uses an integer ID space for both regular grade items (grade_items) and quiz activities (quiz.id). These IDs are independent in Moodle but both land in the same OEC grade hash mapping table.
A quiz with Moodle ID 42 could collide with a grade item with ID 42 in the hash map, causing the grade sync to incorrectly skip one of them (thinking it already processed that ID). The +1,000,000 offset moves all quiz IDs out of the range of normal grade item IDs, making the hash map entries unique. A quiz with Moodle ID 42 is stored in the hash map as ID 1,000,042.
# In sync_grades.py
QUIZ_ID_OFFSET = 1_000_000
# Grade item ID 42 in hash map: key = "grade_42"
# Quiz ID 42 in hash map: key = "grade_1000042"
# No collision.Where Grades Land in OEC
The storage path depends on which OEC edition is installed. Enterprise takes priority if both modules are present.
Community Edition
openeducat_exam- 1
op.exam.session (one per Moodle course) - 2
op.exam (one per quiz/assignment) - 3
op.exam.attendees (one per student) - 4
op.result.line (grade value)
Exam state advanced via sudo().act_held(), required because state is readonly on the model.
Enterprise Edition
openeducat_grading- 1
grading.assignment (one per quiz/assignment) - 2
gradebook.gradebook (one per subject) - 3
gradebook.line (grade per student)
calculate_percentage() and student_Grade_override() called once per batch, not per grade item.
What the Import Does Not Cover
The integration is intentionally scoped to grade results. These items are out of scope:
Per-attempt quiz history
Only the best grade (mod_quiz_get_user_best_grade) is imported. Individual attempt data stays in Moodle's quiz reports.
Question bank sync
Moodle question banks are not imported into OEC. OEC's exam module has its own question management. These are maintained separately.
Attempt metadata (IP, time taken, attempt count)
The mod_quiz_get_user_best_grade function does not return attempt metadata. This is available in Moodle's quiz activity reports only.
Assignment submission files
Only the graded score is imported, not the submission file itself. Files remain in Moodle's file system.
Quiz Import, Frequently Asked Questions
How Moodle quiz and assignment grades are imported into OEC.
Ready to Transform Your Quiz Import?
See how OpenEduCat frees up time so every student gets the attention they deserve.
Try it free for 15 days. No credit card required.