getRealPath()); $existing = DocumentVersion::where('file_hash', $fileHash)->first(); if ($existing) { throw new RuntimeException( "Fail ini sudah pernah diupload. Sila semak dokumen: " . $existing->document->title ); } return DB::transaction(function () use ($data, $file, $fileHash) { // ── Buat rekod dokumen ──────────────────────────────────────── $document = Document::create([ 'category_id' => $data['category_id'], 'title' => $data['title'], 'description' => $data['description'] ?? null, 'status' => Document::STATUS_PROCESSING, 'is_active' => false, 'effective_date' => $data['effective_date'] ?? null, 'expiry_date' => $data['expiry_date'] ?? null, 'tags' => $data['tags'] ?? [], 'language' => $data['language'] ?? 'ms', 'created_by' => auth()->id(), 'updated_by' => auth()->id(), ]); // ── Simpan fail PDF ──────────────────────────────────────────── $storedPath = $this->storePdf($file, $document->id, 1); // ── Buat rekod versi ────────────────────────────────────────── $version = DocumentVersion::create([ 'document_id' => $document->id, 'version_number' => 1, 'original_filename' => $file->getClientOriginalName(), 'stored_path' => $storedPath, 'mime_type' => $file->getMimeType(), 'file_size' => $file->getSize(), 'file_hash' => $fileHash, 'processing_status' => DocumentVersion::STATUS_PENDING, 'is_current' => true, 'change_notes' => $data['change_notes'] ?? 'Versi pertama.', 'uploaded_by' => auth()->id(), ]); // ── Audit log ───────────────────────────────────────────────── $this->auditService->documentUploaded($document, $version); // ── Dispatch job ke queue ───────────────────────────────────── ProcessUploadedDocumentJob::dispatch($version->id); return $document->load('currentVersion'); }); } private function storePdf(UploadedFile $file, int $documentId, int $versionNumber): string { $disk = config('knowledgebase.upload.storage_disk', 'local'); $folder = "documents/{$documentId}/v{$versionNumber}"; $filename = Str::uuid() . '.pdf'; $path = $file->storeAs($folder, $filename, $disk); if (!$path) { throw new RuntimeException('Gagal simpan fail PDF ke storage.'); } return $path; } }