$legacyCode, '--solo' => 'stabili', '--path' => $options['path'] ?? '/mnt/gescon-archives/gescon']; if (!empty($options['dry'])) $params['--dry-run'] = true; if (!empty($options['limit'])) $params['--limit'] = (int)$options['limit']; Artisan::call('gescon:import-full', $params); $out = Artisan::output(); $counts = $this->parseCounts($out); $this->touchMapping($legacyCode, $counts, !empty($options['dry'])); // Enrichment (solo se non dry) $enrichment = []; if (empty($options['dry'])) { try { $enrichment = (new StabileEnrichmentService())->enrich($legacyCode, $options['path'] ?? '/mnt/gescon-archives/gescon'); } catch (\Throwable $e) { Log::warning('EssentialImportService enrichment error: ' . $e->getMessage()); } } return ['step' => 'stabili'] + $counts + ['output' => $out, 'enrichment' => $enrichment]; } public function importGestioni(Amministratore $amm, string $legacyCode, array $options = []): array { $root = $options['path'] ?? '/mnt/gescon-archives/gescon'; $params = ['--stabile' => $legacyCode, '--root' => $root]; if (!empty($options['force_months'])) $params['--force-update-months'] = true; if (!empty($options['dry'])) $params['--dry-run'] = true; Artisan::call('gescon:import-gestioni', $params); $out = Artisan::output(); return ['step' => 'gestioni', 'output' => $out]; } public function importBanche(Amministratore $amm, string $legacyCode, array $options = []): array { $params = ['--stabile' => $legacyCode, '--solo' => 'banche', '--path' => $options['path'] ?? '/mnt/gescon-archives/gescon']; if (!empty($options['dry'])) $params['--dry-run'] = true; Artisan::call('gescon:import-full', $params); $out = Artisan::output(); return ['step' => 'banche', 'output' => $out]; } public function runAll(Amministratore $amm, string $legacyCode, array $options = []): array { $agg = []; $agg[] = $this->importStabileCore($amm, $legacyCode, $options); if (empty($options['dry'])) { $agg[] = $this->importGestioni($amm, $legacyCode, $options); $agg[] = $this->importBanche($amm, $legacyCode, $options); } return $agg; } /** Calcola hash del record staging principale per stabile (per rilevare cambi). */ private function computeStabileHash(string $legacyCode, string $basePath): ?string { try { $parts = []; if (Schema::connection('gescon_import')->hasTable('stabili')) { $r = DB::connection('gescon_import')->table('stabili')->where('cod_stabile', $legacyCode)->first(); if ($r) $parts[] = json_encode($r); } if (Schema::connection('gescon_import')->hasTable('condomin')) { $r2 = DB::connection('gescon_import')->table('condomin')->where('cod_stabile', $legacyCode)->first(); if ($r2) $parts[] = json_encode($r2); } if (!$parts) return null; return substr(hash('sha256', implode('|', $parts)), 0, 40); } catch (\Throwable $e) { return null; } } /** Sincronizza uno stabile se i dati di staging sono cambiati; opzionale banche/gestioni. */ public function syncStabile(Amministratore $amm, string $legacyCode, array $options = []): array { $path = $options['path'] ?? '/mnt/gescon-archives/gescon'; $dry = !empty($options['dry']); $currentHash = $this->computeStabileHash($legacyCode, $path); $mapping = GesconImportMapping::where('legacy_code', $legacyCode)->where('user_id', Auth::id())->first(); $prevHash = $mapping ? ($mapping->meta['stabile_hash'] ?? null) : null; if ($currentHash && $currentHash === $prevHash) { // Nulla da fare (ma arricchimento facoltativo) if (empty($dry)) { try { $enr = (new StabileEnrichmentService())->enrich($legacyCode, $path); } catch (\Throwable $e) { $enr = ['error' => $e->getMessage()]; } } else { $enr = []; } return ['changed' => false, 'hash' => $currentHash, 'enrichment' => $enr]; } $steps = []; $steps[] = $this->importStabileCore($amm, $legacyCode, $options); if (!$dry && !empty($options['with_gestioni'])) $steps[] = $this->importGestioni($amm, $legacyCode, $options); if (!$dry && !empty($options['with_banche'])) $steps[] = $this->importBanche($amm, $legacyCode, $options); // aggiorna hash if ($mapping) { $meta = $mapping->meta ?? []; if ($currentHash) $meta['stabile_hash'] = $currentHash; $mapping->meta = $meta; $mapping->save(); } return ['changed' => true, 'new_hash' => $currentHash, 'steps' => $steps]; } private function parseCounts(string $out): array { $created = 0; $updated = 0; if (preg_match('/creati\s*:\s*(\d+)/i', $out, $m)) $created = (int)$m[1]; if (preg_match('/aggiornati\s*:\s*(\d+)/i', $out, $m)) $updated = (int)$m[1]; return ['created' => $created, 'updated' => $updated]; } private function touchMapping(string $legacyCode, array $counts, bool $dry): void { try { $mapping = GesconImportMapping::firstOrCreate(['user_id' => Auth::id(), 'legacy_code' => $legacyCode], ['status' => 'pending']); $mapping->status = $dry ? 'dry-run' : 'synced'; $mapping->last_dry_run_at = $dry ? Carbon::now() : $mapping->last_dry_run_at; $mapping->last_sync_at = $dry ? $mapping->last_sync_at : Carbon::now(); $meta = $mapping->meta ?? []; $meta['last_core_counts'] = $counts; $mapping->meta = $meta; $mapping->save(); } catch (\Throwable $e) { Log::warning('EssentialImportService touchMapping failed: ' . $e->getMessage()); } } }