Initial commit
This commit is contained in:
@@ -0,0 +1,241 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\DocumentType;
|
||||
use App\Models\Student;
|
||||
use App\Models\StudentDocument;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\View\View;
|
||||
use RealRashid\SweetAlert\Facades\Alert;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class StudentDocumentController extends Controller
|
||||
{
|
||||
public function create(Student $student): View
|
||||
{
|
||||
return view('student-documents.create', [
|
||||
'student' => $student,
|
||||
'documentTypes' => DocumentType::where('is_active', true)->orderBy('name')->get(),
|
||||
'verificationStatuses' => $this->verificationStatuses(),
|
||||
'defaultMaxFileSizeKb' => 5120,
|
||||
]);
|
||||
}
|
||||
|
||||
public function store(Request $request, Student $student): RedirectResponse
|
||||
{
|
||||
$data = $this->validateDocument($request);
|
||||
$uploadedFile = $request->file('document_file');
|
||||
$path = $uploadedFile->store("student-documents/{$student->id}", 'public');
|
||||
|
||||
StudentDocument::create([
|
||||
'student_id' => $student->id,
|
||||
'document_type_id' => $data['document_type_id'],
|
||||
'file_name' => $uploadedFile->getClientOriginalName(),
|
||||
'file_path' => $path,
|
||||
'file_extension' => $uploadedFile->getClientOriginalExtension(),
|
||||
'mime_type' => $uploadedFile->getMimeType(),
|
||||
'file_size' => $uploadedFile->getSize(),
|
||||
'document_number' => $data['document_number'] ?? null,
|
||||
'issued_date' => $data['issued_date'] ?? null,
|
||||
'expired_date' => $data['expired_date'] ?? null,
|
||||
'description' => $data['description'] ?? null,
|
||||
'verification_status' => $data['verification_status'],
|
||||
'verification_note' => $data['verification_note'] ?? null,
|
||||
'uploaded_by' => auth()->id(),
|
||||
'verified_by' => in_array($data['verification_status'], ['valid', 'invalid', 'revision']) ? auth()->id() : null,
|
||||
'verified_at' => in_array($data['verification_status'], ['valid', 'invalid', 'revision']) ? now() : null,
|
||||
]);
|
||||
|
||||
Alert::success('Berhasil', 'Dokumen siswa berhasil diunggah.');
|
||||
|
||||
return redirect()->route('students.show', $student)->with('success', 'Dokumen siswa berhasil diunggah.');
|
||||
}
|
||||
|
||||
public function edit(Student $student, StudentDocument $document): View
|
||||
{
|
||||
abort_unless($document->student_id === $student->id, 404);
|
||||
|
||||
return view('student-documents.edit', [
|
||||
'student' => $student,
|
||||
'document' => $document,
|
||||
'documentTypes' => DocumentType::where('is_active', true)->orderBy('name')->get(),
|
||||
'verificationStatuses' => $this->verificationStatuses(),
|
||||
'defaultMaxFileSizeKb' => 5120,
|
||||
]);
|
||||
}
|
||||
|
||||
public function update(Request $request, Student $student, StudentDocument $document): RedirectResponse
|
||||
{
|
||||
abort_unless($document->student_id === $student->id, 404);
|
||||
|
||||
$data = $this->validateDocument($request, false);
|
||||
|
||||
if ($request->hasFile('document_file')) {
|
||||
if ($document->file_path && Storage::disk('public')->exists($document->file_path)) {
|
||||
Storage::disk('public')->delete($document->file_path);
|
||||
}
|
||||
|
||||
$uploadedFile = $request->file('document_file');
|
||||
$path = $uploadedFile->store("student-documents/{$student->id}", 'public');
|
||||
|
||||
$document->file_name = $uploadedFile->getClientOriginalName();
|
||||
$document->file_path = $path;
|
||||
$document->file_extension = $uploadedFile->getClientOriginalExtension();
|
||||
$document->mime_type = $uploadedFile->getMimeType();
|
||||
$document->file_size = $uploadedFile->getSize();
|
||||
}
|
||||
|
||||
$document->fill([
|
||||
'document_type_id' => $data['document_type_id'],
|
||||
'document_number' => $data['document_number'] ?? null,
|
||||
'issued_date' => $data['issued_date'] ?? null,
|
||||
'expired_date' => $data['expired_date'] ?? null,
|
||||
'description' => $data['description'] ?? null,
|
||||
'verification_status' => $data['verification_status'],
|
||||
'verification_note' => $data['verification_note'] ?? null,
|
||||
]);
|
||||
|
||||
if (in_array($data['verification_status'], ['valid', 'invalid', 'revision'])) {
|
||||
$document->verified_by = auth()->id();
|
||||
$document->verified_at = now();
|
||||
} else {
|
||||
$document->verified_by = null;
|
||||
$document->verified_at = null;
|
||||
}
|
||||
|
||||
$document->save();
|
||||
|
||||
Alert::success('Berhasil', 'Dokumen siswa berhasil diperbarui.');
|
||||
|
||||
return redirect()->route('students.show', $student)->with('success', 'Dokumen siswa berhasil diperbarui.');
|
||||
}
|
||||
|
||||
public function destroy(Student $student, StudentDocument $document): RedirectResponse
|
||||
{
|
||||
$this->ensureAdmin();
|
||||
abort_unless($document->student_id === $student->id, 404);
|
||||
|
||||
if ($document->file_path && Storage::disk('public')->exists($document->file_path)) {
|
||||
Storage::disk('public')->delete($document->file_path);
|
||||
}
|
||||
|
||||
$document->delete();
|
||||
|
||||
Alert::success('Berhasil', 'Dokumen siswa berhasil dihapus.');
|
||||
|
||||
return redirect()->route('students.show', $student)->with('success', 'Dokumen siswa berhasil dihapus.');
|
||||
}
|
||||
|
||||
public function preview(StudentDocument $document): Response|View
|
||||
{
|
||||
abort_unless($document->file_path && Storage::disk('public')->exists($document->file_path), 404);
|
||||
|
||||
$mimeType = $document->mime_type ?: Storage::disk('public')->mimeType($document->file_path);
|
||||
$url = asset('storage/' . $document->file_path);
|
||||
$isImage = str_starts_with((string) $mimeType, 'image/');
|
||||
$isPdf = $mimeType === 'application/pdf';
|
||||
|
||||
return view('student-documents.preview', [
|
||||
'document' => $document,
|
||||
'fileUrl' => $url,
|
||||
'mimeType' => $mimeType,
|
||||
'isImage' => $isImage,
|
||||
'isPdf' => $isPdf,
|
||||
]);
|
||||
}
|
||||
|
||||
public function quickVerify(Request $request, Student $student, StudentDocument $document): RedirectResponse
|
||||
{
|
||||
$this->ensureAdmin();
|
||||
abort_unless($document->student_id === $student->id, 404);
|
||||
|
||||
$data = $request->validate([
|
||||
'verification_status' => ['required', Rule::in(['valid', 'revision', 'invalid'])],
|
||||
'verification_note' => ['nullable', 'string', 'max:1000'],
|
||||
]);
|
||||
|
||||
$document->update([
|
||||
'verification_status' => $data['verification_status'],
|
||||
'verification_note' => $data['verification_note'] ?? null,
|
||||
'verified_by' => auth()->id(),
|
||||
'verified_at' => now(),
|
||||
]);
|
||||
|
||||
Alert::success('Berhasil', 'Status verifikasi dokumen berhasil diperbarui.');
|
||||
|
||||
return redirect()->route('students.show', $student)->with('success', 'Status verifikasi dokumen berhasil diperbarui.');
|
||||
}
|
||||
|
||||
public function download(StudentDocument $document): StreamedResponse
|
||||
{
|
||||
abort_unless($document->file_path && Storage::disk('public')->exists($document->file_path), 404);
|
||||
|
||||
return Storage::disk('public')->download($document->file_path, $document->file_name);
|
||||
}
|
||||
|
||||
public function publicPreview(StudentDocument $document): Response|View
|
||||
{
|
||||
abort_unless($document->file_path && Storage::disk('public')->exists($document->file_path), 404);
|
||||
|
||||
$mimeType = $document->mime_type ?: Storage::disk('public')->mimeType($document->file_path);
|
||||
$url = asset('storage/' . $document->file_path);
|
||||
$isImage = str_starts_with((string) $mimeType, 'image/');
|
||||
$isPdf = $mimeType === 'application/pdf';
|
||||
|
||||
return view('public.document-preview', [
|
||||
'document' => $document,
|
||||
'fileUrl' => $url,
|
||||
'mimeType' => $mimeType,
|
||||
'isImage' => $isImage,
|
||||
'isPdf' => $isPdf,
|
||||
]);
|
||||
}
|
||||
|
||||
public function publicDownload(StudentDocument $document): StreamedResponse
|
||||
{
|
||||
return $this->download($document);
|
||||
}
|
||||
|
||||
protected function validateDocument(Request $request, bool $fileRequired = true): array
|
||||
{
|
||||
$documentType = DocumentType::findOrFail($request->input('document_type_id'));
|
||||
$maxFileSizeKb = $documentType->max_file_size_kb ?: 5120;
|
||||
$allowedExtensions = $documentType->allowed_extensions
|
||||
? collect(explode(',', $documentType->allowed_extensions))->map(fn ($item) => trim($item))->filter()->implode(',')
|
||||
: 'jpg,jpeg,png,pdf,webp';
|
||||
|
||||
return $request->validate([
|
||||
'document_type_id' => ['required', 'exists:document_types,id'],
|
||||
'document_number' => ['nullable', 'string', 'max:100'],
|
||||
'issued_date' => ['nullable', 'date'],
|
||||
'expired_date' => ['nullable', 'date', 'after_or_equal:issued_date'],
|
||||
'description' => ['nullable', 'string'],
|
||||
'verification_status' => ['required', Rule::in(array_keys($this->verificationStatuses()))],
|
||||
'verification_note' => ['nullable', 'string', 'max:1000'],
|
||||
'document_file' => [$fileRequired ? 'required' : 'nullable', 'file', 'mimes:' . $allowedExtensions, 'max:' . $maxFileSizeKb],
|
||||
], [
|
||||
'document_file.max' => 'Ukuran file melebihi batas maksimal untuk jenis dokumen ini (' . number_format($maxFileSizeKb / 1024, 2) . ' MB).',
|
||||
'document_file.mimes' => 'Format file tidak sesuai. Format yang diizinkan untuk jenis dokumen ini: ' . strtoupper(str_replace(',', ', ', $allowedExtensions)) . '.',
|
||||
]);
|
||||
}
|
||||
|
||||
protected function verificationStatuses(): array
|
||||
{
|
||||
return [
|
||||
'pending' => 'Pending',
|
||||
'valid' => 'Valid',
|
||||
'invalid' => 'Invalid',
|
||||
'revision' => 'Perlu Revisi',
|
||||
];
|
||||
}
|
||||
|
||||
protected function ensureAdmin(): void
|
||||
{
|
||||
abort_unless(auth()->user()?->isAdmin(), 403, 'Aksi ini hanya boleh dilakukan administrator.');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user