fix teacher pages display between school years
Tests / PHPUnit (push) Failing after 1m12s

This commit is contained in:
root
2026-07-15 20:52:19 -04:00
parent 5f27dccd0f
commit 9de2ab2a9f
9 changed files with 106 additions and 53 deletions
@@ -54,13 +54,10 @@ class SendExamDraftDeadlineReminders extends BaseCommand
$db = Database::connect();
$teacherClassRows = $db->table('teacher_class')
->select('teacher_id, class_section_id, school_year, semester')
->select('teacher_id, class_section_id, school_year')
->when($schoolYear !== '', static function ($builder) use ($schoolYear) {
return $builder->where('school_year', $schoolYear);
})
->when($semester !== '', static function ($builder) use ($semester) {
return $builder->where('semester', $semester);
})
->get()
->getResultArray();
+11 -1
View File
@@ -57,6 +57,7 @@ class LandingPageController extends BaseController
// Fetch Enrollment and Refund Deadlines from Configuration
$this->schoolYear = $this->configModel->getConfig('school_year');
$this->semester = $this->configModel->getConfig('semester');
$this->schoolYear = $this->selectedSchoolYearName((string) ($this->schoolYear ?? ''));
$this->lastDayOfRegistration = $this->configModel->getConfig('enrollment_deadline') ?? 'Not set';
$this->refundDeadline = $this->configModel->getConfig('refund_deadline') ?? 'Not set';
@@ -103,7 +104,7 @@ class LandingPageController extends BaseController
// Get all class assignments for this teacher in the current term
$assignments = $this->teacherClassModel->getClassAssignmentsByUserId(
(int)$user_id,
(string)$this->schoolYear,
$this->selectedSchoolYearName((string) ($this->schoolYear ?? '')),
(string)$this->semester
);
@@ -126,6 +127,15 @@ class LandingPageController extends BaseController
return $chosen;
}
private function selectedSchoolYearName(string $fallback): string
{
try {
return service('schoolYearContext')->resolve(service('request'))->yearName();
} catch (\Throwable) {
return $fallback;
}
}
public function administrator()
{
+4 -8
View File
@@ -1673,14 +1673,10 @@ class StudentController extends BaseController
$students = [];
if (in_array($role, ['parent', 'parent_dashboard'], true)) {
$schoolYear = $this->currentSchoolYearName((string) ($this->schoolYear ?? ''));
$parentId = (int)(session()->get('user_id') ?? 0);
if ($parentId > 0) {
$students = $this->studentModel
->select('id, school_id, firstname, lastname')
->where('parent_id', $parentId)
->orderBy('lastname', 'ASC')
->orderBy('firstname', 'ASC')
->findAll();
if ($parentId > 0 && $schoolYear !== '') {
$students = $this->studentModel->getByParentAndYear($parentId, $schoolYear);
}
} elseif (in_array($role, ['teacher', 'teacher_assistant', 'teacher_dashboard'], true)) {
$schoolYear = $this->currentSchoolYearName((string) ($this->schoolYear ?? ''));
@@ -1706,7 +1702,7 @@ class StudentController extends BaseController
)), static fn($v) => $v > 0));
if (!empty($sectionIds)) {
$studentClassModel = new \App\Models\StudentClassModel();
$rows = $studentClassModel->getStudentsByClassSectionIds($sectionIds);
$rows = $studentClassModel->getStudentsByClassSectionIds($sectionIds, $schoolYear);
$unique = [];
foreach ($rows as $r) {
$sid = (int)($r['student_id'] ?? 0);
+2 -2
View File
@@ -57,6 +57,7 @@ class TeacherController extends BaseController
// Retrieve the configuration values
$this->semester = $this->configModel->getConfig('semester');
$this->schoolYear = $this->configModel->getConfig('school_year');
$this->schoolYear = $this->currentSchoolYearName((string) ($this->schoolYear ?? ''));
}
@@ -123,7 +124,7 @@ class TeacherController extends BaseController
if (!empty($classSectionIds)) {
// 1) Fetch all students for the selected class sections
$students = $this->studentClassModel->getStudentsByClassSectionIds($classSectionIds);
$students = $this->studentClassModel->getStudentsByClassSectionIds($classSectionIds, (string) $this->schoolYear);
if (!empty($students)) {
// 2) Collect unique student IDs
@@ -344,7 +345,6 @@ class TeacherController extends BaseController
'section_id' => $sectionId,
'class_section_name' => $classNames[$sectionId] ?? 'N/A',
'role' => $role,
'semester' => (string)($assign['semester'] ?? $this->semester ?? ''),
'school_year' => (string)($assign['school_year'] ?? $schoolYear),
];
}
@@ -8,13 +8,20 @@ class RemoveClassAssignmentSemester extends Migration
{
public function up()
{
// Keep the legacy semester columns in place. They may be ignored by newer
// code, but dropping them during a post-restore migrate destroys data.
if (
$this->db->tableExists('teacher_class')
&& $this->db->fieldExists('semester', 'teacher_class')
) {
$this->forge->dropColumn('teacher_class', 'semester');
}
}
public function down()
{
if ($this->db->tableExists('teacher_class')) {
if (
$this->db->tableExists('teacher_class')
&& ! $this->db->fieldExists('semester', 'teacher_class')
) {
$this->forge->addColumn('teacher_class', [
'semester' => [
'type' => 'VARCHAR',
@@ -24,16 +31,6 @@ class RemoveClassAssignmentSemester extends Migration
],
]);
}
if ($this->db->tableExists('student_class')) {
$this->forge->addColumn('student_class', [
'semester' => [
'type' => 'VARCHAR',
'constraint' => 255,
'null' => false,
'default' => '',
],
]);
}
}
private function indexExists(string $table, string $index): bool
+19
View File
@@ -314,6 +314,25 @@ class StudentModel extends Model
->findAll();
}
public function getByParentAndYear(int $parentId, string $schoolYear): array
{
$schoolYear = trim($schoolYear);
if ($parentId <= 0 || $schoolYear === '') {
return [];
}
return $this->select('students.id, students.school_id, students.firstname, students.lastname')
->join('student_class', 'student_class.student_id = students.id', 'inner')
->where('students.parent_id', $parentId)
->where('students.is_active', 1)
->where('student_class.school_year', $schoolYear)
->groupBy('students.id, students.school_id, students.firstname, students.lastname')
->orderBy('students.lastname', 'ASC')
->orderBy('students.firstname', 'ASC')
->findAll();
}
public function getSchoolIdByStudentId($studentId)
{
return $this->select('school_id')
+50 -6
View File
@@ -68,8 +68,15 @@ class TeacherClassModel extends Model
public function getClassAssignmentsByUserId(int $userId, ?string $schoolYear = null, ?string $semester = null): array
{
$hasSectionSchoolYear = $this->db->fieldExists('school_year', 'classSection');
$sectionJoin = 'tc.class_section_id = cs.class_section_id';
if ($schoolYear && $hasSectionSchoolYear) {
$sectionJoin .= ' AND cs.school_year = ' . $this->db->escape($schoolYear);
}
$builder = $this->db->table('teacher_class tc')
->select([
'tc.class_section_id AS teacher_class_section_id',
'cs.class_section_name',
'cs.class_section_id AS class_section_pk',
'cs.class_section_id',
@@ -79,22 +86,28 @@ class TeacherClassModel extends Model
'tc.position',
'tc.school_year',
])
->join('classSection cs', 'tc.class_section_id = cs.class_section_id', 'inner')
->join('classSection cs', $sectionJoin, 'left', false)
->join('classes c', 'cs.class_id = c.id', 'left')
->where('tc.teacher_id', $userId)
->where('tc.class_section_id IS NOT NULL', null, false)
->orderBy('cs.class_section_name', 'ASC');
->orderBy('COALESCE(cs.class_section_name, tc.class_section_id)', 'ASC', false);
if ($schoolYear) $builder->where('tc.school_year', $schoolYear);
if ($schoolYear) {
$builder->where('tc.school_year', $schoolYear);
}
$rows = $builder->get()->getResultArray();
$out = [];
foreach ($rows as $r) {
$sectionId = (int) ($r['teacher_class_section_id'] ?? $r['class_section_id'] ?? 0);
$sectionName = $r['class_section_name']
?? $this->fallbackClassSectionName($sectionId, $schoolYear);
$out[] = [
'class_section_pk' => (int)$r['class_section_pk'],
'class_section_id' => (int)$r['class_section_id'],
'class_section_name' => $r['class_section_name'],
'class_section_pk' => (int)($r['class_section_pk'] ?? $sectionId),
'class_section_id' => $sectionId,
'class_section_name' => $sectionName,
'class_id' => isset($r['class_id']) ? (int)$r['class_id'] : null,
'class_name' => $r['class_name'] ?? null,
'teacher_id' => (int)$r['teacher_id'],
@@ -107,6 +120,37 @@ class TeacherClassModel extends Model
return $out;
}
private function fallbackClassSectionName(int $classSectionId, ?string $schoolYear = null): string
{
if ($classSectionId <= 0) {
return 'Class';
}
if ($schoolYear && $this->db->fieldExists('school_year', 'classSection')) {
$row = $this->db->table('classSection')
->select('class_section_name')
->where('class_section_id', $classSectionId)
->where('school_year', $schoolYear)
->get()
->getRowArray();
if (!empty($row['class_section_name'])) {
return (string) $row['class_section_name'];
}
}
$row = $this->db->table('classSection')
->select('class_section_name')
->where('class_section_id', $classSectionId)
->orderBy('id', 'DESC')
->get()
->getRowArray();
return !empty($row['class_section_name'])
? (string) $row['class_section_name']
: ('Class ' . $classSectionId);
}
public function getClassSectionsByTeacherId($teacherId)
{
$builder = $this->db->table('teacher_class')
@@ -30,13 +30,6 @@
</option>
<?php endforeach; ?>
</select>
<?php $semVal = (string)($semester ?? ($_GET['semester'] ?? '')); ?>
<label for="tcaSemesterSelect" class="col-form-label">Semester</label>
<select id="tcaSemesterSelect" name="semester" class="form-select form-select-sm" style="min-width: 140px;">
<option value="">—</option>
<option value="Fall" <?= (strcasecmp($semVal,'Fall')===0?'selected':'') ?>>Fall</option>
<option value="Spring" <?= (strcasecmp($semVal,'Spring')===0?'selected':'') ?>>Spring</option>
</select>
<button type="submit" class="btn btn-secondary btn-sm">Apply</button>
</form>
<?php if (isset($isCurrentYear) && !$isCurrentYear): ?>
@@ -183,9 +176,7 @@ document.addEventListener('DOMContentLoaded', function () {
position = label.toLowerCase() === 'ta' ? 'ta' : 'main';
}
btn.setAttribute('data-position', position);
var assignmentSemester = assignment.semester || '';
var assignmentSchoolYear = assignment.school_year || selectedYear || '';
btn.setAttribute('data-semester', assignmentSemester);
btn.setAttribute('data-school-year', assignmentSchoolYear);
li.appendChild(btn);
@@ -488,7 +479,6 @@ document.addEventListener('DOMContentLoaded', function () {
var teacherId = removeBtn.getAttribute('data-teacher-id');
var classSectionId = removeBtn.getAttribute('data-class-section-id');
var position = removeBtn.getAttribute('data-position');
var semester = removeBtn.getAttribute('data-semester') || '';
var schoolYear = removeBtn.getAttribute('data-school-year') || '';
var className = removeBtn.getAttribute('data-class-name') || 'this class';
var teacherName = removeBtn.getAttribute('data-teacher-name') || 'this teacher';
@@ -498,7 +488,6 @@ document.addEventListener('DOMContentLoaded', function () {
teacher_id: teacherId,
class_section_id: classSectionId,
position: position,
semester: semester,
school_year: schoolYear
});
}
+9 -8
View File
@@ -49,14 +49,15 @@ switch ($role) {
try {
$studentModel = new \App\Models\StudentModel();
if (in_array($role, ['parent', 'parent_dashboard'], true)) {
$configModel = new \App\Models\ConfigurationModel();
try {
$schoolYear = service('schoolYearContext')->resolve(service('request'))->yearName();
} catch (\Throwable $e) {
$schoolYear = session()->get('school_year') ?? $configModel->getConfig('school_year');
}
$parentId = (int)(session()->get('user_id') ?? 0);
if ($parentId > 0) {
$scoreCardStudents = $studentModel
->select('id, school_id, firstname, lastname')
->where('parent_id', $parentId)
->orderBy('lastname', 'ASC')
->orderBy('firstname', 'ASC')
->findAll();
if ($parentId > 0 && !empty($schoolYear)) {
$scoreCardStudents = $studentModel->getByParentAndYear($parentId, (string) $schoolYear);
}
} else {
$configModel = new \App\Models\ConfigurationModel();
@@ -85,7 +86,7 @@ switch ($role) {
)), static fn($v) => $v > 0));
if (!empty($sectionIds)) {
$studentClassModel = new \App\Models\StudentClassModel();
$rows = $studentClassModel->getStudentsByClassSectionIds($sectionIds);
$rows = $studentClassModel->getStudentsByClassSectionIds($sectionIds, (string) $schoolYear);
$unique = [];
foreach ($rows as $r) {
$sid = (int)($r['student_id'] ?? 0);