From e0a8a5c69ced954c50ce048a5e253155cb4e8088a0c4bcbda571dc35d73a55bb Mon Sep 17 00:00:00 2001 From: Abhishek Mali Date: Tue, 23 Dec 2025 00:36:15 +0530 Subject: [PATCH] status update --- .../Admin/AdminOrderController.php | 70 ++++---- .../Controllers/Admin/ShipmentController.php | 96 +++++++---- .../Controllers/user/UserOrderController.php | 38 +++++ app/Models/Order.php | 20 +++ app/Models/Shipment.php | 51 +++--- resources/views/admin/dashboard.blade.php | 54 +++++-- resources/views/admin/shipments.blade.php | 149 ++++++++++++------ routes/api.php | 1 + 8 files changed, 332 insertions(+), 147 deletions(-) diff --git a/app/Http/Controllers/Admin/AdminOrderController.php b/app/Http/Controllers/Admin/AdminOrderController.php index 486040f..95afaf4 100644 --- a/app/Http/Controllers/Admin/AdminOrderController.php +++ b/app/Http/Controllers/Admin/AdminOrderController.php @@ -36,43 +36,43 @@ class AdminOrderController extends Controller return view('admin.orders_create', compact('markList')); } - public function store(Request $request) - { - $data = $request->validate([ - 'mark_no' => 'required|string', - 'origin' => 'nullable|string', - 'destination' => 'nullable|string', - 'ctn' => 'nullable|numeric', - 'qty' => 'nullable|numeric', - 'ttl_qty' => 'nullable|numeric', - 'ttl_amount' => 'nullable|numeric', - 'cbm' => 'nullable|numeric', - 'ttl_cbm' => 'nullable|numeric', - 'kg' => 'nullable|numeric', - 'ttl_kg' => 'nullable|numeric', - ]); + // public function store(Request $request) + // { + // $data = $request->validate([ + // 'mark_no' => 'required|string', + // 'origin' => 'nullable|string', + // 'destination' => 'nullable|string', + // 'ctn' => 'nullable|numeric', + // 'qty' => 'nullable|numeric', + // 'ttl_qty' => 'nullable|numeric', + // 'ttl_amount' => 'nullable|numeric', + // 'cbm' => 'nullable|numeric', + // 'ttl_cbm' => 'nullable|numeric', + // 'kg' => 'nullable|numeric', + // 'ttl_kg' => 'nullable|numeric', + // ]); - $order = Order::create([ - 'order_id' => $this->generateOrderId(), - 'mark_no' => $data['mark_no'], - 'origin' => $data['origin'] ?? null, - 'destination'=> $data['destination'] ?? null, - 'ctn' => $data['ctn'] ?? 0, - 'qty' => $data['qty'] ?? 0, - 'ttl_qty' => $data['ttl_qty'] ?? 0, - 'ttl_amount' => $data['ttl_amount'] ?? 0, - 'cbm' => $data['cbm'] ?? 0, - 'ttl_cbm' => $data['ttl_cbm'] ?? 0, - 'kg' => $data['kg'] ?? 0, - 'ttl_kg' => $data['ttl_kg'] ?? 0, - 'status' => 'pending', - ]); + // $order = Order::create([ + // 'order_id' => $this->generateOrderId(), + // 'mark_no' => $data['mark_no'], + // 'origin' => $data['origin'] ?? null, + // 'destination'=> $data['destination'] ?? null, + // 'ctn' => $data['ctn'] ?? 0, + // 'qty' => $data['qty'] ?? 0, + // 'ttl_qty' => $data['ttl_qty'] ?? 0, + // 'ttl_amount' => $data['ttl_amount'] ?? 0, + // 'cbm' => $data['cbm'] ?? 0, + // 'ttl_cbm' => $data['ttl_cbm'] ?? 0, + // 'kg' => $data['kg'] ?? 0, + // 'ttl_kg' => $data['ttl_kg'] ?? 0, + // 'status' => 'pending', + // ]); - $this->createInvoice($order); + // $this->createInvoice($order); - return redirect()->route('admin.orders.show', $order->id) - ->with('success', 'Order created successfully.'); - } + // return redirect()->route('admin.orders.show', $order->id) + // ->with('success', 'Order created successfully.'); + // } /* --------------------------- * SHOW / POPUP @@ -580,7 +580,7 @@ class AdminOrderController extends Controller 'ttl_cbm' => $total_ttl_cbm, 'kg' => $total_kg, 'ttl_kg' => $total_ttl_kg, - 'status' => 'pending', + 'status' => 'order_placed', ]); // 6) order items diff --git a/app/Http/Controllers/Admin/ShipmentController.php b/app/Http/Controllers/Admin/ShipmentController.php index 6feffef..781507e 100644 --- a/app/Http/Controllers/Admin/ShipmentController.php +++ b/app/Http/Controllers/Admin/ShipmentController.php @@ -20,7 +20,11 @@ class ShipmentController extends Controller $usedOrderIds = ShipmentItem::pluck('order_id')->toArray(); // 2) Load available orders (not used in any shipment) - $availableOrders = Order::whereNotIn('id', $usedOrderIds)->get(); + $availableOrders = Order::whereNotIn('id', $usedOrderIds) + ->where('status', '!=', 'order_placed') + ->get(); + + // 3) Load all shipments for listing $shipments = Shipment::latest()->get(); @@ -65,6 +69,16 @@ class ShipmentController extends Controller // CALCULATE TOTALS // ----------------------------- $orders = Order::whereIn('id', $request->order_ids)->get(); + foreach ($orders as $order) { + if ($order->status === 'order_placed') { + return back()->with( + 'error', + "Order {$order->order_id} is not ready for shipment" + ); + } + } + + $total_ctn = $orders->sum('ctn'); $total_qty = $orders->sum('qty'); @@ -82,7 +96,7 @@ class ShipmentController extends Controller 'shipment_id' => $newShipmentId, 'origin' => $request->origin, 'destination' => $request->destination, - 'status' => Shipment::STATUS_PENDING, + 'status' => Shipment::STATUS_SHIPMENT_READY, 'shipment_date' => $request->shipment_date, 'total_ctn' => $total_ctn, @@ -135,29 +149,35 @@ class ShipmentController extends Controller * Update Shipment status from action button */ public function updateStatus(Request $request) - { - $request->validate([ - 'shipment_id' => 'required|exists:shipments,id', - 'status' => 'required|string' - ]); +{ + $request->validate([ + 'shipment_id' => 'required|exists:shipments,id', + 'status' => 'required|string' + ]); - // 1) Update shipment status - $shipment = Shipment::findOrFail($request->shipment_id); - $shipment->status = $request->status; - $shipment->save(); + $shipment = Shipment::findOrFail($request->shipment_id); + $shipment->status = $request->status; + $shipment->save(); - // 2) Update ALL related orders' status - foreach ($shipment->orders as $order) { - $order->status = $shipment->status; // status is string: pending, in_transit, dispatched, delivered - $order->save(); + // ✅ Sync shipment status to orders ONLY after shipment exists + foreach ($shipment->orders as $order) { + + // Prevent rollback or overwrite + if ($order->status === 'delivered') { + continue; } - return redirect()->back()->with( - 'success', - "Shipment status updated to {$shipment->statusLabel()} and related orders updated." - ); + $order->status = $shipment->status; + $order->save(); } + return redirect()->back()->with( + 'success', + "Shipment status updated to {$shipment->statusLabel()}." + ); +} + + /** * Update shipment details */ @@ -266,11 +286,23 @@ public function addOrders(Request $request, Shipment $shipment) 'order_ids' => 'required|array|min:1', ]); - // फक्त न वापरलेले orders घ्या $orders = Order::whereIn('id', $request->order_ids)->get(); foreach ($orders as $order) { - // pivot मध्ये insert + + if ($order->status === 'order_placed') { + return back()->with( + 'error', + "Order {$order->order_id} is not ready for shipment" + ); + } + + + // Prevent duplicates + if (ShipmentItem::where('order_id', $order->id)->exists()) { + continue; + } + ShipmentItem::create([ 'shipment_id' => $shipment->id, 'order_id' => $order->id, @@ -282,23 +314,25 @@ public function addOrders(Request $request, Shipment $shipment) ]); } - // totals + // Recalculate totals $orderIds = ShipmentItem::where('shipment_id', $shipment->id)->pluck('order_id'); $allOrders = Order::whereIn('id', $orderIds)->get(); - $shipment->total_ctn = $allOrders->sum('ctn'); - $shipment->total_qty = $allOrders->sum('qty'); - $shipment->total_ttl_qty = $allOrders->sum('ttl_qty'); - $shipment->total_cbm = $allOrders->sum('cbm'); - $shipment->total_ttl_cbm = $allOrders->sum('ttl_cbm'); - $shipment->total_kg = $allOrders->sum('kg'); - $shipment->total_ttl_kg = $allOrders->sum('ttl_kg'); - $shipment->total_amount = $allOrders->sum('ttl_amount'); - $shipment->save(); + $shipment->update([ + 'total_ctn' => $allOrders->sum('ctn'), + 'total_qty' => $allOrders->sum('qty'), + 'total_ttl_qty' => $allOrders->sum('ttl_qty'), + 'total_cbm' => $allOrders->sum('cbm'), + 'total_ttl_cbm' => $allOrders->sum('ttl_cbm'), + 'total_kg' => $allOrders->sum('kg'), + 'total_ttl_kg' => $allOrders->sum('ttl_kg'), + 'total_amount' => $allOrders->sum('ttl_amount'), + ]); return redirect() ->route('admin.shipments.dummy', $shipment->id) ->with('success', 'Orders added to shipment successfully.'); } + } \ No newline at end of file diff --git a/app/Http/Controllers/user/UserOrderController.php b/app/Http/Controllers/user/UserOrderController.php index d18f7ae..da77e68 100644 --- a/app/Http/Controllers/user/UserOrderController.php +++ b/app/Http/Controllers/user/UserOrderController.php @@ -289,6 +289,44 @@ public function invoiceDetails($invoice_id) ]); } +public function confirmOrder($order_id) +{ + $user = JWTAuth::parseToken()->authenticate(); + + if (! $user) { + return response()->json([ + 'success' => false, + 'message' => 'Unauthorized' + ], 401); + } + + $order = $user->orders() + ->where('order_id', $order_id) + ->first(); + + if (! $order) { + return response()->json([ + 'success' => false, + 'message' => 'Order not found' + ], 404); + } + + // 🚫 Only allow confirm from order_placed + if ($order->status !== 'order_placed') { + return response()->json([ + 'success' => false, + 'message' => 'Order cannot be confirmed' + ], 422); + } + + $order->status = 'order_confirmed'; + $order->save(); + + return response()->json([ + 'success' => true, + 'message' => 'Order confirmed successfully' + ]); +} diff --git a/app/Models/Order.php b/app/Models/Order.php index 029cf35..9362328 100644 --- a/app/Models/Order.php +++ b/app/Models/Order.php @@ -64,5 +64,25 @@ class Order extends Model } + const STATUS_LABELS = [ + 'order_placed' => 'Order Placed', + 'order_confirmed' => 'Order Confirmed', + 'supplier_warehouse' => 'Supplier Warehouse', + 'consolidate_warehouse'=> 'Consolidate Warehouse', + 'export_custom' => 'Export Custom', + 'international_transit'=> 'International Transit', + 'arrived_india' => 'Arrived at India', + 'import_custom' => 'Import Custom', + 'warehouse' => 'Warehouse', + 'domestic_distribution'=> 'Domestic Distribution', + 'out_for_delivery' => 'Out for Delivery', + 'delivered' => 'Delivered', + ]; + + public function getStatusLabelAttribute() + { + return self::STATUS_LABELS[$this->status] + ?? ucfirst(str_replace('_', ' ', $this->status)); + } } diff --git a/app/Models/Shipment.php b/app/Models/Shipment.php index 95bb5d5..3c5cacd 100644 --- a/app/Models/Shipment.php +++ b/app/Models/Shipment.php @@ -45,25 +45,6 @@ class Shipment extends Model return $this->belongsToMany(Order::class, 'shipment_items', 'shipment_id', 'order_id'); } - // --------------------------- - // STATUS CONSTANTS - // --------------------------- - - const STATUS_PENDING = 'pending'; - const STATUS_IN_TRANSIT = 'in_transit'; - const STATUS_DISPATCHED = 'dispatched'; - const STATUS_DELIVERED = 'delivered'; - - public static function statusOptions() - { - return [ - self::STATUS_PENDING => 'Pending', - self::STATUS_IN_TRANSIT => 'In Transit', - self::STATUS_DISPATCHED => 'Dispatched', - self::STATUS_DELIVERED => 'Delivered', - ]; - } - // --------------------------- // HELPERS // --------------------------- @@ -73,8 +54,38 @@ class Shipment extends Model return $this->items()->count(); } + // --------------------------- + // STATUS CONSTANTS (LOGISTICS FLOW) + // --------------------------- + const STATUS_SHIPMENT_READY = 'shipment_ready'; + const STATUS_EXPORT_CUSTOM = 'export_custom'; + const STATUS_INTERNATIONAL_TRANSIT= 'international_transit'; + const STATUS_ARRIVED_INDIA = 'arrived_india'; + const STATUS_IMPORT_CUSTOM = 'import_custom'; + const STATUS_WAREHOUSE = 'warehouse'; + const STATUS_DOMESTIC_DISTRIBUTION= 'domestic_distribution'; + const STATUS_OUT_FOR_DELIVERY = 'out_for_delivery'; + const STATUS_DELIVERED = 'delivered'; + + public static function statusOptions() + { + return [ + self::STATUS_SHIPMENT_READY => 'Shipment Ready', + self::STATUS_EXPORT_CUSTOM => 'Export Custom', + self::STATUS_INTERNATIONAL_TRANSIT => 'International Transit', + self::STATUS_ARRIVED_INDIA => 'Arrived at India', + self::STATUS_IMPORT_CUSTOM => 'Import Custom', + self::STATUS_WAREHOUSE => 'Warehouse', + self::STATUS_DOMESTIC_DISTRIBUTION => 'Domestic Distribution', + self::STATUS_OUT_FOR_DELIVERY => 'Out for Delivery', + self::STATUS_DELIVERED => 'Delivered', + ]; + } + public function statusLabel() { - return self::statusOptions()[$this->status] ?? ucfirst($this->status); + return self::statusOptions()[$this->status] + ?? ucfirst(str_replace('_', ' ', $this->status)); } + } diff --git a/resources/views/admin/dashboard.blade.php b/resources/views/admin/dashboard.blade.php index 260c7f0..11fd2ea 100644 --- a/resources/views/admin/dashboard.blade.php +++ b/resources/views/admin/dashboard.blade.php @@ -1253,19 +1253,49 @@ body, .container-fluid { {{ $order->kg }} {{ $order->ttl_kg }} - - @if($order->status == 'pending') - - @elseif($order->status == 'in_transit') - - @elseif($order->status == 'dispatched') - - @elseif($order->status == 'delivered') - - @endif - {{ ucfirst(str_replace('_', ' ', $order->status)) }} + @php + // Badge color mapping + $badgeMap = [ + 'order_placed' => 'secondary', + 'order_confirmed' => 'info', + 'supplier_warehouse' => 'warning', + 'consolidate_warehouse' => 'warning', + 'export_custom' => 'primary', + 'international_transit' => 'primary', + 'arrived_india' => 'info', + 'import_custom' => 'info', + 'warehouse' => 'dark', + 'domestic_distribution' => 'primary', + 'out_for_delivery' => 'success', + 'delivered' => 'success', + ]; + + // Icon mapping + $iconMap = [ + 'order_placed' => 'bi-clock-fill', + 'order_confirmed' => 'bi-check-circle', + 'supplier_warehouse' => 'bi-box-seam', + 'consolidate_warehouse' => 'bi-boxes', + 'export_custom' => 'bi-upload', + 'international_transit' => 'bi-truck', + 'arrived_india' => 'bi-geo-alt', + 'import_custom' => 'bi-download', + 'warehouse' => 'bi-building', + 'domestic_distribution' => 'bi-diagram-3', + 'out_for_delivery' => 'bi-truck-flatbed', + 'delivered' => 'bi-check-circle-fill', + ]; + + $badgeClass = $badgeMap[$order->status] ?? 'secondary'; + $iconClass = $iconMap[$order->status] ?? 'bi-info-circle'; + @endphp + + + + {{ $order->status_label }} - + + {{ $order->created_at->format('d-m-Y') }} diff --git a/resources/views/admin/shipments.blade.php b/resources/views/admin/shipments.blade.php index 2d8be18..0f8d6bf 100644 --- a/resources/views/admin/shipments.blade.php +++ b/resources/views/admin/shipments.blade.php @@ -1093,11 +1093,16 @@
- - - - + + + + + + + + + + @@ -1716,38 +1737,68 @@ function renderTable() { -
- -
-
- - - - - - - -
-
-
- +
+ + +
+
+ + + + + + + + + + + + + + + + + + + + +
+
+
+ + `; tbody.appendChild(row); }); diff --git a/routes/api.php b/routes/api.php index 8cb2ed3..666bbd0 100644 --- a/routes/api.php +++ b/routes/api.php @@ -38,6 +38,7 @@ Route::middleware(['auth:api'])->group(function () { Route::get('/user/order/{order_id}/shipment', [UserOrderController::class, 'orderShipment']); Route::get('/user/order/{order_id}/invoice', [UserOrderController::class, 'orderInvoice']); Route::get('/user/order/{order_id}/track', [UserOrderController::class, 'trackOrder']); + Route::post('/user/orders/{order_id}/confirm', [UserOrderController::class, 'confirmOrder']); // Invoice List