Exams
An Exam is the school's formal, off-app assessment — Mid-Term, Final, Unit Test 1, etc. Unlike class / chapter / quick / prep tests, students do not take an exam in-app. The app's role is paperwork: a teacher creates the exam record (title, section, subjects, per-subject max marks), enters each student's marks per subject, and publishes. Students see their grades; parents see them in the parent app.
Exams are scheduled / announced via the Exam Announcement alert (separate flow). The marks-entry flow on this page is the result-declaration half.
At a glance
| Who can do this | Teachers create + enter marks + publish · Students view results · Parents view results |
| Where it lives | Teacher app /dashboard/exams, /dashboard/exams/:examId, exam-marks at /dashboard/exams/:examId/subjects/:examSubjectId/results · Student app /dashboard/exams (announcements) + /dashboard/results-detail/:examId (marks) · Parent app /results |
| Triggers notifications? | Yes — push + in-app on result publish ("result-declaration" alert type) |
| Related features | Notice Board & Alerts (exam announcements) · Class Tests · Student Analytics |
How it flows
Status lifecycle
The lifecycle is per exam-subject, not per exam. The teacher publishes Mathematics results today and Physics results next week — only published subjects show up to students and parents.
Step-by-step
1. Teacher creates the exam
- App / route: Teacher app →
/dashboard/exams(or/dashboard/classes/:sectionId/testsfor a section-scoped view) → tap + to open the create sheet. - Form fields:
- Exam Name — free text (e.g. "Mid-Term", "Final Exam", "Unit Test 1").
- Class / Section — picker of all sections in the school.
- Subjects — multi-select chips of subjects mapped to the section.
- Max marks per subject — defaults to 100, editable per subject.
- Total max-marks = sum of per-subject max marks. Validation:
- Title required.
- At least one subject.
- Every selected subject must have a positive max-marks value.
- On save the exam record is created.
2. Teacher views the exam detail
- App / route:
/dashboard/exams/:examId - Shows: title, class, section, total max-marks, teacher who created it, list of subjects with their max-marks.
- From here the teacher can:
- Tap a subject → marks-entry page for that subject.
- Delete the entire exam (confirmation sheet).
3. Teacher enters marks per subject
- App / route:
/dashboard/exams/:examId/subjects/:examSubjectId/results - Loads every student in the section. Per student:
- Marks Obtained — numeric input clamped to
[0, maxMarks]. - Attendance status — toggle Present / Absent. Marking Absent forces marks to 0.
- Marks Obtained — numeric input clamped to
- Live stats panel: Highest, Lowest, Average, Pass Rate (35 % threshold).
- Live grade-distribution bar chart (A+ ≥ 90 %, A ≥ 80 %, B+ ≥ 70 %, B ≥ 60 %, C otherwise).
- Two save modes:
- Save draft —
isPublished: false. Students do not see marks yet. - Publish —
isPublished: true. Students + parents are notified, marks become visible.
- Save draft —
- A CSV download button exports the entire subject's marks.
4. Notification + visibility flip
- On publish, the backend fires a result-declaration notification to:
- Every student in the section.
- Every linked parent.
- Until publish, students see nothing for this exam-subject. After publish, the subject's marks surface in their app and the parent app.
5. Student views results
- App / route: Student app
/dashboard/exams— list of EXAM announcements (from the alerts feed). Tapping one opens an exam detail drawer with description, scheduled date, attachments. This is the "what's the exam about" surface./dashboard/school/results—ResultsPagelists every exam created for the student's section, with expandable per-exam marks (only published subjects show marks)./dashboard/results-detail/:examId— per-exam page with each subject's mark, grade letter, and percentage.
- Grades are computed client-side using the same grade table (A+ ≥ 90, A ≥ 80, B ≥ 70, C ≥ 60, D ≥ 50, F otherwise — with one minor difference: parent app uses A+/A/B/C/D/F too, single-letter B at 70).
6. Parent views results
- App / route: Parent app →
/results - Lists every exam for the linked child, grouped by exam:
- Total obtained / total max + percentage progress bar.
- Per-subject breakdown row with mark, grade, percentage.
- Multi-child parents: pass
studentProfileIdin route state to scope to a specific child; otherwise defaults to the first linked child. - Read-only.
Edge cases & things to test
- Partial publish: teacher publishes Math but leaves Physics in draft — student should see Math marks but no Physics row; parent app should reflect the same.
- Edit after publish: teacher edits a student's mark on a published subject and saves — does it stay published, or flip back to draft? What does the student see?
- Attendance toggle: marking Absent zeroes marks; toggling back to Present must keep zeroed marks (per code) or restore previous value — confirm UX is consistent.
- Max-marks lower than entered marks: teacher creates exam with subject max 80, then later edits subject max down to 50 — already-entered marks above 50 should clamp or error.
- Numeric input out of range: entering 999 in a 100-max field — UI clamps to 100, doesn't persist 999.
- Pass rate 35 % threshold: a student exactly on 35 % — confirm they count as passed, not failed.
- Empty subject (no students): subject with zero students enrolled — stats and chart should render gracefully, not divide by zero.
- Multi-child parent: parent with 2 children in same school —
/resultsmust show only the active child's marks (driven by route state / profile fallback). - Result-declaration alert vs in-app surface: tapping the result-declaration push notification should deep-link to the right exam — not the generic exam list.
- Section reassignment after exam: student moves from Section A (where exam was created) to Section B before publish — does the student still see the exam? Should their marks row exist in the original section's exam?
- CSV download: download CSV — verify roll no, attendance, marks, grade columns are correct, and student names with quotes / commas escape properly.
- Exam deletion mid-flow: teacher deletes an exam while another teacher is entering marks — confirm both clients handle the gone-resource case.
Related
- Notice Board & Alerts — exam announcements (scheduling) flow through the
EXAMandresult-declarationalert types - Class Tests — in-app teacher-assigned tests; not the same lifecycle as exams
- Student Analytics — exam results feed into long-term analytics
- Notifications — result-declaration triggers fan-out