Courses & Sessions
API fact source: Django backend generated docs
Why CourseOccurrence Exists
courses owns course records, import rules, seasonal schedules, and concrete class session instances. A course record describes what the course is; CourseOccurrence describes the concrete class session on a specific day and period. Classroom schedules, signage display, reservation conflicts, and check-ins consume the latter so each module does not expand timetables independently.
Code entry:
backend/apps/courses/models/backend/apps/courses/views.pybackend/apps/courses/services/backend/apps/courses/tasks.py
Schedule Configuration
Seasonal class times are controlled by SeasonConfigService and SystemConfig; business code does not hard-code class period times. Successful import can update semester_start_date, which affects future schedule expansion, so import logic and system config write-back belong in the same review.
Why Import Runs Asynchronously
Course import parses Excel, writes course records, and expands class sessions. That work does not fit well in the request thread. Import tasks write to TaskRecord, and uploaded files need to live somewhere the Celery worker can read.
Current import rules include project-specific filters: UC administrative classes are imported directly; other records are limited to floors 2/3 of Building 5; PE courses have special handling. These filters are business policy, not generic Excel parsing logic.
Where Schedule Changes Propagate
- Changes to
CourseOccurrencestatus or generation logic affect classrooms, borrowings, checkins, and signage call sites. - A new schedule source needs a modeling decision: convert it into
CourseOccurrence, or accept the cost of parallel occupancy state. - Seasonal schedule changes need related cache invalidation.
- When changing the import template, also check the import service, frontend upload flow, and async task result shape.