++ fix e controlli

This commit is contained in:
2026-07-30 17:05:39 +02:00
parent 712336d652
commit 440d63a6b9
54 changed files with 4921 additions and 1322 deletions

View File

@@ -0,0 +1,333 @@
<?php
namespace Tests\Feature;
use App\Livewire\Registro;
use App\Models\AnnoTeocratico;
use App\Models\Assegnazione;
use App\Models\Proclamatore;
use App\Models\Territorio;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Collection;
use ReflectionMethod;
use Tests\TestCase;
/**
* Modulo S-13-I: il ciclo da quattro gruppi "Assegnato a" e la colonna
* "Restituito l'ultima volta il".
*
* E' la regola meno intuitiva del Registro — la quinta assegnazione non si
* aggiunge alle quattro precedenti, le sostituisce — e finisce su un modulo che
* viene firmato e archiviato: se sbaglia, sbaglia su carta.
*
* righeS13() e' privata di proposito (non e' un'azione Livewire); qui la si
* chiama in riflessione perche' e' il calcolo, non il PDF, quello da proteggere.
*/
class RegistroS13Test extends TestCase
{
use RefreshDatabase;
private User $utente;
private Proclamatore $proclamatore;
private AnnoTeocratico $anno;
protected function setUp(): void
{
parent::setUp();
$this->utente = User::create([
'name' => 'Amministratore',
'email' => 'admin@example.test',
'password' => 'password',
]);
$this->proclamatore = Proclamatore::create([
'nome' => 'Mario',
'cognome' => 'Rossi',
'attivo' => true,
]);
$this->anno = AnnoTeocratico::create([
'label' => '2025-2026',
'start_date' => '2025-09-01',
'end_date' => '2026-08-31',
]);
}
// ─── Il primo ciclo ─────────────────────────────────────────
public function test_una_sola_assegnazione_riempie_la_prima_colonna_e_lascia_le_altre_in_bianco(): void
{
$territorio = $this->territorio('1');
$this->assegna($territorio, '2025-09-10', '2025-10-15');
$riga = $this->righe()->sole();
$this->assertSame('1', $riga['numero']);
$this->assertSame('', $riga['riporto']);
$this->assertCount(4, $riga['assegnazioni']);
$this->assertSame(
['nome' => 'Rossi Mario', 'assegnato_il' => '10/09/2025', 'restituito_il' => '15/10/2025'],
$riga['assegnazioni'][0]
);
// Le colonne libere restano stampate: sul modulo cartaceo si compilano
// a mano.
foreach ([1, 2, 3] as $indice) {
$this->assertSame(
['nome' => '', 'assegnato_il' => '', 'restituito_il' => ''],
$riga['assegnazioni'][$indice]
);
}
}
public function test_un_assegnazione_ancora_aperta_ha_la_data_di_rientro_vuota(): void
{
$territorio = $this->territorio('1');
$this->assegna($territorio, '2025-09-10');
$riga = $this->righe()->sole();
$this->assertSame('10/09/2025', $riga['assegnazioni'][0]['assegnato_il']);
$this->assertSame('', $riga['assegnazioni'][0]['restituito_il']);
}
public function test_tre_assegnazioni_occupano_le_prime_tre_colonne(): void
{
$territorio = $this->territorio('1');
$this->assegna($territorio, '2025-09-01', '2025-09-20');
$this->assegna($territorio, '2025-10-01', '2025-10-20');
$this->assegna($territorio, '2025-11-01', '2025-11-20');
$riga = $this->righe()->sole();
$this->assertSame(
['01/09/2025', '01/10/2025', '01/11/2025', ''],
array_column($riga['assegnazioni'], 'assegnato_il')
);
$this->assertSame('', $riga['riporto']);
}
public function test_quattro_assegnazioni_riempiono_la_riga_senza_riporto(): void
{
$territorio = $this->territorio('1');
$this->assegna($territorio, '2025-09-01', '2025-09-20');
$this->assegna($territorio, '2025-10-01', '2025-10-20');
$this->assegna($territorio, '2025-11-01', '2025-11-20');
$this->assegna($territorio, '2025-12-01', '2025-12-20');
$riga = $this->righe()->sole();
$this->assertSame(
['01/09/2025', '01/10/2025', '01/11/2025', '01/12/2025'],
array_column($riga['assegnazioni'], 'assegnato_il')
);
// Finche' il primo ciclo non e' esaurito non c'e' niente da riportare.
$this->assertSame('', $riga['riporto']);
}
// ─── Il ciclo che ricomincia ────────────────────────────────
/**
* Il caso che da' il nome alla regola: riempito il quarto gruppo si
* ricomincia da capo, come sul modulo cartaceo si aprirebbe una riga nuova.
* Le prime quattro assegnazioni escono dal modulo e restano solo nel
* riporto.
*/
public function test_la_quinta_assegnazione_apre_un_ciclo_nuovo_e_lascia_il_riporto(): void
{
$territorio = $this->territorio('1');
$this->assegna($territorio, '2025-09-01', '2025-09-20');
$this->assegna($territorio, '2025-10-01', '2025-10-20');
$this->assegna($territorio, '2025-11-01', '2025-11-20');
$this->assegna($territorio, '2025-12-01', '2025-12-24');
$this->assegna($territorio, '2026-01-05', '2026-01-25');
$riga = $this->righe()->sole();
$this->assertSame(
['05/01/2026', '', '', ''],
array_column($riga['assegnazioni'], 'assegnato_il')
);
// La colonna riporta la data di rientro della quarta, cioe' quella che
// chiudeva il giro precedente — senza il nome di chi lo aveva.
$this->assertSame('24/12/2025', $riga['riporto']);
}
public function test_otto_assegnazioni_mostrano_il_secondo_ciclo_per_intero(): void
{
$territorio = $this->territorio('1');
$date = [
['2025-09-01', '2025-09-20'],
['2025-10-01', '2025-10-20'],
['2025-11-01', '2025-11-20'],
['2025-12-01', '2025-12-24'],
['2026-01-05', '2026-01-25'],
['2026-02-05', '2026-02-25'],
['2026-03-05', '2026-03-25'],
['2026-04-05', '2026-04-25'],
];
foreach ($date as [$da, $a]) {
$this->assegna($territorio, $da, $a);
}
$riga = $this->righe()->sole();
$this->assertSame(
['05/01/2026', '05/02/2026', '05/03/2026', '05/04/2026'],
array_column($riga['assegnazioni'], 'assegnato_il')
);
$this->assertSame('24/12/2025', $riga['riporto']);
}
public function test_alla_nona_assegnazione_il_riporto_e_quello_dell_ottava(): void
{
$territorio = $this->territorio('1');
$date = [
['2025-09-01', '2025-09-20'],
['2025-10-01', '2025-10-20'],
['2025-11-01', '2025-11-20'],
['2025-12-01', '2025-12-24'],
['2026-01-05', '2026-01-25'],
['2026-02-05', '2026-02-25'],
['2026-03-05', '2026-03-25'],
['2026-04-05', '2026-04-28'],
['2026-05-05', null],
];
foreach ($date as [$da, $a]) {
$this->assegna($territorio, $da, $a);
}
$riga = $this->righe()->sole();
$this->assertSame(
['05/05/2026', '', '', ''],
array_column($riga['assegnazioni'], 'assegnato_il')
);
$this->assertSame('28/04/2026', $riga['riporto']);
}
/**
* Il riporto legge la data di rientro dell'ultima assegnazione del giro
* precedente: se quella e' ancora aperta la colonna resta vuota invece di
* inventarsi una data.
*/
public function test_il_riporto_resta_vuoto_se_l_ultima_del_giro_precedente_non_e_rientrata(): void
{
$territorio = $this->territorio('1');
$this->assegna($territorio, '2025-09-01', '2025-09-20');
$this->assegna($territorio, '2025-10-01', '2025-10-20');
$this->assegna($territorio, '2025-11-01', '2025-11-20');
$this->assegna($territorio, '2025-12-01', null);
$this->assegna($territorio, '2026-01-05', '2026-01-25');
$riga = $this->righe()->sole();
$this->assertSame('05/01/2026', $riga['assegnazioni'][0]['assegnato_il']);
$this->assertSame('', $riga['riporto']);
}
// ─── Cosa entra nel modulo ──────────────────────────────────
public function test_i_territori_disattivati_restano_fuori_dal_modulo(): void
{
$attivo = $this->territorio('1');
$disattivato = $this->territorio('2', attivo: false);
$this->assegna($attivo, '2025-09-01');
$this->assegna($disattivato, '2025-09-01');
$this->assertSame(['1'], $this->righe()->pluck('numero')->all());
}
public function test_i_territori_nel_cestino_restano_fuori_dal_modulo(): void
{
$vivo = $this->territorio('1');
$cestinato = $this->territorio('2');
$this->assegna($vivo, '2025-09-01');
$this->assegna($cestinato, '2025-09-01');
$cestinato->delete();
$this->assertSame(['1'], $this->righe()->pluck('numero')->all());
}
public function test_le_assegnazioni_di_un_altro_anno_di_servizio_non_compaiono(): void
{
$altroAnno = AnnoTeocratico::create([
'label' => '2024-2025',
'start_date' => '2024-09-01',
'end_date' => '2025-08-31',
]);
$territorio = $this->territorio('1');
$this->assegna($territorio, '2025-09-01', '2025-09-20');
$this->assegna($territorio, '2025-01-10', '2025-02-10', $altroAnno);
$riga = $this->righe()->sole();
$this->assertSame(
['01/09/2025', '', '', ''],
array_column($riga['assegnazioni'], 'assegnato_il')
);
}
public function test_un_territorio_senza_assegnazioni_nell_anno_non_produce_una_riga(): void
{
$this->territorio('1');
$this->assertTrue($this->righe()->isEmpty());
}
/**
* I numeri di territorio sono stringhe ("1", "1 A", "10"): l'ordinamento e'
* naturale, non alfabetico, altrimenti il 10 finirebbe fra l'1 e il 2.
*/
public function test_le_righe_sono_in_ordine_naturale_di_numero(): void
{
foreach (['10', '2', '1 A', '1'] as $numero) {
$this->assegna($this->territorio($numero), '2025-09-01');
}
$this->assertSame(['1', '1 A', '2', '10'], $this->righe()->pluck('numero')->all());
}
// ─── helper ─────────────────────────────────────────────────
private function territorio(string $numero, bool $attivo = true): Territorio
{
return Territorio::create([
'numero' => $numero,
'attivo' => $attivo,
]);
}
private function assegna(
Territorio $territorio,
string $assegnatoIl,
?string $rientratoIl = null,
?AnnoTeocratico $anno = null
): Assegnazione {
return Assegnazione::create([
'territorio_id' => $territorio->id,
'proclamatore_id' => $this->proclamatore->id,
'anno_teocratico_id' => ($anno ?? $this->anno)->id,
'assigned_at' => $assegnatoIl,
'returned_at' => $rientratoIl,
'created_by' => $this->utente->id,
]);
}
/**
* @return Collection<int, array>
*/
private function righe(?AnnoTeocratico $anno = null): Collection
{
$metodo = new ReflectionMethod(Registro::class, 'righeS13');
return $metodo->invoke(new Registro(), $anno ?? $this->anno);
}
}