Seed Contract - LMS QA Data¶
Date: January 25, 2026
Status: Implementation Complete
Script: scola-fe-v2/scripts/qa/seed/seed_lms.py
1. Purpose¶
This document defines the guaranteed data state after running the QA seed script. Playwright tests depend on this contract to execute reliably without flakiness.
Seed Script Location¶
/home/scola/odoo/scola-fe-v2/scripts/qa/seed/seed_lms.py
Execution Command¶
cd /home/scola/odoo
odoo-bin shell -d scola_test --no-http < scola-fe-v2/scripts/qa/seed/seed_lms.py
Or via Makefile:
cd /home/scola/odoo/scola-fe-v2
make qa-seed
2. Environment Variables¶
| Variable | Default | Purpose |
|---|---|---|
E2E_SEED_PREFIX |
QA |
Prefix for all seeded data |
E2E_ADMIN_USER |
admin |
Admin username |
E2E_ADMIN_PASS |
admin |
Admin password |
E2E_TEACHER_USER |
teacher1 |
Primary teacher login |
E2E_TEACHER_PASS |
teacher123 |
Teacher password |
E2E_TEACHER2_USER |
teacher2 |
Secondary teacher login |
E2E_STUDENT_USER |
student1 |
Primary student login |
E2E_STUDENT_PASS |
student123 |
Student password |
E2E_STUDENT2_USER |
student2 |
Secondary student login |
E2E_PARENT_USER |
parent1 |
Primary parent login |
E2E_PARENT_PASS |
parent123 |
Parent password |
E2E_PARENT2_USER |
parent2 |
Secondary parent login |
E2E_PARENT1_NIK |
3201000000000001 |
Parent 1 NIK |
E2E_PARENT2_NIK |
3201000000000002 |
Parent 2 NIK |
Optional GitHub Actions Provisioning¶
Gate default npm run test:e2e:smoke:starter dijalankan manual di server saat perubahan menyentuh auth, routing, atau flow utama. Untuk menjalankan fallback manual di GitHub Actions (workflow_dispatch dengan input run_e2e_smoke=true), sediakan secrets dengan nama yang sama seperti variabel login berikut:
E2E_ADMIN_USER,E2E_ADMIN_PASSE2E_ADMIN_STAFF_USER,E2E_ADMIN_STAFF_PASSE2E_TEACHER_USER,E2E_TEACHER_PASSE2E_STUDENT_USER,E2E_STUDENT_PASSE2E_PARENT_USER,E2E_PARENT_PASS
Wajib:
- Repository variable
E2E_ODOO_URLuntuk target backend dev/staging
Opsional:
- Repository variable
E2E_DB_NAMEuntuk seed script atau utilitas backend lokal; smoke gate Starter tidak lagi memakai fallback auth legacy yang membutuhkan DB name
3. Seeded Users¶
3.1 Admin User¶
Login: admin
Password: admin
Groups: base.group_system
Purpose: Full system access for integration tests
3.2 Teacher 1 (Primary)¶
Login: teacher1
Password: teacher123
Groups:
- scola_core.group_scola_teacher
- openeducat_core.group_op_faculty
Faculty Record: Yes
Assigned Courses: 1 (QA Course - QA Class A)
Purpose: Primary teacher for grade publish and gradebook tests
3.3 Teacher 2 (Secondary)¶
Login: teacher2
Password: teacher123
Groups: Same as Teacher 1
Faculty Record: Yes
Assigned Courses: 0 (not assigned to any course)
Purpose: Test RBAC isolation (teacher cannot access other's courses)
3.4 Student 1 (Primary)¶
Login: student1
Password: student123
Groups: scola_core.group_scola_student
NISN: 1000000001
NIS: student1
GR No: S-001
Enrolled Courses: 1 (QA Class A)
Submissions: 2 versions
- v1: Score 80 (inactive/superseded)
- v2: Score 85 (active)
Purpose: Primary student for submission and grade tests
3.5 Student 2 (Secondary)¶
Login: student2
Password: student123
Groups: Same as Student 1
NISN: 1000000002
NIS: student2
GR No: S-002
Enrolled Courses: 1 (QA Class A)
Submissions: 1 version
- v1: Ungraded (active)
Purpose: Test RBAC isolation and ungraded submission scenarios
3.6 Parent 1 (Primary)¶
Login: parent1
Password: parent123
Groups: scola_parent.group_scola_parent
NIK: 3201000000000001
Children: Student 1
Purpose: Test parent read-only access
3.7 Parent 2 (Secondary)¶
Login: parent2
Password: parent123
Groups: Same as Parent 1
NIK: 3201000000000002
Children: Student 2
Purpose: Test parent RBAC isolation
4. Seeded Academic Structure¶
4.1 Academic Year¶
Name: QA Academic Year
Start Date: Today
End Date: Today + 365 days
Term Structure: Two semesters
4.2 Term¶
Name: QA Term 1
Academic Year: QA Academic Year
Start Date: Today
End Date: Today + 180 days
4.3 Subject¶
Name: QA Subject
Code: QA_SUBJECT
Type: Theory
Subject Type: Compulsory
4.4 Course¶
Name: QA Course
Code: QA_COURSE
Evaluation Type: Normal
Subjects: QA Subject
4.5 Batch (Class)¶
Name: QA Class A
Code: QA_BATCH
Course: QA Course
Academic Year: QA Academic Year
Education Level: SMP
Rombel Type: Reguler
Faculty (Class Teacher): Teacher 1
Students: Student 1, Student 2
4.6 Teaching Assignment (Academic Section)¶
Faculty: Teacher 1
Batch: QA Class A
Subject: QA Subject
Term: QA Term 1
Active: Yes
Purpose: SSOT for course space - all LMS content links to this
5. Seeded LMS Content¶
5.1 Assignment (OpEducat)¶
Name: QA LMS Assignment
Assignment Type: QA_ASSIGNMENT (sub type)
Course: QA Course
Batch: QA Class A
Subject: QA Subject
Faculty: Teacher 1
Reviewer: Teacher 1
Issued Date: Now
Submission Date: Now + 1 day (tomorrow)
Max Marks: 100
State: Published
Allocated Students: Student 1, Student 2
Grade Component Type: TUGAS
5.2 LMS Course Item (Assignment Wrapper)¶
Name: QA Assignment Item
Teaching Assignment: Teacher 1 → QA Class A
Item Type: assignment
Visibility: published
Assignment Reference: QA LMS Assignment
Published At: Now
Lock At: Now + 1 day (matches submission deadline)
Purpose: LMS wrapper for assignment, links to op.assignment
5.3 LMS Course Item (Material)¶
Name: QA LMS Material
Teaching Assignment: Teacher 1 → QA Class A
Item Type: material
Material Type: text
Content: <p>QA material seeded for LMS QA.</p>
Visibility: published
Published At: Now
Purpose: Published learning material visible to students
5.4 LMS Submissions¶
Student 1 Submissions¶
Version 1 (Superseded):
- Student: Student 1
- Assignment Item: QA Assignment Item
- Version: 1
- Description: "QA seeded submission v1."
- Score: 80
- Grade State: graded
- Is Active: False (superseded by v2)
Version 2 (Active):
- Student: Student 1
- Assignment Item: QA Assignment Item
- Version: 2
- Description: "QA seeded submission v2."
- Score: 85
- Grade State: graded
- Is Active: True
Purpose: Test submission versioning and only active submission is gradeable
Student 2 Submissions¶
Version 1 (Ungraded):
- Student: Student 2
- Assignment Item: QA Assignment Item
- Version: 1
- Description: "QA seeded submission v1."
- Score: null
- Grade State: draft
- Is Active: True
Purpose: Test grading workflow (teacher grades this submission)
6. Data Guarantees (Contract)¶
6.1 User Guarantees¶
✅ All 7 users exist (admin, 2 teachers, 2 students, 2 parents)
✅ Passwords are set to default values
✅ Groups are assigned correctly
✅ Faculty/Student/Parent records linked to users
✅ Enrollments are active (students in QA Class A)
6.2 Course Guarantees¶
✅ 1 Teaching Assignment (Teacher 1 → QA Class A)
✅ 1 Published Material (visible to all students)
✅ 1 Published Assignment (due tomorrow)
✅ Assignment is allocated to both students
✅ Lock date is set (tomorrow)
6.3 Submission Guarantees¶
✅ Student 1 has 2 versions (v1 inactive, v2 active)
✅ Student 2 has 1 version (ungraded)
✅ Only active submissions are gradeable
✅ Versioning is enforced (no duplicate versions)
6.4 RBAC Guarantees¶
✅ Teacher 1 assigned to QA Class A
✅ Teacher 2 NOT assigned to any course (isolation test)
✅ Student 1 enrolled in QA Class A
✅ Student 2 enrolled in QA Class A
✅ Parent 1 linked to Student 1
✅ Parent 2 linked to Student 2
7. Playwright Test Dependencies¶
7.1 Smoke Tests (lms_smoke.spec.ts)¶
Depends On: - Admin, Teacher 1, Student 1, Parent 1 users exist - QA Course exists - 1 published material - 1 published assignment - Gradebook accessible to Teacher 1
Validates: - Login works for all roles - Course list shows correct courses per role - Assignments list includes published assignment - Gradebook loads without errors
7.2 Critical Tests (grade_publish_flow.spec.ts)¶
Depends On: - Teacher 1 assigned to QA Class A - Student 2 has ungraded submission (v1) - Assignment is published
Validates: - Teacher can grade student submission - Grade publish creates notification - Gradebook updates after publish - Student sees published grade
7.3 Critical Tests (grade_publish_idempotency.spec.ts)¶
Depends On: - Teacher 1 can publish grades - API endpoints accept idempotency keys
Validates: - Same key + same payload = 200 (idempotent) - Same key + different payload = 409 (conflict) - Overwrite without reason = 409 (rejected) - Overwrite with reason = 200 (success + audit)
7.4 RBAC Tests (rbac_no_leak.spec.ts)¶
Depends On: - Teacher 2 exists but not assigned to QA Class A - Student 1 and Student 2 both enrolled - Parent 1 linked to Student 1 only
Validates: - Student 1 cannot read Student 2 submissions (0 records) - Teacher 2 cannot access QA Class A (403) - Parent 1 cannot see Student 2 grades (403 or 0 records) - Student cannot create content (403) - Student cannot access gradebook (403)
8. Idempotency¶
The seed script is idempotent - running it multiple times will: - ✅ Update existing users (passwords, groups) - ✅ Reuse existing academic records - ✅ Not create duplicate course items - ✅ Not create duplicate submissions
Safe to run: make qa-seed repeatedly without cleanup
9. Cleanup¶
9.1 Full Reset (Recommended Before Tests)¶
cd /home/scola/odoo/scola-fe-v2
make qa-reset
This will:
1. Drop and recreate scola_test database
2. Initialize Odoo
3. Install required modules
4. Run seed script
Duration: ~2-3 minutes
9.2 Seed Only (No DB Reset)¶
cd /home/scola/odoo/scola-fe-v2
make qa-seed
Duration: ~10 seconds
Use Case: After manual data deletion or incremental updates
10. Verification¶
10.1 Manual Verification¶
Check Users:
odoo-bin shell -d scola_test --no-http
>>> env['res.users'].search([('login', 'in', ['teacher1', 'student1', 'parent1'])])
# Should return 3 users
Check Teaching Assignment:
>>> ta = env['op.teaching.assignment'].search([('subject_id.code', '=', 'QA_SUBJECT')])
>>> ta.faculty_id.user_id.login
# Should return 'teacher1'
Check Submissions:
>>> subs = env['lms.submission'].search([('student_id.user_id.login', '=', 'student1')])
>>> len(subs)
# Should return 2 (v1 and v2)
>>> subs.filtered(lambda s: s.is_active).version
# Should return 2
10.2 Automated Verification (Future)¶
Health Check Endpoint:
curl http://localhost:8069/api/testkit/seed_health
# Returns:
# {
# "status": "healthy",
# "users": 7,
# "courses": 1,
# "submissions": 3,
# "seed_prefix": "QA"
# }
(Not yet implemented - planned for Phase 2)
11. Troubleshooting¶
11.1 Common Issues¶
Issue: "Missing model: lms.course.item"
# Solution: Install scola_lms module
odoo-bin -d scola_test -i scola_lms --stop-after-init
Issue: "Gradebook cache clear unavailable"
# Solution: Ensure op.teaching.assignment has _get_gradebook_cached method
# Check scola_lms/models/op_teaching_assignment.py
Issue: "Student already enrolled"
# Solution: Seed is idempotent - this is not an error
# Existing enrollment will be reused
11.2 Debugging¶
Enable Seed Debug Logs:
# Seed script uses print() - redirect to file
odoo-bin shell -d scola_test --no-http < seed_lms.py > seed_output.log 2>&1
Check Created IDs:
# Seed prints summary at the end:
# - teaching_assignment_id=123
# - assignment_id=456
# - lms_assignment_item_id=789
12. Future Enhancements¶
12.1 Planned (Phase 2)¶
- [ ] Seed 50+ students for performance tests
- [ ] Seed multiple courses for cross-course isolation tests
- [ ] Seed grade events (audit trail) for history tests
- [ ] Seed notifications for notification tests
- [ ] Seed calendar events for due date reminder tests
12.2 Wish List¶
- [ ] Parameterized seed (e.g.,
--students=100) - [ ] Seed cleanup command (
make qa-seed-clean) - [ ] Seed health check API
- [ ] Seed data export (JSON snapshot)
13. Maintenance¶
Owner: QA Team
Review Frequency: Every sprint
Update Trigger: When Playwright tests require new data scenarios
Change Process:
1. Update seed_lms.py
2. Update this document (Seed Contract)
3. Run make qa-reset to verify
4. Update Playwright tests if needed
5. Commit all changes together
Document Status: ✅ Complete
Last Updated: January 25, 2026
Next Review: February 25, 2026