feat: add Devis and BesoinInformatique modules

- Devis: CRUD complet, génération PDF (dompdf), paramètres (DevisSetting)
- BesoinInformatique: CRUD complet avec gestion matériels/licences
- Migrations pour les 3 nouvelles tables
- Navigation mise à jour dans AuthenticatedLayout

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
mrKamoo
2026-06-19 14:46:16 +02:00
co-authored by Claude Sonnet 4.6
parent 030d76af53
commit 7312c7640b
24 changed files with 2887 additions and 4 deletions
@@ -0,0 +1,90 @@
<?php
namespace App\Http\Controllers;
use App\Models\BesoinInformatique;
use Illuminate\Http\Request;
use Inertia\Inertia;
class BesoinInformatiqueController extends Controller
{
public function index()
{
$besoins = BesoinInformatique::latest()->get();
return Inertia::render('BesoinsInformatiques/Index', [
'besoins' => $besoins
]);
}
public function create()
{
return Inertia::render('BesoinsInformatiques/Create');
}
public function store(Request $request)
{
$validated = $request->validate([
'collectivite' => 'nullable|string|max:255',
'nom_referent' => 'nullable|string|max:255',
'descriptif_projet' => 'nullable|string',
'materiels_support' => 'nullable|array',
'licences_bureautique' => 'nullable|array',
'equipements_reseaux' => 'nullable|string',
'cablage_reseau' => 'nullable|string',
'telephonie_ip' => 'nullable|string',
'nouveau_batiment' => 'nullable|string',
'logiciels_metiers' => 'nullable|string',
'licences_projets' => 'nullable|array',
'date_validation' => 'nullable|date',
'validation_dgs' => 'nullable|string|max:255',
]);
BesoinInformatique::create($validated);
return redirect()->route('besoins-informatiques.index')->with('success', 'Besoin informatique créé avec succès.');
}
public function show(BesoinInformatique $besoinInformatique)
{
return Inertia::render('BesoinsInformatiques/Show', [
'besoin' => $besoinInformatique
]);
}
public function edit(BesoinInformatique $besoinInformatique)
{
return Inertia::render('BesoinsInformatiques/Edit', [
'besoin' => $besoinInformatique
]);
}
public function update(Request $request, BesoinInformatique $besoinInformatique)
{
$validated = $request->validate([
'collectivite' => 'nullable|string|max:255',
'nom_referent' => 'nullable|string|max:255',
'descriptif_projet' => 'nullable|string',
'materiels_support' => 'nullable|array',
'licences_bureautique' => 'nullable|array',
'equipements_reseaux' => 'nullable|string',
'cablage_reseau' => 'nullable|string',
'telephonie_ip' => 'nullable|string',
'nouveau_batiment' => 'nullable|string',
'logiciels_metiers' => 'nullable|string',
'licences_projets' => 'nullable|array',
'date_validation' => 'nullable|date',
'validation_dgs' => 'nullable|string|max:255',
]);
$besoinInformatique->update($validated);
return redirect()->route('besoins-informatiques.index')->with('success', 'Besoin informatique mis à jour avec succès.');
}
public function destroy(BesoinInformatique $besoinInformatique)
{
$besoinInformatique->delete();
return redirect()->route('besoins-informatiques.index')->with('success', 'Besoin informatique supprimé avec succès.');
}
}
+177
View File
@@ -0,0 +1,177 @@
<?php
namespace App\Http\Controllers;
use App\Models\Devis;
use App\Models\DevisSetting;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Barryvdh\DomPDF\Facade\Pdf;
class DevisController extends Controller
{
public function index()
{
$devis = Devis::latest()->get();
return Inertia::render('Devis/Index', [
'devis' => $devis
]);
}
public function create()
{
return Inertia::render('Devis/Create');
}
public function store(Request $request)
{
$validated = $request->validate([
'title' => 'required|string|max:255',
'destinataire_type' => 'required|string|in:commune,service_interne',
'destinataire_nom' => 'required|string|max:255',
'referent' => 'nullable|string|max:255',
'date_devis' => 'required|date',
'status' => 'required|string|in:draft,sent,accepted,rejected',
'items' => 'nullable|array',
'tva_rate' => 'nullable|numeric|min:0|max:100',
'notes' => 'nullable|string',
]);
// Calculer les montants
$totalHt = 0;
if (!empty($validated['items'])) {
foreach ($validated['items'] as $item) {
$qty = floatval($item['quantite'] ?? 0);
$price = floatval($item['prix_unitaire'] ?? 0);
$totalHt += $qty * $price;
}
}
$tvaRate = floatval($validated['tva_rate'] ?? 20);
$totalTtc = $totalHt * (1 + ($tvaRate / 100));
$validated['total_ht'] = $totalHt;
$validated['total_ttc'] = $totalTtc;
Devis::create($validated);
return redirect()->route('devis.index')->with('success', 'Devis créé avec succès.');
}
public function show(Devis $devi)
{
$settings = DevisSetting::first() ?? DevisSetting::create([
'entity_name' => "Direction des Systèmes d'Information",
'entity_sub' => "Communauté d'Agglomération Béziers Méditerranée",
'email' => "support.informatique@beziers-mediterranee.fr",
'telephone' => "04.67.01.60.00",
'adresse' => "Béziers, France",
]);
return Inertia::render('Devis/Show', [
'devis' => $devi,
'settings' => $settings
]);
}
public function edit(Devis $devi)
{
return Inertia::render('Devis/Edit', [
'devis' => $devi
]);
}
public function update(Request $request, Devis $devi)
{
$validated = $request->validate([
'title' => 'required|string|max:255',
'destinataire_type' => 'required|string|in:commune,service_interne',
'destinataire_nom' => 'required|string|max:255',
'referent' => 'nullable|string|max:255',
'date_devis' => 'required|date',
'status' => 'required|string|in:draft,sent,accepted,rejected',
'items' => 'nullable|array',
'tva_rate' => 'nullable|numeric|min:0|max:100',
'notes' => 'nullable|string',
]);
// Calculer les montants
$totalHt = 0;
if (!empty($validated['items'])) {
foreach ($validated['items'] as $item) {
$qty = floatval($item['quantite'] ?? 0);
$price = floatval($item['prix_unitaire'] ?? 0);
$totalHt += $qty * $price;
}
}
$tvaRate = floatval($validated['tva_rate'] ?? 20);
$totalTtc = $totalHt * (1 + ($tvaRate / 100));
$validated['total_ht'] = $totalHt;
$validated['total_ttc'] = $totalTtc;
$devi->update($validated);
return redirect()->route('devis.index')->with('success', 'Devis mis à jour avec succès.');
}
public function destroy(Devis $devi)
{
$devi->delete();
return redirect()->route('devis.index')->with('success', 'Devis supprimé avec succès.');
}
public function settings()
{
$settings = DevisSetting::first() ?? DevisSetting::create([
'entity_name' => "Direction des Systèmes d'Information",
'entity_sub' => "Communauté d'Agglomération Béziers Méditerranée",
'email' => "support.informatique@beziers-mediterranee.fr",
'telephone' => "04.67.01.60.00",
'adresse' => "Béziers, France",
]);
return Inertia::render('Devis/Settings', [
'settings' => $settings
]);
}
public function updateSettings(Request $request)
{
$validated = $request->validate([
'entity_name' => 'required|string|max:255',
'entity_sub' => 'required|string|max:255',
'email' => 'required|email|max:255',
'telephone' => 'required|string|max:50',
'adresse' => 'nullable|string|max:255',
]);
$settings = DevisSetting::first();
if ($settings) {
$settings->update($validated);
} else {
DevisSetting::create($validated);
}
return redirect()->route('devis.index')->with('success', 'Paramètres du devis mis à jour avec succès.');
}
public function downloadPdf(Devis $devi)
{
$settings = DevisSetting::first() ?? DevisSetting::create([
'entity_name' => "Direction des Systèmes d'Information",
'entity_sub' => "Communauté d'Agglomération Béziers Méditerranée",
'email' => "support.informatique@beziers-mediterranee.fr",
'telephone' => "04.67.01.60.00",
'adresse' => "Béziers, France",
]);
$pdf = Pdf::loadView('pdf.devis', [
'devis' => $devi,
'settings' => $settings,
]);
return $pdf->download("devis-{$devi->number}.pdf");
}
}