02 — User Personas (Academics Module)
- P1 — Organization Admin ("Nishant")
- P2 — Academic Coordinator ("Meera")
- P3 — Teacher ("Mr. Okafor")
- P4 — Student / Parent (read-only)
- Persona → capability matrix (intended; not enforced by API today)
Personas for the Academics module, derived from blueprint
01-Product/USER_PERSONAS.mdrole model (rolesexamples: Super Admin, Organization Admin, Teacher, Parent, Student —COLLECTIONS.md:600-623) and the endpoints/semantics insrc/modules/academics/**. Permission notes reflect the actual guard state: every endpoint is JWT-authenticated but noacademics.*permission exists yet (rbac/permissions.constants.ts:1-97, OQ-1 in 01_Product_Overview.md) — so the "can do X" columns below are the intended mapping, marked accordingly.
P1 — Organization Admin ("Nishant")
| Attribute | Value |
|---|---|
| Role / context | Owner/admin of one school tenant; member with organization.* perms; sees everything (base.repository.ts:20-30 scoping) |
| Tech | Tablet (Galaxy Tab S8) + desktop web; occasional phone |
| Goals | Set up the school's academic skeleton once: create the year, the grade ladder, sections, classes, subjects; flip set-current at rollover; keep one source of truth |
| Pain points | Rebuilding structure every year manually; accidental duplicates ("Grade 1" created twice); forgetting to demote the old current year |
| Key flows | Create academic year → set current → bulk-create grades → create classes with sections; monitor statuses |
| Kill feature | PATCH /academic-years/:id/set-current — one tap demotes all others and activates the new year (academic-year.service.ts:69-83) |
| Perms (intended) | Full CRUD on all six entities (none enforced today) |
P2 — Academic Coordinator ("Meera")
| Attribute | Value |
|---|---|
| Role / context | Senior teacher or dedicated coordinator; the day-to-day owner of the structure after the admin seeds it |
| Tech | Desktop web primary, phone for spot checks |
| Goals | Wire subjects + teachers to classes per year; keep section/class lists accurate; spot gaps (a class with no subjects, a teacher with no assignments) before timetabling |
| Pain points | Assignment matrix gets large (classes × subjects × teachers); no bulk ops; removing a bad assignment requires delete + recreate (subject-assignment.controller.ts:19-39) |
| Key flows | Browse hierarchy per year → open class → view subjects+teachers → add/remove assignments; fix conflicts |
| Kill feature | GET /subject-assignments/by-class/:classId?academicYearId= — the per-class teaching roster (subject-assignment.controller.ts:24-29) |
| Perms (intended) | Read all; create/delete assignments; update class/grade metadata |
P3 — Teacher ("Mr. Okafor")
| Attribute | Value |
|---|---|
| Role / context | Class teacher of "Grade 10 - A" (via classTeacherId), subject teacher via assignments |
| Tech | Phone (Pixel 8) mostly; tablet in classroom |
| Goals | See which classes/sections/subjects they teach this year; know their class's structure; enter timetable/attendance against the right classId |
| Pain points | Years change → roster changes; needs year-scoped view, not a global dump |
| Key flows | My classes (by-teacher) → class detail → subjects; timetable for own class |
| Kill feature | GET /subject-assignments/by-teacher/:teacherId?academicYearId= — year-scoped teaching load (subject-assignment.controller.ts:30-35) |
| Perms (intended) | Read structure; no writes (structure is admin/coordinator-owned) |
P4 — Student / Parent (read-only)
| Attribute | Value |
|---|---|
| Role / context | Student profile linked to a class via class_enrollments (RELATIONSHIPS.md:63-65); parent linked to student |
| Tech | Phone; light usage |
| Goals | See "my grade, my section, my class, my subjects" for the current year; understand report/timetable references |
| Pain points | Currently no client-scoped endpoint: the API returns all classes/subjects per tenant — the client must resolve "my class" from enrollment data (Students module) then render its structure |
| Key flows | Home → Academics (read-only) → structure browse filtered to own class |
| Kill feature | Subject list of their class + academic year status (upcoming/active/archived badge) |
| Perms (intended) | Read only; server has no read-scoping filter — flag OQ-1 in 01_Product_Overview.md |
Persona → capability matrix (intended; not enforced by API today)
| Capability | Admin | Coordinator | Teacher | Student/Parent |
|---|---|---|---|---|
| CRUD academic year + set-current | ✅ | ❌ | ❌ | ❌ |
| CRUD grade / section / class | ✅ | ✅ (coordinated) | ❌ | ❌ |
| CRUD subject | ✅ | ✅ | ❌ | ❌ |
| Create/delete subject assignments | ✅ | ✅ | ❌ | ❌ |
| Read structure (all, tenant-scoped) | ✅ | ✅ | ✅ | ✅ (needs own-class filter, client-side) |
by-class / by-teacher rosters | ✅ | ✅ | ✅ | ❌ |
Every write above currently requires only a valid JWT (
academics.module.ts:46, controllers@UseGuards(JwtAuthGuard)). The matrix is the design target; enforcement is(planned)(OQ-1).