API changes
This commit is contained in:
@@ -9,6 +9,25 @@ use App\Models\User;
|
||||
|
||||
class UserAuthController extends Controller
|
||||
{
|
||||
|
||||
public function refreshToken()
|
||||
{
|
||||
try {
|
||||
$newToken = JWTAuth::refresh(JWTAuth::getToken());
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'token' => $newToken,
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Could not refresh token.',
|
||||
], 401);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* User Login
|
||||
*/
|
||||
@@ -60,6 +79,8 @@ class UserAuthController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* User Logout
|
||||
*/
|
||||
|
||||
296
app/Http/Controllers/user/UserOrderController.php
Normal file
296
app/Http/Controllers/user/UserOrderController.php
Normal file
@@ -0,0 +1,296 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\User;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use PHPOpenSourceSaver\JWTAuth\Facades\JWTAuth;
|
||||
|
||||
class UserOrderController extends Controller
|
||||
{
|
||||
public function orderSummary()
|
||||
{
|
||||
// Authenticate user via JWT
|
||||
$user = JWTAuth::parseToken()->authenticate();
|
||||
|
||||
if (!$user) {
|
||||
return response()->json([
|
||||
'status' => false,
|
||||
'message' => 'Unauthorized'
|
||||
], 401);
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
// Get all orders
|
||||
// -------------------------------------
|
||||
$orders = $user->orders()->with('invoice')->get();
|
||||
|
||||
// -------------------------------------
|
||||
// Counts
|
||||
// -------------------------------------
|
||||
$totalOrders = $orders->count();
|
||||
$delivered = $orders->where('status', 'delivered')->count();
|
||||
$inTransit = $orders->where('status', '!=', 'delivered')->count();
|
||||
$active = $totalOrders;
|
||||
|
||||
// -------------------------------------
|
||||
// Total Amount = Invoice.total_with_gst
|
||||
// -------------------------------------
|
||||
$totalAmount = $orders->sum(function ($o) {
|
||||
return $o->invoice->final_amount_with_gst ?? 0;
|
||||
});
|
||||
|
||||
// Format total amount in K, L, Cr
|
||||
$formattedAmount = $this->formatIndianNumber($totalAmount);
|
||||
|
||||
return response()->json([
|
||||
'status' => true,
|
||||
|
||||
'summary' => [
|
||||
'active_orders' => $active,
|
||||
'in_transit_orders' => $inTransit,
|
||||
'delivered_orders' => $delivered,
|
||||
'total_value' => $formattedAmount, // formatted value
|
||||
'total_raw' => $totalAmount // original value
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert number into Indian Format:
|
||||
* 1000 -> 1K
|
||||
* 100000 -> 1L
|
||||
* 10000000 -> 1Cr
|
||||
*/
|
||||
private function formatIndianNumber($num)
|
||||
{
|
||||
if ($num >= 10000000) {
|
||||
return round($num / 10000000, 1) . 'Cr';
|
||||
}
|
||||
|
||||
if ($num >= 100000) {
|
||||
return round($num / 100000, 1) . 'L';
|
||||
}
|
||||
|
||||
if ($num >= 1000) {
|
||||
return round($num / 1000, 1) . 'K';
|
||||
}
|
||||
|
||||
return (string)$num;
|
||||
}
|
||||
|
||||
public function allOrders()
|
||||
{
|
||||
$user = JWTAuth::parseToken()->authenticate();
|
||||
|
||||
if (!$user) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Unauthorized'
|
||||
], 401);
|
||||
}
|
||||
|
||||
// Fetch orders for this user
|
||||
$orders = $user->orders()
|
||||
->with(['invoice', 'shipments'])
|
||||
->orderBy('id', 'desc')
|
||||
->get()
|
||||
->map(function ($o) {
|
||||
return [
|
||||
'order_id' => $o->order_id,
|
||||
'status' => $o->status,
|
||||
'amount' => $o->ttl_amount,
|
||||
'description'=> "Order from {$o->origin} to {$o->destination}",
|
||||
'created_at' => $o->created_at,
|
||||
];
|
||||
});
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'orders' => $orders
|
||||
]);
|
||||
}
|
||||
|
||||
public function orderDetails($order_id)
|
||||
{
|
||||
$user = JWTAuth::parseToken()->authenticate();
|
||||
|
||||
$order = $user->orders()
|
||||
->with(['items'])
|
||||
->where('order_id', $order_id)
|
||||
->first();
|
||||
|
||||
if (!$order) {
|
||||
return response()->json(['success' => false, 'message' => 'Order not found'], 404);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'order' => $order
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
public function orderShipment($order_id)
|
||||
{
|
||||
$user = JWTAuth::parseToken()->authenticate();
|
||||
|
||||
// Get order
|
||||
$order = $user->orders()->where('order_id', $order_id)->first();
|
||||
|
||||
if (!$order) {
|
||||
return response()->json(['success' => false, 'message' => 'Order not found'], 404);
|
||||
}
|
||||
|
||||
// Find shipment only for this order
|
||||
$shipment = $order->shipments()
|
||||
->with(['items' => function ($q) use ($order) {
|
||||
$q->where('order_id', $order->id);
|
||||
}])
|
||||
->first();
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'shipment' => $shipment
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
public function orderInvoice($order_id)
|
||||
{
|
||||
$user = JWTAuth::parseToken()->authenticate();
|
||||
|
||||
$order = $user->orders()
|
||||
->with('invoice.items')
|
||||
->where('order_id', $order_id)
|
||||
->first();
|
||||
|
||||
if (!$order) {
|
||||
return response()->json(['success' => false, 'message' => 'Order not found'], 404);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'invoice' => $order->invoice
|
||||
]);
|
||||
}
|
||||
|
||||
public function trackOrder($order_id)
|
||||
{
|
||||
$user = JWTAuth::parseToken()->authenticate();
|
||||
|
||||
$order = $user->orders()
|
||||
->with('shipments')
|
||||
->where('order_id', $order_id)
|
||||
->first();
|
||||
|
||||
if (!$order) {
|
||||
return response()->json(['success' => false, 'message' => 'Order not found'], 404);
|
||||
}
|
||||
|
||||
$shipment = $order->shipments()->first();
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'track' => [
|
||||
'order_id' => $order->order_id,
|
||||
'shipment_status' => $shipment->status ?? 'pending',
|
||||
'shipment_date' => $shipment->shipment_date ?? null,
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
public function allInvoices()
|
||||
{
|
||||
$user = JWTAuth::parseToken()->authenticate();
|
||||
|
||||
if (!$user) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Unauthorized'
|
||||
], 401);
|
||||
}
|
||||
|
||||
// Fetch all invoices of customer
|
||||
$invoices = $user->invoices()
|
||||
->withCount('installments')
|
||||
->orderBy('id', 'desc')
|
||||
->get()
|
||||
->map(function ($invoice) {
|
||||
return [
|
||||
'invoice_id' => $invoice->id,
|
||||
'invoice_number' => $invoice->invoice_number,
|
||||
'invoice_date' => $invoice->invoice_date,
|
||||
'status' => $invoice->status,
|
||||
'amount' => $invoice->final_amount_with_gst,
|
||||
'formatted_amount' => $this->formatIndianNumber($invoice->final_amount_with_gst),
|
||||
'pdf_url' => $invoice->pdf_path ? url($invoice->pdf_path) : null,
|
||||
'installment_count' => $invoice->installments_count,
|
||||
];
|
||||
});
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'invoices' => $invoices
|
||||
]);
|
||||
}
|
||||
|
||||
public function invoiceInstallmentsById($invoice_id)
|
||||
{
|
||||
$user = \PHPOpenSourceSaver\JWTAuth\Facades\JWTAuth::parseToken()->authenticate();
|
||||
|
||||
if (! $user) {
|
||||
return response()->json(['success' => false, 'message' => 'Unauthorized'], 401);
|
||||
}
|
||||
|
||||
// Find invoice by numeric id and ensure it belongs to logged-in user (invoice.customer_id = user.id)
|
||||
$invoice = \App\Models\Invoice::where('id', (int)$invoice_id)
|
||||
->where('customer_id', $user->id)
|
||||
->with(['installments' => function($q){
|
||||
$q->orderBy('installment_date', 'ASC')->orderBy('id', 'ASC');
|
||||
}])
|
||||
->first();
|
||||
|
||||
if (! $invoice) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Invoice not found for this customer'
|
||||
], 404);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'invoice_id' => $invoice->id,
|
||||
'invoice_number' => $invoice->invoice_number,
|
||||
'installments' => $invoice->installments
|
||||
]);
|
||||
}
|
||||
|
||||
public function invoiceDetails($invoice_id)
|
||||
{
|
||||
$user = JWTAuth::parseToken()->authenticate();
|
||||
|
||||
if (! $user) {
|
||||
return response()->json(['success' => false, 'message' => 'Unauthorized'], 401);
|
||||
}
|
||||
|
||||
$invoice = \App\Models\Invoice::where('id', $invoice_id)
|
||||
->where('customer_id', $user->id)
|
||||
->with('items')
|
||||
->first();
|
||||
|
||||
if (! $invoice) {
|
||||
return response()->json(['success' => false, 'message' => 'Invoice not found'], 404);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'invoice' => $invoice
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
113
app/Http/Controllers/user/UserProfileController.php
Normal file
113
app/Http/Controllers/user/UserProfileController.php
Normal file
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\User;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use PHPOpenSourceSaver\JWTAuth\Facades\JWTAuth;
|
||||
|
||||
class UserProfileController extends Controller
|
||||
{
|
||||
public function profile()
|
||||
{
|
||||
// Get logged-in user using JWT
|
||||
try {
|
||||
$user = JWTAuth::parseToken()->authenticate();
|
||||
} catch (\Exception $e) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Token invalid or expired',
|
||||
], 401);
|
||||
}
|
||||
|
||||
|
||||
if (! $user) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Unauthorized'
|
||||
], 401);
|
||||
}
|
||||
|
||||
// Format response
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => [
|
||||
'customer_id' => $user->customer_id,
|
||||
'customer_name' => $user->customer_name,
|
||||
'company_name' => $user->company_name,
|
||||
'designation' => $user->designation,
|
||||
'email' => $user->email,
|
||||
'mobile' => $user->mobile_no,
|
||||
'address' => $user->address,
|
||||
'pincode' => $user->pincode,
|
||||
'status' => $user->status,
|
||||
'customer_type' => $user->customer_type,
|
||||
'profile_image' => $user->profile_image ? url($user->profile_image) : null,
|
||||
'date' => $user->date,
|
||||
'created_at' => $user->created_at,
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
public function updateProfile(Request $request)
|
||||
{
|
||||
$user = JWTAuth::parseToken()->authenticate();
|
||||
|
||||
if (! $user) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Unauthorized'
|
||||
], 401);
|
||||
}
|
||||
|
||||
// Validate ONLY profile image
|
||||
$request->validate([
|
||||
'profile_image' => 'required|image|mimes:jpg,jpeg,png|max:2048'
|
||||
]);
|
||||
|
||||
// If new image uploaded
|
||||
if ($request->hasFile('profile_image')) {
|
||||
|
||||
// DELETE OLD IMAGE
|
||||
if ($user->profile_image && file_exists(public_path($user->profile_image))) {
|
||||
@unlink(public_path($user->profile_image));
|
||||
}
|
||||
|
||||
// NEW FILE
|
||||
$file = $request->file('profile_image');
|
||||
$filename = 'profile_' . time() . '.' . $file->getClientOriginalExtension();
|
||||
|
||||
// Correct folder name (from your message)
|
||||
$folder = 'profile_upload/';
|
||||
$fullPath = $folder . $filename;
|
||||
|
||||
// Move file
|
||||
$file->move(public_path($folder), $filename);
|
||||
|
||||
// Save in DB (same pattern you said)
|
||||
$user->profile_image = $fullPath;
|
||||
}
|
||||
|
||||
$user->save();
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Profile image updated successfully',
|
||||
'data' => [
|
||||
'customer_id' => $user->customer_id,
|
||||
'customer_name' => $user->customer_name,
|
||||
'company_name' => $user->company_name,
|
||||
'designation' => $user->designation,
|
||||
'email' => $user->email,
|
||||
'mobile' => $user->mobile_no,
|
||||
'address' => $user->address,
|
||||
'pincode' => $user->pincode,
|
||||
'status' => $user->status,
|
||||
'customer_type' => $user->customer_type,
|
||||
'profile_image' => $user->profile_image ? url($user->profile_image) : null,
|
||||
'date' => $user->date,
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
36
app/Http/Middleware/JwtRefreshMiddleware.php
Normal file
36
app/Http/Middleware/JwtRefreshMiddleware.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Tymon\JWTAuth\Facades\JWTAuth;
|
||||
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
|
||||
use Tymon\JWTAuth\Exceptions\TokenInvalidException;
|
||||
use Tymon\JWTAuth\Exceptions\JWTException;
|
||||
|
||||
class JwtRefreshMiddleware
|
||||
{
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
try {
|
||||
JWTAuth::parseToken()->authenticate();
|
||||
} catch (TokenExpiredException $e) {
|
||||
try {
|
||||
$newToken = JWTAuth::refresh(JWTAuth::getToken());
|
||||
auth()->setToken($newToken);
|
||||
|
||||
$response = $next($request);
|
||||
|
||||
return $response->header('Authorization', 'Bearer ' . $newToken);
|
||||
} catch (\Exception $e) {
|
||||
return response()->json(['message' => 'Session expired, please login again'], 401);
|
||||
}
|
||||
} catch (TokenInvalidException $e) {
|
||||
return response()->json(['message' => 'Invalid token'], 401);
|
||||
} catch (JWTException $e) {
|
||||
return response()->json(['message' => 'Token missing'], 401);
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
@@ -89,4 +89,11 @@ class User extends Authenticatable implements JWTSubject
|
||||
{
|
||||
return [];
|
||||
}
|
||||
public function invoices()
|
||||
{
|
||||
return $this->hasMany(\App\Models\Invoice::class, 'customer_id', 'id');
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
BIN
public/invoices/invoice-INV-2025-000017.pdf
Normal file
BIN
public/invoices/invoice-INV-2025-000017.pdf
Normal file
Binary file not shown.
BIN
public/invoices/invoice-INV-2025-000019.pdf
Normal file
BIN
public/invoices/invoice-INV-2025-000019.pdf
Normal file
Binary file not shown.
BIN
public/invoices/invoice-INV-2025-000023.pdf
Normal file
BIN
public/invoices/invoice-INV-2025-000023.pdf
Normal file
Binary file not shown.
BIN
public/profile_upload/profile_1764394681.jpeg
Normal file
BIN
public/profile_upload/profile_1764394681.jpeg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
BIN
public/profile_upload/profile_1764568863.jpg
Normal file
BIN
public/profile_upload/profile_1764568863.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 65 KiB |
@@ -890,10 +890,10 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Create Invoice Button -->
|
||||
<!-- Create Invoice Button
|
||||
<a href="{{ route('admin.invoices.create') }}" class="create-invoice-btn">
|
||||
<i class="bi bi-plus-circle"></i> Create Invoice
|
||||
</a>
|
||||
</a> -->
|
||||
</div>
|
||||
|
||||
<div class="invoice-management-main no-extra-space">
|
||||
|
||||
@@ -216,10 +216,10 @@
|
||||
<a href="{{ route('admin.account') }}" class="{{ request()->routeIs('admin.account') ? 'active' : '' }}"><i class="bi bi-gear"></i> Account</a>
|
||||
<a href="{{ route('admin.marklist.index') }}" class="{{ request()->routeIs('admin.marklist.index') ? 'active' : '' }}"><i class="bi bi-list-check"></i> Mark List</a>
|
||||
|
||||
<form method="POST" action="{{ route('admin.logout') }}" class="mt-4 px-3">
|
||||
<!-- <form method="POST" action="{{ route('admin.logout') }}" class="mt-4 px-3">
|
||||
@csrf
|
||||
<button type="submit" class="btn btn-danger w-100"><i class="bi bi-box-arrow-right"></i> Logout</button>
|
||||
</form>
|
||||
</form> -->
|
||||
</div>
|
||||
|
||||
<div class="main-content">
|
||||
|
||||
@@ -289,7 +289,22 @@
|
||||
</span>
|
||||
@endif
|
||||
</td>
|
||||
<td>N/A</td>
|
||||
<td>
|
||||
@if($req->status == 'pending')
|
||||
<a href="{{ route('admin.requests.approve', $req->id) }}"
|
||||
class="btn btn-success btn-sm">
|
||||
<i class="bi bi-check-circle"></i> Approve
|
||||
</a>
|
||||
|
||||
<a href="{{ route('admin.requests.reject', $req->id) }}"
|
||||
class="btn btn-danger btn-sm">
|
||||
<i class="bi bi-x-circle"></i> Reject
|
||||
</a>
|
||||
@else
|
||||
<span class="text-muted">No Action</span>
|
||||
@endif
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
|
||||
@@ -4,17 +4,39 @@ use Illuminate\Support\Facades\Route;
|
||||
use App\Http\Controllers\RequestController;
|
||||
use App\Http\Controllers\UserAuthController;
|
||||
use App\Http\Controllers\MarkListController;
|
||||
use App\Http\Controllers\User\UserOrderController;
|
||||
use App\Http\Controllers\User\UserProfileController;
|
||||
|
||||
|
||||
//user send request
|
||||
Route::post('/signup-request', [RequestController::class, 'usersignup']);
|
||||
|
||||
//login / logout
|
||||
Route::post('/user/login', [UserAuthController::class, 'login']);
|
||||
Route::post('/user/logout', [UserAuthController::class, 'logout'])->middleware('auth:api');
|
||||
|
||||
|
||||
|
||||
Route::middleware(['auth:api'])->group(function () {
|
||||
Route::get('/show-mark-list', [MarkListController::class, 'showmarklist']); // Fetch all marks by user
|
||||
Route::post('/add-mark-no', [MarkListController::class, 'addmarkno']); // Create new mark
|
||||
|
||||
Route::post('/user/logout', [UserAuthController::class, 'logout']);
|
||||
|
||||
// Marklist
|
||||
Route::get('/show-mark-list', [MarkListController::class, 'showmarklist']);
|
||||
Route::post('/add-mark-no', [MarkListController::class, 'addmarkno']);
|
||||
|
||||
// Orders
|
||||
Route::get('/user/order-summary', [UserOrderController::class, 'orderSummary']);
|
||||
Route::get('/user/orders', [UserOrderController::class, 'allOrders']);
|
||||
Route::get('/user/order/{order_id}/details', [UserOrderController::class, 'orderDetails']);
|
||||
Route::get('/user/order/{order_id}/shipment', [UserOrderController::class, 'orderShipment']);
|
||||
Route::get('/user/order/{order_id}/invoice', [UserOrderController::class, 'orderInvoice']);
|
||||
Route::get('/user/order/{order_id}/track', [UserOrderController::class, 'trackOrder']);
|
||||
Route::get('/user/invoice/{invoice_id}/details', [UserOrderController::class, 'invoiceDetails']);
|
||||
|
||||
// Invoice List
|
||||
Route::get('/user/invoices', [UserOrderController::class, 'allInvoices']);
|
||||
Route::get('/user/invoice/{invoice_id}/installments', [UserOrderController::class, 'invoiceInstallmentsById']);
|
||||
|
||||
// Profile
|
||||
Route::get('/user/profile', [UserProfileController::class, 'profile']);
|
||||
Route::post('/user/profile/update', [UserProfileController::class, 'updateProfile']);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user