sistem-akademik/app/Http/Controllers/ReportPDFController.php

247 lines
8.4 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Models\AcademicYear;
use App\Models\Assessment;
use App\Models\AssessmentLearningObjective;
use App\Models\ClassRoom;
use App\Models\CompetencyAchievement;
use App\Models\ExtracurricularAssessment;
use App\Models\HomeRoomTeacher;
use App\Models\SchoolInformation;
use App\Models\Student;
use Barryvdh\DomPDF\Facade\Pdf;
use Filament\Notifications\Notification;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
class ReportPDFController extends Controller
{
public $student;
public $class;
public $class_name;
public $academic_year;
public $semester;
public $school_information;
public $table = [];
public $home_room_teacher;
public function reportPDF(Request $request)
{
$params = $request->query();
$defaultParams = ["studentId", "classId", "yearId", "semester", "sakit", "izin", "tanpa_keterangan"];
try {
$this->validateParameters($params, $defaultParams);
} catch (\Illuminate\Validation\ValidationException $e) {
Notification::make()
->title('Parameter tidak valid: ' . $e->getMessage())
->danger()
->send();
return back();
}
$this->student = Student::findOrFail($params["studentId"]);
$this->class = ClassRoom::findOrFail($params["classId"]);
$this->academic_year = AcademicYear::findOrFail($params["yearId"]);
$this->semester = $params["semester"];
$this->school_information = SchoolInformation::firstOrFail();
$this->class_name = $this->toRoman($this->class->class_level) . ' ' . $this->extractClassLetter($this->class->class_name);
$this->loadAssessment();
$data = [
'student' => $this->student,
'school_information' => $this->school_information,
'table' => $this->table,
'sakit' => $params['sakit'],
'izin' => $params['izin'],
'tanpa_keterangan' => $params['tanpa_keterangan'],
'class_name' => $this->class_name,
'semester' => $params['semester'],
'academic_year' => $this->academic_year,
'home_room_teacher' => $this->home_room_teacher,
];
$pdf = Pdf::loadView('print.report', $data)
->setPaper('a4', 'portrait')
->setOption('isRemoteEnabled', true)
->setOption('isHtml5ParserEnabled', true);
return response()->streamDownload(
function () use ($pdf) {
echo $pdf->stream();
},
'Rapor_' . $this->student->full_name . '.pdf'
);
}
protected function loadAssessment(): void
{
$student_id = $this->student->id;
$class_id = $this->class->id;
$semester = $this->semester;
$year_id = $this->academic_year->id;
// Assessment Mapping
$assessments = Assessment::where('semester', $this->semester)
->whereHas('teacherSubject', function($query) use ($class_id, $year_id) {
$query->where('academic_year_id', $year_id)
->where('class_id', $class_id);
})
->where('student_id', $this->student->id)
->with('teacherSubject.subject', 'student')
->get()
->map(function ($as) use ($class_id) {
$subject = $as->teacherSubject->subject ?? null;
if (!$subject) {
return null;
}
$assesmentLearningObjectivesLower = AssessmentLearningObjective::with('learningObjective')
->where('teacher_subject_id', $as->teacherSubject->id)
->where('student_id', $this->student->id)
->where('type', 'lower')
->get()
->pluck('learningObjective.description')
->toArray();
$joinedStringLower = $as->student->full_name . ' perlu peningkatan dalam ' . implode(', ', $assesmentLearningObjectivesLower);
$assesmentLearningObjectivesHighest = AssessmentLearningObjective::with('learningObjective')
->where('teacher_subject_id', $as->teacherSubject->id)
->where('student_id', $this->student->id)
->where('type', 'highest')
->get()
->pluck('learningObjective.description')
->toArray();
$joinedStringHighest = $as->student->full_name . ' menunjukan pemahaman dalam ' . implode(', ', $assesmentLearningObjectivesHighest);
return [
"score" => $as->score,
"subject" => $subject->name,
"category" => $subject->category,
"lower" => $assesmentLearningObjectivesLower ? $joinedStringLower : null,
"highest" => $assesmentLearningObjectivesHighest ? $joinedStringHighest : null,
];
})
->filter() // Hapus null jika ada
->sortByDesc('subject')
->sortBy(function ($item) {
return $item['category'] === 'umum' ? 0 : 1;
})
->values()
->toArray();
$this->table["assessments"]['umum'] = array_filter($assessments, function ($item) {
return $item["category"] === "umum";
});
$this->table["assessments"]['muatan lokal'] = array_filter($assessments, function ($item) {
return $item["category"] === "muatan lokal";
});
$this->table["assessments"]['seni'] = array_filter($assessments, function ($item) {
return $item["category"] === "seni";
});
$extracurricular = ExtracurricularAssessment::with('classStudent','extracurricular')
->where('semester', $this->semester)
->whereHas('classStudent', function($query) use ($class_id, $year_id) {
$query->where('academic_year_id', $year_id)
->where('class_room_id', $class_id)
->where('student_id', $this->student->id);
})
->get()
->map(function ($as) {
return [
"name" => $as->extracurricular->name,
"predicate" => $as->predicate,
"description" => $as->description,
];
})
->toArray();
$this->table["extracurricular"] = $extracurricular;
$homeRoom = HomeRoomTeacher::with(['teacher'])
->where('class_room_id', $this->class->id)
->where('academic_year_id', $this->academic_year->id)
->first();
if ($homeRoom) {
$this->home_room_teacher = $homeRoom ?? [];
}
}
protected function validateParameters(array $params, array $allowedParams): void
{
$validator = Validator::make($params, [
'studentId' => 'required|integer',
'classId' => 'required|integer',
'yearId' => 'required|integer',
'semester' => 'required|in:first,second',
'sakit' => 'nullable|integer|min:0',
'izin' => 'nullable|integer|min:0',
'tanpa_keterangan' => 'nullable|integer|min:0',
]);
if ($validator->fails()) {
throw new \Illuminate\Validation\ValidationException($validator);
}
foreach ($params as $key => $value) {
if (!in_array($key, $allowedParams)) {
throw new \InvalidArgumentException("Parameter {$key} tidak valid");
}
}
}
public function extractClassLetter($className): string
{
preg_match('/[A-Z]+$/i', trim($className), $matches);
return $matches[0] ?? '';
}
public function toRoman($number): string
{
$map = [
'M' => 1000,
'CM' => 900,
'D' => 500,
'CD' => 400,
'C' => 100,
'XC' => 90,
'L' => 50,
'XL' => 40,
'X' => 10,
'IX' => 9,
'V' => 5,
'IV' => 4,
'I' => 1,
];
$returnValue = '';
while ($number > 0) {
foreach ($map as $roman => $int) {
if ($number >= $int) {
$number -= $int;
$returnValue .= $roman;
break;
}
}
}
return $returnValue;
}
}