diff --git a/app/Http/Controllers/Admin/AdminOrderController.php b/app/Http/Controllers/Admin/AdminOrderController.php index 827bd9d..051da6f 100644 --- a/app/Http/Controllers/Admin/AdminOrderController.php +++ b/app/Http/Controllers/Admin/AdminOrderController.php @@ -5,74 +5,198 @@ namespace App\Http\Controllers\Admin; use App\Http\Controllers\Controller; use Illuminate\Http\Request; use App\Models\Order; -use App\Models\MarkList; // ✅ Correct model +use App\Models\OrderItem; +use App\Models\MarkList; class AdminOrderController extends Controller { public function index() { $orders = Order::latest()->get(); - $markList = MarkList::where('status', 'active')->get(); // ✅ Correct usage + $markList = MarkList::where('status', 'active')->get(); return view('admin.dashboard', compact('orders', 'markList')); } - public function store(Request $request) -{ - $request->validate([ - 'mark_no' => 'required', - 'description' => 'required', - ]); + // ------------------------------------------------------------------------- + // STEP 1 : ADD TEMPORARY ITEM + // ------------------------------------------------------------------------- - // ✅ Generate custom order_id like KNT-25-00000001 - $year = date('y'); - $prefix = "KNT-$year-"; + public function addTempItem(Request $request) + { + // Validate item fields + $item = $request->validate([ + 'mark_no' => 'required', + 'origin' => 'required', + 'destination' => 'required', + 'description' => 'required|string', + 'ctn' => 'nullable|numeric', + 'qty' => 'nullable|numeric', + 'ttl_qty' => 'nullable|numeric', + 'unit' => 'nullable|string', + 'price' => 'nullable|numeric', + 'ttl_amount' => 'nullable|numeric', + 'cbm' => 'nullable|numeric', + 'ttl_cbm' => 'nullable|numeric', + 'kg' => 'nullable|numeric', + 'ttl_kg' => 'nullable|numeric', + 'shop_no' => 'nullable|string', + ]); - // Get the last order to increment number - $lastOrder = Order::latest('id')->first(); - $nextNumber = $lastOrder ? intval(substr($lastOrder->order_id, -8)) + 1 : 1; + // ❌ Prevent changing mark_no once first item added + if (session()->has('mark_no') && session('mark_no') != $request->mark_no) { + return redirect()->to(route('admin.orders.index') . '#createOrderForm') + ->with('error', 'You must finish or clear the current order before changing Mark No.'); + } - // Format number with leading zeros (8 digits) - $newOrderId = $prefix . str_pad($nextNumber, 8, '0', STR_PAD_LEFT); + // Save mark, origin, destination ONLY ONCE + if (!session()->has('mark_no')) { + session([ + 'mark_no' => $request->mark_no, + 'origin' => $request->origin, + 'destination' => $request->destination + ]); + } - // ✅ Create order - $order = new Order(); - $order->order_id = $newOrderId; // ✅ set this field - $order->mark_no = $request->mark_no; - $order->origin = $request->origin; - $order->destination = $request->destination; - $order->description = $request->description; - $order->ctn = $request->ctn; - $order->qty = $request->qty; - $order->ttl_qty = $request->ttl_qty; - $order->unit = $request->unit; - $order->price = $request->price; - $order->ttl_amount = $request->ttl_amount; - $order->cbm = $request->cbm; - $order->ttl_cbm = $request->ttl_cbm; - $order->kg = $request->kg; - $order->ttl_kg = $request->ttl_kg; - $order->shop_no = $request->shop_no; - $order->status = 'pending'; - $order->save(); + // ❌ DO NOT overwrite these values again + // session(['mark_no' => $request->mark_no]); + // session(['origin' => $request->origin]); + // session(['destination' => $request->destination]); - return redirect()->back()->with('success', 'Order created successfully with ID: ' . $newOrderId); -} + // Add new sub-item into session + session()->push('temp_order_items', $item); + + return redirect()->to(route('admin.orders.index') . '#createOrderForm') + ->with('success', 'Item added.'); + } + + // ------------------------------------------------------------------------- + // STEP 2 : DELETE TEMPORARY ITEM + // ------------------------------------------------------------------------- + + public function deleteTempItem(Request $request) + { + $index = $request->index; + + $items = session('temp_order_items', []); + + if (isset($items[$index])) { + unset($items[$index]); + session(['temp_order_items' => array_values($items)]); + } + + // If no items left → reset mark_no lock + if (empty($items)) { + session()->forget(['mark_no', 'origin', 'destination']); + } + + return redirect()->to(route('admin.orders.index') . '#createOrderForm') + ->with('success', 'Item removed successfully.'); + } + + // ------------------------------------------------------------------------- + // STEP 3 : FINISH ORDER + // ------------------------------------------------------------------------- + + public function finishOrder(Request $request) + { + $request->validate([ + 'mark_no' => 'required', + 'origin' => 'required', + 'destination' => 'required', + ]); + + $items = session('temp_order_items', []); + + if (empty($items)) { + return redirect()->to(route('admin.orders.index') . '#createOrderForm') + ->with('error', 'Add at least one item before finishing.'); + } + + // Generate Order ID + $year = date('y'); + $prefix = "KNT-$year-"; + + $lastOrder = Order::latest('id')->first(); + $nextNumber = $lastOrder ? intval(substr($lastOrder->order_id, -8)) + 1 : 1; + + $orderId = $prefix . str_pad($nextNumber, 8, '0', STR_PAD_LEFT); + + // TOTAL SUMS + $total_ctn = array_sum(array_column($items, 'ctn')); + $total_qty = array_sum(array_column($items, 'qty')); + $total_ttl_qty = array_sum(array_column($items, 'ttl_qty')); + $total_amount = array_sum(array_column($items, 'ttl_amount')); + $total_cbm = array_sum(array_column($items, 'cbm')); + $total_ttl_cbm = array_sum(array_column($items, 'ttl_cbm')); + $total_kg = array_sum(array_column($items, 'kg')); + $total_ttl_kg = array_sum(array_column($items, 'ttl_kg')); + + // CREATE ORDER + $order = Order::create([ + 'order_id' => $orderId, + 'mark_no' => $request->mark_no, + 'origin' => $request->origin, + 'destination' => $request->destination, + 'ctn' => $total_ctn, + 'qty' => $total_qty, + 'ttl_qty' => $total_ttl_qty, + 'ttl_amount' => $total_amount, + 'cbm' => $total_cbm, + 'ttl_cbm' => $total_ttl_cbm, + 'kg' => $total_kg, + 'ttl_kg' => $total_ttl_kg, + 'status' => 'pending', + ]); + + // SAVE ALL SUB-ITEMS + foreach ($items as $item) { + OrderItem::create([ + 'order_id' => $order->id, + 'description' => $item['description'], + 'ctn' => $item['ctn'], + 'qty' => $item['qty'], + 'ttl_qty' => $item['ttl_qty'], + 'unit' => $item['unit'], + 'price' => $item['price'], + 'ttl_amount' => $item['ttl_amount'], + 'cbm' => $item['cbm'], + 'ttl_cbm' => $item['ttl_cbm'], + 'kg' => $item['kg'], + 'ttl_kg' => $item['ttl_kg'], + 'shop_no' => $item['shop_no'], + ]); + } + + // CLEAR TEMP DATA + session()->forget(['temp_order_items', 'mark_no', 'origin', 'destination']); + + return redirect()->route('admin.orders.index') + ->with('success', 'Order saved successfully.'); + } + + // ------------------------------------------------------------------------- + // ORDER SHOW PAGE + // ------------------------------------------------------------------------- public function show($id) { - $order = Order::with('markList')->findOrFail($id); + $order = Order::with('items', 'markList')->findOrFail($id); - // Get the mark list associated with this order - $markList = $order->markList; - - // Fetch the user using the customer_id from mark list $user = null; - if ($markList && $markList->customer_id) { - $user = \App\Models\User::where('customer_id', $markList->customer_id)->first(); + if ($order->markList && $order->markList->customer_id) { + $user = \App\Models\User::where('customer_id', $order->markList->customer_id)->first(); } - return view('admin.orders_show', compact('order', 'markList', 'user')); + return view('admin.orders_show', compact('order', 'user')); + } + + public function resetTemp() + { + session()->forget(['temp_order_items', 'mark_no', 'origin', 'destination']); + + return redirect()->to(route('admin.orders.index') . '#createOrderForm') + ->with('success', 'Order reset successfully.'); } } diff --git a/app/Models/Order.php b/app/Models/Order.php index c387c31..fdfd683 100644 --- a/app/Models/Order.php +++ b/app/Models/Order.php @@ -4,19 +4,37 @@ namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; -use App\Models\MarkList; class Order extends Model { use HasFactory; protected $fillable = [ - 'order_id', 'mark_no', 'description', 'origin', 'destination', - 'ctn', 'qty', 'ttl_qty', 'unit', 'price', 'ttl_amount', - 'cbm', 'ttl_cbm', 'kg', 'ttl_kg', 'shop_no', 'status' + 'order_id', + 'mark_no', + 'origin', + 'destination', + + // totals only + 'ctn', + 'qty', + 'ttl_qty', + 'ttl_amount', + 'cbm', + 'ttl_cbm', + 'kg', + 'ttl_kg', + + 'status' ]; - // Relation using mark_no instead of id + // One order has many items + public function items() + { + return $this->hasMany(OrderItem::class); + } + + // Link using mark_no (optional) public function markList() { return $this->hasOne(MarkList::class, 'mark_no', 'mark_no'); diff --git a/app/Models/OrderItem.php b/app/Models/OrderItem.php new file mode 100644 index 0000000..75cd416 --- /dev/null +++ b/app/Models/OrderItem.php @@ -0,0 +1,38 @@ + 'array', + ]; + + // Link to parent order + public function order() + { + return $this->belongsTo(Order::class); + } +} diff --git a/database/migrations/2025_11_13_060808_create_order_items_table.php b/database/migrations/2025_11_13_060808_create_order_items_table.php new file mode 100644 index 0000000..a677ccb --- /dev/null +++ b/database/migrations/2025_11_13_060808_create_order_items_table.php @@ -0,0 +1,64 @@ +bigIncrements('id'); + + // Link to orders table (parent order) + $table->foreignId('order_id')->constrained('orders')->onDelete('cascade'); + + // Sub-order / line item fields + $table->string('description')->nullable(); + $table->integer('ctn')->nullable()->default(0); + $table->integer('qty')->nullable()->default(0); + $table->integer('ttl_qty')->nullable()->default(0); + + $table->string('unit')->nullable(); + + // financials & measurements + $table->decimal('price', 14, 2)->nullable()->default(0.00); + $table->decimal('ttl_amount', 16, 2)->nullable()->default(0.00); + + $table->decimal('cbm', 12, 3)->nullable()->default(0.000); + $table->decimal('ttl_cbm', 14, 3)->nullable()->default(0.000); + + $table->decimal('kg', 12, 3)->nullable()->default(0.000); + $table->decimal('ttl_kg', 14, 3)->nullable()->default(0.000); + + $table->string('shop_no')->nullable(); + + // optional extra data (json for extensibility) + $table->json('meta')->nullable(); + + $table->timestamps(); + + // Indexes for common queries + $table->index('order_id'); + $table->index('ctn'); + $table->index('qty'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('order_items'); + } +} diff --git a/resources/views/admin/dashboard.blade.php b/resources/views/admin/dashboard.blade.php index c63bb20..ab8d9bd 100644 --- a/resources/views/admin/dashboard.blade.php +++ b/resources/views/admin/dashboard.blade.php @@ -135,29 +135,29 @@ body, .container-fluid { background: #f4f7fc; }
- +
Admin Dashboard
Monitor operations and manage system
- +
-
📦
Total Shipments
1,247
-
👥
Active Customers
342
-
💰
Total Revenue
₹123
-
Pending Order
23
+
📦
Total Shipments
1,247
+
👥
Active Customers
342
+
💰
Total Revenue
₹123
+
Pending Order
23
-
📦
Total Orders
453
-
🧑‍💼
Total Staff
125
-
📦
Total Items
321
-
Inactive Customers
10
+
📦
Total Orders
453
+
🧑‍💼
Total Staff
125
+
📦
Total Items
321
+
Inactive Customers
10
- +
Order Management @@ -165,123 +165,307 @@ body, .container-fluid { background: #f4f7fc; } Create Order
+
- +
+
New Order Form
-
+ + {{-- FORM START --}} + @csrf +
-
- + + {{-- MARK NO --}} +
+ + + @if(session('temp_order_items')) + {{-- Mark No locked, cannot be changed --}} + + + {{-- Hidden field to submit mark_no --}} + + + @else + {{-- Normal selectable dropdown --}} + + @endif
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- + + + {{-- ORIGIN --}} +
+ + +
+ + {{-- DESTINATION --}} +
+ + +
+ +
+ +
+ + {{-- ITEM INPUTS --}} +
Add Item
+ +
+
+ + +
+ +
+
+
+ +
+ +
+
+ +
+
+ +
+
+ +
+ +
+
+ + {{-- FORM END --}} + + {{-- RESET ORDER BUTTON --}} + @if(session('temp_order_items')) +
+
+ @csrf + +
+
+ @endif + + {{-- TEMPORARY ITEMS TABLE --}} + @if(session('temp_order_items') && count(session('temp_order_items')) > 0) + +
+ +
Temporary Items
+ + + + + + + + + + + + + + + + + + + + + + + @foreach(session('temp_order_items') as $index => $item) + + + + + + + + + + + + + + + + + + @endforeach + +
#DescriptionCTNQTYTTL/QTYUnitPriceTTL AmountCBMTTL CBMKGTTL KGShop NoRemove
{{ $index + 1 }}{{ $item['description'] }}{{ $item['ctn'] }}{{ $item['qty'] }}{{ $item['ttl_qty'] }}{{ $item['unit'] }}{{ $item['price'] }}{{ $item['ttl_amount'] }}{{ $item['cbm'] }}{{ $item['ttl_cbm'] }}{{ $item['kg'] }}{{ $item['ttl_kg'] }}{{ $item['shop_no'] }} +
+ @csrf + + +
+
+ +
+
+ @csrf + + + + + +
+
+ + @endif +
- - {{-- Recent Orders Table --}} -
-
- Recent Orders -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - @forelse($orders as $index => $order) - - - - - - - - - - - - - - - - - - - - - - - @empty - - @endforelse - -
#Order IDMark NoDescriptionOriginDestinationCTNQTYTTL/QTYUnitPrice (₹)TTL Amount (₹)CBMTTL CBMKGTTL KGShop NoStatusDateAction
{{ $order->id }}{{ $order->order_id }}{{ $order->mark_no }}{{ $order->description }}{{ $order->origin }}{{ $order->destination }}{{ $order->ctn }}{{ $order->qty }}{{ $order->ttl_qty }}{{ $order->unit }}₹{{ number_format($order->price, 2) }}₹{{ number_format($order->ttl_amount, 2) }}{{ $order->cbm }}{{ $order->ttl_cbm }}{{ $order->kg }}{{ $order->ttl_kg }}{{ $order->shop_no }}{{ ucfirst($order->status) }}{{ $order->created_at->format('d-m-Y') }} - - View - -
No orders found
+ + +
+
+ Recent Orders +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + @forelse($orders as $order) + + + + + + + + + + + + + + + + + + + + + + + + + + + @empty + + + + @endforelse + + +
#Order IDMark NoOriginDestinationTotal CTNTotal QTYTotal TTL/QTYTotal Amount (₹)Total CBMTotal TTL CBMTotal KGTotal TTL KGStatusDateAction
{{ $order->id }} + + {{ $order->order_id }} + + {{ $order->mark_no }}{{ $order->origin }}{{ $order->destination }}{{ $order->ctn }}{{ $order->qty }}{{ $order->ttl_qty }}₹{{ number_format($order->ttl_amount, 2) }}{{ $order->cbm }}{{ $order->ttl_cbm }}{{ $order->kg }}{{ $order->ttl_kg }} + {{ ucfirst($order->status) }} + {{ $order->created_at->format('d-m-Y') }} + + View + +
No orders found
+
+ +
+
-
+ +{{-- JS: LOCK MARK NO + LOAD ORIGIN/DESTINATION --}} + +{{-- AUTO OPEN FORM AFTER REDIRECT --}} + + @endsection diff --git a/resources/views/admin/orders_show.blade.php b/resources/views/admin/orders_show.blade.php index 1aa40da..08806dd 100644 --- a/resources/views/admin/orders_show.blade.php +++ b/resources/views/admin/orders_show.blade.php @@ -10,8 +10,8 @@
-

Orders Details

- Detailed view of all orders in this shipment consolidation. +

Order Details

+ Detailed view of this shipment order
@@ -43,61 +43,101 @@ {{-- Order Summary --}}
-
+

Order ID

{{ $order->order_id }}
-
-

Total Orders

-
{{ 1 }}
+ +
+

Mark No

+
{{ $order->mark_no }}
-
+ +
+

Total Items

+
{{ $order->items->count() }}
+
+ +

Status

{{ ucfirst($order->status) }}
- {{-- Order Table --}} + {{-- Origin - Destination --}} +
+
+

Origin

+
{{ $order->origin }}
+
+
+

Destination

+
{{ $order->destination }}
+
+
+ + {{-- Order Items Table --}}
- +
- + - + + + + + + + + @foreach($order->items as $index => $item) - - - - - - - + + + + + + + + + + + + + + @endforeach
Item No# Description CTN QTY TTL/QTY UnitAmount (₹)Price (₹)TTL Amount (₹)CBMTTL CBMKGTTL KGShop No
{{ $order->mark_no }}{{ $order->description }}{{ $order->ctn }}{{ $order->qty }}{{ $order->ttl_qty }}{{ $order->unit }}₹{{ number_format($order->ttl_amount, 2) }}{{ $index + 1 }}{{ $item->description }}{{ $item->ctn }}{{ $item->qty }}{{ $item->ttl_qty }}{{ $item->unit }}{{ number_format($item->price, 2) }}{{ number_format($item->ttl_amount, 2) }}{{ $item->cbm }}{{ $item->ttl_cbm }}{{ $item->kg }}{{ $item->ttl_kg }}{{ $item->shop_no }}
{{-- Totals --}} -
-
-
{{ $order->ttl_qty }}
- Total TTL/QTY +
+
+
{{ $order->ctn }}
+ Total CTN
-
-
{{ $order->ttl_kg }}
+ +
+
{{ $order->qty }}
+ Total QTY +
+ +
+
{{ $order->ttl_kg }}
Total TTL KG
-
-
₹{{ number_format($order->ttl_amount, 2) }}
+ +
+
₹{{ number_format($order->ttl_amount, 2) }}
Total Amount
diff --git a/routes/web.php b/routes/web.php index c9958fe..f21c935 100644 --- a/routes/web.php +++ b/routes/web.php @@ -51,9 +51,30 @@ Route::prefix('admin')->middleware('auth:admin')->group(function () { Route::get('/mark-list/status/{id}', [AdminMarkListController::class, 'toggleStatus'])->name('admin.marklist.toggle'); Route::get('/orders', fn() => view('admin.orders'))->name('admin.orders'); + // Orders Controller Routes - Route::get('/orders/list', [AdminOrderController::class, 'index'])->name('admin.orders.index'); - Route::post('/orders/store', [AdminOrderController::class, 'store'])->name('admin.orders.store'); - Route::get('/orders/{id}', [AdminOrderController::class, 'show'])->name('admin.orders.show'); + // Show admin order dashboard (list + create form) + Route::get('/orders/list', [AdminOrderController::class, 'index']) + ->name('admin.orders.index'); + + // View a single order + Route::get('/orders/{id}', [AdminOrderController::class, 'show']) + ->name('admin.orders.show'); + + // TEMPORARY ITEMS (multi-order system) + Route::post('/orders/temp/add', [AdminOrderController::class, 'addTempItem']) + ->name('admin.orders.temp.add'); + + Route::post('/orders/temp/delete', [AdminOrderController::class, 'deleteTempItem']) + ->name('admin.orders.temp.delete'); + + // Finish and save order + Route::post('/orders/finish', [AdminOrderController::class, 'finishOrder']) + ->name('admin.orders.finish'); + + Route::post('/orders/temp/reset', [AdminOrderController::class, 'resetTemp']) + ->name('admin.orders.temp.reset'); + + });