From cb6249b2168276e993ac2808d23beaed556131d9 Mon Sep 17 00:00:00 2001 From: michele Date: Wed, 2 Sep 2026 11:36:07 +0200 Subject: [PATCH] feat(temporal-ownership): gestione cronistoria temporale subentri stabile 0013 e allineamento catasto B-6 B-1 --- .../GesconBonificaStabile0013Command.php | 83 ++++++++++ app/Filament/Pages/UnitaImmobiliarePage.php | 83 ++++++++-- skill-netgescon/control-tower/CURRENT-205.md | 48 +++--- tests/Feature/UnitaGestioneTemporaleTest.php | 152 ++++++++++++++++++ 4 files changed, 336 insertions(+), 30 deletions(-) diff --git a/app/Console/Commands/GesconBonificaStabile0013Command.php b/app/Console/Commands/GesconBonificaStabile0013Command.php index f671d3f..9efb107 100644 --- a/app/Console/Commands/GesconBonificaStabile0013Command.php +++ b/app/Console/Commands/GesconBonificaStabile0013Command.php @@ -160,6 +160,89 @@ public function handle(): int $this->info('Unita 233 (Scala A Int. 1) allineata con dati Sister Catasto.'); } + // 6. Riallineamento Unita 247 (Scala B Int. 6) con dati ufficiali Catasto e subentro Coccia + $unit247 = UnitaImmobiliare::where('stabile_id', $stabile->id)->where('scala', 'B')->where('interno', '6')->first(); + if ($unit247) { + $unit247->subalterno = '25'; + $unit247->categoria_catastale = 'A/2'; + $unit247->rendita_catastale = 742.41; + $unit247->numero_vani = 2.5; + $unit247->denominazione = 'COCCIA Simone'; + $unit247->save(); + $this->info('Unita 247 (Scala B Int. 6) allineata con dati Sister Catasto (Sub 25, Rendita 742.41).'); + } + + // 7. Riallineamento Unita 242 (Scala B Int. 1) + $unit242 = UnitaImmobiliare::where('stabile_id', $stabile->id)->where('scala', 'B')->where('interno', '1')->first(); + if ($unit242) { + $unit242->subalterno = '20'; + $unit242->denominazione = 'Tabacchini Giuseppe'; + $unit242->save(); + $this->info('Unita 242 (Scala B Int. 1) allineata (Sub 20, Tabacchini Giuseppe).'); + } + + // 8. Allineamento temporale UAP per tutti i subentri dello Stabile 0013 + $subentriConfig = [ + // B-6 (ID 247) + ['scala' => 'B', 'interno' => '6', 'vecchio_nome' => 'DE SANTIS Fabio', 'data_fine_vecchio' => '2021-09-28', 'nuovo_nome' => 'COCCIA Simone', 'nuovo_cf' => 'CCCSMN74B06L120H', 'data_inizio_nuovo' => '2021-09-29'], + // B-1 (ID 242) + ['scala' => 'B', 'interno' => '1', 'vecchio_nome' => 'PAVIA Monica', 'data_fine_vecchio' => '2025-10-29', 'nuovo_nome' => 'Tabacchini Giuseppe', 'nuovo_cf' => null, 'data_inizio_nuovo' => '2025-10-30'], + // C-2 (ID 253) + ['scala' => 'C', 'interno' => '2', 'vecchio_nome' => 'TONTI Salvatore', 'data_fine_vecchio' => '2022-11-02', 'nuovo_nome' => 'LAI Lisu', 'nuovo_cf' => null, 'data_inizio_nuovo' => '2022-11-03'], + // C-5 (ID 256) + ['scala' => 'C', 'interno' => '5', 'vecchio_nome' => 'PALLADINO Pasquale', 'data_fine_vecchio' => '2023-02-28', 'nuovo_nome' => 'RACHED Francois Joseph', 'nuovo_cf' => null, 'data_inizio_nuovo' => '2023-03-01'], + // B-8 (ID 249) + ['scala' => 'B', 'interno' => '8', 'vecchio_nome' => 'MAURELLI Rossana', 'data_fine_vecchio' => '2023-09-28', 'nuovo_nome' => 'RANCHINO Valentina', 'nuovo_cf' => null, 'data_inizio_nuovo' => '2023-09-29', 'data_fine_nuovo' => '2024-10-02'], + ['scala' => 'B', 'interno' => '8', 'vecchio_nome' => 'RANCHINO Valentina', 'data_fine_vecchio' => '2024-10-02', 'nuovo_nome' => 'D\'ANIELLO Andrea', 'nuovo_cf' => null, 'data_inizio_nuovo' => '2024-10-03'], + // NGOT-103 (ID 264) + ['scala' => 'NGOT', 'interno' => '103', 'vecchio_nome' => 'GIUSTI GIAMPAOLO', 'data_fine_vecchio' => '2025-07-27', 'nuovo_nome' => 'SELLA LEASING S.p.A.', 'nuovo_cf' => null, 'data_inizio_nuovo' => '2025-07-28'], + // B-3 (ID 244) & B-4 (ID 245) + ['scala' => 'B', 'interno' => '3', 'vecchio_nome' => 'PICCOLO Pasqualina', 'data_fine_vecchio' => '2026-04-07', 'nuovo_nome' => 'RDP S.R.L.', 'nuovo_cf' => '14513691007', 'data_inizio_nuovo' => '2026-04-08'], + ['scala' => 'B', 'interno' => '4', 'vecchio_nome' => 'PICCOLO Pasqualina', 'data_fine_vecchio' => '2026-04-07', 'nuovo_nome' => 'RDP S.R.L.', 'nuovo_cf' => '14513691007', 'data_inizio_nuovo' => '2026-04-08'], + ]; + + foreach ($subentriConfig as $sc) { + $u = UnitaImmobiliare::where('stabile_id', $stabile->id)->where('scala', $sc['scala'])->where('interno', $sc['interno'])->first(); + if (!$u) { + continue; + } + + // Aggiorna vecchio intestatario con data_fine + $oldAnags = DB::table('anagrafiche') + ->where(function($q) use ($sc) { + $q->where('cognome', 'like', '%' . $sc['vecchio_nome'] . '%') + ->orWhere('nome', 'like', '%' . $sc['vecchio_nome'] . '%') + ->orWhere('ragione_sociale', 'like', '%' . $sc['vecchio_nome'] . '%'); + }) + ->pluck('id'); + + if ($oldAnags->isNotEmpty()) { + DB::table('unita_anagrafica_periodo') + ->where('unita_immobiliare_id', $u->id) + ->whereIn('anagrafica_id', $oldAnags) + ->update(['data_fine' => $sc['data_fine_vecchio']]); + } + + // Aggiorna o crea nuovo intestatario con data_inizio + $newAnag = DB::table('anagrafiche') + ->where(function($q) use ($sc) { + $q->where('cognome', 'like', '%' . $sc['nuovo_nome'] . '%') + ->orWhere('nome', 'like', '%' . $sc['nuovo_nome'] . '%') + ->orWhere('ragione_sociale', 'like', '%' . $sc['nuovo_nome'] . '%'); + }) + ->first(); + + if ($newAnag) { + DB::table('unita_anagrafica_periodo') + ->where('unita_immobiliare_id', $u->id) + ->where('anagrafica_id', $newAnag->id) + ->update([ + 'data_inizio' => $sc['data_inizio_nuovo'], + 'data_fine' => $sc['data_fine_nuovo'] ?? null, + ]); + } + } + $this->info('Bonifica Stabile 0013 completata con successo!'); return 0; } diff --git a/app/Filament/Pages/UnitaImmobiliarePage.php b/app/Filament/Pages/UnitaImmobiliarePage.php index 0ee93f3..d4b9a0c 100755 --- a/app/Filament/Pages/UnitaImmobiliarePage.php +++ b/app/Filament/Pages/UnitaImmobiliarePage.php @@ -928,8 +928,54 @@ protected function refreshUnitaOptions(): void } } + $activeAnno = \App\Support\AnnoGestioneContext::resolveActiveAnno(\Illuminate\Support\Facades\Auth::user()) ?: 2026; $currentNominativoByUnita = []; + if (DbSchema::hasTable('unita_anagrafica_periodo') && DbSchema::hasTable('anagrafiche')) { + try { + $startOfYear = "{$activeAnno}-01-01"; + $endOfYear = "{$activeAnno}-12-31"; + + $uapRows = DB::table('unita_anagrafica_periodo as uap') + ->join('anagrafiche as a', 'uap.anagrafica_id', '=', 'a.id') + ->whereIn('uap.unita_immobiliare_id', $unita->pluck('id')) + ->whereIn('uap.ruolo_occupazione', ['condomino', 'proprietario', 'comproprietario', 'nudo_proprietario', 'usufruttuario']) + ->where(function ($q) use ($endOfYear) { + $q->whereNull('uap.data_inizio') + ->orWhere('uap.data_inizio', '<=', $endOfYear); + }) + ->where(function ($q) use ($startOfYear) { + $q->whereNull('uap.data_fine') + ->orWhere('uap.data_fine', '>=', $startOfYear); + }) + ->orderBy('uap.id') + ->select('uap.unita_immobiliare_id', 'a.nome', 'a.cognome', 'a.ragione_sociale') + ->get(); + + foreach ($uapRows as $row) { + $unitId = (int) ($row->unita_immobiliare_id ?? 0); + if ($unitId <= 0) { + continue; + } + + $name = trim((string) ($row->ragione_sociale ?: ($row->cognome . ' ' . $row->nome))); + if ($name === '') { + $name = trim((string) ($row->nome . ' ' . $row->cognome)); + } + if ($name !== '') { + if (! isset($currentNominativoByUnita[$unitId])) { + $currentNominativoByUnita[$unitId] = []; + } + if (! in_array($name, $currentNominativoByUnita[$unitId], true)) { + $currentNominativoByUnita[$unitId][] = $name; + } + } + } + } catch (\Throwable $e) { + // Ignore fallback error + } + } + if (DbSchema::hasTable('rubrica_ruoli') && DbSchema::hasTable('rubrica_universale')) { try { $rows = DB::table('rubrica_ruoli as rr') @@ -943,7 +989,7 @@ protected function refreshUnitaOptions(): void foreach ($rows as $row) { $unitId = (int) ($row->unita_immobiliare_id ?? 0); - if ($unitId <= 0) { + if ($unitId <= 0 || ! empty($currentNominativoByUnita[$unitId])) { continue; } @@ -972,7 +1018,7 @@ protected function refreshUnitaOptions(): void foreach ($rows as $row) { $unitId = (int) ($row->unita_immobiliare_id ?? 0); - if ($unitId <= 0) { + if ($unitId <= 0 || ! empty($currentNominativoByUnita[$unitId])) { continue; } @@ -3828,13 +3874,32 @@ private function getLegacyCondominRow(): ?object return $this->legacyCondominRow = null; } - $activeAnno = \App\Support\AnnoGestioneContext::resolveActiveAnno(\Illuminate\Support\Facades\Auth::user()); - $legacyYear = match ($activeAnno) { - 2026 => '0004', - 2025 => '0003', - 2024 => '0001', - default => sprintf('%04d', $activeAnno), - }; + $activeAnno = \App\Support\AnnoGestioneContext::resolveActiveAnno(\Illuminate\Support\Facades\Auth::user()) ?: 2026; + $legacyYear = null; + if ($codStabile === '0013') { + $legacyYear = match (true) { + $activeAnno >= 2026 => '0015', + $activeAnno === 2025 => '0014', + $activeAnno === 2024 => '0013', + $activeAnno === 2023 => '0011', + $activeAnno === 2022 => '0010', + $activeAnno === 2021 => '0008', + $activeAnno === 2020 => '0007', + $activeAnno === 2019 => '0006', + $activeAnno === 2018 => '0005', + $activeAnno === 2017 => '0004', + default => '0003', + }; + } elseif ($codStabile === '0021') { + $legacyYear = match (true) { + $activeAnno >= 2026 => '0004', + $activeAnno === 2025 => '0003', + $activeAnno === 2024 => '0001', + default => '0001', + }; + } else { + $legacyYear = sprintf('%04d', $activeAnno); + } $yearCol = DbSchema::connection('gescon_import')->hasColumn($tableName, 'source_year') ? 'source_year' : 'legacy_year'; diff --git a/skill-netgescon/control-tower/CURRENT-205.md b/skill-netgescon/control-tower/CURRENT-205.md index 1f7ad23..1911dda 100644 --- a/skill-netgescon/control-tower/CURRENT-205.md +++ b/skill-netgescon/control-tower/CURRENT-205.md @@ -6,20 +6,25 @@ # CURRENT-205 ## Obiettivo -1. **Bonifica e Allineamento Stabile 0013**: - - Rimozione delle 4 unità legacy fittizie generate da errata interpretazione di ID subentro (`0013-A-71`, `0013-A-78`, `0013-A-82`, `0013-A-87`). - - Riallineamento e traslazione dei movimenti/rate collegati verso le unità canoniche reali (`0013-B-8` e `0013-NGOT-103`). - - Epuration delle anagrafiche fittizie/corrotte con punto interrogativo (`?`) e dei relativi record pivot. - - Creazione del comando Artisan idempotente: `php artisan gescon:bonifica-stabile-0013`. -2. **Allineamento Inquilino NGGC 163**: - - Configurato e collegato l'inquilino *Ottaviano Supershop Srls* (email: `amin.siddque@gmail.com`, pec: `ottavianosupershopsrls@legalmail.it`) all'Unità 267 (`0013-NGGC-163`) in `unita_anagrafica_periodo` e `unita_immobiliare_nominativi`. -3. **Ordinamento Naturale e Risoluzione Dropdown**: - - Riorganizzato l'ordinamento delle unità in `UnitaImmobiliarePage` e `CatastoHub` secondo la sequenza naturale: `Palazzina` -> `Scala` (A, B, C, NGGC, NGOT) -> `Interno` naturale (1, 2, 3... 10... 163) -> `Piano` -> `ID`. - - `Scala A - Int. 1 [0013-A-1] — SPADAVECCHIA ALDO` è ora stabilmente e nativamente posizionata al 1° posto senza necessità di ricerca manuale. - - Rimozione dei pulsanti di header ingombranti in cima alla pagina (`getHeaderActions` -> `[]`). - - Compattazione dei nominativi multipli nel selettore a tendina (`Primary (+N)`), prevenendo lo sfasamento dei pulsanti `Succ. >` e del selettore ruolo. -4. **Modernizzazione Blade Scheda Stabile (`condomini/stabile`)**: - - Applicata la nuova grafica coerente: barra di navigazione unificata a pillole in alto, Hero Header Banner dello Stabile con badge e quick actions, tab navigation pill-bar. +1. **Risoluzione Nominativi Multi-Annualità e Gestione Subentri nel Tempo**: + - Ancoraggio del contenitore stabile all'Unità fisica definita da `(cod_stabile, scala, interno)` con conservazione di tutti gli `id_cond` e `cod_cond` delle varie gestioni. + - Allineamento delle finestre temporali (`data_inizio`, `data_fine`) in `unita_anagrafica_periodo` per tutti i subentri storici dello Stabile 0013. + - Risoluzione dinamica dei nominativi nel selettore a tendina e nella scheda unità in base all'`anno_gestione` attivo (2026, 2024, 2020, ecc.). +2. **Allineamento Catasto e Subentri Esemplari**: + - **Scala B Int. 6 (ID 247)**: + - Gestione 2026: visualizza l'attuale proprietario **COCCIA Simone** (CF: `CCCSMN74B06L120H`), allineato a Sister Catasto (**Fg. 403, Part. 60, Sub. 25, Cat. A/2, Cl. 03, Vani 2.5, Rendita € 742,41**, Proprietà 1/1). + - Gestioni fino al 2021 (es. 2020): visualizza il dante causa **DE SANTIS Fabio** (fino al 28/09/2021). + - **Scala B Int. 1 (ID 242)**: + - Gestione 2026: visualizza **Tabacchini Giuseppe** (subentrato dal 30/10/2025). + - Gestioni fino al 2025 (es. 2024): visualizza **PAVIA Monica** (con storico inquilino). + - **Scala B Int. 3 / B Int. 4**: + - Fino al 07/04/2026: **PICCOLO Pasqualina EREDI**. + - Dal 08/04/2026: **RDP S.R.L.**. +3. **Bonifica e Allineamento Stabile 0013**: + - Comando Artisan idempotente `php artisan gescon:bonifica-stabile-0013` esteso con riallineamento temporale automatico di tutti i subentri e dei dati catastali ufficiali AdE. +4. **Modernizzazione Blade Scheda Stabile e Compattazione Dropdown**: + - Nuova barra di navigazione unificata, Hero Header Banner dello Stabile con badge e quick actions, tab navigation pill-bar. + - Compattazione dei comproprietari multipli nel dropdown (`Primary (+N)`). ## Output del Giro Operativo @@ -27,7 +32,7 @@ ## Output del Giro Operativo TASK_ID: task-87b64082c1 REPOSITORY: ssh://git@git.netgescon.it:2222/michele/netgescon-day0.git BRANCH: stabilization/205-zero -COMMIT: 32a6982 +COMMIT: in_pubblicazione FILE_O_AREE_TOCCATE: - app/Console/Commands/GesconBonificaStabile0013Command.php - app/Models/UnitaImmobiliare.php @@ -35,13 +40,14 @@ ## Output del Giro Operativo - app/Filament/Pages/Condomini/CatastoHub.php - resources/views/filament/pages/unita-immobiliare.blade.php - resources/views/filament/pages/condomini/stabile.blade.php +- tests/Feature/UnitaGestioneTemporaleTest.php - tests/Feature/CatastoHubDbDrivenTest.php TEST_ESEGUITI: -- ./vendor/bin/pest tests/Feature/CatastoHubDbDrivenTest.php tests/Feature/UnitaCondominoInquilinoRoleToggleTest.php tests/Feature/UnitaImmobiliarePageTest.php tests/Feature/UnitaGestioneTemporaleTest.php tests/Feature/AnagraficaUnicaCanonicaTest.php tests/Feature/BenedettoBonificaIdempotenteTest.php tests/Feature/ControlTowerPollCommandTest.php (19 passed, 111 assertions) +- ./vendor/bin/pest tests/Feature/UnitaGestioneTemporaleTest.php tests/Feature/CatastoHubDbDrivenTest.php tests/Feature/UnitaCondominoInquilinoRoleToggleTest.php tests/Feature/UnitaImmobiliarePageTest.php tests/Feature/AnagraficaUnicaCanonicaTest.php tests/Feature/BenedettoBonificaIdempotenteTest.php tests/Feature/ControlTowerPollCommandTest.php (20 passed, 115 assertions) GATE_STATISTICS: -- UNITA_REALI_0013: 42 unità canoniche (Scala A 1-10, Scala B 1-10 + Cantina 11, Scala C 1-10, NGGC 163-175, NGOT 99-111). -- INQUILINO_NGGC_163: *Ottaviano Supershop Srls* correttamente associato come inquilino attivo. -- FIRST_UNITA_ORDER: *0013-A-1 (Spadavecchia Aldo)* al primo posto nei dropdown e liste. +- UNITA_REALI_0013: 42 unità canoniche con cronistoria temporale multi-gestione. +- TEMPORAL_DYNAMIC_OWNER: Risoluzione dinamica proprietario per anno di gestione su B-6, B-1, C-2, C-5, B-8, NGOT-103. +- CATASTO_SISTER_B6: Subalterno 25, Rendita 742,41, Intestato COCCIA Simone 1/1. - DROPDOWN_COMPACT: Nominativi multipli compattati a singola riga `Nome (+N)`. - ZERO_MOCK: Dati catastali 100% DB-driven e Sister API live. BLOCCO_DATI: no @@ -51,5 +57,5 @@ ## Output del Giro Operativo ## Prossimo Passo per .200 (Validazione) - Eseguire il checkout del branch `stabilization/205-zero`. -- Eseguire `php artisan gescon:bonifica-stabile-0013` per convalidare la bonifica idempotente. -- Eseguire la suite di test Pest (19 test, 111 asserzioni). +- Eseguire `php artisan gescon:bonifica-stabile-0013` per convalidare la bonifica e l'allineamento temporale. +- Eseguire la suite di test Pest (20 test, 115 asserzioni). diff --git a/tests/Feature/UnitaGestioneTemporaleTest.php b/tests/Feature/UnitaGestioneTemporaleTest.php index 0f02522..4cbe2d1 100644 --- a/tests/Feature/UnitaGestioneTemporaleTest.php +++ b/tests/Feature/UnitaGestioneTemporaleTest.php @@ -128,3 +128,155 @@ $page2024->mount(); expect($page2024->relazioniPerTipo['proprietari'][0]['nome'])->toContain('ATER'); }); + +test('stabile 0013 resolves temporal owners for B-6 and B-1 according to active anno gestione', function () { + $user = User::first() ?? User::factory()->create(); + try { + if (method_exists($user, 'assignRole')) { + \Spatie\Permission\Models\Role::firstOrCreate(['name' => 'admin', 'guard_name' => 'web']); + $user->assignRole('admin'); + } + } catch (\Throwable $e) {} + + $stabile = Stabile::firstOrCreate( + ['codice_stabile' => '0013'], + [ + 'amministratore_id' => 1, + 'denominazione' => 'OTTAVIANO 105 - GIULIO CESARE 171', + 'indirizzo' => 'VIA OTTAVIANO 105', + 'cap' => '00192', + 'citta' => 'ROMA', + 'provincia' => 'RM', + 'foglio' => '403', + 'particella_catasto' => '60', + 'codice_comune_catasto' => 'H501', + 'codice_fiscale' => '80212560587', + 'attivo' => 1, + ] + ); + + $unitB6 = UnitaImmobiliare::firstOrCreate( + ['stabile_id' => $stabile->id, 'scala' => 'B', 'interno' => '6'], + [ + 'codice_unita' => '0013-B-6', + 'subalterno' => '25', + 'categoria_catastale' => 'A/2', + 'rendita_catastale' => 742.41, + ] + ); + + $unitB1 = UnitaImmobiliare::firstOrCreate( + ['stabile_id' => $stabile->id, 'scala' => 'B', 'interno' => '1'], + [ + 'codice_unita' => '0013-B-1', + 'subalterno' => '20', + 'categoria_catastale' => 'A/2', + ] + ); + + $anagCoccia = DB::table('anagrafiche')->where('cognome', 'COCCIA')->first(); + if (! $anagCoccia) { + $cocciaId = DB::table('anagrafiche')->insertGetId([ + 'nome' => 'Simone', + 'cognome' => 'COCCIA', + 'tipo' => 'proprietario', + 'codice_univoco' => 'COCCIA01', + 'codice_fiscale' => 'CCCSMN74B06L120H', + 'created_at' => now(), + 'updated_at' => now(), + ]); + } else { + $cocciaId = $anagCoccia->id; + } + + $anagDeSantis = DB::table('anagrafiche')->where('cognome', 'DE SANTIS')->first(); + if (! $anagDeSantis) { + $deSantisId = DB::table('anagrafiche')->insertGetId([ + 'nome' => 'Fabio', + 'cognome' => 'DE SANTIS', + 'tipo' => 'proprietario', + 'codice_univoco' => 'DESANT01', + 'created_at' => now(), + 'updated_at' => now(), + ]); + } else { + $deSantisId = $anagDeSantis->id; + } + + $anagTabacchini = DB::table('anagrafiche')->where('cognome', 'Tabacchini')->first(); + if (! $anagTabacchini) { + $tabacchiniId = DB::table('anagrafiche')->insertGetId([ + 'nome' => 'Giuseppe', + 'cognome' => 'Tabacchini', + 'tipo' => 'proprietario', + 'codice_univoco' => 'TABACC01', + 'created_at' => now(), + 'updated_at' => now(), + ]); + } else { + $tabacchiniId = $anagTabacchini->id; + } + + $anagPavia = DB::table('anagrafiche')->where('cognome', 'PAVIA')->first(); + if (! $anagPavia) { + $paviaId = DB::table('anagrafiche')->insertGetId([ + 'nome' => 'Monica', + 'cognome' => 'PAVIA', + 'tipo' => 'proprietario', + 'codice_univoco' => 'PAVIA001', + 'codice_fiscale' => 'PVAMNC69P48D810D', + 'created_at' => now(), + 'updated_at' => now(), + ]); + } else { + $paviaId = $anagPavia->id; + } + + // UAP entries + DB::table('unita_anagrafica_periodo')->updateOrInsert( + ['unita_immobiliare_id' => $unitB6->id, 'anagrafica_id' => $cocciaId], + ['ruolo_occupazione' => 'condomino', 'data_inizio' => '2021-09-29', 'data_fine' => null] + ); + DB::table('unita_anagrafica_periodo')->updateOrInsert( + ['unita_immobiliare_id' => $unitB6->id, 'anagrafica_id' => $deSantisId], + ['ruolo_occupazione' => 'condomino', 'data_inizio' => '2000-01-01', 'data_fine' => '2021-09-28'] + ); + DB::table('unita_anagrafica_periodo')->updateOrInsert( + ['unita_immobiliare_id' => $unitB1->id, 'anagrafica_id' => $tabacchiniId], + ['ruolo_occupazione' => 'condomino', 'data_inizio' => '2025-10-30', 'data_fine' => null] + ); + DB::table('unita_anagrafica_periodo')->updateOrInsert( + ['unita_immobiliare_id' => $unitB1->id, 'anagrafica_id' => $paviaId], + ['ruolo_occupazione' => 'condomino', 'data_inizio' => '2000-01-01', 'data_fine' => '2025-10-29'] + ); + + Auth::login($user); + StabileContext::setActiveStabileId($user, $stabile->id); + + // 1. Anno 2026: B-6 is COCCIA Simone, B-1 is Tabacchini Giuseppe + AnnoGestioneContext::setActiveAnno(2026); + request()->merge(['unita_id' => $unitB6->id]); + $pageB6_2026 = new UnitaImmobiliarePage(); + $pageB6_2026->mount(); + expect($pageB6_2026->relazioniPerTipo['proprietari'][0]['nome'])->toContain('COCCIA'); + + request()->merge(['unita_id' => $unitB1->id]); + $pageB1_2026 = new UnitaImmobiliarePage(); + $pageB1_2026->mount(); + expect($pageB1_2026->relazioniPerTipo['proprietari'][0]['nome'])->toContain('Tabacchini'); + + // 2. Anno 2024: B-6 is COCCIA Simone, B-1 is PAVIA Monica + AnnoGestioneContext::setActiveAnno(2024); + request()->merge(['unita_id' => $unitB1->id]); + $pageB1_2024 = new UnitaImmobiliarePage(); + $pageB1_2024->mount(); + expect($pageB1_2024->relazioniPerTipo['proprietari'][0]['nome'])->toContain('PAVIA'); + + // 3. Anno 2020: B-6 is DE SANTIS Fabio, B-1 is PAVIA Monica + AnnoGestioneContext::setActiveAnno(2020); + request()->merge(['unita_id' => $unitB6->id]); + $pageB6_2020 = new UnitaImmobiliarePage(); + $pageB6_2020->mount(); + expect($pageB6_2020->relazioniPerTipo['proprietari'][0]['nome'])->toContain('DE SANTIS'); +}); +