168 lines
12 KiB
Markdown
168 lines
12 KiB
Markdown
# 🧭 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.
|