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.
This commit is contained in:
parent
0209b6b32e
commit
78d21942db
@ -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/
|
||||
@ -1,32 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
if (!Schema::hasTable('shipment_packages')) {
|
||||
Schema::create('shipment_packages', function (Blueprint $table) {
|
||||
$table->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');
|
||||
}
|
||||
};
|
||||
@ -1,2 +0,0 @@
|
||||
$kind: collection
|
||||
name: New Collection
|
||||
@ -1,8 +0,0 @@
|
||||
name: IFNEX Local
|
||||
values:
|
||||
- key: base_url
|
||||
value: ''
|
||||
- key: token
|
||||
value: ''
|
||||
- key: ''
|
||||
value: ''
|
||||
@ -1,6 +0,0 @@
|
||||
name: IFNEX Local2
|
||||
values:
|
||||
- key: base_url
|
||||
value: ''
|
||||
- key: token
|
||||
value: ''
|
||||
@ -1,2 +0,0 @@
|
||||
name: Globals
|
||||
values: []
|
||||
@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -1,145 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* اسکریپت تست تولید PDF برای IFNEX
|
||||
*
|
||||
* این اسکریپت یه محموله نمونه میسازه و سه تا PDF (AWB, Invoice, Label) تولید میکنه
|
||||
* و اونها رو توی پوشه storage/app/pdf-test/ ذخیره میکنه.
|
||||
*
|
||||
* استفاده:
|
||||
* php test_pdf_generation.php
|
||||
*
|
||||
* پس از اجرا، فایلهای تولیدشده رو بررسی کنید:
|
||||
* storage/app/pdf-test/AWB-test.pdf
|
||||
* storage/app/pdf-test/INVOICE-test.pdf
|
||||
* storage/app/pdf-test/LABEL-test.pdf
|
||||
*/
|
||||
|
||||
require __DIR__ . '/vendor/autoload.php';
|
||||
$app = require_once __DIR__ . '/bootstrap/app.php';
|
||||
$app->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";
|
||||
@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user