feat: dashboard amélioré, exports budgets, alertes expiration et correctifs

## Dashboard
- Refonte complète du tableau de bord avec widgets budgets, commandes, contrats
- Intégration des données d'exécution budgétaire en temps réel

## Exports & Rapports
- BudgetExecutionExport : export Excel de l'exécution budgétaire
- Template PDF budgets (budgets_pdf.blade.php)
- Routes d'export PDF et Excel

## Alertes & Notifications
- Commande CheckExpirations : détection des contrats/assets arrivant à échéance
- Mail ExpiringElementsMail avec template Blade
- Planification via routes/console.php

## Correctifs
- CommandePolicy et ContratPolicy : ajustements des règles d'autorisation
- ContratController : corrections mineures
- Commande model : ajustements relations/casts
- AuthenticatedLayout : refonte navigation avec icônes budgets
- Assets/Form.vue : corrections formulaire
- Seeder rôles/permissions mis à jour
- Dépendances composer mises à jour (barryvdh/laravel-dompdf, maatwebsite/excel)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
jeremy bayse
2026-04-11 20:20:49 +02:00
parent 0ad77de412
commit 04fc56cd70
18 changed files with 1403 additions and 229 deletions

View File

@@ -0,0 +1,89 @@
<?php
namespace App\Console\Commands;
use App\Models\Asset;
use App\Models\Contrat;
use App\Models\Licence;
use App\Models\Domaine;
use App\Models\User;
use App\Mail\ExpiringElementsMail;
use Carbon\Carbon;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Mail;
class CheckExpirations extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'app:check-expirations';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Vérifie les éléments arrivant à échéance (contrats, licences, garanties) et envoie une notification par email.';
/**
* Execute the console command.
*/
public function handle()
{
$threshold = 30; // jours
$today = Carbon::today();
$limitDate = Carbon::today()->addDays($threshold);
// 1. Contrats arrivant à échéance
$contrats = Contrat::whereBetween('date_echeance', [$today, $limitDate])
->whereNotIn('statut', ['resilie', 'expire'])
->get();
// 2. Licences expirant bientôt
$licences = Licence::whereBetween('date_expiration', [$today, $limitDate])
->get();
// 3. Garanties d'assets expirant bientôt
$assets = Asset::whereBetween('date_fin_garantie', [$today, $limitDate])
->get();
// 4. Domaines arrivant à échéance
$domaines = Domaine::whereBetween('date_echeance', [$today, $limitDate])
->get();
if ($contrats->isEmpty() && $licences->isEmpty() && $assets->isEmpty() && $domaines->isEmpty()) {
$this->info('Aucun élément n\'arrive à échéance prochainement.');
return 0;
}
$this->info(sprintf(
'Trouvé : %d contrats, %d licences, %d assets et %d domaines à notifier.',
$contrats->count(),
$licences->count(),
$assets->count(),
$domaines->count()
));
// Récupérer les administrateurs et responsables
$recipients = User::role(['admin', 'responsable'])->get();
if ($recipients->isEmpty()) {
$this->warn('Aucun destinataire (admin ou responsable) trouvé.');
return 0;
}
foreach ($recipients as $recipient) {
Mail::to($recipient->email)->send(new ExpiringElementsMail($contrats, $licences, $assets, $domaines));
}
$this->info('Emails de notification envoyés.');
return 0;
}
}