account section
This commit is contained in:
248
app/Http/Controllers/Admin/AdminAccountController.php
Normal file
248
app/Http/Controllers/Admin/AdminAccountController.php
Normal file
@@ -0,0 +1,248 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Entry;
|
||||
use App\Models\Order;
|
||||
use App\Models\Installment;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class AdminAccountController extends Controller
|
||||
{
|
||||
/**
|
||||
* 🚀 1. Get dashboard entries
|
||||
*/
|
||||
public function getDashboardData()
|
||||
{
|
||||
$entries = Entry::withCount('installments')
|
||||
->orderBy('id', 'desc')
|
||||
->get();
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'entries' => $entries
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 🚀 2. Get available consolidated orders
|
||||
*/
|
||||
public function getAvailableOrders()
|
||||
{
|
||||
$orders = Order::whereDoesntHave('entries')
|
||||
->orderBy('id', 'desc')
|
||||
->get();
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'orders' => $orders
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 🚀 3. Create new entry
|
||||
*/
|
||||
public function accountCreateOrder(Request $request)
|
||||
{
|
||||
$data = $request->validate([
|
||||
'description' => 'required|string|max:255',
|
||||
'region' => 'required|string|max:50',
|
||||
'amount' => 'required|numeric|min:1',
|
||||
'entry_date' => 'nullable|date',
|
||||
'selected_orders' => 'nullable|array',
|
||||
'selected_orders.*'=> 'integer|exists:orders,id',
|
||||
]);
|
||||
|
||||
return DB::transaction(function () use ($data) {
|
||||
|
||||
$entryDate = $data['entry_date'] ?? now()->toDateString();
|
||||
|
||||
// Count selected consolidated orders
|
||||
$orderQuantity = !empty($data['selected_orders'])
|
||||
? count($data['selected_orders'])
|
||||
: 0;
|
||||
|
||||
// Generate entry No: PAY-2025-001
|
||||
$prefix = 'PAY-' . date('Y') . '-';
|
||||
$last = Entry::where('entry_no', 'like', $prefix . '%')
|
||||
->orderBy('id', 'desc')
|
||||
->first();
|
||||
|
||||
$next = $last
|
||||
? intval(substr($last->entry_no, strrpos($last->entry_no, '-') + 1)) + 1
|
||||
: 1;
|
||||
|
||||
$entryNo = $prefix . str_pad($next, 7, '0', STR_PAD_LEFT);
|
||||
|
||||
// Create entry
|
||||
$entry = Entry::create([
|
||||
'entry_no' => $entryNo,
|
||||
'description' => $data['description'],
|
||||
'region' => $data['region'],
|
||||
'order_quantity' => $orderQuantity,
|
||||
'amount' => $data['amount'],
|
||||
'pending_amount' => $data['amount'],
|
||||
'entry_date' => $entryDate,
|
||||
'payment_status' => 'unpaid',
|
||||
'toggle_pos' => 0,
|
||||
'dispatch_status' => 'pending',
|
||||
]);
|
||||
|
||||
// Attach consolidated orders
|
||||
if (!empty($data['selected_orders'])) {
|
||||
$entry->orders()->attach($data['selected_orders']);
|
||||
}
|
||||
|
||||
$entry->load('orders');
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Entry Created Successfully',
|
||||
'entry' => $entry
|
||||
], 201);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 🚀 4. Toggle payment switch
|
||||
*/
|
||||
public function togglePayment(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'entry_no' => 'required|string|exists:entries,entry_no',
|
||||
'toggle_pos' => 'required|integer|in:0,1,2',
|
||||
]);
|
||||
|
||||
$entry = Entry::where('entry_no', $request->entry_no)->firstOrFail();
|
||||
|
||||
$map = [
|
||||
0 => 'unpaid',
|
||||
1 => 'pending',
|
||||
2 => 'paid'
|
||||
];
|
||||
|
||||
$entry->update([
|
||||
'toggle_pos' => $request->toggle_pos,
|
||||
'payment_status' => $map[$request->toggle_pos],
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'entry' => $entry
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 🚀 5. Add Installment
|
||||
*/
|
||||
public function addInstallment(Request $request)
|
||||
{
|
||||
$data = $request->validate([
|
||||
'entry_no' => 'required|exists:entries,entry_no',
|
||||
'proc_date' => 'nullable|date',
|
||||
'amount' => 'required|numeric|min:1',
|
||||
'status' => 'required|string'
|
||||
]);
|
||||
|
||||
return DB::transaction(function () use ($data) {
|
||||
|
||||
$entry = Entry::where('entry_no', $data['entry_no'])
|
||||
->lockForUpdate()
|
||||
->firstOrFail();
|
||||
|
||||
$amount = floatval($data['amount']);
|
||||
|
||||
if ($amount > $entry->pending_amount) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Installment cannot exceed pending amount.'
|
||||
], 422);
|
||||
}
|
||||
|
||||
$installment = Installment::create([
|
||||
'entry_id' => $entry->id,
|
||||
'proc_date' => $data['proc_date'] ?? now()->toDateString(),
|
||||
'amount' => $amount,
|
||||
'description'=> $entry->description,
|
||||
'region' => $entry->region,
|
||||
'status' => $data['status']
|
||||
]);
|
||||
|
||||
$entry->pending_amount -= $amount;
|
||||
|
||||
if ($entry->pending_amount <= 0.001) {
|
||||
$entry->pending_amount = 0;
|
||||
$entry->dispatch_status = 'dispatched';
|
||||
}
|
||||
|
||||
$entry->save();
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'entry' => $entry,
|
||||
'installment' => $installment
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 🚀 6. Update Installment Status
|
||||
*/
|
||||
public function updateInstallmentStatus(Request $request)
|
||||
{
|
||||
$data = $request->validate([
|
||||
'installment_id' => 'required|exists:installments,id',
|
||||
'status' => 'required|string|max:50'
|
||||
]);
|
||||
|
||||
return DB::transaction(function () use ($data) {
|
||||
|
||||
$installment = Installment::lockForUpdate()->findOrFail($data['installment_id']);
|
||||
|
||||
$installment->status = $data['status'];
|
||||
$installment->save();
|
||||
|
||||
$entry = Entry::lockForUpdate()->find($installment->entry_id);
|
||||
|
||||
// If ANY installment is not delivered — entry is NOT delivered
|
||||
if ($entry->installments()->where('status', '!=', 'Delivered')->exists()) {
|
||||
// entry still in progress
|
||||
$entry->dispatch_status = 'pending';
|
||||
} else {
|
||||
// all installments delivered
|
||||
$entry->dispatch_status = 'delivered';
|
||||
}
|
||||
|
||||
$entry->save();
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Installment updated successfully',
|
||||
'installment' => $installment,
|
||||
'entry' => $entry
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 🚀 6. Entry Details (installment history)
|
||||
*/
|
||||
public function getEntryDetails($entry_no)
|
||||
{
|
||||
$entry = Entry::with('installments')
|
||||
->where('entry_no', $entry_no)
|
||||
->firstOrFail();
|
||||
|
||||
$totalProcessed = $entry->amount - $entry->pending_amount;
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'entry' => $entry,
|
||||
'total_processed' => $totalProcessed,
|
||||
'pending' => $entry->pending_amount,
|
||||
]);
|
||||
}
|
||||
}
|
||||
56
app/Http/Controllers/Admin/AdminReportController.php
Normal file
56
app/Http/Controllers/Admin/AdminReportController.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Order;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class AdminReportController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display the reports page with joined data
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
// -------------------------------
|
||||
// FETCH REPORT DATA
|
||||
// ONLY orders that have BOTH:
|
||||
// 1. Invoice
|
||||
// 2. Shipment
|
||||
// -------------------------------
|
||||
$reports = DB::table('orders')
|
||||
->join('shipment_items', 'shipment_items.order_id', '=', 'orders.id')
|
||||
->join('shipments', 'shipments.id', '=', 'shipment_items.shipment_id')
|
||||
->join('invoices', 'invoices.order_id', '=', 'orders.id')
|
||||
->leftJoin('mark_list', 'mark_list.mark_no', '=', 'orders.mark_no')
|
||||
->leftJoin('users', 'users.customer_id', '=', 'mark_list.customer_id')
|
||||
|
||||
->select(
|
||||
'orders.id as order_pk',
|
||||
'orders.order_id',
|
||||
'orders.mark_no',
|
||||
'orders.origin',
|
||||
'orders.destination',
|
||||
|
||||
'shipments.id as shipment_pk',
|
||||
'shipments.shipment_id',
|
||||
'shipments.status as shipment_status',
|
||||
'shipments.shipment_date',
|
||||
|
||||
'invoices.invoice_number',
|
||||
'invoices.invoice_date',
|
||||
'invoices.final_amount',
|
||||
'invoices.status as invoice_status',
|
||||
|
||||
'mark_list.company_name',
|
||||
'mark_list.customer_name'
|
||||
)
|
||||
|
||||
->orderBy('shipments.shipment_date', 'desc')
|
||||
->get();
|
||||
|
||||
return view('admin.reports', compact('reports'));
|
||||
}
|
||||
}
|
||||
@@ -147,11 +147,22 @@ class ShipmentController extends Controller
|
||||
'status' => 'required|string'
|
||||
]);
|
||||
|
||||
// 1) Update shipment status
|
||||
$shipment = Shipment::findOrFail($request->shipment_id);
|
||||
$shipment->status = $request->status;
|
||||
$shipment->save();
|
||||
|
||||
return redirect()->back()->with('success', "Shipment status updated to {$shipment->statusLabel()}");
|
||||
// 2) Update ALL related orders' status
|
||||
foreach ($shipment->orders as $order) {
|
||||
$order->status = $shipment->status; // status is string: pending, in_transit, dispatched, delivered
|
||||
$order->save();
|
||||
}
|
||||
|
||||
return redirect()->back()->with(
|
||||
'success',
|
||||
"Shipment status updated to {$shipment->statusLabel()} and related orders updated."
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
37
app/Models/Entry.php
Normal file
37
app/Models/Entry.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Entry extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'entry_no',
|
||||
'description',
|
||||
'region',
|
||||
'order_quantity',
|
||||
'amount',
|
||||
'pending_amount',
|
||||
'entry_date',
|
||||
'payment_status',
|
||||
'toggle_pos',
|
||||
'dispatch_status',
|
||||
];
|
||||
|
||||
// An entry can have multiple installments
|
||||
public function installments()
|
||||
{
|
||||
return $this->hasMany(Installment::class);
|
||||
}
|
||||
|
||||
// An entry can have multiple orders (consolidated orders)
|
||||
public function orders()
|
||||
{
|
||||
return $this->belongsToMany(Order::class, 'entry_order', 'entry_id', 'order_id')
|
||||
->withTimestamps();
|
||||
}
|
||||
}
|
||||
28
app/Models/EntryOrder.php
Normal file
28
app/Models/EntryOrder.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class EntryOrder extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $table = 'entry_order';
|
||||
|
||||
protected $fillable = [
|
||||
'entry_id',
|
||||
'order_id'
|
||||
];
|
||||
|
||||
public function entry()
|
||||
{
|
||||
return $this->belongsTo(Entry::class);
|
||||
}
|
||||
|
||||
public function order()
|
||||
{
|
||||
return $this->belongsTo(Order::class);
|
||||
}
|
||||
}
|
||||
25
app/Models/Installment.php
Normal file
25
app/Models/Installment.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Installment extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'entry_id',
|
||||
'proc_date',
|
||||
'amount',
|
||||
'description',
|
||||
'region',
|
||||
'status'
|
||||
];
|
||||
|
||||
public function entry()
|
||||
{
|
||||
return $this->belongsTo(Entry::class);
|
||||
}
|
||||
}
|
||||
@@ -39,4 +39,11 @@ class Order extends Model
|
||||
{
|
||||
return $this->hasOne(MarkList::class, 'mark_no', 'mark_no');
|
||||
}
|
||||
|
||||
public function entries()
|
||||
{
|
||||
return $this->belongsToMany(Entry::class, 'entry_order', 'order_id', 'entry_id')
|
||||
->withTimestamps();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('entries', function (Blueprint $table) {
|
||||
$table->id();
|
||||
|
||||
$table->string('entry_no')->unique(); // PAY-2024-001
|
||||
$table->string('description');
|
||||
$table->string('region');
|
||||
|
||||
$table->unsignedInteger('order_quantity')->default(0); // selected consolidated order count
|
||||
|
||||
$table->decimal('amount', 12, 2);
|
||||
$table->decimal('pending_amount', 12, 2); // always <= amount
|
||||
|
||||
$table->date('entry_date'); // auto-today default by controller
|
||||
|
||||
// Toggle-based payment states
|
||||
$table->enum('payment_status', ['unpaid', 'pending', 'paid'])->default('unpaid');
|
||||
$table->tinyInteger('toggle_pos')->default(0); // 0 left, 1 middle, 2 right
|
||||
|
||||
// Dispatch state (for second table)
|
||||
$table->enum('dispatch_status', [
|
||||
'pending',
|
||||
'loading',
|
||||
'packed',
|
||||
'dispatched',
|
||||
'delivered'
|
||||
])->default('pending');
|
||||
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('entries');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('installments', function (Blueprint $table) {
|
||||
$table->id();
|
||||
|
||||
$table->foreignId('entry_id')
|
||||
->constrained('entries')
|
||||
->onDelete('cascade');
|
||||
|
||||
$table->date('proc_date'); // processing date
|
||||
$table->decimal('amount', 12, 2);
|
||||
|
||||
$table->string('description')->nullable();
|
||||
$table->string('region')->nullable();
|
||||
|
||||
$table->enum('status', [
|
||||
'Pending',
|
||||
'Loading',
|
||||
'Packed',
|
||||
'Dispatched',
|
||||
'Delivered'
|
||||
])->default('Pending');
|
||||
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('installments');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('entry_order', function (Blueprint $table) {
|
||||
$table->id();
|
||||
|
||||
$table->foreignId('entry_id')
|
||||
->constrained('entries')
|
||||
->onDelete('cascade');
|
||||
|
||||
$table->foreignId('order_id')
|
||||
->constrained('orders')
|
||||
->onDelete('cascade');
|
||||
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('entry_order');
|
||||
}
|
||||
};
|
||||
BIN
public/invoices/invoice-INV-2025-000007.pdf
Normal file
BIN
public/invoices/invoice-INV-2025-000007.pdf
Normal file
Binary file not shown.
BIN
public/invoices/invoice-INV-2025-000008.pdf
Normal file
BIN
public/invoices/invoice-INV-2025-000008.pdf
Normal file
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -420,7 +420,7 @@ body, .container-fluid { background: #f4f7fc; }
|
||||
<th>Total TTL KG</th>
|
||||
<th>Status</th>
|
||||
<th>Date</th>
|
||||
<th>Action</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
@@ -186,8 +186,12 @@
|
||||
<i class="bi bi-people"></i> Customers
|
||||
</a>
|
||||
|
||||
<a href="{{ route('admin.reports') }}"
|
||||
class="{{ request()->routeIs('admin.reports') ? 'active' : '' }}">
|
||||
<i class="bi bi-graph-up"></i> Reports
|
||||
</a>
|
||||
|
||||
|
||||
<a href="{{ route('admin.reports') }}" class="{{ request()->routeIs('admin.reports') ? 'active' : '' }}"><i class="bi bi-graph-up"></i> Reports</a>
|
||||
<a href="{{ route('admin.chat_support') }}" class="{{ request()->routeIs('admin.chat_support') ? 'active' : '' }}"><i class="bi bi-chat-dots"></i> Chat Support</a>
|
||||
<!-- <a href="{{ route('admin.orders.index') }}"
|
||||
class="{{ request()->routeIs('admin.orders.*') ? 'active' : '' }}">
|
||||
|
||||
@@ -1,12 +1,172 @@
|
||||
@extends('admin.layouts.app')
|
||||
|
||||
@section('page-title', 'Dashboard')
|
||||
@section('page-title', 'Shipping Report List')
|
||||
|
||||
@section('content')
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body">
|
||||
<h4>Welcome to the Admin reports</h4>
|
||||
<p>Here you can manage all system modules.</p>
|
||||
|
||||
<style>
|
||||
.report-container {
|
||||
background: #fff;
|
||||
padding: 25px;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 10px rgba(0,0,0,0.06);
|
||||
}
|
||||
|
||||
.report-header {
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.report-subtitle {
|
||||
font-size: 13px;
|
||||
color: #777;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.filter-row {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
margin-bottom: 15px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.filter-row input,
|
||||
.filter-row select {
|
||||
padding: 8px 12px;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #ccc;
|
||||
min-width: 200px;
|
||||
}
|
||||
|
||||
table.report-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
table.report-table thead tr {
|
||||
background: #ffe9b3;
|
||||
}
|
||||
|
||||
table.report-table th,
|
||||
table.report-table td {
|
||||
padding: 10px 12px;
|
||||
font-size: 14px;
|
||||
border-bottom: 1px solid #eee;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.status-badge {
|
||||
padding: 4px 10px;
|
||||
border-radius: 20px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.status-paid { background: #27ae60; }
|
||||
.status-pending { background: #f39c12; }
|
||||
.status-overdue { background: #e74c3c; }
|
||||
|
||||
.ship-pending { background:#f39c12; }
|
||||
.ship-in_transit { background:#3498db; }
|
||||
.ship-dispatched { background:#9b59b6; }
|
||||
.ship-delivered { background:#27ae60; }
|
||||
</style>
|
||||
|
||||
|
||||
<div class="report-container">
|
||||
|
||||
<div class="report-header">Shipping Report List</div>
|
||||
<div class="report-subtitle">Overview of last month</div>
|
||||
|
||||
<!-- FILTER BAR -->
|
||||
<div class="filter-row">
|
||||
<input type="date">
|
||||
<input type="date">
|
||||
|
||||
<select>
|
||||
<option selected>--Select Customer--</option>
|
||||
</select>
|
||||
|
||||
<select>
|
||||
<option selected>--Select shipping status--</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- REPORT TABLE -->
|
||||
<table class="report-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Order ID</th>
|
||||
<th>Shipment ID</th>
|
||||
<th>Company Name</th>
|
||||
<th>User Name</th>
|
||||
<th>Origin</th>
|
||||
<th>Destination</th>
|
||||
<th>Date</th>
|
||||
<th>Invoice ID</th>
|
||||
<th>Invoice Date</th>
|
||||
<th>Invoice Amount</th>
|
||||
<th>Invoice Status</th>
|
||||
<th>Shipment Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
@forelse ($reports as $r)
|
||||
<tr>
|
||||
<td>{{ $r->order_id }}</td>
|
||||
<td>{{ $r->shipment_id }}</td>
|
||||
|
||||
<td>{{ $r->company_name ?? '-' }}</td>
|
||||
<td>{{ $r->customer_name ?? '-' }}</td>
|
||||
|
||||
<td>{{ $r->origin }}</td>
|
||||
<td>{{ $r->destination }}</td>
|
||||
|
||||
<td>{{ \Carbon\Carbon::parse($r->shipment_date)->format('d/m/Y') }}</td>
|
||||
|
||||
<td>{{ $r->invoice_number }}</td>
|
||||
<td>{{ \Carbon\Carbon::parse($r->invoice_date)->format('d/m/Y') }}</td>
|
||||
|
||||
<td>{{ number_format($r->final_amount) }}₹</td>
|
||||
|
||||
<!-- Invoice Status -->
|
||||
<td>
|
||||
@php
|
||||
$ist = strtolower($r->invoice_status);
|
||||
@endphp
|
||||
|
||||
<span class="status-badge
|
||||
{{ $ist === 'paid' ? 'status-paid' : '' }}
|
||||
{{ $ist === 'pending' ? 'status-pending' : '' }}
|
||||
{{ $ist === 'overdue' ? 'status-overdue' : '' }}">
|
||||
{{ ucfirst($ist) }}
|
||||
</span>
|
||||
</td>
|
||||
|
||||
<!-- Shipment Status -->
|
||||
<td>
|
||||
<span class="status-badge ship-{{ $r->shipment_status }}">
|
||||
{{ ucfirst(str_replace('_',' ', $r->shipment_status)) }}
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="12" class="text-center text-muted p-3">
|
||||
No report data available.
|
||||
</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
|
||||
172
routes/web.php
172
routes/web.php
@@ -8,83 +8,113 @@ use App\Http\Controllers\Admin\AdminOrderController;
|
||||
use App\Http\Controllers\Admin\ShipmentController;
|
||||
use App\Http\Controllers\Admin\AdminInvoiceController;
|
||||
use App\Http\Controllers\Admin\AdminCustomerController;
|
||||
use App\Http\Controllers\Admin\AdminAccountController;
|
||||
use App\Http\Controllers\Admin\AdminReportController;
|
||||
|
||||
// -------------------------
|
||||
// Default Front Page
|
||||
// -------------------------
|
||||
// ---------------------------
|
||||
// Public Front Page
|
||||
// ---------------------------
|
||||
Route::get('/', function () {
|
||||
return view('welcome');
|
||||
});
|
||||
|
||||
// -------------------------
|
||||
// Admin Authentication Routes
|
||||
// -------------------------
|
||||
// ---------------------------
|
||||
// ADMIN LOGIN ROUTES
|
||||
// ---------------------------
|
||||
Route::prefix('admin')->group(function () {
|
||||
Route::get('login', [AdminAuthController::class, 'showLoginForm'])->name('admin.login');
|
||||
Route::post('login', [AdminAuthController::class, 'login'])->name('admin.login.submit');
|
||||
Route::post('logout', [AdminAuthController::class, 'logout'])->name('admin.logout');
|
||||
|
||||
// MUST have route name "login" for session redirect
|
||||
Route::get('/login', [AdminAuthController::class, 'showLoginForm'])
|
||||
->name('admin.login');
|
||||
|
||||
Route::post('/login', [AdminAuthController::class, 'login'])
|
||||
->name('admin.login.submit');
|
||||
|
||||
Route::post('/logout', [AdminAuthController::class, 'logout'])
|
||||
->name('admin.logout');
|
||||
});
|
||||
|
||||
// -------------------------
|
||||
// Protected Admin Routes
|
||||
// -------------------------
|
||||
Route::prefix('admin')->middleware('auth:admin')->group(function () {
|
||||
// Dashboard Pages
|
||||
// Route::get('/dashboard', fn() => view('admin.dashboard'))->name('admin.dashboard');
|
||||
Route::get('/dashboard', [AdminOrderController::class, 'index'])->name('admin.dashboard');
|
||||
//Route::get('/shipments', fn() => view('admin.shipments'))->name('admin.shipments');
|
||||
//Route::get('/invoice', fn() => view('admin.invoice'))->name('admin.invoice');
|
||||
//Route::get('/customers', fn() => view('admin.customers'))->name('admin.customers');
|
||||
Route::get('/reports', fn() => view('admin.reports'))->name('admin.reports');
|
||||
Route::get('/chat-support', fn() => view('admin.chat_support'))->name('admin.chat_support');
|
||||
|
||||
Route::get('/staff', fn() => view('admin.staff'))->name('admin.staff');
|
||||
Route::get('/account', fn() => view('admin.account'))->name('admin.account');
|
||||
Route::get('/profile', fn() => view('admin.profile'))->name('admin.profile');
|
||||
Route::get('/admin/orders/{id}/details', [OrderController::class, 'getOrderDetails'])->name('admin.orders.details');
|
||||
// ==========================================
|
||||
// PROTECTED ADMIN ROUTES (session protected)
|
||||
// ==========================================
|
||||
Route::prefix('admin')
|
||||
->middleware('auth:admin')
|
||||
->group(function () {
|
||||
|
||||
// Dashboard
|
||||
Route::get('/dashboard', [AdminOrderController::class, 'index'])
|
||||
->name('admin.dashboard');
|
||||
|
||||
Route::get('/reports', [AdminReportController::class, 'index'])->name('admin.reports');
|
||||
|
||||
Route::get('/chat-support', fn() => view('admin.chat_support'))
|
||||
->name('admin.chat_support');
|
||||
|
||||
Route::get('/staff', fn() => view('admin.staff'))
|
||||
->name('admin.staff');
|
||||
|
||||
Route::get('/account', fn() => view('admin.account'))
|
||||
->name('admin.account');
|
||||
|
||||
Route::get('/profile', fn() => view('admin.profile'))
|
||||
->name('admin.profile');
|
||||
|
||||
|
||||
// ---------------------------
|
||||
// USER REQUESTS
|
||||
// ---------------------------
|
||||
Route::get('/requests', [UserRequestController::class, 'index'])
|
||||
->name('admin.requests');
|
||||
|
||||
Route::get('/requests/approve/{id}', [UserRequestController::class, 'approve'])
|
||||
->name('admin.requests.approve');
|
||||
|
||||
Route::get('/requests/reject/{id}', [UserRequestController::class, 'reject'])
|
||||
->name('admin.requests.reject');
|
||||
|
||||
|
||||
// ✅ User Requests Controller Routes
|
||||
Route::get('/requests', [UserRequestController::class, 'index'])->name('admin.requests');
|
||||
Route::get('/requests/approve/{id}', [UserRequestController::class, 'approve'])->name('admin.requests.approve');
|
||||
Route::get('/requests/reject/{id}', [UserRequestController::class, 'reject'])->name('admin.requests.reject');
|
||||
// ---------------------------
|
||||
// MARK LIST
|
||||
// ---------------------------
|
||||
Route::get('/mark-list', [AdminMarkListController::class, 'index'])
|
||||
->name('admin.marklist.index');
|
||||
|
||||
//mark list show
|
||||
Route::get('/mark-list', [AdminMarkListController::class, 'index'])->name('admin.marklist.index');
|
||||
Route::get('/mark-list/status/{id}', [AdminMarkListController::class, 'toggleStatus'])->name('admin.marklist.toggle');
|
||||
Route::get('/mark-list/status/{id}', [AdminMarkListController::class, 'toggleStatus'])
|
||||
->name('admin.marklist.toggle');
|
||||
|
||||
Route::get('/orders', fn() => view('admin.orders'))->name('admin.orders');
|
||||
|
||||
// Orders Controller Routes
|
||||
// Show admin order dashboard (list + create form)
|
||||
// ---------------------------
|
||||
// ORDERS
|
||||
// ---------------------------
|
||||
Route::get('/orders', fn() => view('admin.orders'))
|
||||
->name('admin.orders');
|
||||
|
||||
Route::get('/orders/list', [AdminOrderController::class, 'index'])
|
||||
->name('admin.orders.index');
|
||||
|
||||
// View a single order
|
||||
Route::get('/orders/{id}', [AdminOrderController::class, 'show'])
|
||||
->name('admin.orders.show');
|
||||
|
||||
// TEMPORARY ITEMS (multi-order system)
|
||||
Route::post('/orders/temp/add', [AdminOrderController::class, 'addTempItem'])
|
||||
->name('admin.orders.temp.add');
|
||||
|
||||
Route::post('/orders/temp/delete', [AdminOrderController::class, 'deleteTempItem'])
|
||||
->name('admin.orders.temp.delete');
|
||||
|
||||
// Finish and save order
|
||||
Route::post('/orders/finish', [AdminOrderController::class, 'finishOrder'])
|
||||
->name('admin.orders.finish');
|
||||
|
||||
Route::post('/orders/temp/reset', [AdminOrderController::class, 'resetTemp'])
|
||||
->name('admin.orders.temp.reset');
|
||||
|
||||
Route::post('/orders/finish', [AdminOrderController::class, 'finishOrder'])
|
||||
->name('admin.orders.finish');
|
||||
|
||||
Route::get('/orders/view/{id}', [AdminOrderController::class, 'popup'])
|
||||
->name('admin.orders.popup');
|
||||
|
||||
|
||||
|
||||
// ---------------------------
|
||||
// SHIPMENTS
|
||||
// ---------------------------
|
||||
Route::get('/shipments', [ShipmentController::class, 'index'])
|
||||
->name('admin.shipments');
|
||||
|
||||
@@ -98,37 +128,71 @@ Route::prefix('admin')->middleware('auth:admin')->group(function () {
|
||||
->name('admin.shipments.show');
|
||||
|
||||
|
||||
// Invoice list page
|
||||
// ---------------------------
|
||||
// INVOICES
|
||||
// ---------------------------
|
||||
Route::get('/invoices', [AdminInvoiceController::class, 'index'])
|
||||
->name('admin.invoices.index');
|
||||
|
||||
// Popup data
|
||||
Route::get('/invoices/{id}/popup', [AdminInvoiceController::class, 'popup'])
|
||||
->name('admin.invoices.popup');
|
||||
|
||||
// Edit invoice
|
||||
Route::get('/invoices/{id}/edit', [AdminInvoiceController::class, 'edit'])
|
||||
->name('admin.invoices.edit');
|
||||
|
||||
// Update invoice
|
||||
Route::post('/invoices/{id}/update', [AdminInvoiceController::class, 'update'])
|
||||
->name('admin.invoices.update');
|
||||
|
||||
// customer
|
||||
|
||||
// ---------------------------
|
||||
// CUSTOMERS
|
||||
// ---------------------------
|
||||
Route::get('/customers', [AdminCustomerController::class, 'index'])
|
||||
->name('admin.customers.index');
|
||||
|
||||
Route::get('/customers/{id}/view', [AdminCustomerController::class, 'view'])
|
||||
->name('admin.customers.view');
|
||||
|
||||
Route::post('/customers/{id}/status', [AdminCustomerController::class, 'toggleStatus'])
|
||||
->name('admin.customers.status');
|
||||
|
||||
|
||||
Route::get('/customers/add', [AdminCustomerController::class, 'create'])
|
||||
->name('admin.customers.add');
|
||||
|
||||
Route::post('/customers/store', [AdminCustomerController::class, 'store'])
|
||||
->name('admin.customers.store');
|
||||
|
||||
Route::get('/customers/{id}/view', [AdminCustomerController::class, 'view'])
|
||||
->name('admin.customers.view');
|
||||
|
||||
Route::post('/customers/{id}/status', [AdminCustomerController::class, 'toggleStatus'])
|
||||
->name('admin.customers.status');
|
||||
});
|
||||
|
||||
|
||||
// ==========================================
|
||||
// ADMIN ACCOUNT (AJAX) ROUTES
|
||||
// ==========================================
|
||||
Route::prefix('admin/account')
|
||||
->middleware('auth:admin')
|
||||
->name('admin.account.')
|
||||
->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');
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user