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 */ private function righe(?AnnoTeocratico $anno = null): Collection { $metodo = new ReflectionMethod(Registro::class, 'righeS13'); return $metodo->invoke(new Registro(), $anno ?? $this->anno); } }