Shipment dashboard changes
This commit is contained in:
@@ -164,46 +164,30 @@ class AdminOrderController extends Controller
|
|||||||
return redirect()->back()->with('success', 'Item deleted and totals updated.');
|
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);
|
|
||||||
$order = Order::findOrFail($item->order_id);
|
|
||||||
|
|
||||||
$item->restore();
|
|
||||||
|
|
||||||
// recalc totals
|
|
||||||
$this->recalcTotals($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)
|
public function updateItem(Request $request, $id)
|
||||||
{
|
{
|
||||||
$order = Order::findOrFail($id);
|
$item = OrderItem::findOrFail($id);
|
||||||
|
|
||||||
$data = $request->validate([
|
$item->update([
|
||||||
'mark_no' => 'required|string',
|
'description' => $request->description,
|
||||||
'origin' => 'nullable|string',
|
'ctn' => $request->ctn,
|
||||||
'destination' => 'nullable|string',
|
'qty' => $request->qty,
|
||||||
|
'ttl_qty' => $request->ttl_qty,
|
||||||
|
'unit' => $request->unit,
|
||||||
|
'price' => $request->price,
|
||||||
|
'ttl_amount' => $request->ttl_amount,
|
||||||
|
'cbm' => $request->cbm,
|
||||||
|
'ttl_cbm' => $request->ttl_cbm,
|
||||||
|
'kg' => $request->kg,
|
||||||
|
'ttl_kg' => $request->ttl_kg,
|
||||||
|
'shop_no' => $request->shop_no,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$order->update([
|
return back()->with('success', 'Item updated successfully!');
|
||||||
'mark_no' => $data['mark_no'],
|
|
||||||
'origin' => $data['origin'] ?? null,
|
|
||||||
'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.');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -340,6 +324,10 @@ class AdminOrderController extends Controller
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
// Popup function
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
public function popup($id)
|
public function popup($id)
|
||||||
{
|
{
|
||||||
@@ -354,8 +342,27 @@ class AdminOrderController extends Controller
|
|||||||
|
|
||||||
return view('admin.popup', compact('order', 'user'));
|
return view('admin.popup', compact('order', 'user'));
|
||||||
}
|
}
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
// Restore Item
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
public function restoreItem($id)
|
||||||
|
{
|
||||||
|
$item = OrderItem::onlyTrashed()->findOrFail($id);
|
||||||
|
$item->restore();
|
||||||
|
|
||||||
|
if (request()->ajax()) {
|
||||||
|
return response()->json([
|
||||||
|
'status' => 'ok',
|
||||||
|
'message' => 'Item restored.'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return back()->belongsTo(Order::class)->with('success', 'Item restored successfully.');
|
||||||
|
}
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
// Reset temp
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
public function resetTemp()
|
public function resetTemp()
|
||||||
@@ -366,6 +373,11 @@ class AdminOrderController extends Controller
|
|||||||
->with('success', 'Order reset successfully.');
|
->with('success', 'Order reset successfully.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
// ORDER SHOW PAGE
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
public function orderShow()
|
public function orderShow()
|
||||||
{
|
{
|
||||||
$orders = Order::with([
|
$orders = Order::with([
|
||||||
@@ -379,48 +391,55 @@ class AdminOrderController extends Controller
|
|||||||
return view('admin.orders', compact('orders'));
|
return view('admin.orders', compact('orders'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function downloadPdf(Request $request)
|
//====================================================
|
||||||
{
|
// Download Pdf
|
||||||
$query = Order::with(['markList', 'invoice', 'shipments']);
|
//=================================================
|
||||||
|
public function downloadPdf(Request $request)
|
||||||
// Apply filters
|
{
|
||||||
if ($request->has('search') && $request->search) {
|
$query = Order::with(['markList', 'invoice', 'shipments']);
|
||||||
$search = $request->search;
|
|
||||||
$query->where(function($q) use ($search) {
|
// Apply filters
|
||||||
$q->where('order_id', 'like', "%{$search}%")
|
if ($request->has('search') && $request->search) {
|
||||||
->orWhereHas('markList', function($q) use ($search) {
|
$search = $request->search;
|
||||||
$q->where('company_name', 'like', "%{$search}%");
|
$query->where(function($q) use ($search) {
|
||||||
})
|
$q->where('order_id', 'like', "%{$search}%")
|
||||||
->orWhereHas('invoice', function($q) use ($search) {
|
->orWhereHas('markList', function($q) use ($search) {
|
||||||
$q->where('invoice_number', 'like', "%{$search}%");
|
$q->where('company_name', 'like', "%{$search}%");
|
||||||
});
|
})
|
||||||
});
|
->orWhereHas('invoice', function($q) use ($search) {
|
||||||
}
|
$q->where('invoice_number', 'like', "%{$search}%");
|
||||||
|
});
|
||||||
if ($request->has('status') && $request->status) {
|
});
|
||||||
$query->whereHas('invoice', function($q) use ($request) {
|
}
|
||||||
$q->where('status', $request->status);
|
|
||||||
});
|
if ($request->has('status') && $request->status) {
|
||||||
}
|
$query->whereHas('invoice', function($q) use ($request) {
|
||||||
|
$q->where('status', $request->status);
|
||||||
if ($request->has('shipment') && $request->shipment) {
|
});
|
||||||
$query->whereHas('shipments', function($q) use ($request) {
|
}
|
||||||
$q->where('status', $request->shipment);
|
|
||||||
});
|
if ($request->has('shipment') && $request->shipment) {
|
||||||
}
|
$query->whereHas('shipments', function($q) use ($request) {
|
||||||
|
$q->where('status', $request->shipment);
|
||||||
$orders = $query->get();
|
});
|
||||||
|
}
|
||||||
$pdf = PDF::loadView('admin.orders.pdf', compact('orders'));
|
|
||||||
return $pdf->download('orders-report-' . date('Y-m-d') . '.pdf');
|
$orders = $query->get();
|
||||||
}
|
|
||||||
|
$pdf = PDF::loadView('admin.orders.pdf', compact('orders'));
|
||||||
|
return $pdf->download('orders-report-' . date('Y-m-d') . '.pdf');
|
||||||
|
}
|
||||||
|
|
||||||
public function downloadExcel(Request $request)
|
public function downloadExcel(Request $request)
|
||||||
{
|
{
|
||||||
return Excel::download(new OrdersExport($request), 'orders-report-' . date('Y-m-d') . '.xlsx');
|
return Excel::download(new OrdersExport($request), 'orders-report-' . date('Y-m-d') . '.xlsx');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addTempItem(Request $request)
|
//====================================================
|
||||||
|
// add Temp Item
|
||||||
|
//=================================================
|
||||||
|
|
||||||
|
public function addTempItem(Request $request)
|
||||||
{
|
{
|
||||||
// Validate item fields
|
// Validate item fields
|
||||||
$item = $request->validate([
|
$item = $request->validate([
|
||||||
@@ -468,81 +487,162 @@ public function addTempItem(Request $request)
|
|||||||
->with('success', 'Item added.');
|
->with('success', 'Item added.');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function finishOrder(Request $request)
|
|
||||||
{
|
public function finishOrder(Request $request)
|
||||||
$request->validate([
|
{
|
||||||
'mark_no' => 'required',
|
$request->validate([
|
||||||
'origin' => 'required',
|
'mark_no' => 'required',
|
||||||
'destination' => 'required',
|
'origin' => 'required',
|
||||||
]);
|
'destination' => 'required',
|
||||||
|
]);
|
||||||
|
|
||||||
$items = session('temp_order_items', []);
|
$items = session('temp_order_items', []);
|
||||||
|
|
||||||
if (empty($items)) {
|
if (empty($items)) {
|
||||||
return redirect()->to(route('admin.orders.index') . '#createOrderForm')
|
return redirect()->to(route('admin.orders.index') . '#createOrderForm')
|
||||||
->with('error', 'Add at least one item before finishing.');
|
->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.');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// =======================
|
||||||
|
// 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 ORDER 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'],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// =======================
|
||||||
|
// INVOICE CREATION START
|
||||||
|
// =======================
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
$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();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Create Invoice Record
|
||||||
|
$invoice = \App\Models\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,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 4. Clone order items into invoice_items
|
||||||
|
foreach ($order->items as $item) {
|
||||||
|
\App\Models\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,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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.');
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers\Admin;
|
namespace App\Http\Controllers\Admin;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use App\Models\Shipment;
|
use App\Models\Shipment;
|
||||||
@@ -106,6 +107,9 @@ class ShipmentController extends Controller
|
|||||||
'order_qty' => $order->qty,
|
'order_qty' => $order->qty,
|
||||||
'order_ttl_qty' => $order->ttl_qty,
|
'order_ttl_qty' => $order->ttl_qty,
|
||||||
'order_ttl_amount' => $order->ttl_amount,
|
'order_ttl_amount' => $order->ttl_amount,
|
||||||
|
'order_cbm' => $order->cbm,
|
||||||
|
'order_ttl_cbm' => $order->ttl_cbm,
|
||||||
|
'order_kg' => $order->kg,
|
||||||
'order_ttl_kg' => $order->ttl_kg,
|
'order_ttl_kg' => $order->ttl_kg,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -113,24 +117,112 @@ class ShipmentController extends Controller
|
|||||||
return redirect()->back()->with('success', "Shipment $newShipmentId created successfully!");
|
return redirect()->back()->with('success', "Shipment $newShipmentId created successfully!");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function edit($id)
|
||||||
* Show shipment details (for modal popup)
|
{
|
||||||
*/
|
$shipment = Shipment::with('orders')->findOrFail($id);
|
||||||
|
|
||||||
|
return view('admin.shipments.show', [
|
||||||
|
'shipment' => $shipment,
|
||||||
|
'orders' => $shipment->orders,
|
||||||
|
'isViewMode' => false // This is the edit mode
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
public function show($id)
|
public function show($id)
|
||||||
{
|
{
|
||||||
$shipment = Shipment::findOrFail($id);
|
$mode = request()->get('mode', 'view');
|
||||||
|
|
||||||
// Load full order data from orders table
|
$shipment = Shipment::with(['items.order'])->findOrFail($id);
|
||||||
$orders = Order::whereIn('id',
|
|
||||||
ShipmentItem::where('shipment_id', $id)->pluck('order_id')
|
|
||||||
)->get();
|
|
||||||
|
|
||||||
return response()->json([
|
// Get orders from shipment items
|
||||||
|
$orders = collect();
|
||||||
|
foreach ($shipment->items as $item) {
|
||||||
|
if ($item->order) {
|
||||||
|
$orders->push($item->order);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get orders not assigned to any shipment (available orders)
|
||||||
|
$usedOrderIds = ShipmentItem::pluck('order_id')->toArray();
|
||||||
|
$availableOrders = Order::whereNotIn('id', $usedOrderIds)->get();
|
||||||
|
|
||||||
|
return view('admin.view-shipment', [
|
||||||
'shipment' => $shipment,
|
'shipment' => $shipment,
|
||||||
'orders' => $orders
|
'orders' => $orders,
|
||||||
|
'mode' => $mode,
|
||||||
|
'availableOrders' => $availableOrders
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function addOrders(Request $request, $id)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'order_ids' => 'required|array|min:1'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$shipment = Shipment::findOrFail($id);
|
||||||
|
$orderIds = $request->order_ids;
|
||||||
|
|
||||||
|
DB::beginTransaction();
|
||||||
|
|
||||||
|
try {
|
||||||
|
$orders = Order::whereIn('id', $orderIds)->get();
|
||||||
|
$addedOrders = [];
|
||||||
|
|
||||||
|
foreach ($orders as $order) {
|
||||||
|
// Prevent duplicates
|
||||||
|
if (ShipmentItem::where('shipment_id', $shipment->id)->where('order_id', $order->id)->exists()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ShipmentItem::create([
|
||||||
|
'shipment_id' => $shipment->id,
|
||||||
|
'order_id' => $order->id,
|
||||||
|
'order_ctn' => $order->ctn,
|
||||||
|
'order_qty' => $order->qty,
|
||||||
|
'order_ttl_qty' => $order->ttl_qty,
|
||||||
|
'order_ttl_amount' => $order->ttl_amount,
|
||||||
|
'order_cbm' => $order->cbm,
|
||||||
|
'order_ttl_cbm' => $order->ttl_cbm,
|
||||||
|
'order_kg' => $order->kg,
|
||||||
|
'order_ttl_kg' => $order->ttl_kg,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$addedOrders[] = $order;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recalculate totals
|
||||||
|
$this->recalculateShipmentTotals($shipment->id);
|
||||||
|
|
||||||
|
DB::commit();
|
||||||
|
|
||||||
|
$shipment->refresh();
|
||||||
|
$shipment->load('items.order');
|
||||||
|
|
||||||
|
// Get updated orders list
|
||||||
|
$updatedOrders = collect();
|
||||||
|
foreach ($shipment->items as $item) {
|
||||||
|
if ($item->order) {
|
||||||
|
$updatedOrders->push($item->order);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true,
|
||||||
|
'message' => 'Orders added to shipment successfully.',
|
||||||
|
'shipment' => $shipment,
|
||||||
|
'orders' => $addedOrders
|
||||||
|
]);
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
DB::rollBack();
|
||||||
|
return response()->json([
|
||||||
|
'success' => false,
|
||||||
|
'message' => 'Failed to add orders: ' . $e->getMessage()
|
||||||
|
], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update Shipment status from action button
|
* Update Shipment status from action button
|
||||||
*/
|
*/
|
||||||
@@ -209,4 +301,77 @@ class ShipmentController extends Controller
|
|||||||
return redirect()->route('admin.shipments')
|
return redirect()->route('admin.shipments')
|
||||||
->with('success', 'Shipment deleted successfully.');
|
->with('success', 'Shipment deleted successfully.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function removeOrder(Request $request)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'shipment_id' => 'required|exists:shipments,id',
|
||||||
|
'order_id' => 'required|exists:orders,id'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$shipmentId = $request->shipment_id;
|
||||||
|
$orderId = $request->order_id;
|
||||||
|
|
||||||
|
// Get order data before deletion
|
||||||
|
$order = Order::findOrFail($orderId);
|
||||||
|
|
||||||
|
// Delete pivot entry
|
||||||
|
ShipmentItem::where('shipment_id', $shipmentId)
|
||||||
|
->where('order_id', $orderId)
|
||||||
|
->delete();
|
||||||
|
|
||||||
|
// Recalculate totals
|
||||||
|
$shipment = $this->recalculateShipmentTotals($shipmentId);
|
||||||
|
|
||||||
|
if ($request->ajax() || $request->wantsJson()) {
|
||||||
|
return response()->json([
|
||||||
|
'success' => true,
|
||||||
|
'message' => 'Order removed successfully.',
|
||||||
|
'order' => $order,
|
||||||
|
'shipment' => $shipment
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return back()->with('success', 'Order removed successfully.');
|
||||||
|
}
|
||||||
|
|
||||||
|
private function recalculateShipmentTotals($shipmentId)
|
||||||
|
{
|
||||||
|
$shipment = Shipment::with('items')->findOrFail($shipmentId);
|
||||||
|
|
||||||
|
// Use the shipment items to calculate totals
|
||||||
|
$shipment->total_ctn = $shipment->items->sum('order_ctn');
|
||||||
|
$shipment->total_qty = $shipment->items->sum('order_qty');
|
||||||
|
$shipment->total_ttl_qty = $shipment->items->sum('order_ttl_qty');
|
||||||
|
$shipment->total_amount = $shipment->items->sum('order_ttl_amount');
|
||||||
|
$shipment->total_cbm = $shipment->items->sum('order_cbm');
|
||||||
|
$shipment->total_ttl_cbm = $shipment->items->sum('order_ttl_cbm');
|
||||||
|
$shipment->total_kg = $shipment->items->sum('order_kg');
|
||||||
|
$shipment->total_ttl_kg = $shipment->items->sum('order_ttl_kg');
|
||||||
|
|
||||||
|
$shipment->save();
|
||||||
|
$shipment->refresh(); // Refresh to get updated data
|
||||||
|
|
||||||
|
return $shipment;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper method to get available orders for a shipment
|
||||||
|
public function getAvailableOrders($shipmentId)
|
||||||
|
{
|
||||||
|
$shipment = Shipment::findOrFail($shipmentId);
|
||||||
|
|
||||||
|
// Get all used order IDs
|
||||||
|
$usedOrderIds = ShipmentItem::pluck('order_id')->toArray();
|
||||||
|
|
||||||
|
// Remove orders that are already in this shipment
|
||||||
|
$shipmentOrderIds = $shipment->items->pluck('order_id')->toArray();
|
||||||
|
$availableOrderIds = array_diff($usedOrderIds, $shipmentOrderIds);
|
||||||
|
|
||||||
|
$availableOrders = Order::whereNotIn('id', $availableOrderIds)->get();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true,
|
||||||
|
'availableOrders' => $availableOrders
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -11,12 +11,27 @@ class ShipmentItem extends Model
|
|||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'shipment_id',
|
'shipment_id',
|
||||||
'order_id',
|
'order_id',
|
||||||
'order_ctn',
|
|
||||||
'order_qty',
|
// OLD fields (keep them if old data exists)
|
||||||
'order_ttl_qty',
|
'order_ctn',
|
||||||
'order_ttl_amount',
|
'order_qty',
|
||||||
'order_ttl_kg',
|
'order_ttl_qty',
|
||||||
|
'order_ttl_amount',
|
||||||
|
'order_ttl_kg',
|
||||||
|
|
||||||
|
// NEW fields (added for correct shipments)
|
||||||
|
'ctn',
|
||||||
|
'qty',
|
||||||
|
'ttl_qty',
|
||||||
|
|
||||||
|
'cbm',
|
||||||
|
'ttl_cbm',
|
||||||
|
|
||||||
|
'kg',
|
||||||
|
'ttl_kg',
|
||||||
|
|
||||||
|
'ttl_amount',
|
||||||
];
|
];
|
||||||
|
|
||||||
// ---------------------------
|
// ---------------------------
|
||||||
@@ -36,11 +51,11 @@ class ShipmentItem extends Model
|
|||||||
// Helper: return order data with fallback to snapshot
|
// Helper: return order data with fallback to snapshot
|
||||||
public function getDisplayQty()
|
public function getDisplayQty()
|
||||||
{
|
{
|
||||||
return $this->order->qty ?? $this->order_qty;
|
return $this->qty;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDisplayAmount()
|
public function getDisplayAmount()
|
||||||
{
|
{
|
||||||
return $this->order->ttl_amount ?? $this->order_ttl_amount;
|
return $this->ttl_amount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,10 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^8.2",
|
"php": "^8.2",
|
||||||
|
"barryvdh/laravel-dompdf": "^3.1",
|
||||||
"laravel/framework": "^12.0",
|
"laravel/framework": "^12.0",
|
||||||
"laravel/tinker": "^2.10.1",
|
"laravel/tinker": "^2.10.1",
|
||||||
|
"maatwebsite/excel": "^1.1",
|
||||||
"mpdf/mpdf": "^8.2",
|
"mpdf/mpdf": "^8.2",
|
||||||
"php-open-source-saver/jwt-auth": "2.8"
|
"php-open-source-saver/jwt-auth": "2.8"
|
||||||
},
|
},
|
||||||
|
|||||||
488
composer.lock
generated
488
composer.lock
generated
@@ -4,8 +4,85 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "fa680e1e8b3550d710849bbd820e3626",
|
"content-hash": "6a2ec43d7e96d38cacfc2f9e1ae5cb9e",
|
||||||
"packages": [
|
"packages": [
|
||||||
|
{
|
||||||
|
"name": "barryvdh/laravel-dompdf",
|
||||||
|
"version": "v3.1.1",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/barryvdh/laravel-dompdf.git",
|
||||||
|
"reference": "8e71b99fc53bb8eb77f316c3c452dd74ab7cb25d"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/barryvdh/laravel-dompdf/zipball/8e71b99fc53bb8eb77f316c3c452dd74ab7cb25d",
|
||||||
|
"reference": "8e71b99fc53bb8eb77f316c3c452dd74ab7cb25d",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"dompdf/dompdf": "^3.0",
|
||||||
|
"illuminate/support": "^9|^10|^11|^12",
|
||||||
|
"php": "^8.1"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"larastan/larastan": "^2.7|^3.0",
|
||||||
|
"orchestra/testbench": "^7|^8|^9|^10",
|
||||||
|
"phpro/grumphp": "^2.5",
|
||||||
|
"squizlabs/php_codesniffer": "^3.5"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"laravel": {
|
||||||
|
"aliases": {
|
||||||
|
"PDF": "Barryvdh\\DomPDF\\Facade\\Pdf",
|
||||||
|
"Pdf": "Barryvdh\\DomPDF\\Facade\\Pdf"
|
||||||
|
},
|
||||||
|
"providers": [
|
||||||
|
"Barryvdh\\DomPDF\\ServiceProvider"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "3.0-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Barryvdh\\DomPDF\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Barry vd. Heuvel",
|
||||||
|
"email": "barryvdh@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "A DOMPDF Wrapper for Laravel",
|
||||||
|
"keywords": [
|
||||||
|
"dompdf",
|
||||||
|
"laravel",
|
||||||
|
"pdf"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/barryvdh/laravel-dompdf/issues",
|
||||||
|
"source": "https://github.com/barryvdh/laravel-dompdf/tree/v3.1.1"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://fruitcake.nl",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/barryvdh",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2025-02-13T15:07:54+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "brick/math",
|
"name": "brick/math",
|
||||||
"version": "0.14.0",
|
"version": "0.14.0",
|
||||||
@@ -377,6 +454,161 @@
|
|||||||
],
|
],
|
||||||
"time": "2024-02-05T11:56:58+00:00"
|
"time": "2024-02-05T11:56:58+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "dompdf/dompdf",
|
||||||
|
"version": "v3.1.4",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/dompdf/dompdf.git",
|
||||||
|
"reference": "db712c90c5b9868df3600e64e68da62e78a34623"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/dompdf/dompdf/zipball/db712c90c5b9868df3600e64e68da62e78a34623",
|
||||||
|
"reference": "db712c90c5b9868df3600e64e68da62e78a34623",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"dompdf/php-font-lib": "^1.0.0",
|
||||||
|
"dompdf/php-svg-lib": "^1.0.0",
|
||||||
|
"ext-dom": "*",
|
||||||
|
"ext-mbstring": "*",
|
||||||
|
"masterminds/html5": "^2.0",
|
||||||
|
"php": "^7.1 || ^8.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"ext-gd": "*",
|
||||||
|
"ext-json": "*",
|
||||||
|
"ext-zip": "*",
|
||||||
|
"mockery/mockery": "^1.3",
|
||||||
|
"phpunit/phpunit": "^7.5 || ^8 || ^9 || ^10 || ^11",
|
||||||
|
"squizlabs/php_codesniffer": "^3.5",
|
||||||
|
"symfony/process": "^4.4 || ^5.4 || ^6.2 || ^7.0"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"ext-gd": "Needed to process images",
|
||||||
|
"ext-gmagick": "Improves image processing performance",
|
||||||
|
"ext-imagick": "Improves image processing performance",
|
||||||
|
"ext-zlib": "Needed for pdf stream compression"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Dompdf\\": "src/"
|
||||||
|
},
|
||||||
|
"classmap": [
|
||||||
|
"lib/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"LGPL-2.1"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "The Dompdf Community",
|
||||||
|
"homepage": "https://github.com/dompdf/dompdf/blob/master/AUTHORS.md"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "DOMPDF is a CSS 2.1 compliant HTML to PDF converter",
|
||||||
|
"homepage": "https://github.com/dompdf/dompdf",
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/dompdf/dompdf/issues",
|
||||||
|
"source": "https://github.com/dompdf/dompdf/tree/v3.1.4"
|
||||||
|
},
|
||||||
|
"time": "2025-10-29T12:43:30+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "dompdf/php-font-lib",
|
||||||
|
"version": "1.0.1",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/dompdf/php-font-lib.git",
|
||||||
|
"reference": "6137b7d4232b7f16c882c75e4ca3991dbcf6fe2d"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/dompdf/php-font-lib/zipball/6137b7d4232b7f16c882c75e4ca3991dbcf6fe2d",
|
||||||
|
"reference": "6137b7d4232b7f16c882c75e4ca3991dbcf6fe2d",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-mbstring": "*",
|
||||||
|
"php": "^7.1 || ^8.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"symfony/phpunit-bridge": "^3 || ^4 || ^5 || ^6"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"FontLib\\": "src/FontLib"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"LGPL-2.1-or-later"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "The FontLib Community",
|
||||||
|
"homepage": "https://github.com/dompdf/php-font-lib/blob/master/AUTHORS.md"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "A library to read, parse, export and make subsets of different types of font files.",
|
||||||
|
"homepage": "https://github.com/dompdf/php-font-lib",
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/dompdf/php-font-lib/issues",
|
||||||
|
"source": "https://github.com/dompdf/php-font-lib/tree/1.0.1"
|
||||||
|
},
|
||||||
|
"time": "2024-12-02T14:37:59+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "dompdf/php-svg-lib",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/dompdf/php-svg-lib.git",
|
||||||
|
"reference": "eb045e518185298eb6ff8d80d0d0c6b17aecd9af"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/eb045e518185298eb6ff8d80d0d0c6b17aecd9af",
|
||||||
|
"reference": "eb045e518185298eb6ff8d80d0d0c6b17aecd9af",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-mbstring": "*",
|
||||||
|
"php": "^7.1 || ^8.0",
|
||||||
|
"sabberworm/php-css-parser": "^8.4"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Svg\\": "src/Svg"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"LGPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "The SvgLib Community",
|
||||||
|
"homepage": "https://github.com/dompdf/php-svg-lib/blob/master/AUTHORS.md"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "A library to read, parse and export to PDF SVG files.",
|
||||||
|
"homepage": "https://github.com/dompdf/php-svg-lib",
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/dompdf/php-svg-lib/issues",
|
||||||
|
"source": "https://github.com/dompdf/php-svg-lib/tree/1.0.0"
|
||||||
|
},
|
||||||
|
"time": "2024-04-29T13:26:35+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "dragonmantank/cron-expression",
|
"name": "dragonmantank/cron-expression",
|
||||||
"version": "v3.6.0",
|
"version": "v3.6.0",
|
||||||
@@ -2081,6 +2313,132 @@
|
|||||||
],
|
],
|
||||||
"time": "2024-12-08T08:18:47+00:00"
|
"time": "2024-12-08T08:18:47+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "maatwebsite/excel",
|
||||||
|
"version": "v1.1.5",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/Maatwebsite/Laravel-Excel.git",
|
||||||
|
"reference": "0c67aba8387726458d42461eae91a3415593bbc4"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/Maatwebsite/Laravel-Excel/zipball/0c67aba8387726458d42461eae91a3415593bbc4",
|
||||||
|
"reference": "0c67aba8387726458d42461eae91a3415593bbc4",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.3.0",
|
||||||
|
"phpoffice/phpexcel": "~1.8.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"mockery/mockery": "~0.9",
|
||||||
|
"orchestra/testbench": "~2.2.0@dev",
|
||||||
|
"phpunit/phpunit": "~4.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-0": {
|
||||||
|
"Maatwebsite\\Excel\\": "src/"
|
||||||
|
},
|
||||||
|
"classmap": [
|
||||||
|
"src/Maatwebsite/Excel",
|
||||||
|
"tests/TestCase.php"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"LGPL"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Maatwebsite.nl",
|
||||||
|
"email": "patrick@maatwebsite.nl"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "An eloquent way of importing and exporting Excel and CSV in Laravel 4 with the power of PHPExcel",
|
||||||
|
"keywords": [
|
||||||
|
"PHPExcel",
|
||||||
|
"batch",
|
||||||
|
"csv",
|
||||||
|
"excel",
|
||||||
|
"export",
|
||||||
|
"import",
|
||||||
|
"laravel"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/Maatwebsite/Laravel-Excel/issues",
|
||||||
|
"source": "https://github.com/Maatwebsite/Laravel-Excel/tree/master"
|
||||||
|
},
|
||||||
|
"time": "2014-07-10T09:06:07+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "masterminds/html5",
|
||||||
|
"version": "2.10.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/Masterminds/html5-php.git",
|
||||||
|
"reference": "fcf91eb64359852f00d921887b219479b4f21251"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/Masterminds/html5-php/zipball/fcf91eb64359852f00d921887b219479b4f21251",
|
||||||
|
"reference": "fcf91eb64359852f00d921887b219479b4f21251",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-dom": "*",
|
||||||
|
"php": ">=5.3.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8 || ^9"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "2.7-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Masterminds\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Matt Butcher",
|
||||||
|
"email": "technosophos@gmail.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Matt Farina",
|
||||||
|
"email": "matt@mattfarina.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Asmir Mustafic",
|
||||||
|
"email": "goetas@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "An HTML5 parser and serializer.",
|
||||||
|
"homepage": "http://masterminds.github.io/html5-php",
|
||||||
|
"keywords": [
|
||||||
|
"HTML5",
|
||||||
|
"dom",
|
||||||
|
"html",
|
||||||
|
"parser",
|
||||||
|
"querypath",
|
||||||
|
"serializer",
|
||||||
|
"xml"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/Masterminds/html5-php/issues",
|
||||||
|
"source": "https://github.com/Masterminds/html5-php/tree/2.10.0"
|
||||||
|
},
|
||||||
|
"time": "2025-07-25T09:04:22+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "monolog/monolog",
|
"name": "monolog/monolog",
|
||||||
"version": "3.9.0",
|
"version": "3.9.0",
|
||||||
@@ -3034,6 +3392,68 @@
|
|||||||
},
|
},
|
||||||
"time": "2025-02-10T21:11:16+00:00"
|
"time": "2025-02-10T21:11:16+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "phpoffice/phpexcel",
|
||||||
|
"version": "1.8.1",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/PHPOffice/PHPExcel.git",
|
||||||
|
"reference": "372c7cbb695a6f6f1e62649381aeaa37e7e70b32"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/PHPOffice/PHPExcel/zipball/372c7cbb695a6f6f1e62649381aeaa37e7e70b32",
|
||||||
|
"reference": "372c7cbb695a6f6f1e62649381aeaa37e7e70b32",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-xml": "*",
|
||||||
|
"ext-xmlwriter": "*",
|
||||||
|
"php": ">=5.2.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-0": {
|
||||||
|
"PHPExcel": "Classes/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"LGPL"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Maarten Balliauw",
|
||||||
|
"homepage": "http://blog.maartenballiauw.be"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Mark Baker"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Franck Lefevre",
|
||||||
|
"homepage": "http://blog.rootslabs.net"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Erik Tilt"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "PHPExcel - OpenXML - Read, Create and Write Spreadsheet documents in PHP - Spreadsheet engine",
|
||||||
|
"homepage": "http://phpexcel.codeplex.com",
|
||||||
|
"keywords": [
|
||||||
|
"OpenXML",
|
||||||
|
"excel",
|
||||||
|
"php",
|
||||||
|
"spreadsheet",
|
||||||
|
"xls",
|
||||||
|
"xlsx"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/PHPOffice/PHPExcel/issues",
|
||||||
|
"source": "https://github.com/PHPOffice/PHPExcel/tree/master"
|
||||||
|
},
|
||||||
|
"abandoned": "phpoffice/phpspreadsheet",
|
||||||
|
"time": "2015-05-01T07:00:55+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "phpoption/phpoption",
|
"name": "phpoption/phpoption",
|
||||||
"version": "1.9.4",
|
"version": "1.9.4",
|
||||||
@@ -3798,6 +4218,72 @@
|
|||||||
},
|
},
|
||||||
"time": "2025-09-04T20:59:21+00:00"
|
"time": "2025-09-04T20:59:21+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "sabberworm/php-css-parser",
|
||||||
|
"version": "v8.9.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/MyIntervals/PHP-CSS-Parser.git",
|
||||||
|
"reference": "d8e916507b88e389e26d4ab03c904a082aa66bb9"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/MyIntervals/PHP-CSS-Parser/zipball/d8e916507b88e389e26d4ab03c904a082aa66bb9",
|
||||||
|
"reference": "d8e916507b88e389e26d4ab03c904a082aa66bb9",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-iconv": "*",
|
||||||
|
"php": "^5.6.20 || ^7.0.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "5.7.27 || 6.5.14 || 7.5.20 || 8.5.41",
|
||||||
|
"rawr/cross-data-providers": "^2.0.0"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"ext-mbstring": "for parsing UTF-8 CSS"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-main": "9.0.x-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Sabberworm\\CSS\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Raphael Schweikert"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Oliver Klee",
|
||||||
|
"email": "github@oliverklee.de"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Jake Hotson",
|
||||||
|
"email": "jake.github@qzdesign.co.uk"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Parser for CSS Files written in PHP",
|
||||||
|
"homepage": "https://www.sabberworm.com/blog/2010/6/10/php-css-parser",
|
||||||
|
"keywords": [
|
||||||
|
"css",
|
||||||
|
"parser",
|
||||||
|
"stylesheet"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/MyIntervals/PHP-CSS-Parser/issues",
|
||||||
|
"source": "https://github.com/MyIntervals/PHP-CSS-Parser/tree/v8.9.0"
|
||||||
|
},
|
||||||
|
"time": "2025-07-11T13:20:48+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "setasign/fpdi",
|
"name": "setasign/fpdi",
|
||||||
"version": "v2.6.4",
|
"version": "v2.6.4",
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('shipment_items', function (Blueprint $table) {
|
||||||
|
|
||||||
|
if (!Schema::hasColumn('shipment_items', 'ctn')) {
|
||||||
|
$table->integer('ctn')->default(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Schema::hasColumn('shipment_items', 'qty')) {
|
||||||
|
$table->integer('qty')->default(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Schema::hasColumn('shipment_items', 'ttl_qty')) {
|
||||||
|
$table->integer('ttl_qty')->default(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Schema::hasColumn('shipment_items', 'cbm')) {
|
||||||
|
$table->double('cbm')->default(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Schema::hasColumn('shipment_items', 'ttl_cbm')) {
|
||||||
|
$table->double('ttl_cbm')->default(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Schema::hasColumn('shipment_items', 'kg')) {
|
||||||
|
$table->double('kg')->default(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Schema::hasColumn('shipment_items', 'ttl_kg')) {
|
||||||
|
$table->double('ttl_kg')->default(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Schema::hasColumn('shipment_items', 'ttl_amount')) {
|
||||||
|
$table->double('ttl_amount')->default(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('shipment_items', function (Blueprint $table) {
|
||||||
|
// safely remove columns (optional)
|
||||||
|
$columns = [
|
||||||
|
'ctn', 'qty', 'ttl_qty', 'cbm',
|
||||||
|
'ttl_cbm', 'kg', 'ttl_kg', 'ttl_amount'
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($columns as $col) {
|
||||||
|
if (Schema::hasColumn('shipment_items', $col)) {
|
||||||
|
$table->dropColumn($col);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
Binary file not shown.
BIN
public/invoices/invoice-INV-2025-000028.pdf
Normal file
BIN
public/invoices/invoice-INV-2025-000028.pdf
Normal file
Binary file not shown.
BIN
public/invoices/invoice-INV-2025-000029.pdf
Normal file
BIN
public/invoices/invoice-INV-2025-000029.pdf
Normal file
Binary file not shown.
BIN
public/invoices/invoice-INV-2025-000030.pdf
Normal file
BIN
public/invoices/invoice-INV-2025-000030.pdf
Normal file
Binary file not shown.
BIN
public/invoices/invoice-INV-2025-000032.pdf
Normal file
BIN
public/invoices/invoice-INV-2025-000032.pdf
Normal file
Binary file not shown.
@@ -15,27 +15,30 @@
|
|||||||
<h4 class="fw-bold mb-0">Order Details</h4>
|
<h4 class="fw-bold mb-0">Order Details</h4>
|
||||||
<small class="text-muted">Detailed view of this shipment order</small>
|
<small class="text-muted">Detailed view of this shipment order</small>
|
||||||
</div>
|
</div>
|
||||||
<a href="{{ route('admin.dashboard') }}" class="btn-close"></a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{-- ACTION BUTTONS --}}
|
|
||||||
<div class="mt-3 d-flex gap-2">
|
|
||||||
|
|
||||||
{{-- ADD ITEM --}}
|
{{-- ADD ITEM --}}
|
||||||
<button class="btn btn-add-item" data-bs-toggle="modal" data-bs-target="#addItemModal">
|
<button class="btn btn-add-item" data-bs-toggle="modal" data-bs-target="#addItemModal">
|
||||||
<i class="fas fa-plus-circle me-2"></i>Add New Item
|
<i class="fas fa-plus-circle me-2"></i>Add New Item
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{{-- EDIT ORDER --}}
|
<a href="{{ route('admin.dashboard') }}" class="btn-close"></a>
|
||||||
@if($order->status === 'pending')
|
</div>
|
||||||
|
|
||||||
|
<!-- {{-- ACTION BUTTONS --}}
|
||||||
|
<div class="mt-3 d-flex gap-2">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{{-- EDIT ORDER --}} -->
|
||||||
|
<!-- @if($order->status === 'pending')
|
||||||
<button class="btn btn-edit-order" onclick="document.getElementById('editOrderForm').style.display='block'">
|
<button class="btn btn-edit-order" onclick="document.getElementById('editOrderForm').style.display='block'">
|
||||||
<i class="fas fa-edit me-2"></i>Edit Order
|
<i class="fas fa-edit me-2"></i>Edit Order
|
||||||
</button>
|
</button>
|
||||||
@else
|
@else
|
||||||
<button class="btn btn-edit-order" disabled><i class="fas fa-edit me-2"></i>Edit Order</button>
|
<button class="btn btn-edit-order" disabled><i class="fas fa-edit me-2"></i>Edit Order</button>
|
||||||
@endif
|
@endif -->
|
||||||
|
|
||||||
{{-- DELETE ORDER --}}
|
<!-- {{-- DELETE ORDER --}}
|
||||||
@if($order->status === 'pending')
|
@if($order->status === 'pending')
|
||||||
<form action="{{ route('admin.orders.destroy', $order->id) }}"
|
<form action="{{ route('admin.orders.destroy', $order->id) }}"
|
||||||
method="POST"
|
method="POST"
|
||||||
@@ -46,9 +49,9 @@
|
|||||||
<i class="fas fa-trash-alt me-2"></i>Delete Order
|
<i class="fas fa-trash-alt me-2"></i>Delete Order
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
@endif
|
@endif -->
|
||||||
|
|
||||||
</div>
|
<!-- </div> -->
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
@@ -56,7 +59,7 @@
|
|||||||
<div id="editOrderForm" class="p-3 bg-light rounded mb-4 shadow-sm" style="display:none;">
|
<div id="editOrderForm" class="p-3 bg-light rounded mb-4 shadow-sm" style="display:none;">
|
||||||
<h5 class="fw-bold mb-3">Edit Order</h5>
|
<h5 class="fw-bold mb-3">Edit Order</h5>
|
||||||
|
|
||||||
<form action="{{ route('admin.orders.update', $order->id) }}" method="POST">
|
<form action="{{ route('admin.orders.updateItem', $order->id) }}" method="POST">
|
||||||
@csrf
|
@csrf
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@@ -185,23 +188,157 @@
|
|||||||
<td>{{ $item->ttl_kg }}</td>
|
<td>{{ $item->ttl_kg }}</td>
|
||||||
<td>{{ $item->shop_no }}</td>
|
<td>{{ $item->shop_no }}</td>
|
||||||
|
|
||||||
<td>
|
<td class="d-flex justify-content-center gap-2">
|
||||||
<form action="{{ route('admin.orders.deleteItem', $item->id) }}"
|
|
||||||
method="POST"
|
{{-- EDIT BUTTON --}}
|
||||||
onsubmit="return confirm('Delete this item?')">
|
<button
|
||||||
@csrf
|
type="button"
|
||||||
@method('DELETE')
|
class="btn btn-sm btn-edit-item"
|
||||||
<button class="btn btn-sm btn-delete-item">
|
data-bs-toggle="modal"
|
||||||
<i class="fas fa-trash"></i>
|
data-bs-target="#editItemModal{{ $item->id }}">
|
||||||
</button>
|
<i class="fas fa-edit"></i>
|
||||||
</form>
|
</button>
|
||||||
</td>
|
|
||||||
|
{{-- DELETE BUTTON --}}
|
||||||
|
<form action="{{ route('admin.orders.deleteItem', $item->id) }}"
|
||||||
|
method="POST"
|
||||||
|
onsubmit="return confirm('Delete this item?')">
|
||||||
|
@csrf
|
||||||
|
@method('DELETE')
|
||||||
|
<button class="btn btn-sm btn-delete-item">
|
||||||
|
<i class="fas fa-trash"></i>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
|
||||||
</tr>
|
</tr>
|
||||||
@endforeach
|
@endforeach
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
@foreach($order->items as $item)
|
||||||
|
<div class="modal fade" id="editItemModal{{ $item->id }}" tabindex="-1">
|
||||||
|
<div class="modal-dialog modal-lg">
|
||||||
|
<div class="modal-content custom-modal">
|
||||||
|
|
||||||
|
<div class="modal-header modal-gradient-header">
|
||||||
|
<h5 class="modal-title text-white">
|
||||||
|
<i class="fas fa-edit me-2"></i>Edit Item
|
||||||
|
</h5>
|
||||||
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form action="{{ route('admin.orders.updateItem', $item->id) }}" method="POST">
|
||||||
|
@csrf
|
||||||
|
@method('PUT')
|
||||||
|
|
||||||
|
<div class="modal-body">
|
||||||
|
|
||||||
|
<div class="row g-3">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label">Description</label>
|
||||||
|
<input type="text" name="description"
|
||||||
|
value="{{ $item->description }}"
|
||||||
|
class="form-control custom-input" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-3">
|
||||||
|
<label class="form-label">CTN</label>
|
||||||
|
<input type="number" name="ctn"
|
||||||
|
value="{{ $item->ctn }}"
|
||||||
|
class="form-control custom-input">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-3">
|
||||||
|
<label class="form-label">QTY</label>
|
||||||
|
<input type="number" name="qty"
|
||||||
|
value="{{ $item->qty }}"
|
||||||
|
class="form-control custom-input">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-3">
|
||||||
|
<label class="form-label">TTL QTY</label>
|
||||||
|
<input type="number" name="ttl_qty"
|
||||||
|
value="{{ $item->ttl_qty }}"
|
||||||
|
class="form-control custom-input">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-3">
|
||||||
|
<label class="form-label">Unit</label>
|
||||||
|
<input type="text" name="unit"
|
||||||
|
value="{{ $item->unit }}"
|
||||||
|
class="form-control custom-input">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-3">
|
||||||
|
<label class="form-label">Price</label>
|
||||||
|
<input type="number" name="price"
|
||||||
|
value="{{ $item->price }}"
|
||||||
|
class="form-control custom-input">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-3">
|
||||||
|
<label class="form-label">Total Amount</label>
|
||||||
|
<input type="number" name="ttl_amount"
|
||||||
|
value="{{ $item->ttl_amount }}"
|
||||||
|
class="form-control custom-input">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-3">
|
||||||
|
<label class="form-label">CBM</label>
|
||||||
|
<input type="number" name="cbm"
|
||||||
|
value="{{ $item->cbm }}"
|
||||||
|
class="form-control custom-input">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-3">
|
||||||
|
<label class="form-label">TTL CBM</label>
|
||||||
|
<input type="number" name="ttl_cbm"
|
||||||
|
value="{{ $item->ttl_cbm }}"
|
||||||
|
class="form-control custom-input">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-3">
|
||||||
|
<label class="form-label">KG</label>
|
||||||
|
<input type="number" name="kg"
|
||||||
|
value="{{ $item->kg }}"
|
||||||
|
class="form-control custom-input">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-3">
|
||||||
|
<label class="form-label">TTL KG</label>
|
||||||
|
<input type="number" name="ttl_kg"
|
||||||
|
value="{{ $item->ttl_kg }}"
|
||||||
|
class="form-control custom-input">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-3">
|
||||||
|
<label class="form-label">Shop No</label>
|
||||||
|
<input type="text" name="shop_no"
|
||||||
|
value="{{ $item->shop_no }}"
|
||||||
|
class="form-control custom-input">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal-footer">
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-modal-close" data-bs-dismiss="modal">Close</button>
|
||||||
|
<button type="submit" class="btn btn-modal-add">Add Item</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
|
||||||
|
|
||||||
{{-- TOTALS --}}
|
{{-- TOTALS --}}
|
||||||
<div class="row text-center mt-4">
|
<div class="row text-center mt-4">
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
@@ -239,7 +376,7 @@
|
|||||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form action="{{ route('admin.orders.addItem', $order->id) }}" method="POST">
|
<form id="addItemForm" action="{{ route('admin.orders.addItem', $order->id) }}" method="POST">
|
||||||
@csrf
|
@csrf
|
||||||
|
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
@@ -253,54 +390,75 @@
|
|||||||
|
|
||||||
<h5 class="section-title">Deleted Items (Use / Restore)</h5>
|
<h5 class="section-title">Deleted Items (Use / Restore)</h5>
|
||||||
|
|
||||||
<ul class="list-group mb-3">
|
<div class="table-responsive mb-4">
|
||||||
|
<table class="table table-bordered align-middle text-center">
|
||||||
|
<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>Actions</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
@forelse($deletedItems as $deleted)
|
<tbody>
|
||||||
<li class="list-group-item">
|
@forelse($deletedItems as $key => $deleted)
|
||||||
|
<tr>
|
||||||
|
<td>{{ $key + 1 }}</td>
|
||||||
|
<td>{{ $deleted->description }}</td>
|
||||||
|
<td>{{ $deleted->ctn }}</td>
|
||||||
|
<td>{{ $deleted->qty }}</td>
|
||||||
|
<td>{{ $deleted->ttl_qty }}</td>
|
||||||
|
<td>{{ $deleted->unit }}</td>
|
||||||
|
<td>{{ number_format($deleted->price, 2) }}</td>
|
||||||
|
<td>{{ number_format($deleted->ttl_amount, 2) }}</td>
|
||||||
|
<td>{{ $deleted->cbm }}</td>
|
||||||
|
<td>{{ $deleted->ttl_cbm }}</td>
|
||||||
|
<td>{{ $deleted->kg }}</td>
|
||||||
|
<td>{{ $deleted->ttl_kg }}</td>
|
||||||
|
<td>{{ $deleted->shop_no }}</td>
|
||||||
|
|
||||||
<div class="d-flex justify-content-between">
|
<td class="d-flex justify-content-center gap-2">
|
||||||
|
|
||||||
<div>
|
{{-- USE THIS ITEM --}}
|
||||||
<strong>{{ $deleted->description }}</strong><br>
|
<button type="button"
|
||||||
<small>
|
class="btn btn-sm btn-use-item"
|
||||||
CTN: {{ $deleted->ctn }},
|
onclick="fillFormFromDeleted({{ json_encode($deleted) }})">
|
||||||
QTY: {{ $deleted->qty }},
|
Use
|
||||||
TTL/QTY: {{ $deleted->ttl_qty }},
|
</button>
|
||||||
Unit: {{ $deleted->unit }},
|
|
||||||
Price: ₹{{ $deleted->price }},
|
|
||||||
TTL Amt: ₹{{ $deleted->ttl_amount }},
|
|
||||||
CBM: {{ $deleted->cbm }},
|
|
||||||
TTL CBM: {{ $deleted->ttl_cbm }},
|
|
||||||
KG: {{ $deleted->kg }},
|
|
||||||
TTL KG: {{ $deleted->ttl_kg }},
|
|
||||||
Shop: {{ $deleted->shop_no }}
|
|
||||||
</small>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="d-flex gap-2">
|
{{-- RESTORE ITEM --}}
|
||||||
|
<form action="{{ route('admin.orders.restoreItem', $deleted->id) }}" method="POST">
|
||||||
{{-- Auto-fill button --}}
|
@csrf
|
||||||
<button type="button" class="btn btn-sm btn-use-item"
|
<button type="button"
|
||||||
onclick="fillFormFromDeleted({{ json_encode($deleted) }})">
|
class="btn btn-sm btn-restore js-restore-item"
|
||||||
Use This
|
data-id="{{ $deleted->id }}"
|
||||||
|
data-url="{{ route('admin.orders.restoreItem', $deleted->id) }}">
|
||||||
|
Restore
|
||||||
</button>
|
</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
{{-- Restore --}}
|
</td>
|
||||||
<form action="{{ route('admin.orders.restoreItem', $deleted->id) }}" method="POST">
|
</tr>
|
||||||
@csrf
|
@empty
|
||||||
<button class="btn btn-sm btn-restore">Restore</button>
|
<tr>
|
||||||
</form>
|
<td colspan="14" class="text-muted">No deleted items.</td>
|
||||||
|
</tr>
|
||||||
|
@endforelse
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</li>
|
|
||||||
@empty
|
|
||||||
<li class="list-group-item text-muted">No deleted items.</li>
|
|
||||||
@endforelse
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
{{-- ADD FORM --}}
|
{{-- ADD FORM --}}
|
||||||
<div class="row g-3">
|
<div class="row g-3">
|
||||||
@@ -380,21 +538,62 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
|
const token = '{{ csrf_token() }}';
|
||||||
|
|
||||||
|
document.querySelectorAll('.js-restore-item').forEach(function (btn) {
|
||||||
|
btn.addEventListener('click', function () {
|
||||||
|
if (!confirm('Restore this item?')) return;
|
||||||
|
|
||||||
|
const url = this.dataset.url;
|
||||||
|
const row = this.closest('tr');
|
||||||
|
|
||||||
|
fetch(url, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'X-CSRF-TOKEN': token,
|
||||||
|
'X-Requested-With': 'XMLHttpRequest',
|
||||||
|
'Accept': 'application/json',
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify({})
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
if (!response.ok) throw new Error('Restore failed');
|
||||||
|
return response.json().catch(() => ({}));
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
row.remove();
|
||||||
|
location.reload(); // 🔥 refresh UI so restored item appears
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
alert('Could not restore item. Please try again.');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
{{-- AUTO-FILL SCRIPT --}}
|
{{-- AUTO-FILL SCRIPT --}}
|
||||||
<script>
|
<script>
|
||||||
function fillFormFromDeleted(item) {
|
function fillFormFromDeleted(item) {
|
||||||
document.querySelector('input[name="description"]').value = item.description;
|
let form = document.getElementById('addItemForm');
|
||||||
document.querySelector('input[name="ctn"]').value = item.ctn;
|
|
||||||
document.querySelector('input[name="qty"]').value = item.qty;
|
form.querySelector('input[name="description"]').value = item.description;
|
||||||
document.querySelector('input[name="ttl_qty"]').value = item.ttl_qty;
|
form.querySelector('input[name="ctn"]').value = item.ctn;
|
||||||
document.querySelector('input[name="unit"]').value = item.unit;
|
form.querySelector('input[name="qty"]').value = item.qty;
|
||||||
document.querySelector('input[name="price"]').value = item.price;
|
form.querySelector('input[name="ttl_qty"]').value = item.ttl_qty;
|
||||||
document.querySelector('input[name="ttl_amount"]').value = item.ttl_amount;
|
form.querySelector('input[name="unit"]').value = item.unit;
|
||||||
document.querySelector('input[name="cbm"]').value = item.cbm;
|
form.querySelector('input[name="price"]').value = item.price;
|
||||||
document.querySelector('input[name="ttl_cbm"]').value = item.ttl_cbm;
|
form.querySelector('input[name="ttl_amount"]').value = item.ttl_amount;
|
||||||
document.querySelector('input[name="kg"]').value = item.kg;
|
form.querySelector('input[name="cbm"]').value = item.cbm;
|
||||||
document.querySelector('input[name="ttl_kg"]').value = item.ttl_kg;
|
form.querySelector('input[name="ttl_cbm"]').value = item.ttl_cbm;
|
||||||
document.querySelector('input[name="shop_no"]').value = item.shop_no;
|
form.querySelector('input[name="kg"]').value = item.kg;
|
||||||
|
form.querySelector('input[name="ttl_kg"]').value = item.ttl_kg;
|
||||||
|
form.querySelector('input[name="shop_no"]').value = item.shop_no;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -404,13 +603,15 @@ function fillFormFromDeleted(item) {
|
|||||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
border: none;
|
border: none;
|
||||||
color: white;
|
color: white;
|
||||||
padding: 12px 24px;
|
padding: 6px 14px;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
font-size: 0.85rem;
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
box-shadow: 0 4px 15px 0 rgba(102, 126, 234, 0.3);
|
box-shadow: 0 4px 15px 0 rgba(102, 126, 234, 0.3);
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
margin-right: -800px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-add-item:hover {
|
.btn-add-item:hover {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
975
resources/views/admin/view-shipment.blade.php
Normal file
975
resources/views/admin/view-shipment.blade.php
Normal file
@@ -0,0 +1,975 @@
|
|||||||
|
@extends('admin.layouts.app')
|
||||||
|
|
||||||
|
@section('page-title', 'Shipment Details')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
|
||||||
|
<style>
|
||||||
|
/* ===== ANIMATIONS ===== */
|
||||||
|
.fade-in {
|
||||||
|
animation: fadeIn 0.6s ease-out;
|
||||||
|
}
|
||||||
|
@keyframes fadeIn {
|
||||||
|
from { opacity: 0; transform: translateY(10px); }
|
||||||
|
to { opacity: 1; transform: translateY(0px); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== CARD STYLES ===== */
|
||||||
|
.card {
|
||||||
|
border-radius: 20px;
|
||||||
|
background: #ffffff;
|
||||||
|
box-shadow: 0 15px 35px rgba(13, 38, 76, 0.08);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
||||||
|
box-shadow 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card:hover {
|
||||||
|
transform: translateY(-6px);
|
||||||
|
box-shadow: 0 20px 40px rgba(103, 126, 234, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-header h5 {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 800;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== GLASSMORPHISM BUTTON ===== */
|
||||||
|
.glass-btn {
|
||||||
|
background: linear-gradient(
|
||||||
|
135deg,
|
||||||
|
rgba(103, 126, 234, 0.25) 0%,
|
||||||
|
rgba(118, 75, 162, 0.25) 100%
|
||||||
|
);
|
||||||
|
backdrop-filter: blur(12px);
|
||||||
|
-webkit-backdrop-filter: blur(12px);
|
||||||
|
border: 1.5px solid rgba(255, 255, 255, 0.4);
|
||||||
|
color: #ffffff !important;
|
||||||
|
padding: 12px 24px;
|
||||||
|
border-radius: 14px;
|
||||||
|
font-weight: 700;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
box-shadow:
|
||||||
|
0 8px 32px rgba(103, 126, 234, 0.2),
|
||||||
|
inset 0 1px 0 rgba(255, 255, 255, 0.3),
|
||||||
|
inset 0 -1px 0 rgba(0, 0, 0, 0.1);
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glass-btn::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background: linear-gradient(
|
||||||
|
135deg,
|
||||||
|
rgba(103, 126, 234, 0.4) 0%,
|
||||||
|
rgba(118, 75, 162, 0.4) 100%
|
||||||
|
);
|
||||||
|
z-index: -1;
|
||||||
|
transition: opacity 0.4s ease;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glass-btn:hover {
|
||||||
|
transform: translateY(-4px) scale(1.05);
|
||||||
|
box-shadow:
|
||||||
|
0 15px 40px rgba(103, 126, 234, 0.35),
|
||||||
|
inset 0 1px 0 rgba(255, 255, 255, 0.4),
|
||||||
|
inset 0 -1px 0 rgba(0, 0, 0, 0.1);
|
||||||
|
border-color: rgba(255, 255, 255, 0.6);
|
||||||
|
background: linear-gradient(
|
||||||
|
135deg,
|
||||||
|
rgba(103, 126, 234, 0.15) 0%,
|
||||||
|
rgba(118, 75, 162, 0.15) 100%
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
.glass-btn:hover::before {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glass-btn:active {
|
||||||
|
transform: translateY(-1px) scale(0.98);
|
||||||
|
transition: transform 0.1s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glass-btn i {
|
||||||
|
font-size: 18px;
|
||||||
|
filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== HEADER STYLES ===== */
|
||||||
|
.card-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 16px;
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
color: #fff;
|
||||||
|
padding: 22px 28px;
|
||||||
|
border-radius: 20px 20px 0 0 !important;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-header::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background: linear-gradient(
|
||||||
|
to right,
|
||||||
|
rgba(255, 255, 255, 0.1) 0%,
|
||||||
|
rgba(255, 255, 255, 0.05) 100%
|
||||||
|
);
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-controls {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-cancel-btn {
|
||||||
|
background: rgba(255, 255, 255, 0.15);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
color: rgba(255, 255, 255, 0.95);
|
||||||
|
border: 1.5px solid rgba(255, 255, 255, 0.3);
|
||||||
|
padding: 10px 14px;
|
||||||
|
border-radius: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-cancel-btn:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.25);
|
||||||
|
border-color: rgba(255, 255, 255, 0.5);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== INFO BLOCKS ===== */
|
||||||
|
.shipment-info-box {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 24px;
|
||||||
|
margin-bottom: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shipment-info-item {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 220px;
|
||||||
|
background: linear-gradient(145deg, #ffffff, #f8fafc);
|
||||||
|
padding: 24px;
|
||||||
|
border-radius: 16px;
|
||||||
|
box-shadow:
|
||||||
|
0 5px 20px rgba(0, 0, 0, 0.05),
|
||||||
|
inset 0 1px 0 rgba(255, 255, 255, 0.8);
|
||||||
|
text-align: center;
|
||||||
|
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.8);
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shipment-info-item::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 4px;
|
||||||
|
background: linear-gradient(90deg, #667eea, #764ba2);
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.4s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shipment-info-item:hover {
|
||||||
|
transform: translateY(-6px);
|
||||||
|
box-shadow:
|
||||||
|
0 15px 35px rgba(103, 126, 234, 0.15),
|
||||||
|
inset 0 1px 0 rgba(255, 255, 255, 0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
.shipment-info-item:hover::before {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shipment-info-label {
|
||||||
|
color: #64748b;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
font-size: 14px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shipment-info-value {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 800;
|
||||||
|
color: #1e293b;
|
||||||
|
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== TOTAL BOXES ===== */
|
||||||
|
.total-box {
|
||||||
|
background: linear-gradient(145deg, #ffffff, #f8fafc);
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 16px;
|
||||||
|
box-shadow:
|
||||||
|
0 5px 20px rgba(0, 0, 0, 0.05),
|
||||||
|
inset 0 1px 0 rgba(255, 255, 255, 0.8);
|
||||||
|
text-align: center;
|
||||||
|
min-width: 160px;
|
||||||
|
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.8);
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.total-box::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 3px;
|
||||||
|
background: linear-gradient(90deg, #667eea, #764ba2);
|
||||||
|
transform: translateX(-100%);
|
||||||
|
transition: transform 0.4s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.total-box:hover {
|
||||||
|
transform: translateY(-5px) scale(1.03);
|
||||||
|
box-shadow:
|
||||||
|
0 15px 35px rgba(103, 126, 234, 0.15),
|
||||||
|
inset 0 1px 0 rgba(255, 255, 255, 0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
.total-box:hover::after {
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.total-title {
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #64748b;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.total-value {
|
||||||
|
font-size: 22px;
|
||||||
|
font-weight: 900;
|
||||||
|
color: #1e293b;
|
||||||
|
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== TABLE STYLES ===== */
|
||||||
|
.table {
|
||||||
|
border-collapse: separate;
|
||||||
|
border-spacing: 0;
|
||||||
|
border-radius: 16px;
|
||||||
|
overflow: hidden;
|
||||||
|
background: #ffffff;
|
||||||
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.table thead th {
|
||||||
|
background: #667eea ;
|
||||||
|
color: #ffffff;
|
||||||
|
font-weight: 700;
|
||||||
|
padding: 18px;
|
||||||
|
white-space: nowrap;
|
||||||
|
border: none;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table thead th::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 15px;
|
||||||
|
right: 15px;
|
||||||
|
height: 1px;
|
||||||
|
background: rgba(255, 255, 255, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.table tbody tr {
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
border-left: 3px solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table tbody tr:hover {
|
||||||
|
background: linear-gradient(90deg, rgba(103, 126, 234, 0.05), rgba(118, 75, 162, 0.05));
|
||||||
|
transform: translateX(4px);
|
||||||
|
border-left: 3px solid #667eea;
|
||||||
|
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.table tbody td {
|
||||||
|
padding: 16px;
|
||||||
|
vertical-align: middle;
|
||||||
|
white-space: nowrap;
|
||||||
|
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== GLASSMORPHISM MODAL ===== */
|
||||||
|
#newOrderModal .modal-content {
|
||||||
|
background: rgba(255, 255, 255, 0.95);
|
||||||
|
backdrop-filter: blur(20px) saturate(180%);
|
||||||
|
-webkit-backdrop-filter: blur(20px) saturate(180%);
|
||||||
|
border-radius: 24px;
|
||||||
|
border: 1.5px solid rgba(255, 255, 255, 0.3);
|
||||||
|
box-shadow:
|
||||||
|
0 25px 50px -12px rgba(0, 0, 0, 0.25),
|
||||||
|
inset 0 1px 0 rgba(255, 255, 255, 0.5);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#newOrderModal .modal-header {
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
border-bottom: 1px solid rgba(255, 255, 255, 0.3);
|
||||||
|
padding: 24px 32px;
|
||||||
|
border-radius: 24px 24px 0 0;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#newOrderModal .modal-header::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background: linear-gradient(
|
||||||
|
to right,
|
||||||
|
rgba(255, 255, 255, 0.1) 0%,
|
||||||
|
rgba(255, 255, 255, 0.05) 100%
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#newOrderModal .modal-title {
|
||||||
|
color: #ffffff;
|
||||||
|
font-weight: 800;
|
||||||
|
font-size: 22px;
|
||||||
|
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#newOrderModal .btn-close {
|
||||||
|
background: rgba(255, 255, 255, 0.2);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 8px;
|
||||||
|
opacity: 0.9;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#newOrderModal .btn-close:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.3);
|
||||||
|
opacity: 1;
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
#newOrderModal .modal-body {
|
||||||
|
background: rgba(248, 250, 252, 0.7);
|
||||||
|
padding: 32px;
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#newOrderModal .modal-footer {
|
||||||
|
background: rgba(255, 255, 255, 0.8);
|
||||||
|
border-top: 1px solid rgba(255, 255, 255, 0.4);
|
||||||
|
padding: 24px 32px;
|
||||||
|
border-radius: 0 0 24px 24px;
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#newOrderModal h6 {
|
||||||
|
color: #1e293b;
|
||||||
|
font-weight: 700;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
font-size: 16px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== ORDER LIST ITEMS ===== */
|
||||||
|
#availableOrdersList,
|
||||||
|
#deletedOrdersList {
|
||||||
|
max-height: 300px;
|
||||||
|
overflow-y: auto;
|
||||||
|
border-radius: 16px;
|
||||||
|
background: rgba(255, 255, 255, 0.6);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
border: 1.5px solid rgba(255, 255, 255, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-group-item {
|
||||||
|
background: rgba(255, 255, 255, 0.7);
|
||||||
|
border: 1.5px solid rgba(255, 255, 255, 0.4);
|
||||||
|
margin-bottom: 8px;
|
||||||
|
border-radius: 12px !important;
|
||||||
|
padding: 16px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-group-item:hover {
|
||||||
|
background: rgba(103, 126, 234, 0.1);
|
||||||
|
border-color: rgba(103, 126, 234, 0.3);
|
||||||
|
transform: translateX(4px);
|
||||||
|
box-shadow: 0 5px 15px rgba(103, 126, 234, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-group-item strong {
|
||||||
|
color: #1e293b;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-group-item .small {
|
||||||
|
color: #64748b;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.order-checkbox {
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
border-radius: 6px;
|
||||||
|
border: 2px solid #cbd5e1;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.order-checkbox:checked {
|
||||||
|
background: linear-gradient(135deg, #667eea, #764ba2);
|
||||||
|
border-color: #667eea;
|
||||||
|
box-shadow: 0 0 0 3px rgba(103, 126, 234, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== MODAL BUTTONS ===== */
|
||||||
|
#newOrderModal .btn-secondary {
|
||||||
|
background: rgba(100, 116, 139, 0.2);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
border: 1.5px solid rgba(100, 116, 139, 0.3);
|
||||||
|
color: #64748b;
|
||||||
|
padding: 12px 28px;
|
||||||
|
border-radius: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
#newOrderModal .btn-secondary:hover {
|
||||||
|
background: rgba(100, 116, 139, 0.3);
|
||||||
|
border-color: rgba(100, 116, 139, 0.5);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 6px 20px rgba(100, 116, 139, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#newOrderModal .btn-success {
|
||||||
|
background: linear-gradient(
|
||||||
|
135deg,
|
||||||
|
rgba(34, 197, 94, 0.25) 0%,
|
||||||
|
rgba(21, 128, 61, 0.25) 100%
|
||||||
|
);
|
||||||
|
backdrop-filter: blur(12px);
|
||||||
|
border: 1.5px solid rgba(34, 197, 94, 0.4);
|
||||||
|
color: #166534;
|
||||||
|
padding: 12px 28px;
|
||||||
|
border-radius: 12px;
|
||||||
|
font-weight: 700;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
box-shadow:
|
||||||
|
0 8px 25px rgba(34, 197, 94, 0.2),
|
||||||
|
inset 0 1px 0 rgba(255, 255, 255, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
#newOrderModal .btn-success:hover {
|
||||||
|
background: linear-gradient(
|
||||||
|
135deg,
|
||||||
|
rgba(34, 197, 94, 0.35) 0%,
|
||||||
|
rgba(21, 128, 61, 0.35) 100%
|
||||||
|
);
|
||||||
|
border-color: rgba(34, 197, 94, 0.6);
|
||||||
|
color: #14532d;
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow:
|
||||||
|
0 12px 30px rgba(34, 197, 94, 0.3),
|
||||||
|
inset 0 1px 0 rgba(255, 255, 255, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== SCROLLBAR STYLING ===== */
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-track {
|
||||||
|
background: rgba(0, 0, 0, 0.05);
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
background: linear-gradient(135deg, #667eea, #764ba2);
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: linear-gradient(135deg, #5a6fe8, #6a42a0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== ACTION BUTTONS ===== */
|
||||||
|
.btn-secondary {
|
||||||
|
background: linear-gradient(135deg, #94a3b8, #64748b);
|
||||||
|
border: none;
|
||||||
|
color: white;
|
||||||
|
padding: 12px 28px;
|
||||||
|
border-radius: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
box-shadow: 0 6px 20px rgba(100, 116, 139, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-secondary:hover {
|
||||||
|
background: linear-gradient(135deg, #8492a6, #565e6e);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 10px 25px rgba(100, 116, 139, 0.3);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== RESPONSIVE ADJUSTMENTS ===== */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.shipment-info-item,
|
||||||
|
.total-box {
|
||||||
|
min-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-header {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-controls {
|
||||||
|
width: 100%;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glass-btn {
|
||||||
|
padding: 10px 20px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="container-fluid py-4">
|
||||||
|
|
||||||
|
<div class="card mb-4">
|
||||||
|
<div class="card-header">
|
||||||
|
<div class="title-row">
|
||||||
|
<h5 class="mb-0"><i class="bi bi-truck me-2"></i>Shipment Details</h5>
|
||||||
|
<!-- <small class="text-white-50" style="margin-left:8px; font-weight:600;">{{ $shipment->shipment_id ?? '' }}</small> -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="header-controls">
|
||||||
|
<!-- Add Order button (top-right) with glass effect -->
|
||||||
|
@if($mode === 'edit' && $shipment->status === 'pending')
|
||||||
|
<a href="#" data-bs-toggle="modal" data-bs-target="#newOrderModal" class="glass-btn">
|
||||||
|
<i class="bi bi-plus-circle"></i> Add Order
|
||||||
|
</a>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<!-- Cancel/close: goes back to shipments list -->
|
||||||
|
<a href="{{ route('admin.shipments') }}" class="btn header-cancel-btn" title="Cancel / Back">
|
||||||
|
<i class="bi bi-x-lg"></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card-body">
|
||||||
|
|
||||||
|
<!-- ================================ -->
|
||||||
|
<!-- SHIPMENT MAIN DETAILS -->
|
||||||
|
<!-- ================================ -->
|
||||||
|
<div class="shipment-info-box">
|
||||||
|
|
||||||
|
<div class="shipment-info-item">
|
||||||
|
<div class="shipment-info-label">Shipment ID</div>
|
||||||
|
<div class="shipment-info-value">{{ $shipment->shipment_id }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="shipment-info-item">
|
||||||
|
<div class="shipment-info-label">Status</div>
|
||||||
|
<div class="shipment-info-value text-capitalize">
|
||||||
|
{{ str_replace('_', ' ', $shipment->status) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="shipment-info-item">
|
||||||
|
<div class="shipment-info-label">Shipment Date</div>
|
||||||
|
<div class="shipment-info-value">
|
||||||
|
{{ \Carbon\Carbon::parse($shipment->shipment_date)->format('d M Y') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="shipment-info-item">
|
||||||
|
<div class="shipment-info-label">Total Orders</div>
|
||||||
|
<div class="shipment-info-value">{{ $orders->count() }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ================================ -->
|
||||||
|
<!-- SHIPMENT TOTAL BLOCKS -->
|
||||||
|
<!-- ================================ -->
|
||||||
|
<h5 class="fw-bold mb-3 mt-4" style="color: #1e293b;">Shipment Summary</h5>
|
||||||
|
<div class="d-flex flex-wrap gap-3">
|
||||||
|
|
||||||
|
<div class="total-box">
|
||||||
|
<div class="total-title">TOTAL CTN</div>
|
||||||
|
<div class="total-value">{{ $shipment->total_ctn }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="total-box">
|
||||||
|
<div class="total-title">TOTAL QTY</div>
|
||||||
|
<div class="total-value">{{ $shipment->total_qty }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="total-box">
|
||||||
|
<div class="total-title">TOTAL CBM</div>
|
||||||
|
<div class="total-value">{{ $shipment->total_cbm }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="total-box">
|
||||||
|
<div class="total-title">TOTAL KG</div>
|
||||||
|
<div class="total-value">{{ $shipment->total_kg }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="total-box">
|
||||||
|
<div class="total-title">TOTAL TTL QTY</div>
|
||||||
|
<div class="total-value">{{ $shipment->total_ttl_qty }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="total-box">
|
||||||
|
<div class="total-title">TOTAL TTL CBM</div>
|
||||||
|
<div class="total-value">{{ $shipment->total_ttl_cbm }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="total-box">
|
||||||
|
<div class="total-title">TOTAL TTL KG</div>
|
||||||
|
<div class="total-value">{{ $shipment->total_ttl_kg }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="total-box">
|
||||||
|
<div class="total-title">TOTAL AMOUNT</div>
|
||||||
|
<div class="total-value text-success">
|
||||||
|
₹{{ number_format($shipment->total_amount, 2) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ================================ -->
|
||||||
|
<!-- ORDERS TABLE LIST -->
|
||||||
|
<!-- ================================ -->
|
||||||
|
<h5 class="fw-bold mb-3 mt-5" style="color: #1e293b;">Orders in This Shipment</h5>
|
||||||
|
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-bordered table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Order ID</th>
|
||||||
|
<th>Origin</th>
|
||||||
|
<th>Destination</th>
|
||||||
|
<th>CTN</th>
|
||||||
|
<th>QTY</th>
|
||||||
|
<th>TTL/QTY</th>
|
||||||
|
<th>CBM</th>
|
||||||
|
<th>TTL CBM</th>
|
||||||
|
<th>KG</th>
|
||||||
|
<th>TTL KG</th>
|
||||||
|
<th>Amount (₹)</th>
|
||||||
|
<!-- Conditionally show Delete column header -->
|
||||||
|
@if($mode === 'edit' && $shipment->status === 'pending')
|
||||||
|
<th>Delete</th>
|
||||||
|
@endif
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
@foreach($orders as $order)
|
||||||
|
<tr>
|
||||||
|
<td class="fw-bold text-primary">{{ $order->order_id }}</td>
|
||||||
|
<td>{{ $order->origin }}</td>
|
||||||
|
<td>{{ $order->destination }}</td>
|
||||||
|
<td>{{ $order->ctn }}</td>
|
||||||
|
<td>{{ $order->qty }}</td>
|
||||||
|
<td>{{ $order->ttl_qty }}</td>
|
||||||
|
<td>{{ $order->cbm }}</td>
|
||||||
|
<td>{{ $order->ttl_cbm }}</td>
|
||||||
|
<td>{{ $order->kg }}</td>
|
||||||
|
<td>{{ $order->ttl_kg }}</td>
|
||||||
|
<td class="fw-bold text-success">
|
||||||
|
₹{{ number_format($order->ttl_amount, 2) }}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<!-- Conditionally show Delete button -->
|
||||||
|
@if($mode === 'edit' && $shipment->status === 'pending')
|
||||||
|
<td>
|
||||||
|
<form method="POST" action="{{ route('admin.shipments.removeOrder') }}" onsubmit="return confirmDelete()">
|
||||||
|
@csrf
|
||||||
|
<input type="hidden" name="shipment_id" value="{{ $shipment->id }}">
|
||||||
|
<input type="hidden" name="order_id" value="{{ $order->id }}">
|
||||||
|
<button type="submit" class="btn btn-danger btn-sm" style="border-radius: 10px; padding: 8px 16px;">
|
||||||
|
<i class="bi bi-trash"></i> Delete
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
@endif
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Action Buttons -->
|
||||||
|
<div class="d-flex justify-content-between mt-4">
|
||||||
|
<!-- <a href="{{ route('admin.shipments') }}" class="btn btn-secondary">
|
||||||
|
<i class="bi bi-arrow-left"></i> Back to Shipments
|
||||||
|
</a>
|
||||||
|
-->
|
||||||
|
@if($mode === 'edit' && $shipment->status === 'pending')
|
||||||
|
<div>
|
||||||
|
<!-- <a href="{{ route('admin.shipments.view', ['id' => $shipment->id, 'mode' => 'edit']) }}"
|
||||||
|
class="btn btn-warning me-2">
|
||||||
|
<i class="bi bi-pencil"></i> Edit Shipment
|
||||||
|
</a> -->
|
||||||
|
|
||||||
|
<!-- <a href="{{ route('admin.shipments.view', ['id' => $shipment->id, 'mode' => 'view']) }}"
|
||||||
|
class="btn btn-info">
|
||||||
|
<i class="bi bi-eye"></i> View Mode
|
||||||
|
</a> -->
|
||||||
|
</div>
|
||||||
|
@elseif($shipment->status === 'pending')
|
||||||
|
<div>
|
||||||
|
<!-- <a href="{{ route('admin.shipments.view', ['id' => $shipment->id, 'mode' => 'edit']) }}"
|
||||||
|
class="btn btn-primary">
|
||||||
|
<i class="bi bi-pencil"></i> Edit Shipment
|
||||||
|
</a> -->
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- New Order Modal -->
|
||||||
|
<div class="modal fade" id="newOrderModal" tabindex="-1" aria-labelledby="newOrderModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-xl modal-dialog-scrollable">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title" id="newOrderModalLabel">Add Orders to Shipment</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<h6>Deleted Orders (recently removed)</h6>
|
||||||
|
<div id="deletedOrdersList" class="list-group"></div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<h6>Available Orders</h6>
|
||||||
|
<div id="availableOrdersList" class="list-group"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-3">
|
||||||
|
<small class="text-muted">Select orders to add back to this shipment, then click "Add Selected".</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
||||||
|
<button id="addSelectedOrdersBtn" type="button" class="btn btn-success">Add Selected</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function confirmDelete() {
|
||||||
|
return confirm('Are you sure you want to remove this order from the shipment?');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
|
const csrfToken = '{{ csrf_token() }}';
|
||||||
|
const shipmentId = {{ $shipment->id }};
|
||||||
|
let availableOrders = @json($availableOrders ?? []);
|
||||||
|
let deletedOrders = [];
|
||||||
|
|
||||||
|
function renderOrdersList(containerId, orders) {
|
||||||
|
const container = document.getElementById(containerId);
|
||||||
|
container.innerHTML = '';
|
||||||
|
if (!orders.length) {
|
||||||
|
container.innerHTML = '<div class="text-muted py-3">No orders</div>';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
orders.forEach(order => {
|
||||||
|
const item = document.createElement('label');
|
||||||
|
item.className = 'list-group-item d-flex justify-content-between align-items-center';
|
||||||
|
item.innerHTML = `
|
||||||
|
<div>
|
||||||
|
<input type="checkbox" class="me-2 order-checkbox" data-order='${JSON.stringify(order)}'>
|
||||||
|
<strong>${order.order_id}</strong>
|
||||||
|
<div class="small text-muted"> ${order.origin} → ${order.destination} • ${order.qty} qty • ₹${parseFloat(order.ttl_amount).toLocaleString('en-IN', {minimumFractionDigits:2})}</div>
|
||||||
|
</div>
|
||||||
|
<div class="small text-muted">ID: ${order.id}</div>
|
||||||
|
`;
|
||||||
|
container.appendChild(item);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
renderOrdersList('availableOrdersList', availableOrders);
|
||||||
|
renderOrdersList('deletedOrdersList', deletedOrders);
|
||||||
|
|
||||||
|
// Intercept remove-order forms (update selector if form action different)
|
||||||
|
document.querySelectorAll('form[action="{{ route('admin.shipments.removeOrder') }}"]').forEach(form => {
|
||||||
|
form.addEventListener('submit', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
if (!confirm('Are you sure you want to remove this order from the shipment?')) return;
|
||||||
|
|
||||||
|
const formData = new FormData(this);
|
||||||
|
|
||||||
|
fetch(this.action, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json'},
|
||||||
|
body: formData
|
||||||
|
})
|
||||||
|
.then(res => res.json())
|
||||||
|
.then(data => {
|
||||||
|
if (!data.success) { alert(data.message || 'Failed'); return; }
|
||||||
|
|
||||||
|
// Remove row from DOM
|
||||||
|
const row = this.closest('tr');
|
||||||
|
// Build deleted order object from row cells if present
|
||||||
|
const orderObj = {
|
||||||
|
id: formData.get('order_id'),
|
||||||
|
order_id: row ? row.querySelector('td:first-child')?.innerText.trim() : ('Order-'+formData.get('order_id')),
|
||||||
|
origin: row ? row.cells[1]?.innerText.trim() : '',
|
||||||
|
destination: row ? row.cells[2]?.innerText.trim() : '',
|
||||||
|
qty: row ? row.cells[4]?.innerText.trim() : '',
|
||||||
|
ttl_amount: row ? row.cells[10]?.innerText.replace('₹','').replace(',','').trim() : 0
|
||||||
|
};
|
||||||
|
|
||||||
|
if (row) row.remove();
|
||||||
|
|
||||||
|
deletedOrders.unshift(orderObj);
|
||||||
|
renderOrdersList('deletedOrdersList', deletedOrders);
|
||||||
|
|
||||||
|
// Optional: update totals by refetching shipment summary endpoint or reload
|
||||||
|
if (data.shipment) updateTotalsInDOM(data.shipment);
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
alert('Remove failed.');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Open modal from add-order button
|
||||||
|
document.querySelectorAll('.glass-btn').forEach(btn => {
|
||||||
|
btn.addEventListener('click', function(e) {
|
||||||
|
renderOrdersList('availableOrdersList', availableOrders);
|
||||||
|
renderOrdersList('deletedOrdersList', deletedOrders);
|
||||||
|
const modal = new bootstrap.Modal(document.getElementById('newOrderModal'));
|
||||||
|
modal.show();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add selected orders
|
||||||
|
document.getElementById('addSelectedOrdersBtn').addEventListener('click', function() {
|
||||||
|
const checked = Array.from(document.querySelectorAll('.order-checkbox:checked'));
|
||||||
|
if (!checked.length) { alert('Please select orders'); return; }
|
||||||
|
|
||||||
|
const orderIds = checked.map(cb => JSON.parse(cb.getAttribute('data-order')).id);
|
||||||
|
|
||||||
|
fetch(`/admin/shipments/${shipmentId}/add-orders`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json'},
|
||||||
|
body: JSON.stringify({ order_ids: orderIds })
|
||||||
|
})
|
||||||
|
.then(r => r.json())
|
||||||
|
.then(data => {
|
||||||
|
if (!data.success) { alert(data.message || 'Failed'); return; }
|
||||||
|
|
||||||
|
// Update orders table — simplest approach: reload page to reflect DB
|
||||||
|
// But we can also append rows from data.orders (if provided)
|
||||||
|
location.reload();
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
alert('Add failed.');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function updateTotalsInDOM(shipment) {
|
||||||
|
try {
|
||||||
|
if (document.getElementById('total_qty')) {
|
||||||
|
document.getElementById('total_qty').innerText = shipment.total_qty;
|
||||||
|
}
|
||||||
|
if (document.getElementById('total_amount')) {
|
||||||
|
document.getElementById('total_amount').innerText = '₹' + parseFloat(shipment.total_amount).toLocaleString('en-IN', {minimumFractionDigits:2});
|
||||||
|
}
|
||||||
|
// add other totals similarly...
|
||||||
|
} catch(e) { console.warn(e); }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
document.addEventListener('hidden.bs.modal', function (event) {
|
||||||
|
document.body.classList.remove('modal-open');
|
||||||
|
let backdrop = document.querySelector('.modal-backdrop');
|
||||||
|
if (backdrop) backdrop.remove();
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
@endsection
|
||||||
263
routes/web.php
263
routes/web.php
@@ -66,207 +66,211 @@ Route::prefix('admin')
|
|||||||
// ---------------------------
|
// ---------------------------
|
||||||
// USER REQUESTS
|
// USER REQUESTS
|
||||||
// ---------------------------
|
// ---------------------------
|
||||||
Route::get('/requests', [UserRequestController::class, 'index'])
|
Route::get('/requests', [UserRequestController::class, 'index'])
|
||||||
->name('admin.requests');
|
->name('admin.requests');
|
||||||
|
|
||||||
Route::get('/requests/approve/{id}', [UserRequestController::class, 'approve'])
|
Route::get('/requests/approve/{id}', [UserRequestController::class, 'approve'])
|
||||||
->name('admin.requests.approve');
|
->name('admin.requests.approve');
|
||||||
|
|
||||||
Route::get('/requests/reject/{id}', [UserRequestController::class, 'reject'])
|
Route::get('/requests/reject/{id}', [UserRequestController::class, 'reject'])
|
||||||
->name('admin.requests.reject');
|
->name('admin.requests.reject');
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------
|
// ---------------------------
|
||||||
// MARK LIST
|
// MARK LIST
|
||||||
// ---------------------------
|
// ---------------------------
|
||||||
Route::get('/mark-list', [AdminMarkListController::class, 'index'])
|
Route::get('/mark-list', [AdminMarkListController::class, 'index'])
|
||||||
->name('admin.marklist.index');
|
->name('admin.marklist.index');
|
||||||
|
|
||||||
Route::get('/mark-list/status/{id}', [AdminMarkListController::class, 'toggleStatus'])
|
Route::get('/mark-list/status/{id}', [AdminMarkListController::class, 'toggleStatus'])
|
||||||
->name('admin.marklist.toggle');
|
->name('admin.marklist.toggle');
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------
|
// ---------------------------
|
||||||
// ORDERS
|
// ORDERS
|
||||||
// ---------------------------
|
// ---------------------------
|
||||||
Route::get('/orders', [AdminOrderController::class, 'orderShow'])
|
Route::get('/orders', [AdminOrderController::class, 'orderShow'])
|
||||||
->name('admin.orders');
|
->name('admin.orders');
|
||||||
|
|
||||||
|
|
||||||
Route::get('/orders/list', [AdminOrderController::class, 'index'])
|
Route::get('/orders/list', [AdminOrderController::class, 'index'])
|
||||||
->name('admin.orders.index');
|
->name('admin.orders.index');
|
||||||
|
|
||||||
Route::get('/orders/{id}', [AdminOrderController::class, 'show'])
|
Route::get('/orders/{id}', [AdminOrderController::class, 'show'])
|
||||||
->name('admin.orders.show');
|
->name('admin.orders.show');
|
||||||
|
|
||||||
Route::post('/orders/temp/add', [AdminOrderController::class, 'addTempItem'])
|
Route::post('/orders/temp/add', [AdminOrderController::class, 'addTempItem'])
|
||||||
->name('admin.orders.temp.add');
|
->name('admin.orders.temp.add');
|
||||||
|
|
||||||
Route::post('/orders/temp/delete', [AdminOrderController::class, 'deleteTempItem'])
|
Route::post('/orders/temp/delete', [AdminOrderController::class, 'deleteTempItem'])
|
||||||
->name('admin.orders.temp.delete');
|
->name('admin.orders.temp.delete');
|
||||||
|
|
||||||
Route::post('/orders/temp/reset', [AdminOrderController::class, 'resetTemp'])
|
Route::post('/orders/temp/reset', [AdminOrderController::class, 'resetTemp'])
|
||||||
->name('admin.orders.temp.reset');
|
->name('admin.orders.temp.reset');
|
||||||
|
|
||||||
Route::post('/orders/finish', [AdminOrderController::class, 'finishOrder'])
|
Route::post('/orders/finish', [AdminOrderController::class, 'finishOrder'])
|
||||||
->name('admin.orders.finish');
|
->name('admin.orders.finish');
|
||||||
|
|
||||||
Route::get('/orders/view/{id}', [AdminOrderController::class, 'popup'])
|
Route::get('/orders/view/{id}', [AdminOrderController::class, 'popup'])
|
||||||
->name('admin.orders.popup');
|
->name('admin.orders.popup');
|
||||||
|
|
||||||
// ---------------------------
|
// ---------------------------
|
||||||
// ORDERS (FIXED ROUTES)
|
// ORDERS (FIXED ROUTES)
|
||||||
// ---------------------------
|
// ---------------------------
|
||||||
|
|
||||||
// Add item to order
|
// Add item to order
|
||||||
Route::post('/orders/{order}/item', [AdminOrderController::class, 'addItem'])
|
Route::post('/orders/{order}/item', [AdminOrderController::class, 'addItem'])
|
||||||
->name('admin.orders.addItem');
|
->name('admin.orders.addItem');
|
||||||
|
|
||||||
// Delete item from order
|
// Delete item from order
|
||||||
Route::delete('/orders/item/{id}', [AdminOrderController::class, 'deleteItem'])
|
Route::delete('/orders/item/{id}', [AdminOrderController::class, 'deleteItem'])
|
||||||
->name('admin.orders.deleteItem');
|
->name('admin.orders.deleteItem');
|
||||||
|
|
||||||
// Restore deleted item
|
// Restore deleted item
|
||||||
Route::post('/orders/item/{id}/restore', [AdminOrderController::class, 'restoreItem'])
|
Route::post('/orders/item/{id}/restore', [AdminOrderController::class, 'restoreItem'])
|
||||||
->name('admin.orders.restoreItem');
|
->name('admin.orders.restoreItem');
|
||||||
|
|
||||||
// Update main order fields
|
// Update main order fields
|
||||||
Route::post('/orders/{id}/update', [AdminOrderController::class, 'update'])
|
Route::put('/admin/orders/item/update/{id}', [AdminOrderController::class, 'updateItem'])
|
||||||
->name('admin.orders.update');
|
->name('admin.orders.updateItem');
|
||||||
|
|
||||||
// Delete full order
|
// Delete full order
|
||||||
Route::delete('/orders/{id}/delete', [AdminOrderController::class, 'destroy'])
|
Route::delete('/orders/{id}/delete', [AdminOrderController::class, 'destroy'])
|
||||||
->name('admin.orders.destroy');
|
->name('admin.orders.destroy');
|
||||||
|
|
||||||
// ---------------------------
|
// ---------------------------
|
||||||
// SHIPMENTS (FIXED ROUTES)
|
// SHIPMENTS (FIXED ROUTES)
|
||||||
// ---------------------------
|
// ---------------------------
|
||||||
Route::get('/shipments', [ShipmentController::class, 'index'])
|
|
||||||
->name('admin.shipments');
|
|
||||||
|
|
||||||
Route::post('/shipments', [ShipmentController::class, 'store'])
|
// View shipment MUST be before /shipments/{id}
|
||||||
->name('admin.shipments.store');
|
Route::get('/shipments/view/{id}', [ShipmentController::class, 'show'])
|
||||||
|
->name('admin.shipments.view');
|
||||||
|
|
||||||
Route::post('/shipments/update-status', [ShipmentController::class, 'updateStatus'])
|
// List shipments
|
||||||
->name('admin.shipments.updateStatus');
|
Route::get('/shipments', [ShipmentController::class, 'index'])
|
||||||
|
->name('admin.shipments');
|
||||||
|
|
||||||
// Get shipment orders for modal (AJAX)
|
// Create shipment
|
||||||
Route::get('/shipments/{id}/orders', [ShipmentController::class, 'getShipmentOrders'])
|
Route::post('/shipments', [ShipmentController::class, 'store'])
|
||||||
->name('admin.shipments.orders');
|
->name('admin.shipments.store');
|
||||||
|
|
||||||
// Get shipment details for edit (AJAX)
|
// Update status
|
||||||
Route::get('/shipments/{id}', [ShipmentController::class, 'show'])
|
Route::post('/shipments/update-status', [ShipmentController::class, 'updateStatus'])
|
||||||
->name('admin.shipments.show');
|
->name('admin.shipments.updateStatus');
|
||||||
|
|
||||||
// Shipment Update
|
// Shipment orders (AJAX)
|
||||||
Route::put('/shipments/{id}', [ShipmentController::class, 'update'])
|
Route::get('/shipments/{id}/orders', [ShipmentController::class, 'getShipmentOrders'])
|
||||||
->name('admin.shipments.update');
|
->name('admin.shipments.orders');
|
||||||
|
|
||||||
// Shipment Delete
|
// Shipment update
|
||||||
Route::delete('/shipments/{id}', [ShipmentController::class, 'destroy'])
|
Route::put('/shipments/{id}', [ShipmentController::class, 'update'])
|
||||||
->name('admin.shipments.destroy');
|
->name('admin.shipments.update');
|
||||||
|
|
||||||
|
// Shipment delete
|
||||||
|
Route::delete('/shipments/{id}', [ShipmentController::class, 'destroy'])
|
||||||
|
->name('admin.shipments.destroy');
|
||||||
|
|
||||||
|
// Remove order
|
||||||
|
Route::post('/shipments/remove-order', [ShipmentController::class, 'removeOrder'])
|
||||||
|
->name('admin.shipments.removeOrder');
|
||||||
|
|
||||||
|
Route::post('/shipments/add-order', [ShipmentController::class, 'addOrder'])
|
||||||
|
->name('admin.shipments.addOrder');
|
||||||
|
|
||||||
|
Route::post('/shipments/{id}/add-orders', [ShipmentController::class, 'addOrders'])
|
||||||
|
->name('admin.shipments.addOrders');
|
||||||
// ---------------------------
|
// ---------------------------
|
||||||
// INVOICES
|
// INVOICES
|
||||||
// ---------------------------
|
// ---------------------------
|
||||||
Route::get('/invoices', [AdminInvoiceController::class, 'index'])
|
Route::get('/invoices', [AdminInvoiceController::class, 'index'])
|
||||||
->name('admin.invoices.index');
|
->name('admin.invoices.index');
|
||||||
|
|
||||||
Route::get('/invoices/{id}/popup', [AdminInvoiceController::class, 'popup'])
|
Route::get('/invoices/{id}/popup', [AdminInvoiceController::class, 'popup'])
|
||||||
->name('admin.invoices.popup');
|
->name('admin.invoices.popup');
|
||||||
|
|
||||||
Route::get('/invoices/{id}/edit', [AdminInvoiceController::class, 'edit'])
|
Route::get('/invoices/{id}/edit', [AdminInvoiceController::class, 'edit'])
|
||||||
->name('admin.invoices.edit');
|
->name('admin.invoices.edit');
|
||||||
|
|
||||||
Route::post('/invoices/{id}/update', [AdminInvoiceController::class, 'update'])
|
Route::post('/invoices/{id}/update', [AdminInvoiceController::class, 'update'])
|
||||||
->name('admin.invoices.update');
|
->name('admin.invoices.update');
|
||||||
|
|
||||||
Route::post('/invoices/{invoice}/installments', [AdminInvoiceController::class, 'storeInstallment'])
|
Route::post('/invoices/{invoice}/installments', [AdminInvoiceController::class, 'storeInstallment'])
|
||||||
|
->name('admin.invoice.installment.store');
|
||||||
|
|
||||||
|
Route::post('/invoices/{id}/installment', [AdminInvoiceController::class, 'storeInstallment'])
|
||||||
->name('admin.invoice.installment.store');
|
->name('admin.invoice.installment.store');
|
||||||
|
|
||||||
Route::post('/invoices/{id}/installment', [AdminInvoiceController::class, 'storeInstallment'])
|
Route::delete('/installment/{id}', [AdminInvoiceController::class, 'deleteInstallment'])
|
||||||
->name('admin.invoice.installment.store');
|
->name('admin.invoice.installment.delete');
|
||||||
|
|
||||||
Route::delete('/installment/{id}', [AdminInvoiceController::class, 'deleteInstallment'])
|
|
||||||
->name('admin.invoice.installment.delete');
|
|
||||||
|
|
||||||
|
|
||||||
|
//Add New Invoice
|
||||||
|
Route::get('/admin/invoices/create', [InvoiceController::class, 'create'])->name('admin.invoices.create');
|
||||||
//Add New Invoice
|
|
||||||
Route::get('/admin/invoices/create', [InvoiceController::class, 'create'])->name('admin.invoices.create');
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------
|
// ---------------------------
|
||||||
// CUSTOMERS
|
// CUSTOMERS
|
||||||
// ---------------------------
|
// ---------------------------
|
||||||
Route::get('/customers', [AdminCustomerController::class, 'index'])
|
Route::get('/customers', [AdminCustomerController::class, 'index'])
|
||||||
->name('admin.customers.index');
|
->name('admin.customers.index');
|
||||||
|
|
||||||
Route::get('/customers/add', [AdminCustomerController::class, 'create'])
|
Route::get('/customers/add', [AdminCustomerController::class, 'create'])
|
||||||
->name('admin.customers.add');
|
->name('admin.customers.add');
|
||||||
|
|
||||||
Route::post('/customers/store', [AdminCustomerController::class, 'store'])
|
Route::post('/customers/store', [AdminCustomerController::class, 'store'])
|
||||||
->name('admin.customers.store');
|
->name('admin.customers.store');
|
||||||
|
|
||||||
Route::get('/customers/{id}/view', [AdminCustomerController::class, 'view'])
|
Route::get('/customers/{id}/view', [AdminCustomerController::class, 'view'])
|
||||||
->name('admin.customers.view');
|
->name('admin.customers.view');
|
||||||
|
|
||||||
Route::post('/customers/{id}/status', [AdminCustomerController::class, 'toggleStatus'])
|
Route::post('/customers/{id}/status', [AdminCustomerController::class, 'toggleStatus'])
|
||||||
->name('admin.customers.status');
|
->name('admin.customers.status');
|
||||||
});
|
});
|
||||||
|
|
||||||
// ==========================================
|
// ==========================================
|
||||||
// ADMIN ACCOUNT (AJAX) ROUTES
|
// ADMIN ACCOUNT (AJAX) ROUTES
|
||||||
// ==========================================
|
// ==========================================
|
||||||
Route::prefix('admin/account')
|
Route::prefix('admin/account')
|
||||||
->middleware('auth:admin')
|
->middleware('auth:admin')
|
||||||
->name('admin.account.')
|
->name('admin.account.')
|
||||||
->group(function () {
|
->group(function () {
|
||||||
|
|
||||||
Route::get('/dashboard', [AdminAccountController::class, 'getDashboardData'])
|
|
||||||
->name('dashboard');
|
|
||||||
|
|
||||||
Route::get('/available-orders', [AdminAccountController::class, 'getAvailableOrders'])
|
|
||||||
->name('orders.available');
|
|
||||||
|
|
||||||
Route::post('/create-order', [AdminAccountController::class, 'accountCreateOrder'])
|
|
||||||
->name('create');
|
|
||||||
|
|
||||||
Route::post('/toggle-payment', [AdminAccountController::class, 'togglePayment'])
|
|
||||||
->name('toggle');
|
|
||||||
|
|
||||||
Route::post('/installment/create', [AdminAccountController::class, 'addInstallment'])
|
|
||||||
->name('installment.create');
|
|
||||||
|
|
||||||
Route::post('/installment/update-status', [AdminAccountController::class, 'updateInstallmentStatus'])
|
|
||||||
->name('installment.update');
|
|
||||||
|
|
||||||
Route::get('/entry/{entry_no}', [AdminAccountController::class, 'getEntryDetails'])
|
|
||||||
->name('entry.details');
|
|
||||||
|
|
||||||
// ⬇⬇ NEW ROUTES FOR EDIT + DELETE ⬇⬇
|
|
||||||
Route::post('/update-entry', [AdminAccountController::class, 'updateEntry'])
|
|
||||||
->name('update.entry');
|
|
||||||
|
|
||||||
Route::post('/delete-entry', [AdminAccountController::class, 'deleteEntry'])
|
|
||||||
->name('delete.entry');
|
|
||||||
|
|
||||||
|
|
||||||
// ===== Associated Orders Routes (EDIT MODAL साठी) =====
|
|
||||||
Route::post('/add-orders-to-entry', [AdminAccountController::class, 'addOrdersToEntry'])
|
|
||||||
->name('add.orders.to.entry');
|
|
||||||
|
|
||||||
Route::get('/entry-orders/{entry_no}', [AdminAccountController::class, 'getEntryOrders'])
|
Route::get('/dashboard', [AdminAccountController::class, 'getDashboardData'])
|
||||||
->name('entry.orders');
|
->name('dashboard');
|
||||||
|
|
||||||
Route::post('/remove-order-from-entry', [AdminAccountController::class, 'removeOrderFromEntry'])
|
Route::get('/available-orders', [AdminAccountController::class, 'getAvailableOrders'])
|
||||||
->name('remove.order.from.entry');
|
->name('orders.available');
|
||||||
|
|
||||||
|
Route::post('/create-order', [AdminAccountController::class, 'accountCreateOrder'])
|
||||||
|
->name('create');
|
||||||
|
|
||||||
|
Route::post('/toggle-payment', [AdminAccountController::class, 'togglePayment'])
|
||||||
|
->name('toggle');
|
||||||
|
|
||||||
|
Route::post('/installment/create', [AdminAccountController::class, 'addInstallment'])
|
||||||
|
->name('installment.create');
|
||||||
|
|
||||||
|
Route::post('/installment/update-status', [AdminAccountController::class, 'updateInstallmentStatus'])
|
||||||
|
->name('installment.update');
|
||||||
|
|
||||||
|
Route::get('/entry/{entry_no}', [AdminAccountController::class, 'getEntryDetails'])
|
||||||
|
->name('entry.details');
|
||||||
|
|
||||||
|
// ⬇⬇ NEW ROUTES FOR EDIT + DELETE ⬇⬇
|
||||||
|
Route::post('/update-entry', [AdminAccountController::class, 'updateEntry'])
|
||||||
|
->name('update.entry');
|
||||||
|
|
||||||
|
Route::post('/delete-entry', [AdminAccountController::class, 'deleteEntry'])
|
||||||
|
->name('delete.entry');
|
||||||
|
|
||||||
|
|
||||||
|
// ===== Associated Orders Routes (EDIT MODAL साठी) =====
|
||||||
|
Route::post('/add-orders-to-entry', [AdminAccountController::class, 'addOrdersToEntry'])
|
||||||
|
->name('add.orders.to.entry');
|
||||||
|
|
||||||
});
|
Route::get('/entry-orders/{entry_no}', [AdminAccountController::class, 'getEntryOrders'])
|
||||||
|
->name('entry.orders');
|
||||||
|
|
||||||
|
Route::post('/remove-order-from-entry', [AdminAccountController::class, 'removeOrderFromEntry'])
|
||||||
|
->name('remove.order.from.entry');
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -274,11 +278,10 @@ Route::prefix('admin')
|
|||||||
// ---------------------------
|
// ---------------------------
|
||||||
// REPORTS DOWNLOAD ROUTES
|
// REPORTS DOWNLOAD ROUTES
|
||||||
// ---------------------------
|
// ---------------------------
|
||||||
Route::get('/admin/orders/download/pdf', [OrderController::class, 'downloadPdf'])->name('admin.orders.download.pdf');
|
Route::get('/admin/orders/download/pdf', [OrderController::class, 'downloadPdf'])->name('admin.orders.download.pdf');
|
||||||
Route::get('/admin/orders/download/excel', [OrderController::class, 'downloadExcel'])->name('admin.orders.download.excel');
|
Route::get('/admin/orders/download/excel', [OrderController::class, 'downloadExcel'])->name('admin.orders.download.excel');
|
||||||
|
|
||||||
//---------------------------
|
//---------------------------
|
||||||
//Edit Button Route
|
//Edit Button Route
|
||||||
//---------------------------
|
//---------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user