Per-module credit-registration configuration: the rollout switch and the module’s own fields
merged with its course_module_suotar_configurations row. Every field of that row is optional
here because a module with no configuration row is a valid, unconfigured module.
The module editor’s writable half of the Suotar configuration. The pause and the
config-validation verdict are not here: their writers are the admin dashboard and the pipeline.
How many chapters and exercises a course module contains. Used for deciding whether the module
is small enough to be exempt from the minimum cheater threshold.
The gate for admin actions that are not tied to one course (e.g. resolving or manually
linking a student number), where get_credit_registration_enabled_ids_for_course has no
course to check against.
Shared by every getter below, so the 13-column join lives in one place. enabled_only isn’t a
“this id or any” filter like the other two: the by-id and by-course lookups want every module,
opted in or not, while the all-modules listing wants only the opted-in ones.
Every course the user is enrolled on that has at least one module opted in to credit
registration, so the profile page can list a course the student was never asked about.
Writes the module’s Suotar configuration row and reconciles its realisations. An unknown grade
scale is refused here because otherwise it surfaces as no_grade_scale_mapping on every
completion of the module, long after the teacher left the editor.
Both paths would put the same attainment in Sisu. course_modules_one_credit_registration_path
enforces this too; here it becomes an error the module editor can render.