finale 2.0.0
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user