hasTable('condomin')) { return 0; } if (!Schema::hasTable('proprieta') || !Schema::hasTable('unita_immobiliari') || !Schema::hasTable('soggetti')) { return 0; } $created = 0; $updated = 0; $skipped = 0; $processed = 0; $batch = $limit ? min(max(1, $limit), 1000) : 1000; $offset = 0; while (true) { $q = DB::connection('gescon_import')->table('condomin'); if ($this->option('stabile')) { $q->where('cod_stabile', $this->option('stabile')); } if ($this->option('scala')) { $q->where('scala', $this->option('scala')); } $q->limit($batch)->offset($offset); $rows = $q->get(); if ($rows->isEmpty()) { break; } foreach ($rows as $r) { // Resolve unità $unita = $this->findUnitaByStagingRow($r); if (!$unita) { $skipped++; continue; } // Resolve soggetto (già creato in stepSoggetti) $nome = isset($r->nome) ? trim((string)$r->nome) : null; $cognome = isset($r->cognome) ? trim((string)$r->cognome) : null; if ($nome === '') { $nome = null; } if ($cognome === '') { $cognome = null; } $sog = $this->findExistingSoggetto( trim($r->codice_fiscale ?? '') ?: null, trim($r->email ?? '') ?: null, $nome, $cognome ); if (!$sog) { $sog = $this->createSoggettoFromDirittiRow($r); if (!$sog) { $skipped++; continue; } } $this->ensurePersonaForSoggetto($sog); $tipo = ($r->proprietario ?? 0) ? 'proprieta' : (($r->inquilino ?? 0) ? 'locazione' : 'proprieta'); $exists = DB::table('proprieta') ->where('unita_immobiliare_id', $unita->id) ->where('soggetto_id', $sog->id) ->first(); if ($exists) { if (($exists->tipo_diritto ?? '') !== $tipo) { DB::table('proprieta')->where('id', $exists->id)->update([ 'tipo_diritto' => $tipo, 'updated_at' => now(), ]); $updated++; } else { $skipped++; } } else { DB::table('proprieta')->insert([ 'unita_immobiliare_id' => $unita->id, 'soggetto_id' => $sog->id, 'tipo_diritto' => $tipo, 'percentuale_possesso' => null, 'data_inizio' => null, 'data_fine' => null, 'created_at' => now(), 'updated_at' => now() ]); $created++; } $processed++; if ($limit && $processed >= $limit) { break 2; } } $offset += $batch; } $this->line(" → diritti: creati {$created}, aggiornati {$updated}, skip {$skipped}"); $this->dedupProprietaPairs(); return $created + $updated; } private function createSoggettoFromDirittiRow(object $row): ?object { if (!Schema::hasTable('soggetti')) { return null; } $cf = trim((string)($row->codice_fiscale ?? '')) ?: null; if ($cf) { $cf = strtoupper($cf); } $email = trim((string)($row->email ?? '')) ?: null; $nome = isset($row->nome) ? trim((string)$row->nome) : null; $cognome = isset($row->cognome) ? trim((string)$row->cognome) : null; if ($nome === '') { $nome = null; } if ($cognome === '') { $cognome = null; } if (!$nome && !$cognome) { return null; } $tipo = ($row->inquilino ?? 0) ? 'inquilino' : 'proprietario'; $data = [ 'old_id' => $this->safeOldId($row->cod_cond ?? null), 'nome' => $nome, 'cognome' => $cognome, 'ragione_sociale' => null, 'codice_fiscale' => $cf, 'partita_iva' => null, 'email' => $email, 'telefono' => $row->telefono ?? null, 'indirizzo' => $row->indirizzo_corrispondenza ?? null, 'cap' => null, 'citta' => null, 'provincia' => null, 'tipo' => $tipo, 'attivo' => Schema::hasColumn('soggetti', 'attivo') ? true : null, 'created_at' => now(), 'updated_at' => now(), ]; if (Schema::hasColumn('soggetti', 'codice_univoco')) { $baseKey = $this->normalizeNameKey($nome, $cognome) ?: ($email ?: 'ND'); $code = $this->generateStableCondKey('S', $row->cod_stabile ?? 'S0', $baseKey); $tries = 0; while (DB::table('soggetti')->where('codice_univoco', $code)->exists() && $tries < 5) { $salt = ($row->cod_cond ?? '') . '-' . ($tries + 1); $code = $this->generateStableCondKey('S', $row->cod_stabile ?? 'S0', $baseKey . '|' . $salt); $tries++; } $data['codice_univoco'] = $code; $existingByCode = DB::table('soggetti')->where('codice_univoco', $code)->first(); if ($existingByCode) { $patch = []; foreach ( [ 'nome' => $nome, 'cognome' => $cognome, 'codice_fiscale' => $cf, 'email' => $email, 'telefono' => $row->telefono ?? null, 'indirizzo' => $row->indirizzo_corrispondenza ?? null, ] as $field => $value ) { if ($value && (empty($existingByCode->$field) || $existingByCode->$field === 'ND')) { $patch[$field] = $value; } } if (!empty($patch)) { $patch['updated_at'] = now(); DB::table('soggetti')->where('id', $existingByCode->id)->update($patch); } return DB::table('soggetti')->where('id', $existingByCode->id)->first(); } } $this->dynamicInsert('soggetti', $data); return $this->findExistingSoggetto($cf, $email, $nome, $cognome); } }