feat: implement user management system and integrate AI services with Ollama and Gemini
This commit is contained in:
@@ -3,8 +3,12 @@
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Attachment;
|
||||
use App\Services\GeminiService;
|
||||
use App\Services\OllamaService;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class AttachmentController extends Controller
|
||||
{
|
||||
@@ -30,4 +34,61 @@ class AttachmentController extends Controller
|
||||
'Content-Disposition' => 'inline; filename="' . basename($attachment->file_name) . '"'
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Effectue une OCRisation de la pièce jointe à l'aide de l'API Gemini.
|
||||
*/
|
||||
public function ocr(Request $request, Attachment $attachment, GeminiService $geminiService, OllamaService $ollamaService): JsonResponse
|
||||
{
|
||||
// On vérifie si l'utilisateur a le droit de voir la commande liée à cette pièce jointe
|
||||
$order = $attachment->order;
|
||||
Gate::authorize('view', $order);
|
||||
|
||||
try {
|
||||
$mode = $request->input('mode', 'gemini');
|
||||
if ($mode === 'ollama') {
|
||||
$data = $ollamaService->analyzeQuote($attachment);
|
||||
} else {
|
||||
$data = $geminiService->analyzeQuote($attachment);
|
||||
}
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => $data
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Effectue une OCRisation directe sur un fichier téléchargé temporairement.
|
||||
*/
|
||||
public function ocrUpload(Request $request, GeminiService $geminiService, OllamaService $ollamaService): JsonResponse
|
||||
{
|
||||
$request->validate([
|
||||
'file' => 'required|file|mimes:pdf,png,jpg,jpeg,webp|max:10240',
|
||||
'mode' => 'nullable|string'
|
||||
]);
|
||||
|
||||
try {
|
||||
$mode = $request->input('mode', 'gemini');
|
||||
if ($mode === 'ollama') {
|
||||
$data = $ollamaService->analyzeUploadedFile($request->file('file'));
|
||||
} else {
|
||||
$data = $geminiService->analyzeUploadedFile($request->file('file'));
|
||||
}
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => $data
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,6 +78,12 @@ class DevisController extends Controller
|
||||
|
||||
public function createFromCommande(\App\Models\Order $commande)
|
||||
{
|
||||
$commande->load('attachments');
|
||||
$quoteAttachments = $commande->attachments->where('file_type', 'quote')->map(fn($a) => [
|
||||
'id' => $a->id,
|
||||
'file_name' => $a->file_name,
|
||||
])->values()->all();
|
||||
|
||||
return Inertia::render('Devis/CreateFromCommande', [
|
||||
'commande' => [
|
||||
'id' => $commande->id,
|
||||
@@ -85,6 +91,7 @@ class DevisController extends Controller
|
||||
'label' => $commande->label,
|
||||
'supplier' => $commande->supplier,
|
||||
'quote_number' => $commande->quote_number,
|
||||
'quote_attachments' => $quoteAttachments,
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Inertia\Inertia;
|
||||
|
||||
class UserController extends Controller
|
||||
{
|
||||
/**
|
||||
* Vérifie les droits d'administration de l'utilisateur.
|
||||
*/
|
||||
protected function authorizeAdmin(Request $request)
|
||||
{
|
||||
if ($request->user()->role !== 'chef_service') {
|
||||
abort(403, 'Action non autorisée. Réservé aux chefs de service.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Liste des utilisateurs.
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$this->authorizeAdmin($request);
|
||||
|
||||
$users = User::latest()->get();
|
||||
|
||||
return Inertia::render('Users/Index', [
|
||||
'users' => $users,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formulaire de création.
|
||||
*/
|
||||
public function create(Request $request)
|
||||
{
|
||||
$this->authorizeAdmin($request);
|
||||
|
||||
return Inertia::render('Users/Form', [
|
||||
'isEdit' => false,
|
||||
'user' => null,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enregistrer un nouvel utilisateur.
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$this->authorizeAdmin($request);
|
||||
|
||||
$validated = $request->validate([
|
||||
'name' => 'required|string|max:255',
|
||||
'email' => 'required|string|email|max:255|unique:users',
|
||||
'password' => 'required|string|min:8',
|
||||
'role' => 'required|string|in:chef_service,admin_reseau',
|
||||
]);
|
||||
|
||||
User::create([
|
||||
'name' => $validated['name'],
|
||||
'email' => $validated['email'],
|
||||
'password' => Hash::make($validated['password']),
|
||||
'role' => $validated['role'],
|
||||
]);
|
||||
|
||||
return redirect()->route('users.index')->with('success', 'Utilisateur créé avec succès.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Formulaire d'édition.
|
||||
*/
|
||||
public function edit(Request $request, User $user)
|
||||
{
|
||||
$this->authorizeAdmin($request);
|
||||
|
||||
return Inertia::render('Users/Form', [
|
||||
'isEdit' => true,
|
||||
'user' => $user,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mettre à jour un utilisateur.
|
||||
*/
|
||||
public function update(Request $request, User $user)
|
||||
{
|
||||
$this->authorizeAdmin($request);
|
||||
|
||||
$validated = $request->validate([
|
||||
'name' => 'required|string|max:255',
|
||||
'email' => [
|
||||
'required',
|
||||
'string',
|
||||
'email',
|
||||
'max:255',
|
||||
Rule::unique('users')->ignore($user->id),
|
||||
],
|
||||
'password' => 'nullable|string|min:8',
|
||||
'role' => 'required|string|in:chef_service,admin_reseau',
|
||||
]);
|
||||
|
||||
$data = [
|
||||
'name' => $validated['name'],
|
||||
'email' => $validated['email'],
|
||||
'role' => $validated['role'],
|
||||
];
|
||||
|
||||
if (!empty($validated['password'])) {
|
||||
$data['password'] = Hash::make($validated['password']);
|
||||
}
|
||||
|
||||
$user->update($data);
|
||||
|
||||
return redirect()->route('users.index')->with('success', 'Utilisateur mis à jour avec succès.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Supprimer un utilisateur.
|
||||
*/
|
||||
public function destroy(Request $request, User $user)
|
||||
{
|
||||
$this->authorizeAdmin($request);
|
||||
|
||||
if ($request->user()->id === $user->id) {
|
||||
return redirect()->back()->withErrors(['error' => 'Vous ne pouvez pas vous supprimer vous-même !']);
|
||||
}
|
||||
|
||||
$user->delete();
|
||||
|
||||
return redirect()->route('users.index')->with('success', 'Utilisateur supprimé avec succès.');
|
||||
}
|
||||
}
|
||||
@@ -39,6 +39,17 @@ class HandleInertiaRequests extends Middleware
|
||||
'error' => fn () => $request->session()->get('error'),
|
||||
],
|
||||
'appName' => config('app.name'),
|
||||
'ollamaAvailable' => cache()->remember('ollama_available', 15, function () {
|
||||
try {
|
||||
$url = rtrim(config('services.ollama.url', 'http://127.0.0.1:11434'), '/');
|
||||
// Remplacement de localhost par 127.0.0.1 pour contourner les lenteurs de résolution DNS sur Windows
|
||||
$url = str_replace('localhost', '127.0.0.1', $url);
|
||||
$response = \Illuminate\Support\Facades\Http::timeout(2.0)->get($url);
|
||||
return $response->successful();
|
||||
} catch (\Exception $e) {
|
||||
return false;
|
||||
}
|
||||
}),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user