Introduce program-scoped student portal with leave application flow - #456
Conversation
Add portal-specific student APIs so the SPA loads all submitted program
enrollments, lets the user choose the active program, and derives student
groups and page data from that selection instead of a single auto-detected
current enrollment.
Backend (education/education/api.py):
- Add get_portal_student_profile(student=None): whitelisted student profile
(field whitelist), all submitted Program Enrollments, and suggested_program
(active enrollment if valid, else most recent)
- Add get_portal_program_context(student=None, program=None): enrollment row
plus student_groups for the selected program, permission-checked
- Add internal helpers: _resolve_portal_student, _get_submitted_program_enrollments,
_resolve_default_program, _get_program_enrollment
- Refactor get_student_context(student, program=None) to delegate to the
portal APIs while keeping the legacy response shape (current_program,
student_groups, programs)
Frontend:
- Refactor studentStore to load profile then program context sequentially;
expose programs, activeProgram, currentProgram, studentGroups
- Persist selected program per student in localStorage
(education-active-program-{studentId})
- Add ProgramSelector.vue and mount it in Navbar for multi-program users
- Make Schedule, Grades, Attendance, and Fees reactive to program/student
changes (watch store refs and reload resources)
- Remove Grades page-local program picker in favor of the global selector
- Add role_home_page for Student/Guardian -> edu-portal, rename portal endpoints to get_student_profile/get_program_context, update the SPA store, grant Student read access on Student Group
- Replace direct make_attendance_records calls with Student Leave Application docs - Rename leave helpers to create_student_leave_application_based_on_* - Reindent api.py tabs to spaces (file-wide formatting pass) - Reset leave form fields after successful submission in Attendance.vue - Drop Student role read permission on Student Group doctype
Confidence Score: 2/5The leave application refactor has multiple functional regressions that would cause leaves to be silently not applied in production. Both leave-application helpers call education/education/api.py — the leave application logic (save vs submit, missing permission check, single-group limitation)
|
| student_leave_application.reason = leave_data.get("reason") | ||
| student_leave_application.save() | ||
|
|
||
|
|
||
| def apply_leave_based_on_student_group(leave_data, program_name): | ||
| def create_student_leave_application_based_on_student_group(leave_data, program_name): |
There was a problem hiding this comment.
Leave application silently never applied —
save() leaves the document in Draft (docstatus=0) and update_attendance() only runs from on_submit. Attendance records are never created, so the student's leave has no effect.
| student_leave_application.reason = leave_data.get("reason") | |
| student_leave_application.save() | |
| def apply_leave_based_on_student_group(leave_data, program_name): | |
| def create_student_leave_application_based_on_student_group(leave_data, program_name): | |
| student_leave_application.reason = leave_data.get("reason") | |
| student_leave_application.save() | |
| student_leave_application.submit() | |
| def create_student_leave_application_based_on_student_group(leave_data, program_name): |
| student_leave_application.student_group = student_groups[0].get("label") | ||
| student_leave_application.from_date = leave_data.get("from_date") | ||
| student_leave_application.to_date = leave_data.get("to_date") | ||
| student_leave_application.reason = leave_data.get("reason") | ||
| student_leave_application.save() |
There was a problem hiding this comment.
Same
.save() without .submit() issue as the course-schedule path — the leave application is saved as a Draft but on_submit → update_attendance() is never triggered, so no attendance records are created.
| student_leave_application.student_group = student_groups[0].get("label") | |
| student_leave_application.from_date = leave_data.get("from_date") | |
| student_leave_application.to_date = leave_data.get("to_date") | |
| student_leave_application.reason = leave_data.get("reason") | |
| student_leave_application.save() | |
| student_leave_application.student_group = student_groups[0].get("label") | |
| student_leave_application.from_date = leave_data.get("from_date") | |
| student_leave_application.to_date = leave_data.get("to_date") | |
| student_leave_application.reason = leave_data.get("reason") | |
| student_leave_application.save() | |
| student_leave_application.submit() |
Summary
Extends the education student portal so users with multiple program enrollments can choose an active program and see schedule, grades, and attendance, scoped to that program.
Program selection and scoped portal data
get_student_profileandget_program_contextbackend APIs to load student profile, all submitted enrollments, and student groups for the selected programstudentStoreto load profile then program context sequentially; persist the selected program per student inlocalStorageProgramSelectorin the navbar for multi-program usersPortal API cleanup and routing
get_student_profile/get_program_contextand update the SPA store accordinglyrole_home_pagefor Student and Guardian roles toedu-portalLeave application refactor
make_attendance_recordscalls with submittedStudent Leave Applicationdocuments