- ClassroomRentalsService.create/update now upsert a ClassSchedule row with schedule_type='RENTAL' and rental_id set.
- ClassroomRentalsService.remove deletes the synced schedule row; update to 'cancelled' also removes it.
- SchedulesService.getClassroomOccupancy explicitly returns INTERNAL and RENTAL schedules.
- Make classId/teacherId/rentalId nullable in ClassSchedule entity to support rental schedules.
- Add unit tests for rental schedule sync and mixed-type occupancy.
P2-12 Teacher Management:
- Add profile JSON field (subjects, joinedAt, qualifications) to User entity
- Add GET/PUT /rbac/users/:id/profile endpoints with UpdateProfileDto
- Add GET /rbac/teacher-workspace endpoint returning assignedClasses,
todaySchedules, and myStudents
- Create /teacher-workspace page with tabs (My Classes, Today's Schedule,
My Students)
- Add route with PermissionRoute and menu item in MainLayout
P2-13 Student Archive Multi-class:
- Add GET /students/:id/compare-classes endpoint returning side-by-side
enrollment data with per-class attendance statistics
- Students module now includes ClassStudent and AttendanceRecord entities
- No 2-enrollment cap existed in the codebase; student enrollments
already return all records via class-student table
- Create AttendancePage with filter bar, table, calendar view toggle, batch add modal
- Register /attendance route with PermissionRoute (attendance:view)
- Add menu item in MainLayout with CheckCircleOutlined icon
- Add GET /attendance-records with pagination and filters
- Add GET /attendance-records/classes for class dropdown
- Add source column to AttendanceRecord entity (default: manual)
- Frontend tsc --noEmit: clean; backend: only pre-existing test errors
- Move backend/ to apps/server/ via git mv
- Move frontend/ to apps/admin/ via git mv
- Create packages/typescript-config/ with base, nestjs, and react-vite presets