++ gruppi: sorvegliante non piu' attivo scioglie il gruppo; dettagli del gruppo nella scheda e nel profilo

- Proclamatore::booted: reso non attivo, spostato nel cestino o
  anonimizzato, il sorvegliante scioglie il gruppo (territori non dati in
  reparto, membri liberi, utenza disattivata); il motivo va nel registro.
  L'elenco chiede conferma, la modifica avvisa sotto "Attivo". Un membro
  nel cestino esce dal gruppo.
- Scheda del proclamatore: gruppo guidato con membri, pacchetto, da dare,
  assegnazioni dal gruppo, utenza e ultimo accesso; oppure gruppo di cui
  e' membro; gruppi sciolti guidati in passato.
- Profilo del sorvegliante: il suo gruppo con gli stessi numeri.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Francesco Picone
2026-10-20 10:48:37 +02:00
parent 9999a3b031
commit 4d9e445cba
14 changed files with 370 additions and 48 deletions

View File

@@ -377,24 +377,120 @@ class GruppiServizioTest extends TestCase
$this->assertSame($nuovo->id, $utente->gruppoSorvegliato()?->id);
}
// ─── Proclamatori: cestino, anonimizzazione, registro ───────
// ─── Sorvegliante non più attivo: il gruppo si scioglie ─────
public function test_il_sorvegliante_di_un_gruppo_attivo_non_si_cestina_ne_si_anonimizza(): void
/** Il gruppo è sciolto come da "Togli il ruolo": tutto tranne l'assegnazione già fatta. */
private function assertSciolto(array $g, Assegnazione $data): void
{
['rossi' => $rossi, 'verdi' => $verdi] = $this->gruppo();
$this->assertNotNull($g['gruppo']->fresh()->sciolto_at, 'Gruppo sciolto');
$this->assertNull($g['territori'][1]->fresh()->gruppo_servizio_id, 'I non dati tornano in reparto');
$this->assertSame('in_reparto', $g['territori'][2]->fresh()->stato);
$this->assertNull($data->fresh()->returned_at, 'Quello già dato resta al membro');
$this->assertNull($g['bianchi']->fresh()->gruppo_servizio_id, 'Membri liberi');
$this->assertTrue($g['sorvegliante']->fresh()->isDisattivato());
$this->assertFalse($g['sorvegliante']->fresh()->hasRole('sorvegliante'));
}
public function test_disattivare_il_sorvegliante_dall_elenco_scioglie_il_gruppo(): void
{
$g = $this->gruppo();
$data = app(GruppiServizio::class)->assegna($g['gruppo'], $g['territori'][0], $g['verdi'], now());
Livewire::test(\App\Livewire\Proclamatori\ProclamatoreIndex::class)
->call('deleteProclamatore', $rossi->id)
->call('anonimizza', $rossi->id);
$this->assertFalse($rossi->fresh()->trashed());
$this->assertSame('Rossi', $rossi->fresh()->cognome);
->assertSeeHtml('è il sorvegliante del gruppo Zisa')
->call('toggleActive', $g['rossi']->id)
->assertDispatched('avviso', fn ($nome, $parametri) => str_contains($parametri['testo'], 'il gruppo è stato sciolto'));
// Un membro qualsiasi sì, e lascia il gruppo.
Livewire::test(\App\Livewire\Proclamatori\ProclamatoreIndex::class)->call('deleteProclamatore', $verdi->id);
$this->assertTrue($verdi->fresh()->trashed());
$this->assertNull($verdi->fresh()->gruppo_servizio_id);
$this->assertFalse($g['rossi']->fresh()->attivo);
$this->assertSciolto($g, $data);
// Riattivarlo non ricostruisce il gruppo: se ne crea uno nuovo.
Livewire::test(\App\Livewire\Proclamatori\ProclamatoreIndex::class)->call('toggleActive', $g['rossi']->id);
$this->assertNotNull($g['gruppo']->fresh()->sciolto_at);
$this->assertNull($g['rossi']->fresh()->gruppoSorvegliato());
}
public function test_disattivare_il_sorvegliante_dalla_modifica_scioglie_il_gruppo(): void
{
$g = $this->gruppo();
$data = app(GruppiServizio::class)->assegna($g['gruppo'], $g['territori'][0], $g['verdi'], now());
$this->get(route('proclamatori.edit', $g['rossi']))->assertOk()->assertSee('se non è più attivo il gruppo si scioglie');
Livewire::test(\App\Livewire\Proclamatori\ProclamatoreEdit::class, ['proclamatore' => $g['rossi']])
->set('attivo', false)
->call('save')
->assertHasNoErrors();
$this->assertSciolto($g, $data);
$this->assertStringContainsString('il gruppo è stato sciolto', session('success'));
}
public function test_spostare_nel_cestino_il_sorvegliante_scioglie_il_gruppo(): void
{
$g = $this->gruppo();
$data = app(GruppiServizio::class)->assegna($g['gruppo'], $g['territori'][0], $g['verdi'], now());
Livewire::test(\App\Livewire\Proclamatori\ProclamatoreIndex::class)->call('deleteProclamatore', $g['rossi']->id);
$this->assertTrue($g['rossi']->fresh()->trashed());
$this->assertSciolto($g, $data);
}
public function test_disattivare_o_cestinare_un_membro_non_scioglie_il_gruppo(): void
{
['gruppo' => $gruppo, 'verdi' => $verdi, 'bianchi' => $bianchi] = $this->gruppo();
Livewire::test(\App\Livewire\Proclamatori\ProclamatoreIndex::class)
->call('toggleActive', $verdi->id)
->call('deleteProclamatore', $bianchi->id);
$this->assertNull($gruppo->fresh()->sciolto_at);
$this->assertSame($gruppo->id, $verdi->fresh()->gruppo_servizio_id, 'Non attivo resta membro, ma non riceve territori');
$this->assertNull($bianchi->fresh()->gruppo_servizio_id, 'Nel cestino lascia il gruppo');
}
// ─── Dettagli del gruppo nel profilo ────────────────────────
public function test_la_scheda_del_proclamatore_mostra_il_gruppo_che_guida(): void
{
$g = $this->gruppo();
app(GruppiServizio::class)->assegna($g['gruppo'], $g['territori'][0], $g['verdi'], now());
$this->get(route('proclamatori.show', $g['rossi']))->assertOk()
->assertSeeInOrder(['Gruppo di servizio', 'Sorvegliante', 'Zisa', 'Membri', '3', 'Nel pacchetto', '3', 'Da dare', '2', 'Assegnazioni dal gruppo', '1'])
->assertSee('mario@example.test')
->assertSee('non è ancora entrato');
$this->get(route('proclamatori.show', $g['verdi']))->assertOk()
->assertSee('Membro del gruppo')
->assertSee('sorvegliante Rossi Mario');
app(GruppiServizio::class)->sciogli($g['gruppo']);
$this->get(route('proclamatori.show', $g['rossi']))->assertOk()
->assertSee('In passato sorvegliante di:')
->assertDontSee('Assegnazioni dal gruppo');
}
public function test_il_profilo_del_sorvegliante_mostra_il_suo_gruppo(): void
{
$g = $this->gruppo();
app(GruppiServizio::class)->assegna($g['gruppo'], $g['territori'][0], $g['verdi'], now());
$this->flushSession();
$this->actingAs($g['sorvegliante'])->get(route('profile'))->assertOk()
->assertSee('Il tuo gruppo di servizio')
->assertSeeInOrder(['Zisa', 'Membri', '3', 'Nel pacchetto', '3', 'Da dare', '2', 'Dati ai membri', '1'])
->assertSee('Torna al mio gruppo');
// L'amministratore un gruppo suo non ce l'ha.
$this->actingAs($this->admin)->get(route('profile'))->assertOk()
->assertDontSee('Il tuo gruppo di servizio')
->assertSee('Torna alla home');
}
// ─── Proclamatori: anonimizzazione, registro ────────────────
public function test_anonimizzare_un_ex_sorvegliante_anonimizza_anche_la_sua_utenza(): void
{
['gruppo' => $gruppo, 'rossi' => $rossi, 'sorvegliante' => $s] = $this->gruppo();