count(); $totalShipments = Shipment::count(); $totalItems = OrderItem::count(); $totalRevenue = Invoice::sum('final_amount_with_gst'); $activeCustomers = User::where('status', 'active')->count(); $inactiveCustomers = User::where('status', 'inactive')->count(); $totalStaff = Admin::where('type', 'staff')->count(); $markList = MarkList::where('status', 'active')->get(); $orders = Order::latest()->get(); return view('admin.dashboard', compact( 'totalOrders', 'pendingOrders', 'totalShipments', 'totalItems', 'totalRevenue', 'activeCustomers', 'inactiveCustomers', 'totalStaff', 'orders', 'markList' )); } /* --------------------------- * LIST (new: Invoices Management for Orders page) * ---------------------------*/ public function index(Request $request) { $invoices = DB::table('invoices') ->leftJoin('containers', 'containers.id', '=', 'invoices.container_id') ->leftJoin('mark_list', 'mark_list.mark_no', '=', 'invoices.mark_no') ->select( 'invoices.id', 'invoices.invoice_number', 'invoices.invoice_date', 'invoices.final_amount', 'invoices.final_amount_with_gst', 'invoices.status as invoice_status', 'invoices.mark_no', 'invoices.container_id', // <<< हे नक्की घाल 'containers.container_number', 'containers.container_date', DB::raw('COALESCE(invoices.company_name, mark_list.company_name) as company_name'), DB::raw('COALESCE(invoices.customer_name, mark_list.customer_name) as customer_name') ) ->when($request->filled('search'), function ($q) use ($request) { $search = trim($request->search); $q->where(function ($qq) use ($search) { $qq->where('invoices.invoice_number', 'like', "%{$search}%") ->orWhere('containers.container_number', 'like', "%{$search}%") ->orWhere('invoices.mark_no', 'like', "%{$search}%") ->orWhere('mark_list.company_name', 'like', "%{$search}%") ->orWhere('mark_list.customer_name', 'like', "%{$search}%"); }); }) ->when($request->filled('status'), function ($q) use ($request) { $q->where('invoices.status', $request->status); }) ->orderByDesc('invoices.invoice_date') // इथे बदल ->orderByDesc('invoices.id') // same-date साठी tie-breaker ->get(); return view('admin.orders', compact('invoices')); } /* --------------------------- * CREATE NEW ORDER (simple page) * ---------------------------*/ public function create() { $markList = MarkList::where('status', 'active')->get(); return view('admin.orders_create', compact('markList')); } /* --------------------------- * SHOW / POPUP * ---------------------------*/ public function show($id) { $order = Order::with('items', 'markList')->findOrFail($id); $user = $this->getCustomerFromOrder($order); return view('admin.orders_show', compact('order', 'user')); } public function popup($id) { $order = Order::with(['items', 'markList'])->findOrFail($id); $user = null; if ($order->markList && $order->markList->customer_id) { $user = User::where('customer_id', $order->markList->customer_id)->first(); } return view('admin.popup', compact('order', 'user')); } /* --------------------------- * ORDER ITEM MANAGEMENT (existing orders) * ---------------------------*/ public function addItem(Request $request, $orderId) { $order = Order::findOrFail($orderId); $data = $request->validate([ 'description' => 'required|string', 'ctn' => 'nullable|numeric', 'qty' => 'nullable|numeric', 'unit' => 'nullable|string', 'price' => 'nullable|numeric', 'cbm' => 'nullable|numeric', 'kg' => 'nullable|numeric', 'shop_no' => 'nullable|string', ]); $ctn = (float) ($data['ctn'] ?? 0); $qty = (float) ($data['qty'] ?? 0); $price = (float) ($data['price'] ?? 0); $cbm = (float) ($data['cbm'] ?? 0); $kg = (float) ($data['kg'] ?? 0); $data['ttl_qty'] = $ctn * $qty; $data['ttl_amount'] = $data['ttl_qty'] * $price; $data['ttl_cbm'] = $cbm * $ctn; $data['ttl_kg'] = $ctn * $kg; $data['order_id'] = $order->id; OrderItem::create($data); $this->recalcTotals($order); return redirect()->back()->with('success', 'Item added and totals updated.'); } public function deleteItem($id) { $item = OrderItem::findOrFail($id); $order = $item->order; $item->delete(); $this->recalcTotals($order); return redirect()->back()->with('success', 'Item deleted and totals updated.'); } public function restoreItem($id) { $item = OrderItem::withTrashed()->findOrFail($id); $order = Order::findOrFail($item->order_id); $item->restore(); $this->recalcTotals($order); return redirect()->back()->with('success', 'Item restored and totals updated.'); } /* --------------------------- * ORDER CRUD: update / destroy * ---------------------------*/ public function update(Request $request, $id) { $order = Order::findOrFail($id); $data = $request->validate([ 'mark_no' => 'required|string', 'origin' => 'nullable|string', 'destination' => 'nullable|string', ]); $order->update([ 'mark_no' => $data['mark_no'], 'origin' => $data['origin'] ?? null, 'destination' => $data['destination'] ?? null, ]); $this->recalcTotals($order); return redirect()->route('admin.orders.show', $order->id) ->with('success', 'Order updated successfully.'); } public function destroy($id) { $order = Order::findOrFail($id); OrderItem::where('order_id', $order->id)->delete(); $order->delete(); return redirect()->route('admin.orders.index') ->with('success', 'Order deleted successfully.'); } /* --------------------------- * HELPERS * ---------------------------*/ private function recalcTotals(Order $order) { $items = $order->items()->get(); $order->update([ 'ctn' => (int) $items->sum(fn($i) => (int) ($i->ctn ?? 0)), 'qty' => (int) $items->sum(fn($i) => (int) ($i->qty ?? 0)), 'ttl_qty' => (int) $items->sum(fn($i) => (int) ($i->ttl_qty ?? 0)), 'ttl_amount'=> (float) $items->sum(fn($i) => (float) ($i->ttl_amount ?? 0)), 'cbm' => (float) $items->sum(fn($i) => (float) ($i->cbm ?? 0)), 'ttl_cbm' => (float) $items->sum(fn($i) => (float) ($i->ttl_cbm ?? 0)), 'kg' => (float) $items->sum(fn($i) => (float) ($i->kg ?? 0)), 'ttl_kg' => (float) $items->sum(fn($i) => (float) ($i->ttl_kg ?? 0)), ]); } private function generateOrderId() { $year = date('y'); $prefix = "KNT-$year-"; $lastOrder = Order::latest('id')->first(); $nextNumber = $lastOrder ? intval(substr($lastOrder->order_id, -8)) + 1 : 1; return $prefix . str_pad($nextNumber, 8, '0', STR_PAD_LEFT); } /* --------------------------- * INVOICE CREATION HELPERS * ---------------------------*/ private function createInvoice(Order $order) { $invoiceNumber = $this->generateInvoiceNumber(); $customer = $this->getCustomerFromMarkList($order->mark_no); $totalAmount = $order->ttl_amount; $invoice = Invoice::create([ 'order_id' => $order->id, 'customer_id' => $customer->id ?? null, 'mark_no' => $order->mark_no, 'invoice_number' => $invoiceNumber, 'invoice_date' => now(), 'due_date' => now()->addDays(10), 'payment_method' => null, 'reference_no' => null, 'status' => 'pending', 'final_amount' => $totalAmount, 'gst_percent' => 0, 'gst_amount' => 0, 'final_amount_with_gst' => $totalAmount, 'customer_name' => $customer->customer_name ?? null, 'company_name' => $customer->company_name ?? null, 'customer_email' => $customer->email ?? null, 'customer_mobile' => $customer->mobile_no ?? null, 'customer_address' => $customer->address ?? null, 'pincode' => $customer->pincode ?? null, 'notes' => null, 'pdf_path' => null, ]); foreach ($order->items as $item) { InvoiceItem::create([ 'invoice_id' => $invoice->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, ]); } } private function generateInvoiceNumber() { $lastInvoice = Invoice::latest()->first(); $nextInvoice = $lastInvoice ? $lastInvoice->id + 1 : 1; return 'INV-' . date('Y') . '-' . str_pad($nextInvoice, 6, '0', STR_PAD_LEFT); } private function getCustomerFromMarkList($markNo) { $markList = MarkList::where('mark_no', $markNo)->first(); if ($markList && $markList->customer_id) { return User::where('customer_id', $markList->customer_id)->first(); } return null; } private function getCustomerFromOrder($order) { if ($order->markList && $order->markList->customer_id) { return User::where('customer_id', $order->markList->customer_id)->first(); } return null; } /* --------------------------- * SEE (detailed) * ---------------------------*/ public function see($id) { $order = Order::with([ 'markList', 'items', 'shipments' => function ($q) use ($id) { $q->whereHas('orders', function ($oq) use ($id) { $oq->where('orders.id', $id) ->whereNull('orders.deleted_at'); })->with([ 'orders' => function ($oq) use ($id) { $oq->where('orders.id', $id) ->whereNull('orders.deleted_at') ->with('items'); } ]); } ])->findOrFail($id); $orderData = [ 'order_id' => $order->order_id, 'status' => $order->status, 'totals' => [ 'ctn' => $order->ctn, 'qty' => $order->qty, 'ttl_qty' => $order->ttl_qty, 'cbm' => $order->cbm, 'ttl_cbm' => $order->ttl_cbm, 'kg' => $order->kg, 'ttl_kg' => $order->ttl_kg, 'amount' => $order->ttl_amount, ], 'items' => $order->items, ]; $shipmentsData = []; foreach ($order->shipments as $shipment) { $shipmentOrders = []; $totals = [ 'ctn' => 0, 'qty' => 0, 'ttl_qty' => 0, 'cbm' => 0, 'ttl_cbm' => 0, 'kg' => 0, 'ttl_kg' => 0, 'amount' => 0, ]; foreach ($shipment->orders as $shipOrder) { foreach ($shipOrder->items as $item) { $shipmentOrders[] = [ 'order_id' => $shipOrder->order_id, 'origin' => $shipOrder->origin, 'destination' => $shipOrder->destination, 'description' => $item->description, 'ctn' => $item->ctn, 'qty' => $item->qty, 'ttl_qty' => $item->ttl_qty, 'amount' => $item->ttl_amount, ]; $totals['ctn'] += $item->ctn; $totals['qty'] += $item->qty; $totals['ttl_qty'] += $item->ttl_qty; $totals['cbm'] += $item->cbm; $totals['ttl_cbm'] += $item->ttl_cbm; $totals['kg'] += $item->kg; $totals['ttl_kg'] += $item->ttl_kg; $totals['amount'] += $item->ttl_amount; } } if (empty($shipmentOrders)) { continue; } $shipmentsData[] = [ 'shipment_id' => $shipment->shipment_id, 'status' => $shipment->status, 'date' => $shipment->shipment_date, 'total_orders' => 1, 'orders' => $shipmentOrders, 'totals' => $totals, ]; } $invoiceData = null; return view('admin.see_order', compact( 'order', 'orderData', 'shipmentsData', 'invoiceData' )); } /* --------------------------- * FILTERED LIST + EXPORTS (old orders listing) * ---------------------------*/ public function orderShow() { $orders = Order::with([ 'markList', 'shipments', ])->latest('id')->get(); return view('admin.orders', compact('orders')); } private function buildOrdersQueryFromRequest(Request $request) { $query = Order::query() ->with(['markList', 'shipments']); if ($request->filled('search')) { $search = trim($request->search); $query->where(function ($q) use ($search) { $q->where('orders.order_id', 'like', "%{$search}%") ->orWhereHas('markList', function ($q2) use ($search) { $q2->where('company_name', 'like', "%{$search}%") ->orWhere('customer_id', 'like', "%{$search}%") ->orWhere('origin', 'like', "%{$search}%") ->orWhere('destination', 'like', "%{$search}%"); }) ->orWhereHas('shipments', function ($q4) use ($search) { $q4->where('shipments.shipment_id', 'like', "%{$search}%"); }); }); } if ($request->filled('shipment')) { $query->where(function ($q) use ($request) { $q->whereHas('shipments', function ($q2) use ($request) { $q2->where('status', $request->shipment); })->orWhereDoesntHave('shipments'); }); } if ($request->filled('from_date')) { $query->whereDate('orders.created_at', '>=', $request->from_date); } if ($request->filled('to_date')) { $query->whereDate('orders.created_at', '<=', $request->to_date); } return $query->latest('orders.id'); } public function downloadPdf(Request $request) { $invoices = DB::table('invoices') ->leftJoin('containers', 'containers.id', '=', 'invoices.container_id') ->leftJoin('mark_list', 'mark_list.mark_no', '=', 'invoices.mark_no') ->select( 'invoices.invoice_number', 'invoices.invoice_date', 'invoices.mark_no', 'containers.container_number', 'containers.container_date', DB::raw('COALESCE(invoices.company_name, mark_list.company_name) as company_name'), DB::raw('COALESCE(invoices.customer_name, mark_list.customer_name) as customer_name'), 'invoices.final_amount', 'invoices.final_amount_with_gst', 'invoices.status as invoice_status' ) ->when($request->filled('search'), function ($q) use ($request) { $search = trim($request->search); $q->where(function ($qq) use ($search) { $qq->where('invoices.invoice_number', 'like', "%{$search}%") ->orWhere('invoices.mark_no', 'like', "%{$search}%") ->orWhere('containers.container_number', 'like', "%{$search}%") ->orWhere('mark_list.company_name', 'like', "%{$search}%") ->orWhere('mark_list.customer_name', 'like', "%{$search}%"); }); }) ->when($request->filled('status'), function ($q) use ($request) { $q->where('invoices.status', $request->status); }) ->when($request->filled('from_date'), function ($q) use ($request) { $q->whereDate('invoices.invoice_date', '>=', $request->from_date); }) ->when($request->filled('to_date'), function ($q) use ($request) { $q->whereDate('invoices.invoice_date', '<=', $request->to_date); }) ->orderByDesc('containers.container_date') ->orderByDesc('invoices.id') ->get(); $pdf = PDF::loadView('admin.pdf.invoices_report', compact('invoices')) ->setPaper('a4', 'landscape'); return $pdf->download( 'invoices-report-' . now()->format('Y-m-d') . '.pdf' ); } public function downloadExcel(Request $request) { return Excel::download( new InvoicesExport($request), 'invoices-report-' . now()->format('Y-m-d') . '.xlsx' ); } /* -------------------------------------------------- * NEW: Create Order + Invoice directly from popup * --------------------------------------------------*/ public function addTempItem(Request $request) { $request->validate([ 'mark_no' => 'required', 'origin' => 'nullable', 'destination' => 'nullable', ]); $items = $request->validate([ 'items' => 'required|array', 'items.*.description' => 'required|string', 'items.*.ctn' => 'nullable|numeric', 'items.*.qty' => 'nullable|numeric', 'items.*.unit' => 'nullable|string', 'items.*.price' => 'nullable|numeric', 'items.*.cbm' => 'nullable|numeric', 'items.*.kg' => 'nullable|numeric', 'items.*.shop_no' => 'nullable|string', ])['items']; $items = array_filter($items, function ($row) { return trim($row['description'] ?? '') !== ''; }); if (empty($items)) { return back()->with('error', 'Add at least one item.'); } foreach ($items as &$item) { $ctn = (float) ($item['ctn'] ?? 0); $qty = (float) ($item['qty'] ?? 0); $price = (float) ($item['price'] ?? 0); $cbm = (float) ($item['cbm'] ?? 0); $kg = (float) ($item['kg'] ?? 0); $item['ttl_qty'] = $ctn * $qty; $item['ttl_amount'] = $item['ttl_qty'] * $price; $item['ttl_cbm'] = $cbm * $ctn; $item['ttl_kg'] = $ctn * $kg; } unset($item); $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')); $orderId = $this->generateOrderId(); $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' => 'order_placed', ]); 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'], ]); } $invoiceNumber = $this->generateInvoiceNumber(); $markList = MarkList::where('mark_no', $order->mark_no)->first(); $customer = null; if ($markList && $markList->customer_id) { $customer = User::where('customer_id', $markList->customer_id)->first(); } $invoice = Invoice::create([ 'order_id' => $order->id, 'customer_id' => $customer->id ?? null, 'mark_no' => $order->mark_no, 'invoice_number' => $invoiceNumber, 'invoice_date' => now(), 'due_date' => now()->addDays(10), 'payment_method' => null, 'reference_no' => null, 'status' => 'pending', 'final_amount' => $total_amount, 'gst_percent' => 0, 'gst_amount' => 0, 'final_amount_with_gst' => $total_amount, 'customer_name' => $customer->customer_name ?? null, 'company_name' => $customer->company_name ?? null, 'customer_email' => $customer->email ?? null, 'customer_mobile' => $customer->mobile_no ?? null, 'customer_address' => $customer->address ?? null, 'pincode' => $customer->pincode ?? null, 'notes' => null, 'pdf_path' => null, ]); foreach ($order->items as $item) { InvoiceItem::create([ 'invoice_id' => $invoice->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, ]); } return redirect()->route('admin.orders.index') ->with('success', 'Order + Invoice created successfully.'); } /* --------------------------- * UPDATE ORDER ITEM (existing orders) * ---------------------------*/ public function updateItem(Request $request, $id) { $item = OrderItem::findOrFail($id); $order = $item->order; $request->validate([ 'description' => 'required|string', 'ctn' => 'nullable|numeric', 'qty' => 'nullable|numeric', 'unit' => 'nullable|string', 'price' => 'nullable|numeric', 'cbm' => 'nullable|numeric', 'kg' => 'nullable|numeric', 'shop_no' => 'nullable|string', ]); $ctn = (float) ($request->ctn ?? 0); $qty = (float) ($request->qty ?? 0); $price = (float) ($request->price ?? 0); $cbm = (float) ($request->cbm ?? 0); $kg = (float) ($request->kg ?? 0); $item->update([ 'description' => $request->description, 'ctn' => $ctn, 'qty' => $qty, 'ttl_qty' => $ctn * $qty, 'unit' => $request->unit, 'price' => $price, 'ttl_amount' => ($ctn * $qty) * $price, 'cbm' => $cbm, 'ttl_cbm' => $cbm * $ctn, 'kg' => $kg, 'ttl_kg' => $ctn * $kg, 'shop_no' => $request->shop_no, ]); $this->recalcTotals($order); return back()->with('success', 'Item updated successfully'); } public function uploadExcelPreview(Request $request) { try { $request->validate([ 'excel' => 'required|file|mimes:xlsx,xls' ]); $import = new OrderItemsPreviewImport(); Excel::import($import, $request->file('excel')); return response()->json([ 'success' => true, 'items' => $import->rows ]); } catch (ValidationException $e) { return response()->json([ 'success' => false, 'message' => 'Invalid Excel file format' ], 422); } catch (\Throwable $e) { \Log::error($e); return response()->json([ 'success' => false, 'message' => 'Server error' ], 500); } } }