finale 2.0.0

This commit is contained in:
2026-06-09 11:22:56 +02:00
parent 7d7d384a0d
commit b7842bf2e0
57 changed files with 1707 additions and 172 deletions
+158 -2
View File
@@ -11,6 +11,7 @@ use App\Models\Evento;
use App\Models\Documento;
use App\Models\MailingList;
use App\Models\Contatto;
use App\Models\Tag;
use App\Models\TipologiaDocumento;
use App\Models\ReportCustom;
use Illuminate\Http\Request;
@@ -47,12 +48,15 @@ class ReportController extends Controller
$columnOptions[$type] = ReportColumnRegistry::getColumns($type);
}
$allTags = Tag::orderBy('name')->get();
return view('report.index', compact(
'stats',
'prebuiltReports',
'customReports',
'tipologieDocumento',
'columnOptions'
'columnOptions',
'allTags'
));
}
@@ -136,6 +140,14 @@ class ReportController extends Controller
$config['search_columns'] = $request->input('search_columns');
}
if ($request->has('tag_filter')) {
$config['tag_filter'] = $request->input('tag_filter');
}
if ($request->filled('tag_filter_mode')) {
$config['tag_filter_mode'] = $request->input('tag_filter_mode');
}
ReportCustom::create([
'user_id' => auth()->id(),
'nome' => $data['nome'],
@@ -252,6 +264,9 @@ class ReportController extends Controller
'documenti_completo' => $this->reportDocumentiCompleto($tipologiaFilter),
'contatti_completo' => $this->reportContattiCompleto(),
'scadenze_documenti' => $this->reportScadenzeDocumenti($tipologiaFilter),
'tag_statistiche' => $this->reportTagStatistiche(),
'individui_per_tag' => $this->reportIndividuiPerTag(),
'documenti_per_tag' => $this->reportDocumentiPerTag(),
default => null,
};
}
@@ -403,6 +418,30 @@ class ReportController extends Controller
'colore' => 'teal',
'has_tipologia_filter' => false,
],
[
'id' => 'tag_statistiche',
'nome' => 'Statistiche Tag',
'descrizione' => 'Distribuzione degli elementi per tag (individui, gruppi, eventi, documenti, mailing list)',
'icona' => 'fa-tags',
'colore' => 'indigo',
'has_tipologia_filter' => false,
],
[
'id' => 'individui_per_tag',
'nome' => 'Individui per Tag',
'descrizione' => 'Elenco completo degli individui raggruppati per tag assegnato',
'icona' => 'fa-user-tag',
'colore' => 'info',
'has_tipologia_filter' => false,
],
[
'id' => 'documenti_per_tag',
'nome' => 'Documenti per Tag',
'descrizione' => 'Elenco completo dei documenti raggruppati per tag assegnato',
'icona' => 'fa-tags',
'colore' => 'secondary',
'has_tipologia_filter' => false,
],
];
}
@@ -927,6 +966,102 @@ class ReportController extends Controller
];
}
protected function reportTagStatistiche(): array
{
$tags = Tag::orderBy('name')->get();
$rows = $tags->map(function ($tag) {
return [
'name' => $tag->name,
'color' => $tag->color ?? '#6c757d',
'individui' => $tag->individui()->count(),
'gruppi' => $tag->gruppi()->count(),
'eventi' => $tag->eventi()->count(),
'documenti' => $tag->documenti()->count(),
'mailing' => $tag->mailingLists()->count(),
'totale' => $tag->count,
];
})->toArray();
$totalIndividui = array_sum(array_column($rows, 'individui'));
$totalGruppi = array_sum(array_column($rows, 'gruppi'));
$totalEventi = array_sum(array_column($rows, 'eventi'));
$totalDocumenti = array_sum(array_column($rows, 'documenti'));
$totalMailing = array_sum(array_column($rows, 'mailing'));
return [
'title' => 'Statistiche Tag',
'headers' => ['Tag', 'Individui', 'Gruppi', 'Eventi', 'Documenti', 'Mailing List', 'Totale Elementi'],
'rows' => array_map(fn($r) => [$r['name'], $r['individui'], $r['gruppi'], $r['eventi'], $r['documenti'], $r['mailing'], $r['totale']], $rows),
'summary' => 'Tag: ' . count($tags) . ' | Individui: ' . $totalIndividui . ' | Gruppi: ' . $totalGruppi . ' | Eventi: ' . $totalEventi . ' | Documenti: ' . $totalDocumenti . ' | Mailing List: ' . $totalMailing,
'detail_rows' => $rows,
];
}
protected function reportIndividuiPerTag(): array
{
$individui = Individuo::with('tags')
->whereHas('tags')
->orderBy('cognome')
->orderBy('nome')
->get();
$rows = $individui->flatMap(function ($ind) {
if ($ind->tags->isEmpty()) {
return collect();
}
return $ind->tags->map(function ($tag) use ($ind) {
return [
'tag' => $tag->name,
'tag_color' => $tag->color ?? '#6c757d',
'codice' => $ind->codice_id,
'cognome' => $ind->cognome,
'nome' => $ind->nome,
'email' => $ind->email_primaria ?? '-',
];
});
})->toArray();
return [
'title' => 'Individui per Tag',
'headers' => ['Tag', 'Codice', 'Cognome', 'Nome', 'Email'],
'rows' => array_map(fn($r) => [$r['tag'], $r['codice'], $r['cognome'], $r['nome'], $r['email']], $rows),
'summary' => 'Totale righe (individuo × tag): ' . count($rows),
'detail_rows' => $rows,
];
}
protected function reportDocumentiPerTag(): array
{
$documenti = Documento::with('tags')
->whereHas('tags')
->orderBy('nome_file')
->get();
$rows = $documenti->flatMap(function ($doc) {
if ($doc->tags->isEmpty()) {
return collect();
}
return $doc->tags->map(function ($tag) use ($doc) {
return [
'tag' => $tag->name,
'tag_color' => $tag->color ?? '#6c757d',
'nome_file' => $doc->nome_file,
'tipologia' => ucfirst((string) $doc->tipologia),
'data' => $doc->created_at->format('d/m/Y'),
];
});
})->toArray();
return [
'title' => 'Documenti per Tag',
'headers' => ['Tag', 'Nome File', 'Tipologia', 'Data Caricamento'],
'rows' => array_map(fn($r) => [$r['tag'], $r['nome_file'], $r['tipologia'], $r['data']], $rows),
'summary' => 'Totale righe (documento × tag): ' . count($rows),
'detail_rows' => $rows,
];
}
protected function runCustomReport(ReportCustom $report): array
{
$tipo = $report->tipo_report;
@@ -954,11 +1089,32 @@ class ReportController extends Controller
$columns = $config['columns'] ?? [];
$hasRelations = false;
// Always load tags if tags column or tag filter is present
$needsTags = in_array('tags.nome', $columns) || !empty($config['tag_filter']);
if ($needsTags) {
$query->with('tags');
}
foreach ($columns as $col) {
if (str_contains($col, '.')) {
$hasRelations = true;
$relation = explode('.', $col)[0];
$query->with($relation);
if ($relation !== 'tags') {
$query->with($relation);
}
}
}
// Apply tag filter
if (!empty($config['tag_filter'])) {
$tagSlugs = Tag::whereIn('id', (array) $config['tag_filter'])->pluck('slug')->toArray();
if (!empty($tagSlugs)) {
$mode = $config['tag_filter_mode'] ?? 'any';
if ($mode === 'all') {
$query->withAllTags($tagSlugs);
} else {
$query->withAnyTags($tagSlugs);
}
}
}