diff --git a/app/Http/Requests/ApiFormRequest.php b/app/Http/Requests/ApiFormRequest.php index b1266d21..4137d30a 100644 --- a/app/Http/Requests/ApiFormRequest.php +++ b/app/Http/Requests/ApiFormRequest.php @@ -16,6 +16,7 @@ abstract class ApiFormRequest extends FormRequest return array_merge( $this->query->all(), $this->request->all(), + $this->allFiles(), $this->json()->all(), $json ); diff --git a/app/Http/Requests/Exams/ExamDraftAdminLegacyRequest.php b/app/Http/Requests/Exams/ExamDraftAdminLegacyRequest.php index 03396aa7..ac73d50a 100644 --- a/app/Http/Requests/Exams/ExamDraftAdminLegacyRequest.php +++ b/app/Http/Requests/Exams/ExamDraftAdminLegacyRequest.php @@ -10,10 +10,10 @@ class ExamDraftAdminLegacyRequest extends ApiFormRequest { return [ 'class_section_id' => ['required', 'integer', 'min:1'], - 'school_year' => ['required', 'string'], - 'semester' => ['required', 'string'], + 'school_year' => ['nullable', 'string'], + 'semester' => ['nullable', 'string'], 'exam_type' => ['nullable', 'string', 'max:50'], - 'old_exam_file' => ['required', 'file', 'mimes:doc,docx,pdf', 'max:12288'], + 'old_exam_file' => ['required', 'file', 'extensions:doc,docx,pdf', 'max:12288'], ]; } } diff --git a/app/Services/Attendance/AttendanceQueryService.php b/app/Services/Attendance/AttendanceQueryService.php index 3312bb35..778e1729 100644 --- a/app/Services/Attendance/AttendanceQueryService.php +++ b/app/Services/Attendance/AttendanceQueryService.php @@ -449,15 +449,38 @@ class AttendanceQueryService public function buildDailyAttendanceData(string $termSemester, string $termYear): array { - $classSections = $this->classSection - ->query() - ->select('classSection.id', 'classSection.class_id', 'classSection.class_section_id', 'classSection.class_section_name') - ->join('student_class as sc', 'sc.class_section_id', '=', 'classSection.class_section_id') - ->where('sc.school_year', $termYear) - ->groupBy('classSection.id', 'classSection.class_id', 'classSection.class_section_id', 'classSection.class_section_name') - ->get() - ->map(fn($row) => (array)$row) - ->all(); + $effectiveTermYear = $termYear; + + $loadClassSections = function (string $schoolYear): array { + if ($schoolYear === '') { + return []; + } + + return $this->classSection + ->query() + ->select('classSection.id', 'classSection.class_id', 'classSection.class_section_id', 'classSection.class_section_name') + ->join('student_class as sc', 'sc.class_section_id', '=', 'classSection.class_section_id') + ->where('sc.school_year', $schoolYear) + ->groupBy('classSection.id', 'classSection.class_id', 'classSection.class_section_id', 'classSection.class_section_name') + ->get() + ->map(fn($row) => $row->toArray()) + ->all(); + }; + + $classSections = $loadClassSections($effectiveTermYear); + + if ($classSections === []) { + $fallbackYear = (string) DB::table('student_class') + ->whereNotNull('school_year') + ->where('school_year', '<>', '') + ->orderByDesc('school_year') + ->value('school_year'); + + if ($fallbackYear !== '' && $fallbackYear !== $effectiveTermYear) { + $effectiveTermYear = $fallbackYear; + $classSections = $loadClassSections($effectiveTermYear); + } + } $attendanceData = []; $attendanceRecord = []; @@ -466,7 +489,7 @@ class AttendanceQueryService $datesBySection = []; $studentSchoolMap = []; - $sectionCounts = $this->studentClass->getStudentCountsBySection($termYear); + $sectionCounts = $this->studentClass->getStudentCountsBySection($effectiveTermYear); foreach ($classSections as $classSection) { $secPk = (int)($classSection['id'] ?? 0); @@ -483,9 +506,9 @@ class AttendanceQueryService $countForPk = (int)($sectionCounts[$secPk] ?? 0); $sectionHasStudents = ($countForCode + $countForPk) > 0; - $students = $this->studentClass->getClassStudents($secCode, $termYear); + $students = $this->studentClass->getClassStudents($secCode, $effectiveTermYear); if (!$students && $secPk && (string)$secPk !== (string)$secCode) { - $students = $this->studentClass->getClassStudents($secPk, $termYear); + $students = $this->studentClass->getClassStudents($secPk, $effectiveTermYear); } if (!$sectionHasStudents || !$students) { @@ -522,7 +545,7 @@ class AttendanceQueryService } }) ->when($termSemester !== '', fn($q) => $q->where('semester', $termSemester)) - ->when($termYear !== '', fn($q) => $q->where('school_year', $termYear)) + ->when($effectiveTermYear !== '', fn($q) => $q->where('school_year', $effectiveTermYear)) ->orderBy('date') ->get() ->map(fn($row) => $row->toArray()) @@ -547,7 +570,7 @@ class AttendanceQueryService } }) ->when($termSemester !== '', fn($q) => $q->where('semester', $termSemester)) - ->when($termYear !== '', fn($q) => $q->where('school_year', $termYear)) + ->when($effectiveTermYear !== '', fn($q) => $q->where('school_year', $effectiveTermYear)) ->first(); $attendanceRecord[$secCode][$studentId] = $summary?->toArray() ?? [ @@ -581,11 +604,11 @@ class AttendanceQueryService ksort($grades, SORT_NUMERIC); - [$rangeStart, $rangeEnd] = $this->semesterRangeService->getSchoolYearRange($termYear); + [$rangeStart, $rangeEnd] = $this->semesterRangeService->getSchoolYearRange($effectiveTermYear); $semesterNorm = $this->semesterRangeService->normalizeSemester($termSemester); if ($semesterNorm !== '') { - $semRange = $this->semesterRangeService->getSemesterRange($termYear, $semesterNorm); + $semRange = $this->semesterRangeService->getSemesterRange($effectiveTermYear, $semesterNorm); if ($semRange) { [$rangeStart, $rangeEnd] = $semRange; } @@ -621,7 +644,7 @@ class AttendanceQueryService $totalPassedDays = count($passedDatesSet); - if ($totalPassedDays > 0 && $termYear !== '' && $termSemester !== '') { + if ($totalPassedDays > 0 && $effectiveTermYear !== '' && $termSemester !== '') { foreach ($attendanceData as $secCode => $studentEntries) { foreach ($studentEntries as $studentId => $entries) { $statusByDate = []; @@ -663,7 +686,7 @@ class AttendanceQueryService [ 'student_id' => $studentId, 'semester' => $termSemester, - 'school_year' => $termYear, + 'school_year' => $effectiveTermYear, ], [ 'class_section_id' => $secCode, @@ -705,7 +728,7 @@ class AttendanceQueryService 'noSchoolDays' => $noSchoolDays, 'totalPassedDays' => $totalPassedDays, 'semester' => $termSemester, - 'schoolYear' => $termYear, + 'schoolYear' => $effectiveTermYear, 'currentAdminName' => $adminName, ]; } @@ -876,4 +899,4 @@ class AttendanceQueryService return ''; } } -} \ No newline at end of file +} diff --git a/app/Services/Exams/ExamDraftAdminService.php b/app/Services/Exams/ExamDraftAdminService.php index 5bbade1e..79d63c07 100644 --- a/app/Services/Exams/ExamDraftAdminService.php +++ b/app/Services/Exams/ExamDraftAdminService.php @@ -37,6 +37,18 @@ class ExamDraftAdminService $classSections = ClassSection::query() ->select('class_section_id', 'class_section_name') + ->whereExists(function ($query) use ($context) { + $query->selectRaw('1') + ->from('student_class as sc') + ->join('students as s', 's.id', '=', 'sc.student_id') + ->whereColumn('sc.class_section_id', 'classSection.class_section_id') + ->where('s.is_active', 1); + + $schoolYear = (string) ($context['school_year'] ?? ''); + if ($schoolYear !== '') { + $query->where('sc.school_year', $schoolYear); + } + }) ->orderBy('class_section_name') ->get() ->toArray(); @@ -95,6 +107,22 @@ class ExamDraftAdminService return ['ok' => false, 'message' => 'File type not allowed or upload failed.']; } + $pdfName = $stored['extension'] === 'pdf' + ? $stored['stored'] + : $this->fileService->ensurePdfExists( + $stored['stored'], + $stored['extension'], + ExamDraftConfigService::FINAL_UPLOAD_DIR + ); + + if ($pdfName === null) { + return ['ok' => false, 'message' => 'Unable to convert the uploaded exam to PDF.']; + } + + $finalFilename = $stored['extension'] === 'pdf' + ? $stored['original'] + : (pathinfo($stored['original'], PATHINFO_FILENAME) . '.pdf'); + $payload = [ 'teacher_id' => $adminId, 'class_section_id' => $classSectionId, @@ -102,8 +130,8 @@ class ExamDraftAdminService 'school_year' => $schoolYear, 'exam_type' => $examType !== '' ? $examType : null, 'draft_title' => $examType !== '' ? $examType : 'Legacy Exam', - 'final_file' => $stored['stored'], - 'final_filename' => $stored['original'], + 'final_file' => $pdfName, + 'final_filename' => $finalFilename, 'status' => 'finalized', 'admin_id' => $adminId, 'reviewed_at' => now(), @@ -114,17 +142,7 @@ class ExamDraftAdminService $payload['is_legacy'] = 1; } - $pdfName = null; - if ($stored['extension'] === 'pdf') { - $pdfName = $stored['stored']; - } else { - $pdfName = $this->fileService->ensurePdfExists( - $stored['stored'], - $stored['extension'], - ExamDraftConfigService::FINAL_UPLOAD_DIR - ); - } - if ($pdfName !== null && ($context['has_final_pdf'] ?? false)) { + if ($context['has_final_pdf'] ?? false) { $payload['final_pdf_file'] = $pdfName; } diff --git a/storage/uploads/exams/drafts/exam_69ed761424c7b2.44571493.docx b/storage/uploads/exams/drafts/exam_69ed761424c7b2.44571493.docx new file mode 100644 index 00000000..7509cccc Binary files /dev/null and b/storage/uploads/exams/drafts/exam_69ed761424c7b2.44571493.docx differ diff --git a/storage/uploads/exams/finals/exam_69ed72bd3a6dc4.07998677.docx b/storage/uploads/exams/finals/exam_69ed72bd3a6dc4.07998677.docx new file mode 100644 index 00000000..7509cccc Binary files /dev/null and b/storage/uploads/exams/finals/exam_69ed72bd3a6dc4.07998677.docx differ diff --git a/storage/uploads/exams/finals/exam_69ed72bd3a6dc4.07998677.pdf b/storage/uploads/exams/finals/exam_69ed72bd3a6dc4.07998677.pdf new file mode 100644 index 00000000..213c868e Binary files /dev/null and b/storage/uploads/exams/finals/exam_69ed72bd3a6dc4.07998677.pdf differ diff --git a/storage/uploads/exams/finals/exam_69ed73e60801b2.28115656.docx b/storage/uploads/exams/finals/exam_69ed73e60801b2.28115656.docx new file mode 100644 index 00000000..7509cccc Binary files /dev/null and b/storage/uploads/exams/finals/exam_69ed73e60801b2.28115656.docx differ diff --git a/storage/uploads/exams/finals/exam_69ed73e60801b2.28115656.pdf b/storage/uploads/exams/finals/exam_69ed73e60801b2.28115656.pdf new file mode 100644 index 00000000..94df79f1 Binary files /dev/null and b/storage/uploads/exams/finals/exam_69ed73e60801b2.28115656.pdf differ diff --git a/storage/uploads/exams/finals/exam_69ed75c4cf2966.31484103.docx b/storage/uploads/exams/finals/exam_69ed75c4cf2966.31484103.docx new file mode 100644 index 00000000..7509cccc Binary files /dev/null and b/storage/uploads/exams/finals/exam_69ed75c4cf2966.31484103.docx differ diff --git a/storage/uploads/exams/finals/exam_69ed75c4cf2966.31484103.pdf b/storage/uploads/exams/finals/exam_69ed75c4cf2966.31484103.pdf new file mode 100644 index 00000000..f2ae647a Binary files /dev/null and b/storage/uploads/exams/finals/exam_69ed75c4cf2966.31484103.pdf differ