selectRaw('o.*, o.ordered_customer as customer, CONCAT_WS(\' \', o.owner_last_name, o.owner_first_name, o.owner_patronymic) as owner') ->where('o.id', $id)->first(); if ($order) { $dillerUser = $order->diller_id ? DB::table('users')->find($order->diller_id) : null; $order->diller = $dillerUser->name ?? ''; } return view('conclusion.add', compact('id', 'type', 'order')); } public function store(Request $request) { $orderId = $request->input('order_id'); $orderType = $request->input('order_type'); // 'AUTO' or 'ESTATE' $dbType = $orderType === 'AUTO' ? 'auto_' : 'estate_'; $table = $orderType === 'AUTO' ? 'auto_orders' : 'estate_orders'; // Update order prices $updateData = ['updated_at' => now()]; if ($request->filled('object_price')) { $updateData['object_price'] = preg_replace('/\D/', '', $request->object_price); } if ($request->filled('price')) { $updateData['price'] = preg_replace('/\D/', '', $request->price); } DB::table($table)->where('id', $orderId)->update($updateData); // Create debit if is_diller = yes if ($request->input('is_diller') === 'yes') { $order = DB::table($table)->find($orderId); DB::table('debits')->insert([ 'order_id' => $orderId, 'order_type' => $dbType, 'appraiser_id' => auth()->id(), 'cost' => $order->cost ?? 0, 'status' => 'nopaid', 'expired' => $request->input('expired'), 'customer' => $order->ordered_customer ?? '', 'created_at' => now(), 'updated_at' => now(), ]); } // Handle PDF file upload with QR watermark if ($request->hasFile('file')) { $file = $request->file('file'); $ext = strtolower($file->getClientOriginalExtension()); $name = pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME); $size = $file->getSize(); $dir = 'public/attachments/' . $dbType . $orderId; Storage::makeDirectory($dir); $tmpPath = $file->getPathname(); $outputName = Str::uuid() . '.pdf'; $outputPath = storage_path('app/' . $dir . '/' . $outputName); if ($ext === 'pdf') { // Add QR watermark to PDF try { $qrPath = storage_path('app/public/attachments/' . $dbType . $orderId . '/qr.png'); if (!file_exists($qrPath)) { Storage::makeDirectory('public/attachments/' . $dbType . $orderId); $cleanType = strtolower($orderType); $qrContent = route('qr.verify', ['type' => $cleanType, 'id' => $orderId]); $qrImage = QrCode::format('png')->size(150)->generate($qrContent); file_put_contents($qrPath, $qrImage); chmod($qrPath, 0644); } // Convert PDF to 1.4 compatible format so FPDI can parse any PDF version $gsTmp = tempnam(sys_get_temp_dir(), 'gs_') . '.pdf'; exec('gs -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -sOutputFile=' . escapeshellarg($gsTmp) . ' ' . escapeshellarg($tmpPath) . ' 2>/dev/null', $gsOut, $gsCode); if ($gsCode === 0 && file_exists($gsTmp) && filesize($gsTmp) > 0) { $tmpPath = $gsTmp; } $pdf = new Fpdi(); $pageCount = $pdf->setSourceFile($tmpPath); $qrSize = 30; // mm for ($i = 1; $i <= $pageCount; $i++) { $tpl = $pdf->importPage($i); $size2 = $pdf->getTemplateSize($tpl); $pdf->AddPage($size2['orientation'], [$size2['width'], $size2['height']]); $pdf->useTemplate($tpl); if ($i === 1) { // First page: right side, in the blank area below header separator lines $sz = 35; $qrX = $size2['width'] - $sz - 18; $qrY = 15; } else { // Other pages: bottom-right $sz = 22; $qrX = $size2['width'] - $sz - 8; $qrY = $size2['height'] - $sz - 6; } $pdf->SetFillColor(255, 255, 255); $pdf->Rect($qrX - 1, $qrY - 1, $sz + 2, $sz + 2, 'F'); $pdf->Image($qrPath, $qrX, $qrY, $sz, $sz); } // Append certificates from the database $certificates = DB::table('certificates')->orderBy('sort')->get(); foreach ($certificates as $certificate) { $certPath = storage_path('app/' . $certificate->path); if (file_exists($certPath)) { $extCert = strtolower(pathinfo($certPath, PATHINFO_EXTENSION)); if ($extCert === 'pdf') { $certPageCount = $pdf->setSourceFile($certPath); for ($j = 1; $j <= $certPageCount; $j++) { $tplCert = $pdf->importPage($j); $sizeCert = $pdf->getTemplateSize($tplCert); $pdf->AddPage($sizeCert['orientation'], [$sizeCert['width'], $sizeCert['height']]); $pdf->useTemplate($tplCert); $cqX = $sizeCert['width'] - 22 - 8; $cqY = $sizeCert['height'] - 22 - 6; $pdf->SetFillColor(255, 255, 255); $pdf->Rect($cqX - 1, $cqY - 1, 24, 24, 'F'); $pdf->Image($qrPath, $cqX, $cqY, 22, 22); } } elseif (in_array($extCert, ['jpg', 'jpeg', 'png'])) { $pdf->AddPage('P', 'A4'); $pdf->Image($certPath, 0, 0, 210, 297); $pdf->SetFillColor(255, 255, 255); $pdf->Rect(210 - 22 - 8 - 1, 297 - 22 - 6 - 1, 24, 24, 'F'); $pdf->Image($qrPath, 210 - 22 - 8, 297 - 22 - 6, 22, 22); } } } $pdf->Output('F', $outputPath); } catch (\Exception $e) { \Illuminate\Support\Facades\Log::error('ConclusionController PDF/QR failed: ' . $e->getMessage(), [ 'order_id' => $orderId, 'type' => $orderType, 'file' => $e->getFile(), 'line' => $e->getLine(), ]); copy($tmpPath, $outputPath); } } else { $file->move(storage_path('app/' . $dir), $outputName); } $storagePath = '/storage/attachments/' . $dbType . $orderId . '/' . $outputName; DB::table('files')->insert([ 'id' => (string) Str::uuid(), 'path' => $storagePath, 'extension' => $ext, 'order_id' => $orderId, 'order_type' => 'conclusion_', 'type' => 'conclusion', 'name' => $name, 'size' => round($size / 1024 / 1024, 2), 'size_in_bytes' => $size, 'created_at' => now(), 'updated_at' => now(), ]); DB::table($table)->where('id', $orderId)->update([ 'status' => \App\Enums\OrderStatusEnum::FINISHED->name, 'updated_at' => now(), ]); } $route = $orderType === 'AUTO' ? 'auto.show' : 'estate.show'; return redirect()->route($route, $orderId); } public function reject(Request $request) { $orderId = $request->input('order_id'); $orderType = $request->input('order_type'); // 'AUTO' or 'ESTATE' $table = $orderType === 'AUTO' ? 'auto_orders' : 'estate_orders'; DB::table($table)->where('id', $orderId)->update([ 'status' => 'rejected', 'updated_at' => now(), ]); return redirect()->back(); } public function testWaterMark() { return view('conclusion.watermark'); } }