calendarService->buildDateRange($schoolYear, $semester); $sundays = $this->calendarService->buildSundays($start, $end); $eventDays = $this->calendarService->eventDays($schoolYear); $dateToIndex = $this->calendarService->dateToIndex($sundays, $eventDays); $limitToSemester = $this->hasTeacherAssignments($schoolYear); $homeworkByIndex = $this->loadHomeworkByIndex($schoolYear, $semester, $limitToSemester); $homeworkByDate = $this->loadHomeworkByDate($schoolYear, $semester, $limitToSemester, $sundays, $eventDays); $teachers = $this->loadTeachers($schoolYear); $perPage = 8; $totalRows = count($teachers); $totalPages = max(1, (int) ceil($totalRows / $perPage)); $page = max(1, min($page, $totalPages)); $offset = ($page - 1) * $perPage; $teachersPage = array_slice($teachers, $offset, $perPage); return [ 'semester' => $semester, 'school_year' => $schoolYear, 'sundays' => $sundays, 'event_days' => $eventDays, 'date_to_index' => $dateToIndex, 'teachers' => $teachersPage, 'has_homework' => $homeworkByIndex['has_homework'], 'hw_entered_at' => $homeworkByIndex['entered_at'], 'has_homework_by_date' => $homeworkByDate['has_homework'], 'hw_entered_at_by_date' => $homeworkByDate['entered_at'], 'page' => $page, 'total_pages' => $totalPages, 'per_page' => $perPage, 'total_rows' => $totalRows, ]; } private function hasTeacherAssignments(string $schoolYear): bool { $year = trim((string) $schoolYear); if ($year === '') { return false; } if (array_key_exists($year, $this->teacherAssignmentCache)) { return $this->teacherAssignmentCache[$year]; } $cnt = DB::table('teacher_class')->where('school_year', $year)->count(); $this->teacherAssignmentCache[$year] = $cnt > 0; return $this->teacherAssignmentCache[$year]; } private function loadHomeworkByIndex(string $schoolYear, string $semester, bool $limitToSemester): array { $query = DB::table('homework') ->select('class_section_id', 'homework_index', DB::raw('MIN(created_at) as first_created'), DB::raw('COUNT(*) as cnt')) ->where('school_year', $schoolYear); if ($limitToSemester && $semester !== '') { $query->where('semester', $semester); } $rows = $query->groupBy('class_section_id', 'homework_index')->get(); $hasHomework = []; $enteredAt = []; foreach ($rows as $row) { $csid = (int) $row->class_section_id; $hi = (int) $row->homework_index; $cnt = (int) $row->cnt; if ($csid > 0 && $hi > 0 && $cnt > 0) { $hasHomework[$csid][$hi] = true; $dateStr = substr((string) ($row->first_created ?? ''), 0, 10); $enteredAt[$csid][$hi] = $dateStr ?: null; } } return ['has_homework' => $hasHomework, 'entered_at' => $enteredAt]; } private function loadHomeworkByDate(string $schoolYear, string $semester, bool $limitToSemester, array $sundays, array $eventDays): array { $query = DB::table('homework') ->select(DB::raw('class_section_id, DATE(created_at) as hw_date, MIN(created_at) as first_created, COUNT(*) as cnt')) ->where('school_year', $schoolYear); if ($limitToSemester && $semester !== '') { $query->where('semester', $semester); } $rows = $query ->groupBy('class_section_id', DB::raw('DATE(created_at)')) ->orderBy('hw_date', 'ASC') ->get(); $hasHomework = []; $enteredAt = []; foreach ($rows as $row) { $csid = (int) $row->class_section_id; $date = substr((string) ($row->hw_date ?? ''), 0, 10); $cnt = (int) $row->cnt; $firstCreated = substr((string) ($row->first_created ?? ''), 0, 10); if ($csid <= 0 || !$date || $cnt <= 0) { continue; } $baseIndex = -1; for ($i = count($sundays) - 1; $i >= 0; $i--) { if ($sundays[$i] <= $date) { $baseIndex = $i; break; } } if ($baseIndex < 0) { continue; } $j = $baseIndex; while ($j >= 0 && !empty($eventDays[$sundays[$j]])) { $j--; } if ($j < 0) { continue; } $sunday = $sundays[$j]; $hasHomework[$csid][$sunday] = true; $candidate = $firstCreated ?: $date; if (empty($enteredAt[$csid][$sunday]) || ($candidate && $candidate < $enteredAt[$csid][$sunday])) { $enteredAt[$csid][$sunday] = $candidate; } } return ['has_homework' => $hasHomework, 'entered_at' => $enteredAt]; } private function loadTeachers(string $schoolYear): array { $rows = DB::table('teacher_class as tc') ->select('tc.class_section_id', 'tc.position', 'cs.class_section_name', 'cs.class_id', 'u.firstname', 'u.lastname') ->leftJoin('classSection as cs', 'cs.class_section_id', '=', 'tc.class_section_id') ->leftJoin('users as u', 'u.id', '=', 'tc.teacher_id') ->where('tc.school_year', $schoolYear) ->whereNotNull('tc.class_section_id') ->whereIn('tc.position', ['main', 'ta']) ->orderBy('cs.class_id', 'ASC') ->orderBy('cs.class_section_name', 'ASC') ->orderByRaw("CASE tc.position WHEN 'main' THEN 0 WHEN 'ta' THEN 1 ELSE 2 END") ->orderBy('u.firstname', 'ASC') ->get(); $bySection = []; foreach ($rows as $row) { $sid = (int) $row->class_section_id; if ($sid <= 0) { continue; } if (!isset($bySection[$sid])) { $bySection[$sid] = [ 'class_section_id' => $sid, 'class_id' => (int) ($row->class_id ?? 0), 'class_section_name' => (string) ($row->class_section_name ?? ''), 'teachers' => [], 'tas' => [], ]; } $name = trim((string) ($row->firstname ?? '') . ' ' . (string) ($row->lastname ?? '')); $pos = strtolower((string) ($row->position ?? '')); if ($name !== '') { if ($pos === 'main') { $bySection[$sid]['teachers'][] = $name; } elseif ($pos === 'ta') { $bySection[$sid]['tas'][] = $name; } } } $teachers = array_values($bySection); usort($teachers, function ($a, $b) { $ai = (int) ($a['class_id'] ?? 0); $bi = (int) ($b['class_id'] ?? 0); $order = function (int $cid): int { if ($cid === 13) return 0; if ($cid >= 1 && $cid <= 11) return $cid; if ($cid === 12) return 99; return 200 + $cid; }; $cmp = $order($ai) <=> $order($bi); if ($cmp !== 0) { return $cmp; } return strnatcasecmp($a['class_section_name'] ?? '', $b['class_section_name'] ?? ''); }); return $teachers; } }