2025-11-12 11:56:43 +05:30
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace App\Http\Controllers\Admin;
|
|
|
|
|
|
|
|
|
|
use App\Http\Controllers\Controller;
|
|
|
|
|
use Illuminate\Http\Request;
|
|
|
|
|
use App\Models\Order;
|
2025-11-13 13:05:17 +05:30
|
|
|
use App\Models\OrderItem;
|
|
|
|
|
use App\Models\MarkList;
|
2025-12-01 10:38:52 +05:30
|
|
|
use App\Models\Invoice;
|
|
|
|
|
use App\Models\InvoiceItem;
|
|
|
|
|
use App\Models\User;
|
2025-11-12 11:56:43 +05:30
|
|
|
|
|
|
|
|
class AdminOrderController extends Controller
|
|
|
|
|
{
|
2025-12-01 10:38:52 +05:30
|
|
|
// ---------------------------
|
|
|
|
|
// LIST / DASHBOARD
|
|
|
|
|
// ---------------------------
|
2025-11-12 11:56:43 +05:30
|
|
|
public function index()
|
|
|
|
|
{
|
2025-12-01 10:38:52 +05:30
|
|
|
// raw list for admin dashboard (simple)
|
2025-11-12 11:56:43 +05:30
|
|
|
$orders = Order::latest()->get();
|
2025-11-13 13:05:17 +05:30
|
|
|
$markList = MarkList::where('status', 'active')->get();
|
2025-11-12 11:56:43 +05:30
|
|
|
|
|
|
|
|
return view('admin.dashboard', compact('orders', 'markList'));
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
/**
|
|
|
|
|
* Orders list (detailed)
|
|
|
|
|
*/
|
|
|
|
|
public function orderShow()
|
|
|
|
|
{
|
|
|
|
|
$orders = Order::with(['markList', 'shipments', 'invoice'])
|
|
|
|
|
->latest('id')
|
|
|
|
|
->get();
|
|
|
|
|
|
|
|
|
|
return view('admin.orders', compact('orders'));
|
|
|
|
|
}
|
2025-11-12 11:56:43 +05:30
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
// ---------------------------
|
|
|
|
|
// CREATE NEW ORDER (simple DB flow)
|
|
|
|
|
// ---------------------------
|
|
|
|
|
/**
|
|
|
|
|
* Show create form (you can place create UI on separate view or dashboard)
|
|
|
|
|
*/
|
|
|
|
|
public function create()
|
2025-11-13 13:05:17 +05:30
|
|
|
{
|
2025-12-01 10:38:52 +05:30
|
|
|
// return a dedicated create view - create it at resources/views/admin/orders_create.blade.php
|
|
|
|
|
// If you prefer create UI on dashboard, change this to redirect route('admin.orders.index') etc.
|
|
|
|
|
$markList = MarkList::where('status', 'active')->get();
|
|
|
|
|
return view('admin.orders_create', compact('markList'));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Store a new order and optionally create initial invoice
|
|
|
|
|
*/
|
|
|
|
|
public function store(Request $request)
|
|
|
|
|
{
|
|
|
|
|
$data = $request->validate([
|
|
|
|
|
'mark_no' => 'required|string',
|
|
|
|
|
'origin' => 'nullable|string',
|
|
|
|
|
'destination' => 'nullable|string',
|
|
|
|
|
// totals optional when creating without items
|
2025-11-13 13:05:17 +05:30
|
|
|
'ctn' => 'nullable|numeric',
|
|
|
|
|
'qty' => 'nullable|numeric',
|
|
|
|
|
'ttl_qty' => 'nullable|numeric',
|
|
|
|
|
'ttl_amount' => 'nullable|numeric',
|
|
|
|
|
'cbm' => 'nullable|numeric',
|
|
|
|
|
'ttl_cbm' => 'nullable|numeric',
|
|
|
|
|
'kg' => 'nullable|numeric',
|
|
|
|
|
'ttl_kg' => 'nullable|numeric',
|
|
|
|
|
]);
|
|
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
$order = Order::create([
|
|
|
|
|
'order_id' => $this->generateOrderId(),
|
|
|
|
|
'mark_no' => $data['mark_no'],
|
|
|
|
|
'origin' => $data['origin'] ?? null,
|
|
|
|
|
'destination' => $data['destination'] ?? null,
|
|
|
|
|
'ctn' => $data['ctn'] ?? 0,
|
|
|
|
|
'qty' => $data['qty'] ?? 0,
|
|
|
|
|
'ttl_qty' => $data['ttl_qty'] ?? 0,
|
|
|
|
|
'ttl_amount' => $data['ttl_amount'] ?? 0,
|
|
|
|
|
'cbm' => $data['cbm'] ?? 0,
|
|
|
|
|
'ttl_cbm' => $data['ttl_cbm'] ?? 0,
|
|
|
|
|
'kg' => $data['kg'] ?? 0,
|
|
|
|
|
'ttl_kg' => $data['ttl_kg'] ?? 0,
|
|
|
|
|
'status' => 'pending',
|
|
|
|
|
]);
|
2025-11-13 13:05:17 +05:30
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
// If you want to auto-create an invoice at order creation, uncomment:
|
|
|
|
|
// $this->createInvoice($order);
|
2025-11-13 13:05:17 +05:30
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
return redirect()->route('admin.orders.show', $order->id)
|
|
|
|
|
->with('success', 'Order created successfully.');
|
|
|
|
|
}
|
2025-11-13 13:05:17 +05:30
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
// ---------------------------
|
|
|
|
|
// SHOW / POPUP
|
|
|
|
|
// ---------------------------
|
|
|
|
|
public function show($id)
|
|
|
|
|
{
|
|
|
|
|
$order = Order::with('items', 'markList')->findOrFail($id);
|
|
|
|
|
$user = $this->getCustomerFromOrder($order);
|
2025-11-13 13:05:17 +05:30
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
return view('admin.orders_show', compact('order', 'user'));
|
2025-11-13 13:05:17 +05:30
|
|
|
}
|
|
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
public function popup($id)
|
|
|
|
|
{
|
|
|
|
|
$order = Order::with(['items', 'markList'])->findOrFail($id);
|
|
|
|
|
$user = $this->getCustomerFromOrder($order);
|
|
|
|
|
|
|
|
|
|
return view('admin.popup', compact('order', 'user'));
|
|
|
|
|
}
|
2025-11-13 13:05:17 +05:30
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
// ---------------------------
|
|
|
|
|
// ORDER ITEM MANAGEMENT (DB)
|
|
|
|
|
// ---------------------------
|
|
|
|
|
/**
|
|
|
|
|
* Add an item to an existing order
|
|
|
|
|
*/
|
|
|
|
|
public function addItem(Request $request, $orderId)
|
2025-11-13 13:05:17 +05:30
|
|
|
{
|
2025-12-01 10:38:52 +05:30
|
|
|
$order = Order::findOrFail($orderId);
|
2025-11-13 13:05:17 +05:30
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
$data = $request->validate([
|
|
|
|
|
'description' => 'required|string',
|
|
|
|
|
'ctn' => 'nullable|numeric',
|
|
|
|
|
'qty' => 'nullable|numeric',
|
|
|
|
|
'ttl_qty' => 'nullable|numeric',
|
|
|
|
|
'unit' => 'nullable|string',
|
|
|
|
|
'price' => 'nullable|numeric',
|
|
|
|
|
'ttl_amount' => 'nullable|numeric',
|
|
|
|
|
'cbm' => 'nullable|numeric',
|
|
|
|
|
'ttl_cbm' => 'nullable|numeric',
|
|
|
|
|
'kg' => 'nullable|numeric',
|
|
|
|
|
'ttl_kg' => 'nullable|numeric',
|
|
|
|
|
'shop_no' => 'nullable|string',
|
|
|
|
|
]);
|
2025-11-13 13:05:17 +05:30
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
$data['order_id'] = $order->id;
|
2025-11-13 13:05:17 +05:30
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
OrderItem::create($data);
|
2025-11-13 13:05:17 +05:30
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
// recalc totals and save to order
|
|
|
|
|
$this->recalcTotals($order);
|
2025-11-13 13:05:17 +05:30
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
return redirect()->back()->with('success', 'Item added and totals updated.');
|
|
|
|
|
}
|
2025-11-13 13:05:17 +05:30
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
/**
|
|
|
|
|
* Soft-delete an order item and recalc totals
|
|
|
|
|
*/
|
|
|
|
|
public function deleteItem($id)
|
|
|
|
|
{
|
|
|
|
|
$item = OrderItem::findOrFail($id);
|
|
|
|
|
$order = $item->order;
|
2025-11-13 13:05:17 +05:30
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
$item->delete(); // soft delete
|
2025-11-13 13:05:17 +05:30
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
// recalc totals
|
|
|
|
|
$this->recalcTotals($order);
|
2025-11-13 13:05:17 +05:30
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
return redirect()->back()->with('success', 'Item deleted and totals updated.');
|
2025-11-17 10:33:11 +05:30
|
|
|
}
|
2025-11-13 13:05:17 +05:30
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
/**
|
|
|
|
|
* Restore soft-deleted item and recalc totals
|
|
|
|
|
*/
|
|
|
|
|
public function restoreItem($id)
|
|
|
|
|
{
|
|
|
|
|
$item = OrderItem::withTrashed()->findOrFail($id);
|
|
|
|
|
$order = Order::findOrFail($item->order_id);
|
2025-11-13 13:05:17 +05:30
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
$item->restore();
|
2025-11-17 10:33:11 +05:30
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
// recalc totals
|
|
|
|
|
$this->recalcTotals($order);
|
2025-11-17 10:33:11 +05:30
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
return redirect()->back()->with('success', 'Item restored and totals updated.');
|
2025-11-17 10:33:11 +05:30
|
|
|
}
|
2025-11-13 13:05:17 +05:30
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
// ---------------------------
|
|
|
|
|
// ORDER CRUD: update / destroy
|
|
|
|
|
// ---------------------------
|
|
|
|
|
public function update(Request $request, $id)
|
|
|
|
|
{
|
|
|
|
|
$order = Order::findOrFail($id);
|
2025-11-12 19:44:04 +05:30
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
$data = $request->validate([
|
|
|
|
|
'mark_no' => 'required|string',
|
|
|
|
|
'origin' => 'nullable|string',
|
|
|
|
|
'destination' => 'nullable|string',
|
|
|
|
|
]);
|
2025-11-17 10:33:11 +05:30
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
$order->update([
|
|
|
|
|
'mark_no' => $data['mark_no'],
|
|
|
|
|
'origin' => $data['origin'] ?? null,
|
|
|
|
|
'destination' => $data['destination'] ?? null,
|
|
|
|
|
]);
|
2025-11-17 10:33:11 +05:30
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
// optionally recalc totals (not necessary unless you change item-level fields here)
|
|
|
|
|
$this->recalcTotals($order);
|
2025-11-17 10:33:11 +05:30
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
return redirect()->route('admin.orders.show', $order->id)
|
|
|
|
|
->with('success', 'Order updated successfully.');
|
|
|
|
|
}
|
2025-11-17 10:33:11 +05:30
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
/**
|
|
|
|
|
* Soft-delete whole order and its items (soft-delete items first then order)
|
|
|
|
|
*/
|
|
|
|
|
public function destroy($id)
|
|
|
|
|
{
|
|
|
|
|
$order = Order::findOrFail($id);
|
2025-11-17 10:33:11 +05:30
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
// soft-delete items first (so they show up in onlyTrashed for restore)
|
|
|
|
|
OrderItem::where('order_id', $order->id)->delete();
|
2025-11-13 13:05:17 +05:30
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
// then soft-delete order
|
|
|
|
|
$order->delete();
|
2025-11-12 19:44:04 +05:30
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
return redirect()->route('admin.orders.index')
|
|
|
|
|
->with('success', 'Order deleted successfully.');
|
|
|
|
|
}
|
2025-11-12 19:44:04 +05:30
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
// ---------------------------
|
|
|
|
|
// HELPERS
|
|
|
|
|
// ---------------------------
|
|
|
|
|
/**
|
|
|
|
|
* Recalculate totals for the order from current (non-deleted) items
|
|
|
|
|
*/
|
|
|
|
|
private function recalcTotals(Order $order)
|
|
|
|
|
{
|
|
|
|
|
// make sure we re-query live items (non-deleted)
|
|
|
|
|
$items = $order->items()->get();
|
|
|
|
|
|
|
|
|
|
$order->update([
|
|
|
|
|
'ctn' => (int) $items->sum(fn($i) => (int) ($i->ctn ?? 0)),
|
|
|
|
|
'qty' => (int) $items->sum(fn($i) => (int) ($i->qty ?? 0)),
|
|
|
|
|
'ttl_qty' => (int) $items->sum(fn($i) => (int) ($i->ttl_qty ?? 0)),
|
|
|
|
|
'ttl_amount'=> (float) $items->sum(fn($i) => (float) ($i->ttl_amount ?? 0)),
|
|
|
|
|
'cbm' => (float) $items->sum(fn($i) => (float) ($i->cbm ?? 0)),
|
|
|
|
|
'ttl_cbm' => (float) $items->sum(fn($i) => (float) ($i->ttl_cbm ?? 0)),
|
|
|
|
|
'kg' => (float) $items->sum(fn($i) => (float) ($i->kg ?? 0)),
|
|
|
|
|
'ttl_kg' => (float) $items->sum(fn($i) => (float) ($i->ttl_kg ?? 0)),
|
|
|
|
|
]);
|
2025-11-13 13:05:17 +05:30
|
|
|
}
|
|
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
/**
|
|
|
|
|
* Generate order id (keeps old format)
|
|
|
|
|
*/
|
|
|
|
|
private function generateOrderId()
|
2025-11-15 10:08:43 +05:30
|
|
|
{
|
2025-12-01 10:38:52 +05:30
|
|
|
$year = date('y');
|
|
|
|
|
$prefix = "KNT-$year-";
|
2025-11-15 10:08:43 +05:30
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
$lastOrder = Order::latest('id')->first();
|
|
|
|
|
$nextNumber = $lastOrder ? intval(substr($lastOrder->order_id, -8)) + 1 : 1;
|
2025-11-15 10:08:43 +05:30
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
return $prefix . str_pad($nextNumber, 8, '0', STR_PAD_LEFT);
|
2025-11-15 10:08:43 +05:30
|
|
|
}
|
|
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
// ---------------------------
|
|
|
|
|
// INVOICE CREATION (optional helper used by store/finish)
|
|
|
|
|
// ---------------------------
|
|
|
|
|
private function createInvoice(Order $order)
|
|
|
|
|
{
|
|
|
|
|
$invoiceNumber = $this->generateInvoiceNumber();
|
|
|
|
|
$customer = $this->getCustomerFromMarkList($order->mark_no);
|
|
|
|
|
$totalAmount = $order->ttl_amount;
|
2025-11-15 10:08:43 +05:30
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
$invoice = Invoice::create([
|
|
|
|
|
'order_id' => $order->id,
|
|
|
|
|
'customer_id' => $customer->id ?? null,
|
|
|
|
|
'mark_no' => $order->mark_no,
|
|
|
|
|
'invoice_number' => $invoiceNumber,
|
|
|
|
|
'invoice_date' => now(),
|
|
|
|
|
'due_date' => now()->addDays(10),
|
|
|
|
|
'payment_method' => null,
|
|
|
|
|
'reference_no' => null,
|
|
|
|
|
'status' => 'pending',
|
|
|
|
|
'final_amount' => $totalAmount,
|
|
|
|
|
'gst_percent' => 0,
|
|
|
|
|
'gst_amount' => 0,
|
|
|
|
|
'final_amount_with_gst' => $totalAmount,
|
|
|
|
|
'customer_name' => $customer->customer_name ?? null,
|
|
|
|
|
'company_name' => $customer->company_name ?? null,
|
|
|
|
|
'customer_email' => $customer->email ?? null,
|
|
|
|
|
'customer_mobile' => $customer->mobile_no ?? null,
|
|
|
|
|
'customer_address' => $customer->address ?? null,
|
|
|
|
|
'pincode' => $customer->pincode ?? null,
|
|
|
|
|
'notes' => null,
|
|
|
|
|
'pdf_path' => null,
|
|
|
|
|
]);
|
2025-11-15 10:08:43 +05:30
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
// clone order items into invoice items
|
|
|
|
|
foreach ($order->items as $item) {
|
|
|
|
|
InvoiceItem::create([
|
|
|
|
|
'invoice_id' => $invoice->id,
|
|
|
|
|
'description' => $item->description,
|
|
|
|
|
'ctn' => $item->ctn,
|
|
|
|
|
'qty' => $item->qty,
|
|
|
|
|
'ttl_qty' => $item->ttl_qty,
|
|
|
|
|
'unit' => $item->unit,
|
|
|
|
|
'price' => $item->price,
|
|
|
|
|
'ttl_amount' => $item->ttl_amount,
|
|
|
|
|
'cbm' => $item->cbm,
|
|
|
|
|
'ttl_cbm' => $item->ttl_cbm,
|
|
|
|
|
'kg' => $item->kg,
|
|
|
|
|
'ttl_kg' => $item->ttl_kg,
|
|
|
|
|
'shop_no' => $item->shop_no,
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-11-15 10:08:43 +05:30
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
private function generateInvoiceNumber()
|
2025-11-13 13:05:17 +05:30
|
|
|
{
|
2025-12-01 10:38:52 +05:30
|
|
|
$lastInvoice = Invoice::latest()->first();
|
|
|
|
|
$nextInvoice = $lastInvoice ? $lastInvoice->id + 1 : 1;
|
2025-11-13 13:05:17 +05:30
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
return 'INV-' . date('Y') . '-' . str_pad($nextInvoice, 6, '0', STR_PAD_LEFT);
|
2025-11-12 11:56:43 +05:30
|
|
|
}
|
2025-11-12 19:44:04 +05:30
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
private function getCustomerFromMarkList($markNo)
|
2025-11-26 23:07:12 +05:30
|
|
|
{
|
2025-12-01 10:38:52 +05:30
|
|
|
$markList = MarkList::where('mark_no', $markNo)->first();
|
2025-11-26 23:07:12 +05:30
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
if ($markList && $markList->customer_id) {
|
|
|
|
|
return User::where('customer_id', $markList->customer_id)->first();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
2025-11-26 23:07:12 +05:30
|
|
|
}
|
|
|
|
|
|
2025-12-01 10:38:52 +05:30
|
|
|
private function getCustomerFromOrder($order)
|
|
|
|
|
{
|
|
|
|
|
if ($order->markList && $order->markList->customer_id) {
|
|
|
|
|
return User::where('customer_id', $order->markList->customer_id)->first();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
}
|
2025-11-12 11:56:43 +05:30
|
|
|
}
|