458 lines
13 KiB
PHP
458 lines
13 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Jobs\ProcessDocumentOCR;
|
|
use App\Models\Document;
|
|
use App\Models\Project;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Storage;
|
|
|
|
class DocumentController extends Controller
|
|
{
|
|
public $comments=[];
|
|
|
|
|
|
/**
|
|
* Display a listing of the resource.
|
|
*/
|
|
public function index()
|
|
{
|
|
//
|
|
}
|
|
|
|
/**
|
|
* Show the form for creating a new resource.
|
|
*/
|
|
public function create()
|
|
{
|
|
//
|
|
}
|
|
|
|
/**
|
|
* Store a newly created resource in storage.
|
|
*/
|
|
public function store(Request $request)
|
|
{
|
|
$validated = $request->validate([
|
|
'files.*' => 'required|file|mimes:pdf,docx,xlsx,jpg,png|max:5120',
|
|
'project_id' => 'required|exists:projects,id',
|
|
'folder_id' => 'nullable|exists:folders,id'
|
|
]);
|
|
|
|
foreach ($request->file('files') as $file) {
|
|
$document = Document::create([
|
|
'name' => $file->getClientOriginalName(),
|
|
'project_id' => $request->project_id,
|
|
'folder_id' => $request->folder_id,
|
|
'created_by' => auth()->id()
|
|
]);
|
|
|
|
$document->addMedia($file)->toMediaCollection('documents');
|
|
ProcessDocumentOCR::dispatch($document->currentVersion);
|
|
}
|
|
|
|
return redirect()->back()->with('success', 'Files uploaded successfully');
|
|
}
|
|
|
|
/**
|
|
* Display the specified resource.
|
|
*/
|
|
public function show(Document $document)
|
|
{
|
|
$this->authorize('view', $document); // Si usas políticas
|
|
|
|
if (!Storage::exists($document->file_path)) {
|
|
abort(404);
|
|
}
|
|
|
|
$document->url = Storage::url($document->file_path);
|
|
|
|
$document->load('user');
|
|
|
|
return view('documents.show', [
|
|
'document' => $document,
|
|
'versions' => $document->versions()->latest()->get(),
|
|
'comments' => $this->comments,
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Show the form for editing the specified resource.
|
|
*/
|
|
public function edit(Document $document)
|
|
{
|
|
//
|
|
}
|
|
|
|
/**
|
|
* Update the specified resource in storage.
|
|
*/
|
|
public function update(Request $request, Document $document)
|
|
{
|
|
//
|
|
}
|
|
|
|
/**
|
|
* Remove the specified resource from storage.
|
|
*/
|
|
public function destroy(Document $document)
|
|
{
|
|
//
|
|
}
|
|
|
|
public function upload(Request $request, Project $project)
|
|
{
|
|
$request->validate([
|
|
'files.*' => 'required|mimes:pdf,docx,xlsx,jpeg,png|max:2048'
|
|
]);
|
|
|
|
foreach ($request->file('files') as $file) {
|
|
$document = $project->documents()->create([
|
|
'name' => $file->getClientOriginalName(),
|
|
'status' => 0
|
|
]);
|
|
|
|
$this->createVersion($document, $file);
|
|
}
|
|
}
|
|
|
|
private function createVersion(Document $document, $file)
|
|
{
|
|
$version = $document->versions()->create([
|
|
'file_path' => $file->store("projects/{$document->project_id}/documents"),
|
|
'hash' => hash_file('sha256', $file),
|
|
'user_id' => auth()->id()
|
|
]);
|
|
|
|
$document->update(['current_version_id' => $version->id]);
|
|
}
|
|
|
|
|
|
/**
|
|
* Actualizar PDF con anotaciones, firmas y sellos
|
|
*/
|
|
public function updatePdf(Request $request, Document $document)
|
|
{
|
|
$this->authorize('update', $document);
|
|
|
|
$request->validate([
|
|
'pdf_data' => 'required|string', // PDF modificado en base64
|
|
'annotations' => 'sometimes|array',
|
|
'signatures' => 'sometimes|array',
|
|
'stamps' => 'sometimes|array',
|
|
]);
|
|
|
|
try {
|
|
// Procesar el PDF modificado
|
|
$modifiedPdf = $this->processPdfData($request->pdf_data);
|
|
|
|
// Reemplazar el archivo original (sin crear nueva versión si no quieres)
|
|
$this->replaceOriginalPdf($document, $modifiedPdf);
|
|
|
|
// Opcional: también crear una nueva versión para historial
|
|
$newVersion = $this->createNewVersion($document, $modifiedPdf, $request->all());
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'message' => 'PDF actualizado correctamente',
|
|
'version_id' => $newVersion->id ?? null,
|
|
]);
|
|
|
|
} catch (\Exception $e) {
|
|
\Log::error('Error updating PDF: ' . $e->getMessage());
|
|
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Error al actualizar el PDF: ' . $e->getMessage()
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Procesar datos del PDF en base64
|
|
*/
|
|
private function processPdfData($pdfData)
|
|
{
|
|
// Eliminar el prefijo data:application/pdf;base64, si existe
|
|
$pdfData = preg_replace('/^data:application\/pdf;base64,/', '', $pdfData);
|
|
|
|
// Decodificar base64
|
|
$pdfContent = base64_decode($pdfData);
|
|
|
|
if (!$pdfContent) {
|
|
throw new \Exception('Datos PDF inválidos');
|
|
}
|
|
|
|
return $pdfContent;
|
|
}
|
|
|
|
/**
|
|
* Procesar PDF con anotaciones (método alternativo)
|
|
*/
|
|
private function processPdfWithAnnotations($document, $data)
|
|
{
|
|
// Aquí integrarías una librería PHP para PDF como spatie/pdf-to-image o setasign/fpdi
|
|
// Por ahora, devolvemos el contenido del archivo original
|
|
// En producción, implementarías la lógica de modificación
|
|
|
|
if ($document->currentVersion) {
|
|
$filePath = $document->currentVersion->file_path;
|
|
} else {
|
|
$filePath = $document->getFirstMedia('documents')->getPath();
|
|
}
|
|
|
|
if (!Storage::exists($filePath)) {
|
|
throw new \Exception('Archivo PDF no encontrado');
|
|
}
|
|
|
|
return Storage::get($filePath);
|
|
}
|
|
|
|
/**
|
|
* Reemplazar el PDF original
|
|
*/
|
|
private function replaceOriginalPdf($document, $pdfContent)
|
|
{
|
|
// Obtener la ruta del archivo original
|
|
$filePath = $document->file_path;
|
|
|
|
// Si el documento usa media library
|
|
if ($document->getFirstMedia('documents')) {
|
|
$media = $document->getFirstMedia('documents');
|
|
$media->update([
|
|
'file_name' => $document->name . '.pdf',
|
|
'size' => strlen($pdfContent),
|
|
]);
|
|
|
|
// Reemplazar el archivo
|
|
Storage::put($media->getPath(), $pdfContent);
|
|
} else {
|
|
// Si usas file_path directo
|
|
Storage::put($filePath, $pdfContent);
|
|
|
|
// Actualizar metadata del documento
|
|
$document->update([
|
|
'file_size' => strlen($pdfContent),
|
|
'updated_at' => now(),
|
|
]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Crear nueva versión del documento
|
|
*/
|
|
private function createNewVersion($document, $pdfContent, $data = [])
|
|
{
|
|
$versionNumber = $document->versions()->count() + 1;
|
|
$fileName = "documents/{$document->id}/v{$versionNumber}.pdf";
|
|
|
|
// Guardar el nuevo PDF
|
|
Storage::put($fileName, $pdfContent);
|
|
|
|
// Crear registro de versión
|
|
$version = $document->versions()->create([
|
|
'version_number' => $versionNumber,
|
|
'file_path' => $fileName,
|
|
'file_size' => strlen($pdfContent),
|
|
'hash' => hash('sha256', $pdfContent),
|
|
'created_by' => auth()->id(),
|
|
'metadata' => [
|
|
'annotations_count' => count($data['annotations'] ?? []),
|
|
'signatures_count' => count($data['signatures'] ?? []),
|
|
'stamps_count' => count($data['stamps'] ?? []),
|
|
'edited_at' => now()->toISOString(),
|
|
'edited_by' => auth()->user()->name
|
|
]
|
|
]);
|
|
|
|
return $version;
|
|
}
|
|
|
|
/**
|
|
* Guardar metadatos de anotaciones
|
|
*/
|
|
private function saveAnnotationsMetadata($version, $data)
|
|
{
|
|
// Guardar anotaciones en la base de datos si es necesario
|
|
if (!empty($data['annotations'])) {
|
|
foreach ($data['annotations'] as $annotation) {
|
|
$version->annotations()->create([
|
|
'type' => $annotation['type'] ?? 'text',
|
|
'content' => $annotation['content'] ?? '',
|
|
'position' => $annotation['position'] ?? [],
|
|
'page' => $annotation['page'] ?? 1,
|
|
'created_by' => auth()->id()
|
|
]);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Subir firma
|
|
*/
|
|
public function uploadSignature(Request $request)
|
|
{
|
|
$request->validate([
|
|
'signature' => 'required|image|max:2048|mimes:png,jpg,jpeg'
|
|
]);
|
|
|
|
try {
|
|
$user = auth()->user();
|
|
$path = $request->file('signature')->store("signatures/{$user->id}", 'public');
|
|
|
|
// Opcional: Guardar en base de datos
|
|
$user->signatures()->create([
|
|
'file_path' => $path,
|
|
'file_name' => $request->file('signature')->getClientOriginalName()
|
|
]);
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'path' => Storage::url($path),
|
|
'filename' => basename($path)
|
|
]);
|
|
|
|
} catch (\Exception $e) {
|
|
\Log::error('Error uploading signature: ' . $e->getMessage());
|
|
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Error al subir la firma'
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Subir sello
|
|
*/
|
|
public function uploadStamp(Request $request)
|
|
{
|
|
$request->validate([
|
|
'stamp' => 'required|image|max:2048|mimes:png,jpg,jpeg'
|
|
]);
|
|
|
|
try {
|
|
$user = auth()->user();
|
|
$path = $request->file('stamp')->store("stamps/{$user->id}", 'public');
|
|
|
|
// Opcional: Guardar en base de datos
|
|
$user->stamps()->create([
|
|
'file_path' => $path,
|
|
'file_name' => $request->file('stamp')->getClientOriginalName(),
|
|
'type' => $request->type ?? 'custom'
|
|
]);
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'path' => Storage::url($path),
|
|
'filename' => basename($path)
|
|
]);
|
|
|
|
} catch (\Exception $e) {
|
|
\Log::error('Error uploading stamp: ' . $e->getMessage());
|
|
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Error al subir el sello'
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Obtener firmas del usuario
|
|
*/
|
|
public function getSignatures()
|
|
{
|
|
$user = auth()->user();
|
|
$signatures = $user->signatures()->get()->map(function($signature) {
|
|
return [
|
|
'id' => $signature->id,
|
|
'url' => Storage::url($signature->file_path),
|
|
'name' => $signature->file_name
|
|
];
|
|
});
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'signatures' => $signatures
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Obtener sellos del usuario
|
|
*/
|
|
public function getStamps()
|
|
{
|
|
$user = auth()->user();
|
|
$stamps = $user->stamps()->get()->map(function($stamp) {
|
|
return [
|
|
'id' => $stamp->id,
|
|
'url' => Storage::url($stamp->file_path),
|
|
'name' => $stamp->file_name,
|
|
'type' => $stamp->type
|
|
];
|
|
});
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'stamps' => $stamps
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Descargar documento
|
|
*/
|
|
public function download(Document $document, $versionId = null)
|
|
{
|
|
$this->authorize('view', $document);
|
|
|
|
$version = $versionId ?
|
|
$document->versions()->findOrFail($versionId) :
|
|
$document->currentVersion;
|
|
|
|
if (!$version || !Storage::exists($version->file_path)) {
|
|
abort(404);
|
|
}
|
|
|
|
return Storage::download($version->file_path, $document->name . '.pdf');
|
|
}
|
|
|
|
/**
|
|
* Obtener el PDF actual para edición
|
|
*/
|
|
public function getPdfForEditing(Document $document)
|
|
{
|
|
$this->authorize('view', $document);
|
|
|
|
try {
|
|
if ($document->getFirstMedia('documents')) {
|
|
$filePath = $document->getFirstMedia('documents')->getPath();
|
|
} else {
|
|
$filePath = $document->file_path;
|
|
}
|
|
|
|
if (!Storage::exists($filePath)) {
|
|
abort(404);
|
|
}
|
|
|
|
$pdfContent = Storage::get($filePath);
|
|
$base64Pdf = base64_encode($pdfContent);
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'pdf_data' => $base64Pdf,
|
|
'document_name' => $document->name
|
|
]);
|
|
|
|
} catch (\Exception $e) {
|
|
\Log::error('Error getting PDF for editing: ' . $e->getMessage());
|
|
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Error al cargar el PDF'
|
|
], 500);
|
|
}
|
|
}
|
|
}
|