changes of invoice and shipment
This commit is contained in:
@@ -10,61 +10,38 @@ use App\Models\MarkList;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\InvoiceItem;
|
||||
use App\Models\User;
|
||||
use PDF; // barryvdh/laravel-dompdf facade
|
||||
use PDF;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
use App\Exports\OrdersExport;
|
||||
|
||||
|
||||
class AdminOrderController extends Controller
|
||||
{
|
||||
// ---------------------------
|
||||
// LIST / DASHBOARD
|
||||
// ---------------------------
|
||||
/* ---------------------------
|
||||
* LIST / DASHBOARD
|
||||
* ---------------------------*/
|
||||
public function index()
|
||||
{
|
||||
// raw list for admin dashboard (simple)
|
||||
$orders = Order::latest()->get();
|
||||
$markList = MarkList::where('status', 'active')->get();
|
||||
|
||||
return view('admin.dashboard', compact('orders', 'markList'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Orders list (detailed)
|
||||
*/
|
||||
// public function orderShow()
|
||||
// {
|
||||
// $orders = Order::with(['markList', 'shipments', 'invoice'])
|
||||
// ->latest('id')
|
||||
// ->get();
|
||||
|
||||
// return view('admin.orders', compact('orders'));
|
||||
// }
|
||||
|
||||
// ---------------------------
|
||||
// CREATE NEW ORDER (simple DB flow)
|
||||
// ---------------------------
|
||||
/**
|
||||
* Show create form (you can place create UI on separate view or dashboard)
|
||||
*/
|
||||
/* ---------------------------
|
||||
* CREATE NEW ORDER (simple page)
|
||||
* ---------------------------*/
|
||||
public function create()
|
||||
{
|
||||
// return a dedicated create view - create it at resources/views/admin/orders_create.blade.php
|
||||
// If you prefer create UI on dashboard, change this to redirect route('admin.orders.index') etc.
|
||||
$markList = MarkList::where('status', 'active')->get();
|
||||
return view('admin.orders_create', compact('markList'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a new order and optionally create initial invoice
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$data = $request->validate([
|
||||
'mark_no' => 'required|string',
|
||||
'origin' => 'nullable|string',
|
||||
'destination' => 'nullable|string',
|
||||
// totals optional when creating without items
|
||||
'ctn' => 'nullable|numeric',
|
||||
'qty' => 'nullable|numeric',
|
||||
'ttl_qty' => 'nullable|numeric',
|
||||
@@ -91,16 +68,15 @@ class AdminOrderController extends Controller
|
||||
'status' => 'pending',
|
||||
]);
|
||||
|
||||
//If you want to auto-create an invoice at order creation, uncomment:
|
||||
$this->createInvoice($order);
|
||||
|
||||
return redirect()->route('admin.orders.show', $order->id)
|
||||
->with('success', 'Order created successfully.');
|
||||
}
|
||||
|
||||
// ---------------------------
|
||||
// SHOW / POPUP
|
||||
// ---------------------------
|
||||
/* ---------------------------
|
||||
* SHOW / POPUP
|
||||
* ---------------------------*/
|
||||
public function show($id)
|
||||
{
|
||||
$order = Order::with('items', 'markList')->findOrFail($id);
|
||||
@@ -109,20 +85,21 @@ class AdminOrderController extends Controller
|
||||
return view('admin.orders_show', compact('order', 'user'));
|
||||
}
|
||||
|
||||
// public function popup($id)
|
||||
// {
|
||||
// $order = Order::with(['items', 'markList'])->findOrFail($id);
|
||||
// $user = $this->getCustomerFromOrder($order);
|
||||
public function popup($id)
|
||||
{
|
||||
$order = Order::with(['items', 'markList'])->findOrFail($id);
|
||||
|
||||
// return view('admin.popup', compact('order', 'user'));
|
||||
// }
|
||||
$user = null;
|
||||
if ($order->markList && $order->markList->customer_id) {
|
||||
$user = User::where('customer_id', $order->markList->customer_id)->first();
|
||||
}
|
||||
|
||||
// ---------------------------
|
||||
// ORDER ITEM MANAGEMENT (DB)
|
||||
// ---------------------------
|
||||
/**
|
||||
* Add an item to an existing order
|
||||
*/
|
||||
return view('admin.popup', compact('order', 'user'));
|
||||
}
|
||||
|
||||
/* ---------------------------
|
||||
* ORDER ITEM MANAGEMENT (existing orders)
|
||||
* ---------------------------*/
|
||||
public function addItem(Request $request, $orderId)
|
||||
{
|
||||
$order = Order::findOrFail($orderId);
|
||||
@@ -146,34 +123,25 @@ class AdminOrderController extends Controller
|
||||
|
||||
OrderItem::create($data);
|
||||
|
||||
// recalc totals and save to order
|
||||
$this->recalcTotals($order);
|
||||
$this->updateInvoiceFromOrder($order); // <-- NEW
|
||||
$this->updateInvoiceFromOrder($order);
|
||||
|
||||
return redirect()->back()->with('success', 'Item added and totals updated.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Soft-delete an order item and recalc totals
|
||||
*/
|
||||
public function deleteItem($id)
|
||||
{
|
||||
$item = OrderItem::findOrFail($id);
|
||||
$order = $item->order;
|
||||
|
||||
$item->delete(); // soft delete
|
||||
$item->delete();
|
||||
|
||||
// recalc totals
|
||||
$this->recalcTotals($order);
|
||||
$this->updateInvoiceFromOrder($order);
|
||||
|
||||
|
||||
return redirect()->back()->with('success', 'Item deleted and totals updated.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore soft-deleted item and recalc totals
|
||||
*/
|
||||
public function restoreItem($id)
|
||||
{
|
||||
$item = OrderItem::withTrashed()->findOrFail($id);
|
||||
@@ -181,17 +149,15 @@ class AdminOrderController extends Controller
|
||||
|
||||
$item->restore();
|
||||
|
||||
// recalc totals
|
||||
$this->recalcTotals($order);
|
||||
$this->updateInvoiceFromOrder($order);
|
||||
|
||||
|
||||
return redirect()->back()->with('success', 'Item restored and totals updated.');
|
||||
}
|
||||
|
||||
// ---------------------------
|
||||
// ORDER CRUD: update / destroy
|
||||
// ---------------------------
|
||||
/* ---------------------------
|
||||
* ORDER CRUD: update / destroy
|
||||
* ---------------------------*/
|
||||
public function update(Request $request, $id)
|
||||
{
|
||||
$order = Order::findOrFail($id);
|
||||
@@ -208,39 +174,28 @@ class AdminOrderController extends Controller
|
||||
'destination' => $data['destination'] ?? null,
|
||||
]);
|
||||
|
||||
// optionally recalc totals (not necessary unless you change item-level fields here)
|
||||
$this->recalcTotals($order);
|
||||
|
||||
return redirect()->route('admin.orders.show', $order->id)
|
||||
->with('success', 'Order updated successfully.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Soft-delete whole order and its items (soft-delete items first then order)
|
||||
*/
|
||||
public function destroy($id)
|
||||
{
|
||||
$order = Order::findOrFail($id);
|
||||
|
||||
// soft-delete items first (so they show up in onlyTrashed for restore)
|
||||
OrderItem::where('order_id', $order->id)->delete();
|
||||
|
||||
// then soft-delete order
|
||||
$order->delete();
|
||||
|
||||
return redirect()->route('admin.orders.index')
|
||||
->with('success', 'Order deleted successfully.');
|
||||
}
|
||||
|
||||
// ---------------------------
|
||||
// HELPERS
|
||||
// ---------------------------
|
||||
/**
|
||||
* Recalculate totals for the order from current (non-deleted) items
|
||||
*/
|
||||
/* ---------------------------
|
||||
* HELPERS
|
||||
* ---------------------------*/
|
||||
private function recalcTotals(Order $order)
|
||||
{
|
||||
// make sure we re-query live items (non-deleted)
|
||||
$items = $order->items()->get();
|
||||
|
||||
$order->update([
|
||||
@@ -255,9 +210,6 @@ class AdminOrderController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate order id (keeps old format)
|
||||
*/
|
||||
private function generateOrderId()
|
||||
{
|
||||
$year = date('y');
|
||||
@@ -269,9 +221,9 @@ class AdminOrderController extends Controller
|
||||
return $prefix . str_pad($nextNumber, 8, '0', STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
// ---------------------------
|
||||
// INVOICE CREATION (optional helper used by store/finish)
|
||||
// ---------------------------
|
||||
/* ---------------------------
|
||||
* INVOICE CREATION HELPERS
|
||||
* ---------------------------*/
|
||||
private function createInvoice(Order $order)
|
||||
{
|
||||
$invoiceNumber = $this->generateInvoiceNumber();
|
||||
@@ -302,7 +254,6 @@ class AdminOrderController extends Controller
|
||||
'pdf_path' => null,
|
||||
]);
|
||||
|
||||
// clone order items into invoice items
|
||||
foreach ($order->items as $item) {
|
||||
InvoiceItem::create([
|
||||
'invoice_id' => $invoice->id,
|
||||
@@ -350,21 +301,9 @@ class AdminOrderController extends Controller
|
||||
return null;
|
||||
}
|
||||
|
||||
public function popup($id)
|
||||
{
|
||||
// Load order with items + markList
|
||||
$order = Order::with(['items', 'markList'])->findOrFail($id);
|
||||
|
||||
// Fetch user based on markList customer_id (same as show method)
|
||||
$user = null;
|
||||
if ($order->markList && $order->markList->customer_id) {
|
||||
$user = \App\Models\User::where('customer_id', $order->markList->customer_id)->first();
|
||||
}
|
||||
|
||||
return view('admin.popup', compact('order', 'user'));
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------
|
||||
* SEE (detailed)
|
||||
* ---------------------------*/
|
||||
public function see($id)
|
||||
{
|
||||
$order = Order::with([
|
||||
@@ -385,7 +324,6 @@ class AdminOrderController extends Controller
|
||||
}
|
||||
])->findOrFail($id);
|
||||
|
||||
/* ---------------- ORDER DATA ---------------- */
|
||||
$orderData = [
|
||||
'order_id' => $order->order_id,
|
||||
'status' => $order->status,
|
||||
@@ -402,11 +340,8 @@ class AdminOrderController extends Controller
|
||||
'items' => $order->items,
|
||||
];
|
||||
|
||||
/* ---------------- SHIPMENTS DATA ---------------- */
|
||||
$shipmentsData = [];
|
||||
|
||||
foreach ($order->shipments as $shipment) {
|
||||
|
||||
$shipmentOrders = [];
|
||||
$totals = [
|
||||
'ctn' => 0, 'qty' => 0, 'ttl_qty' => 0,
|
||||
@@ -417,7 +352,6 @@ class AdminOrderController extends Controller
|
||||
|
||||
foreach ($shipment->orders as $shipOrder) {
|
||||
foreach ($shipOrder->items as $item) {
|
||||
|
||||
$shipmentOrders[] = [
|
||||
'order_id' => $shipOrder->order_id,
|
||||
'origin' => $shipOrder->origin,
|
||||
@@ -454,7 +388,6 @@ class AdminOrderController extends Controller
|
||||
];
|
||||
}
|
||||
|
||||
/* ---------------- INVOICE DATA ---------------- */
|
||||
$invoiceData = null;
|
||||
if ($order->invoice) {
|
||||
$invoice = $order->invoice;
|
||||
@@ -488,89 +421,61 @@ class AdminOrderController extends Controller
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
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.');
|
||||
}
|
||||
|
||||
/* ---------------------------
|
||||
* FILTERED LIST + EXPORTS
|
||||
* ---------------------------*/
|
||||
public function orderShow()
|
||||
{
|
||||
$orders = Order::with([
|
||||
'markList', // company, customer, origin, destination, date
|
||||
'shipments', // shipment_id, shipment_date, status
|
||||
'invoice' // invoice number, dates, amounts, status
|
||||
])
|
||||
->latest('id') // show latest orders first
|
||||
->get();
|
||||
'markList',
|
||||
'shipments',
|
||||
'invoice'
|
||||
])->latest('id')->get();
|
||||
|
||||
return view('admin.orders', compact('orders'));
|
||||
}
|
||||
|
||||
// inside AdminOrderController
|
||||
|
||||
private function buildOrdersQueryFromRequest(Request $request)
|
||||
{
|
||||
$query = Order::query()
|
||||
->with(['markList', 'invoice', 'shipments']);
|
||||
|
||||
/* ----------------------------------
|
||||
| SEARCH FILTER
|
||||
|----------------------------------*/
|
||||
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('invoice', function ($q3) use ($search) {
|
||||
$q3->where('invoice_number', 'like', "%{$search}%");
|
||||
})
|
||||
|
||||
->orWhereHas('shipments', function ($q4) use ($search) {
|
||||
// ✅ VERY IMPORTANT: table name added
|
||||
$q4->where('shipments.shipment_id', 'like', "%{$search}%");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/* ----------------------------------
|
||||
| INVOICE STATUS FILTER
|
||||
|----------------------------------*/
|
||||
if ($request->filled('status')) {
|
||||
$query->where(function ($q) use ($request) {
|
||||
$q->whereHas('invoice', function ($q2) use ($request) {
|
||||
$q2->where('status', $request->status);
|
||||
})
|
||||
->orWhereDoesntHave('invoice');
|
||||
})->orWhereDoesntHave('invoice');
|
||||
});
|
||||
}
|
||||
|
||||
/* ----------------------------------
|
||||
| SHIPMENT STATUS FILTER
|
||||
|----------------------------------*/
|
||||
if ($request->filled('shipment')) {
|
||||
$query->where(function ($q) use ($request) {
|
||||
$q->whereHas('shipments', function ($q2) use ($request) {
|
||||
$q2->where('status', $request->shipment);
|
||||
})
|
||||
->orWhereDoesntHave('shipments');
|
||||
})->orWhereDoesntHave('shipments');
|
||||
});
|
||||
}
|
||||
|
||||
/* ----------------------------------
|
||||
| DATE RANGE FILTER (🔥 FIXED)
|
||||
|----------------------------------*/
|
||||
if ($request->filled('from_date')) {
|
||||
$query->whereDate('orders.created_at', '>=', $request->from_date);
|
||||
}
|
||||
@@ -582,33 +487,9 @@ class AdminOrderController extends Controller
|
||||
return $query->latest('orders.id');
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public function downloadPdf(Request $request)
|
||||
{
|
||||
// Build same filtered query used for table
|
||||
// $query = $this->buildOrdersQueryFromRequest($request);
|
||||
|
||||
// $orders = $query->get();
|
||||
|
||||
// // optional: pass filters to view for header
|
||||
// $filters = [
|
||||
// 'search' => $request->search ?? null,
|
||||
// 'status' => $request->status ?? null,
|
||||
// 'shipment' => $request->shipment ?? null,
|
||||
// ];
|
||||
|
||||
// $pdf = PDF::loadView('admin.orders.pdf', compact('orders', 'filters'))
|
||||
// ->setPaper('a4', 'landscape'); // adjust if needed
|
||||
|
||||
// $fileName = 'orders-report'
|
||||
// . ($filters['status'] ? "-{$filters['status']}" : '')
|
||||
// . '-' . date('Y-m-d') . '.pdf';
|
||||
|
||||
// return $pdf->download($fileName);
|
||||
$orders = $this->buildOrdersQueryFromRequest($request)->get();
|
||||
|
||||
$filters = [
|
||||
'search' => $request->search,
|
||||
'status' => $request->status,
|
||||
@@ -627,97 +508,52 @@ class AdminOrderController extends Controller
|
||||
|
||||
public function downloadExcel(Request $request)
|
||||
{
|
||||
// pass request to OrdersExport which will build Filtered query internally
|
||||
// return Excel::download(new OrdersExport($request), 'orders-report-' . date('Y-m-d') . '.xlsx');
|
||||
return Excel::download(
|
||||
new OrdersExport($request),
|
||||
'orders-report-' . now()->format('Y-m-d') . '.xlsx'
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/* --------------------------------------------------
|
||||
* NEW: Create Order + Invoice directly from popup
|
||||
* route: admin.orders.temp.add (Create New Order form)
|
||||
* --------------------------------------------------*/
|
||||
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',
|
||||
]);
|
||||
|
||||
// ❌ 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.');
|
||||
}
|
||||
|
||||
// Save mark, origin, destination ONLY ONCE
|
||||
if (!session()->has('mark_no')) {
|
||||
session([
|
||||
'mark_no' => $request->mark_no,
|
||||
'origin' => $request->origin,
|
||||
'destination' => $request->destination
|
||||
]);
|
||||
}
|
||||
|
||||
// ❌ DO NOT overwrite these values again
|
||||
// session(['mark_no' => $request->mark_no]);
|
||||
// session(['origin' => $request->origin]);
|
||||
// session(['destination' => $request->destination]);
|
||||
|
||||
// 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 3 : FINISH ORDER
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
public function finishOrder(Request $request)
|
||||
{
|
||||
// 1) order-level fields
|
||||
$request->validate([
|
||||
'mark_no' => 'required',
|
||||
'origin' => 'required',
|
||||
'destination' => 'required',
|
||||
]);
|
||||
|
||||
$items = session('temp_order_items', []);
|
||||
// 2) multi-row items
|
||||
$items = $request->validate([
|
||||
'items' => 'required|array',
|
||||
'items.*.description' => 'required|string',
|
||||
'items.*.ctn' => 'nullable|numeric',
|
||||
'items.*.qty' => 'nullable|numeric',
|
||||
'items.*.ttl_qty' => 'nullable|numeric',
|
||||
'items.*.unit' => 'nullable|string',
|
||||
'items.*.price' => 'nullable|numeric',
|
||||
'items.*.ttl_amount' => 'nullable|numeric',
|
||||
'items.*.cbm' => 'nullable|numeric',
|
||||
'items.*.ttl_cbm' => 'nullable|numeric',
|
||||
'items.*.kg' => 'nullable|numeric',
|
||||
'items.*.ttl_kg' => 'nullable|numeric',
|
||||
'items.*.shop_no' => 'nullable|string',
|
||||
])['items'];
|
||||
|
||||
// रिकामे rows काढा
|
||||
$items = array_filter($items, function ($row) {
|
||||
return trim($row['description'] ?? '') !== '';
|
||||
});
|
||||
|
||||
if (empty($items)) {
|
||||
return redirect()->to(route('admin.orders.index') . '#createOrderForm')
|
||||
->with('error', 'Add at least one item before finishing.');
|
||||
return back()->with('error', 'Add at least one item.');
|
||||
}
|
||||
|
||||
// =======================
|
||||
// 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
|
||||
// =======================
|
||||
// 3) totals
|
||||
$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'));
|
||||
@@ -727,9 +563,10 @@ class AdminOrderController extends Controller
|
||||
$total_kg = array_sum(array_column($items, 'kg'));
|
||||
$total_ttl_kg = array_sum(array_column($items, 'ttl_kg'));
|
||||
|
||||
// =======================
|
||||
// CREATE ORDER
|
||||
// =======================
|
||||
// 4) order id generate
|
||||
$orderId = $this->generateOrderId();
|
||||
|
||||
// 5) order create
|
||||
$order = Order::create([
|
||||
'order_id' => $orderId,
|
||||
'mark_no' => $request->mark_no,
|
||||
@@ -746,7 +583,7 @@ class AdminOrderController extends Controller
|
||||
'status' => 'pending',
|
||||
]);
|
||||
|
||||
// SAVE ORDER ITEMS
|
||||
// 6) order items
|
||||
foreach ($items as $item) {
|
||||
OrderItem::create([
|
||||
'order_id' => $order->id,
|
||||
@@ -765,56 +602,44 @@ class AdminOrderController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
// =======================
|
||||
// INVOICE CREATION START
|
||||
// =======================
|
||||
// 7) invoice number
|
||||
$invoiceNumber = $this->generateInvoiceNumber();
|
||||
|
||||
// 1. Auto-generate invoice number
|
||||
$lastInvoice = \App\Models\Invoice::latest()->first();
|
||||
$nextInvoice = $lastInvoice ? $lastInvoice->id + 1 : 1;
|
||||
$invoiceNumber = 'INV-' . date('Y') . '-' . str_pad($nextInvoice, 6, '0', STR_PAD_LEFT);
|
||||
|
||||
// 2. Fetch customer (using mark list → customer_id)
|
||||
// 8) customer fetch
|
||||
$markList = MarkList::where('mark_no', $order->mark_no)->first();
|
||||
$customer = null;
|
||||
|
||||
if ($markList && $markList->customer_id) {
|
||||
$customer = \App\Models\User::where('customer_id', $markList->customer_id)->first();
|
||||
$customer = User::where('customer_id', $markList->customer_id)->first();
|
||||
}
|
||||
|
||||
// 3. Create Invoice Record
|
||||
$invoice = \App\Models\Invoice::create([
|
||||
// 9) invoice create
|
||||
$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,
|
||||
|
||||
// snapshot customer fields
|
||||
'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,
|
||||
]);
|
||||
|
||||
// 4. Clone order items into invoice_items
|
||||
// 10) invoice items
|
||||
foreach ($order->items as $item) {
|
||||
\App\Models\InvoiceItem::create([
|
||||
InvoiceItem::create([
|
||||
'invoice_id' => $invoice->id,
|
||||
'description' => $item->description,
|
||||
'ctn' => $item->ctn,
|
||||
@@ -831,24 +656,13 @@ class AdminOrderController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
// 5. TODO: PDF generation (I will add this later)
|
||||
$invoice->pdf_path = null; // placeholder for now
|
||||
$invoice->save();
|
||||
|
||||
// =======================
|
||||
// END INVOICE CREATION
|
||||
// =======================
|
||||
|
||||
// CLEAR TEMP DATA
|
||||
session()->forget(['temp_order_items', 'mark_no', 'origin', 'destination']);
|
||||
|
||||
return redirect()->route('admin.orders.index')
|
||||
->with('success', 'Order + Invoice created successfully.');
|
||||
}
|
||||
|
||||
// ---------------------------
|
||||
// ORDER CRUD: update / destroy
|
||||
// ---------------------------
|
||||
/* ---------------------------
|
||||
* UPDATE ORDER ITEM (existing orders)
|
||||
* ---------------------------*/
|
||||
public function updateItem(Request $request, $id)
|
||||
{
|
||||
$item = OrderItem::findOrFail($id);
|
||||
@@ -870,31 +684,27 @@ class AdminOrderController extends Controller
|
||||
]);
|
||||
|
||||
$this->recalcTotals($order);
|
||||
$this->updateInvoiceFromOrder($order); // <-- NEW
|
||||
$this->updateInvoiceFromOrder($order);
|
||||
|
||||
return back()->with('success', 'Item updated successfully');
|
||||
}
|
||||
|
||||
|
||||
private function updateInvoiceFromOrder(Order $order)
|
||||
{
|
||||
$invoice = Invoice::where('order_id', $order->id)->first();
|
||||
|
||||
if (!$invoice) {
|
||||
return; // No invoice exists (should not happen normally)
|
||||
return;
|
||||
}
|
||||
|
||||
// Update invoice totals
|
||||
$invoice->final_amount = $order->ttl_amount;
|
||||
$invoice->gst_percent = 0;
|
||||
$invoice->gst_amount = 0;
|
||||
$invoice->final_amount_with_gst = $order->ttl_amount;
|
||||
$invoice->save();
|
||||
|
||||
// Delete old invoice items
|
||||
InvoiceItem::where('invoice_id', $invoice->id)->delete();
|
||||
|
||||
// Re-create invoice items from updated order items
|
||||
foreach ($order->items as $item) {
|
||||
InvoiceItem::create([
|
||||
'invoice_id' => $invoice->id,
|
||||
@@ -913,5 +723,4 @@ class AdminOrderController extends Controller
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -261,7 +261,6 @@ body, .container-fluid {
|
||||
font-family: 'Inter', sans-serif;
|
||||
border-bottom: 2px solid #e9ecef;
|
||||
}
|
||||
|
||||
.table thead th:first-child { border-radius: 9px 0 0 0;}
|
||||
.table thead th:last-child { border-radius: 0 9px 0 0;}
|
||||
|
||||
@@ -466,45 +465,47 @@ body, .container-fluid {
|
||||
min-width: 2000px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
/* ===== CREATE ORDER MODAL STYLES ===== */
|
||||
.create-order-modal {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
width: 100vw; /* full screen */
|
||||
height: 100vh; /* full screen */
|
||||
background: #f8fafc; /* backdrop काढून direct page सारखा bg */
|
||||
display: none;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
justify-content: flex-start; /* top पासून सुरू कर */
|
||||
align-items: stretch; /* full height */
|
||||
z-index: 9999;
|
||||
overflow-y: auto; /* content scroll */
|
||||
}
|
||||
|
||||
/* JS madhun modal.classList.add('show') already aahe */
|
||||
.create-order-modal.show {
|
||||
display: flex;
|
||||
display: block; /* flex ऐवजी block => full page section सारखा */
|
||||
}
|
||||
|
||||
/* Card ला full-width/height सारखं कर */
|
||||
.create-order-modal .modal-card {
|
||||
background: #fff;
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 25px 50px rgba(0, 0, 0, 0.3);
|
||||
width: 95%;
|
||||
max-width: 900px;
|
||||
max-height: 90vh;
|
||||
overflow-y: auto;
|
||||
border-radius: 0; /* corner radius काढला => normal page feel */
|
||||
box-shadow: none; /* popup सारखा shadow काढला */
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
min-height: 100vh;
|
||||
max-height: none;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.create-order-modal .modal-header {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
padding: 20px 25px;
|
||||
border-radius: 16px 16px 0 0;
|
||||
border-radius: 0;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.create-order-modal .modal-title {
|
||||
font-size: 1.4rem;
|
||||
font-weight: 700;
|
||||
@@ -630,6 +631,13 @@ body, .container-fluid {
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
|
||||
/* items table inputs */
|
||||
.items-input {
|
||||
width: 100%;
|
||||
padding: 4px 6px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
/* ===== ORDER DETAILS MODAL STYLES ===== */
|
||||
.modal.fade .modal-dialog {
|
||||
transition: transform 0.3s ease-out;
|
||||
@@ -869,6 +877,27 @@ body, .container-fluid {
|
||||
.pagination-controls {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.create-order-modal .modal-card {
|
||||
width: 98%;
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.create-order-modal .modal-body {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.create-order-modal .modal-header {
|
||||
padding: 15px 20px;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
padding: 20px 15px;
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
padding: 10px 15px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Mobile Landscape (768px and below) */
|
||||
@@ -1131,7 +1160,6 @@ body, .container-fluid {
|
||||
break-inside: avoid;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<div class="container-fluid py-3">
|
||||
@@ -1169,7 +1197,6 @@ body, .container-fluid {
|
||||
@endcan
|
||||
|
||||
</div>
|
||||
|
||||
<div class="order-mgmt-main">
|
||||
<!-- RECENT ORDERS TABLE -->
|
||||
<div class="card shadow-sm">
|
||||
@@ -1348,22 +1375,35 @@ body, .container-fluid {
|
||||
|
||||
{{-- ITEM INPUTS --}}
|
||||
<h6 class="text-primary">Add Item</h6>
|
||||
<div class="row g-3">
|
||||
<div class="col-md-4">
|
||||
<label class="form-label">Description</label>
|
||||
<input type="text" class="form-control" name="description" id="itemDescription" required placeholder="Enter item description">
|
||||
|
||||
{{-- NEW ITEMS TABLE (INSTEAD OF SINGLE-ROW INPUTS) --}}
|
||||
<div class="table-wrapper mb-3">
|
||||
<table class="table table-bordered table-sm align-middle text-center" id="itemsTable">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Description</th>
|
||||
<th>CTN</th>
|
||||
<th>QTY</th>
|
||||
<th>TTL/QTY</th>
|
||||
<th>Unit</th>
|
||||
<th>Price</th>
|
||||
<th>TTL Amount</th>
|
||||
<th>CBM</th>
|
||||
<th>TTL CBM</th>
|
||||
<th>KG</th>
|
||||
<th>TTL KG</th>
|
||||
<th>Shop No</th>
|
||||
<th>Remove</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="itemsTableBody">
|
||||
{{-- JS will create default 2 blank rows --}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="col-md-2"><label class="form-label">CTN</label><input type="number" name="ctn" id="itemCtn" class="form-control" placeholder="CTN"></div>
|
||||
<div class="col-md-2"><label class="form-label">QTY</label><input type="number" name="qty" id="itemQty" class="form-control" placeholder="QTY"></div>
|
||||
<div class="col-md-2"><label class="form-label">TTL/QTY</label><input type="number" name="ttl_qty" id="itemTtlQty" class="form-control" placeholder="TTL/QTY"></div>
|
||||
<div class="col-md-2"><label class="form-label">Unit</label><input type="text" name="unit" id="itemUnit" class="form-control" placeholder="Unit"></div>
|
||||
<div class="col-md-2"><label class="form-label">Price</label><input type="number" step="0.01" name="price" id="itemPrice" class="form-control" placeholder="Price"></div>
|
||||
<div class="col-md-2"><label class="form-label">TTL Amount</label><input type="number" step="0.01" name="ttl_amount" id="itemTtlAmount" class="form-control" placeholder="TTL Amount"></div>
|
||||
<div class="col-md-2"><label class="form-label">CBM</label><input type="number" step="0.001" name="cbm" id="itemCbm" class="form-control" placeholder="CBM"></div>
|
||||
<div class="col-md-2"><label class="form-label">TTL CBM</label><input type="number" step="0.001" name="ttl_cbm" id="itemTtlCbm" class="form-control" placeholder="TTL CBM"></div>
|
||||
<div class="col-md-2"><label class="form-label">KG</label><input type="number" step="0.001" name="kg" id="itemKg" class="form-control" placeholder="KG"></div>
|
||||
<div class="col-md-2"><label class="form-label">TTL KG</label><input type="number" step="0.001" name="ttl_kg" id="itemTtlKg" class="form-control" placeholder="TTL KG"></div>
|
||||
<div class="col-md-3"><label class="form-label">Shop No</label><input type="text" name="shop_no" id="itemShopNo" class="form-control" placeholder="Shop No"></div>
|
||||
|
||||
<div class="row g-3">
|
||||
<div class="col-md-12 text-end mt-3">
|
||||
<button type="button" class="btn btn-secondary clear-form-btn" id="clearForm">
|
||||
<i class="bi bi-arrow-clockwise"></i> Clear Form
|
||||
@@ -1485,7 +1525,60 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
const ordersPerPage = 10;
|
||||
let allOrders = @json($orders->values());
|
||||
|
||||
// Initialize pagination
|
||||
// ------- ITEMS TABLE LOGIC (NEW) -------
|
||||
|
||||
const itemsTableBody = document.getElementById('itemsTableBody');
|
||||
|
||||
function addRow(index) {
|
||||
const tr = document.createElement('tr');
|
||||
tr.innerHTML = `
|
||||
<td class="align-middle fw-bold">${index + 1}</td>
|
||||
<td><input type="text" class="form-control form-control-sm items-input" name="items[${index}][description]" data-field="description"></td>
|
||||
<td><input type="number" class="form-control form-control-sm items-input" name="items[${index}][ctn]" data-field="ctn"></td>
|
||||
<td><input type="number" class="form-control form-control-sm items-input" name="items[${index}][qty]" data-field="qty"></td>
|
||||
<td><input type="number" class="form-control form-control-sm items-input" name="items[${index}][ttl_qty]" data-field="ttl_qty"></td>
|
||||
<td><input type="text" class="form-control form-control-sm items-input" name="items[${index}][unit]" data-field="unit"></td>
|
||||
<td><input type="number" class="form-control form-control-sm items-input" name="items[${index}][price]" data-field="price" step="0.01"></td>
|
||||
<td><input type="number" class="form-control form-control-sm items-input" name="items[${index}][ttl_amount]" data-field="ttl_amount" step="0.01"></td>
|
||||
<td><input type="number" class="form-control form-control-sm items-input" name="items[${index}][cbm]" data-field="cbm" step="0.001"></td>
|
||||
<td><input type="number" class="form-control form-control-sm items-input" name="items[${index}][ttl_cbm]" data-field="ttl_cbm" step="0.001"></td>
|
||||
<td><input type="number" class="form-control form-control-sm items-input" name="items[${index}][kg]" data-field="kg" step="0.001"></td>
|
||||
<td><input type="number" class="form-control form-control-sm items-input" name="items[${index}][ttl_kg]" data-field="ttl_kg" step="0.001"></td>
|
||||
<td><input type="text" class="form-control form-control-sm items-input" name="items[${index}][shop_no]" data-field="shop_no"></td>
|
||||
<td><button type="button" class="btn btn-sm btn-danger remove-row-btn">×</button></td>
|
||||
`;
|
||||
itemsTableBody.appendChild(tr);
|
||||
}
|
||||
|
||||
function generateDefaultRows() {
|
||||
itemsTableBody.innerHTML = '';
|
||||
addRow(0);
|
||||
addRow(1);
|
||||
focusFirstInput();
|
||||
}
|
||||
|
||||
function reindexRows() {
|
||||
const rows = itemsTableBody.querySelectorAll('tr');
|
||||
rows.forEach((tr, idx) => {
|
||||
tr.querySelector('td:first-child').textContent = idx + 1;
|
||||
tr.querySelectorAll('input').forEach(input => {
|
||||
const field = input.getAttribute('data-field');
|
||||
input.name = `items[${idx}][${field}]`;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function rowHasData(row) {
|
||||
const inputs = row.querySelectorAll('input');
|
||||
return Array.from(inputs).some(inp => inp.value.trim() !== '');
|
||||
}
|
||||
|
||||
function focusFirstInput() {
|
||||
const first = itemsTableBody.querySelector('tr:first-child input');
|
||||
if (first) first.focus();
|
||||
}
|
||||
|
||||
// ------- EXISTING PAGINATION INITIALIZE -------
|
||||
initializePagination();
|
||||
|
||||
// Reset temp data function
|
||||
@@ -1504,7 +1597,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
modal.classList.add('show');
|
||||
document.body.style.overflow = 'hidden';
|
||||
document.querySelector('.alert-success')?.remove();
|
||||
clearForm();
|
||||
generateDefaultRows();
|
||||
};
|
||||
|
||||
const closeModal = () => {
|
||||
@@ -1518,11 +1611,9 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
@endif
|
||||
};
|
||||
|
||||
// Clear form function
|
||||
// Clear form -> clear items table
|
||||
const clearForm = () => {
|
||||
['itemDescription','itemCtn','itemQty','itemTtlQty','itemUnit','itemPrice','itemTtlAmount','itemCbm','itemTtlCbm','itemKg','itemTtlKg','itemShopNo']
|
||||
.forEach(id => document.getElementById(id).value = '');
|
||||
document.getElementById('itemDescription').focus();
|
||||
generateDefaultRows();
|
||||
};
|
||||
|
||||
// Event listeners
|
||||
@@ -1533,7 +1624,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
modal.addEventListener('click', (e) => e.target === modal && closeModal());
|
||||
document.addEventListener('keydown', (e) => e.key === 'Escape' && modal.classList.contains('show') && closeModal());
|
||||
|
||||
// Mark No functionality
|
||||
// Mark No functionality (unchanged)
|
||||
const markNoSelect = document.getElementById('markNoSelect');
|
||||
if (markNoSelect) {
|
||||
markNoSelect.addEventListener('change', function() {
|
||||
@@ -1553,7 +1644,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
@if(session('temp_order_items') && count(session('temp_order_items')) > 0)
|
||||
modal.classList.add('show');
|
||||
document.body.style.overflow = 'hidden';
|
||||
clearForm();
|
||||
generateDefaultRows();
|
||||
@endif
|
||||
|
||||
// Reset confirmation
|
||||
@@ -1564,16 +1655,16 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
}
|
||||
}));
|
||||
|
||||
// Order details modal functionality
|
||||
// Order details modal functionality (unchanged)
|
||||
document.querySelectorAll('.open-order-modal').forEach(button => {
|
||||
button.addEventListener('click', function() {
|
||||
let id = this.dataset.id;
|
||||
let modal = new bootstrap.Modal(document.getElementById('orderDetailsModal'));
|
||||
let modalInstance = new bootstrap.Modal(document.getElementById('orderDetailsModal'));
|
||||
|
||||
document.getElementById('orderDetailsBody').innerHTML =
|
||||
"<p class='text-center text-muted'>Loading...</p>";
|
||||
|
||||
modal.show();
|
||||
modalInstance.show();
|
||||
|
||||
fetch(`/admin/orders/view/${id}`)
|
||||
.then(response => response.text())
|
||||
@@ -1587,12 +1678,11 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
});
|
||||
});
|
||||
|
||||
/* ---------- Pagination Functions ---------- */
|
||||
/* ---------- Pagination Functions (unchanged) ---------- */
|
||||
function initializePagination() {
|
||||
renderOrdersTable(allOrders);
|
||||
updatePaginationControls();
|
||||
|
||||
// Bind pagination buttons
|
||||
document.getElementById('prevPageBtn').addEventListener('click', goToPreviousPage);
|
||||
document.getElementById('nextPageBtn').addEventListener('click', goToNextPage);
|
||||
}
|
||||
@@ -1624,21 +1714,17 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
prevBtn.disabled = currentPage === 1;
|
||||
nextBtn.disabled = currentPage === totalPages || totalPages === 0;
|
||||
|
||||
// Update page info text
|
||||
const startIndex = (currentPage - 1) * ordersPerPage + 1;
|
||||
const endIndex = Math.min(currentPage * ordersPerPage, allOrders.length);
|
||||
pageInfo.textContent = `Showing ${startIndex} to ${endIndex} of ${allOrders.length} entries`;
|
||||
|
||||
// Generate page numbers
|
||||
paginationPages.innerHTML = '';
|
||||
|
||||
if (totalPages <= 7) {
|
||||
// Show all pages
|
||||
for (let i = 1; i <= totalPages; i++) {
|
||||
addPageButton(i, paginationPages);
|
||||
}
|
||||
} else {
|
||||
// Show first page, current page range, and last page
|
||||
addPageButton(1, paginationPages);
|
||||
|
||||
if (currentPage > 3) {
|
||||
@@ -1684,7 +1770,6 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate pagination
|
||||
const startIndex = (currentPage - 1) * ordersPerPage;
|
||||
const endIndex = startIndex + ordersPerPage;
|
||||
const paginatedOrders = orders.slice(startIndex, endIndex);
|
||||
@@ -1729,17 +1814,16 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
`;
|
||||
tbody.appendChild(tr);
|
||||
|
||||
// Re-bind order details modal for newly rendered rows
|
||||
const orderLink = tr.querySelector('.open-order-modal');
|
||||
if (orderLink) {
|
||||
orderLink.addEventListener('click', function() {
|
||||
let id = this.dataset.id;
|
||||
let modal = new bootstrap.Modal(document.getElementById('orderDetailsModal'));
|
||||
let modalInstance = new bootstrap.Modal(document.getElementById('orderDetailsModal'));
|
||||
|
||||
document.getElementById('orderDetailsBody').innerHTML =
|
||||
"<p class='text-center text-muted'>Loading...</p>";
|
||||
|
||||
modal.show();
|
||||
modalInstance.show();
|
||||
|
||||
fetch(`/admin/orders/view/${id}`)
|
||||
.then(response => response.text())
|
||||
@@ -1754,19 +1838,65 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Enter key behavior for items/table
|
||||
itemsTableBody.addEventListener('keydown', function(e) {
|
||||
if (e.key !== 'Enter' || e.target.tagName !== 'INPUT') return;
|
||||
e.preventDefault();
|
||||
|
||||
const currentInput = e.target;
|
||||
const currentRow = currentInput.closest('tr');
|
||||
const rows = Array.from(itemsTableBody.querySelectorAll('tr'));
|
||||
const currentRowIndex = rows.indexOf(currentRow);
|
||||
|
||||
const inputs = Array.from(currentRow.querySelectorAll('input'));
|
||||
const currentInputIndex = inputs.indexOf(currentInput);
|
||||
|
||||
const isLastRow = currentRowIndex === rows.length - 1;
|
||||
const hasData = rowHasData(currentRow);
|
||||
|
||||
if (currentInputIndex < inputs.length - 1) {
|
||||
inputs[currentInputIndex + 1].focus();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isLastRow) {
|
||||
const nextRow = rows[currentRowIndex + 1];
|
||||
const firstInputNextRow = nextRow.querySelector('input');
|
||||
if (firstInputNextRow) firstInputNextRow.focus();
|
||||
return;
|
||||
}
|
||||
|
||||
if (isLastRow && hasData) {
|
||||
const newIndex = rows.length;
|
||||
addRow(newIndex);
|
||||
reindexRows();
|
||||
const newRow = itemsTableBody.querySelector('tr:last-child');
|
||||
const firstInput = newRow.querySelector('input');
|
||||
if (firstInput) firstInput.focus();
|
||||
}
|
||||
});
|
||||
|
||||
// Remove row
|
||||
itemsTableBody.addEventListener('click', function(e) {
|
||||
if (!e.target.classList.contains('remove-row-btn')) return;
|
||||
const rows = itemsTableBody.querySelectorAll('tr');
|
||||
if (rows.length <= 1) {
|
||||
alert('At least one row must exist.');
|
||||
return;
|
||||
}
|
||||
e.target.closest('tr').remove();
|
||||
reindexRows();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<script>
|
||||
document.addEventListener("hidden.bs.modal", function () {
|
||||
// Remove Bootstrap backdrops
|
||||
document.querySelectorAll(".modal-backdrop").forEach(el => el.remove());
|
||||
|
||||
// Fix page scroll locking
|
||||
document.body.classList.remove("modal-open");
|
||||
document.body.style.overflow = "";
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@endsection
|
||||
@@ -133,6 +133,10 @@ Route::prefix('admin')
|
||||
Route::get('/orders/view/{id}', [AdminOrderController::class, 'popup'])
|
||||
->name('admin.orders.popup');
|
||||
|
||||
Route::post('/admin/orders/temp/add', [AdminOrderController::class, 'addTempItem'])
|
||||
->name('admin.orders.temp.add');
|
||||
|
||||
|
||||
// Route::get('/orders/{id}', [AdminOrderController::class, 'view'])
|
||||
// ->name('admin.orders.view');
|
||||
Route::get('/orders/{order:order_id}/see', [AdminOrderController::class, 'see'])
|
||||
|
||||
Reference in New Issue
Block a user