findOrFail($id); $pdf = Pdf::loadView('pdfs.record', compact('record')) ->setPaper('a4', 'portrait') ->setOptions([ 'defaultFont' => 'sans-serif', 'isHtml5ParserEnabled' => true, 'isRemoteEnabled' => true, ]); return $pdf->stream('constancia-inscripcion-' . $id . '.pdf'); } public function generatePdfVerification($id) { $record = Record::with('vehicle.owner', 'user')->findOrFail($id); $pdf = Pdf::loadView('pdfs.verification', compact('record')) ->setPaper('a4', 'landscape') ->setOptions([ 'defaultFont' => 'sans-serif', 'isHtml5ParserEnabled' => true, 'isRemoteEnabled' => true, ]); return $pdf->stream('hoja-verificacion-' . $id . '.pdf'); } public function generatePdfConstancia($id) { $record = Record::with('vehicle.owner', 'user')->findOrFail($id); $pdf = Pdf::loadView('pdfs.constancia', compact('record')) ->setPaper('a4', 'landscape') ->setOptions([ 'defaultFont' => 'sans-serif', 'isHtml5ParserEnabled' => true, 'isRemoteEnabled' => true, ]); return $pdf->stream('constancia-inscripcion' . $id . '.pdf'); } /** * Generar PDF con las imágenes */ public function generatePdfImages($id) { try { // Obtener el record con sus archivos $record = Record::with(['vehicle.owner', 'files'])->findOrFail($id); // Validar que tenga archivos if ($record->files->isEmpty()) { return ApiResponse::NOT_FOUND->response([ 'message' => 'El expediente no tiene imágenes adjuntas.', 'record_id' => $id, ]); } // Crear instancia de FPDF $pdf = new Fpdf('P', 'mm', 'A4'); $pdf->SetAutoPageBreak(false); $pdf->SetMargins(10, 10, 10); $currentImage = 0; foreach ($record->files as $file) { $currentImage++; // Buscar archivo en disk 'records' $diskRecords = Storage::disk('records'); $fileContent = null; if ($diskRecords->exists($file->path)) { $fileContent = $diskRecords->get($file->path); } // Si no se encontró el archivo, continuar if ($fileContent === null) { continue; } // Agregar nueva página $pdf->AddPage(); // Header con folio $pdf->SetFillColor(44, 62, 80); $pdf->Rect(0, 0, 210, 20, 'F'); $pdf->SetTextColor(255, 255, 255); $pdf->SetFont('Arial', 'B', 14); $pdf->SetXY(10, 7); $pdf->Cell(0, 6, 'FOLIO: ' . $record->folio, 0, 1, 'L'); // Obtener ruta temporal del archivo $tempPath = tempnam(sys_get_temp_dir(), 'pdf_img_'); file_put_contents($tempPath, $fileContent); // Obtener dimensiones de la imagen $imageInfo = getimagesize($tempPath); if ($imageInfo !== false) { list($originalWidth, $originalHeight) = $imageInfo; $imageType = $imageInfo[2]; $availableWidth = 190; // 210mm - 20mm márgenes $availableHeight = 247; // 297mm - 20mm header - 20mm footer - 10mm márgenes // Calcular dimensiones manteniendo proporción $ratio = min($availableWidth / $originalWidth, $availableHeight / $originalHeight); $newWidth = $originalWidth * $ratio; $newHeight = $originalHeight * $ratio; // Centrar imagen $x = (210 - $newWidth) / 2; $y = 25 + (($availableHeight - $newHeight) / 2); // Determinar tipo de imagen $imageExtension = ''; switch ($imageType) { case IMAGETYPE_JPEG: $imageExtension = 'JPEG'; break; case IMAGETYPE_JPEG: $imageExtension = 'JPG'; break; case IMAGETYPE_PNG: $imageExtension = 'PNG'; break; default: // Si no es un formato soportado, continuar unlink($tempPath); continue 2; } // Insertar imagen $pdf->Image($tempPath, $x, $y, $newWidth, $newHeight, $imageExtension); } // Limpiar archivo temporal unlink($tempPath); } // Verificar que se agregaron páginas if ($pdf->PageNo() == 0) { return ApiResponse::NOT_FOUND->response([ 'message' => 'No se pudieron procesar las imágenes del expediente.', 'record_id' => $id, ]); } // Generar PDF $pdfContent = $pdf->Output('S'); return response($pdfContent, 200) ->header('Content-Type', 'application/pdf') ->header('Content-Disposition', 'inline; filename="expediente-imagenes-' . $record->folio . '.pdf"'); } catch (\Exception $e) { return ApiResponse::INTERNAL_ERROR->response([ 'message' => 'Error al generar el PDF de imágenes', 'error' => $e->getMessage(), ]); } } public function errors(Request $request) { $request->validate([ 'folio' => 'nullable|string', 'placa' => 'nullable|string', 'vin' => 'nullable|string', ]); $records = Record::with(['vehicle.owner', 'vehicle.tag', 'files', 'user', 'error']) ->whereNotNull('api_response') ->whereRaw("JSON_EXTRACT(api_response, '$.has_error') = true") ->orderBy('id', 'ASC'); if ($request->filled('folio')) { $records->where('folio', 'LIKE', '%' . $request->input('folio') . '%'); } if ($request->filled('placa')) { $records->whereHas('vehicle', function ($q) use ($request) { $q->where('placa', 'LIKE', '%' . $request->input('placa') . '%'); }); } if ($request->filled('vin')) { $records->whereHas('vehicle', function ($q) use ($request) { $q->where('niv', 'LIKE', '%' . $request->input('vin') . '%'); }); } return ApiResponse::OK->response([ 'message' => 'Expedientes con errores encontrados exitosamente', 'records' => $records->paginate(config('app.pagination')), ]); } }