@php /* * AR16 — Redesigned PDF label that mirrors the live HTML preview. * Grid sections: * Row 1: merchant logo + courier mark/mode * Row 2: deliver-to + order details * COD banner (if applicable) * Row 3: products table with footer total * Row 4: barcode + AWB text * Row 5: return-to block * Row 6: "Powered by Shipieons" * * `$wrappedInTile` is true when included inside the 4-up grid template — * we suppress the wrappers AND scale fonts down so 4 * labels fit on one A4 page without the layout breaking. * * DomPDF can't render ₹ in its default Helvetica build, so we use * "Rs." consistently — matches the reference label format anyway. */ $wrappedInTile = $wrappedInTile ?? false; $prefs = $prefs ?? new \App\Modules\Shipment\Models\MerchantLabelPreference; $courier = $courier ?? null; $buyer = $shipment->order?->buyer ?? []; $items = $shipment->order?->items ?? []; $codAmt = (float) ($shipment->order?->cod_amount ?? 0); $invAmt = (float) ($shipment->order?->order_value ?? 0); $isCod = $shipment->order?->payment_mode === 'cod'; $ps = $prefs->paper_size ?? 'thermal_4x6'; // Size buckets — compact for tile, big for A4, default for thermal/A6 if ($wrappedInTile) { $fSm = 5.5; $fBase = 6.5; $fMd = 7.5; $fLg = 9; $fXl = 10.5; $pad = 2.5; $rowMin = 32; $barcodeH = 28; $logoH = 22; $courierR = 26; } elseif ($ps === 'a4') { $fSm = 9; $fBase = 11; $fMd = 13; $fLg = 17; $fXl = 22; $pad = 8; $rowMin = 72; $barcodeH = 70; $logoH = 60; $courierR = 60; } else { $fSm = 6.5; $fBase = 8.5; $fMd = 10; $fLg = 13; $fXl = 16; $pad = 5; $rowMin = 50; $barcodeH = 50; $logoH = 40; $courierR = 42; } // Truncate helpers $trim = fn ($s, $n) => mb_strlen($s) > $n ? mb_substr($s, 0, $n - 1).'…' : $s; $nameLimit = (int) ($prefs->product_name_limit ?: 60); $skuLimit = (int) ($prefs->sku_limit ?: 24); $totalQty = 0; $totalPrice = 0; foreach ($items as $it) { $totalQty += (int) ($it['qty'] ?? 1); $totalPrice += (float) ($it['price'] ?? 0) * (int) ($it['qty'] ?? 1); } // AR18 — Cap visible product rows so a merchant with 20 SKUs in one // order doesn't blow the label height. The Total row still reflects // ALL items; we just collapse the overflow into a "+N more SKUs" line. if ($wrappedInTile) { $visibleProductCount = 2; // 4-up tile is tiny } elseif ($ps === 'a4') { $visibleProductCount = 8; // A4 has lots of room } else { $visibleProductCount = 4; // thermal/a6 } $visibleItems = array_slice($items, 0, $visibleProductCount); $overflowCount = max(0, count($items) - $visibleProductCount); // AR19 — Real Code128 barcode generated as a PNG and embedded as a // base64 data URL. The earlier HTML-divs approach (Picqer's // BarcodeGeneratorHTML) used absolutely-positioned
bars which // DomPDF can't reliably render inside table cells — the barcode area // came out blank. PNGs through data: URLs are bullet-proof in DomPDF. $barcodeImg = ''; $barcodeWidthPt = 0; $barcodeHeightPt = 0; if (! empty($shipment->awb) && function_exists('imagecreatetruecolor')) { try { $gen = new \Picqer\Barcode\BarcodeGeneratorPNG; // widthFactor sets the px-per-module — pick by paper size for a // crisp, scannable barcode that fits the row width comfortably. $widthFactor = $wrappedInTile ? 1 : ($ps === 'a4' ? 3 : 2); $heightPx = $wrappedInTile ? 32 : ($ps === 'a4' ? 80 : 56); $png = $gen->getBarcode((string) $shipment->awb, $gen::TYPE_CODE_128, $widthFactor, $heightPx); $barcodeImg = 'data:image/png;base64,' . base64_encode($png); // Derived display size in pt — px-as-pt at 0.6 ratio works well // because DomPDF treats 1px ≈ 1pt by default and the barcode // was generated with extra resolution. $barcodeWidthPt = $wrappedInTile ? 180 : ($ps === 'a4' ? 360 : 240); $barcodeHeightPt = $wrappedInTile ? 22 : ($ps === 'a4' ? 70 : 48); } catch (\Throwable $e) { $barcodeImg = ''; } } @endphp @if(! $wrappedInTile) Shipping Label — {{ $shipment->awb }} @endif {{-- ── Row 1 — Merchant logo (left) | Courier mark + mode (right) ── --}} {{-- ── Row 2 — Deliver To | Order details ── --}} {{-- ── COD banner ── --}} @if($prefs->show_cod_amount && $isCod && $codAmt > 0) @endif {{-- ── Row 3 — Products table ── --}} @if(! empty($items) && ($prefs->show_product_name || $prefs->show_sku || $prefs->show_quantity || $prefs->show_item_price)) @endif {{-- ── Row 4 — Real Code128 barcode (PNG) + AWB text ── --}} {{-- ── Row 5 — Return-to ── --}} {{-- ── Row 6 — Powered by Shipieons (platform brand) ── --}}
@if($prefs->show_seller_logo && $prefs->seller_logo_path && file_exists(public_path('storage/'.$prefs->seller_logo_path))) @else
{{ $prefs->return_address_name ?: 'Shipieons' }}
@endif
{{ $courier?->code ? strtoupper(substr($courier->code, 0, 3)) : 'CRR' }}
{{ strtoupper($shipment->mode ?? 'Surface') }}
Deliver To : {{ data_get($buyer, 'name', '—') }}
@if(data_get($buyer, 'phone'))
Contact : {{ data_get($buyer, 'phone') }}
@endif
Address : {{ data_get($buyer, 'address', '—') }} @if(data_get($buyer, 'city')), {{ data_get($buyer, 'city') }}@endif @if(data_get($buyer, 'state')) {{ data_get($buyer, 'state') }}@endif @if(data_get($buyer, 'pincode')) {{ data_get($buyer, 'pincode') }}@endif
Pin : {{ data_get($buyer, 'pincode', '—') }}
Payment Type : {{ $isCod ? 'COD' : 'Prepaid' }}
Order Id : {{ $shipment->order?->order_number ?? '—' }}
Date : {{ optional($shipment->booked_at ?? $shipment->created_at)->format('Y-m-d') ?? now()->format('Y-m-d') }}
@if($prefs->show_invoice_value)
Invoice Value : Rs. {{ number_format($invAmt, 2) }}
@endif @if($prefs->show_weight)
Weight : {{ number_format((float) ($shipment->chargeable_weight_kg ?? 0.5), 2) }} KG
@endif @if($prefs->show_dimensions && $shipment->declared_dims_cm)
Dimensions : {{ data_get($shipment->declared_dims_cm, 'l') }}×{{ data_get($shipment->declared_dims_cm, 'b') }}×{{ data_get($shipment->declared_dims_cm, 'h') }} cm
@endif @if($prefs->show_edd && $shipment->edd)
EDD : {{ $shipment->edd->format('d M Y') }}
@endif @if($prefs->show_invoice_number)
Inv No : INV-{{ str_pad((string) ($shipment->order?->id ?? 0), 4, '0', STR_PAD_LEFT) }}
@endif @if($courier)
Courier : {{ $courier->name }}
@endif
COD Rs. {{ number_format($codAmt, 2) }} — Cash on Delivery
@if($prefs->show_product_name)@endif @if($prefs->show_sku)@endif @if($prefs->show_quantity)@endif @if($prefs->show_item_price)@endif @foreach($visibleItems as $it) @if($prefs->show_product_name)@endif @if($prefs->show_sku)@endif @if($prefs->show_quantity)@endif @if($prefs->show_item_price)@endif @endforeach @if($overflowCount > 0) @php $colSpan = 0; if ($prefs->show_product_name) { $colSpan++; } if ($prefs->show_sku) { $colSpan++; } if ($prefs->show_quantity) { $colSpan++; } if ($prefs->show_item_price) { $colSpan++; } @endphp @endif @if($prefs->show_product_name)@endif @if($prefs->show_sku)@endif @if($prefs->show_quantity)@endif @if($prefs->show_item_price)@endif
Product NameSKUQtyPrice
{{ $trim($it['name'] ?? '', $nameLimit) }}{{ $trim($it['sku'] ?? '', $skuLimit) }}{{ (int) ($it['qty'] ?? 1) }}{{ number_format((float) ($it['price'] ?? 0), 2) }}
+ {{ $overflowCount }} more SKU{{ $overflowCount === 1 ? '' : 's' }}
Total{{ $totalQty }}Rs. {{ number_format($totalPrice, 2) }}
@if($barcodeImg) Code128 barcode for {{ $shipment->awb }} @endif
{{ $shipment->awb ?? 'SAMPLE-AWB' }}
If not delivered, Return to :
{{ $prefs->return_address_line ?: '—' }} @if($prefs->return_address_city), {{ $prefs->return_address_city }}@endif @if($prefs->return_address_state) {{ $prefs->return_address_state }}@endif @if($prefs->return_address_pincode) {{ $prefs->return_address_pincode }}@endif
Contact Name : {{ $prefs->return_address_name ?: '—' }}
Company Name : {{ $prefs->return_address_name ?: 'Shipieons' }}
@if($prefs->show_seller_mobile && $prefs->return_address_phone ?? null)
Phone : {{ $prefs->return_address_phone }}
@endif
Powered by Shipieons
@if(! $wrappedInTile) @endif