getRealPath()); // Semak sama ada hash sama dengan versi semasa $currentVersion = $document->currentVersion; if ($currentVersion && $currentVersion->file_hash === $fileHash) { throw new RuntimeException( 'Fail ini sama dengan versi semasa. Tiada perubahan.' ); } return DB::transaction(function () use ($document, $file, $fileHash, $data) { $newVersionNumber = $document->getLatestVersionNumber() + 1; // ── Simpan fail baru ────────────────────────────────────────── $disk = config('knowledgebase.upload.storage_disk', 'local'); $folder = "documents/{$document->id}/v{$newVersionNumber}"; $filename = Str::uuid() . '.pdf'; $path = $file->storeAs($folder, $filename, $disk); if (!$path) { throw new RuntimeException('Gagal simpan fail PDF ke storage.'); } // ── Buat rekod versi baru ───────────────────────────────────── $version = DocumentVersion::create([ 'document_id' => $document->id, 'version_number' => $newVersionNumber, 'original_filename' => $file->getClientOriginalName(), 'stored_path' => $path, 'mime_type' => $file->getMimeType(), 'file_size' => $file->getSize(), 'file_hash' => $fileHash, 'processing_status' => DocumentVersion::STATUS_PENDING, 'is_current' => false, // akan di-set current semasa ingestion 'change_notes' => $data['change_notes'] ?? null, 'uploaded_by' => auth()->id(), ]); // Kemaskini status dokumen ke processing $document->update([ 'status' => Document::STATUS_PROCESSING, 'updated_by' => auth()->id(), ]); // ── Audit log ───────────────────────────────────────────────── $this->auditService->documentUploaded($document, $version); // ── Dispatch job ────────────────────────────────────────────── ProcessUploadedDocumentJob::dispatch($version->id); return $version; }); } }