- LimitaSorvegliante: la rotta delle azioni di Livewire 3.7 si chiama "default.livewire.update"; con 'livewire.*' ogni clic era un 403. - Territorio::ordinaPerPriorita(): la regola di "Da assegnare" della Home in un metodo solo, usato dalla Home, dall'aggiunta al pacchetto e da "Il mio gruppo". - Aggiunta al pacchetto: ricerca, zona, tipologia, solo prioritari, "Seleziona tutti quelli mostrati", badge e giorni di fermo. - Il mio gruppo: da dare in ordine di priorita' poi i gia' dati; filtri stato, zona, tipologia, solo prioritari; sotto il titolo nome e cognome del sorvegliante. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
153 lines
5.9 KiB
PHP
153 lines
5.9 KiB
PHP
<?php
|
|
|
|
namespace App\Livewire;
|
|
|
|
use Livewire\Component;
|
|
use App\Models\Territorio;
|
|
use App\Models\Proclamatore;
|
|
use App\Models\Assegnazione;
|
|
use App\Models\AnnoTeocratico;
|
|
use App\Models\Campagna;
|
|
use App\Models\Setting;
|
|
use Barryvdh\DomPDF\Facade\Pdf;
|
|
|
|
class Home extends Component
|
|
{
|
|
public function downloadPdfDaAssegnare()
|
|
{
|
|
$this->authorize('territori.assign');
|
|
|
|
$settings = Setting::instance();
|
|
|
|
$territori = Territorio::ordinaPerPriorita(
|
|
Territorio::inReparto()->with('zona', 'tipologia', 'ultimaAssegnazione')->get()
|
|
);
|
|
|
|
$pdf = Pdf::loadView('pdf.territori-lista', [
|
|
'titolo' => 'Territori da Assegnare',
|
|
'congregazione' => $settings->congregazione_nome ?? 'TerManager2',
|
|
'data' => now()->format('d/m/Y'),
|
|
'territori' => $territori,
|
|
'tipo' => 'assegnare',
|
|
]);
|
|
|
|
return response()->streamDownload(
|
|
fn () => print($pdf->output()),
|
|
'territori-da-assegnare-' . now()->format('Y-m-d') . '.pdf'
|
|
);
|
|
}
|
|
|
|
public function downloadPdfDaRientrare()
|
|
{
|
|
$this->authorize('territori.return');
|
|
|
|
$settings = Setting::instance();
|
|
|
|
$territori = Territorio::daRientrare()
|
|
->with(['zona', 'assegnazioneCorrente.proclamatore'])
|
|
->get();
|
|
|
|
$pdf = Pdf::loadView('pdf.territori-lista', [
|
|
'titolo' => 'Territori da Rientrare',
|
|
'congregazione' => $settings->congregazione_nome ?? 'TerManager2',
|
|
'data' => now()->format('d/m/Y'),
|
|
'territori' => $territori,
|
|
'tipo' => 'rientrare',
|
|
]);
|
|
|
|
return response()->streamDownload(
|
|
fn () => print($pdf->output()),
|
|
'territori-da-rientrare-' . now()->format('Y-m-d') . '.pdf'
|
|
);
|
|
}
|
|
|
|
public function render()
|
|
{
|
|
$settings = Setting::instance();
|
|
$homeLimit = max(1, (int) ($settings->home_limit_list ?? 10));
|
|
$annoCorrente = AnnoTeocratico::corrente();
|
|
$campagnaAttiva = Campagna::attiva();
|
|
|
|
// Territory counts
|
|
$totTerritoriAttivi = Territorio::where('attivo', true)->count();
|
|
$totAssegnati = Territorio::assegnato()->count();
|
|
$totInReparto = Territorio::inReparto()->count();
|
|
|
|
// Coverage: returned territories per current theocratic year
|
|
$territoriPercorsi = 0;
|
|
if ($annoCorrente) {
|
|
$territoriPercorsi = Assegnazione::where('anno_teocratico_id', $annoCorrente->id)
|
|
->whereNotNull('returned_at')
|
|
->distinct('territorio_id')
|
|
->count('territorio_id');
|
|
}
|
|
|
|
// Monthly average (territories/month this year)
|
|
$mediaPercorrenzaMensile = 0;
|
|
if ($annoCorrente && $annoCorrente->mesi_trascorsi > 0) {
|
|
$mediaPercorrenzaMensile = round($territoriPercorsi / $annoCorrente->mesi_trascorsi, 1);
|
|
}
|
|
|
|
// Average assignment duration in months (current year only, matches old app "Media Percorrenza Congregazione")
|
|
//
|
|
// Il calcolo sta in PHP e non in SQL. La versione precedente usava
|
|
// DATEDIFF() e YEAR(), che sono funzioni MySQL: rendevano questa pagina
|
|
// — la piu' visitata dell'applicazione — l'unica non verificabile dalla
|
|
// suite di test, che gira su SQLite. Il costo e' due colonne di date per
|
|
// le assegnazioni chiuse di un anno di servizio: qualche centinaio di
|
|
// righe, non un tavolo intero.
|
|
//
|
|
// I due filtri sono quelli di prima: le date assurde arrivate dalla
|
|
// conversione del vecchio database, e le durate non positive, che
|
|
// altrimenti abbasserebbero la media senza significare niente.
|
|
$avgGiorni = null;
|
|
if ($annoCorrente) {
|
|
$durate = Assegnazione::where('anno_teocratico_id', $annoCorrente->id)
|
|
->whereNotNull('returned_at')
|
|
->get(['assigned_at', 'returned_at'])
|
|
->filter(fn (Assegnazione $a) => $a->assigned_at?->year >= 1900)
|
|
->map(fn (Assegnazione $a) => $a->assigned_at->diffInDays($a->returned_at, false))
|
|
->filter(fn (float $giorni) => $giorni > 0);
|
|
|
|
$avgGiorni = $durate->isEmpty() ? null : $durate->avg();
|
|
}
|
|
$mediaDurataPercorrenzaMesi = $avgGiorni ? round($avgGiorni / 30.44, 1) : 0;
|
|
|
|
// Campaign stats
|
|
$campagnaStats = null;
|
|
if ($campagnaAttiva) {
|
|
$campagnaStats = [
|
|
'descrizione' => $campagnaAttiva->descrizione,
|
|
'percentuale' => $campagnaAttiva->percentuale_percorrenza,
|
|
'fine' => $campagnaAttiva->end_date->format('d/m/Y'),
|
|
];
|
|
}
|
|
|
|
// Quick lists: la logica di priorità sta in Territorio::ordinaPerPriorita
|
|
// (la usano anche il pacchetto dei gruppi di servizio e "Il mio gruppo").
|
|
$territoriDaAssegnare = Territorio::ordinaPerPriorita(
|
|
Territorio::inReparto()->with('zona', 'tipologia', 'ultimaAssegnazione')->get()
|
|
)->take($homeLimit)->values();
|
|
|
|
$daRientrare = Territorio::daRientrare()
|
|
->with(['zona', 'assegnazioneCorrente.proclamatore'])
|
|
->take($homeLimit)
|
|
->get();
|
|
|
|
return view('livewire.home', [
|
|
'congregazione' => $settings->congregazione_nome ?? 'TerManager2',
|
|
'annoCorrente' => $annoCorrente,
|
|
'totTerritoriAttivi' => $totTerritoriAttivi,
|
|
'totAssegnati' => $totAssegnati,
|
|
'totInReparto' => $totInReparto,
|
|
'territoriPercorsi' => $territoriPercorsi,
|
|
'mediaPercorrenzaMensile' => $mediaPercorrenzaMensile,
|
|
'mediaDurataPercorrenzaMesi' => $mediaDurataPercorrenzaMesi,
|
|
'campagnaStats' => $campagnaStats,
|
|
'homeLimit' => $homeLimit,
|
|
'territoriDaAssegnare' => $territoriDaAssegnare,
|
|
'daRientrare' => $daRientrare,
|
|
]);
|
|
}
|
|
}
|