info('Avvio bonifica e allineamento Stabile 0013...'); $stabile = Stabile::where('codice_stabile', '0013')->first(); if (!$stabile) { $this->error('Stabile 0013 non trovato!'); return 1; } // 1. Riallineamento rate e movimenti dalle unita fantasma (338, 339, 340, 341) alle unita canoniche // 339 (0013-A-82) -> 249 (0013-B-8, Scala B Int. 8) $unit249 = UnitaImmobiliare::where('stabile_id', $stabile->id)->where('scala', 'B')->where('interno', '8')->first(); if ($unit249) { if (Schema::hasTable('rate_emesse') && Schema::hasColumn('rate_emesse', 'unita_immobiliare_id')) { DB::table('rate_emesse')->where('unita_immobiliare_id', 339)->update(['unita_immobiliare_id' => $unit249->id]); } if (Schema::hasTable('dettagli_ripartizione_spese') && Schema::hasColumn('dettagli_ripartizione_spese', 'unita_immobiliare_id')) { DB::table('dettagli_ripartizione_spese')->where('unita_immobiliare_id', 339)->update(['unita_immobiliare_id' => $unit249->id]); } } // 340 (0013-A-87) -> 264 (0013-NGOT-103, Scala NGOT Int. 103) $unit264 = UnitaImmobiliare::where('stabile_id', $stabile->id)->where('scala', 'NGOT')->where('interno', '103')->first(); if ($unit264) { if (Schema::hasTable('rate_emesse') && Schema::hasColumn('rate_emesse', 'unita_immobiliare_id')) { DB::table('rate_emesse')->where('unita_immobiliare_id', 340)->update(['unita_immobiliare_id' => $unit264->id]); } if (Schema::hasTable('dettagli_ripartizione_spese') && Schema::hasColumn('dettagli_ripartizione_spese', 'unita_immobiliare_id')) { DB::table('dettagli_ripartizione_spese')->where('unita_immobiliare_id', 340)->update(['unita_immobiliare_id' => $unit264->id]); } } // 2. Eliminazione unita fantasma 338, 339, 340, 341 if (Schema::hasTable('unita_anagrafica_periodo')) { DB::table('unita_anagrafica_periodo')->whereIn('unita_immobiliare_id', [338, 339, 340, 341])->delete(); } if (Schema::hasTable('proprieta')) { DB::table('proprieta')->whereIn('unita_immobiliare_id', [338, 339, 340, 341])->delete(); } if (Schema::hasTable('unita_immobiliare_nominativi')) { DB::table('unita_immobiliare_nominativi')->whereIn('unita_immobiliare_id', [338, 339, 340, 341])->delete(); } if (Schema::hasTable('persone_unita_relazioni')) { DB::table('persone_unita_relazioni')->whereIn('unita_id', [338, 339, 340, 341])->delete(); } if (Schema::hasTable('rubrica_ruoli')) { DB::table('rubrica_ruoli')->whereIn('unita_immobiliare_id', [338, 339, 340, 341])->delete(); } DB::table('unita_immobiliari')->whereIn('id', [338, 339, 340, 341])->delete(); $this->info('Unita fantasma (71, 78, 82, 87) rimosse con successo.'); // 3. Eliminazione anagrafiche corrotte con '?' $badAnagIds = DB::table('anagrafiche') ->where('cognome', 'like', '%?%') ->orWhere('nome', 'like', '%?%') ->orWhere('ragione_sociale', 'like', '%?%') ->pluck('id') ->all(); if (!empty($badAnagIds)) { if (Schema::hasTable('unita_anagrafica_periodo')) { DB::table('unita_anagrafica_periodo')->whereIn('anagrafica_id', $badAnagIds)->delete(); } if (Schema::hasTable('proprieta')) { DB::table('proprieta')->whereIn('anagrafica_id', $badAnagIds)->delete(); } DB::table('anagrafiche')->whereIn('id', $badAnagIds)->delete(); $this->info('Anagrafiche corrotte rimaste bonificate.'); } // 3b. Pulizia comproprietari incrociati orfani su Unità 233 (0013-A-1) $unit233 = UnitaImmobiliare::where('stabile_id', $stabile->id)->where('scala', 'A')->where('interno', '1')->first(); if ($unit233) { DB::table('unita_anagrafica_periodo') ->where('unita_immobiliare_id', $unit233->id) ->where('ruolo_occupazione', 'comproprietario') ->delete(); } // 3c. Pulizia assegnazioni errate RDP S.R.L. (consentita solo su B-3 e B-4) if (Schema::hasTable('unita_immobiliare_nominativi')) { $unitB3B4Ids = UnitaImmobiliare::where('stabile_id', $stabile->id) ->where('scala', 'B') ->whereIn('interno', ['3', '4']) ->pluck('id') ->all(); DB::table('unita_immobiliare_nominativi') ->where('stabile_id', $stabile->id) ->where('nominativo', 'like', '%RDP%') ->whereNotIn('unita_immobiliare_id', $unitB3B4Ids) ->delete(); } // 4. Bonifica e allineamento Unità NGGC 163 (ID 267) $unit163 = UnitaImmobiliare::where('stabile_id', $stabile->id)->where('scala', 'NGGC')->where('interno', '163')->first(); if ($unit163) { // Anagrafica Inquilino: Ottaviano Supershop Srls $inqAnag = DB::table('anagrafiche')->where('ragione_sociale', 'like', '%Ottaviano Supershop%')->first() ?? DB::table('anagrafiche')->where('nome', 'like', '%Ottaviano Supershop%')->first(); if (!$inqAnag) { $inqId = DB::table('anagrafiche')->insertGetId([ 'ragione_sociale' => 'Ottaviano Supershop Srls', 'email' => 'amin.siddque@gmail.com', 'tipo' => 'inquilino', 'created_at' => now(), 'updated_at' => now(), ]); } else { $inqId = $inqAnag->id; DB::table('anagrafiche')->where('id', $inqId)->update([ 'ragione_sociale' => 'Ottaviano Supershop Srls', 'email' => 'amin.siddque@gmail.com', 'tipo' => 'inquilino', 'updated_at' => now(), ]); } // Assicura relazione inquilino attiva in UAP $existsInqUap = DB::table('unita_anagrafica_periodo') ->where('unita_immobiliare_id', $unit163->id) ->where('anagrafica_id', $inqId) ->where('ruolo_occupazione', 'inquilino') ->first(); if (!$existsInqUap) { DB::table('unita_anagrafica_periodo')->insert([ 'unita_immobiliare_id' => $unit163->id, 'anagrafica_id' => $inqId, 'ruolo_occupazione' => 'inquilino', 'data_inizio' => '2026-01-01', 'percentuale_spesa' => 100.000, 'sussidiata_da_proprietario' => 0, 'created_at' => now(), 'updated_at' => now(), ]); } // Assicura nominativo inquilino in unita_immobiliare_nominativi if (Schema::hasTable('unita_immobiliare_nominativi')) { DB::table('unita_immobiliare_nominativi')->updateOrInsert( ['unita_immobiliare_id' => $unit163->id, 'ruolo' => 'I'], [ 'stabile_id' => $stabile->id, 'nominativo' => 'Ottaviano Supershop Srls', 'data_inizio' => '2026-01-01', 'percentuale' => 100.00, 'fonte' => 'gescon_bonifica', 'updated_at' => now(), ] ); } $this->info('Unita NGGC 163 allineata con Inquilino Ottaviano Supershop Srls.'); } // 5. Riallineamento Unita 233 (Scala A Int. 1) con dati ufficiali Catasto $unit233 = UnitaImmobiliare::where('stabile_id', $stabile->id)->where('scala', 'A')->where('interno', '1')->first(); if ($unit233) { $unit233->subalterno = '509'; $unit233->categoria_catastale = 'A/2'; $unit233->rendita_catastale = 2524.18; $unit233->piano = '3'; $unit233->numero_vani = 9; $unit233->sezione_urbana = null; $unit233->save(); $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, ]); } } // 9. Sincronizzazione tabelle Protocollo Comunicazioni ed Estratti Conto da generale_stabile.mdb $mdbPath = '/mnt/gescon-archives/gescon/0013/generale_stabile.mdb'; if (file_exists($mdbPath)) { if (! Schema::connection('gescon_import')->hasTable('protoc_ec')) { Schema::connection('gescon_import')->create('protoc_ec', function ($table) { $table->increments('id'); $table->string('cod_stabile')->index(); $table->integer('id_corrisp')->nullable(); $table->string('protocollo')->nullable()->index(); $table->string('tipo_documento')->nullable(); $table->string('data_invio')->nullable(); $table->string('forn_cond_altro')->nullable(); $table->string('codice')->nullable(); $table->string('destinatario')->nullable(); $table->string('oggetto')->nullable(); $table->text('note')->nullable(); $table->string('scala')->nullable()->index(); $table->string('interno')->nullable()->index(); $table->string('c_i')->nullable(); $table->string('nome')->nullable(); $table->decimal('totale', 12, 2)->default(0); $table->string('nome_pdf')->nullable(); $table->integer('id_condomino')->nullable()->index(); $table->timestamps(); }); } if (! Schema::connection('gescon_import')->hasTable('corrisp_inviata')) { Schema::connection('gescon_import')->create('corrisp_inviata', function ($table) { $table->increments('id'); $table->string('cod_stabile')->index(); $table->integer('id_corrisp')->nullable(); $table->string('protocollo')->nullable()->index(); $table->string('tipo_documento')->nullable(); $table->string('data_invio')->nullable(); $table->string('forn_cond_altro')->nullable(); $table->string('codice')->nullable(); $table->string('destinatario')->nullable(); $table->string('oggetto')->nullable(); $table->string('lettera_tipo_caricata')->nullable(); $table->text('note')->nullable(); $table->integer('id_cond_for')->nullable()->index(); $table->timestamps(); }); } try { // Protoc_EC $csvEc = shell_exec('mdb-export ' . escapeshellarg($mdbPath) . ' Protoc_EC 2>/dev/null'); if ($csvEc) { $lines = explode("\n", $csvEc); $header = str_getcsv(array_shift($lines)); $ecRows = []; foreach ($lines as $l) { if (trim($l) === '') continue; $data = str_getcsv($l); if (count($data) < count($header)) continue; $row = array_combine($header, $data); $ecRows[] = [ 'cod_stabile' => '0013', 'id_corrisp' => is_numeric($row['ID_corrisp'] ?? null) ? (int) $row['ID_corrisp'] : null, 'protocollo' => $row['protocollo'] ?? null, 'tipo_documento' => $row['Tipo_documento'] ?? null, 'data_invio' => $row['Data'] ?? null, 'forn_cond_altro' => $row['Forn_Cond_Altro'] ?? null, 'codice' => $row['Codice'] ?? null, 'destinatario' => $row['Destinatario'] ?? null, 'oggetto' => $row['Oggetto'] ?? null, 'note' => $row['Note'] ?? null, 'scala' => $row['Scala'] ?? null, 'interno' => $row['Interno'] ?? null, 'c_i' => $row['C_I'] ?? null, 'nome' => $row['Nome'] ?? null, 'totale' => is_numeric($row['Totale'] ?? null) ? (float) $row['Totale'] : 0, 'nome_pdf' => $row['Nome_pdf'] ?? null, 'id_condomino' => is_numeric($row['id_condomino'] ?? null) ? (int) $row['id_condomino'] : null, 'created_at' => now(), 'updated_at' => now(), ]; } DB::connection('gescon_import')->table('protoc_ec')->where('cod_stabile', '0013')->delete(); DB::connection('gescon_import')->table('protoc_ec')->insert($ecRows); $this->info('Protoc_EC sincronizzato: ' . count($ecRows) . ' record.'); } // Corrisp_inviata $csvCorr = shell_exec('mdb-export ' . escapeshellarg($mdbPath) . ' Corrisp_inviata 2>/dev/null'); if ($csvCorr) { $lines = explode("\n", $csvCorr); $header = str_getcsv(array_shift($lines)); $corrRows = []; foreach ($lines as $l) { if (trim($l) === '') continue; $data = str_getcsv($l); if (count($data) < count($header)) continue; $row = array_combine($header, $data); $corrRows[] = [ 'cod_stabile' => '0013', 'id_corrisp' => is_numeric($row['ID_corrisp'] ?? null) ? (int) $row['ID_corrisp'] : null, 'protocollo' => $row['protocollo'] ?? null, 'tipo_documento' => $row['Tipo_documento'] ?? null, 'data_invio' => $row['Data'] ?? null, 'forn_cond_altro' => $row['Forn_Cond_Altro'] ?? null, 'codice' => $row['Codice'] ?? null, 'destinatario' => $row['Destinatario'] ?? null, 'oggetto' => $row['Oggetto'] ?? null, 'lettera_tipo_caricata' => $row['lettera_tipo_caricata'] ?? ($row['Lettera_tipo_caricata'] ?? null), 'note' => $row['Note'] ?? null, 'id_cond_for' => is_numeric($row['id_cond_for'] ?? null) ? (int) $row['id_cond_for'] : null, 'created_at' => now(), 'updated_at' => now(), ]; } DB::connection('gescon_import')->table('corrisp_inviata')->where('cod_stabile', '0013')->delete(); DB::connection('gescon_import')->table('corrisp_inviata')->insert($corrRows); $this->info('Corrisp_inviata sincronizzato: ' . count($corrRows) . ' record.'); } } catch (\Throwable $e) { $this->warn('Avviso sincronizzazione protocollo: ' . $e->getMessage()); } } $this->info('Bonifica Stabile 0013 completata con successo!'); return 0; } }