diff --git a/04_Laravel/app/Http/Controllers/OrderController.php b/04_Laravel/app/Http/Controllers/OrderController.php new file mode 100644 index 0000000..fa48265 --- /dev/null +++ b/04_Laravel/app/Http/Controllers/OrderController.php @@ -0,0 +1,109 @@ +get(); + $directions = ShipmentDirection::cases(); + $types = ShipmentType::cases(); + + return view('orders.create', compact('countries', 'directions', 'types')); + } + + public function store(Request $request) + { + $validator = Validator::make($request->all(), [ + 'direction' => ['required', 'in:export,import'], + 'type' => ['required', 'in:DOC_NORMAL,DOC_ECONOMY,PARCEL'], + 'from_country_id' => ['required', 'exists:countries,id'], + 'to_country_id' => ['required', 'exists:countries,id'], + 'forwarder' => ['nullable', 'string', 'max:255'], + 'weight' => ['required', 'numeric', 'min:0.1'], + 'volumetric_weight' => ['nullable', 'numeric', 'min:0'], + 'dimensions' => ['nullable', 'string', 'max:255'], + 'sender_name' => ['required', 'string', 'max:255'], + 'sender_company' => ['nullable', 'string', 'max:255'], + 'sender_phone' => ['required', 'string', 'max:50'], + 'sender_email' => ['nullable', 'email', 'max:255'], + 'sender_address' => ['required', 'string', 'max:500'], + 'sender_city' => ['required', 'string', 'max:255'], + 'sender_zip' => ['nullable', 'string', 'max:20'], + 'sender_id_number' => ['nullable', 'string', 'max:50'], + 'receiver_name' => ['required', 'string', 'max:255'], + 'receiver_company' => ['nullable', 'string', 'max:255'], + 'receiver_phone' => ['required', 'string', 'max:50'], + 'receiver_email' => ['nullable', 'email', 'max:255'], + 'receiver_address' => ['required', 'string', 'max:500'], + 'receiver_city' => ['required', 'string', 'max:255'], + 'receiver_zip' => ['nullable', 'string', 'max:20'], + 'receiver_id_number' => ['nullable', 'string', 'max:50'], + 'items' => ['required', 'array', 'min:1', 'max:9'], + 'items.*.description' => ['required', 'string', 'max:500'], + 'items.*.hs_code' => ['required', 'string', 'max:50'], + 'items.*.quantity' => ['required', 'numeric', 'min:1'], + 'items.*.unit_price' => ['required', 'numeric', 'min:0'], + 'items.*.total_usd' => ['required', 'numeric', 'min:0'], + ]); + + $data = $validator->validated(); + + $shipment = Shipment::create([ + 'awb_no' => 'IFNEX-' . strtoupper(uniqid()), + 'direction' => $data['direction'], + 'type' => $data['type'], + 'from_country_id' => $data['from_country_id'], + 'to_country_id' => $data['to_country_id'], + 'forwarder' => $data['forwarder'] ?? null, + 'weight' => $data['weight'], + 'volumetric_weight' => $data['volumetric_weight'] ?? $data['weight'], + 'chargeable_weight' => max($data['weight'], $data['volumetric_weight'] ?? $data['weight']), + 'dimensions' => $data['dimensions'] ?? null, + 'sender_name' => $data['sender_name'], + 'sender_company' => $data['sender_company'] ?? null, + 'sender_phone' => $data['sender_phone'], + 'sender_email' => $data['sender_email'] ?? null, + 'sender_address' => $data['sender_address'], + 'sender_city' => $data['sender_city'], + 'sender_zip' => $data['sender_zip'] ?? null, + 'sender_id_number' => $data['sender_id_number'] ?? null, + 'receiver_name' => $data['receiver_name'], + 'receiver_company' => $data['receiver_company'] ?? null, + 'receiver_phone' => $data['receiver_phone'], + 'receiver_email' => $data['receiver_email'] ?? null, + 'receiver_address' => $data['receiver_address'], + 'receiver_city' => $data['receiver_city'], + 'receiver_zip' => $data['receiver_zip'] ?? null, + 'receiver_id_number' => $data['receiver_id_number'] ?? null, + 'status' => 'processed', + ]); + + foreach ($data['items'] as $index => $item) { + $shipment->items()->create([ + 'row_number' => $index + 1, + 'description' => $item['description'], + 'hs_code' => $item['hs_code'], + 'quantity' => $item['quantity'], + 'unit_price' => $item['unit_price'], + 'total_usd' => $item['total_usd'], + ]); + } + + return redirect()->route('orders.success', $shipment)->with('success', 'سفارش شما با موفقیت ثبت شد.'); + } + + public function success(Shipment $shipment) + { + return view('orders.success', compact('shipment')); + } +} diff --git a/04_Laravel/debug_assumptions.php b/04_Laravel/debug_assumptions.php deleted file mode 100644 index 95882b3..0000000 --- a/04_Laravel/debug_assumptions.php +++ /dev/null @@ -1,27 +0,0 @@ -getSheetByName('Assumptions'); -echo "=== Assumptions sheet ===" . PHP_EOL; -echo "Total rows: " . $sheet->getHighestRow() . PHP_EOL; -echo "Total cols: " . $sheet->getHighestColumn() . PHP_EOL; - -for ($row = 1; $row <= $sheet->getHighestRow(); $row++) { - $rowData = $sheet->rangeToArray("A{$row}:Z{$row}")[0]; - echo "Row $row: " . implode(' | ', array_map(function($cell) { - return $cell === null ? '(null)' : $cell; - }, $rowData)) . PHP_EOL; -} - -echo PHP_EOL . "=== Zone sheet ===" . PHP_EOL; -$sheet = $spreadsheet->getSheetByName('Zone'); -for ($row = 1; $row <= $sheet->getHighestRow(); $row++) { - $rowData = $sheet->rangeToArray("A{$row}:Z{$row}")[0]; - echo "Row $row: " . implode(' | ', array_map(function($cell) { - return $cell === null ? '(null)' : $cell; - }, $rowData)) . PHP_EOL; -} diff --git a/04_Laravel/debug_compare.php b/04_Laravel/debug_compare.php deleted file mode 100644 index b55f70d..0000000 --- a/04_Laravel/debug_compare.php +++ /dev/null @@ -1,32 +0,0 @@ -getSheetByName('DocNor'); - -echo "=== Raw Excel values (DocNor) ===" . PHP_EOL; -for ($r = 9; $r <= 11; $r++) { - $row = $sheet->rangeToArray("A{$r}:C{$r}")[0]; - echo "Row {$r}: weight={$row[0]}, zone={$row[1]}, raw={$row[2]}, /455000=" . ($row[2] / 455000) . PHP_EOL; -} - -echo PHP_EOL . "=== Stored values (DB) ===" . PHP_EOL; -$records = \App\Models\ShippingRate::where('direction', 'export') - ->where('type', 'DOC_NORMAL') - ->where('weight', 1) - ->first(['zone_1', 'zone_2', 'zone_3', 'zone_4', 'zone_5', 'zone_6', 'zone_7']); -echo json_encode($records, JSON_PRETTY_PRINT) . PHP_EOL; - -echo PHP_EOL . "=== Raw Excel values (Export Rate) ===" . PHP_EOL; -$sheet2 = $ss->getSheetByName('Export Rate'); -for ($r = 6; $r <= 9; $r++) { - $row = $sheet2->rangeToArray("A{$r}:J{$r}")[0]; - echo "Row {$r}: " . implode(' | ', array_map(function($c) { return $c === null ? '(null)' : $c; }, $row)) . PHP_EOL; -} - -echo PHP_EOL . "=== System Settings ===" . PHP_EOL; -echo "aed_to_irr: " . \App\Models\SystemSetting::get('aed_to_irr', 455000) . PHP_EOL; -echo "profit_margin: " . \App\Models\SystemSetting::get('profit_margin', 1.25) . PHP_EOL; -echo "vat_rate: " . \App\Models\SystemSetting::get('vat_rate', 0.09) . PHP_EOL; diff --git a/04_Laravel/debug_doceco.php b/04_Laravel/debug_doceco.php deleted file mode 100644 index 647ffbb..0000000 --- a/04_Laravel/debug_doceco.php +++ /dev/null @@ -1,25 +0,0 @@ -getSheetByName('DocEco'); - -echo "=== DocEco: looking for weight 2, zone 3 ===" . PHP_EOL; -for ($row = 1; $row <= $sheet->getHighestRow(); $row++) { - $rowData = $sheet->rangeToArray("A{$row}:C{$row}")[0]; - if ((float) $rowData[0] == 2 && (int) $rowData[1] == 3) { - echo "Row $row: Weight={$rowData[0]}, Zone={$rowData[1]}, Value={$rowData[2]}" . PHP_EOL; - echo "Divided by 455000: " . ($rowData[2] / 455000) . PHP_EOL; - echo "Divided by 37000: " . ($rowData[2] / 37000) . PHP_EOL; - echo "Divided by 30000: " . ($rowData[2] / 30000) . PHP_EOL; - break; - } -} - -echo PHP_EOL . "=== DocEco: all rows ===" . PHP_EOL; -for ($row = 2; $row <= $sheet->getHighestRow(); $row++) { - $rowData = $sheet->rangeToArray("A{$row}:C{$row}")[0]; - echo "Row $row: {$rowData[0]} | {$rowData[1]} | {$rowData[2]}" . PHP_EOL; -} diff --git a/04_Laravel/debug_meta.php b/04_Laravel/debug_meta.php deleted file mode 100644 index 8e9e001..0000000 --- a/04_Laravel/debug_meta.php +++ /dev/null @@ -1,37 +0,0 @@ -getSheetNames() as $name) { - echo " - $name" . PHP_EOL; -} - -// Check DocNor for any notes -$sheet = $spreadsheet->getSheetByName('DocNor'); -echo PHP_EOL . "=== DocNor notes/comments ===" . PHP_EOL; -$comments = $sheet->getComments(); -foreach ($comments as $cell => $comment) { - echo "Cell $cell: " . $comment->getText() . PHP_EOL; -} - -// Check for any cells with formulas -echo PHP_EOL . "=== DocNor formulas ===" . PHP_EOL; -for ($row = 1; $row <= 5; $row++) { - for ($col = 1; $col <= 3; $col++) { - $cell = $sheet->getCellByColumnAndRow($col, $row); - if ($cell->getDataType() == \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_FORMULA) { - echo "Cell " . $cell->getCoordinate() . ": " . $cell->getValue() . " = " . $cell->getCalculatedValue() . PHP_EOL; - } - } -} - -// Check if there's any metadata -echo PHP_EOL . "=== DocNor first cell values ===" . PHP_EOL; -echo "A1: " . $sheet->getCell('A1')->getValue() . PHP_EOL; -echo "B1: " . $sheet->getCell('B1')->getValue() . PHP_EOL; -echo "C1: " . $sheet->getCell('C1')->getValue() . PHP_EOL; diff --git a/04_Laravel/debug_rates.php b/04_Laravel/debug_rates.php deleted file mode 100644 index a618e91..0000000 --- a/04_Laravel/debug_rates.php +++ /dev/null @@ -1,29 +0,0 @@ -getSheetByName($sheetName); - if (!$sheet) { - echo "Sheet '$sheetName' not found" . PHP_EOL; - continue; - } - - echo "=== Sheet: $sheetName ===" . PHP_EOL; - echo "Total rows: " . $sheet->getHighestRow() . PHP_EOL; - echo "Total cols: " . $sheet->getHighestColumn() . PHP_EOL; - - // Print first 10 rows - for ($row = 1; $row <= min(10, $sheet->getHighestRow()); $row++) { - $rowData = $sheet->rangeToArray("A{$row}:J{$row}")[0]; - echo "Row $row: " . implode(' | ', array_map(function($cell) { - return $cell === null ? '(null)' : $cell; - }, $rowData)) . PHP_EOL; - } - echo PHP_EOL; -} diff --git a/04_Laravel/debug_search.php b/04_Laravel/debug_search.php deleted file mode 100644 index c2f9f3d..0000000 --- a/04_Laravel/debug_search.php +++ /dev/null @@ -1,19 +0,0 @@ -getSheetNames() as $sheetName) { - $sheet = $spreadsheet->getSheetByName($sheetName); - echo "=== $sheetName ===" . PHP_EOL; - - foreach ($sheet->getCellCollection() as $cell) { - $value = $sheet->getCell($cell)->getValue(); - if (is_string($value) && (stripos($value, 'rate') !== false || stripos($value, 'exchange') !== false || stripos($value, 'currency') !== false || stripos($value, 'aed') !== false || stripos($value, 'irr') !== false || stripos($value, 'rial') !== false || stripos($value, 'dirham') !== false)) { - echo " Cell {$cell}: {$value}" . PHP_EOL; - } - } -} diff --git a/04_Laravel/debug_start.php b/04_Laravel/debug_start.php deleted file mode 100644 index b8da145..0000000 --- a/04_Laravel/debug_start.php +++ /dev/null @@ -1,19 +0,0 @@ -getSheetByName($sheetName); - if (!$sheet) continue; - echo "=== $sheetName ===" . PHP_EOL; - for ($row = 1; $row <= min(10, $sheet->getHighestRow()); $row++) { - $rowData = $sheet->rangeToArray("A{$row}:Z{$row}")[0]; - echo "Row $row: " . implode(' | ', array_map(function($cell) { - return $cell === null ? '(null)' : $cell; - }, $rowData)) . PHP_EOL; - } - echo PHP_EOL; -} diff --git a/04_Laravel/debug_structure.php b/04_Laravel/debug_structure.php deleted file mode 100644 index adba81f..0000000 --- a/04_Laravel/debug_structure.php +++ /dev/null @@ -1,25 +0,0 @@ -getSheetByName('Export Rate'); -echo "=== Export Rate full structure ===" . PHP_EOL; -for ($row = 1; $row <= 15; $row++) { - $rowData = $sheet->rangeToArray("A{$row}:L{$row}")[0]; - echo "Row $row: " . implode(' | ', array_map(function($cell) { - return $cell === null ? '(null)' : $cell; - }, $rowData)) . PHP_EOL; -} - -echo PHP_EOL . "=== Import Rate full structure ===" . PHP_EOL; -$sheet = $spreadsheet->getSheetByName('Import Rate'); -for ($row = 1; $row <= 15; $row++) { - $rowData = $sheet->rangeToArray("A{$row}:K{$row}")[0]; - echo "Row $row: " . implode(' | ', array_map(function($cell) { - return $cell === null ? '(null)' : $cell; - }, $rowData)) . PHP_EOL; -} diff --git a/04_Laravel/debug_structure2.php b/04_Laravel/debug_structure2.php deleted file mode 100644 index eb840b4..0000000 --- a/04_Laravel/debug_structure2.php +++ /dev/null @@ -1,20 +0,0 @@ -getSheetByName('Export Rate'); -for ($r = 4; $r <= 14; $r++) { - $row = $sheet->rangeToArray("A{$r}:L{$r}")[0]; - echo "Row {$r}: " . implode(' | ', array_map(function($c) { return $c === null ? '(null)' : $c; }, $row)) . PHP_EOL; -} - -echo PHP_EOL . "=== Import Rate structure ===" . PHP_EOL; -$sheet = $ss->getSheetByName('Import Rate'); -for ($r = 4; $r <= 14; $r++) { - $row = $sheet->rangeToArray("A{$r}:K{$r}")[0]; - echo "Row {$r}: " . implode(' | ', array_map(function($c) { return $c === null ? '(null)' : $c; }, $row)) . PHP_EOL; -} diff --git a/04_Laravel/resources/views/layouts/app.blade.php b/04_Laravel/resources/views/layouts/app.blade.php new file mode 100644 index 0000000..fe5b160 --- /dev/null +++ b/04_Laravel/resources/views/layouts/app.blade.php @@ -0,0 +1,55 @@ + + + + + + {{ config('app.name', 'IFNEX Logistics') }} — ثبت سفارش + + + + + +
+ @if(session('success')) +
+
+ {{ session('success') }} +
+
+ @endif + + @if($errors->any()) +
+
+
    + @foreach($errors->all() as $error) +
  • {{ $error }}
  • + @endforeach +
+
+
+ @endif + + @yield('content') +
+ + + + @stack('scripts') + + diff --git a/04_Laravel/resources/views/orders/create.blade.php b/04_Laravel/resources/views/orders/create.blade.php new file mode 100644 index 0000000..8637866 --- /dev/null +++ b/04_Laravel/resources/views/orders/create.blade.php @@ -0,0 +1,405 @@ +@extends('layouts.app') + +@section('content') +
+
+
+

فرم ثبت سفارش

+

لطفاً اطلاعات مرسوله و کالاهای گمرکی را وارد کنید

+
+ +
+ @csrf + + + + +
+
+

اطلاعات مسیر

+ +
+ + +
+ +
+ + +
+ +
+
+ + +
+
+ + +
+
+ +
+ + +
+ +
+
+ + +
+
+ + +
+
+ +
+ + +
+ + +
+ +
+

اطلاعات فرستنده

+ +
+
+ + +
+
+ + +
+
+ +
+
+ + +
+
+ + +
+
+ +
+ + +
+ +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ +
+

اطلاعات گیرنده

+
+
+
+
+ + +
+
+ + +
+
+ +
+
+ + +
+
+ + +
+
+ +
+ + +
+ +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+
+ +
+
+

کالاهای گمرکی

+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
ردیفشرح کالاکد HSتعدادقیمت واحد (USD)جمع (USD)عملیات
+
+ +
+
+
جمع کل فاکتور (USD):
+
0.00
+
+
+
+ + + +
+ +
+
+
+
+@endsection + +@push('scripts') + +@endpush diff --git a/04_Laravel/resources/views/orders/success.blade.php b/04_Laravel/resources/views/orders/success.blade.php new file mode 100644 index 0000000..bc71343 --- /dev/null +++ b/04_Laravel/resources/views/orders/success.blade.php @@ -0,0 +1,24 @@ +@extends('layouts.app') + +@section('content') +
+
+
+ + + +
+

سفارش شما با موفقیت ثبت شد

+

کد پیگیری سفارش شما:

+
+ {{ $shipment->awb_no ?? 'N/A' }} +
+

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

+ +
+
+@endsection diff --git a/04_Laravel/routes/api.php b/04_Laravel/routes/api.php index 48c0e2f..88e1aba 100644 --- a/04_Laravel/routes/api.php +++ b/04_Laravel/routes/api.php @@ -1,5 +1,6 @@ prefix('v1')->group(function () { Route::get('/track/{awb_no}', [TrackController::class, 'show']); }); + +Route::post('/v1/calculate', [PricingController::class, 'calculate']); diff --git a/04_Laravel/routes/web.php b/04_Laravel/routes/web.php index 86a06c5..b8eee92 100644 --- a/04_Laravel/routes/web.php +++ b/04_Laravel/routes/web.php @@ -1,7 +1,12 @@ name('orders.create'); +Route::post('/order', [OrderController::class, 'store'])->name('orders.store'); +Route::get('/order/success/{shipment}', [OrderController::class, 'success'])->name('orders.success');