12f42d5efc
- Changed from View::make() to View::file() with full path resolution
- Added file existence check with detailed error logging
- Allow GET/POST for regenerate sticker endpoint for easier testing
- Add design name and customer surname to A6 PDF stickers
- Add regenerate sticker endpoint POST /test/sticker/{orderNumber}/regenerate
- Add test sticker preview page at /test/sticker/{orderNumber}
168 lines
5.1 KiB
PHP
168 lines
5.1 KiB
PHP
<?php
|
||
|
||
namespace App\Services;
|
||
|
||
use App\Models\Order;
|
||
use Barryvdh\DomPDF\Facade\Pdf;
|
||
use chillerlan\QRCode\QRCode;
|
||
use chillerlan\QRCode\QROptions;
|
||
use Illuminate\Support\Facades\Log;
|
||
use Illuminate\Support\Facades\Storage;
|
||
use Illuminate\Support\Facades\View;
|
||
|
||
class QrStickerService
|
||
{
|
||
/**
|
||
* Generate both SVG and A6 PDF sticker for an order
|
||
*/
|
||
public function generateSticker(Order $order): array
|
||
{
|
||
try {
|
||
// Generate QR code URL
|
||
$qrUrl = route('ops.order.show', ['token' => $order->qr_token]);
|
||
|
||
Log::debug('Generating QR sticker', [
|
||
'order_uuid' => $order->uuid,
|
||
'order_number' => $order->order_number,
|
||
'qr_url' => $qrUrl,
|
||
]);
|
||
|
||
// Generate SVG (for web display)
|
||
$svgPath = $this->generateSvg($order, $qrUrl);
|
||
|
||
// Generate A6 PDF (for printing)
|
||
$pdfPath = $this->generatePdf($order, $qrUrl);
|
||
|
||
Log::info('QR sticker generated successfully', [
|
||
'order_uuid' => $order->uuid,
|
||
'svg_path' => $svgPath,
|
||
'pdf_path' => $pdfPath,
|
||
]);
|
||
|
||
return [
|
||
'svg_path' => $svgPath,
|
||
'pdf_path' => $pdfPath,
|
||
];
|
||
} catch (\Exception $e) {
|
||
Log::error('Failed to generate QR sticker', [
|
||
'order_uuid' => $order->uuid,
|
||
'error' => $e->getMessage(),
|
||
]);
|
||
|
||
throw $e;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Generate SVG QR code for web display
|
||
*/
|
||
private function generateSvg(Order $order, string $qrUrl): string
|
||
{
|
||
$options = new QROptions([
|
||
'outputType' => QRCode::OUTPUT_MARKUP_SVG,
|
||
'eccLevel' => QRCode::ECC_H,
|
||
'scale' => 3,
|
||
'imageBase64' => false,
|
||
]);
|
||
|
||
$qrCode = new QRCode($options);
|
||
$qrSvg = $qrCode->render($qrUrl);
|
||
|
||
$path = "qr-codes/{$order->uuid}.svg";
|
||
Storage::disk('public')->put($path, $qrSvg);
|
||
|
||
return $path;
|
||
}
|
||
|
||
/**
|
||
* Generate A6 PDF sticker (105mm × 148mm) with QR code and readable info
|
||
*
|
||
* A6 dimensions: 105mm × 148mm landscape
|
||
* Margins: 5mm all around
|
||
* QR size: ~50mm × 50mm
|
||
* Text area: remaining space for order info
|
||
*/
|
||
private function generatePdf(Order $order, string $qrUrl): string
|
||
{
|
||
// Generate inline QR code as SVG
|
||
$options = new QROptions([
|
||
'outputType' => QRCode::OUTPUT_MARKUP_SVG,
|
||
'eccLevel' => QRCode::ECC_H,
|
||
'scale' => 4,
|
||
'imageBase64' => false,
|
||
]);
|
||
|
||
$qrCode = new QRCode($options);
|
||
$qrSvg = $qrCode->render($qrUrl);
|
||
|
||
// Determine order type and format label
|
||
$orderType = $order->type === 'standard'
|
||
? 'STOCK ORDER'
|
||
: 'CUSTOM ORDER';
|
||
|
||
// Extract design name from first order item
|
||
$designName = '';
|
||
if ($order->items && $order->items->count() > 0) {
|
||
$firstItem = $order->items->first();
|
||
$designName = $firstItem->product?->name ?? $firstItem->name ?? 'Custom Design';
|
||
}
|
||
|
||
// Extract customer surname (last word of name)
|
||
$customerName = $order->user?->name ?? '';
|
||
$nameParts = explode(' ', trim($customerName));
|
||
$customerSurname = end($nameParts);
|
||
|
||
// Prepare data for the view
|
||
$data = [
|
||
'order' => $order,
|
||
'qrSvg' => $qrSvg,
|
||
'orderType' => $orderType,
|
||
'designName' => $designName,
|
||
'customerSurname' => $customerSurname,
|
||
'qrUrl' => $qrUrl,
|
||
'generatedAt' => now()->format('Y-m-d H:i'),
|
||
];
|
||
|
||
// Render the view to HTML first
|
||
try {
|
||
$viewPath = resource_path('views/stickers/qr-sticker.blade.php');
|
||
if (!file_exists($viewPath)) {
|
||
throw new \Exception("View file not found at: {$viewPath}");
|
||
}
|
||
|
||
// Compile and render the view
|
||
$html = View::file($viewPath, $data)->render();
|
||
} catch (\Exception $e) {
|
||
Log::error('Failed to render sticker view', [
|
||
'order_uuid' => $order->uuid,
|
||
'error' => $e->getMessage(),
|
||
'view_path' => $viewPath ?? 'unknown',
|
||
]);
|
||
throw $e;
|
||
}
|
||
|
||
// Generate PDF from HTML using DomPDF
|
||
try {
|
||
$pdf = Pdf::loadHTML($html);
|
||
|
||
// Configure for A6 landscape
|
||
// A6 is 105mm × 148mm (landscape: 148mm × 105mm)
|
||
$pdf->setPaper([0, 0, 420.94, 297.64], 'portrait'); // 148mm × 105mm in points (1mm ≈ 2.834645669 points)
|
||
|
||
// Store PDF
|
||
$filename = "{$order->uuid}.pdf";
|
||
$path = "qr-stickers/{$filename}";
|
||
$pdfContent = $pdf->output();
|
||
Storage::disk('public')->put($path, $pdfContent);
|
||
|
||
return $path;
|
||
} catch (\Exception $e) {
|
||
Log::error('DomPDF generation failed', [
|
||
'order_uuid' => $order->uuid,
|
||
'error' => $e->getMessage(),
|
||
]);
|
||
throw $e;
|
||
}
|
||
}
|
||
}
|