kevin 284d228dc5 feat(vehicle): add vehicle+convoy feature with API, models, repos, UI
Adds model, repo, controller, and request classes for Vehicle and Convoy.
Registers routes for vehicles and convoys, updates client store.
Adds front‑end files to list, add, edit vehicles.
Cleans up console logging from client store.
2026-04-15 17:27:40 +03:00

221 lines
12 KiB
PHP

<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\Api\AuthController;
use App\Http\Controllers\Api\ClientController;
use App\Http\Controllers\Api\ClientGroupController;
use App\Http\Controllers\Api\ClientLocationController;
use App\Http\Controllers\Api\ContactController;
use App\Http\Controllers\Api\ClientCategoryController;
use App\Http\Controllers\Api\FournisseurController;
use App\Http\Controllers\Api\ProductController;
use App\Http\Controllers\Api\ProductCategoryController;
use App\Http\Controllers\Api\EmployeeController;
use App\Http\Controllers\Api\ThanatopractitionerController;
use App\Http\Controllers\Api\PractitionerDocumentController;
use App\Http\Controllers\Api\DeceasedController;
use App\Http\Controllers\Api\DeceasedDocumentController;
use App\Http\Controllers\Api\InterventionController;
use App\Http\Controllers\Api\FileController;
use App\Http\Controllers\Api\FileAttachmentController;
use App\Http\Controllers\Api\QuoteController;
use App\Http\Controllers\Api\ClientActivityTimelineController;
use App\Http\Controllers\Api\PurchaseOrderController;
use App\Http\Controllers\Api\PriceListController;
use App\Http\Controllers\Api\TvaRateController;
use App\Http\Controllers\Api\GoodsReceiptController;
use App\Http\Controllers\Api\UserController;
use App\Http\Controllers\Api\VehicleController;
use App\Http\Controllers\Api\ConvoyController;
/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| These routes are loaded with the "api" middleware group and are prefixed
| with /api automatically via bootstrap/app.php.
|
*/
Route::prefix('auth')->group(function () {
Route::post('/register', [AuthController::class, 'register']);
Route::post('/login', [AuthController::class, 'login']);
Route::post('/check-email', [AuthController::class, 'checkEmail']);
Route::post('/create-password', [AuthController::class, 'createPasswordAndLogin']);
Route::middleware('auth:sanctum')->group(function () {
Route::get('/me', [AuthController::class, 'me']);
// Alias to support clients calling /api/auth/user
Route::get('/user', [AuthController::class, 'me']);
Route::post('/logout', [AuthController::class, 'logout']);
Route::post('/logout-all', [AuthController::class, 'logoutAll']);
});
});
// Protected API routes
Route::middleware('auth:sanctum')->group(function () {
// Client management
// IMPORTANT: Specific routes must come before apiResource
Route::get('/clients/searchBy', [ClientController::class, 'searchBy']);
Route::apiResource('clients', ClientController::class);
Route::post('client-groups/{id}/assign-clients', [ClientGroupController::class, 'assignClients']);
Route::apiResource('client-groups', ClientGroupController::class);
Route::apiResource('price-lists', PriceListController::class);
Route::apiResource('users', UserController::class);
Route::apiResource('client-locations', ClientLocationController::class);
Route::apiResource('client-locations', ClientLocationController::class);
Route::get('clients/{clientId}/locations', [ClientLocationController::class, 'getLocationsByClient']);
// Client Parent/Child routes
Route::get('clients/{id}/children', [ClientController::class, 'getChildren']);
Route::post('clients/{id}/children/{childId}', [ClientController::class, 'addChild']);
Route::delete('clients/{id}/children/{childId}', [ClientController::class, 'removeChild']);
Route::patch('clients/{id}/status', [ClientController::class, 'changeStatus']);
Route::get('clients/{client}/timeline', [ClientActivityTimelineController::class, 'index']);
// Contact management
Route::apiResource('contacts', ContactController::class);
Route::get('clients/{clientId}/contacts', [ContactController::class, 'getContactsByClient']);
Route::apiResource('client-categories', ClientCategoryController::class);
// Quote management
Route::post('/quotes/{id}/send-email', [QuoteController::class, 'sendByEmail']);
Route::get('/quotes/{id}/download-pdf', [QuoteController::class, 'downloadPdf']);
Route::apiResource('quotes', QuoteController::class);
// Invoice management
Route::post('/invoices/{id}/send-email', [\App\Http\Controllers\Api\InvoiceController::class, 'sendByEmail']);
Route::post('/invoices/from-quote/{quoteId}', [\App\Http\Controllers\Api\InvoiceController::class, 'createFromQuote']);
Route::apiResource('invoices', \App\Http\Controllers\Api\InvoiceController::class);
// Avoir management
Route::apiResource('avoirs', \App\Http\Controllers\Api\AvoirController::class);
// Fournisseur management
Route::get('/fournisseurs/searchBy', [FournisseurController::class, 'searchBy']);
Route::apiResource('purchase-orders', PurchaseOrderController::class);
Route::apiResource('fournisseurs', FournisseurController::class);
Route::get('fournisseurs/{fournisseurId}/contacts', [ContactController::class, 'getContactsByFournisseur']);
// Product management
Route::get('/products/searchBy', [ProductController::class, 'searchBy']);
Route::get('/products/low-stock', [ProductController::class, 'lowStock']);
Route::get('/products/by-category', [ProductController::class, 'byCategory']);
Route::get('/products/statistics', [ProductController::class, 'statistics']);
Route::apiResource('products', ProductController::class);
Route::patch('/products/{id}/stock', [ProductController::class, 'updateStock']);
// Warehouse management
Route::get('/warehouses/searchBy', [\App\Http\Controllers\Api\WarehouseController::class, 'searchBy']);
Route::apiResource('warehouses', \App\Http\Controllers\Api\WarehouseController::class);
// Stock management
Route::apiResource('stock-items', \App\Http\Controllers\Api\StockItemController::class);
Route::apiResource('stock-moves', \App\Http\Controllers\Api\StockMoveController::class);
// TVA Rates management
Route::apiResource('tva-rates', TvaRateController::class);
// Goods Receipts management
Route::apiResource('goods-receipts', GoodsReceiptController::class);
Route::apiResource('vehicles', VehicleController::class);
Route::apiResource('convoys', ConvoyController::class);
// Product Category management
Route::get('/product-categories/search', [ProductCategoryController::class, 'search']);
Route::get('/product-categories/active', [ProductCategoryController::class, 'active']);
Route::get('/product-categories/roots', [ProductCategoryController::class, 'roots']);
Route::get('/product-categories/hierarchical', [ProductCategoryController::class, 'hierarchical']);
Route::get('/product-categories/statistics', [ProductCategoryController::class, 'statistics']);
Route::apiResource('product-categories', ProductCategoryController::class);
Route::patch('/product-categories/{id}/toggle-active', [ProductCategoryController::class, 'toggleActive']);
// Employee management
Route::get('/employees/searchBy', [EmployeeController::class, 'searchBy']);
Route::get('/employees/thanatopractitioners', [EmployeeController::class, 'getThanatopractitioners']);
Route::apiResource('employees', EmployeeController::class);
// Thanatopractitioner management
Route::get('/thanatopractitioners/search', [ThanatopractitionerController::class, 'searchByEmployeeName']);
Route::apiResource('thanatopractitioners', ThanatopractitionerController::class);
Route::get('employees/{employeeId}/thanatopractitioners', [ThanatopractitionerController::class, 'getByEmployee']);
Route::get('/thanatopractitioners/{id}/documents', [PractitionerDocumentController::class, 'getByThanatopractitioner']);
// Practitioner Document management
Route::get('/practitioner-documents/searchBy', [PractitionerDocumentController::class, 'searchBy']);
Route::get('/practitioner-documents/expiring', [PractitionerDocumentController::class, 'getExpiringDocuments']);
Route::apiResource('practitioner-documents', PractitionerDocumentController::class);
Route::patch('/practitioner-documents/{id}/verify', [PractitionerDocumentController::class, 'verifyDocument']);
// Deceased Routes
Route::prefix('deceased')->group(function () {
Route::get('/searchBy', [DeceasedController::class, 'searchBy']);
Route::get('/', [DeceasedController::class, 'index']);
Route::post('/', [DeceasedController::class, 'store']);
Route::get('/{deceased}', [DeceasedController::class, 'show']);
Route::put('/{deceased}', [DeceasedController::class, 'update']);
Route::delete('/{deceased}', [DeceasedController::class, 'destroy']);
});
// Deceased Document Routes
Route::prefix('deceased-documents')->group(function () {
Route::get('/by-deceased/{deceasedId}', [DeceasedDocumentController::class, 'byDeceased']);
Route::get('/by-doc-type', [DeceasedDocumentController::class, 'byDocType']);
Route::get('/by-file/{fileId}', [DeceasedDocumentController::class, 'byFile']);
Route::get('/search', [DeceasedDocumentController::class, 'search']);
Route::get('/', [DeceasedDocumentController::class, 'index']);
Route::post('/', [DeceasedDocumentController::class, 'store']);
Route::get('/{id}', [DeceasedDocumentController::class, 'show']);
Route::put('/{id}', [DeceasedDocumentController::class, 'update']);
Route::delete('/{id}', [DeceasedDocumentController::class, 'destroy']);
});
// Intervention Routes
Route::prefix('interventions')->group(function () {
Route::get('/by-month', [InterventionController::class, 'byMonth']);
Route::get('/', [InterventionController::class, 'index']);
Route::post('/', [InterventionController::class, 'store']);
Route::post('/with-all-data', [InterventionController::class, 'createInterventionalldata']);
Route::get('/{intervention}', [InterventionController::class, 'show']);
Route::put('/{intervention}', [InterventionController::class, 'update']);
Route::delete('/{intervention}', [InterventionController::class, 'destroy']);
Route::patch('/{intervention}/status', [InterventionController::class, 'changeStatus']);
Route::patch('/{intervention}/assign', [InterventionController::class, 'createAssignment']);
Route::patch('/{intervention}/{practitionerId}/unassignPractitioner', [InterventionController::class, 'unassignPractitioner']);
Route::get('/{intervention}/debug', [InterventionController::class, 'debugPractitioners']);
});
// File management
Route::prefix('files')->group(function () {
Route::get('/', [FileController::class, 'index']);
Route::post('/', [FileController::class, 'store']);
Route::get('/by-category/{category}', [FileController::class, 'byCategory']);
Route::get('/by-client/{clientId}', [FileController::class, 'byClient']);
Route::get('/organized', [FileController::class, 'organized']);
Route::get('/statistics', [FileController::class, 'stats']);
Route::get('/{id}', [FileController::class, 'show']);
Route::put('/{id}', [FileController::class, 'update']);
Route::delete('/{id}', [FileController::class, 'destroy']);
Route::get('/{id}/download', [FileController::class, 'download']);
});
// File Attachment management
Route::prefix('file-attachments')->group(function () {
Route::post('/', [FileAttachmentController::class, 'attach']);
Route::put('/{attachmentId}', [FileAttachmentController::class, 'update']);
Route::delete('/{attachmentId}', [FileAttachmentController::class, 'detach']);
Route::post('/detach-multiple', [FileAttachmentController::class, 'detachMultiple']);
Route::post('/reorder', [FileAttachmentController::class, 'reorder']);
Route::get('/attached-files', [FileAttachmentController::class, 'getAttachedFiles']);
Route::get('/intervention/{interventionId}/files', [FileAttachmentController::class, 'getInterventionFiles']);
Route::get('/client/{clientId}/files', [FileAttachmentController::class, 'getClientFiles']);
Route::get('/deceased/{deceasedId}/files', [FileAttachmentController::class, 'getDeceasedFiles']);
});
});