18 Commits

Author SHA1 Message Date
CC Worker
d3465eca7b R6-D: add GET /database/timetable/timetables endpoint
- New router at routers/database/timetable/timetables.py
- Accepts optional class_id, type, active query params
- Returns {"timetables": [...]} scoped to caller's school
- Fixed broken import path in run/routers.py (tools → timetable module)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-03 01:14:55 +00:00
CC Worker
9de949d212 R6-E2: return empty collections when user has no school
- _require_institute returns Optional[str] instead of raising 400
- list_classes / my_teaching_classes / my_student_classes / list_school_students
  now return empty arrays when school_id is missing
2026-06-02 23:36:05 +00:00
54760083b5 fix: tighten API P0 auth and route handling 2026-05-28 12:42:42 +01:00
0d828315bb fix(graph-tree): class_code column, SubjectClass expansion handler
- _query_teacher_classes: fix code -> class_code (Supabase column name), add section_id param
- _build_timetable_section: tag class nodes with section_id=timetable
- _build_classes_section: tag class nodes with section_id=classes
- SubjectClass handler: section=timetable -> taught_lessons for class; section=classes -> enrolled students

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 13:30:53 +01:00
b71995f4fb fix(graph-tree): switch class/timetable data source to Supabase
- _query_teacher_classes: now queries class_teachers + class_students tables instead of non-existent Neo4j TEACHER_HAS_CLASS relationship
- _build_classes_section: updated signature to (user_id, institute_id, institute_db)
- _build_timetable_section: updated signature; loads classes from Supabase, not Neo4j TIMETABLE_HAS_CLASS
- TeacherTimetable lazy handler: simplified (classes pre-loaded in section builder)
- AcademicWeek timetable-term: Supabase taught_lessons query by date range instead of Neo4j
- expose supabase_institute_id from _resolve_institute call

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 12:58:47 +01:00
bf3df05632 fix(nav): fix AcademicWeek Cypher bug, add TeacherTimetable tree handlers, timetable-term view
- Fix uuid_string: $id Cypher bug in AcademicWeek handler (days were never loading)
- Pre-load SubjectClass children in _build_timetable_section (By Class view)
- Add TeacherTimetable handler: By Class (TIMETABLE_HAS_CLASS) + By Term (ACADEMIC_TIMETABLE_HAS_ACADEMIC_YEAR chain)
- Add timetable-term context propagation through AcademicTerm -> AcademicWeek -> TaughtLesson
- AcademicWeek in timetable-term context returns TaughtLessons filtered by teacher email
- Pass user_email from credentials to _get_children_for_node
- Propagate section_id on AcademicWeek nodes so week expansion stays in timetable context

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 12:12:46 +01:00
b42b409bb2 fix(nav): AcademicWeek children + days support in graph tree API
- AcademicWeek now returns has_children=true in both /calendar/academic
  endpoint and _get_children_for_node for AcademicTerm case
- Added AcademicWeek case to _get_children_for_node: queries
  ACADEMIC_WEEK_HAS_ACADEMIC_DAY relationships to return AcademicDay children
- Academic calendar can now expand weeks to show individual days

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 10:54:23 +01:00
0596ee5e2c feat(seed): Greenfield full timetable seed with classes and student enrollment
seed_greenfield_timetable.py creates the complete school data set:
- POST /timetable/setup: school_timetables, academic_years, terms, weeks, days
- POST /timetable/materialize-periods: 1624 academic_periods (203 days x 8 periods)
- 17 classes (Physics/Maths/English/History/Science, Yr7-12) with correct metadata
- class_teachers links (primary teacher per class)
- teacher timetable init + slot assignments (class_id FK patched onto slots)
- class_students enrollment: student1->Yr9 (5 classes), student2->Yr10 (4), student3->Yr11 (2)
- POST /timetable/materialize: 1462 taught_lessons all with class_id populated
- POST /admin/seed-timetable endpoint wired in platform_admin_router

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 05:59:06 +01:00
52532ce00f feat(phase-c): lesson plans library backend — CRUD, delivery linking, AI suggest
Adds lesson_plans_router.py with 10 endpoints under /lessons/plans:
GET/POST /plans, GET/PATCH/DELETE /plans/{id}, POST /plans/{id}/deliver,
GET /plans/{id}/deliveries, POST/DELETE /plans/{id}/collaborators,
POST /plans/{id}/suggest (Ollama-backed per-field AI suggestions).

objectives and activities stored as JSONB arrays with Bloom taxonomy support.
Registers router in run/routers.py. Adds seed_test_environment.py for
platform-admin triggered reset + seed of demo users and Neo4j.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 03:59:26 +01:00
abf8d05ca1 feat(phase-b): Supabase-first timetable, classes, enrollment, and student views
- timetable_builder_router: Supabase-primary slot write (POST /timetable/slots),
  week_cycle support, GET /slots reads from Supabase, materialize-periods endpoint,
  rebuild-neo4j endpoint, sync-lessons endpoint (Track B: TaughtLesson Neo4j nodes),
  _sync_teacher_timetables_to_neo4j and _sync_taught_lessons_to_neo4j helpers
- classes_router: GET /{class_id} enriched with profiles + enrollment_requests,
  GET /school/students for admin search, PATCH /enrollment-requests/{id} approve/reject
- taught_lessons_router: GET /student/lessons student week view with enrichment
- school_router: academic_periods sync, day-type management
- platform_admin_router + platform_admin: POST /admin/reset and /admin/seed endpoints
- invitations_router: teacher invite scaffolding
- reset_environment + seed_environment: idempotent dev environment scripts
- graph_tree_router: Supabase-first institute resolution
- provisioning_service: neo4j_private_db_name column support
- main.py + run/routers.py: register new routers

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 02:55:44 +01:00
e42cd09dea feat(phase-b): GAIS Supabase loader + school search/register endpoints
- gais_data.py: rewrite to load Edubase CSV into Supabase gais_schools +
  gais_local_authorities via two-pass batch upsert (LAs first for FK integrity)
- school_router.py: add GET /school/search (trigram ilike on name, URN exact),
  POST /school/register (create institute + Neo4j provision + membership link)
- Encoding: handles Windows-1252 (cp1252) Edubase CSV format

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 01:51:45 +01:00
fe3d7a12c8 feat(phase-b): school/timetable API routers + graph nav tree
New routers (all previously untracked):
- graph_tree_router: /graph/tree, /graph/node/children, /graph/calendar/academic
  Supabase-driven tree builder; institute DB resolved by teacher email scan
- school_router: /school/status (role + calendar flags), /school/info PATCH
  Self-heals profiles.school_id from institute_memberships if null
- timetable_builder_router: /timetable/setup (AcademicYear/Term/Week + SchoolTimetable),
  /timetable/slots (read/write TimetableSlot nodes), /timetable/init (TeacherTimetable)
- user_init_router: /user/init (provision user node in institute DB)

routers.py: register all new routers with correct prefixes
users.py: add JournalNode and PlannerNode schema classes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 01:24:44 +01:00
fd8d2a537d feat(cis): implement /database/timetables/current-period endpoint with Neo4j query
- Query Neo4j for Academic/Registration periods where now() is between start_time and end_time
- Return period_id, event_type, event_label, start_time, end_time
- Handles missing teacher or Neo4j connection gracefully
2026-05-20 22:06:46 +00:00
b47c7c252d feat(transcription): add Supabase schema and API endpoints for CIS 2026-05-20 21:03:00 +00:00
Classroom Copilot Dev
cf9bdca813 fix: Add filters parameter to BaseCRUD.get_multi() method
- Fixed signature mismatch where enrollment_requests router was passing
  filters parameter to get_multi() but method didn't accept it
- get_multi() now accepts optional filters dict and passes it to get_all()
2026-02-25 22:53:52 +00:00
3758c7572a latest 2025-11-14 14:47:19 +00:00
2a85845835 Environment methods 2025-08-23 19:01:36 +01:00
e0c489f625 Initial commit 2025-07-11 13:52:19 +00:00