shared->getSemester(); $schoolYear = $this->shared->getSchoolYear(); $assignmentRows = DB::table('teacher_class as tc') ->select([ 'tc.class_section_id', 'cs.class_section_name', 'tc.teacher_id', 'u.firstname', 'u.lastname', 'tc.position', ]) ->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) ->where('tc.semester', $semester) ->orderBy('cs.class_section_name') ->get() ->map(fn ($r) => (array) $r) ->all(); $teachersBySection = []; foreach ($assignmentRows as $assignment) { $sectionId = (int) ($assignment['class_section_id'] ?? 0); if ($sectionId <= 0) { continue; } $positionKey = strtolower(trim((string) ($assignment['position'] ?? ''))); $roleKey = $positionKey !== '' ? $positionKey : 'teacher'; $positionLabel = match ($roleKey) { 'ta' => 'TA', 'main' => 'Main', default => $roleKey !== '' ? ucfirst($roleKey) : 'Teacher', }; $teacherFullName = trim(($assignment['firstname'] ?? '') . ' ' . ($assignment['lastname'] ?? '')); $teacherId = (int) ($assignment['teacher_id'] ?? 0); if ($teacherFullName === '' || $teacherId <= 0) { continue; } if (!isset($teachersBySection[$sectionId])) { $teachersBySection[$sectionId] = [ 'class_section' => $assignment['class_section_name'] ?? "Section {$sectionId}", 'teachers' => [], ]; } $teachersBySection[$sectionId]['teachers'][] = [ 'id' => $teacherId, 'label' => "{$positionLabel}: {$teacherFullName}", 'role_key' => $roleKey, ]; } $today = now()->format('Y-m-d'); $rows = []; $totalStatuses = 0; $missingItemCount = 0; $allTeacherIds = []; $allClassSectionIds = []; foreach ($teachersBySection as $classSectionId => $section) { $classSectionId = (int) $classSectionId; if ($classSectionId <= 0) { continue; } $studentIds = DB::table('student_class') ->where('class_section_id', $classSectionId) ->where('semester', $semester) ->where('school_year', $schoolYear) ->pluck('student_id') ->map(fn ($id) => (int) $id) ->filter() ->values() ->all(); $expected = count($studentIds); $midtermStudents = []; $participationStudents = []; $scoreRecords = SemesterScore::query() ->where('class_section_id', $classSectionId) ->where('semester', $semester) ->where('school_year', $schoolYear) ->get(); foreach ($scoreRecords as $score) { $sid = (int) ($score->student_id ?? 0); if ($sid <= 0 || ($expected > 0 && !in_array($sid, $studentIds, true))) { continue; } if (trim((string) ($score->midterm_exam_score ?? '')) !== '') { $midtermStudents[$sid] = true; } if (trim((string) ($score->participation_score ?? '')) !== '') { $participationStudents[$sid] = true; } } $midtermCommentStudents = []; $ptapCommentStudents = []; if (!empty($studentIds)) { $comments = ScoreComment::query() ->select('student_id', 'score_type', 'comment') ->whereIn('student_id', $studentIds) ->where('semester', $semester) ->where('school_year', $schoolYear) ->whereIn('score_type', ['midterm', 'ptap']) ->get(); foreach ($comments as $comment) { $sid = (int) ($comment->student_id ?? 0); if ($sid <= 0) { continue; } $text = trim((string) ($comment->comment ?? '')); if ($text === '') { continue; } $type = strtolower(trim((string) ($comment->score_type ?? ''))); if ($type === 'midterm') { $midtermCommentStudents[$sid] = true; } if ($type === 'ptap') { $ptapCommentStudents[$sid] = true; } } } $attendanceRow = AttendanceDay::query() ->where('class_section_id', $classSectionId) ->where('semester', $semester) ->where('school_year', $schoolYear) ->whereDate('date', $today) ->first(); $attendanceSubmitted = $attendanceRow && in_array(strtolower((string) ($attendanceRow->status ?? '')), ['submitted', 'published', 'finalized'], true); $teacherList = $section['teachers'] ?? []; usort( $teacherList, fn ($a, $b) => $this->support->teacherRolePriority($a['role_key'] ?? 'teacher') <=> $this->support->teacherRolePriority($b['role_key'] ?? 'teacher') ); foreach ($teacherList as $teacherEntry) { if (!empty($teacherEntry['id'])) { $allTeacherIds[] = $teacherEntry['id']; } } $allClassSectionIds[] = $classSectionId; $midtermScoreStatus = $this->support->submissionStatus(count($midtermStudents), $expected); $midtermCommentStatus = $this->support->submissionStatus(count($midtermCommentStudents), $expected); $participationStatus = $this->support->submissionStatus(count($participationStudents), $expected); $ptapCommentStatus = $this->support->submissionStatus(count($ptapCommentStudents), $expected); $attendanceStatus = $this->support->attendanceStatus($attendanceSubmitted, $expected); $statusDetails = [ 'midterm_score_status' => $midtermScoreStatus, 'midterm_comment_status' => $midtermCommentStatus, 'participation_status' => $participationStatus, 'ptap_comment_status' => $ptapCommentStatus, 'attendance_status' => $attendanceStatus, ]; $missingItemsForSection = $this->support->buildMissingItems($statusDetails); $missingItemCount += count($missingItemsForSection); $totalStatuses += count($statusDetails); $rows[] = [ 'class_section' => $section['class_section'] ?? "Section {$classSectionId}", 'class_section_id' => $classSectionId, 'teachers' => array_values($teacherList), 'midterm_score_status' => $midtermScoreStatus, 'midterm_comment_status' => $midtermCommentStatus, 'participation_status' => $participationStatus, 'ptap_comment_status' => $ptapCommentStatus, 'attendance_status' => $attendanceStatus, 'missing_items' => $missingItemsForSection, 'student_count' => $expected, ]; } $historyMap = $this->notificationHistoryMap($allTeacherIds, $allClassSectionIds); $summary = [ 'total_items' => $totalStatuses, 'missing_items' => $missingItemCount, 'submitted_items' => max(0, $totalStatuses - $missingItemCount), 'submission_percentage' => $totalStatuses > 0 ? (int) round((($totalStatuses - $missingItemCount) / $totalStatuses) * 100) : 100, ]; return [ 'rows' => $rows, 'semester' => $semester, 'schoolYear' => $schoolYear, 'notificationHistory' => $historyMap, 'summary' => $summary, ]; } protected function notificationHistoryMap(array $allTeacherIds, array $allClassSectionIds): array { $historyMap = []; $teacherIds = array_values(array_unique($allTeacherIds)); $classSectionIds = array_values(array_unique($allClassSectionIds)); if (empty($teacherIds) || empty($classSectionIds)) { return $historyMap; } $historyRecords = TeacherSubmissionNotificationHistory::query() ->select('teacher_submission_notification_history.*', 'u.firstname', 'u.lastname') ->leftJoin('users as u', 'u.id', '=', 'teacher_submission_notification_history.admin_id') ->where('notification_category', 'teacher_submissions') ->whereIn('teacher_submission_notification_history.teacher_id', $teacherIds) ->whereIn('teacher_submission_notification_history.class_section_id', $classSectionIds) ->orderByDesc('sent_at') ->get(); foreach ($historyRecords as $record) { $sectionId = (int) ($record->class_section_id ?? 0); $teacherId = (int) ($record->teacher_id ?? 0); if ($sectionId <= 0 || $teacherId <= 0) { continue; } $adminName = trim(($record->firstname ?? '') . ' ' . ($record->lastname ?? '')); if ($adminName === '') { $adminName = 'Administrator'; } $historyMap[$sectionId][$teacherId][] = [ 'sent_at_text' => $record->sent_at ? Carbon::parse($record->sent_at)->format('M j, Y g:i A') : '', 'admin_name' => $adminName, 'status' => strtolower((string) ($record->status ?? 'sent')), ]; } foreach ($historyMap as &$teachersHistory) { foreach ($teachersHistory as &$entries) { $entries = array_slice($entries, 0, 3); } } return $historyMap; } }