Files
full_encoach_platform/new_project/seed_demo_data.py
Yamen Ahmad 3e83d8d7d5 feat: add complete EnCoach backend — Odoo 19 + all addons
Includes:
- Odoo 19 framework (odoo/)
- 27 custom EnCoach addons (new_project/custom_addons/)
  - encoach_core, encoach_api, encoach_lms_api, encoach_adaptive_api
  - encoach_exam, encoach_taxonomy, encoach_adaptive, encoach_assignment
  - encoach_ai, encoach_ai_grading, encoach_ai_generation, encoach_ai_media
  - encoach_courseware, encoach_communication, encoach_subscription
  - encoach_notification, encoach_approval, encoach_branding
  - encoach_classroom, encoach_registration, encoach_stats
  - encoach_faq, encoach_ticket, encoach_training, encoach_resources
  - encoach_adaptive_ai, encoach_sis
- 21 OpenEduCat Enterprise modules (new_project/enterprise-19/)
- 14 OpenEduCat Community modules (new_project/openeducat_erp-19.0/)
- Configuration: odoo.conf, requirements.txt, scripts
- 200+ REST API endpoints with JWT authentication
- SRS and test documentation

Made-with: Cursor
2026-04-01 17:10:04 +04:00

1417 lines
85 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""
EnCoach LMS FULL Demo Data Seeder
=====================================
Covers every module end-to-end across 3 subjects (English, Math, IT):
Academic departments, years, terms, courses, batches, subjects,
classrooms, timings, timetable, admissions
LMS / Courseware chapters, materials, student progress
Exams structures, rubrics, exams, sessions, evaluations, stats
Assignments grading types, assignments (OP + EnCoach), extensions
Adaptive diagnostics, proficiency, learning plans/items, content cache
Institutional entities, invite codes, roles, user-role links, branding
Management roles, permissions, user permissions
Communication announcements, discussion boards/posts, direct messages
Approvals workflows, stages, requests
Notifications rules, preferences, notifications
Resources learning resources
Subscription packages, discounts, payments
Registration registration batches
Training tips, walkthroughs
Support tickets, FAQ
Reports/Stats exam session stats
Classroom Groups
Run: python new_project/seed_demo_data.py
"""
import psycopg2
import json
from datetime import date, datetime, timedelta
import random
DB = dict(dbname='encoach_v2', user='yamenahmad', host='localhost')
random.seed(42)
# ═══════════════════════════════════════════════════
# Helpers
# ═══════════════════════════════════════════════════
def j(val):
"""Odoo jsonb translatable field."""
return json.dumps({'en_US': val})
def insert(cur, table, vals):
cols = list(vals.keys())
sql = f"INSERT INTO {table} ({', '.join(cols)}) VALUES ({', '.join(['%s']*len(cols))}) RETURNING id"
cur.execute(sql, list(vals.values()))
return cur.fetchone()[0]
def find_or_create(cur, table, match_col, vals):
cur.execute(f"SELECT id FROM {table} WHERE {match_col} = %s", (vals[match_col],))
row = cur.fetchone()
if row:
return row[0]
return insert(cur, table, vals)
def m2m(cur, rel, c1, c2, v1, v2):
cur.execute(f"INSERT INTO {rel} ({c1},{c2}) VALUES (%s,%s) ON CONFLICT DO NOTHING", (v1, v2))
def ensure_partner(cur, name, email, company_id=1):
cur.execute("SELECT id FROM res_partner WHERE email = %s", (email,))
row = cur.fetchone()
if row:
return row[0]
return insert(cur, 'res_partner', {
'name': name, 'email': email, 'active': True,
'company_id': company_id, 'type': 'contact',
'autopost_bills': 'no', 'create_uid': 2, 'write_uid': 2,
})
def ensure_user(cur, name, email, company_id=1):
cur.execute("SELECT id FROM res_users WHERE login = %s", (email,))
row = cur.fetchone()
if row:
return row[0]
pid = ensure_partner(cur, name, email, company_id)
return insert(cur, 'res_users', {
'login': email, 'password': '$pbkdf2-sha512$25000$admin',
'active': True, 'company_id': company_id, 'partner_id': pid,
'notification_type': 'email', 'create_uid': 2, 'write_uid': 2,
})
AU = {'create_uid': 2, 'write_uid': 2}
# ═══════════════════════════════════════════════════
# Static data definitions
# ═══════════════════════════════════════════════════
DEPARTMENTS = [
{'code': 'LANG', 'name': 'Languages & Linguistics'},
{'code': 'MATH', 'name': 'Mathematics & Statistics'},
{'code': 'IT', 'name': 'Information Technology'},
]
ACADEMIC_YEARS = [
{'name': '2025-2026', 'start': date(2025, 9, 1), 'end': date(2026, 6, 30)},
{'name': '2026-2027', 'start': date(2026, 9, 1), 'end': date(2027, 6, 30)},
]
TERMS = {
'2025-2026': [
('Fall 2025', date(2025, 9, 1), date(2025, 12, 20)),
('Spring 2026', date(2026, 1, 15), date(2026, 5, 30)),
('Summer 2026', date(2026, 6, 1), date(2026, 8, 15)),
],
'2026-2027': [
('Fall 2026', date(2026, 9, 1), date(2026, 12, 20)),
('Spring 2027', date(2027, 1, 15), date(2027, 5, 30)),
],
}
OP_SUBJECTS = [
('ENG-101','English Grammar','theory','compulsory','LANG'),
('ENG-102','English Writing','theory','compulsory','LANG'),
('ENG-103','English Reading','theory','compulsory','LANG'),
('ENG-104','English Speaking','practical','compulsory','LANG'),
('ENG-105','IELTS Listening','practical','elective','LANG'),
('MTH-101','Calculus I','theory','compulsory','MATH'),
('MTH-102','Linear Algebra','theory','compulsory','MATH'),
('MTH-103','Probability & Stats','theory','compulsory','MATH'),
('MTH-104','Discrete Mathematics','theory','elective','MATH'),
('MTH-105','Numerical Methods','both','elective','MATH'),
('IT-101','Programming Basics','both','compulsory','IT'),
('IT-102','Database Systems','both','compulsory','IT'),
('IT-103','Web Development','practical','compulsory','IT'),
('IT-104','Networking Basics','theory','compulsory','IT'),
('IT-105','Cybersecurity Intro','theory','elective','IT'),
]
COURSES = [
('ENG-IELTS','IELTS & English Mastery','LANG','Comprehensive IELTS preparation: Reading, Writing, Listening, Speaking.',['ENG-101','ENG-102','ENG-103','ENG-104','ENG-105']),
('MATH-FND','Mathematics Foundations','MATH','Core mathematics from calculus through statistics.',['MTH-101','MTH-102','MTH-103','MTH-104','MTH-105']),
('IT-CORE','IT & Computer Science Core','IT','Essential IT: programming, databases, web dev, security.',['IT-101','IT-102','IT-103','IT-104','IT-105']),
]
BATCHES = [
('ENG-F26A','English Fall 2026 Morning','ENG-IELTS',date(2026,9,1),date(2026,12,20),30),
('ENG-F26B','English Fall 2026 Evening','ENG-IELTS',date(2026,9,1),date(2026,12,20),25),
('MTH-F26A','Math Fall 2026 Group A','MATH-FND',date(2026,9,1),date(2026,12,20),35),
('MTH-F26B','Math Fall 2026 Group B','MATH-FND',date(2026,9,1),date(2026,12,20),35),
('IT-F26A','IT Fall 2026 Lab A','IT-CORE',date(2026,9,1),date(2026,12,20),28),
('IT-F26B','IT Fall 2026 Lab B','IT-CORE',date(2026,9,1),date(2026,12,20),28),
]
TEACHERS = [
('Dr. Sarah Mitchell','sarah.mitchell@encoach.com','Sarah','Mitchell','female','LANG','IELTS & Applied Linguistics'),
('Prof. James Carter','james.carter@encoach.com','James','Carter','male','LANG','English Literature'),
('Dr. Elena Popov','elena.popov@encoach.com','Elena','Popov','female','MATH','Calculus & Analysis'),
('Prof. Ahmed Hassan','ahmed.hassan@encoach.com','Ahmed','Hassan','male','MATH','Statistics & Probability'),
('Dr. Lisa Wang','lisa.wang@encoach.com','Lisa','Wang','female','IT','Software Engineering'),
('Prof. David Kim','david.kim@encoach.com','David','Kim','male','IT','Databases & Cybersecurity'),
]
STUDENTS = [
('Emma Johnson','emma.johnson@student.encoach.com','Emma','Johnson','f',date(2004,3,15)),
('Liam Brown','liam.brown@student.encoach.com','Liam','Brown','m',date(2003,7,22)),
('Sophia Davis','sophia.davis@student.encoach.com','Sophia','Davis','f',date(2004,1,8)),
('Noah Wilson','noah.wilson@student.encoach.com','Noah','Wilson','m',date(2003,11,30)),
('Olivia Martinez','olivia.martinez@student.encoach.com','Olivia','Martinez','f',date(2004,5,19)),
('Ethan Anderson','ethan.anderson@student.encoach.com','Ethan','Anderson','m',date(2003,9,12)),
('Ava Thomas','ava.thomas@student.encoach.com','Ava','Thomas','f',date(2004,8,3)),
('Mason Jackson','mason.jackson@student.encoach.com','Mason','Jackson','m',date(2003,4,25)),
('Isabella White','isabella.white@student.encoach.com','Isabella','White','f',date(2004,12,7)),
('Lucas Harris','lucas.harris@student.encoach.com','Lucas','Harris','m',date(2003,6,18)),
('Mia Clark','mia.clark@student.encoach.com','Mia','Clark','f',date(2004,2,28)),
('Alexander Lewis','alex.lewis@student.encoach.com','Alexander','Lewis','m',date(2003,10,14)),
('Charlotte Lee','charlotte.lee@student.encoach.com','Charlotte','Lee','f',date(2004,7,9)),
('William Young','william.young@student.encoach.com','William','Young','m',date(2003,1,21)),
('Amelia Walker','amelia.walker@student.encoach.com','Amelia','Walker','f',date(2004,11,5)),
('James Hall','james.hall@student.encoach.com','James','Hall','m',date(2003,8,27)),
('Harper Allen','harper.allen@student.encoach.com','Harper','Allen','f',date(2004,4,16)),
('Benjamin King','benjamin.king@student.encoach.com','Benjamin','King','m',date(2003,12,2)),
('Evelyn Wright','evelyn.wright@student.encoach.com','Evelyn','Wright','f',date(2004,6,24)),
('Daniel Scott','daniel.scott@student.encoach.com','Daniel','Scott','m',date(2003,3,11)),
]
CLASSROOMS = [
('LNG101','Lang Lab 1',30),('LNG102','Lang Lab 2',25),
('MTH201','Math Hall A',40),('MTH202','Math Room B',20),
('IT301','Comp Lab A',30),('IT302','Comp Lab B',28),
('GEN101','Auditorium',100),('GEN102','Meeting Rm 1',15),
]
TIMINGS = [
('08:00 AM',8,0,1.5,'am',1),('09:30 AM',9,30,1.5,'am',2),
('11:00 AM',11,0,1.5,'am',3),('01:00 PM',1,0,1.5,'pm',4),
('02:30 PM',2,30,1.5,'pm',5),('04:00 PM',4,0,1.5,'pm',6),
]
DOMAINS_TOPICS = {
'english': {
'Reading': [('Skimming & Scanning','intermediate'),('Passage Comprehension','intermediate'),('True/False/Not Given','beginner'),('Matching Headings','advanced'),('Summary Completion','intermediate')],
'Writing': [('Task 1 - Data Description','intermediate'),('Task 1 - Process Diagrams','advanced'),('Task 2 - Opinion Essays','intermediate'),('Task 2 - Discussion Essays','advanced'),('Coherence & Cohesion','beginner')],
'Listening': [('Section 1 - Social Contexts','beginner'),('Section 2 - Monologues','intermediate'),('Section 3 - Academic Discussion','advanced'),('Section 4 - Academic Lecture','advanced'),('Note Completion','intermediate')],
'Speaking': [('Part 1 - Introduction','beginner'),('Part 2 - Long Turn','intermediate'),('Part 3 - Discussion','advanced'),('Pronunciation & Fluency','intermediate'),('Vocabulary Range','intermediate')],
'Grammar': [('Tenses & Aspects','beginner'),('Conditionals','intermediate'),('Relative Clauses','intermediate'),('Passive Voice','beginner'),('Complex Sentences','advanced')],
},
'math': {
'Algebra': [('Linear Equations','beginner'),('Quadratic Equations','intermediate'),('Systems of Equations','intermediate'),('Polynomials','advanced'),('Inequalities','beginner')],
'Calculus': [('Limits & Continuity','intermediate'),('Derivatives','intermediate'),('Integration Techniques','advanced'),('Applications of Integrals','advanced'),('Series & Sequences','advanced')],
'Statistics': [('Descriptive Statistics','beginner'),('Probability Distributions','intermediate'),('Hypothesis Testing','advanced'),('Regression Analysis','advanced'),('Sampling Methods','intermediate')],
'Geometry': [('Euclidean Geometry','beginner'),('Coordinate Geometry','intermediate'),('Trigonometry','intermediate'),('Vectors in 2D/3D','advanced'),('Conic Sections','advanced')],
'Logic': [('Propositional Logic','beginner'),('Set Theory','intermediate'),('Graph Theory','intermediate'),('Combinatorics','advanced'),('Mathematical Proofs','advanced')],
},
'it': {
'Programming': [('Variables & Data Types','beginner'),('Control Structures','beginner'),('Functions & Modules','intermediate'),('OOP Concepts','intermediate'),('Algorithms & Complexity','advanced')],
'Databases': [('SQL Fundamentals','beginner'),('Table Design & Normalization','intermediate'),('Joins & Subqueries','intermediate'),('Indexing & Optimization','advanced'),('NoSQL Concepts','advanced')],
'Web Development': [('HTML & CSS Basics','beginner'),('JavaScript Fundamentals','intermediate'),('React / Frontend Frameworks','advanced'),('REST APIs','intermediate'),('Responsive Design','intermediate')],
'Networking': [('OSI Model','beginner'),('TCP/IP Protocol Suite','intermediate'),('DNS & HTTP','intermediate'),('Firewalls & VPNs','advanced'),('Cloud Networking','advanced')],
'Security': [('Cybersecurity Fundamentals','beginner'),('Encryption & Hashing','intermediate'),('Auth & Authorization','intermediate'),('Vulnerability Assessment','advanced'),('Ethical Hacking Basics','advanced')],
},
}
ENTITIES = [
('MAIN-UNI','EnCoach Academy','university'),
('CORP-TECH','TechCorp Training Center','corporate'),
('FREE-TUTOR','Independent Tutors Hub','freelance'),
]
TICKETS = [
('Cannot access IELTS Writing module','bug','open','When clicking on the Writing module, the page returns a 500 error.'),
('Add dark mode to exam interface','feature','open','Students request dark mode for exam-taking.'),
('Math formula rendering broken on mobile','bug','in_progress','LaTeX formulas do not render on mobile browsers.'),
('Request: Export grades to CSV','feature','open','Teachers want CSV export for gradebook data.'),
('IT lab booking conflicts','bug','resolved','Double-booking on Computer Lab A Tuesdays.'),
('Improve attendance tracking UX','feature','in_progress','Batch check-in needed for large classes.'),
('Student portal login timeout too short','bug','open','Session expires after only 5 minutes.'),
('Add video conferencing for Speaking tests','feature','open','Integration with Zoom/Meet for remote sessions.'),
('Broken link in Chapter 3 materials','bug','open','PDF link 404 in English Writing Chapter 3.'),
('Request: Parent portal access','feature','open','Parents want read-only access to student progress.'),
]
FAQ_DATA = [
('Getting Started', [
('How do I enroll in a course?', 'Navigate to Courses, select your desired course, click "Enroll". Your advisor approves within 24 hours.'),
('What are system requirements?', 'Modern browser (Chrome, Firefox, Safari, Edge) with JS enabled. For IT labs, laptop with 8GB+ RAM.'),
('How do I reset my password?', 'Click "Forgot Password" on login, enter your email. Reset link arrives in minutes.'),
]),
('Exams & Assessments', [
('How are IELTS mock exams scored?', 'Official 9-band scoring. AI grading gives immediate feedback; teacher review within 48h.'),
('Can I retake a failed exam?', 'Yes, up to 3 retakes per semester, at least 1 week apart.'),
('What if internet drops during timed exam?', 'Auto-saves every 30s. Resume within 15 minutes of disconnection.'),
]),
('Technical Support', [
('Platform loading slowly', 'Clear cache, disable extensions, or switch to Chrome. Report browser version if issue persists.'),
('Cannot upload assignment', 'Supported: PDF, DOCX, TXT, ZIP (max 50MB). For code, use ZIP.'),
]),
('Billing & Payments', [
('What payment methods are accepted?', 'Visa, MasterCard, PayPal, bank transfers. Installment plans available.'),
('How do I get a refund?', 'Submit within 14 days of enrollment. Contact billing@encoach.com with enrollment ID.'),
]),
]
# ═══════════════════════════════════════════════════
# Main seed function
# ═══════════════════════════════════════════════════
def seed():
conn = psycopg2.connect(**DB)
conn.autocommit = False
cur = conn.cursor()
step = [0]
total_steps = 30
def log(msg):
step[0] += 1
print(f"[{step[0]:2d}/{total_steps}] {msg}")
print("=" * 65)
print(" EnCoach LMS Full Demo Data Seeder")
print("=" * 65)
try:
# ══════════════════════════════════════════
# SECTION A ACADEMIC FOUNDATION
# ══════════════════════════════════════════
# 1. Departments
log("Departments...")
dept_ids = {}
for d in DEPARTMENTS:
dept_ids[d['code']] = find_or_create(cur, 'op_department', 'code', {'code': d['code'], 'name': d['name'], **AU})
print(f" {len(dept_ids)} departments")
# 2. Academic years & terms
log("Academic years & terms...")
ay_ids = {}
for ay in ACADEMIC_YEARS:
ay_ids[ay['name']] = find_or_create(cur, 'op_academic_year', 'name', {
'name': ay['name'], 'start_date': ay['start'], 'end_date': ay['end'],
'term_structure': 'semester', 'company_id': 1, **AU,
})
term_ids = {}
for ay_name, terms in TERMS.items():
for n, s, e in terms:
term_ids[n] = find_or_create(cur, 'op_academic_term', 'name', {
'name': n, 'term_start_date': s, 'term_end_date': e,
'academic_year_id': ay_ids[ay_name], 'company_id': 1, **AU,
})
print(f" {len(ay_ids)} years, {len(term_ids)} terms")
# 3. Op Subjects
log("Academic subjects...")
dept_map = {'ENG': 'LANG', 'MTH': 'MATH', 'IT': 'IT'}
subj_ids = {}
for code, name, typ, stype, dept in OP_SUBJECTS:
subj_ids[code] = find_or_create(cur, 'op_subject', 'code', {
'code': code, 'name': name, 'type': typ, 'subject_type': stype,
'active': True, 'department_id': dept_ids[dept], **AU,
})
print(f" {len(subj_ids)} subjects")
# 4. Courses + subject links
log("Courses...")
course_ids = {}
for code, name, dept, desc, subs in COURSES:
cid = find_or_create(cur, 'op_course', 'code', {
'code': code, 'name': j(name), 'active': True,
'department_id': dept_ids[dept], 'evaluation_type': 'normal',
'description': desc, 'status': 'active', 'company_id': 1, **AU,
})
course_ids[code] = cid
for sc in subs:
if sc in subj_ids:
m2m(cur, 'op_course_op_subject_rel', 'op_course_id', 'op_subject_id', cid, subj_ids[sc])
print(f" {len(course_ids)} courses")
# 5. Batches
log("Batches...")
batch_ids = {}
batch_course = {}
for code, name, crs, s, e, mx in BATCHES:
batch_ids[code] = find_or_create(cur, 'op_batch', 'code', {
'code': code, 'name': name, 'active': True,
'course_id': course_ids[crs], 'start_date': s, 'end_date': e,
'max_students': mx, 'status': 'active', 'company_id': 1, **AU,
})
batch_course[code] = crs
print(f" {len(batch_ids)} batches")
# 6. Faculty
log("Faculty...")
faculty_ids = {}
faculty_uids = {}
for name, email, first, last, gender, dept, spec in TEACHERS:
uid = ensure_user(cur, name, email)
cur.execute("SELECT partner_id FROM res_users WHERE id=%s", (uid,))
pid = cur.fetchone()[0]
cur.execute("SELECT id FROM op_faculty WHERE partner_id=%s", (pid,))
frow = cur.fetchone()
fid = frow[0] if frow else insert(cur, 'op_faculty', {
'partner_id': pid, 'first_name': j(first), 'last_name': last,
'gender': gender, 'birth_date': date(1985, 6, 15), 'active': True,
'department_id': dept_ids[dept], 'specialization': spec, 'company_id': 1, **AU,
})
faculty_ids[email] = fid
faculty_uids[email] = uid
print(f" {len(faculty_ids)} faculty")
# 7. Students
log("Students...")
student_ids = {}
student_uids = {}
batch_list = list(batch_ids.keys())
for i, (name, email, first, last, gender, dob) in enumerate(STUDENTS):
uid = ensure_user(cur, name, email)
cur.execute("SELECT partner_id FROM res_users WHERE id=%s", (uid,))
pid = cur.fetchone()[0]
cur.execute("SELECT id FROM op_student WHERE partner_id=%s", (pid,))
srow = cur.fetchone()
sid = srow[0] if srow else insert(cur, 'op_student', {
'partner_id': pid, 'user_id': uid, 'first_name': j(first), 'last_name': j(last),
'gender': gender, 'birth_date': dob, 'gr_no': f'STU-2026{i+1:04d}',
'active': True, 'status': 'active', 'enrollment_date': date(2026, 8, 15),
'company_id': 1, **AU,
})
student_ids[email] = sid
student_uids[email] = uid
b = batch_list[i % len(batch_list)]
crs = batch_course[b]
cur.execute("INSERT INTO op_student_course (student_id,course_id,batch_id,roll_number,state,create_uid,write_uid) VALUES(%s,%s,%s,%s,'running',2,2) ON CONFLICT DO NOTHING",
(sid, course_ids[crs], batch_ids[b], f'R-{i+1:04d}'))
print(f" {len(student_ids)} students")
# 8. Classrooms
log("Classrooms...")
cls_ids = {}
for code, name, cap in CLASSROOMS:
cls_ids[code] = find_or_create(cur, 'op_classroom', 'code', {
'code': code, 'name': name, 'capacity': cap, 'active': True, 'company_id': 1, **AU,
})
print(f" {len(cls_ids)} classrooms")
# 9. Timings
log("Timings...")
timing_ids = {}
for name, h, m, dur, ampm, seq in TIMINGS:
timing_ids[name] = find_or_create(cur, 'op_timing', 'name', {
'name': name, 'hour': h, 'minute': m, 'duration': dur, 'am_pm': ampm, 'sequence': seq, **AU,
})
print(f" {len(timing_ids)} timings")
# 10. Timetable sessions
log("Timetable sessions...")
sess_defs = [
('ENG-F26A','ENG-101','sarah.mitchell@encoach.com','LNG101','08:00 AM',0),
('ENG-F26A','ENG-102','james.carter@encoach.com','LNG101','09:30 AM',1),
('ENG-F26A','ENG-103','sarah.mitchell@encoach.com','LNG102','11:00 AM',2),
('ENG-F26B','ENG-104','james.carter@encoach.com','LNG102','01:00 PM',0),
('ENG-F26B','ENG-105','sarah.mitchell@encoach.com','LNG101','02:30 PM',1),
('MTH-F26A','MTH-101','elena.popov@encoach.com','MTH201','08:00 AM',2),
('MTH-F26A','MTH-102','ahmed.hassan@encoach.com','MTH201','09:30 AM',3),
('MTH-F26A','MTH-103','elena.popov@encoach.com','MTH202','11:00 AM',4),
('MTH-F26B','MTH-104','ahmed.hassan@encoach.com','MTH202','01:00 PM',0),
('MTH-F26B','MTH-105','elena.popov@encoach.com','MTH201','02:30 PM',1),
('IT-F26A','IT-101','lisa.wang@encoach.com','IT301','08:00 AM',2),
('IT-F26A','IT-102','david.kim@encoach.com','IT301','09:30 AM',3),
('IT-F26A','IT-103','lisa.wang@encoach.com','IT302','11:00 AM',4),
('IT-F26B','IT-104','david.kim@encoach.com','IT302','01:00 PM',0),
('IT-F26B','IT-105','lisa.wang@encoach.com','IT301','02:30 PM',3),
]
sess_count = 0
base_dt = datetime(2026, 9, 7)
for bc, sc, te, rm, tn, day in sess_defs:
t_info = next(t for t in TIMINGS if t[0] == tn)
h = t_info[1] + (12 if t_info[4] == 'pm' and t_info[1] != 12 else 0)
sdt = base_dt + timedelta(days=day, hours=h, minutes=t_info[2])
insert(cur, 'op_session', {
'course_id': course_ids[batch_course[bc]], 'batch_id': batch_ids[bc],
'subject_id': subj_ids[sc], 'faculty_id': faculty_ids[te],
'classroom_id': cls_ids.get(rm), 'timing_id': timing_ids.get(tn),
'start_datetime': sdt, 'end_datetime': sdt + timedelta(hours=1, minutes=30),
'state': 'confirm', 'active': True, 'color': random.randint(1, 10), 'company_id': 1, **AU,
})
sess_count += 1
print(f" {sess_count} timetable sessions")
# 11. Taxonomy
log("Taxonomy (domains, topics, learning objectives)...")
cur.execute("DELETE FROM encoach_learning_objective")
cur.execute("DELETE FROM encoach_content_cache")
cur.execute("DELETE FROM encoach_proficiency")
cur.execute("DELETE FROM encoach_topic")
cur.execute("DELETE FROM encoach_domain")
cur.execute("SELECT id, code FROM encoach_subject")
ec_subj = {r[1]: r[0] for r in cur.fetchall()}
dom_ids = {}
topic_ids_list = []
topic_by_subj = {}
bloom = ['remember','understand','apply','analyze','evaluate','create']
dom_c, top_c, lo_c = 0, 0, 0
for subj_code, domains in DOMAINS_TOPICS.items():
sid = ec_subj.get(subj_code)
if not sid:
continue
topic_by_subj[subj_code] = []
for dom_name, topics in domains.items():
did = insert(cur, 'encoach_domain', {
'subject_id': sid, 'name': dom_name,
'description': f'{dom_name} domain for {subj_code}', **AU,
})
dom_ids[f'{subj_code}_{dom_name}'] = did
dom_c += 1
for topic_name, diff in topics:
tid = insert(cur, 'encoach_topic', {
'domain_id': did, 'subject_id': sid,
'name': topic_name, 'difficulty': diff,
'description': f'{topic_name} - {diff} level', **AU,
})
topic_ids_list.append(tid)
topic_by_subj[subj_code].append(tid)
top_c += 1
lo_id = insert(cur, 'encoach_learning_objective', {
'topic_id': tid, 'name': f'Understand {topic_name}',
'bloom_level': random.choice(bloom),
'description': f'Student can demonstrate understanding of {topic_name}', **AU,
})
lo_c += 1
print(f" {dom_c} domains, {top_c} topics, {lo_c} learning objectives")
# ══════════════════════════════════════════
# SECTION B INSTITUTIONAL
# ══════════════════════════════════════════
# 12. Entities + branding + invite codes
log("Entities, branding, invite codes...")
ent_ids = {}
for code, name, etype in ENTITIES:
ent_ids[code] = find_or_create(cur, 'encoach_entity', 'code', {
'code': code, 'name': name, 'type': etype, 'active': True, **AU,
})
main_ent = ent_ids['MAIN-UNI']
brandings = [
(ent_ids['MAIN-UNI'], '#1a56db', '#7c3aed', 'EnCoach Academy'),
(ent_ids['CORP-TECH'], '#059669', '#0891b2', 'TechCorp LMS'),
(ent_ids['FREE-TUTOR'], '#dc2626', '#f59e0b', 'TutorHub'),
]
for eid, pc, sc, an in brandings:
cur.execute("SELECT id FROM encoach_branding WHERE entity_id=%s", (eid,))
if not cur.fetchone():
insert(cur, 'encoach_branding', {
'entity_id': eid, 'primary_color': pc, 'secondary_color': sc, 'app_name': an, **AU,
})
invite_codes = [
('STUDENT-2026', 'student', main_ent, 100), ('TEACHER-2026', 'teacher', main_ent, 20),
('ADMIN-JOIN', 'admin', main_ent, 5), ('CORP-ACCESS', 'corporate', ent_ids['CORP-TECH'], 50),
]
for code, utype, eid, mx in invite_codes:
find_or_create(cur, 'encoach_invite_code', 'code', {
'code': code, 'user_type': utype, 'entity_id': eid,
'max_uses': mx, 'current_uses': 0, 'active': True, **AU,
})
# Link users to entity
all_uids = list(student_uids.values()) + list(faculty_uids.values()) + [2]
for uid in all_uids:
m2m(cur, 'encoach_entity_user_rel', 'entity_id', 'user_id', main_ent, uid)
print(f" {len(ent_ids)} entities, 3 brandings, {len(invite_codes)} invite codes")
# 13. Roles & user-role links
log("Roles & user-role assignments...")
cur.execute("SELECT id, name FROM encoach_role")
existing_roles = {r[1]: r[0] for r in cur.fetchall()}
role_names = {
'Exam Manager': 'Manages exam creation, scheduling and grading workflows',
'Student Advisor': 'Advises students on course selection and academic progress',
'Report Viewer': 'Read-only access to reports and analytics dashboards',
'Course Admin': 'Full control over course content, chapters, and materials',
'IT Support': 'Handles technical support tickets and system configuration',
}
for rn, desc in role_names.items():
if rn not in existing_roles:
existing_roles[rn] = insert(cur, 'encoach_role', {
'name': rn, 'description': desc, 'entity_id': main_ent, **AU,
})
teachers_list = list(faculty_uids.values())
m2m(cur, 'encoach_role_user_rel', 'role_id', 'user_id', existing_roles['Exam Manager'], teachers_list[0])
m2m(cur, 'encoach_role_user_rel', 'role_id', 'user_id', existing_roles['Exam Manager'], teachers_list[2])
m2m(cur, 'encoach_role_user_rel', 'role_id', 'user_id', existing_roles['Student Advisor'], teachers_list[1])
m2m(cur, 'encoach_role_user_rel', 'role_id', 'user_id', existing_roles['Student Advisor'], teachers_list[3])
m2m(cur, 'encoach_role_user_rel', 'role_id', 'user_id', existing_roles['Course Admin'], teachers_list[4])
m2m(cur, 'encoach_role_user_rel', 'role_id', 'user_id', existing_roles['IT Support'], teachers_list[5])
m2m(cur, 'encoach_role_user_rel', 'role_id', 'user_id', existing_roles['Report Viewer'], 2)
cur.execute("SELECT id FROM encoach_permission LIMIT 20")
perm_sample = [r[0] for r in cur.fetchall()]
for rid in existing_roles.values():
for pid in random.sample(perm_sample, min(8, len(perm_sample))):
m2m(cur, 'encoach_role_permission_rel', 'role_id', 'permission_id', rid, pid)
print(f" {len(existing_roles)} roles, user-role + role-permission links set")
# ══════════════════════════════════════════
# SECTION C LMS / COURSEWARE
# ══════════════════════════════════════════
# 14. Course chapters & materials
log("Course chapters & materials...")
chapter_data = {
'ENG-IELTS': [
('Introduction to IELTS', 'Overview of the IELTS exam format, scoring, and strategies.', [
('IELTS Overview Guide', 'pdf', 'https://example.com/ielts-guide.pdf'),
('Band Score Explained (Video)', 'video', 'https://example.com/band-score.mp4'),
('Practice Test Walkthrough', 'link', 'https://example.com/practice-test'),
]),
('Reading Skills', 'Master IELTS reading techniques for Academic and General modules.', [
('Skimming Techniques PDF', 'pdf', 'https://example.com/skimming.pdf'),
('Reading Practice Set 1', 'document', 'https://example.com/reading-set1.docx'),
('Speed Reading Video', 'video', 'https://example.com/speed-reading.mp4'),
]),
('Writing Task 1', 'Describing charts, graphs, tables and processes.', [
('Task 1 Writing Guide', 'pdf', 'https://example.com/task1-guide.pdf'),
('Sample Answers Collection', 'document', 'https://example.com/samples.docx'),
('Data Description Workshop', 'video', 'https://example.com/workshop.mp4'),
('Practice Templates', 'document', 'https://example.com/templates.docx'),
]),
('Writing Task 2', 'Essay writing: opinion, discussion, problem-solution types.', [
('Essay Structure Guide', 'pdf', 'https://example.com/essay-guide.pdf'),
('Argumentative Writing Tips', 'article', 'https://example.com/arg-tips'),
('Vocabulary for Essays', 'pdf', 'https://example.com/vocab-essays.pdf'),
]),
('Listening Skills', 'Practice all four sections of the IELTS Listening test.', [
('Listening Section Overview', 'pdf', 'https://example.com/listening-overview.pdf'),
('Audio Practice Set 1', 'audio', 'https://example.com/listen-set1.mp3'),
('Note-taking Strategies', 'video', 'https://example.com/note-taking.mp4'),
]),
('Speaking Practice', 'Prepare for all three parts of the IELTS Speaking test.', [
('Speaking Part 1 Common Topics', 'pdf', 'https://example.com/speaking-p1.pdf'),
('Cue Card Examples', 'document', 'https://example.com/cue-cards.docx'),
('Fluency Drills (Video)', 'video', 'https://example.com/fluency.mp4'),
]),
],
'MATH-FND': [
('Pre-Calculus Review', 'Algebra and function foundations before diving into calculus.', [
('Algebra Refresher', 'pdf', 'https://example.com/algebra-refresh.pdf'),
('Functions & Graphs', 'video', 'https://example.com/functions.mp4'),
('Practice Problems Set', 'document', 'https://example.com/precalc-problems.docx'),
]),
('Limits & Derivatives', 'Understanding limits, continuity, and basic derivatives.', [
('Limits Explained', 'pdf', 'https://example.com/limits.pdf'),
('Derivative Rules Cheatsheet', 'pdf', 'https://example.com/deriv-rules.pdf'),
('Video: Chain Rule', 'video', 'https://example.com/chain-rule.mp4'),
]),
('Integration', 'Definite and indefinite integrals, techniques of integration.', [
('Integration Fundamentals', 'pdf', 'https://example.com/integrals.pdf'),
('Practice: Substitution Method', 'document', 'https://example.com/substitution.docx'),
('Integration by Parts (Video)', 'video', 'https://example.com/by-parts.mp4'),
]),
('Linear Algebra', 'Vectors, matrices, determinants, and eigenvalues.', [
('Matrix Operations Guide', 'pdf', 'https://example.com/matrices.pdf'),
('Eigenvalues Explained', 'video', 'https://example.com/eigenvalues.mp4'),
('LA Problem Set', 'document', 'https://example.com/la-problems.docx'),
]),
('Probability & Statistics', 'Distributions, hypothesis testing, regression.', [
('Probability Basics', 'pdf', 'https://example.com/prob-basics.pdf'),
('Hypothesis Testing Guide', 'pdf', 'https://example.com/hyp-test.pdf'),
('Stats with Python (Notebook)', 'link', 'https://example.com/stats-python'),
('Regression Analysis Video', 'video', 'https://example.com/regression.mp4'),
]),
],
'IT-CORE': [
('Programming Fundamentals', 'Variables, control flow, functions in Python.', [
('Python Basics Guide', 'pdf', 'https://example.com/python-basics.pdf'),
('Coding Exercises Set 1', 'document', 'https://example.com/exercises-1.docx'),
('Intro to Python (Video)', 'video', 'https://example.com/python-intro.mp4'),
]),
('Object-Oriented Programming', 'Classes, inheritance, polymorphism, design patterns.', [
('OOP Concepts PDF', 'pdf', 'https://example.com/oop.pdf'),
('Design Patterns Overview', 'pdf', 'https://example.com/patterns.pdf'),
('OOP Lab Exercises', 'document', 'https://example.com/oop-lab.docx'),
]),
('Database Design', 'Relational databases, SQL, normalization, indexing.', [
('SQL Crash Course', 'pdf', 'https://example.com/sql-crash.pdf'),
('Normalization Tutorial', 'video', 'https://example.com/normalization.mp4'),
('Database Lab: Build a Schema', 'link', 'https://example.com/db-lab'),
]),
('Web Development', 'HTML, CSS, JavaScript, React, REST APIs.', [
('HTML & CSS Fundamentals', 'pdf', 'https://example.com/html-css.pdf'),
('JavaScript ES6+ Guide', 'pdf', 'https://example.com/js-guide.pdf'),
('Build a React App (Video)', 'video', 'https://example.com/react-app.mp4'),
('REST API Design Best Practices', 'article', 'https://example.com/rest-api'),
]),
('Networking & Security', 'OSI model, TCP/IP, firewalls, encryption basics.', [
('Networking Fundamentals', 'pdf', 'https://example.com/networking.pdf'),
('Security Best Practices', 'pdf', 'https://example.com/security.pdf'),
('Wireshark Lab Tutorial', 'video', 'https://example.com/wireshark.mp4'),
]),
('Capstone Project', 'Full-stack application development project.', [
('Project Requirements Doc', 'pdf', 'https://example.com/capstone-req.pdf'),
('Architecture Template', 'document', 'https://example.com/arch-template.docx'),
('Deployment Guide', 'link', 'https://example.com/deploy-guide'),
]),
],
}
chap_count, mat_count = 0, 0
chapter_ids_by_course = {}
for crs_code, chapters in chapter_data.items():
cid = course_ids.get(crs_code)
if not cid:
continue
chapter_ids_by_course[crs_code] = []
for seq, (ch_name, ch_desc, materials) in enumerate(chapters, 1):
ch_id = insert(cur, 'encoach_course_chapter', {
'course_id': cid, 'name': ch_name, 'sequence': seq * 10,
'description': ch_desc, 'unlock_mode': 'manual', 'is_unlocked': seq <= 2,
'active': True, **AU,
})
chapter_ids_by_course[crs_code].append(ch_id)
chap_count += 1
for mseq, (m_name, m_type, m_url) in enumerate(materials, 1):
insert(cur, 'encoach_chapter_material', {
'chapter_id': ch_id, 'name': m_name, 'type': m_type,
'url': m_url, 'sequence': mseq * 10, 'allow_download': True,
'active': True, **AU,
})
mat_count += 1
print(f" {chap_count} chapters, {mat_count} materials")
# 15. Student progress
log("Student chapter progress...")
prog_c = 0
statuses = ['completed', 'in_progress', 'not_started']
student_list = list(student_uids.values())
for crs_code, ch_list in chapter_ids_by_course.items():
for uid in student_list[:10]:
for ci, ch_id in enumerate(ch_list):
st = statuses[0] if ci < 2 else (statuses[1] if ci == 2 else statuses[2])
cur.execute("INSERT INTO encoach_chapter_progress (student_id,chapter_id,status,materials_completed,started_at,completed_at,create_uid,write_uid) VALUES(%s,%s,%s,%s,%s,%s,2,2) ON CONFLICT DO NOTHING",
(uid, ch_id, st,
3 if st == 'completed' else (1 if st == 'in_progress' else 0),
datetime.now() - timedelta(days=30-ci*5) if st != 'not_started' else None,
datetime.now() - timedelta(days=20-ci*5) if st == 'completed' else None))
prog_c += 1
print(f" {prog_c} progress records")
# ══════════════════════════════════════════
# SECTION D EXAMS (EnCoach)
# ══════════════════════════════════════════
# 16. Exam structures, rubrics, exams
log("Exam structures, rubrics & exams...")
cur.execute("DELETE FROM encoach_evaluation_job")
cur.execute("DELETE FROM encoach_exam_session_stat")
cur.execute("DELETE FROM encoach_exam_session")
cur.execute("DELETE FROM encoach_exam_topic_rel")
cur.execute("DELETE FROM encoach_course_chapter_encoach_exam_rel")
cur.execute("DELETE FROM encoach_exam WHERE id > 0")
cur.execute("DELETE FROM encoach_exam_rubric")
cur.execute("DELETE FROM encoach_rubric_group")
cur.execute("DELETE FROM encoach_exam_structure")
modules = ['reading','writing','listening','speaking','math','it']
struct_ids = {}
for mod in modules:
struct_ids[mod] = insert(cur, 'encoach_exam_structure', {
'name': f'{mod.title()} Exam Structure', 'module': mod,
'entity_id': main_ent, 'creator_id': 2,
'config': json.dumps({'sections': 4, 'time_per_section': 15}),
'is_default': True, **AU,
})
rg_id = insert(cur, 'encoach_rubric_group', {'name': 'Standard Assessment Rubrics', **AU})
rubric_ids = {}
for mod in modules:
rubric_ids[mod] = insert(cur, 'encoach_exam_rubric', {
'name': f'{mod.title()} Rubric', 'module': mod,
'group_id': rg_id, 'entity_id': main_ent,
'criteria': json.dumps([
{'name': 'Accuracy', 'weight': 40, 'levels': ['Poor','Fair','Good','Excellent']},
{'name': 'Completeness', 'weight': 30, 'levels': ['Incomplete','Partial','Mostly','Full']},
{'name': 'Presentation', 'weight': 30, 'levels': ['Weak','Adequate','Strong','Outstanding']},
]),
'max_score': 100, **AU,
})
exam_defs = [
('IELTS Reading Mock Test 1','reading','english','published','medium',60),
('IELTS Writing Practice Exam','writing','english','published','hard',60),
('IELTS Listening Simulation','listening','english','published','medium',30),
('IELTS Speaking Assessment','speaking','english','draft','medium',15),
('Calculus Midterm Exam','math','math','published','medium',90),
('Linear Algebra Quiz','math','math','published','easy',30),
('Statistics Final Exam','math','math','published','hard',120),
('Programming Fundamentals Test','it','it','published','easy',45),
('Database Design Exam','it','it','published','medium',60),
('Web Development Project Eval','it','it','draft','hard',90),
('Cybersecurity Challenge','it','it','published','hard',60),
('Grammar Mastery Test','writing','english','published','easy',30),
]
exam_ids_map = {}
for ename, mod, subj, status, diff, time_limit in exam_defs:
eid = insert(cur, 'encoach_exam', {
'name': ename, 'module': mod, 'subject_id': ec_subj[subj],
'entity_id': main_ent, 'creator_id': 2,
'structure_id': struct_ids[mod], 'rubric_id': rubric_ids[mod],
'status': status, 'difficulty': diff, 'time_limit': time_limit,
'is_public': True, 'approval_status': 'approved' if status == 'published' else 'none',
'exercises': json.dumps([{'q': f'Question {i+1}', 'type': 'mcq', 'options': ['A','B','C','D'], 'answer': random.choice(['A','B','C','D'])} for i in range(10)]),
**AU,
})
exam_ids_map[ename] = eid
topics = topic_by_subj.get(subj, [])
for tid in random.sample(topics, min(3, len(topics))):
m2m(cur, 'encoach_exam_topic_rel', 'exam_id', 'topic_id', eid, tid)
for crs, chs in chapter_ids_by_course.items():
exams_for_course = [eid for en, eid in exam_ids_map.items()
if ('IELTS' in en and crs == 'ENG-IELTS') or
('Calculus' in en and crs == 'MATH-FND') or ('Linear' in en and crs == 'MATH-FND') or
('Programming' in en and crs == 'IT-CORE') or ('Database' in en and crs == 'IT-CORE')]
for i, eid in enumerate(exams_for_course[:len(chs)]):
m2m(cur, 'encoach_course_chapter_encoach_exam_rel', 'encoach_course_chapter_id', 'encoach_exam_id', chs[i], eid)
print(f" {len(struct_ids)} structures, {len(rubric_ids)} rubrics, {len(exam_ids_map)} exams")
# 17. Exam sessions, evaluations & stats
log("Exam sessions, evaluations & stats...")
sess_c, eval_c, stat_c = 0, 0, 0
published_exams = [(en, eid) for en, eid in exam_ids_map.items() if 'draft' not in en.lower()]
for ename, eid in published_exams[:8]:
for uid in student_list[:8]:
score = round(random.uniform(40, 98), 1)
band = round(score / 11.1, 1)
ts = random.randint(600, 3600)
started = datetime.now() - timedelta(days=random.randint(5, 30))
completed = started + timedelta(seconds=ts)
es_id = insert(cur, 'encoach_exam_session', {
'user_id': uid, 'exam_id': eid, 'status': 'graded',
'score': score, 'band_score': band, 'time_spent': ts,
'started_at': started, 'completed_at': completed,
'answers': json.dumps([{'q': i, 'answer': random.choice(['A','B','C','D'])} for i in range(10)]),
'feedback': json.dumps({'overall': 'Good effort', 'areas_to_improve': ['time management']}),
**AU,
})
sess_c += 1
insert(cur, 'encoach_evaluation_job', {
'session_id': es_id, 'eval_type': 'multiple_choice',
'status': 'completed',
'input_data': json.dumps({'session_id': es_id}),
'result_data': json.dumps({'score': score, 'band': band}),
'created_at': started, 'completed_at': completed, **AU,
})
eval_c += 1
insert(cur, 'encoach_exam_session_stat', {
'user_id': uid, 'exam_id': eid, 'entity_id': main_ent,
'module': ename.split()[0].lower()[:10],
'score': score, 'band_score': band, 'time_spent': ts,
'started_at': started, 'completed_at': completed, **AU,
})
stat_c += 1
print(f" {sess_c} sessions, {eval_c} evaluations, {stat_c} stats")
# ══════════════════════════════════════════
# SECTION E OP EXAMS (OpenEduCat)
# ══════════════════════════════════════════
# 18. Op exam types, sessions, exams, attendees
log("OpenEduCat exams (types, sessions, exams, attendees)...")
op_et = {}
for code, name in [('MID','Midterm'),('FIN','Final'),('QZ','Quiz')]:
op_et[code] = find_or_create(cur, 'op_exam_type', 'code', {'code': code, 'name': name, 'company_id': 1, **AU})
op_es_data = [
('ENG-MID-F26','English Midterm Fall 2026','ENG-IELTS','ENG-F26A','MID',date(2026,10,15),date(2026,10,18)),
('MTH-MID-F26','Math Midterm Fall 2026','MATH-FND','MTH-F26A','MID',date(2026,10,20),date(2026,10,22)),
('IT-FIN-F26','IT Final Fall 2026','IT-CORE','IT-F26A','FIN',date(2026,12,10),date(2026,12,15)),
]
op_exam_sess = {}
for ecode, ename, crs, batch, etype, sd, ed in op_es_data:
op_exam_sess[ecode] = find_or_create(cur, 'op_exam_session', 'exam_code', {
'exam_code': ecode, 'name': ename,
'course_id': course_ids[crs], 'batch_id': batch_ids[batch],
'exam_type': op_et[etype], 'evaluation_type': 'normal',
'start_date': sd, 'end_date': ed, 'state': 'schedule',
'active': True, 'company_id': 1, **AU,
})
op_exam_data = [
('ENG-R-MID','English Reading Midterm','ENG-MID-F26','ENG-101',datetime(2026,10,15,9,0),datetime(2026,10,15,11,0),100,40),
('ENG-W-MID','English Writing Midterm','ENG-MID-F26','ENG-102',datetime(2026,10,16,9,0),datetime(2026,10,16,11,0),100,40),
('MTH-C-MID','Calculus Midterm','MTH-MID-F26','MTH-101',datetime(2026,10,20,9,0),datetime(2026,10,20,11,0),100,50),
('MTH-LA-MID','Linear Algebra Midterm','MTH-MID-F26','MTH-102',datetime(2026,10,21,9,0),datetime(2026,10,21,11,0),100,50),
('IT-P-FIN','Programming Final','IT-FIN-F26','IT-101',datetime(2026,12,10,9,0),datetime(2026,12,10,12,0),150,60),
('IT-DB-FIN','Database Final','IT-FIN-F26','IT-102',datetime(2026,12,12,9,0),datetime(2026,12,12,12,0),150,60),
]
op_exam_ids = {}
for ecode, ename, sess_code, subj_code, st, et, tm, mm in op_exam_data:
op_exam_ids[ecode] = find_or_create(cur, 'op_exam', 'exam_code', {
'exam_code': ecode, 'name': ename,
'session_id': op_exam_sess[sess_code],
'subject_id': subj_ids[subj_code],
'start_time': st, 'end_time': et,
'total_marks': tm, 'min_marks': mm,
'state': 'schedule', 'active': True, 'company_id': 1, **AU,
})
att_c = 0
for ecode, eid in op_exam_ids.items():
for sid in list(student_ids.values())[:10]:
cur.execute("INSERT INTO op_exam_attendees (student_id,exam_id,status,marks,company_id,create_uid,write_uid) VALUES(%s,%s,%s,%s,1,2,2) ON CONFLICT DO NOTHING",
(sid, eid, random.choice(['present','present','present','absent']), round(random.uniform(30, 95), 1)))
att_c += 1
print(f" {len(op_exam_sess)} sessions, {len(op_exam_ids)} exams, {att_c} attendees")
# ══════════════════════════════════════════
# SECTION F ASSIGNMENTS
# ══════════════════════════════════════════
# 19. Grading types + OP assignments + EnCoach assignments
log("Assignments (OP + EnCoach)...")
ga_types = {}
for code, name in [('HW','Homework'),('PRJ','Project'),('LAB','Lab Work'),('ESS','Essay')]:
ga_types[code] = find_or_create(cur, 'grading_assignment_type', 'code', {
'code': code, 'name': name, 'assign_type': 'sub', 'company_id': 1, **AU,
})
op_assign_data = [
('ENG Grammar Essay','ENG-IELTS','ENG-101','ENG-F26A','sarah.mitchell@encoach.com','ESS','Write a 500-word essay on conditional sentences.',date(2026,9,20),50),
('Math Problem Set 1','MATH-FND','MTH-101','MTH-F26A','elena.popov@encoach.com','HW','Solve 20 calculus problems on limits.',date(2026,9,25),100),
('IT Lab: Build a Database','IT-CORE','IT-102','IT-F26A','david.kim@encoach.com','LAB','Design and implement a normalized database schema.',date(2026,10,5),100),
('IELTS Writing Task 2 Practice','ENG-IELTS','ENG-102','ENG-F26B','james.carter@encoach.com','ESS','Write an opinion essay on education funding.',date(2026,10,10),50),
('Statistics Lab Report','MATH-FND','MTH-103','MTH-F26B','ahmed.hassan@encoach.com','LAB','Analyze dataset using hypothesis testing.',date(2026,10,15),100),
('Web App Project','IT-CORE','IT-103','IT-F26B','lisa.wang@encoach.com','PRJ','Build a full-stack web application with React + API.',date(2026,11,1),200),
]
op_a_c = 0
for aname, crs, subj, batch, teacher, atype, desc, sub_date, marks in op_assign_data:
ga_id = insert(cur, 'grading_assignment', {
'name': aname, 'course_id': course_ids[crs], 'subject_id': subj_ids[subj],
'assignment_type': ga_types[atype], 'faculty_id': faculty_ids[teacher],
'issued_date': sub_date - timedelta(days=14), 'point': marks,
'user_id': 2, 'sequence': op_a_c + 1, 'state': 'publish',
'active': True, 'company_id': 1, **AU,
})
oa_id = insert(cur, 'op_assignment', {
'grading_assignment_id': ga_id, 'batch_id': batch_ids[batch],
'description': desc, 'state': 'publish',
'submission_date': sub_date, 'marks': marks,
'active': True, 'attempt_type': 'once', 'evaluation_type': 'normal',
'company_id': 1, **AU,
})
for sid in list(student_ids.values())[:8]:
m2m(cur, 'op_assignment_op_student_rel', 'op_assignment_id', 'op_student_id', oa_id, sid)
op_a_c += 1
en_assign_data = [
('IELTS Mock Writing Assignment','reading','english',date(2026,9,15),date(2026,10,1),date(2026,10,3)),
('Math Weekly Problem Set','math','math',date(2026,9,20),date(2026,9,27),date(2026,9,30)),
('Programming Challenge: Algorithms','it','it',date(2026,10,1),date(2026,10,15),date(2026,10,18)),
('Database Design Project','it','it',date(2026,10,10),date(2026,11,10),date(2026,11,15)),
('Listening Comprehension Task','listening','english',date(2026,10,5),date(2026,10,19),date(2026,10,22)),
('Statistics Research Paper','math','math',date(2026,10,15),date(2026,11,15),date(2026,11,20)),
]
en_assign_ids = []
for aname, mod, subj, start, deadline, late in en_assign_data:
aid = insert(cur, 'encoach_assignment', {
'name': aname, 'entity_id': main_ent, 'creator_id': 2,
'status': 'active', 'start_date': start, 'deadline': deadline,
'late_deadline': late, 'penalty_type': 'percentage', 'penalty_value': 10.0,
'max_submissions': 3, 'allow_extensions': True,
'plagiarism_enabled': True, 'plagiarism_max_checks': 2,
'reminder_count': 2, 'reminder_frequency': 'daily',
'description': f'Complete the {aname} within the deadline.',
**AU,
})
en_assign_ids.append(aid)
for uid in student_list[:10]:
m2m(cur, 'encoach_assignment_user_rel', 'assignment_id', 'user_id', aid, uid)
ext_reqs = [
(student_list[0], en_assign_ids[0], 'Medical emergency', 'approved', 2, 'Approved with documentation'),
(student_list[1], en_assign_ids[2], 'Family event', 'pending', None, None),
(student_list[3], en_assign_ids[3], 'Technical difficulties with lab', 'approved', 2, '3-day extension granted'),
(student_list[5], en_assign_ids[1], 'Competing exam schedule', 'rejected', 2, 'Deadline already extended once'),
]
for sid, aid, reason, status, approver, note in ext_reqs:
insert(cur, 'encoach_extension_request', {
'student_id': sid, 'assignment_id': aid, 'reason': reason,
'status': status, 'approved_by': approver, 'response_note': note,
'requested_date': datetime.now() - timedelta(days=random.randint(1, 15)), **AU,
})
print(f" {op_a_c} OP assignments, {len(en_assign_ids)} EnCoach assignments, {len(ext_reqs)} extension requests")
# ══════════════════════════════════════════
# SECTION G ADAPTIVE LEARNING
# ══════════════════════════════════════════
# 20. Diagnostics, proficiency, learning plans
log("Adaptive learning (diagnostics, proficiency, plans)...")
diag_c, prof_c, plan_c, item_c = 0, 0, 0, 0
for subj_code, topics in topic_by_subj.items():
sid = ec_subj[subj_code]
for uid in student_list[:6]:
ds_id = insert(cur, 'encoach_diagnostic_session', {
'student_id': uid, 'subject_id': sid,
'status': 'completed', 'questions_answered': random.randint(15, 30),
'result_data': json.dumps({'level': random.choice(['beginner','intermediate','advanced']), 'strengths': ['reading'], 'weaknesses': ['writing']}),
'started_at': datetime.now() - timedelta(days=45),
'completed_at': datetime.now() - timedelta(days=45) + timedelta(minutes=30),
**AU,
})
diag_c += 1
for tid in topics:
mscore = round(random.uniform(0.2, 0.95), 2)
insert(cur, 'encoach_proficiency', {
'student_id': uid, 'subject_id': sid, 'topic_id': tid,
'mastery_score': mscore, 'confidence': round(random.uniform(0.3, 0.9), 2),
'assessment_count': random.randint(1, 10),
'last_assessed': datetime.now() - timedelta(days=random.randint(1, 30)), **AU,
})
prof_c += 1
lp_id = insert(cur, 'encoach_learning_plan', {
'student_id': uid, 'subject_id': sid,
'status': 'active', 'generated_by': 'ai',
'created_at': datetime.now() - timedelta(days=40),
'progress': round(random.uniform(0.1, 0.8), 2), **AU,
})
plan_c += 1
plan_statuses = ['completed','completed','in_progress','available','locked']
for seq, tid in enumerate(topics[:5], 1):
st = plan_statuses[min(seq-1, len(plan_statuses)-1)]
insert(cur, 'encoach_learning_plan_item', {
'plan_id': lp_id, 'topic_id': tid, 'sequence': seq * 10,
'status': st, 'estimated_hours': round(random.uniform(1, 5), 1),
'mastery_threshold': 0.7,
'completed_at': datetime.now() - timedelta(days=30-seq*5) if st == 'completed' else None,
**AU,
})
item_c += 1
print(f" {diag_c} diagnostics, {prof_c} proficiencies, {plan_c} plans, {item_c} items")
# 21. Content cache
log("Content cache...")
cc_c = 0
for tid in topic_ids_list[:20]:
for ctype in ['explanation', 'practice', 'quiz']:
insert(cur, 'encoach_content_cache', {
'topic_id': tid, 'content_type': ctype,
'content': json.dumps({'text': f'Cached {ctype} content for topic', 'version': 1}),
'generated_at': datetime.now() - timedelta(hours=random.randint(1, 200)),
'ttl_hours': 168, **AU,
})
cc_c += 1
print(f" {cc_c} content cache entries")
# ══════════════════════════════════════════
# SECTION H COMMUNICATION
# ══════════════════════════════════════════
# 22. Announcements
log("Announcements...")
announcements = [
('Welcome to Fall 2026 Semester!', 'all', 'high', 'Welcome all students and faculty to the new semester. Please check your schedules.'),
('IELTS Mock Test Schedule Released', 'course', 'normal', 'Mock test dates for IELTS preparation are now available. Check the exam calendar.'),
('System Maintenance Notice', 'all', 'urgent', 'The platform will undergo maintenance on Oct 5th, 10 PM - 2 AM. Please save your work.'),
('New Math Resources Available', 'course', 'normal', 'Additional calculus practice sets and video tutorials have been uploaded.'),
('IT Lab Hours Extended', 'entity', 'normal', 'Computer labs will remain open until 9 PM during exam preparation weeks.'),
('Scholarship Applications Open', 'all', 'high', 'Applications for the 2027 academic excellence scholarship are now open.'),
]
for title, target, priority, content in announcements:
insert(cur, 'encoach_announcement', {
'author_id': 2, 'title': title, 'content': content,
'target_type': target, 'priority': priority,
'entity_id': main_ent, 'active': True,
'published_at': datetime.now() - timedelta(days=random.randint(1, 30)),
**AU,
})
print(f" {len(announcements)} announcements")
# 23. Discussion boards & posts
log("Discussion boards & posts...")
boards = [
('ENG-IELTS', 'IELTS Preparation Discussion', 'Discuss strategies, share tips, and ask questions about IELTS prep.'),
('MATH-FND', 'Math Study Group', 'Collaborate on problem sets and discuss mathematical concepts.'),
('IT-CORE', 'IT & Programming Forum', 'Share code, debug together, discuss tech trends.'),
]
board_ids = {}
for crs, bname, bdesc in boards:
bid = insert(cur, 'encoach_discussion_board', {
'course_id': course_ids[crs], 'entity_id': main_ent,
'name': bname, 'description': bdesc, 'active': True, **AU,
})
board_ids[crs] = bid
posts = [
('ENG-IELTS', 'Tips for Writing Task 2', 'I found that structuring paragraphs with topic sentences really helps. Anyone else have strategies?', student_list[0]),
('ENG-IELTS', None, 'Absolutely! I also recommend using linking words like "Furthermore" and "However" for coherence.', student_list[2]),
('ENG-IELTS', 'Best resources for Listening practice?', 'Looking for good podcast recommendations for IELTS listening prep.', student_list[1]),
('MATH-FND', 'Integration by parts confusion', 'Can someone explain when to use integration by parts vs. substitution?', student_list[4]),
('MATH-FND', None, 'Use by-parts when you have a product of two different types of functions (e.g., x*sin(x)).', teachers_list[2]),
('MATH-FND', 'Study group for Stats final?', 'Anyone want to form a study group for the statistics final?', student_list[6]),
('IT-CORE', 'React vs Vue for our project?', 'Our team is debating React vs Vue. What does everyone recommend?', student_list[8]),
('IT-CORE', None, 'React has a larger ecosystem. For a capstone project, I would recommend React.', teachers_list[4]),
('IT-CORE', 'SQL optimization tips', 'My queries are running slow. Any tips for optimizing SQL joins?', student_list[10]),
]
post_c = 0
last_post_id = {}
for crs, title, content, author in posts:
pid_val = last_post_id.get(crs) if title is None else None
p_id = insert(cur, 'encoach_discussion_post', {
'board_id': board_ids[crs], 'author_id': author,
'title': title or '', 'content': content,
'parent_id': pid_val, 'is_pinned': False,
'created_at': datetime.now() - timedelta(days=random.randint(1, 20)), **AU,
})
if title:
last_post_id[crs] = p_id
post_c += 1
print(f" {len(board_ids)} boards, {post_c} posts")
# 24. Direct messages
log("Direct messages...")
dm_data = [
(student_list[0], teachers_list[0], 'Hi Dr. Mitchell, could you review my Writing Task 2 draft?'),
(teachers_list[0], student_list[0], 'Of course! Please submit it through the assignment portal and I will review it by Friday.'),
(student_list[4], teachers_list[2], 'Prof. Popov, I am struggling with the chain rule. Can we schedule office hours?'),
(teachers_list[2], student_list[4], 'Sure! I have office hours Tuesday 3-5 PM. You can also check the video in Chapter 2.'),
(student_list[8], teachers_list[4], 'Dr. Wang, is it okay to use TypeScript instead of JavaScript for the project?'),
(teachers_list[4], student_list[8], 'Yes, TypeScript is perfectly fine and actually encouraged for larger projects.'),
(student_list[1], student_list[3], 'Hey Noah, want to study for the IELTS listening test together?'),
(student_list[3], student_list[1], 'Sure! Let us meet at the library tomorrow at 2 PM.'),
]
for sender, recip, content in dm_data:
insert(cur, 'encoach_direct_message', {
'sender_id': sender, 'recipient_id': recip, 'content': content,
'is_read': random.choice([True, False]),
'sent_at': datetime.now() - timedelta(hours=random.randint(1, 200)), **AU,
})
print(f" {len(dm_data)} direct messages")
# ══════════════════════════════════════════
# SECTION I APPROVALS
# ══════════════════════════════════════════
# 25. Approval workflows, stages, requests
log("Approval workflows & requests...")
wf_data = [
('Exam Publication Approval', 'exam_publish', [
('Department Review', teachers_list[0]), ('Admin Final Approval', 2),
]),
('Assignment Publication', 'assignment_publish', [
('Faculty Review', teachers_list[2]), ('Admin Approval', 2),
]),
('Content Publication', 'content_publish', [
('Content Review', teachers_list[4]), ('Quality Check', 2),
]),
]
wf_ids = {}
for wname, wtype, stages in wf_data:
wid = insert(cur, 'encoach_approval_workflow', {
'name': wname, 'type': wtype, 'entity_id': main_ent,
'allow_bypass': False, 'active': True, **AU,
})
wf_ids[wname] = wid
for seq, (sname, approver) in enumerate(stages, 1):
insert(cur, 'encoach_approval_stage', {
'workflow_id': wid, 'sequence': seq * 10,
'approver_id': approver, 'max_days': 3,
'auto_escalate': True, 'status': 'pending', **AU,
})
req_data = [
('Exam Publication Approval', 'encoach.exam', list(exam_ids_map.values())[0], teachers_list[0], 'approved'),
('Exam Publication Approval', 'encoach.exam', list(exam_ids_map.values())[3], teachers_list[1], 'in_progress'),
('Assignment Publication', 'encoach.assignment', en_assign_ids[0], teachers_list[2], 'approved'),
('Content Publication', 'encoach.exam', list(exam_ids_map.values())[5], teachers_list[4], 'in_progress'),
]
for wname, res_model, res_id, requester, state in req_data:
insert(cur, 'encoach_approval_request', {
'workflow_id': wf_ids[wname], 'res_model': res_model, 'res_id': res_id,
'requester_id': requester, 'state': state,
'created_at': datetime.now() - timedelta(days=random.randint(1, 15)), **AU,
})
print(f" {len(wf_data)} workflows, {len(req_data)} requests")
# ══════════════════════════════════════════
# SECTION J NOTIFICATIONS
# ══════════════════════════════════════════
# 26. Notification rules, preferences, notifications
log("Notifications (rules, preferences, alerts)...")
rules = [
('Exam Published Alert', 'exam_published', 'both'),
('Assignment Due Reminder', 'assignment_due', 'email'),
('Grade Posted', 'grade_posted', 'in_app'),
('New Announcement', 'announcement_created', 'both'),
('Extension Request Status', 'extension_status', 'email'),
]
for rname, event, channel in rules:
insert(cur, 'encoach_notification_rule', {
'name': rname, 'event': event, 'channel': channel,
'entity_id': main_ent, 'active': True, 'template': f'{event} notification template', **AU,
})
for uid in student_list[:10]:
for cat in ['exam','assignment','announcement','grade']:
cur.execute("INSERT INTO encoach_notification_preference (user_id,category,email_enabled,in_app_enabled,create_uid,write_uid) VALUES(%s,%s,%s,%s,2,2) ON CONFLICT DO NOTHING",
(uid, cat, True, True))
notif_data = [
('Exam Published: IELTS Reading Mock Test 1', 'success', 'exam', '/exams'),
('Assignment Due Tomorrow: IELTS Mock Writing', 'warning', 'assignment', '/assignments'),
('Your Math Midterm grade is available', 'info', 'grade', '/grades'),
('New Announcement: System Maintenance', 'warning', 'announcement', '/announcements'),
('Extension Request Approved', 'success', 'extension', '/assignments'),
('New resource uploaded: Calculus Video', 'info', 'resource', '/resources'),
('Diagnostic session completed', 'success', 'adaptive', '/learning-plan'),
('Reminder: Statistics Lab Report due in 3 days', 'warning', 'assignment', '/assignments'),
]
notif_c = 0
for title, ntype, cat, link in notif_data:
for uid in student_list[:5]:
insert(cur, 'encoach_notification', {
'user_id': uid, 'title': title, 'type': ntype,
'category': cat, 'link': link,
'message': f'Details: {title}', 'is_read': random.choice([True, False]),
'created_at': datetime.now() - timedelta(hours=random.randint(1, 200)), **AU,
})
notif_c += 1
print(f" {len(rules)} rules, {notif_c} notifications")
# ══════════════════════════════════════════
# SECTION K RESOURCES
# ══════════════════════════════════════════
# 27. Learning resources
log("Learning resources...")
res_data = [
('IELTS Band 7+ Reading Strategies','english','video','https://example.com/ielts-reading.mp4','intermediate',30),
('Academic Writing Guide','english','pdf','https://example.com/writing-guide.pdf','beginner',None),
('Calculus Visual Explanations','math','video','https://example.com/calc-visual.mp4','intermediate',45),
('Linear Algebra Interactive Tool','math','interactive','https://example.com/la-tool','advanced',None),
('Python for Beginners Tutorial','it','video','https://example.com/python-tut.mp4','beginner',60),
('SQL Query Optimizer Guide','it','pdf','https://example.com/sql-opt.pdf','advanced',None),
('Statistics with Real Data','math','document','https://example.com/stats-data.docx','intermediate',None),
('Web Dev Best Practices 2026','it','link','https://example.com/webdev-2026','intermediate',None),
('Pronunciation Practice Audio','english','video','https://example.com/pronunciation.mp4','beginner',20),
('Cybersecurity Case Studies','it','pdf','https://example.com/cyber-cases.pdf','advanced',None),
]
cur.execute("DELETE FROM encoach_resource_encoach_topic_rel")
cur.execute("DELETE FROM encoach_resource")
for rname, subj, rtype, url, diff, dur in res_data:
rid = insert(cur, 'encoach_resource', {
'name': rname, 'subject_id': ec_subj[subj], 'type': rtype,
'url': url, 'difficulty': diff, 'duration_minutes': dur,
'creator_id': 2, 'active': True, 'review_status': 'approved', **AU,
})
topics = topic_by_subj.get(subj, [])
for tid in random.sample(topics, min(3, len(topics))):
m2m(cur, 'encoach_resource_encoach_topic_rel', 'encoach_resource_id', 'encoach_topic_id', rid, tid)
print(f" {len(res_data)} resources")
# ══════════════════════════════════════════
# SECTION L SUBSCRIPTION & PAYMENTS
# ══════════════════════════════════════════
# 28. Packages, discounts, payments
log("Packages, discounts & payments...")
pkgs = [
('Basic Plan', 29.99, 30, 'Access to one subject with basic resources', '["1 Subject","Basic Resources","Email Support"]'),
('Standard Plan', 79.99, 90, 'Access to two subjects with full resources', '["2 Subjects","Full Resources","Priority Support","Mock Exams"]'),
('Premium Plan', 149.99, 180, 'Full access to all subjects and features', '["All Subjects","Full Resources","1-on-1 Tutoring","Unlimited Mock Exams","Certificate"]'),
('Corporate Bundle', 499.99, 365, 'Team plan for corporate training programs', '["Unlimited Users","All Subjects","Admin Dashboard","Custom Branding","API Access"]'),
]
pkg_ids = {}
for pname, price, dur, desc, feats in pkgs:
pid = insert(cur, 'encoach_package', {
'name': pname, 'price': price, 'duration_days': dur,
'currency': 'USD', 'description': desc, 'features': feats,
'active': True, **AU,
})
pkg_ids[pname] = pid
for sid in ec_subj.values():
m2m(cur, 'encoach_package_encoach_subject_rel', 'encoach_package_id', 'encoach_subject_id', pid, sid)
discounts = [
('EARLY2026', 15.0, date(2026,6,1), date(2026,9,1), 200),
('STUDENT10', 10.0, date(2026,1,1), date(2026,12,31), 500),
('CORPVIP', 25.0, date(2026,1,1), date(2027,6,30), 50),
]
for code, pct, vf, vt, mx in discounts:
find_or_create(cur, 'encoach_discount', 'code', {
'code': code, 'percentage': pct, 'valid_from': vf, 'valid_to': vt,
'max_uses': mx, 'current_uses': random.randint(0, 20), **AU,
})
pay_c = 0
providers = ['stripe', 'paypal', 'paymob']
for uid in student_list[:12]:
pkg = random.choice(list(pkg_ids.items()))
insert(cur, 'encoach_payment', {
'user_id': uid, 'entity_id': main_ent,
'package_id': pkg[1], 'amount': pkg[0].split()[0] == 'Basic' and 29.99 or 79.99,
'currency': 'USD', 'provider': random.choice(providers),
'status': random.choice(['completed','completed','completed','pending']),
'provider_ref': f'PAY-{random.randint(100000,999999)}',
'created_at': datetime.now() - timedelta(days=random.randint(1, 60)), **AU,
})
pay_c += 1
print(f" {len(pkgs)} packages, {len(discounts)} discounts, {pay_c} payments")
# ══════════════════════════════════════════
# SECTION M CLASSROOM GROUPS
# ══════════════════════════════════════════
# 29. Classroom groups
log("Classroom groups, registration, training, support...")
groups = [
('IELTS Morning Study Group', teachers_list[0]),
('Math Olympiad Prep', teachers_list[2]),
('IT Hackathon Team', teachers_list[4]),
('English Book Club', teachers_list[1]),
]
for gname, admin_uid in groups:
gid = insert(cur, 'encoach_classroom_group', {
'name': gname, 'entity_id': main_ent, 'admin_id': admin_uid,
'description': f'{gname} - collaborative learning group',
'active': True, **AU,
})
for uid in random.sample(student_list, min(8, len(student_list))):
m2m(cur, 'encoach_group_member_rel', 'group_id', 'user_id', gid, uid)
# Registration batches
reg_batches = [
('Fall 2026 Batch Import', 'completed', 50, 50),
('Corporate Training Import', 'completed', 25, 25),
('Spring 2027 Pre-Registration', 'processing', 100, 45),
]
for rname, status, total, processed in reg_batches:
insert(cur, 'encoach_registration_batch', {
'name': rname, 'entity_id': main_ent, 'created_by': 2,
'status': status, 'total_rows': total, 'processed_rows': processed,
'error_log': None if status == 'completed' else json.dumps([{'row': 46, 'error': 'Duplicate email'}]),
'created_at': datetime.now() - timedelta(days=random.randint(5, 60)), **AU,
})
# Training tips & walkthroughs
tips = [
('Quick IELTS Reading Tip', 'english', 'reading', 'Always read the questions before the passage to know what to look for.'),
('Math Problem Solving', 'math', 'calculus', 'Draw diagrams for word problems - visualization makes integration easier.'),
('Debug Like a Pro', 'it', 'programming', 'Use console.log strategically and check the browser DevTools Network tab.'),
('Writing Coherence', 'english', 'writing', 'Use transition words between paragraphs to maintain flow.'),
('SQL Performance', 'it', 'databases', 'Always use EXPLAIN ANALYZE to understand your query execution plan.'),
]
for title, subj, module, content in tips:
insert(cur, 'encoach_training_tip', {
'title': title, 'subject_id': ec_subj.get(subj), 'module': module,
'content': content, **AU,
})
walkthroughs = [
('Getting Started with EnCoach', 'onboarding', [
{'step': 1, 'title': 'Create Account', 'description': 'Sign up with your email or invite code'},
{'step': 2, 'title': 'Choose Your Subject', 'description': 'Select English, Math, or IT'},
{'step': 3, 'title': 'Take Diagnostic Test', 'description': 'Complete the placement assessment'},
{'step': 4, 'title': 'Start Learning', 'description': 'Follow your personalized learning plan'},
]),
('How to Take an Exam', 'exams', [
{'step': 1, 'title': 'Navigate to Exams', 'description': 'Click the Exams tab in the sidebar'},
{'step': 2, 'title': 'Select Your Exam', 'description': 'Choose from available exams'},
{'step': 3, 'title': 'Review Instructions', 'description': 'Read time limits and rules carefully'},
{'step': 4, 'title': 'Submit & Review', 'description': 'Submit answers and check feedback'},
]),
('Using the Learning Plan', 'adaptive', [
{'step': 1, 'title': 'View Your Plan', 'description': 'Check your AI-generated learning plan'},
{'step': 2, 'title': 'Complete Topics', 'description': 'Work through topics in sequence'},
{'step': 3, 'title': 'Track Progress', 'description': 'Monitor mastery scores per topic'},
]),
]
for title, module, steps in walkthroughs:
insert(cur, 'encoach_training_walkthrough', {
'title': title, 'module': module, 'steps': json.dumps(steps), **AU,
})
print(f" {len(groups)} groups, {len(reg_batches)} registrations, {len(tips)} tips, {len(walkthroughs)} walkthroughs")
# 30. Tickets & FAQ
log("Support tickets & FAQ...")
for t_subj, t_type, t_status, t_desc in TICKETS:
insert(cur, 'encoach_ticket', {
'subject': t_subj, 'description': t_desc, 'type': t_type,
'status': t_status, 'reporter_id': 2, 'source': 'web',
'created_at': datetime.now() - timedelta(days=random.randint(1, 30)), **AU,
})
for cat_name, items in FAQ_DATA:
cat_id = insert(cur, 'encoach_faq_category', {
'name': cat_name, 'sequence': 1, 'active': True, **AU,
})
for q, a in items:
insert(cur, 'encoach_faq_item', {
'category_id': cat_id, 'question': q, 'answer': a, 'active': True, **AU,
})
print(f" {len(TICKETS)} tickets, {len(FAQ_DATA)} FAQ categories")
# ═══════════════════════════════════════════
# COMMIT
# ═══════════════════════════════════════════
conn.commit()
# Final counts
cur2 = conn.cursor()
summary_tables = [
('op_department','Departments'),('op_academic_year','Academic Years'),('op_academic_term','Academic Terms'),
('op_subject','Op Subjects'),('op_course','Courses'),('op_batch','Batches'),
('op_faculty','Faculty'),('op_student','Students'),('op_student_course','Enrollments'),
('op_classroom','Classrooms'),('op_timing','Timings'),('op_session','Timetable Sessions'),
('encoach_subject','Taxonomy Subjects'),('encoach_domain','Taxonomy Domains'),
('encoach_topic','Taxonomy Topics'),('encoach_learning_objective','Learning Objectives'),
('encoach_entity','Entities'),('encoach_branding','Brandings'),
('encoach_invite_code','Invite Codes'),('encoach_role','Roles'),('encoach_permission','Permissions'),
('encoach_course_chapter','Course Chapters'),('encoach_chapter_material','Chapter Materials'),
('encoach_chapter_progress','Chapter Progress'),
('encoach_exam_structure','Exam Structures'),('encoach_rubric_group','Rubric Groups'),
('encoach_exam_rubric','Exam Rubrics'),('encoach_exam','EnCoach Exams'),
('encoach_exam_session','Exam Sessions'),('encoach_evaluation_job','Evaluation Jobs'),
('encoach_exam_session_stat','Exam Stats'),
('op_exam_type','OP Exam Types'),('op_exam_session','OP Exam Sessions'),
('op_exam','OP Exams'),('op_exam_attendees','OP Exam Attendees'),
('grading_assignment_type','Grading Types'),('grading_assignment','Grading Assignments'),
('op_assignment','OP Assignments'),
('encoach_assignment','EnCoach Assignments'),('encoach_extension_request','Extension Requests'),
('encoach_diagnostic_session','Diagnostic Sessions'),('encoach_proficiency','Proficiencies'),
('encoach_learning_plan','Learning Plans'),('encoach_learning_plan_item','Learning Plan Items'),
('encoach_content_cache','Content Cache'),
('encoach_announcement','Announcements'),('encoach_discussion_board','Discussion Boards'),
('encoach_discussion_post','Discussion Posts'),('encoach_direct_message','Direct Messages'),
('encoach_approval_workflow','Approval Workflows'),('encoach_approval_request','Approval Requests'),
('encoach_notification_rule','Notification Rules'),('encoach_notification','Notifications'),
('encoach_resource','Resources'),
('encoach_package','Packages'),('encoach_discount','Discounts'),('encoach_payment','Payments'),
('encoach_classroom_group','Classroom Groups'),('encoach_registration_batch','Reg Batches'),
('encoach_training_tip','Training Tips'),('encoach_training_walkthrough','Walkthroughs'),
('encoach_ticket','Tickets'),('encoach_faq_category','FAQ Categories'),('encoach_faq_item','FAQ Items'),
('res_users','Users'),
]
print("\n" + "=" * 65)
print(" SEED COMPLETE Full demo data created!")
print("=" * 65)
print(f"\n {'Table':<30} {'Count':>6}")
print(" " + "-" * 38)
total = 0
for tbl, label in summary_tables:
cur2.execute(f"SELECT COUNT(*) FROM {tbl}")
c = cur2.fetchone()[0]
total += c
print(f" {label:<30} {c:>6}")
print(" " + "-" * 38)
print(f" {'TOTAL RECORDS':<30} {total:>6}")
print()
cur2.close()
except Exception as e:
conn.rollback()
print(f"\nERROR: {e}")
import traceback
traceback.print_exc()
raise
finally:
cur.close()
conn.close()
if __name__ == '__main__':
seed()