feat: add graduation archive and public document services

This commit is contained in:
2026-04-14 13:51:39 +00:00
parent d77ad72bcc
commit 58c9b47dc0
30 changed files with 2513 additions and 295 deletions
@@ -0,0 +1,168 @@
<?php
namespace App\Http\Controllers;
use App\Models\AcademicYear;
use App\Models\Department;
use App\Models\SchoolClass;
use App\Models\StudentGraduation;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Illuminate\View\View;
use RealRashid\SweetAlert\Facades\Alert;
class GraduatedStudentController extends Controller
{
public function index(Request $request): View
{
$search = trim((string) $request->get('search'));
$academicYearId = $request->get('academic_year_id');
$departmentId = $request->get('department_id');
$classId = $request->get('class_id');
$sort = (string) $request->get('sort', 'full_name');
$direction = strtolower((string) $request->get('direction', 'asc')) === 'desc' ? 'desc' : 'asc';
$allowedSorts = [
'full_name' => 'full_name',
'student_number' => 'student_number',
'academic_year' => 'academic_year_id',
'department' => 'department_id',
'class' => 'class_id',
'graduation_date' => 'graduation_date',
'created_at' => 'created_at',
];
if (! array_key_exists($sort, $allowedSorts)) {
$sort = 'full_name';
}
$graduations = StudentGraduation::query()
->with(['academicYear', 'department', 'classRoom'])
->when($search !== '', function ($query) use ($search) {
$query->where(function ($subQuery) use ($search) {
$subQuery->where('full_name', 'like', "%{$search}%")
->orWhere('student_number', 'like', "%{$search}%")
->orWhere('nisn', 'like', "%{$search}%");
});
})
->when($academicYearId, fn ($query) => $query->where('academic_year_id', $academicYearId))
->when($departmentId, fn ($query) => $query->where('department_id', $departmentId))
->when($classId, fn ($query) => $query->where('class_id', $classId))
->orderBy($allowedSorts[$sort], $direction)
->orderBy('id', $direction)
->paginate(10)
->withQueryString();
$summary = [
'total' => $graduations->total(),
'with_skl' => StudentGraduation::query()->whereNotNull('skl_file_path')->count(),
'with_ijazah' => StudentGraduation::query()->whereNotNull('ijazah_file_path')->count(),
];
return view('graduated-students.index', [
'graduations' => $graduations,
'search' => $search,
'filters' => [
'academic_year_id' => $academicYearId,
'department_id' => $departmentId,
'class_id' => $classId,
],
'academicYears' => AcademicYear::orderBy('name')->pluck('name', 'id'),
'departments' => Department::orderBy('name')->pluck('name', 'id'),
'classes' => SchoolClass::orderBy('name')->pluck('name', 'id'),
'sort' => $sort,
'direction' => $direction,
'summary' => $summary,
]);
}
public function show(StudentGraduation $graduatedStudent): View
{
$graduatedStudent->load(['academicYear', 'department', 'classRoom']);
return view('graduated-students.show', [
'graduation' => $graduatedStudent,
]);
}
public function update(Request $request, StudentGraduation $graduatedStudent): RedirectResponse
{
$validated = $request->validate([
'graduation_date' => ['nullable', 'date'],
'graduation_note' => ['nullable', 'string'],
'skl_file' => ['nullable', 'file', 'mimes:pdf,jpg,jpeg,png', 'max:4096'],
'ijazah_file' => ['nullable', 'file', 'mimes:pdf,jpg,jpeg,png', 'max:4096'],
], [
'skl_file.mimes' => 'File SKL harus berupa PDF, JPG, JPEG, atau PNG.',
'skl_file.max' => 'Ukuran file SKL maksimal 4 MB.',
'ijazah_file.mimes' => 'File ijazah harus berupa PDF, JPG, JPEG, atau PNG.',
'ijazah_file.max' => 'Ukuran file ijazah maksimal 4 MB.',
]);
$graduatedStudent->graduation_date = $validated['graduation_date'] ?? $graduatedStudent->graduation_date;
$graduatedStudent->graduation_note = $validated['graduation_note'] ?? $graduatedStudent->graduation_note;
if ($request->hasFile('skl_file')) {
if ($graduatedStudent->skl_file_path && Storage::disk('public')->exists($graduatedStudent->skl_file_path)) {
Storage::disk('public')->delete($graduatedStudent->skl_file_path);
}
$file = $request->file('skl_file');
$path = $file->store("student-graduation-documents/{$graduatedStudent->student_id}/skl", 'public');
$graduatedStudent->skl_file_name = $file->getClientOriginalName();
$graduatedStudent->skl_file_path = $path;
$graduatedStudent->skl_mime_type = $file->getMimeType();
$graduatedStudent->skl_file_size = $file->getSize();
}
if ($request->hasFile('ijazah_file')) {
if ($graduatedStudent->ijazah_file_path && Storage::disk('public')->exists($graduatedStudent->ijazah_file_path)) {
Storage::disk('public')->delete($graduatedStudent->ijazah_file_path);
}
$file = $request->file('ijazah_file');
$path = $file->store("student-graduation-documents/{$graduatedStudent->student_id}/ijazah", 'public');
$graduatedStudent->ijazah_file_name = $file->getClientOriginalName();
$graduatedStudent->ijazah_file_path = $path;
$graduatedStudent->ijazah_mime_type = $file->getMimeType();
$graduatedStudent->ijazah_file_size = $file->getSize();
}
$graduatedStudent->save();
Alert::success('Berhasil', 'Arsip siswa lulus berhasil diperbarui.');
return redirect()->route('graduated-students.show', $graduatedStudent)->with('success', 'Arsip siswa lulus berhasil diperbarui.');
}
public function previewDocument(StudentGraduation $graduatedStudent, string $document): View
{
abort_unless(in_array($document, ['skl', 'ijazah'], true), 404);
$filePathField = $document === 'skl' ? 'skl_file_path' : 'ijazah_file_path';
$fileNameField = $document === 'skl' ? 'skl_file_name' : 'ijazah_file_name';
$mimeTypeField = $document === 'skl' ? 'skl_mime_type' : 'ijazah_mime_type';
abort_unless($graduatedStudent->{$filePathField} && Storage::disk('public')->exists($graduatedStudent->{$filePathField}), 404);
$mimeType = $graduatedStudent->{$mimeTypeField} ?: Storage::disk('public')->mimeType($graduatedStudent->{$filePathField});
$fileUrl = asset('storage/' . $graduatedStudent->{$filePathField});
$isImage = Str::startsWith((string) $mimeType, 'image/');
$isPdf = $mimeType === 'application/pdf';
return view('graduated-students.preview-document', [
'graduation' => $graduatedStudent,
'documentType' => $document,
'documentLabel' => $document === 'skl' ? 'SKL' : 'Ijazah',
'fileName' => $graduatedStudent->{$fileNameField},
'fileUrl' => $fileUrl,
'mimeType' => $mimeType,
'isImage' => $isImage,
'isPdf' => $isPdf,
]);
}
}