fix parent, teacher and admin pages

This commit is contained in:
root
2026-04-25 00:00:23 -04:00
parent 4cd98f1d30
commit eafe4eb134
30 changed files with 1566 additions and 105 deletions
+13 -1
View File
@@ -132,6 +132,18 @@ class Staff extends BaseModel
->first();
}
// The table enforces unique email addresses, so a user cannot safely
// have multiple staff rows across different school years with the same
// generated email. If an exact school-year row is missing but the user
// already has any staff row, update that existing row instead of trying
// to insert a duplicate-email record.
if (!$existing) {
$existing = static::query()
->where('user_id', $userId)
->orderByDesc('id')
->first();
}
$now = now(); // use UTC if app.timezone=UTC (recommended)
// Only allow fillable keys
@@ -195,4 +207,4 @@ class Staff extends BaseModel
'updated_at' => ['nullable', 'date'],
];
}
}
}
+61 -9
View File
@@ -150,6 +150,27 @@ class TeacherClass extends BaseModel
})->all();
}
/**
* Distinct `class_section_id` values this teacher has ever been assigned to (`teacher_class`),
* ignoring school year / semester (covers legacy rows vs `class_progress_reports`).
*
* @return list<int>
*/
public static function distinctSectionIdsForTeacher(int $userId): array
{
return static::query()
->where('teacher_id', $userId)
->whereNotNull('class_section_id')
->where('class_section_id', '>', 0)
->distinct()
->orderBy('class_section_id')
->pluck('class_section_id')
->map(static fn ($id) => (int) $id)
->unique()
->values()
->all();
}
/** CI: getClassSectionsByTeacherId() */
public static function getClassSectionsByTeacherId(int $teacherId): array
{
@@ -285,15 +306,41 @@ class TeacherClass extends BaseModel
/**
* CI: assignedForSectionTerm()
* Returns rows: class_section_id, teacher_id, position, firstname, lastname
*
* @param int|null $alsoSectionCode When teacher_class rows use the section PK while $sectionCode
* is the business code (or the reverse), pass the other id.
* @param bool $requireSemester When false, ignore semester (legacy DBs with blank/wrong tc.semester).
*/
public static function assignedForSectionTerm(int $sectionCode, string $semester, string $schoolYear): array
{
return DB::table('teacher_class as tc')
public static function assignedForSectionTerm(
int $sectionCode,
string $semester,
string $schoolYear,
?int $alsoSectionCode = null,
bool $requireSemester = true,
): array {
$sectionIds = array_values(array_unique(array_filter(
[$sectionCode, $alsoSectionCode ?? 0],
static fn (int $v): bool => $v > 0,
)));
if ($sectionIds === []) {
return [];
}
$q = DB::table('teacher_class as tc')
->selectRaw('tc.class_section_id, tc.teacher_id, tc.position, u.firstname, u.lastname')
->leftJoin('users as u', 'u.id', '=', 'tc.teacher_id')
->where('tc.class_section_id', $sectionCode)
->where('tc.school_year', $schoolYear)
->orderByRaw("CASE tc.position WHEN 'main' THEN 0 WHEN 'ta' THEN 1 ELSE 2 END")
->whereIn('tc.class_section_id', $sectionIds)
->where('tc.school_year', $schoolYear);
if ($requireSemester) {
$sem = trim($semester);
if ($sem !== '') {
$q->whereRaw('TRIM(tc.semester) = ?', [$sem]);
}
}
return $q->orderByRaw("CASE tc.position WHEN 'main' THEN 0 WHEN 'ta' THEN 1 ELSE 2 END")
->orderBy('u.firstname', 'asc')
->get()
->map(fn ($r) => (array) $r)
@@ -301,10 +348,15 @@ class TeacherClass extends BaseModel
}
/** CI: assignedMapForSectionTerm() */
public static function assignedMapForSectionTerm(int $sectionCode, string $semester, string $schoolYear): array
{
public static function assignedMapForSectionTerm(
int $sectionCode,
string $semester,
string $schoolYear,
?int $alsoSectionCode = null,
bool $requireSemester = true,
): array {
$out = [];
foreach (static::assignedForSectionTerm($sectionCode, $semester, $schoolYear) as $r) {
foreach (static::assignedForSectionTerm($sectionCode, $semester, $schoolYear, $alsoSectionCode, $requireSemester) as $r) {
$out[(int) $r['teacher_id']] = $r;
}
return $out;
+56
View File
@@ -97,6 +97,62 @@ class User extends Authenticatable implements JWTSubject
->all();
}
/**
* Resolve the primary teacher class section to persist in auth/session payloads.
*
* @return array{class_section_id: ?int, class_section_name: ?string}
*/
public function teacherSessionContext(): array
{
$empty = [
'class_section_id' => null,
'class_section_name' => null,
];
$roles = array_map(
static fn ($role) => strtolower(trim((string) $role)),
$this->roleNamesLikeCodeIgniter(),
);
$isTeacherScoped = in_array('teacher', $roles, true)
|| in_array('teacher_assistant', $roles, true)
|| in_array('ta', $roles, true);
if (! $isTeacherScoped) {
return $empty;
}
$schoolYear = trim((string) (Configuration::getConfig('school_year') ?? ''));
$semester = trim((string) (Configuration::getConfig('semester') ?? ''));
$assignments = TeacherClass::getClassAssignmentsByUserId(
(int) $this->id,
$schoolYear !== '' ? $schoolYear : null,
$semester !== '' ? $semester : null,
);
if ($assignments === []) {
$assignments = TeacherClass::getClassAssignmentsByUserId(
(int) $this->id,
null,
$semester !== '' ? $semester : null,
);
}
$primary = $assignments[0] ?? null;
if (! is_array($primary)) {
return $empty;
}
$classSectionId = (int) ($primary['class_section_id'] ?? 0);
$classSectionName = trim((string) ($primary['class_section_name'] ?? ''));
return [
'class_section_id' => $classSectionId > 0 ? $classSectionId : null,
'class_section_name' => $classSectionName !== '' ? $classSectionName : null,
];
}
/* ============================================================
* Relationships
* ============================================================