Account,Order&Request change
This commit is contained in:
@@ -11,6 +11,71 @@ use Illuminate\Support\Facades\DB;
|
|||||||
|
|
||||||
class AdminAccountController extends Controller
|
class AdminAccountController extends Controller
|
||||||
{
|
{
|
||||||
|
public function updateEntry(Request $request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$data = $request->validate([
|
||||||
|
'entry_no' => 'required|exists:entries,entry_no',
|
||||||
|
'description' => 'required|string|max:255',
|
||||||
|
'order_quantity' => 'required|numeric|min:0',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$entry = Entry::where('entry_no', $data['entry_no'])->first();
|
||||||
|
|
||||||
|
if (!$entry) {
|
||||||
|
return response()->json([
|
||||||
|
'success' => false,
|
||||||
|
'message' => 'Entry not found.',
|
||||||
|
], 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
$entry->description = $data['description'];
|
||||||
|
$entry->order_quantity = $data['order_quantity'];
|
||||||
|
$entry->save();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true,
|
||||||
|
'message' => 'Entry updated successfully.',
|
||||||
|
'entry' => $entry,
|
||||||
|
]);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return response()->json([
|
||||||
|
'success' => false,
|
||||||
|
'message' => 'Server error: '.$e->getMessage(),
|
||||||
|
], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function deleteEntry(Request $request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$data = $request->validate([
|
||||||
|
'entry_no' => 'required|exists:entries,entry_no',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$entry = Entry::where('entry_no', $data['entry_no'])->first();
|
||||||
|
|
||||||
|
if (!$entry) {
|
||||||
|
return response()->json([
|
||||||
|
'success' => false,
|
||||||
|
'message' => 'Entry not found.',
|
||||||
|
], 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
$entry->delete();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true,
|
||||||
|
'message' => 'Entry deleted successfully.',
|
||||||
|
]);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return response()->json([
|
||||||
|
'success' => false,
|
||||||
|
'message' => 'Server error: '.$e->getMessage(),
|
||||||
|
], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 🚀 1. Get dashboard entries
|
* 🚀 1. Get dashboard entries
|
||||||
*/
|
*/
|
||||||
@@ -245,4 +310,82 @@ class AdminAccountController extends Controller
|
|||||||
'pending' => $entry->pending_amount,
|
'pending' => $entry->pending_amount,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------
|
||||||
|
//add order Entry
|
||||||
|
//--------------------------
|
||||||
|
public function addOrdersToEntry(Request $request)
|
||||||
|
{
|
||||||
|
$data = $request->validate([
|
||||||
|
'entry_no' => 'required|exists:entries,entry_no',
|
||||||
|
'order_ids' => 'required|array',
|
||||||
|
'order_ids.*' => 'integer|exists:orders,id',
|
||||||
|
]);
|
||||||
|
|
||||||
|
return DB::transaction(function () use ($data) {
|
||||||
|
$entry = Entry::where('entry_no', $data['entry_no'])->firstOrFail();
|
||||||
|
|
||||||
|
// आधीचे orders काढू नका, फक्त नवीन add करा
|
||||||
|
$entry->orders()->syncWithoutDetaching($data['order_ids']);
|
||||||
|
|
||||||
|
// इथे quantity auto update
|
||||||
|
$entry->order_quantity = $entry->orders()->count();
|
||||||
|
$entry->save();
|
||||||
|
|
||||||
|
$entry->load('orders');
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true,
|
||||||
|
'message' => 'Orders added successfully.',
|
||||||
|
'entry' => $entry,
|
||||||
|
]);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public function getEntryOrders($entry_no)
|
||||||
|
{
|
||||||
|
$entry = Entry::where('entry_no', $entry_no)
|
||||||
|
->with('orders')
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if (!$entry) {
|
||||||
|
return response()->json([
|
||||||
|
'success' => false,
|
||||||
|
'message' => 'Entry not found.',
|
||||||
|
], 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true,
|
||||||
|
'orders' => $entry->orders,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function removeOrderFromEntry(Request $request)
|
||||||
|
{
|
||||||
|
$data = $request->validate([
|
||||||
|
'entry_no' => 'required|exists:entries,entry_no',
|
||||||
|
'order_id' => 'required|integer|exists:orders,id',
|
||||||
|
]);
|
||||||
|
|
||||||
|
return DB::transaction(function () use ($data) {
|
||||||
|
$entry = Entry::where('entry_no', $data['entry_no'])->firstOrFail();
|
||||||
|
|
||||||
|
// order detach करा
|
||||||
|
$entry->orders()->detach($data['order_id']);
|
||||||
|
|
||||||
|
// इथे quantity auto update
|
||||||
|
$entry->order_quantity = $entry->orders()->count();
|
||||||
|
$entry->save();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true,
|
||||||
|
'message' => 'Order removed successfully.',
|
||||||
|
'entry' => $entry,
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -309,5 +309,46 @@ class AdminOrderController extends Controller
|
|||||||
|
|
||||||
return view('admin.orders', compact('orders'));
|
return view('admin.orders', compact('orders'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function downloadPdf(Request $request)
|
||||||
|
{
|
||||||
|
$query = Order::with(['markList', 'invoice', 'shipments']);
|
||||||
|
|
||||||
|
// Apply filters
|
||||||
|
if ($request->has('search') && $request->search) {
|
||||||
|
$search = $request->search;
|
||||||
|
$query->where(function($q) use ($search) {
|
||||||
|
$q->where('order_id', 'like', "%{$search}%")
|
||||||
|
->orWhereHas('markList', function($q) use ($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('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');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function downloadExcel(Request $request)
|
||||||
|
{
|
||||||
|
return Excel::download(new OrdersExport($request), 'orders-report-' . date('Y-m-d') . '.xlsx');
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
43
resources/views/admin/pdf/order_pdf.blade.php
Normal file
43
resources/views/admin/pdf/order_pdf.blade.php
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Orders Report</title>
|
||||||
|
<style>
|
||||||
|
body { font-family: DejaVu Sans, sans-serif; font-size: 12px; }
|
||||||
|
table { width: 100%; border-collapse: collapse; margin-top: 10px; }
|
||||||
|
th, td { border: 1px solid #ccc; padding: 6px 8px; text-align: left; }
|
||||||
|
th { background: #f3f4f6; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h3>Orders Report</h3>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Order ID</th>
|
||||||
|
<th>Company</th>
|
||||||
|
<th>Invoice No</th>
|
||||||
|
<th>Invoice Status</th>
|
||||||
|
<th>Shipment Status</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@foreach($orders as $order)
|
||||||
|
@php
|
||||||
|
$mark = $order->markList ?? null;
|
||||||
|
$invoice = $order->invoice ?? null;
|
||||||
|
$shipment = $order->shipments->first() ?? null;
|
||||||
|
@endphp
|
||||||
|
<tr>
|
||||||
|
<td>{{ $order->order_id ?? '-' }}</td>
|
||||||
|
<td>{{ $mark->company_name ?? '-' }}</td>
|
||||||
|
<td>{{ $invoice->invoice_number ?? '-' }}</td>
|
||||||
|
<td>{{ $invoice->status ?? '-' }}</td>
|
||||||
|
<td>{{ $shipment->status ?? '-' }}</td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -189,7 +189,101 @@
|
|||||||
filter: brightness(0) saturate(100%) invert(84%) sepia(8%) saturate(165%) hue-rotate(179deg) brightness(89%) contrast(86%);
|
filter: brightness(0) saturate(100%) invert(84%) sepia(8%) saturate(165%) hue-rotate(179deg) brightness(89%) contrast(86%);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Responsive pagination */
|
/* ===== UPDATED SEARCH BAR STYLES ===== */
|
||||||
|
.search-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
gap: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-form {
|
||||||
|
flex: 1;
|
||||||
|
max-width: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-input-group {
|
||||||
|
display: flex;
|
||||||
|
box-shadow: 0 2px 6px rgba(0,0,0,0.08);
|
||||||
|
border-radius: 10px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-input {
|
||||||
|
flex: 1;
|
||||||
|
border: 1px solid #e2e8f0;
|
||||||
|
border-right: none;
|
||||||
|
padding: 10px 16px;
|
||||||
|
font-size: 14px;
|
||||||
|
background-color: #fff;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-input:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: #3b82f6;
|
||||||
|
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-button {
|
||||||
|
background: #3b82f6;
|
||||||
|
border: 1px solid #3b82f6;
|
||||||
|
color: white;
|
||||||
|
padding: 10px 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-button:hover {
|
||||||
|
background: #2563eb;
|
||||||
|
border-color: #2563eb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-icon {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-badges {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-badge {
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
padding: 6px 12px;
|
||||||
|
border-radius: 20px;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-badge-pending {
|
||||||
|
background: linear-gradient(135deg, #fef3c7, #fde68a);
|
||||||
|
color: #d97706;
|
||||||
|
border: 1px solid #f59e0b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-badge-approved {
|
||||||
|
background: linear-gradient(135deg, #d1fae5, #a7f3d0);
|
||||||
|
color: #065f46;
|
||||||
|
border: 1px solid #10b981;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-badge-rejected {
|
||||||
|
background: linear-gradient(135deg, #fecaca, #fca5a5);
|
||||||
|
color: #991b1b;
|
||||||
|
border: 1px solid #ef4444;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsive styles */
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.pagination-container {
|
.pagination-container {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -199,28 +293,50 @@
|
|||||||
.pagination-controls {
|
.pagination-controls {
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.search-container {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-form {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-badges {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<!-- Counts -->
|
<!-- Counts -->
|
||||||
<div class="d-flex justify-content-between align-items-center mb-2 mt-3">
|
<div class="d-flex justify-content-between align-items-center mb-2 mt-3">
|
||||||
<h4 class="fw-bold mb-0">User Requests (Total: {{ $total }})</h4>
|
<h4 class="fw-bold mb-0">User Requests (Total: {{ $total }})</h4>
|
||||||
<div>
|
|
||||||
<span class="count-badge badge rounded-pill bg-warning text-dark me-1">{{ $requests->where('status', 'pending')->count() }} Pending</span>
|
|
||||||
<span class="count-badge badge rounded-pill bg-success me-1">{{ $requests->where('status', 'approved')->count() }} Approved</span>
|
|
||||||
<span class="count-badge badge rounded-pill bg-danger">{{ $requests->where('status', 'rejected')->count() }} Rejected</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Search + Table -->
|
<!-- Search + Table -->
|
||||||
<div class="card mb-4 shadow-sm">
|
<div class="card mb-4 shadow-sm">
|
||||||
<div class="card-body pb-1">
|
<div class="card-body pb-1">
|
||||||
<form method="GET" action="">
|
<!-- Updated Search Bar with Status Badges in the same line -->
|
||||||
<div class="input-group mb-2">
|
<div class="search-container">
|
||||||
<input type="text" name="search" value="{{ request('search') }}" class="form-control" placeholder="🔍 Search by name, email, company...">
|
<form method="GET" action="" class="search-form">
|
||||||
<button class="btn btn-outline-primary" type="submit"><i class="bi bi-search"></i></button>
|
<div class="search-input-group">
|
||||||
|
<input type="text" name="search" value="{{ request('search') }}" class="search-input" placeholder="Search by name, email, company...">
|
||||||
|
<button class="search-button" type="submit">
|
||||||
|
<svg class="search-icon" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M21 21L16.514 16.506L21 21ZM19 10.5C19 15.194 15.194 19 10.5 19C5.806 19 2 15.194 2 10.5C2 5.806 5.806 2 10.5 2C15.194 2 19 5.806 19 10.5Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div class="status-badges">
|
||||||
|
<span class="status-badge status-badge-pending">{{ $requests->where('status', 'pending')->count() }} Pending</span>
|
||||||
|
<span class="status-badge status-badge-approved">{{ $requests->where('status', 'approved')->count() }} Approved</span>
|
||||||
|
<span class="status-badge status-badge-rejected">{{ $requests->where('status', 'rejected')->count() }} Rejected</span>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</div>
|
||||||
|
|
||||||
<div class="table-responsive custom-table-wrapper">
|
<div class="table-responsive custom-table-wrapper">
|
||||||
<table class="table align-middle mb-0 custom-table">
|
<table class="table align-middle mb-0 custom-table">
|
||||||
|
|||||||
@@ -182,36 +182,67 @@ Route::prefix('admin')
|
|||||||
->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'])
|
||||||
Route::get('/dashboard', [AdminAccountController::class, 'getDashboardData'])
|
->name('dashboard');
|
||||||
->name('dashboard');
|
|
||||||
|
Route::get('/available-orders', [AdminAccountController::class, 'getAvailableOrders'])
|
||||||
Route::get('/available-orders', [AdminAccountController::class, 'getAvailableOrders'])
|
->name('orders.available');
|
||||||
->name('orders.available');
|
|
||||||
|
Route::post('/create-order', [AdminAccountController::class, 'accountCreateOrder'])
|
||||||
Route::post('/create-order', [AdminAccountController::class, 'accountCreateOrder'])
|
->name('create');
|
||||||
->name('create');
|
|
||||||
|
Route::post('/toggle-payment', [AdminAccountController::class, 'togglePayment'])
|
||||||
Route::post('/toggle-payment', [AdminAccountController::class, 'togglePayment'])
|
->name('toggle');
|
||||||
->name('toggle');
|
|
||||||
|
Route::post('/installment/create', [AdminAccountController::class, 'addInstallment'])
|
||||||
Route::post('/installment/create', [AdminAccountController::class, 'addInstallment'])
|
->name('installment.create');
|
||||||
->name('installment.create');
|
|
||||||
|
Route::post('/installment/update-status', [AdminAccountController::class, 'updateInstallmentStatus'])
|
||||||
Route::post('/installment/update-status', [AdminAccountController::class, 'updateInstallmentStatus'])
|
->name('installment.update');
|
||||||
->name('installment.update');
|
|
||||||
|
Route::get('/entry/{entry_no}', [AdminAccountController::class, 'getEntryDetails'])
|
||||||
Route::get('/entry/{entry_no}', [AdminAccountController::class, 'getEntryDetails'])
|
->name('entry.details');
|
||||||
->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');
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------
|
||||||
|
// REPORTS DOWNLOAD ROUTES
|
||||||
|
// ---------------------------
|
||||||
|
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');
|
||||||
|
|
||||||
|
//---------------------------
|
||||||
|
//Edit Button Route
|
||||||
|
//---------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user