From 78d21942dbae4e1dfa77db3b164e9b60f4c4266e Mon Sep 17 00:00:00 2001 From: Kazem Alghasi Date: Sat, 3 Oct 2026 06:20:32 +0330 Subject: [PATCH] docs(architecture): document shipment review workflow and ADRs Add comprehensive Architecture Decision Records (ADRs) detailing the new shipment review state machine, review history domain, and customer resubmission logic. This documentation establishes the separation between operational shipment status and the review lifecycle. Additionally, perform repository cleanup by removing obsolete Postman collections, environment files, test scripts, and unused migrations. - Add ADR-001 through ADR-005 regarding review workflow and state. - Add shipment review handoff documentation. - Remove redundant Postman resources and local environment configs. - Remove `test_pdf_generation.php` and `resubmit-test.json`. - Remove unused `shipment_packages` migration. - Rename and reorganize one-off maintenance scripts. --- .../IFNEX_ADR.md | 0 ...IFNEX_Logistics_Review_Workflow_HANDOFF.md | 0 04_Laravel/.postman/resources.yaml | 9 -- ..._030000_create_shipment_packages_table.php | 32 ---- 04_Laravel/echo | 0 .../New Collection/.resources/definition.yaml | 2 - .../environments/IFNEX Local.environment.yaml | 8 - .../IFNEX Local2.environment.yaml | 6 - .../postman/globals/workspace.globals.yaml | 2 - 04_Laravel/resubmit-test.json | 36 ----- .../one-off}/update_all_calling_codes.php | 0 .../one-off}/update_calling_codes.php | 0 04_Laravel/test_pdf_generation.php | 145 ------------------ resubmit-test.json | 36 ----- 14 files changed, 276 deletions(-) rename IFNEX Logistics.md => 01_Documents/IFNEX_ADR.md (100%) rename IFNEX_Logistics_Review_Workflow_HANDOFF.md => 01_Documents/archives/IFNEX_Logistics_Review_Workflow_HANDOFF.md (100%) delete mode 100644 04_Laravel/.postman/resources.yaml delete mode 100644 04_Laravel/database_migrations/2026_08_29_030000_create_shipment_packages_table.php delete mode 100644 04_Laravel/echo delete mode 100644 04_Laravel/postman/collections/New Collection/.resources/definition.yaml delete mode 100644 04_Laravel/postman/environments/IFNEX Local.environment.yaml delete mode 100644 04_Laravel/postman/environments/IFNEX Local2.environment.yaml delete mode 100644 04_Laravel/postman/globals/workspace.globals.yaml delete mode 100644 04_Laravel/resubmit-test.json rename 04_Laravel/{ => scripts/one-off}/update_all_calling_codes.php (100%) rename 04_Laravel/{ => scripts/one-off}/update_calling_codes.php (100%) delete mode 100644 04_Laravel/test_pdf_generation.php delete mode 100644 resubmit-test.json diff --git a/IFNEX Logistics.md b/01_Documents/IFNEX_ADR.md similarity index 100% rename from IFNEX Logistics.md rename to 01_Documents/IFNEX_ADR.md diff --git a/IFNEX_Logistics_Review_Workflow_HANDOFF.md b/01_Documents/archives/IFNEX_Logistics_Review_Workflow_HANDOFF.md similarity index 100% rename from IFNEX_Logistics_Review_Workflow_HANDOFF.md rename to 01_Documents/archives/IFNEX_Logistics_Review_Workflow_HANDOFF.md diff --git a/04_Laravel/.postman/resources.yaml b/04_Laravel/.postman/resources.yaml deleted file mode 100644 index 0d77e70..0000000 --- a/04_Laravel/.postman/resources.yaml +++ /dev/null @@ -1,9 +0,0 @@ -# Use this workspace to collaborate -workspace: - id: c5409f98-698e-4a6c-8edb-443e130b005c - -# All resources in the `postman/` folder are automatically registered in Local View. -# Point to additional files outside the `postman/` folder to register them individually. Example: -#localResources: -# collections: -# - ../tests/E2E Test Collection/ diff --git a/04_Laravel/database_migrations/2026_08_29_030000_create_shipment_packages_table.php b/04_Laravel/database_migrations/2026_08_29_030000_create_shipment_packages_table.php deleted file mode 100644 index 50d2186..0000000 --- a/04_Laravel/database_migrations/2026_08_29_030000_create_shipment_packages_table.php +++ /dev/null @@ -1,32 +0,0 @@ -id(); - $table->foreignId('shipment_id')->constrained()->cascadeOnDelete(); - $table->unsignedTinyInteger('package_number')->default(1); // ۱، ۲، ۳، ... - $table->decimal('weight', 10, 3)->default(0); // وزن واقعی (kg) - $table->decimal('volumetric_weight', 10, 3)->default(0); // وزن حجمی (kg) - $table->decimal('chargeable_weight', 10, 3)->default(0); // وزن قابل محاسبه - $table->string('dimensions', 50)->nullable(); // ابعاد W*L*H (cm) - $table->text('description')->nullable(); // توضیحات بسته - $table->timestamps(); - - $table->index('shipment_id'); - }); - } - } - - public function down(): void - { - Schema::dropIfExists('shipment_packages'); - } -}; diff --git a/04_Laravel/echo b/04_Laravel/echo deleted file mode 100644 index e69de29..0000000 diff --git a/04_Laravel/postman/collections/New Collection/.resources/definition.yaml b/04_Laravel/postman/collections/New Collection/.resources/definition.yaml deleted file mode 100644 index 8697d90..0000000 --- a/04_Laravel/postman/collections/New Collection/.resources/definition.yaml +++ /dev/null @@ -1,2 +0,0 @@ -$kind: collection -name: New Collection diff --git a/04_Laravel/postman/environments/IFNEX Local.environment.yaml b/04_Laravel/postman/environments/IFNEX Local.environment.yaml deleted file mode 100644 index c68636e..0000000 --- a/04_Laravel/postman/environments/IFNEX Local.environment.yaml +++ /dev/null @@ -1,8 +0,0 @@ -name: IFNEX Local -values: - - key: base_url - value: '' - - key: token - value: '' - - key: '' - value: '' diff --git a/04_Laravel/postman/environments/IFNEX Local2.environment.yaml b/04_Laravel/postman/environments/IFNEX Local2.environment.yaml deleted file mode 100644 index 62b1e7e..0000000 --- a/04_Laravel/postman/environments/IFNEX Local2.environment.yaml +++ /dev/null @@ -1,6 +0,0 @@ -name: IFNEX Local2 -values: - - key: base_url - value: '' - - key: token - value: '' diff --git a/04_Laravel/postman/globals/workspace.globals.yaml b/04_Laravel/postman/globals/workspace.globals.yaml deleted file mode 100644 index e96c6d6..0000000 --- a/04_Laravel/postman/globals/workspace.globals.yaml +++ /dev/null @@ -1,2 +0,0 @@ -name: Globals -values: [] diff --git a/04_Laravel/resubmit-test.json b/04_Laravel/resubmit-test.json deleted file mode 100644 index 8e254ce..0000000 --- a/04_Laravel/resubmit-test.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "direction": "export", - "type": "PARCEL", - "from_country_id": 96, - "to_country_id": 7, - "weight": 3.70, - "dimensions": "90*90*90", - "packages": [ - { - "weight": 3.70, - "dimensions": "90*90*90", - "description": "dfasdf" - } - ], - "sender_name": "Moshtari Updated", - "sender_phone": "989898989899", - "sender_address": "New addresssss", - "sender_city": "asdfasdf", - "receiver_name": "moshtari2", - "receiver_phone": "565656565", - "receiver_address": "sdfhsdfsdhsdgh", - "receiver_city": "dfgsdfgsdfgs", - "extra_service": 0, - "packing_cost": 0, - "domestic_pickup": 0, - "domestic_delivery": 0, - "warehousing_cost": 0, - "items": [ - { - "description": "HHHH25", - "hs_code": "989898989", - "quantity": 12, - "unit_price": 1.20 - } - ] -} \ No newline at end of file diff --git a/04_Laravel/update_all_calling_codes.php b/04_Laravel/scripts/one-off/update_all_calling_codes.php similarity index 100% rename from 04_Laravel/update_all_calling_codes.php rename to 04_Laravel/scripts/one-off/update_all_calling_codes.php diff --git a/04_Laravel/update_calling_codes.php b/04_Laravel/scripts/one-off/update_calling_codes.php similarity index 100% rename from 04_Laravel/update_calling_codes.php rename to 04_Laravel/scripts/one-off/update_calling_codes.php diff --git a/04_Laravel/test_pdf_generation.php b/04_Laravel/test_pdf_generation.php deleted file mode 100644 index c1b4a37..0000000 --- a/04_Laravel/test_pdf_generation.php +++ /dev/null @@ -1,145 +0,0 @@ -make('Illuminate\Contracts\Console\Kernel')->bootstrap(); - -use App\Models\Shipment; -use App\Models\ShipmentItem; -use App\Models\Country; -use App\Services\PdfService; -use Illuminate\Support\Facades\File; - -echo "═══════════════════════════════════════════\n"; -echo "🧪 IFNEX PDF Generation Test\n"; -echo "═══════════════════════════════════════════\n\n"; - -// ─── ۱. بررسی نصب بودن کتابخانه بارکد ─── -echo "1️⃣ Checking barcode library...\n"; -if (class_exists(\Picqer\Barcode\BarcodeGeneratorPNG::class)) { - echo " ✅ picqer/php-barcode-generator is installed\n\n"; -} else { - echo " ❌ picqer/php-barcode-generator is NOT installed\n"; - echo " Run: composer require picqer/php-barcode-generator\n\n"; - exit(1); -} - -// ─── ۲. ایجاد پوشه تست ─── -$testDir = storage_path('app/pdf-test'); -if (!File::exists($testDir)) { - File::makeDirectory($testDir, 0755, true); - echo "2️⃣ Created test directory: {$testDir}\n\n"; -} else { - echo "2️⃣ Test directory exists: {$testDir}\n\n"; -} - -// ─── ۳. پیدا کردن یه محموله نمونه ─── -echo "3️⃣ Finding sample shipment...\n"; -$shipment = Shipment::with(['fromCountry', 'toCountry', 'items'])->latest()->first(); - -if (!$shipment) { - echo " ❌ No shipment found in database. Please create one first.\n"; - exit(1); -} - -echo " ✅ Found shipment: {$shipment->awb_no}\n"; -echo " - Type: {$shipment->type?->value}\n"; -echo " - Direction: {$shipment->direction?->value}\n"; -echo " - From: {$shipment->fromCountry?->name}\n"; -echo " - To: {$shipment->toCountry?->name}\n"; -echo " - Items: {$shipment->items->count()}\n\n"; - -// ─── ۴. اگر آیتم نداره، یه آیتم تستی اضافه کن ─── -if ($shipment->items->isEmpty()) { - echo " ⚠️ Shipment has no items. Adding test item...\n"; - ShipmentItem::create([ - 'shipment_id' => $shipment->id, - 'row_number' => 1, - 'description' => 'Electronics PCB Board', - 'hs_code' => '8542390001', - 'quantity' => 104, - 'unit_price' => 1.10, - 'total_usd' => 114.40, - ]); - $shipment->load('items'); - echo " ✅ Added test item\n\n"; -} - -// ─── ۵. تولید AWB PDF ─── -echo "4️⃣ Generating AWB PDF...\n"; -try { - $pdfService = app(PdfService::class); - $awbContent = $pdfService->awb($shipment); - $awbPath = $testDir . '/AWB-' . $shipment->awb_no . '.pdf'; - File::put($awbPath, $awbContent); - echo " ✅ AWB PDF saved: {$awbPath}\n"; - echo " Size: " . number_format(strlen($awbContent) / 1024, 2) . " KB\n\n"; -} catch (\Throwable $e) { - echo " ❌ AWB PDF failed: " . $e->getMessage() . "\n\n"; -} - -// ─── ۶. تولید Invoice PDF ─── -echo "5️⃣ Generating Invoice PDF...\n"; -try { - $invoiceContent = $pdfService->invoice($shipment); - $invoicePath = $testDir . '/INVOICE-' . $shipment->awb_no . '.pdf'; - File::put($invoicePath, $invoiceContent); - echo " ✅ Invoice PDF saved: {$invoicePath}\n"; - echo " Size: " . number_format(strlen($invoiceContent) / 1024, 2) . " KB\n\n"; -} catch (\InvalidArgumentException $e) { - echo " ⚠️ Invoice skipped: " . $e->getMessage() . "\n"; - echo " (این طبیعی است اگر محموله DOC است)\n\n"; -} catch (\Throwable $e) { - echo " ❌ Invoice PDF failed: " . $e->getMessage() . "\n\n"; -} - -// ─── ۷. تولید Label PDF ─── -echo "6️⃣ Generating Label PDF...\n"; -try { - $labelContent = $pdfService->label($shipment); - $labelPath = $testDir . '/LABEL-' . $shipment->awb_no . '.pdf'; - File::put($labelPath, $labelContent); - echo " ✅ Label PDF saved: {$labelPath}\n"; - echo " Size: " . number_format(strlen($labelContent) / 1024, 2) . " KB\n\n"; -} catch (\Throwable $e) { - echo " ❌ Label PDF failed: " . $e->getMessage() . "\n\n"; -} - -// ─── ۸. تست محموله DOC (بدون فاکتور) ─── -echo "7️⃣ Testing DOC shipment (should skip invoice)...\n"; -$docShipment = Shipment::where('type', 'DOC_NORMAL')->first(); -if ($docShipment) { - try { - $docShipment->load('items'); - if ($docShipment->items->isEmpty()) { - $pdfService->invoice($docShipment); - echo " ❌ ERROR: Should have thrown exception for DOC shipment!\n\n"; - } else { - echo " ℹ️ DOC shipment has items, invoice would work\n\n"; - } - } catch (\InvalidArgumentException $e) { - echo " ✅ Correctly skipped invoice for DOC: " . $e->getMessage() . "\n\n"; - } -} else { - echo " ℹ️ No DOC shipment found for testing (skipped)\n\n"; -} - -echo "═══════════════════════════════════════════\n"; -echo "✅ Test completed!\n"; -echo "═══════════════════════════════════════════\n\n"; -echo "📁 Check the generated PDFs at:\n"; -echo " {$testDir}\n\n"; diff --git a/resubmit-test.json b/resubmit-test.json deleted file mode 100644 index 8e254ce..0000000 --- a/resubmit-test.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "direction": "export", - "type": "PARCEL", - "from_country_id": 96, - "to_country_id": 7, - "weight": 3.70, - "dimensions": "90*90*90", - "packages": [ - { - "weight": 3.70, - "dimensions": "90*90*90", - "description": "dfasdf" - } - ], - "sender_name": "Moshtari Updated", - "sender_phone": "989898989899", - "sender_address": "New addresssss", - "sender_city": "asdfasdf", - "receiver_name": "moshtari2", - "receiver_phone": "565656565", - "receiver_address": "sdfhsdfsdhsdgh", - "receiver_city": "dfgsdfgsdfgs", - "extra_service": 0, - "packing_cost": 0, - "domestic_pickup": 0, - "domestic_delivery": 0, - "warehousing_cost": 0, - "items": [ - { - "description": "HHHH25", - "hs_code": "989898989", - "quantity": 12, - "unit_price": 1.20 - } - ] -} \ No newline at end of file