feat(temporal-ownership): gestione cronistoria temporale subentri stabile 0013 e allineamento catasto B-6 B-1

This commit is contained in:
michele 2026-09-02 11:36:07 +02:00
parent e465a2271c
commit cb6249b216
4 changed files with 336 additions and 30 deletions

View File

@ -160,6 +160,89 @@ public function handle(): int
$this->info('Unita 233 (Scala A Int. 1) allineata con dati Sister Catasto.'); $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!'); $this->info('Bonifica Stabile 0013 completata con successo!');
return 0; return 0;
} }

View File

@ -928,8 +928,54 @@ protected function refreshUnitaOptions(): void
} }
} }
$activeAnno = \App\Support\AnnoGestioneContext::resolveActiveAnno(\Illuminate\Support\Facades\Auth::user()) ?: 2026;
$currentNominativoByUnita = []; $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')) { if (DbSchema::hasTable('rubrica_ruoli') && DbSchema::hasTable('rubrica_universale')) {
try { try {
$rows = DB::table('rubrica_ruoli as rr') $rows = DB::table('rubrica_ruoli as rr')
@ -943,7 +989,7 @@ protected function refreshUnitaOptions(): void
foreach ($rows as $row) { foreach ($rows as $row) {
$unitId = (int) ($row->unita_immobiliare_id ?? 0); $unitId = (int) ($row->unita_immobiliare_id ?? 0);
if ($unitId <= 0) { if ($unitId <= 0 || ! empty($currentNominativoByUnita[$unitId])) {
continue; continue;
} }
@ -972,7 +1018,7 @@ protected function refreshUnitaOptions(): void
foreach ($rows as $row) { foreach ($rows as $row) {
$unitId = (int) ($row->unita_immobiliare_id ?? 0); $unitId = (int) ($row->unita_immobiliare_id ?? 0);
if ($unitId <= 0) { if ($unitId <= 0 || ! empty($currentNominativoByUnita[$unitId])) {
continue; continue;
} }
@ -3828,13 +3874,32 @@ private function getLegacyCondominRow(): ?object
return $this->legacyCondominRow = null; return $this->legacyCondominRow = null;
} }
$activeAnno = \App\Support\AnnoGestioneContext::resolveActiveAnno(\Illuminate\Support\Facades\Auth::user()); $activeAnno = \App\Support\AnnoGestioneContext::resolveActiveAnno(\Illuminate\Support\Facades\Auth::user()) ?: 2026;
$legacyYear = match ($activeAnno) { $legacyYear = null;
2026 => '0004', if ($codStabile === '0013') {
2025 => '0003', $legacyYear = match (true) {
2024 => '0001', $activeAnno >= 2026 => '0015',
default => sprintf('%04d', $activeAnno), $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'; $yearCol = DbSchema::connection('gescon_import')->hasColumn($tableName, 'source_year') ? 'source_year' : 'legacy_year';

View File

@ -6,20 +6,25 @@ # CURRENT-205
## Obiettivo ## Obiettivo
1. **Bonifica e Allineamento Stabile 0013**: 1. **Risoluzione Nominativi Multi-Annualità e Gestione Subentri nel Tempo**:
- 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`). - 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.
- Riallineamento e traslazione dei movimenti/rate collegati verso le unità canoniche reali (`0013-B-8` e `0013-NGOT-103`). - Allineamento delle finestre temporali (`data_inizio`, `data_fine`) in `unita_anagrafica_periodo` per tutti i subentri storici dello Stabile 0013.
- Epuration delle anagrafiche fittizie/corrotte con punto interrogativo (`?`) e dei relativi record pivot. - Risoluzione dinamica dei nominativi nel selettore a tendina e nella scheda unità in base all'`anno_gestione` attivo (2026, 2024, 2020, ecc.).
- Creazione del comando Artisan idempotente: `php artisan gescon:bonifica-stabile-0013`. 2. **Allineamento Catasto e Subentri Esemplari**:
2. **Allineamento Inquilino NGGC 163**: - **Scala B Int. 6 (ID 247)**:
- 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`. - 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).
3. **Ordinamento Naturale e Risoluzione Dropdown**: - Gestioni fino al 2021 (es. 2020): visualizza il dante causa **DE SANTIS Fabio** (fino al 28/09/2021).
- 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 B Int. 1 (ID 242)**:
- `Scala A - Int. 1 [0013-A-1] — SPADAVECCHIA ALDO` è ora stabilmente e nativamente posizionata al 1° posto senza necessità di ricerca manuale. - Gestione 2026: visualizza **Tabacchini Giuseppe** (subentrato dal 30/10/2025).
- Rimozione dei pulsanti di header ingombranti in cima alla pagina (`getHeaderActions` -> `[]`). - Gestioni fino al 2025 (es. 2024): visualizza **PAVIA Monica** (con storico inquilino).
- Compattazione dei nominativi multipli nel selettore a tendina (`Primary (+N)`), prevenendo lo sfasamento dei pulsanti `Succ. >` e del selettore ruolo. - **Scala B Int. 3 / B Int. 4**:
4. **Modernizzazione Blade Scheda Stabile (`condomini/stabile`)**: - Fino al 07/04/2026: **PICCOLO Pasqualina EREDI**.
- 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. - 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 ## Output del Giro Operativo
@ -27,7 +32,7 @@ ## Output del Giro Operativo
TASK_ID: task-87b64082c1 TASK_ID: task-87b64082c1
REPOSITORY: ssh://git@git.netgescon.it:2222/michele/netgescon-day0.git REPOSITORY: ssh://git@git.netgescon.it:2222/michele/netgescon-day0.git
BRANCH: stabilization/205-zero BRANCH: stabilization/205-zero
COMMIT: 32a6982 COMMIT: in_pubblicazione
FILE_O_AREE_TOCCATE: FILE_O_AREE_TOCCATE:
- app/Console/Commands/GesconBonificaStabile0013Command.php - app/Console/Commands/GesconBonificaStabile0013Command.php
- app/Models/UnitaImmobiliare.php - app/Models/UnitaImmobiliare.php
@ -35,13 +40,14 @@ ## Output del Giro Operativo
- app/Filament/Pages/Condomini/CatastoHub.php - app/Filament/Pages/Condomini/CatastoHub.php
- resources/views/filament/pages/unita-immobiliare.blade.php - resources/views/filament/pages/unita-immobiliare.blade.php
- resources/views/filament/pages/condomini/stabile.blade.php - resources/views/filament/pages/condomini/stabile.blade.php
- tests/Feature/UnitaGestioneTemporaleTest.php
- tests/Feature/CatastoHubDbDrivenTest.php - tests/Feature/CatastoHubDbDrivenTest.php
TEST_ESEGUITI: 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: 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). - UNITA_REALI_0013: 42 unità canoniche con cronistoria temporale multi-gestione.
- INQUILINO_NGGC_163: *Ottaviano Supershop Srls* correttamente associato come inquilino attivo. - TEMPORAL_DYNAMIC_OWNER: Risoluzione dinamica proprietario per anno di gestione su B-6, B-1, C-2, C-5, B-8, NGOT-103.
- FIRST_UNITA_ORDER: *0013-A-1 (Spadavecchia Aldo)* al primo posto nei dropdown e liste. - CATASTO_SISTER_B6: Subalterno 25, Rendita 742,41, Intestato COCCIA Simone 1/1.
- DROPDOWN_COMPACT: Nominativi multipli compattati a singola riga `Nome (+N)`. - DROPDOWN_COMPACT: Nominativi multipli compattati a singola riga `Nome (+N)`.
- ZERO_MOCK: Dati catastali 100% DB-driven e Sister API live. - ZERO_MOCK: Dati catastali 100% DB-driven e Sister API live.
BLOCCO_DATI: no BLOCCO_DATI: no
@ -51,5 +57,5 @@ ## Output del Giro Operativo
## Prossimo Passo per .200 (Validazione) ## Prossimo Passo per .200 (Validazione)
- Eseguire il checkout del branch `stabilization/205-zero`. - Eseguire il checkout del branch `stabilization/205-zero`.
- Eseguire `php artisan gescon:bonifica-stabile-0013` per convalidare la bonifica idempotente. - Eseguire `php artisan gescon:bonifica-stabile-0013` per convalidare la bonifica e l'allineamento temporale.
- Eseguire la suite di test Pest (19 test, 111 asserzioni). - Eseguire la suite di test Pest (20 test, 115 asserzioni).

View File

@ -128,3 +128,155 @@
$page2024->mount(); $page2024->mount();
expect($page2024->relazioniPerTipo['proprietari'][0]['nome'])->toContain('ATER'); 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');
});