feat(shipment): implement PDF generation for AWB, invoice, and labels
Introduce PDF generation capabilities for shipments using laravel-dompdf. This includes a new service layer, dedicated controller, and routes to handle the generation of Air Waybills (AWB), Invoices, and Shipping Labels. - Add `PdfService` to encapsulate PDF generation logic. - Add `ShipmentPdfController` to handle PDF download requests. - Integrate `barryvdh/laravel-dompdf` dependency. - Add Filament header actions to view shipment pages for quick PDF access. - Update order success view to provide direct download links for documents. - Add label methods to `ShipmentDirection` and `ShipmentType` enums. - Update project status documentation to reflect initial PDF implementation.
This commit is contained in:
parent
24fc56feaf
commit
5874568c63
@ -237,7 +237,7 @@
|
|||||||
- [ ] موتور قیمتگذاری کامل (PriceCalculatorService) — نوشته شد، نیاز به تست با دادههای واقعی
|
- [ ] موتور قیمتگذاری کامل (PriceCalculatorService) — نوشته شد، نیاز به تست با دادههای واقعی
|
||||||
- [ ] جدول `shipping_rates` — ۴۰۴ رکورد import شد، نیاز به تکمیل
|
- [ ] جدول `shipping_rates` — ۴۰۴ رکورد import شد، نیاز به تکمیل
|
||||||
- [ ] فرم ثبت سفارش آنلاین با ۹ ردیف کالای گمرکی
|
- [ ] فرم ثبت سفارش آنلاین با ۹ ردیف کالای گمرکی
|
||||||
- [ ] تولید PDF: AWB، INVOICE، Label مطابق قالب اکسل
|
- [ ] تولید PDF: AWB، INVOICE، Label مطابق قالب اکسل — اولیه پیاده شد، نیاز به تطبیق دقیق با قالبهای اکسل و رفع ساختار فعلی
|
||||||
- [ ] ماژول ایمپورت اکسل تعرفهها
|
- [ ] ماژول ایمپورت اکسل تعرفهها
|
||||||
- [ ] صفحه استعلام قیمت واقعی
|
- [ ] صفحه استعلام قیمت واقعی
|
||||||
|
|
||||||
|
|||||||
@ -6,4 +6,12 @@ enum ShipmentDirection: string
|
|||||||
{
|
{
|
||||||
case Import = 'import';
|
case Import = 'import';
|
||||||
case Export = 'export';
|
case Export = 'export';
|
||||||
|
|
||||||
|
public function label(): string
|
||||||
|
{
|
||||||
|
return match($this) {
|
||||||
|
self::Import => 'Import',
|
||||||
|
self::Export => 'Export',
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,4 +7,13 @@ enum ShipmentType: string
|
|||||||
case DocNormal = 'DOC_NORMAL';
|
case DocNormal = 'DOC_NORMAL';
|
||||||
case DocEconomy = 'DOC_ECONOMY';
|
case DocEconomy = 'DOC_ECONOMY';
|
||||||
case Parcel = 'PARCEL';
|
case Parcel = 'PARCEL';
|
||||||
|
|
||||||
|
public function label(): string
|
||||||
|
{
|
||||||
|
return match($this) {
|
||||||
|
self::DocNormal => 'Document Normal',
|
||||||
|
self::DocEconomy => 'Document Economy',
|
||||||
|
self::Parcel => 'Parcel',
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,4 +9,28 @@ use Filament\Resources\Pages\ViewRecord;
|
|||||||
class ViewShipment extends ViewRecord
|
class ViewShipment extends ViewRecord
|
||||||
{
|
{
|
||||||
protected static string $resource = ShipmentResource::class;
|
protected static string $resource = ShipmentResource::class;
|
||||||
|
|
||||||
|
protected function getHeaderActions(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
Actions\Action::make('print_label')
|
||||||
|
->label('چاپ لیبل')
|
||||||
|
->icon('heroicon-o-printer')
|
||||||
|
->color('success')
|
||||||
|
->url(fn ($record) => route('shipments.pdf.label', $record))
|
||||||
|
->openUrlInNewTab(),
|
||||||
|
|
||||||
|
Actions\Action::make('download_awb')
|
||||||
|
->label('دانلود AWB')
|
||||||
|
->icon('heroicon-o-document-text')
|
||||||
|
->color('warning')
|
||||||
|
->url(fn ($record) => route('shipments.pdf.awb', $record)),
|
||||||
|
|
||||||
|
Actions\Action::make('download_invoice')
|
||||||
|
->label('دانلود INVOICE')
|
||||||
|
->icon('heroicon-o-currency-dollar')
|
||||||
|
->color('info')
|
||||||
|
->url(fn ($record) => route('shipments.pdf.invoice', $record)),
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
60
04_Laravel/app/Http/Controllers/ShipmentPdfController.php
Normal file
60
04_Laravel/app/Http/Controllers/ShipmentPdfController.php
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\Shipment;
|
||||||
|
use App\Services\PdfService;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
|
class ShipmentPdfController extends Controller
|
||||||
|
{
|
||||||
|
public function __construct(protected PdfService $pdf) {}
|
||||||
|
|
||||||
|
public function awb(Shipment $shipment)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
Log::info('Generating AWB PDF', ['shipment_id' => $shipment->id]);
|
||||||
|
$content = $this->pdf->awb($shipment);
|
||||||
|
Log::info('AWB PDF generated successfully');
|
||||||
|
return response($content, 200, [
|
||||||
|
'Content-Type' => 'application/pdf',
|
||||||
|
'Content-Disposition' => 'attachment; filename="AWB-' . $shipment->awb_no . '.pdf"',
|
||||||
|
]);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Log::error('AWB PDF generation failed', [
|
||||||
|
'error' => $e->getMessage(),
|
||||||
|
'trace' => $e->getTraceAsString(),
|
||||||
|
]);
|
||||||
|
return response('PDF generation failed: ' . $e->getMessage(), 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function invoice(Shipment $shipment)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$content = $this->pdf->invoice($shipment);
|
||||||
|
return response($content, 200, [
|
||||||
|
'Content-Type' => 'application/pdf',
|
||||||
|
'Content-Disposition' => 'attachment; filename="INVOICE-' . $shipment->awb_no . '.pdf"',
|
||||||
|
]);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Log::error('Invoice PDF generation failed', ['error' => $e->getMessage()]);
|
||||||
|
return response('PDF generation failed: ' . $e->getMessage(), 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function label(Shipment $shipment)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$content = $this->pdf->label($shipment);
|
||||||
|
return response($content, 200, [
|
||||||
|
'Content-Type' => 'application/pdf',
|
||||||
|
'Content-Disposition' => 'attachment; filename="LABEL-' . $shipment->awb_no . '.pdf"',
|
||||||
|
]);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Log::error('Label PDF generation failed', ['error' => $e->getMessage()]);
|
||||||
|
return response('PDF generation failed: ' . $e->getMessage(), 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
96
04_Laravel/app/Services/PdfService.php
Normal file
96
04_Laravel/app/Services/PdfService.php
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services;
|
||||||
|
|
||||||
|
use App\Models\Shipment;
|
||||||
|
use App\Models\ShipmentItem;
|
||||||
|
use Dompdf\Dompdf;
|
||||||
|
use Dompdf\Options;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
class PdfService
|
||||||
|
{
|
||||||
|
public function awb(Shipment $shipment): string
|
||||||
|
{
|
||||||
|
$shipment->loadMissing(['fromCountry', 'toCountry', 'items']);
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'shipment' => $shipment,
|
||||||
|
'shipper' => $this->formatAddress($shipment, 'sender'),
|
||||||
|
'receiver' => $this->formatAddress($shipment, 'receiver'),
|
||||||
|
'items' => $shipment->items ?? collect(),
|
||||||
|
'invoice_total_usd' => optional($shipment->items)->sum('total_usd') ?? 0,
|
||||||
|
];
|
||||||
|
|
||||||
|
$html = view('pdfs.awb', $data)->render();
|
||||||
|
|
||||||
|
return $this->generatePdf($html, 'A4', 'portrait');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function invoice(Shipment $shipment): string
|
||||||
|
{
|
||||||
|
$shipment->loadMissing(['fromCountry', 'toCountry', 'items']);
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'shipment' => $shipment,
|
||||||
|
'shipper' => $this->formatAddress($shipment, 'sender'),
|
||||||
|
'receiver' => $this->formatAddress($shipment, 'receiver'),
|
||||||
|
'items' => $shipment->items ?? collect(),
|
||||||
|
'invoice_total_usd' => optional($shipment->items)->sum('total_usd') ?? 0,
|
||||||
|
];
|
||||||
|
|
||||||
|
$html = view('pdfs.invoice', $data)->render();
|
||||||
|
|
||||||
|
return $this->generatePdf($html, 'A4', 'portrait');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function label(Shipment $shipment): string
|
||||||
|
{
|
||||||
|
$shipment->loadMissing(['fromCountry', 'toCountry']);
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'shipment' => $shipment,
|
||||||
|
'shipper' => $this->formatAddress($shipment, 'sender'),
|
||||||
|
'receiver' => $this->formatAddress($shipment, 'receiver'),
|
||||||
|
];
|
||||||
|
|
||||||
|
$html = view('pdfs.label', $data)->render();
|
||||||
|
|
||||||
|
return $this->generatePdf($html, [0, 0, 80, 120], 'portrait');
|
||||||
|
}
|
||||||
|
|
||||||
|
private function generatePdf(string $html, array|string $paper, string $orientation): string
|
||||||
|
{
|
||||||
|
$options = new Options();
|
||||||
|
$options->set('isHtml5ParserEnabled', true);
|
||||||
|
$options->set('isRemoteEnabled', true);
|
||||||
|
$options->set('defaultFont', 'DejaVu Sans');
|
||||||
|
|
||||||
|
$dompdf = new Dompdf($options);
|
||||||
|
$dompdf->loadHtml($html);
|
||||||
|
|
||||||
|
if (is_array($paper)) {
|
||||||
|
$dompdf->setPaper($paper, $orientation);
|
||||||
|
} else {
|
||||||
|
$dompdf->setPaper($paper, $orientation);
|
||||||
|
}
|
||||||
|
|
||||||
|
$dompdf->render();
|
||||||
|
|
||||||
|
return $dompdf->output();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function formatAddress(Shipment $shipment, string $prefix): Collection
|
||||||
|
{
|
||||||
|
return collect([
|
||||||
|
'name' => $shipment->{$prefix . '_name'},
|
||||||
|
'company' => $shipment->{$prefix . '_company'},
|
||||||
|
'phone' => $shipment->{$prefix . '_phone'},
|
||||||
|
'email' => $shipment->{$prefix . '_email'},
|
||||||
|
'address' => $shipment->{$prefix . '_address'},
|
||||||
|
'city' => $shipment->{$prefix . '_city'},
|
||||||
|
'zip' => $shipment->{$prefix . '_zip'},
|
||||||
|
'id_number' => $shipment->{$prefix . '_id_number'},
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -7,6 +7,7 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^8.2",
|
"php": "^8.2",
|
||||||
|
"barryvdh/laravel-dompdf": "*",
|
||||||
"filament/filament": "3.3.*",
|
"filament/filament": "3.3.*",
|
||||||
"laravel/framework": "^11.0",
|
"laravel/framework": "^11.0",
|
||||||
"laravel/tinker": "^2.10.1",
|
"laravel/tinker": "^2.10.1",
|
||||||
|
|||||||
457
04_Laravel/composer.lock
generated
457
04_Laravel/composer.lock
generated
@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "36a7ef85e0bbcd022965ce2b7234718f",
|
"content-hash": "c0d4db086122fe759e56ff3bf438bc30",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "anourvalar/eloquent-serialize",
|
"name": "anourvalar/eloquent-serialize",
|
||||||
@ -71,6 +71,83 @@
|
|||||||
},
|
},
|
||||||
"time": "2026-06-20T14:30:25+00:00"
|
"time": "2026-06-20T14:30:25+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "barryvdh/laravel-dompdf",
|
||||||
|
"version": "v3.1.2",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/barryvdh/laravel-dompdf.git",
|
||||||
|
"reference": "ee3b72b19ccdf57d0243116ecb2b90261344dedc"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/barryvdh/laravel-dompdf/zipball/ee3b72b19ccdf57d0243116ecb2b90261344dedc",
|
||||||
|
"reference": "ee3b72b19ccdf57d0243116ecb2b90261344dedc",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"dompdf/dompdf": "^3.0",
|
||||||
|
"illuminate/support": "^9|^10|^11|^12|^13.0",
|
||||||
|
"php": "^8.1"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"larastan/larastan": "^2.7|^3.0",
|
||||||
|
"orchestra/testbench": "^7|^8|^9.16|^10|^11.0",
|
||||||
|
"phpro/grumphp": "^2.5",
|
||||||
|
"squizlabs/php_codesniffer": "^3.5"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"laravel": {
|
||||||
|
"aliases": {
|
||||||
|
"PDF": "Barryvdh\\DomPDF\\Facade\\Pdf",
|
||||||
|
"Pdf": "Barryvdh\\DomPDF\\Facade\\Pdf"
|
||||||
|
},
|
||||||
|
"providers": [
|
||||||
|
"Barryvdh\\DomPDF\\ServiceProvider"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "3.0-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Barryvdh\\DomPDF\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Barry vd. Heuvel",
|
||||||
|
"email": "barryvdh@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "A DOMPDF Wrapper for Laravel",
|
||||||
|
"keywords": [
|
||||||
|
"dompdf",
|
||||||
|
"laravel",
|
||||||
|
"pdf"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/barryvdh/laravel-dompdf/issues",
|
||||||
|
"source": "https://github.com/barryvdh/laravel-dompdf/tree/v3.1.2"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://fruitcake.nl",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/barryvdh",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2026-02-21T08:51:10+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "beberlei/assert",
|
"name": "beberlei/assert",
|
||||||
"version": "v3.3.4",
|
"version": "v3.3.4",
|
||||||
@ -1071,6 +1148,161 @@
|
|||||||
],
|
],
|
||||||
"time": "2024-02-05T11:56:58+00:00"
|
"time": "2024-02-05T11:56:58+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "dompdf/dompdf",
|
||||||
|
"version": "v3.1.6",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/dompdf/dompdf.git",
|
||||||
|
"reference": "6d4b4eb8500f7a786da8868ba463a71b725a4005"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/dompdf/dompdf/zipball/6d4b4eb8500f7a786da8868ba463a71b725a4005",
|
||||||
|
"reference": "6d4b4eb8500f7a786da8868ba463a71b725a4005",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"dompdf/php-font-lib": "^1.0.0",
|
||||||
|
"dompdf/php-svg-lib": "^1.0.0",
|
||||||
|
"ext-dom": "*",
|
||||||
|
"ext-mbstring": "*",
|
||||||
|
"masterminds/html5": "^2.0",
|
||||||
|
"php": "^7.1 || ^8.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"ext-gd": "*",
|
||||||
|
"ext-json": "*",
|
||||||
|
"ext-zip": "*",
|
||||||
|
"mockery/mockery": "^1.3",
|
||||||
|
"phpunit/phpunit": "^7.5 || ^8 || ^9 || ^10 || ^11",
|
||||||
|
"squizlabs/php_codesniffer": "^3.5",
|
||||||
|
"symfony/process": "^4.4 || ^5.4 || ^6.2 || ^7.0"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"ext-gd": "Needed to process images",
|
||||||
|
"ext-gmagick": "Improves image processing performance",
|
||||||
|
"ext-imagick": "Improves image processing performance",
|
||||||
|
"ext-zlib": "Needed for pdf stream compression"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Dompdf\\": "src/"
|
||||||
|
},
|
||||||
|
"classmap": [
|
||||||
|
"lib/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"LGPL-2.1"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "The Dompdf Community",
|
||||||
|
"homepage": "https://github.com/dompdf/dompdf/blob/master/AUTHORS.md"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "DOMPDF is a CSS 2.1 compliant HTML to PDF converter",
|
||||||
|
"homepage": "https://github.com/dompdf/dompdf",
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/dompdf/dompdf/issues",
|
||||||
|
"source": "https://github.com/dompdf/dompdf/tree/v3.1.6"
|
||||||
|
},
|
||||||
|
"time": "2026-07-20T12:29:38+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "dompdf/php-font-lib",
|
||||||
|
"version": "1.0.2",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/dompdf/php-font-lib.git",
|
||||||
|
"reference": "a6e9a688a2a80016ac080b97be73d3e10c444c9a"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/dompdf/php-font-lib/zipball/a6e9a688a2a80016ac080b97be73d3e10c444c9a",
|
||||||
|
"reference": "a6e9a688a2a80016ac080b97be73d3e10c444c9a",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-mbstring": "*",
|
||||||
|
"php": "^7.1 || ^8.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "^7.5 || ^8 || ^9 || ^10 || ^11 || ^12"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"FontLib\\": "src/FontLib"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"LGPL-2.1-or-later"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "The FontLib Community",
|
||||||
|
"homepage": "https://github.com/dompdf/php-font-lib/blob/master/AUTHORS.md"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "A library to read, parse, export and make subsets of different types of font files.",
|
||||||
|
"homepage": "https://github.com/dompdf/php-font-lib",
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/dompdf/php-font-lib/issues",
|
||||||
|
"source": "https://github.com/dompdf/php-font-lib/tree/1.0.2"
|
||||||
|
},
|
||||||
|
"time": "2026-01-20T14:10:26+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "dompdf/php-svg-lib",
|
||||||
|
"version": "1.0.2",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/dompdf/php-svg-lib.git",
|
||||||
|
"reference": "8259ffb930817e72b1ff1caef5d226501f3dfeb1"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/8259ffb930817e72b1ff1caef5d226501f3dfeb1",
|
||||||
|
"reference": "8259ffb930817e72b1ff1caef5d226501f3dfeb1",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-mbstring": "*",
|
||||||
|
"php": "^7.1 || ^8.0",
|
||||||
|
"sabberworm/php-css-parser": "^8.4 || ^9.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "^7.5 || ^8 || ^9 || ^10 || ^11"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Svg\\": "src/Svg"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"LGPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "The SvgLib Community",
|
||||||
|
"homepage": "https://github.com/dompdf/php-svg-lib/blob/master/AUTHORS.md"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "A library to read, parse and export to PDF SVG files.",
|
||||||
|
"homepage": "https://github.com/dompdf/php-svg-lib",
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/dompdf/php-svg-lib/issues",
|
||||||
|
"source": "https://github.com/dompdf/php-svg-lib/tree/1.0.2"
|
||||||
|
},
|
||||||
|
"time": "2026-01-02T16:01:13+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "dragonmantank/cron-expression",
|
"name": "dragonmantank/cron-expression",
|
||||||
"version": "v3.6.0",
|
"version": "v3.6.0",
|
||||||
@ -5435,6 +5667,86 @@
|
|||||||
],
|
],
|
||||||
"time": "2026-03-19T10:36:26+00:00"
|
"time": "2026-03-19T10:36:26+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "sabberworm/php-css-parser",
|
||||||
|
"version": "v9.4.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/MyIntervals/PHP-CSS-Parser.git",
|
||||||
|
"reference": "fd3bf9fb173e0df649bc4e3e0d088a1b2417c08f"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/MyIntervals/PHP-CSS-Parser/zipball/fd3bf9fb173e0df649bc4e3e0d088a1b2417c08f",
|
||||||
|
"reference": "fd3bf9fb173e0df649bc4e3e0d088a1b2417c08f",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-iconv": "*",
|
||||||
|
"php": "^7.2.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0",
|
||||||
|
"thecodingmachine/safe": "^1.3 || ^2.5 || ^3.4"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"php-parallel-lint/php-parallel-lint": "1.4.0",
|
||||||
|
"phpstan/extension-installer": "1.4.3",
|
||||||
|
"phpstan/phpstan": "1.12.33 || 2.2.2",
|
||||||
|
"phpstan/phpstan-phpunit": "1.4.2 || 2.0.16",
|
||||||
|
"phpstan/phpstan-strict-rules": "1.6.2 || 2.0.11",
|
||||||
|
"phpunit/phpunit": "8.5.52",
|
||||||
|
"rawr/phpunit-data-provider": "3.3.1",
|
||||||
|
"rector/rector": "1.2.10 || 2.4.6",
|
||||||
|
"rector/type-perfect": "1.0.0 || 2.1.3",
|
||||||
|
"squizlabs/php_codesniffer": "4.0.1",
|
||||||
|
"thecodingmachine/phpstan-safe-rule": "1.2.0 || 1.4.3"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"ext-mbstring": "for parsing UTF-8 CSS"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-main": "9.5.x-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"src/Rule/Rule.php",
|
||||||
|
"src/RuleSet/RuleContainer.php"
|
||||||
|
],
|
||||||
|
"psr-4": {
|
||||||
|
"Sabberworm\\CSS\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Raphael Schweikert"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Oliver Klee",
|
||||||
|
"email": "github@oliverklee.de"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Jake Hotson",
|
||||||
|
"email": "jake.github@qzdesign.co.uk"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Parser for CSS Files written in PHP",
|
||||||
|
"homepage": "https://www.sabberworm.com/blog/2010/6/10/php-css-parser",
|
||||||
|
"keywords": [
|
||||||
|
"css",
|
||||||
|
"parser",
|
||||||
|
"stylesheet"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/MyIntervals/PHP-CSS-Parser/issues",
|
||||||
|
"source": "https://github.com/MyIntervals/PHP-CSS-Parser/tree/v9.4.0"
|
||||||
|
},
|
||||||
|
"time": "2026-06-18T15:10:53+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "spatie/color",
|
"name": "spatie/color",
|
||||||
"version": "1.8.0",
|
"version": "1.8.0",
|
||||||
@ -8117,6 +8429,149 @@
|
|||||||
],
|
],
|
||||||
"time": "2026-07-21T15:13:06+00:00"
|
"time": "2026-07-21T15:13:06+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "thecodingmachine/safe",
|
||||||
|
"version": "v3.4.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/thecodingmachine/safe.git",
|
||||||
|
"reference": "705683a25bacf0d4860c7dea4d7947bfd09eea19"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/thecodingmachine/safe/zipball/705683a25bacf0d4860c7dea4d7947bfd09eea19",
|
||||||
|
"reference": "705683a25bacf0d4860c7dea4d7947bfd09eea19",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": "^8.1"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"php-parallel-lint/php-parallel-lint": "^1.4",
|
||||||
|
"phpstan/phpstan": "^2",
|
||||||
|
"phpunit/phpunit": "^10",
|
||||||
|
"squizlabs/php_codesniffer": "^3.2"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"lib/special_cases.php",
|
||||||
|
"generated/apache.php",
|
||||||
|
"generated/apcu.php",
|
||||||
|
"generated/array.php",
|
||||||
|
"generated/bzip2.php",
|
||||||
|
"generated/calendar.php",
|
||||||
|
"generated/classobj.php",
|
||||||
|
"generated/com.php",
|
||||||
|
"generated/cubrid.php",
|
||||||
|
"generated/curl.php",
|
||||||
|
"generated/datetime.php",
|
||||||
|
"generated/dir.php",
|
||||||
|
"generated/eio.php",
|
||||||
|
"generated/errorfunc.php",
|
||||||
|
"generated/exec.php",
|
||||||
|
"generated/fileinfo.php",
|
||||||
|
"generated/filesystem.php",
|
||||||
|
"generated/filter.php",
|
||||||
|
"generated/fpm.php",
|
||||||
|
"generated/ftp.php",
|
||||||
|
"generated/funchand.php",
|
||||||
|
"generated/gettext.php",
|
||||||
|
"generated/gmp.php",
|
||||||
|
"generated/gnupg.php",
|
||||||
|
"generated/hash.php",
|
||||||
|
"generated/ibase.php",
|
||||||
|
"generated/ibmDb2.php",
|
||||||
|
"generated/iconv.php",
|
||||||
|
"generated/image.php",
|
||||||
|
"generated/imap.php",
|
||||||
|
"generated/info.php",
|
||||||
|
"generated/inotify.php",
|
||||||
|
"generated/json.php",
|
||||||
|
"generated/ldap.php",
|
||||||
|
"generated/libxml.php",
|
||||||
|
"generated/lzf.php",
|
||||||
|
"generated/mailparse.php",
|
||||||
|
"generated/mbstring.php",
|
||||||
|
"generated/misc.php",
|
||||||
|
"generated/mysql.php",
|
||||||
|
"generated/mysqli.php",
|
||||||
|
"generated/network.php",
|
||||||
|
"generated/oci8.php",
|
||||||
|
"generated/opcache.php",
|
||||||
|
"generated/openssl.php",
|
||||||
|
"generated/outcontrol.php",
|
||||||
|
"generated/pcntl.php",
|
||||||
|
"generated/pcre.php",
|
||||||
|
"generated/pgsql.php",
|
||||||
|
"generated/posix.php",
|
||||||
|
"generated/ps.php",
|
||||||
|
"generated/pspell.php",
|
||||||
|
"generated/readline.php",
|
||||||
|
"generated/rnp.php",
|
||||||
|
"generated/rpminfo.php",
|
||||||
|
"generated/rrd.php",
|
||||||
|
"generated/sem.php",
|
||||||
|
"generated/session.php",
|
||||||
|
"generated/shmop.php",
|
||||||
|
"generated/sockets.php",
|
||||||
|
"generated/sodium.php",
|
||||||
|
"generated/solr.php",
|
||||||
|
"generated/spl.php",
|
||||||
|
"generated/sqlsrv.php",
|
||||||
|
"generated/ssdeep.php",
|
||||||
|
"generated/ssh2.php",
|
||||||
|
"generated/stream.php",
|
||||||
|
"generated/strings.php",
|
||||||
|
"generated/swoole.php",
|
||||||
|
"generated/uodbc.php",
|
||||||
|
"generated/uopz.php",
|
||||||
|
"generated/url.php",
|
||||||
|
"generated/var.php",
|
||||||
|
"generated/xdiff.php",
|
||||||
|
"generated/xml.php",
|
||||||
|
"generated/xmlrpc.php",
|
||||||
|
"generated/yaml.php",
|
||||||
|
"generated/yaz.php",
|
||||||
|
"generated/zip.php",
|
||||||
|
"generated/zlib.php"
|
||||||
|
],
|
||||||
|
"classmap": [
|
||||||
|
"lib/DateTime.php",
|
||||||
|
"lib/DateTimeImmutable.php",
|
||||||
|
"lib/Exceptions/",
|
||||||
|
"generated/Exceptions/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"description": "PHP core functions that throw exceptions instead of returning FALSE on error",
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/thecodingmachine/safe/issues",
|
||||||
|
"source": "https://github.com/thecodingmachine/safe/tree/v3.4.0"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://github.com/OskarStark",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/shish",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/silasjoisten",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/staabm",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2026-02-04T18:08:13+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "tijsverkoyen/css-to-inline-styles",
|
"name": "tijsverkoyen/css-to-inline-styles",
|
||||||
"version": "v2.4.0",
|
"version": "v2.4.0",
|
||||||
|
|||||||
35
04_Laravel/inspect_awb.php
Normal file
35
04_Laravel/inspect_awb.php
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
require 'C:/xampp/htdocs/IFNEX-Logistics/04_Laravel/vendor/autoload.php';
|
||||||
|
|
||||||
|
$reader = new \PhpOffice\PhpSpreadsheet\IOFactory();
|
||||||
|
$spreadsheet = $reader->load('C:/xampp/htdocs/IFNEX-Logistics/04_Laravel/storage/app/public/01KYWGVNKS5TNMN37RV77PCYNZ.xlsx');
|
||||||
|
$sheets = $spreadsheet->getSheetNames();
|
||||||
|
echo "=== ALL SHEET NAMES ===" . PHP_EOL;
|
||||||
|
echo implode(', ', $sheets) . PHP_EOL . PHP_EOL;
|
||||||
|
|
||||||
|
// Inspect AWB sheet
|
||||||
|
echo "=== AWB SHEET ===" . PHP_EOL;
|
||||||
|
$awbSheet = $spreadsheet->getSheetByName('AWB');
|
||||||
|
if ($awbSheet) {
|
||||||
|
echo "Dimensions: " . $awbSheet->calculateWorksheetDimensions() . PHP_EOL;
|
||||||
|
echo "Highest row: " . $awbSheet->getHighestRow() . PHP_EOL;
|
||||||
|
echo "Highest column: " . $awbSheet->getHighestColumn() . PHP_EOL;
|
||||||
|
echo PHP_EOL;
|
||||||
|
|
||||||
|
// Print first 50 rows
|
||||||
|
for ($row = 1; $row <= min(50, $awbSheet->getHighestRow()); $row++) {
|
||||||
|
$rowData = [];
|
||||||
|
for ($col = 1; $col <= 15; $col++) {
|
||||||
|
$cell = $awbSheet->getCellByColumnAndRow($col, $row);
|
||||||
|
$value = $cell->getValue();
|
||||||
|
if ($value !== null) {
|
||||||
|
$rowData[] = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($col) . $row . "=" . json_encode($value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!empty($rowData)) {
|
||||||
|
echo "Row $row: " . implode(" | ", $rowData) . PHP_EOL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
echo "AWB sheet not found!" . PHP_EOL;
|
||||||
|
}
|
||||||
@ -14,8 +14,21 @@
|
|||||||
<span class="text-2xl font-mono font-bold text-orange-600">{{ $shipment->awb_no ?? 'N/A' }}</span>
|
<span class="text-2xl font-mono font-bold text-orange-600">{{ $shipment->awb_no ?? 'N/A' }}</span>
|
||||||
</div>
|
</div>
|
||||||
<p class="text-sm text-gray-500 mb-8">کارشناسان ما در اسرع وقت با شما تماس خواهند گرفت.</p>
|
<p class="text-sm text-gray-500 mb-8">کارشناسان ما در اسرع وقت با شما تماس خواهند گرفت.</p>
|
||||||
<div class="flex justify-center gap-4">
|
|
||||||
<a href="{{ route('orders.create') }}" class="inline-flex items-center px-4 py-2 bg-orange-600 border border-transparent rounded-md font-semibold text-white hover:bg-orange-700">
|
<div class="flex flex-wrap justify-center gap-3 mb-6">
|
||||||
|
<a href="{{ route('shipments.pdf.awb', $shipment) }}" class="inline-flex items-center px-4 py-2 bg-orange-600 border border-transparent rounded-md font-semibold text-white hover:bg-orange-700">
|
||||||
|
دانلود AWB
|
||||||
|
</a>
|
||||||
|
<a href="{{ route('shipments.pdf.invoice', $shipment) }}" class="inline-flex items-center px-4 py-2 bg-blue-600 border border-transparent rounded-md font-semibold text-white hover:bg-blue-700">
|
||||||
|
دانلود INVOICE
|
||||||
|
</a>
|
||||||
|
<a href="{{ route('shipments.pdf.label', $shipment) }}" class="inline-flex items-center px-4 py-2 bg-gray-700 border border-transparent rounded-md font-semibold text-white hover:bg-gray-800">
|
||||||
|
دانلود LABEL
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex justify-center">
|
||||||
|
<a href="{{ route('orders.create') }}" class="inline-flex items-center px-4 py-2 bg-white border border-gray-300 rounded-md font-semibold text-gray-700 hover:bg-gray-50">
|
||||||
ثبت سفارش جدید
|
ثبت سفارش جدید
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
113
04_Laravel/resources/views/pdfs/awb.blade.php
Normal file
113
04_Laravel/resources/views/pdfs/awb.blade.php
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fa" dir="rtl">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<style>
|
||||||
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||||
|
body { font-family: DejaVu Sans, sans-serif; font-size: 11px; direction: rtl; text-align: right; }
|
||||||
|
.container { padding: 20px; }
|
||||||
|
.header { text-align: center; margin-bottom: 20px; border-bottom: 2px solid #f37021; padding-bottom: 10px; }
|
||||||
|
.header h1 { color: #f37021; font-size: 18px; margin-bottom: 5px; }
|
||||||
|
.header p { color: #666; font-size: 10px; }
|
||||||
|
.logo { font-size: 20px; font-weight: bold; color: #f37021; margin-bottom: 5px; }
|
||||||
|
.section { margin-bottom: 15px; border: 1px solid #ddd; padding: 10px; }
|
||||||
|
.section-title { font-weight: bold; color: #f37021; margin-bottom: 8px; font-size: 12px; border-bottom: 1px solid #eee; padding-bottom: 3px; }
|
||||||
|
.row { display: flex; margin-bottom: 5px; }
|
||||||
|
.label { width: 120px; font-weight: bold; color: #555; }
|
||||||
|
.value { flex: 1; }
|
||||||
|
.two-col { display: flex; gap: 20px; }
|
||||||
|
.col { flex: 1; }
|
||||||
|
table { width: 100%; border-collapse: collapse; margin-top: 10px; }
|
||||||
|
th, td { border: 1px solid #ddd; padding: 6px; text-align: right; font-size: 10px; }
|
||||||
|
th { background-color: #f5f5f5; font-weight: bold; }
|
||||||
|
.financial { background-color: #f9f9f9; }
|
||||||
|
.total { font-weight: bold; color: #f37021; font-size: 12px; }
|
||||||
|
.signature { margin-top: 30px; display: flex; justify-content: space-between; }
|
||||||
|
.signature-box { width: 45%; border-top: 1px solid #333; padding-top: 5px; text-align: center; font-size: 10px; }
|
||||||
|
.footer { margin-top: 20px; text-align: center; font-size: 9px; color: #999; border-top: 1px solid #ddd; padding-top: 10px; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<div class="header">
|
||||||
|
<div class="logo">IFNEX LOGISTICS</div>
|
||||||
|
<h1>AIR WAYBILL</h1>
|
||||||
|
<p>AWB No: {{ $shipment->awb_no }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="two-col">
|
||||||
|
<div class="col section">
|
||||||
|
<div class="section-title">SHIPPER / فرستنده</div>
|
||||||
|
<div class="row"><span class="label">Name:</span><span class="value">{{ $shipper['name'] }}</span></div>
|
||||||
|
<div class="row"><span class="label">Company:</span><span class="value">{{ $shipper['company'] }}</span></div>
|
||||||
|
<div class="row"><span class="label">Phone:</span><span class="value">{{ $shipper['phone'] }}</span></div>
|
||||||
|
<div class="row"><span class="label">Email:</span><span class="value">{{ $shipper['email'] }}</span></div>
|
||||||
|
<div class="row"><span class="label">Address:</span><span class="value">{{ $shipper['address'] }}</span></div>
|
||||||
|
<div class="row"><span class="label">City:</span><span class="value">{{ $shipper['city'] }}</span></div>
|
||||||
|
<div class="row"><span class="label">Zip:</span><span class="value">{{ $shipper['zip'] }}</span></div>
|
||||||
|
<div class="row"><span class="label">ID:</span><span class="value">{{ $shipper['id_number'] }}</span></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col section">
|
||||||
|
<div class="section-title">RECEIVER / گیرنده</div>
|
||||||
|
<div class="row"><span class="label">Name:</span><span class="value">{{ $receiver['name'] }}</span></div>
|
||||||
|
<div class="row"><span class="label">Company:</span><span class="value">{{ $receiver['company'] }}</span></div>
|
||||||
|
<div class="row"><span class="label">Phone:</span><span class="value">{{ $receiver['phone'] }}</span></div>
|
||||||
|
<div class="row"><span class="label">Email:</span><span class="value">{{ $receiver['email'] }}</span></div>
|
||||||
|
<div class="row"><span class="label">Address:</span><span class="value">{{ $receiver['address'] }}</span></div>
|
||||||
|
<div class="row"><span class="label">City:</span><span class="value">{{ $receiver['city'] }}</span></div>
|
||||||
|
<div class="row"><span class="label">Zip:</span><span class="value">{{ $receiver['zip'] }}</span></div>
|
||||||
|
<div class="row"><span class="label">ID:</span><span class="value">{{ $receiver['id_number'] }}</span></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="section">
|
||||||
|
<div class="section-title">SHIPMENT DETAILS</div>
|
||||||
|
<div class="row">
|
||||||
|
<div style="width: 50%">
|
||||||
|
<div class="row"><span class="label">Gross Weight:</span><span class="value">{{ $shipment->weight }} kg</span></div>
|
||||||
|
<div class="row"><span class="label">Volumetric Weight:</span><span class="value">{{ $shipment->volumetric_weight }} kg</span></div>
|
||||||
|
<div class="row"><span class="label">Chargeable Weight:</span><span class="value">{{ $shipment->chargeable_weight }} kg</span></div>
|
||||||
|
<div class="row"><span class="label">Dimensions:</span><span class="value">{{ $shipment->dimensions }}</span></div>
|
||||||
|
<div class="row"><span class="label">Service:</span><span class="value">{{ $shipment->type?->label() }}</span></div>
|
||||||
|
<div class="row"><span class="label">Direction:</span><span class="value">{{ $shipment->direction?->label() }}</span></div>
|
||||||
|
</div>
|
||||||
|
<div style="width: 50%">
|
||||||
|
<div class="row"><span class="label">From:</span><span class="value">{{ $shipment->fromCountry?->name }}</span></div>
|
||||||
|
<div class="row"><span class="label">To:</span><span class="value">{{ $shipment->toCountry?->name }}</span></div>
|
||||||
|
<div class="row"><span class="label">Forwarder:</span><span class="value">{{ $shipment->forwarder }}</span></div>
|
||||||
|
<div class="row"><span class="label">Content:</span><span class="value">{{ $shipment->reason_for_export ?: 'General Goods' }}</span></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="section financial">
|
||||||
|
<div class="section-title">PAYMENT / پرداخت</div>
|
||||||
|
<div class="row"><span class="label">Shipping Price (AED):</span><span class="value">{{ number_format($shipment->shipping_price ?? 0, 2) }}</span></div>
|
||||||
|
<div class="row"><span class="label">Extra Service (IRR):</span><span class="value">{{ number_format($shipment->extra_service ?? 0) }}</span></div>
|
||||||
|
<div class="row"><span class="label">Packing Cost (IRR):</span><span class="value">{{ number_format($shipment->packing_cost ?? 0) }}</span></div>
|
||||||
|
<div class="row"><span class="label">Domestic Pickup (IRR):</span><span class="value">{{ number_format($shipment->domestic_pickup ?? 0) }}</span></div>
|
||||||
|
<div class="row"><span class="label">Domestic Delivery (IRR):</span><span class="value">{{ number_format($shipment->domestic_delivery ?? 0) }}</span></div>
|
||||||
|
<div class="row"><span class="label">Warehousing (IRR):</span><span class="value">{{ number_format($shipment->warehousing_cost ?? 0) }}</span></div>
|
||||||
|
<div class="row"><span class="label">Discount (IRR):</span><span class="value">{{ number_format($shipment->discount ?? 0) }}</span></div>
|
||||||
|
<div class="row total"><span class="label">Total Fee (IRR):</span><span class="value">{{ number_format($shipment->total_fee ?? 0) }}</span></div>
|
||||||
|
<div class="row total"><span class="label">Net Dirham (AED):</span><span class="value">{{ number_format($shipment->net_dirham ?? 0, 2) }}</span></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="signature">
|
||||||
|
<div class="signature-box">
|
||||||
|
Shipper Name & Signature<br>
|
||||||
|
Date: {{ now()->format('Y-m-d') }}
|
||||||
|
</div>
|
||||||
|
<div class="signature-box">
|
||||||
|
Track Your Shipment at:<br>
|
||||||
|
http://ifnex.net
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer">
|
||||||
|
IFNEX Logistics — We Deliver Value | Generated on {{ now()->format('Y-m-d H:i') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
124
04_Laravel/resources/views/pdfs/invoice.blade.php
Normal file
124
04_Laravel/resources/views/pdfs/invoice.blade.php
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fa" dir="rtl">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<style>
|
||||||
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||||
|
body { font-family: DejaVu Sans, sans-serif; font-size: 11px; direction: rtl; text-align: right; }
|
||||||
|
.container { padding: 20px; }
|
||||||
|
.header { text-align: center; margin-bottom: 20px; border-bottom: 2px solid #f37021; padding-bottom: 10px; }
|
||||||
|
.header h1 { color: #f37021; font-size: 20px; margin-bottom: 5px; }
|
||||||
|
.header .meta { display: flex; justify-content: space-between; font-size: 10px; color: #666; }
|
||||||
|
.section { margin-bottom: 15px; border: 1px solid #ddd; padding: 10px; }
|
||||||
|
.section-title { font-weight: bold; color: #f37021; margin-bottom: 8px; font-size: 12px; border-bottom: 1px solid #eee; padding-bottom: 3px; }
|
||||||
|
.row { display: flex; margin-bottom: 4px; }
|
||||||
|
.label { width: 130px; font-weight: bold; color: #555; }
|
||||||
|
.value { flex: 1; }
|
||||||
|
.two-col { display: flex; gap: 20px; }
|
||||||
|
.col { flex: 1; }
|
||||||
|
table { width: 100%; border-collapse: collapse; margin-top: 10px; }
|
||||||
|
th, td { border: 1px solid #ddd; padding: 6px; text-align: right; font-size: 10px; }
|
||||||
|
th { background-color: #f5f5f5; font-weight: bold; }
|
||||||
|
.text-right { text-align: right; }
|
||||||
|
.text-center { text-align: center; }
|
||||||
|
.total { font-weight: bold; color: #f37021; }
|
||||||
|
.footer { margin-top: 20px; border-top: 1px solid #ddd; padding-top: 10px; font-size: 9px; color: #666; }
|
||||||
|
.declaration { font-size: 9px; color: #666; margin-top: 15px; line-height: 1.5; }
|
||||||
|
.awb-box { background-color: #f9f9f9; padding: 5px 10px; display: inline-block; border: 1px dashed #f37021; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<div class="header">
|
||||||
|
<h1>INVOICE / فاکتور</h1>
|
||||||
|
<div class="meta">
|
||||||
|
<span>DATE: {{ $shipment->created_at?->format('Y-m-d') }}</span>
|
||||||
|
<span class="awb-box">INVOICE NO: {{ $shipment->awb_no }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="two-col">
|
||||||
|
<div class="col section">
|
||||||
|
<div class="section-title">SHIPPER / فرستنده</div>
|
||||||
|
<div class="row"><span class="label">Name:</span><span class="value">{{ $shipper['name'] }}</span></div>
|
||||||
|
<div class="row"><span class="label">Company:</span><span class="value">{{ $shipper['company'] }}</span></div>
|
||||||
|
<div class="row"><span class="label">Contact:</span><span class="value">{{ $shipper['phone'] }}</span></div>
|
||||||
|
<div class="row"><span class="label">Address:</span><span class="value">{{ $shipper['address'] }}</span></div>
|
||||||
|
<div class="row"><span class="label">City/Zip:</span><span class="value">{{ $shipper['city'] }} {{ $shipper['zip'] }}</span></div>
|
||||||
|
<div class="row"><span class="label">Email:</span><span class="value">{{ $shipper['email'] }}</span></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col section">
|
||||||
|
<div class="section-title">CONSIGNEE / گیرنده</div>
|
||||||
|
<div class="row"><span class="label">Name:</span><span class="value">{{ $receiver['name'] }}</span></div>
|
||||||
|
<div class="row"><span class="label">Company:</span><span class="value">{{ $receiver['company'] }}</span></div>
|
||||||
|
<div class="row"><span class="label">Contact:</span><span class="value">{{ $receiver['phone'] }}</span></div>
|
||||||
|
<div class="row"><span class="label">Address:</span><span class="value">{{ $receiver['address'] }}</span></div>
|
||||||
|
<div class="row"><span class="label">City/Zip:</span><span class="value">{{ $receiver['city'] }} {{ $receiver['zip'] }}</span></div>
|
||||||
|
<div class="row"><span class="label">Email:</span><span class="value">{{ $receiver['email'] }}</span></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="section">
|
||||||
|
<div class="section-title">SHIPMENT DETAILS</div>
|
||||||
|
<div class="row">
|
||||||
|
<div style="width: 50%">
|
||||||
|
<div class="row"><span class="label">Weight:</span><span class="value">{{ $shipment->weight }} kg</span></div>
|
||||||
|
<div class="row"><span class="label">Volumetric:</span><span class="value">{{ $shipment->volumetric_weight }} kg</span></div>
|
||||||
|
<div class="row"><span class="label">Dimensions:</span><span class="value">{{ $shipment->dimensions }}</span></div>
|
||||||
|
<div class="row"><span class="label">Service:</span><span class="value">{{ $shipment->type?->label() }}</span></div>
|
||||||
|
<div class="row"><span class="label">Direction:</span><span class="value">{{ $shipment->direction?->label() }}</span></div>
|
||||||
|
</div>
|
||||||
|
<div style="width: 50%">
|
||||||
|
<div class="row"><span class="label">From:</span><span class="value">{{ $shipment->fromCountry?->name }}</span></div>
|
||||||
|
<div class="row"><span class="label">To:</span><span class="value">{{ $shipment->toCountry?->name }}</span></div>
|
||||||
|
<div class="row"><span class="label">Forwarder:</span><span class="value">{{ $shipment->forwarder }}</span></div>
|
||||||
|
<div class="row"><span class="label">Reason:</span><span class="value">{{ $shipment->reason_for_export ?: 'N/A' }}</span></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="section">
|
||||||
|
<div class="section-title">CONTENT / محموله</div>
|
||||||
|
<p style="margin-bottom: 10px;">{{ $shipment->reason_for_export ?: 'General Goods' }}</p>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style="width: 40px">No</th>
|
||||||
|
<th>Description</th>
|
||||||
|
<th style="width: 100px">H.S. Code</th>
|
||||||
|
<th style="width: 70px">Qty</th>
|
||||||
|
<th style="width: 90px">Unit Price (USD)</th>
|
||||||
|
<th style="width: 100px">Total (USD)</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@forelse($items as $item)
|
||||||
|
<tr>
|
||||||
|
<td class="text-center">{{ $item->row_number }}</td>
|
||||||
|
<td>{{ $item->description }}</td>
|
||||||
|
<td class="text-center">{{ $item->hs_code }}</td>
|
||||||
|
<td class="text-center">{{ $item->quantity }}</td>
|
||||||
|
<td class="text-center">{{ number_format($item->unit_price, 2) }}</td>
|
||||||
|
<td class="text-center">{{ number_format($item->total_usd, 2) }}</td>
|
||||||
|
</tr>
|
||||||
|
@empty
|
||||||
|
<tr><td colspan="6" class="text-center">No items</td></tr>
|
||||||
|
@endforelse
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div style="margin-top: 10px; text-align: left;">
|
||||||
|
<strong>TOTAL INVOICE AMOUNT IN USD: {{ number_format($invoice_total_usd, 2) }}</strong>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="declaration">
|
||||||
|
I HEREBY STATE THAT THE ABOVE INFORMATION IS TRUE AND CORRECT TO THE BEST OF MY KNOWLEDGE.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer">
|
||||||
|
IFNEX Logistics — We Deliver Value | AWB: {{ $shipment->awb_no }} | Generated on {{ now()->format('Y-m-d H:i') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
57
04_Laravel/resources/views/pdfs/label.blade.php
Normal file
57
04_Laravel/resources/views/pdfs/label.blade.php
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fa" dir="rtl">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<style>
|
||||||
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||||
|
body { font-family: DejaVu Sans, sans-serif; font-size: 10px; direction: rtl; text-align: right; }
|
||||||
|
.container { padding: 10px; }
|
||||||
|
.header { text-align: center; margin-bottom: 10px; }
|
||||||
|
.header .logo { font-size: 14px; font-weight: bold; color: #f37021; }
|
||||||
|
.header .awb { font-size: 16px; font-weight: bold; background: #f37021; color: white; padding: 3px 8px; display: inline-block; margin-top: 3px; }
|
||||||
|
.section { margin-bottom: 8px; border: 1px solid #ddd; padding: 6px; }
|
||||||
|
.section-title { font-weight: bold; color: #f37021; font-size: 10px; margin-bottom: 3px; }
|
||||||
|
.row { display: flex; margin-bottom: 2px; }
|
||||||
|
.label { width: 90px; font-weight: bold; color: #555; }
|
||||||
|
.value { flex: 1; }
|
||||||
|
.footer { text-align: center; font-size: 8px; color: #999; margin-top: 8px; border-top: 1px solid #ddd; padding-top: 5px; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<div class="header">
|
||||||
|
<div class="logo">IFNEX LOGISTICS</div>
|
||||||
|
<div class="awb">{{ $shipment->awb_no }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="section">
|
||||||
|
<div class="section-title">SHIPPER / فرستنده</div>
|
||||||
|
<div class="row"><span class="label">Name:</span><span class="value">{{ $shipper['name'] }}</span></div>
|
||||||
|
<div class="row"><span class="label">Company:</span><span class="value">{{ $shipper['company'] }}</span></div>
|
||||||
|
<div class="row"><span class="label">Phone:</span><span class="value">{{ $shipper['phone'] }}</span></div>
|
||||||
|
<div class="row"><span class="label">Address:</span><span class="value">{{ $shipper['address'] }}</span></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="section">
|
||||||
|
<div class="section-title">RECEIVER / گیرنده</div>
|
||||||
|
<div class="row"><span class="label">Name:</span><span class="value">{{ $receiver['name'] }}</span></div>
|
||||||
|
<div class="row"><span class="label">Company:</span><span class="value">{{ $receiver['company'] }}</span></div>
|
||||||
|
<div class="row"><span class="label">Phone:</span><span class="value">{{ $receiver['phone'] }}</span></div>
|
||||||
|
<div class="row"><span class="label">Address:</span><span class="value">{{ $receiver['address'] }}</span></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="section">
|
||||||
|
<div class="section-title">SHIPMENT</div>
|
||||||
|
<div class="row"><span class="label">Gross Weight:</span><span class="value">{{ $shipment->weight }} kg</span></div>
|
||||||
|
<div class="row"><span class="label">Volumetric:</span><span class="value">{{ $shipment->volumetric_weight }} kg</span></div>
|
||||||
|
<div class="row"><span class="label">Dimensions:</span><span class="value">{{ $shipment->dimensions }}</span></div>
|
||||||
|
<div class="row"><span class="label">From:</span><span class="value">{{ $shipment->fromCountry?->name }}</span></div>
|
||||||
|
<div class="row"><span class="label">To:</span><span class="value">{{ $shipment->toCountry?->name }}</span></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer">
|
||||||
|
IFNEX Logistics | {{ $shipment->awb_no }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@ -1,6 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use App\Http\Controllers\OrderController;
|
use App\Http\Controllers\OrderController;
|
||||||
|
use App\Http\Controllers\ShipmentPdfController;
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
Route::get('/', function () {
|
Route::get('/', function () {
|
||||||
@ -10,3 +11,9 @@ Route::get('/', function () {
|
|||||||
Route::get('/order', [OrderController::class, 'create'])->name('orders.create');
|
Route::get('/order', [OrderController::class, 'create'])->name('orders.create');
|
||||||
Route::post('/order', [OrderController::class, 'store'])->name('orders.store');
|
Route::post('/order', [OrderController::class, 'store'])->name('orders.store');
|
||||||
Route::get('/order/success/{shipment}', [OrderController::class, 'success'])->name('orders.success');
|
Route::get('/order/success/{shipment}', [OrderController::class, 'success'])->name('orders.success');
|
||||||
|
|
||||||
|
Route::middleware('auth')->group(function () {
|
||||||
|
Route::get('/shipments/{shipment}/pdf/awb', [ShipmentPdfController::class, 'awb'])->name('shipments.pdf.awb');
|
||||||
|
Route::get('/shipments/{shipment}/pdf/invoice', [ShipmentPdfController::class, 'invoice'])->name('shipments.pdf.invoice');
|
||||||
|
Route::get('/shipments/{shipment}/pdf/label', [ShipmentPdfController::class, 'label'])->name('shipments.pdf.label');
|
||||||
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user