netgescon-day0/docs/07-IMPORT-UNITA-IMMOBILIARI.md

168 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 🧭 Piano Operativo Import Unità Immobiliari (Gescon → NetGescon)
**Versione**: 0.1 03 Agosto 2025
**Ambito**: Modulo `Admin → Gescon Import → Tab Unità` (Laravel)
---
## 🎯 Obiettivi
1. **Acquisire le unità da `singolo_anno.mdb` (tabella `condomin`)** preservando i riferimenti \(SCALA/INTERNO/SUB\) e le informazioni d'uso.
2. **Popolare almeno tre archivi NetGescon** con dati coerenti e deduplicati:
- `unita_immobiliari`
- `soggetti` / `rubrica_universale`
- `proprieta` + `rubrica_ruoli`
3. **Classificare pertinenze e locali tecnici** per gestire cumuli, manutentori e futuri contratti/chiavi.
4. **Preparare l'aggancio a rate/pagamenti** garantendo codici stabili, millesimi e diritti aggiornati.
---
## 🗂️ Fonti Legacy & Metadati
| Fonte | Percorso | Note operative |
| --- | --- | --- |
| `singolo_anno.mdb``condomin` | `/mnt/gescon-archives/gescon/<codice>/singolo_anno.mdb` | Accesso via `mdb-tables`/`mdb-export`. Il servizio `LegacyArchiveService::unita()` estrae headers dinamici, preview righe e summary scale/occupanti. |
| Staging SQL (`gescon_import.condomin`) | Connessione configurabile (`gescon_import`, fallback `gescon_import_<anno>`) | Replica della tabella per lavorare senza MDB. Le colonne vengono lette tramite `Schema::connection(...)->getColumnListing`. |
| Dataset JSON (`migration_datasets` / `migration_records`) | chiave `unita` | Utilizzato come fallback per test oppure quando MDB/staging non è disponibile. |
| Summary calcolati | `LegacyArchiveService``summary.scale`, `summary.people` | Liste di scale, interni presenti, proprietari e inquilini dedotti dalle colonne nominative. Utili per UI mapping e per generare ruoli. |
**Headers principali di `condomin` da considerare** (case insensitive):
`cod_stabile`, `cod_cond`, `scala`, `piano`, `interno`, `sub`, `cognome`, `nome`, `codice_fiscale`, `telefono`, `email`, `indirizzo_corrispondenza`, `millesimi_*`, `inquilino`, `proprietario`, `note`, `cognome_inquilino`, `nome_inquilino`, `cf_inquilino`.
---
## 🧱 Tabelle Target & Responsabilità
| Tabella | Scopo | Campi chiave | Dipendenze |
| --- | --- | --- | --- |
| `unita_immobiliari` | Master unità (abitazioni, pertinenze, locali tecnici) | `stabile_id`, `codice_unita`, `scala`, `interno`, `piano`, `tipo_unita`, `millesimi_*`, `stato_occupazione`, `meta` | richiede `stabili.id` |
| `soggetti` | Albero proprietari/occupanti “legacy-friendly” usato da contabilità | `codice_fiscale`, `email`, `codice_univoco`, `tipo` | Deducibile direttamente da `condomin` |
| `rubrica_universale` | Anagrafica unica NetGescon (contatti, manutentori, banche) | `codice_univoco`, `categoria`, `tipo_contatto`, `pec`, `telefono` | Sincronizzata con `soggetti` (1:1 logico) |
| `proprieta` | Relazione giuridica unità ↔ soggetto | `unita_immobiliare_id`, `soggetto_id`, `tipo_diritto`, `percentuale_possesso`, `data_inizio/fine` | richiede unità + soggetti |
| `rubrica_ruoli` | Ruoli dinamici (proprietario, inquilino, manutentore, tecnico locale) con periodo e preferenze | `rubrica_id`, `ruolo_standard`, `unita_immobiliare_id`, `stabile_id`, `data_inizio/fine`, `meta` | richiede rubrica |
| `unita_pertinenze` *(opzionale ma supportato)* | legame unità principale ↔ pertinenza (cantina, box, locale tecnico) | `unita_principale_id`, `unita_accessoria_id`, `tipo`, `cumulo` | richiede unità distinte |
---
## 🔁 Matrici di Mapping
### 1. Identità & Posizionamento
| Target (`unita_immobiliari`) | Source `condomin` | Regole/Note |
| --- | --- | --- |
| `stabile_id` | input utente / lookup `stabili` (`codice_stabile`, `denominazione`) | obbligatorio dal tab principale; fallback `mapping.stabile_id`. |
| `codice_unita` | `cod_stabile`, `scala`, `interno` | formato `STAB-SCALA-INT`. Zero padding opzionale. Per pertinenze usa il codice normalizzato (es. `LT03`). |
| `palazzina`, `scala` | `scala` | normalizzare: uppercase, fallback `A`. UI deve mostrare lista scale da `summary.scale`. |
| `piano` | `piano` | convertire `T/PT/R`→0, `S/PS/-1`→-1, numeri interi altrove. |
| `interno` | `interno` | trim, uppercase, gestire multi valori (es. `1/A`). |
| `subalterno` | `sub` oppure `interno` | se vuoto, mantenere `interno`. |
| `denominazione` | `cognome + nome` | fallback `"Scala {scala} Interno {interno}"`. |
| `posizione_dettagliata` | composizione `palazzina / scala / piano / interno` | utile per UI senza query aggiuntive. |
### 2. Dati catastali & superfici
| Target | Source | Regole |
| --- | --- | --- |
| `foglio`, `particella`, `subalterno` | `foglio`, `particella`, `sub` | normalizzare numeri, rimuovere leading zeros superflui ma conservarli in `meta_legacy`. |
| `categoria_catastale`, `classe`, `consistenza`, `rendita_catastale` | `categoria`, `classe`, `cons`, `rendita` (se presenti) | tipicamente presenti nei dataset `condomin`. |
| `superficie_commerciale`, `superficie_calpestabile` | `sup_com`, `sup_calp` | unità m². Validare range 0-10.000. |
| `millesimi_generali`, `millesimi_riscaldamento`, `millesimi_acqua`, `millesimi_ascensore`, `millesimi_scale` | `millesimi_generali`, `mill_risc`, `mill_acqua`, `mill_asc`, `mill_scale` | usare `decimal(8,3)`; se >1000 loggare warning. |
### 3. Caratteristiche, impianti, autorizzazioni
| Target | Legacy | Note |
| --- | --- | --- |
| `tipo_unita` | derived | `abitazione` default. Pattern `CAN`, `BOX/GAR`, `PA`, `SOF`, `LT``cantina`, `box`, `posto_auto`, `soffitta`, `locale_tecnico`. |
| `utilizzo_attuale` | `uso`, `destinazione` | mapping statico (es. `AB`→`residenziale`, `U`→`ufficio`). |
| `stato_conservazione` | `stato`, `cons`, flag qualitativo | mappare `O/B/D/C``ottimo/buono/discreto/scarso`. |
| `stato_occupazione` | flag `proprietario`, `inquilino`, `libero` | `proprietario=1``occupata_proprietario`; `inquilino=1``occupata_inquilino`; altrimenti `libera`. |
| `riscaldamento`, `ha_climatizzazione`, `ha_impianto_gas` | `tipo_risc`, `clima`, `gas` | booleane/in enum. |
| `ha_cambio_destinazione_uso`, `data_scadenza_autorizzazioni`, `note_autorizzazioni` | `cambio_uso`, `scad_aut`, `note` | Fieldset per future audit. |
| `valore_commerciale_stimato`, `canone_locazione_mensile` | `valore`, `canone` | Numeric, usati per analisi rate. |
### 4. Metadati & Audit
- `meta_legacy` (JSON) con: `cod_cond`, `id_record`, `path_archivio`, `raw_columns` per tracciabilità.
- `created_by` / `updated_by`: impostare all'utente che effettua il mapping/import.
- `attiva`, `unita_demo`: flag gestiti dall'import (+ eventuale override UI).
---
## 👥 Anagrafica Unica & Ruoli Occupanti
### Soggetti (`soggetti`)
| Target campo | Source | Regole |
| --- | --- | --- |
| `nome`, `cognome`, `codice_fiscale`, `email`, `telefono`, `indirizzo` | `cognome`, `nome`, `codice_fiscale`, `email`, `telefono`, `indirizzo_corrispondenza` | Normalizzare CF (uppercase, 16 char). Vuoti ⇒ `null`. |
| `tipo` | flag `proprietario` / `inquilino` | `proprietario=1``proprietario`, `inquilino=1``inquilino`, fallback `proprietario`. |
| `codice_univoco` | generato | `generateStableCondKey('S', cod_stabile, nome_norm)` con retry. |
### Rubrica Universale (`rubrica_universale`)
- Sincronizzare 1:1 con `soggetti` usando `codice_univoco` come ponte.
- `categoria`: `condomino` per proprietari, `occupante` per inquilini, `locale_tecnico` per manutentori (vedi sezione dedicata).
- `tipo_contatto`: `persona_fisica` se valorizzati `nome`/`cognome`, altrimenti `persona_giuridica`.
- Dati aggiuntivi: `pec`, `cellulare`, `note` (da `note` o `note_inquilino`).
### Ruoli (`rubrica_ruoli`)
| Campo | Valore | Fonte |
| --- | --- | --- |
| `ruolo_standard` | `proprietario`, `occupante`, `referente_locale_tecnico`, `manutentore_locale_tecnico` | Dalla casistica: proprietario/inquilino, più voci speciali per locali tecnici. |
| `unita_immobiliare_id` | lookup da `codice_unita` | Necessario per ruoli legati alla singola unità. |
| `stabile_id` | `stabile.id` usato nel mapping | Permette vista aggregata condominio. |
| `data_inizio` / `data_fine` | se disponibili in `condomin` (`data_inizio_locazione`, `data_fine_locazione`) | Altrimenti `null` e gestito successivamente. |
| `meta` | JSON con `legacy_cod_cond`, `scala`, `interno`, `fonte` | per audit e dedup futuro. |
---
## 🗝️ Pertinenze & Locali Tecnici
1. **Classificazione automatica** sul campo `interno` (case insensitive, spazi normalizzati):
- `CAN\d+``cantina`
- `BOX`, `GAR`, `GARAGE``box`
- `PA`, `POSTO AUTO``posto_auto`
- `SOF`, `SOFFITTA`, `SOLAIO``soffitta`
- `LT`, `LOCALE TECNICO``locale_tecnico`
2. **Codice unità** mantiene il prefisso (`BOX01`, `LT03`) per distinguere dai civici.
3. **`unita_pertinenze`**: dopo l'inserimento, collegare la prima unità principale della stessa scala come `unita_principale_id`, marcando `cumulo=true`. In futuro l'UI dovrà consentire la scelta manuale.
4. **Manutentori**: per `locale_tecnico` valorizzare anche `rubrica_ruoli` con `ruolo_standard = manutentore_locale_tecnico` quando nel dataset sono presenti riferimenti (es. colonne `tecnico`, `manutentore`). Nell'immediato, salvare il nominativo raw in `meta_legacy` per completamenti successivi.
---
## ✅ Validazioni & Normalizzazioni
1. **SCALA / INTERNO obbligatori**: se mancanti, bloccare salvataggio UI e richiedere input manuale.
2. **Codici fiscali**: validare lunghezza (16/11/partita IVA). Se non validi, flaggare in `meta.warnings`.
3. **Millesimi**: totale per scala deve avvicinarsi a 1000 (±5). In caso contrario, riportare nel riepilogo import.
4. **Duplicati unità**: `codice_unita` deve essere unico; UI deve suggerire un merge se già presente.
5. **Dedup soggetti**: ordine preferenza `codice_fiscale``email``nome+cognome`. Le funzioni `findExistingSoggetto` e `dedupSoggettiBy` già disponibili vanno riutilizzate nel controller.
6. **Ruoli sovrapposti**: prima di inserire in `rubrica_ruoli` controllare se esiste un record attivo con stesso `rubrica_id` + `unita_immobiliare_id` + `ruolo_standard`. Aggiornare date invece di duplicare.
7. **Locali tecnici senza manutentore**: marcare `stato_occupazione = 'locale_tecnico'` e impostare `note` "Manutentore da assegnare" per facilitarne l'individuazione post-import.
---
## 🚀 Prossimi Passi Implementativi
1. **UI Mapping**:
- Riutilizzare il pattern "schede stabili" per mostrare preview condomin con badge Scala/Interno, includendo summary persone.
- Esporre selettori per ognuna delle categorie sopra (identità, catastale, superfici, ruoli) con default suggeriti.
2. **Controller/Service**:
- Estendere `GesconImportController@mappingSave` con sezione `unità`, salvando in `gescon_import_mappings.meta['unita']` il pairing `target_field``legacy_key`.
- Aggiungere action `executeUnitImport()` che orchestri `LegacyArchiveService`, `ImportGesconFullPipeline::stepUnita/stepSoggetti/stepDiritti` filtrati per stabile/scala.
3. **Test & Verifica**:
- Dataset di prova: `condomin` per `cod_stabile = 000123`. Verificare totale righe importate = righe legate allo stabile.
- Validare che ogni proprietario compaia in `rubrica_ruoli` con `ruolo_standard = proprietario` e che eventuali `inquilini` aggiungano ruoli e diritti di tipo `locazione`.
4. **Estensioni future**:
- Collegare `locale_tecnico` a `chiavi_stabili` (tipologia `locali_tecnici`).
- Integrare `dett_tab` per popolare `dettaglio_millesimi` con scala-specific translations.
- Pre-calcolare `responsabile_pagamenti` per pipeline rate/bollette.
---
Con questo blueprint il team può implementare la nuova esperienza di mapping/import delle unità immobiliari mantenendo coerenza con l'anagrafica unica e preparando i dati per occupanti, locali tecnici e rate/pagamenti.