metatroncubeswdev 709bd2eca7 O1: complete the gate - program, subject, room, batch, people, enrollment
Rounds out mc_education_base with the remaining O1 models: mc.program,
mc.subject, mc.room, mc.batch, mc.teacher, mc.student, mc.guardian,
mc.student.guardian, and mc.enrollment - the spine everything else in
the O1 table (attendance, timetable, exam, portal) is built against.

Two rules get the same "DB constraint is the real guarantee, the ORM
does a friendly pre-check" treatment as academic.year.is_current:

  - At most one primary guardian per student (mc.student.guardian):
    partial unique index on student_id WHERE is_primary, plus a
    create/write toggle.
  - At most one Active enrollment per student per year
    (mc.enrollment): partial unique index on (student_id, year_id)
    WHERE state='active'. This one is CLAUDE.md's flagship rule
    ("Enforce as a database constraint, not application logic").

Two more real bugs surfaced by testing against a live odoo:19.0
container rather than trusting the code by inspection:

  - The partial unique index fires at INSERT/UPDATE time, before
    @api.constrains ever runs - so a naive "index + constrains for a
    friendly message" design never reaches the friendly message, the
    raw IntegrityError wins the race. Fixed by pre-checking for a
    conflict in create()/write() before calling super(), with
    @api.constrains kept only as a backstop for batch creates.
  - create() issues a direct SQL INSERT that does not wait for
    unrelated pending writes in the ORM cache (e.g. withdrawing one
    enrollment right before creating its replacement, in the same
    method) - needs an explicit self.env.flush_all() first, same
    lesson as the is_current toggle.

Also caught before it became a permanent test flake: the enrollment
and academic-calendar tests originally hardcoded the same year names
("2025-26", "2026-27") and program code ("G8") as the demo data.
Passed in isolation, failed as soon as demo data was loaded first -
so verification here included a combined
`--without-demo=False --test-enable` run, matching what CI actually
does, not just an isolated test-tagged run. Renamed to TEST-prefixed
fixtures.

Security access rows added for all new models across the four
internal groups (Administrator: full CRUD everywhere; Staff: full
CRUD on the people/enrollment models that are front office's daily
job, read-only on academic structure; Teacher/Accountant: read-only
across the board, narrower record rules land with the modules that
need them - attendance, exam, portal). No portal-group access yet;
that is O7's job once explicit ownership-scoped record rules exist -
granting it now without those rules would be exactly the "identifier
supplied by the client" hole CLAUDE.md's standing security rule
warns about.

Demo data populates the shared/DEMO_SCRIPT.md cast: Meera Krishnan as
primary guardian of both Aditya (Grade 8-A) and Ananya (Grade 5-B) -
the multi-child guardian view the script calls "the single most
convincing portal feature" - plus Arun Prakash as Grade 8-A's class
teacher. Verified by querying the resulting database directly, not
just by the install succeeding.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-11 09:58:36 -04:00

3.9 KiB

1idnamemodel_id:idgroup_id:idperm_readperm_writeperm_createperm_unlink
2access_mc_academic_year_administratormc.academic.year.administratormodel_mc_academic_yeargroup_school_administrator1111
3access_mc_academic_year_staffmc.academic.year.staffmodel_mc_academic_yeargroup_school_staff1000
4access_mc_academic_term_administratormc.academic.term.administratormodel_mc_academic_termgroup_school_administrator1111
5access_mc_academic_term_staffmc.academic.term.staffmodel_mc_academic_termgroup_school_staff1000
6access_mc_room_administratormc.room.administratormodel_mc_roomgroup_school_administrator1111
7access_mc_room_staffmc.room.staffmodel_mc_roomgroup_school_staff1000
8access_mc_room_teachermc.room.teachermodel_mc_roomgroup_teacher1000
9access_mc_room_accountantmc.room.accountantmodel_mc_roomgroup_accountant1000
10access_mc_program_administratormc.program.administratormodel_mc_programgroup_school_administrator1111
11access_mc_program_staffmc.program.staffmodel_mc_programgroup_school_staff1000
12access_mc_program_teachermc.program.teachermodel_mc_programgroup_teacher1000
13access_mc_program_accountantmc.program.accountantmodel_mc_programgroup_accountant1000
14access_mc_subject_administratormc.subject.administratormodel_mc_subjectgroup_school_administrator1111
15access_mc_subject_staffmc.subject.staffmodel_mc_subjectgroup_school_staff1000
16access_mc_subject_teachermc.subject.teachermodel_mc_subjectgroup_teacher1000
17access_mc_subject_accountantmc.subject.accountantmodel_mc_subjectgroup_accountant1000
18access_mc_teacher_administratormc.teacher.administratormodel_mc_teachergroup_school_administrator1111
19access_mc_teacher_staffmc.teacher.staffmodel_mc_teachergroup_school_staff1000
20access_mc_teacher_teachermc.teacher.teachermodel_mc_teachergroup_teacher1000
21access_mc_teacher_accountantmc.teacher.accountantmodel_mc_teachergroup_accountant1000
22access_mc_batch_administratormc.batch.administratormodel_mc_batchgroup_school_administrator1111
23access_mc_batch_staffmc.batch.staffmodel_mc_batchgroup_school_staff1110
24access_mc_batch_teachermc.batch.teachermodel_mc_batchgroup_teacher1000
25access_mc_batch_accountantmc.batch.accountantmodel_mc_batchgroup_accountant1000
26access_mc_student_administratormc.student.administratormodel_mc_studentgroup_school_administrator1111
27access_mc_student_staffmc.student.staffmodel_mc_studentgroup_school_staff1110
28access_mc_student_teachermc.student.teachermodel_mc_studentgroup_teacher1000
29access_mc_student_accountantmc.student.accountantmodel_mc_studentgroup_accountant1000
30access_mc_guardian_administratormc.guardian.administratormodel_mc_guardiangroup_school_administrator1111
31access_mc_guardian_staffmc.guardian.staffmodel_mc_guardiangroup_school_staff1110
32access_mc_guardian_teachermc.guardian.teachermodel_mc_guardiangroup_teacher1000
33access_mc_guardian_accountantmc.guardian.accountantmodel_mc_guardiangroup_accountant1000
34access_mc_student_guardian_administratormc.student.guardian.administratormodel_mc_student_guardiangroup_school_administrator1111
35access_mc_student_guardian_staffmc.student.guardian.staffmodel_mc_student_guardiangroup_school_staff1110
36access_mc_student_guardian_teachermc.student.guardian.teachermodel_mc_student_guardiangroup_teacher1000
37access_mc_student_guardian_accountantmc.student.guardian.accountantmodel_mc_student_guardiangroup_accountant1000
38access_mc_enrollment_administratormc.enrollment.administratormodel_mc_enrollmentgroup_school_administrator1111
39access_mc_enrollment_staffmc.enrollment.staffmodel_mc_enrollmentgroup_school_staff1110
40access_mc_enrollment_teachermc.enrollment.teachermodel_mc_enrollmentgroup_teacher1000
41access_mc_enrollment_accountantmc.enrollment.accountantmodel_mc_enrollmentgroup_accountant1000