diff --git a/01_Documents/STATUS.md b/01_Documents/STATUS.md index 5b2f83c..b10d7ef 100644 --- a/01_Documents/STATUS.md +++ b/01_Documents/STATUS.md @@ -237,7 +237,7 @@ - [ ] موتور قیمت‌گذاری کامل (PriceCalculatorService) — نوشته شد، نیاز به تست با داده‌های واقعی - [ ] جدول `shipping_rates` — ۴۰۴ رکورد import شد، نیاز به تکمیل - [ ] فرم ثبت سفارش آنلاین با ۹ ردیف کالای گمرکی -- [ ] تولید PDF: AWB، INVOICE، Label مطابق قالب اکسل +- [ ] تولید PDF: AWB، INVOICE، Label مطابق قالب اکسل — اولیه پیاده شد، نیاز به تطبیق دقیق با قالب‌های اکسل و رفع ساختار فعلی - [ ] ماژول ایمپورت اکسل تعرفه‌ها - [ ] صفحه استعلام قیمت واقعی diff --git a/04_Laravel/app/Enums/ShipmentDirection.php b/04_Laravel/app/Enums/ShipmentDirection.php index bd91697..acb74b7 100644 --- a/04_Laravel/app/Enums/ShipmentDirection.php +++ b/04_Laravel/app/Enums/ShipmentDirection.php @@ -6,4 +6,12 @@ enum ShipmentDirection: string { case Import = 'import'; case Export = 'export'; + + public function label(): string + { + return match($this) { + self::Import => 'Import', + self::Export => 'Export', + }; + } } diff --git a/04_Laravel/app/Enums/ShipmentType.php b/04_Laravel/app/Enums/ShipmentType.php index 86b3c9b..b3c440f 100644 --- a/04_Laravel/app/Enums/ShipmentType.php +++ b/04_Laravel/app/Enums/ShipmentType.php @@ -7,4 +7,13 @@ enum ShipmentType: string case DocNormal = 'DOC_NORMAL'; case DocEconomy = 'DOC_ECONOMY'; case Parcel = 'PARCEL'; + + public function label(): string + { + return match($this) { + self::DocNormal => 'Document Normal', + self::DocEconomy => 'Document Economy', + self::Parcel => 'Parcel', + }; + } } diff --git a/04_Laravel/app/Filament/Resources/ShipmentResource/Pages/ViewShipment.php b/04_Laravel/app/Filament/Resources/ShipmentResource/Pages/ViewShipment.php index 200e02b..6ceaf7a 100644 --- a/04_Laravel/app/Filament/Resources/ShipmentResource/Pages/ViewShipment.php +++ b/04_Laravel/app/Filament/Resources/ShipmentResource/Pages/ViewShipment.php @@ -9,4 +9,28 @@ use Filament\Resources\Pages\ViewRecord; class ViewShipment extends ViewRecord { 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)), + ]; + } } diff --git a/04_Laravel/app/Http/Controllers/ShipmentPdfController.php b/04_Laravel/app/Http/Controllers/ShipmentPdfController.php new file mode 100644 index 0000000..bd3d5b8 --- /dev/null +++ b/04_Laravel/app/Http/Controllers/ShipmentPdfController.php @@ -0,0 +1,60 @@ + $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); + } + } +} diff --git a/04_Laravel/app/Services/PdfService.php b/04_Laravel/app/Services/PdfService.php new file mode 100644 index 0000000..ebfed30 --- /dev/null +++ b/04_Laravel/app/Services/PdfService.php @@ -0,0 +1,96 @@ +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'}, + ]); + } +} diff --git a/04_Laravel/composer.json b/04_Laravel/composer.json index 1a3649b..8c99b50 100644 --- a/04_Laravel/composer.json +++ b/04_Laravel/composer.json @@ -7,6 +7,7 @@ "license": "MIT", "require": { "php": "^8.2", + "barryvdh/laravel-dompdf": "*", "filament/filament": "3.3.*", "laravel/framework": "^11.0", "laravel/tinker": "^2.10.1", diff --git a/04_Laravel/composer.lock b/04_Laravel/composer.lock index 83c9227..4d56a2c 100644 --- a/04_Laravel/composer.lock +++ b/04_Laravel/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "36a7ef85e0bbcd022965ce2b7234718f", + "content-hash": "c0d4db086122fe759e56ff3bf438bc30", "packages": [ { "name": "anourvalar/eloquent-serialize", @@ -71,6 +71,83 @@ }, "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", "version": "v3.3.4", @@ -1071,6 +1148,161 @@ ], "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", "version": "v3.6.0", @@ -5435,6 +5667,86 @@ ], "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", "version": "1.8.0", @@ -8117,6 +8429,149 @@ ], "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", "version": "v2.4.0", diff --git a/04_Laravel/inspect_awb.php b/04_Laravel/inspect_awb.php new file mode 100644 index 0000000..bcc3691 --- /dev/null +++ b/04_Laravel/inspect_awb.php @@ -0,0 +1,35 @@ +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; +} \ No newline at end of file diff --git a/04_Laravel/resources/views/orders/success.blade.php b/04_Laravel/resources/views/orders/success.blade.php index bc71343..239d394 100644 --- a/04_Laravel/resources/views/orders/success.blade.php +++ b/04_Laravel/resources/views/orders/success.blade.php @@ -14,8 +14,21 @@ {{ $shipment->awb_no ?? 'N/A' }}

کارشناسان ما در اسرع وقت با شما تماس خواهند گرفت.

-
- + +
+ + دانلود AWB + + + دانلود INVOICE + + + دانلود LABEL + +
+ +
+ ثبت سفارش جدید
diff --git a/04_Laravel/resources/views/pdfs/awb.blade.php b/04_Laravel/resources/views/pdfs/awb.blade.php new file mode 100644 index 0000000..9889367 --- /dev/null +++ b/04_Laravel/resources/views/pdfs/awb.blade.php @@ -0,0 +1,113 @@ + + + + + + + +
+
+ +

AIR WAYBILL

+

AWB No: {{ $shipment->awb_no }}

+
+ +
+
+
SHIPPER / فرستنده
+
Name:{{ $shipper['name'] }}
+
Company:{{ $shipper['company'] }}
+
Phone:{{ $shipper['phone'] }}
+
Email:{{ $shipper['email'] }}
+
Address:{{ $shipper['address'] }}
+
City:{{ $shipper['city'] }}
+
Zip:{{ $shipper['zip'] }}
+
ID:{{ $shipper['id_number'] }}
+
+ +
+
RECEIVER / گیرنده
+
Name:{{ $receiver['name'] }}
+
Company:{{ $receiver['company'] }}
+
Phone:{{ $receiver['phone'] }}
+
Email:{{ $receiver['email'] }}
+
Address:{{ $receiver['address'] }}
+
City:{{ $receiver['city'] }}
+
Zip:{{ $receiver['zip'] }}
+
ID:{{ $receiver['id_number'] }}
+
+
+ +
+
SHIPMENT DETAILS
+
+
+
Gross Weight:{{ $shipment->weight }} kg
+
Volumetric Weight:{{ $shipment->volumetric_weight }} kg
+
Chargeable Weight:{{ $shipment->chargeable_weight }} kg
+
Dimensions:{{ $shipment->dimensions }}
+
Service:{{ $shipment->type?->label() }}
+
Direction:{{ $shipment->direction?->label() }}
+
+
+
From:{{ $shipment->fromCountry?->name }}
+
To:{{ $shipment->toCountry?->name }}
+
Forwarder:{{ $shipment->forwarder }}
+
Content:{{ $shipment->reason_for_export ?: 'General Goods' }}
+
+
+
+ +
+
PAYMENT / پرداخت
+
Shipping Price (AED):{{ number_format($shipment->shipping_price ?? 0, 2) }}
+
Extra Service (IRR):{{ number_format($shipment->extra_service ?? 0) }}
+
Packing Cost (IRR):{{ number_format($shipment->packing_cost ?? 0) }}
+
Domestic Pickup (IRR):{{ number_format($shipment->domestic_pickup ?? 0) }}
+
Domestic Delivery (IRR):{{ number_format($shipment->domestic_delivery ?? 0) }}
+
Warehousing (IRR):{{ number_format($shipment->warehousing_cost ?? 0) }}
+
Discount (IRR):{{ number_format($shipment->discount ?? 0) }}
+
Total Fee (IRR):{{ number_format($shipment->total_fee ?? 0) }}
+
Net Dirham (AED):{{ number_format($shipment->net_dirham ?? 0, 2) }}
+
+ +
+
+ Shipper Name & Signature
+ Date: {{ now()->format('Y-m-d') }} +
+
+ Track Your Shipment at:
+ http://ifnex.net +
+
+ + +
+ + diff --git a/04_Laravel/resources/views/pdfs/invoice.blade.php b/04_Laravel/resources/views/pdfs/invoice.blade.php new file mode 100644 index 0000000..c9bb3b6 --- /dev/null +++ b/04_Laravel/resources/views/pdfs/invoice.blade.php @@ -0,0 +1,124 @@ + + + + + + + +
+
+

INVOICE / فاکتور

+
+ DATE: {{ $shipment->created_at?->format('Y-m-d') }} + INVOICE NO: {{ $shipment->awb_no }} +
+
+ +
+
+
SHIPPER / فرستنده
+
Name:{{ $shipper['name'] }}
+
Company:{{ $shipper['company'] }}
+
Contact:{{ $shipper['phone'] }}
+
Address:{{ $shipper['address'] }}
+
City/Zip:{{ $shipper['city'] }} {{ $shipper['zip'] }}
+
Email:{{ $shipper['email'] }}
+
+ +
+
CONSIGNEE / گیرنده
+
Name:{{ $receiver['name'] }}
+
Company:{{ $receiver['company'] }}
+
Contact:{{ $receiver['phone'] }}
+
Address:{{ $receiver['address'] }}
+
City/Zip:{{ $receiver['city'] }} {{ $receiver['zip'] }}
+
Email:{{ $receiver['email'] }}
+
+
+ +
+
SHIPMENT DETAILS
+
+
+
Weight:{{ $shipment->weight }} kg
+
Volumetric:{{ $shipment->volumetric_weight }} kg
+
Dimensions:{{ $shipment->dimensions }}
+
Service:{{ $shipment->type?->label() }}
+
Direction:{{ $shipment->direction?->label() }}
+
+
+
From:{{ $shipment->fromCountry?->name }}
+
To:{{ $shipment->toCountry?->name }}
+
Forwarder:{{ $shipment->forwarder }}
+
Reason:{{ $shipment->reason_for_export ?: 'N/A' }}
+
+
+
+ +
+
CONTENT / محموله
+

{{ $shipment->reason_for_export ?: 'General Goods' }}

+ + + + + + + + + + + + + @forelse($items as $item) + + + + + + + + + @empty + + @endforelse + +
NoDescriptionH.S. CodeQtyUnit Price (USD)Total (USD)
{{ $item->row_number }}{{ $item->description }}{{ $item->hs_code }}{{ $item->quantity }}{{ number_format($item->unit_price, 2) }}{{ number_format($item->total_usd, 2) }}
No items
+
+ TOTAL INVOICE AMOUNT IN USD: {{ number_format($invoice_total_usd, 2) }} +
+
+ +
+ I HEREBY STATE THAT THE ABOVE INFORMATION IS TRUE AND CORRECT TO THE BEST OF MY KNOWLEDGE. +
+ + +
+ + diff --git a/04_Laravel/resources/views/pdfs/label.blade.php b/04_Laravel/resources/views/pdfs/label.blade.php new file mode 100644 index 0000000..588210a --- /dev/null +++ b/04_Laravel/resources/views/pdfs/label.blade.php @@ -0,0 +1,57 @@ + + + + + + + +
+
+ +
{{ $shipment->awb_no }}
+
+ +
+
SHIPPER / فرستنده
+
Name:{{ $shipper['name'] }}
+
Company:{{ $shipper['company'] }}
+
Phone:{{ $shipper['phone'] }}
+
Address:{{ $shipper['address'] }}
+
+ +
+
RECEIVER / گیرنده
+
Name:{{ $receiver['name'] }}
+
Company:{{ $receiver['company'] }}
+
Phone:{{ $receiver['phone'] }}
+
Address:{{ $receiver['address'] }}
+
+ +
+
SHIPMENT
+
Gross Weight:{{ $shipment->weight }} kg
+
Volumetric:{{ $shipment->volumetric_weight }} kg
+
Dimensions:{{ $shipment->dimensions }}
+
From:{{ $shipment->fromCountry?->name }}
+
To:{{ $shipment->toCountry?->name }}
+
+ + +
+ + diff --git a/04_Laravel/routes/web.php b/04_Laravel/routes/web.php index b8eee92..99db712 100644 --- a/04_Laravel/routes/web.php +++ b/04_Laravel/routes/web.php @@ -1,6 +1,7 @@ name('orders.create'); Route::post('/order', [OrderController::class, 'store'])->name('orders.store'); 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'); +});