update exam and attendance

This commit is contained in:
root
2026-04-26 14:57:43 -04:00
parent 5e8fa682b9
commit 8beeed883f
11 changed files with 78 additions and 36 deletions
+1
View File
@@ -16,6 +16,7 @@ abstract class ApiFormRequest extends FormRequest
return array_merge( return array_merge(
$this->query->all(), $this->query->all(),
$this->request->all(), $this->request->all(),
$this->allFiles(),
$this->json()->all(), $this->json()->all(),
$json $json
); );
@@ -10,10 +10,10 @@ class ExamDraftAdminLegacyRequest extends ApiFormRequest
{ {
return [ return [
'class_section_id' => ['required', 'integer', 'min:1'], 'class_section_id' => ['required', 'integer', 'min:1'],
'school_year' => ['required', 'string'], 'school_year' => ['nullable', 'string'],
'semester' => ['required', 'string'], 'semester' => ['nullable', 'string'],
'exam_type' => ['nullable', 'string', 'max:50'], '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'],
]; ];
} }
} }
@@ -449,15 +449,38 @@ class AttendanceQueryService
public function buildDailyAttendanceData(string $termSemester, string $termYear): array public function buildDailyAttendanceData(string $termSemester, string $termYear): array
{ {
$classSections = $this->classSection $effectiveTermYear = $termYear;
->query()
->select('classSection.id', 'classSection.class_id', 'classSection.class_section_id', 'classSection.class_section_name') $loadClassSections = function (string $schoolYear): array {
->join('student_class as sc', 'sc.class_section_id', '=', 'classSection.class_section_id') if ($schoolYear === '') {
->where('sc.school_year', $termYear) return [];
->groupBy('classSection.id', 'classSection.class_id', 'classSection.class_section_id', 'classSection.class_section_name') }
->get()
->map(fn($row) => (array)$row) return $this->classSection
->all(); ->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 = []; $attendanceData = [];
$attendanceRecord = []; $attendanceRecord = [];
@@ -466,7 +489,7 @@ class AttendanceQueryService
$datesBySection = []; $datesBySection = [];
$studentSchoolMap = []; $studentSchoolMap = [];
$sectionCounts = $this->studentClass->getStudentCountsBySection($termYear); $sectionCounts = $this->studentClass->getStudentCountsBySection($effectiveTermYear);
foreach ($classSections as $classSection) { foreach ($classSections as $classSection) {
$secPk = (int)($classSection['id'] ?? 0); $secPk = (int)($classSection['id'] ?? 0);
@@ -483,9 +506,9 @@ class AttendanceQueryService
$countForPk = (int)($sectionCounts[$secPk] ?? 0); $countForPk = (int)($sectionCounts[$secPk] ?? 0);
$sectionHasStudents = ($countForCode + $countForPk) > 0; $sectionHasStudents = ($countForCode + $countForPk) > 0;
$students = $this->studentClass->getClassStudents($secCode, $termYear); $students = $this->studentClass->getClassStudents($secCode, $effectiveTermYear);
if (!$students && $secPk && (string)$secPk !== (string)$secCode) { if (!$students && $secPk && (string)$secPk !== (string)$secCode) {
$students = $this->studentClass->getClassStudents($secPk, $termYear); $students = $this->studentClass->getClassStudents($secPk, $effectiveTermYear);
} }
if (!$sectionHasStudents || !$students) { if (!$sectionHasStudents || !$students) {
@@ -522,7 +545,7 @@ class AttendanceQueryService
} }
}) })
->when($termSemester !== '', fn($q) => $q->where('semester', $termSemester)) ->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') ->orderBy('date')
->get() ->get()
->map(fn($row) => $row->toArray()) ->map(fn($row) => $row->toArray())
@@ -547,7 +570,7 @@ class AttendanceQueryService
} }
}) })
->when($termSemester !== '', fn($q) => $q->where('semester', $termSemester)) ->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(); ->first();
$attendanceRecord[$secCode][$studentId] = $summary?->toArray() ?? [ $attendanceRecord[$secCode][$studentId] = $summary?->toArray() ?? [
@@ -581,11 +604,11 @@ class AttendanceQueryService
ksort($grades, SORT_NUMERIC); ksort($grades, SORT_NUMERIC);
[$rangeStart, $rangeEnd] = $this->semesterRangeService->getSchoolYearRange($termYear); [$rangeStart, $rangeEnd] = $this->semesterRangeService->getSchoolYearRange($effectiveTermYear);
$semesterNorm = $this->semesterRangeService->normalizeSemester($termSemester); $semesterNorm = $this->semesterRangeService->normalizeSemester($termSemester);
if ($semesterNorm !== '') { if ($semesterNorm !== '') {
$semRange = $this->semesterRangeService->getSemesterRange($termYear, $semesterNorm); $semRange = $this->semesterRangeService->getSemesterRange($effectiveTermYear, $semesterNorm);
if ($semRange) { if ($semRange) {
[$rangeStart, $rangeEnd] = $semRange; [$rangeStart, $rangeEnd] = $semRange;
} }
@@ -621,7 +644,7 @@ class AttendanceQueryService
$totalPassedDays = count($passedDatesSet); $totalPassedDays = count($passedDatesSet);
if ($totalPassedDays > 0 && $termYear !== '' && $termSemester !== '') { if ($totalPassedDays > 0 && $effectiveTermYear !== '' && $termSemester !== '') {
foreach ($attendanceData as $secCode => $studentEntries) { foreach ($attendanceData as $secCode => $studentEntries) {
foreach ($studentEntries as $studentId => $entries) { foreach ($studentEntries as $studentId => $entries) {
$statusByDate = []; $statusByDate = [];
@@ -663,7 +686,7 @@ class AttendanceQueryService
[ [
'student_id' => $studentId, 'student_id' => $studentId,
'semester' => $termSemester, 'semester' => $termSemester,
'school_year' => $termYear, 'school_year' => $effectiveTermYear,
], ],
[ [
'class_section_id' => $secCode, 'class_section_id' => $secCode,
@@ -705,7 +728,7 @@ class AttendanceQueryService
'noSchoolDays' => $noSchoolDays, 'noSchoolDays' => $noSchoolDays,
'totalPassedDays' => $totalPassedDays, 'totalPassedDays' => $totalPassedDays,
'semester' => $termSemester, 'semester' => $termSemester,
'schoolYear' => $termYear, 'schoolYear' => $effectiveTermYear,
'currentAdminName' => $adminName, 'currentAdminName' => $adminName,
]; ];
} }
@@ -876,4 +899,4 @@ class AttendanceQueryService
return ''; return '';
} }
} }
} }
+31 -13
View File
@@ -37,6 +37,18 @@ class ExamDraftAdminService
$classSections = ClassSection::query() $classSections = ClassSection::query()
->select('class_section_id', 'class_section_name') ->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') ->orderBy('class_section_name')
->get() ->get()
->toArray(); ->toArray();
@@ -95,6 +107,22 @@ class ExamDraftAdminService
return ['ok' => false, 'message' => 'File type not allowed or upload failed.']; 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 = [ $payload = [
'teacher_id' => $adminId, 'teacher_id' => $adminId,
'class_section_id' => $classSectionId, 'class_section_id' => $classSectionId,
@@ -102,8 +130,8 @@ class ExamDraftAdminService
'school_year' => $schoolYear, 'school_year' => $schoolYear,
'exam_type' => $examType !== '' ? $examType : null, 'exam_type' => $examType !== '' ? $examType : null,
'draft_title' => $examType !== '' ? $examType : 'Legacy Exam', 'draft_title' => $examType !== '' ? $examType : 'Legacy Exam',
'final_file' => $stored['stored'], 'final_file' => $pdfName,
'final_filename' => $stored['original'], 'final_filename' => $finalFilename,
'status' => 'finalized', 'status' => 'finalized',
'admin_id' => $adminId, 'admin_id' => $adminId,
'reviewed_at' => now(), 'reviewed_at' => now(),
@@ -114,17 +142,7 @@ class ExamDraftAdminService
$payload['is_legacy'] = 1; $payload['is_legacy'] = 1;
} }
$pdfName = null; if ($context['has_final_pdf'] ?? false) {
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)) {
$payload['final_pdf_file'] = $pdfName; $payload['final_pdf_file'] = $pdfName;
} }