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; }
| # | -Order ID | -Mark No | -Description | -Origin | -Destination | -CTN | -QTY | -TTL/QTY | -Unit | -Price (₹) | -TTL Amount (₹) | -CBM | -TTL CBM | -KG | -TTL KG | -Shop No | -Status | -Date | -Action | -
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| {{ $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 | |||||||||||||||||||
| # | +Order ID | +Mark No | +Origin | +Destination | +Total CTN | +Total QTY | +Total TTL/QTY | +Total Amount (₹) | +Total CBM | +Total TTL CBM | +Total KG | +Total TTL KG | +Status | +Date | +Action | +
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| {{ $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 | +|||||||||||||||
Order ID
Total Orders
-Mark No
+Total Items
+Status
{{ ucfirst($order->status) }}Origin
+Destination
+| Item No | +# | Description | CTN | QTY | TTL/QTY | Unit | -Amount (₹) | +Price (₹) | +TTL Amount (₹) | +CBM | +TTL CBM | +KG | +TTL KG | +Shop 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 }} |