reconstruction of the project
This commit is contained in:
@@ -0,0 +1,285 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Administrator;
|
||||
|
||||
use App\Models\AttendanceDay;
|
||||
use App\Models\ScoreComment;
|
||||
use App\Models\SemesterScore;
|
||||
use App\Models\TeacherSubmissionNotificationHistory;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class TeacherSubmissionReportService
|
||||
{
|
||||
public function __construct(
|
||||
protected AdministratorSharedService $shared,
|
||||
protected TeacherSubmissionSupportService $support
|
||||
) {
|
||||
}
|
||||
|
||||
public function report(): array
|
||||
{
|
||||
$semester = $this->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)
|
||||
->where('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);
|
||||
|
||||
$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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user