249 lines
11 KiB
PHP
Executable File
249 lines
11 KiB
PHP
Executable File
<?php
|
|
|
|
namespace App\Http\Controllers\Admin;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Cache;
|
|
use Illuminate\Support\Facades\Config;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Auth;
|
|
use Illuminate\Support\Facades\Log;
|
|
use Illuminate\Support\Str;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Carbon\Carbon;
|
|
|
|
class ComuniImportController extends Controller
|
|
{
|
|
private function progressKey(): string
|
|
{
|
|
return 'comuni_import:' . (Auth::id() ?? 'guest');
|
|
}
|
|
|
|
public function stagingTables()
|
|
{
|
|
$conn = Config::get('database.connections.gescon_import') ? 'gescon_import' : Config::get('database.default');
|
|
// Try to list tables containing "comun"
|
|
$driver = DB::connection($conn)->getDriverName();
|
|
try {
|
|
if ($driver === 'mysql') {
|
|
$dbName = DB::connection($conn)->getDatabaseName();
|
|
$rows = DB::connection($conn)->select(
|
|
'SELECT table_name FROM information_schema.tables WHERE table_schema = ? AND table_name LIKE ? ORDER BY table_name',
|
|
[$dbName, 'mdb%comun%']
|
|
);
|
|
$tables = array_map(fn($r) => $r->table_name, $rows);
|
|
} elseif ($driver === 'pgsql') {
|
|
$rows = DB::connection($conn)->select(
|
|
"SELECT tablename FROM pg_catalog.pg_tables WHERE schemaname NOT IN ('pg_catalog','information_schema') AND tablename ILIKE 'mdb%comun%' ORDER BY tablename"
|
|
);
|
|
$tables = array_map(fn($r) => $r->tablename, $rows);
|
|
} else {
|
|
// Fallback generic (may not work on all drivers)
|
|
$tables = [];
|
|
}
|
|
} catch (\Throwable $e) {
|
|
$tables = [];
|
|
}
|
|
return new JsonResponse(['tables' => $tables, 'connection' => $conn]);
|
|
}
|
|
|
|
public function init(Request $request)
|
|
{
|
|
$request->validate([
|
|
'staging_table' => 'required|string',
|
|
]);
|
|
$conn = Config::get('database.connections.gescon_import') ? 'gescon_import' : Config::get('database.default');
|
|
$table = $request->string('staging_table')->toString();
|
|
if (!DB::connection($conn)->getSchemaBuilder()->hasTable($table)) {
|
|
return new JsonResponse(['ok' => false, 'error' => 'Tabella di staging non trovata', 'table' => $table], 400);
|
|
}
|
|
$total = (int) DB::connection($conn)->table($table)->count();
|
|
$state = [
|
|
'table' => $table,
|
|
'connection' => $conn,
|
|
'total' => $total,
|
|
'processed' => 0,
|
|
'last_id' => 0,
|
|
'status' => 'running',
|
|
'started_at' => Carbon::now()->toISOString(),
|
|
];
|
|
Cache::put($this->progressKey(), $state, Carbon::now()->addHours(2));
|
|
return new JsonResponse(['ok' => true, 'progress' => $state]);
|
|
}
|
|
|
|
public function progress()
|
|
{
|
|
$state = Cache::get($this->progressKey());
|
|
if (!$state) return new JsonResponse(['ok' => false, 'error' => 'Nessun import attivo']);
|
|
// Calcola percentuale
|
|
$pct = $state['total'] > 0 ? (int) floor(($state['processed'] / $state['total']) * 100) : 0;
|
|
$state['percent'] = max(0, min(100, $pct));
|
|
return new JsonResponse(['ok' => true, 'progress' => $state]);
|
|
}
|
|
|
|
public function processChunk(Request $request)
|
|
{
|
|
$chunk = max(1, min(2000, (int) $request->input('chunk', 500)));
|
|
$state = Cache::get($this->progressKey());
|
|
if (!$state) return new JsonResponse(['ok' => false, 'error' => 'Import non inizializzato'], 400);
|
|
if (($state['status'] ?? '') === 'completed') {
|
|
return new JsonResponse(['ok' => true, 'progress' => $state]);
|
|
}
|
|
$conn = $state['connection'];
|
|
$table = $state['table'];
|
|
$lastId = (int) ($state['last_id'] ?? 0);
|
|
|
|
if (!DB::connection($conn)->getSchemaBuilder()->hasTable($table)) {
|
|
return new JsonResponse(['ok' => false, 'error' => 'Tabella di staging non trovata', 'table' => $table], 400);
|
|
}
|
|
|
|
$rows = DB::connection($conn)->table($table)
|
|
->where('id', '>', $lastId)
|
|
->orderBy('id')
|
|
->limit($chunk)
|
|
->get();
|
|
|
|
if ($rows->isEmpty()) {
|
|
$state['status'] = 'completed';
|
|
$state['completed_at'] = Carbon::now()->toISOString();
|
|
Cache::put($this->progressKey(), $state, Carbon::now()->addHours(2));
|
|
return new JsonResponse(['ok' => true, 'progress' => $state]);
|
|
}
|
|
|
|
// Import logic → comuni_italiani
|
|
$imported = 0;
|
|
foreach ($rows as $r) {
|
|
$data = (array) $r;
|
|
$map = $this->mapComuneRecord($data);
|
|
if (!$map) {
|
|
$lastId = $r->id; // advance pointer
|
|
continue;
|
|
}
|
|
try {
|
|
$this->upsertComuneItaliano($map);
|
|
$imported++;
|
|
} catch (\Throwable $e) {
|
|
Log::warning('Comuni import: errore record', ['id' => $r->id, 'err' => $e->getMessage()]);
|
|
}
|
|
$lastId = $r->id;
|
|
}
|
|
|
|
$state['processed'] = (int) $state['processed'] + $rows->count();
|
|
$state['last_id'] = $lastId;
|
|
if ($state['processed'] >= $state['total']) {
|
|
$state['status'] = 'completed';
|
|
$state['completed_at'] = Carbon::now()->toISOString();
|
|
}
|
|
Cache::put($this->progressKey(), $state, Carbon::now()->addHours(2));
|
|
|
|
return new JsonResponse(['ok' => true, 'progress' => $state, 'chunk_imported' => $imported]);
|
|
}
|
|
|
|
private function mapComuneRecord(array $row): ?array
|
|
{
|
|
// Normalizza chiavi in snake
|
|
$lower = [];
|
|
foreach ($row as $k => $v) {
|
|
$lower[Str::snake(strtolower((string) $k))] = is_string($v) ? trim($v) : $v;
|
|
}
|
|
$get = function (array $candidates) use ($lower) {
|
|
foreach ($candidates as $c) {
|
|
if (array_key_exists($c, $lower) && $lower[$c] !== null && $lower[$c] !== '') return $lower[$c];
|
|
}
|
|
return null;
|
|
};
|
|
|
|
$codiceIstat = $get(['codice_istat', 'istat', 'cod_istat', 'codiceistat']);
|
|
$denominazione = $get(['denominazione', 'comune', 'nome_comune', 'dencom']);
|
|
$den_straniera = $get(['denominazione_straniera', 'denominazione_altra_lingua', 'denominazione_alt']);
|
|
$codiceCat = $get(['codice_catastale', 'cod_catastale', 'cod_cat', 'belfiore']);
|
|
$cap = $get(['cap']);
|
|
$provCod = strtoupper((string) $get(['provincia', 'sigla_provincia', 'prov', 'pr']));
|
|
if ($provCod && strlen($provCod) > 2) $provCod = substr($provCod, 0, 2);
|
|
$provDen = $get(['provincia_denominazione', 'denominazione_provincia']);
|
|
$regCod = $get(['regione_codice', 'codice_regione', 'regione_cod']);
|
|
$regDen = $get(['regione_denominazione', 'denominazione_regione']);
|
|
|
|
if (!$denominazione && !$codiceIstat && !$codiceCat) return null;
|
|
|
|
return [
|
|
'codice_istat' => $codiceIstat,
|
|
'denominazione' => $denominazione ?: null,
|
|
'denominazione_straniera' => $den_straniera ?: null,
|
|
'codice_catastale' => $codiceCat ?: null,
|
|
'cap' => $cap ?: null,
|
|
'provincia_codice' => $provCod ?: null,
|
|
'provincia_denominazione' => $provDen ?: null,
|
|
'regione_codice' => $regCod ?: null,
|
|
'regione_denominazione' => $regDen ?: null,
|
|
];
|
|
}
|
|
|
|
private function upsertComuneItaliano(array $rec): void
|
|
{
|
|
// Preferisci upsert per codice_istat univoco, altrimenti fallback su codice_catastale
|
|
if (!empty($rec['codice_istat'])) {
|
|
DB::table('comuni_italiani')->updateOrInsert(
|
|
['codice_istat' => $rec['codice_istat']],
|
|
[
|
|
'denominazione' => $rec['denominazione'],
|
|
'denominazione_straniera' => $rec['denominazione_straniera'],
|
|
'codice_catastale' => $rec['codice_catastale'],
|
|
'cap' => $rec['cap'],
|
|
'provincia_codice' => $rec['provincia_codice'],
|
|
'provincia_denominazione' => $rec['provincia_denominazione'],
|
|
'regione_codice' => $rec['regione_codice'],
|
|
'regione_denominazione' => $rec['regione_denominazione'],
|
|
'updated_at' => Carbon::now(),
|
|
'created_at' => DB::raw('COALESCE(created_at, NOW())'),
|
|
]
|
|
);
|
|
return;
|
|
}
|
|
if (!empty($rec['codice_catastale'])) {
|
|
$existing = DB::table('comuni_italiani')->where('codice_catastale', $rec['codice_catastale'])->first();
|
|
if ($existing) {
|
|
DB::table('comuni_italiani')->where('id', $existing->id)->update([
|
|
'denominazione' => $rec['denominazione'],
|
|
'denominazione_straniera' => $rec['denominazione_straniera'],
|
|
'cap' => $rec['cap'],
|
|
'provincia_codice' => $rec['provincia_codice'],
|
|
'provincia_denominazione' => $rec['provincia_denominazione'],
|
|
'regione_codice' => $rec['regione_codice'],
|
|
'regione_denominazione' => $rec['regione_denominazione'],
|
|
'updated_at' => Carbon::now(),
|
|
]);
|
|
} else {
|
|
DB::table('comuni_italiani')->insert(array_merge($rec, [
|
|
'created_at' => Carbon::now(),
|
|
'updated_at' => Carbon::now(),
|
|
]));
|
|
}
|
|
return;
|
|
}
|
|
// Fallback fragile: denominazione+provincia
|
|
if (!empty($rec['denominazione'])) {
|
|
$q = DB::table('comuni_italiani')->where('denominazione', $rec['denominazione']);
|
|
if (!empty($rec['provincia_codice'])) $q->where('provincia_codice', $rec['provincia_codice']);
|
|
$existing = $q->first();
|
|
if ($existing) {
|
|
DB::table('comuni_italiani')->where('id', $existing->id)->update([
|
|
'codice_istat' => $rec['codice_istat'],
|
|
'codice_catastale' => $rec['codice_catastale'],
|
|
'cap' => $rec['cap'],
|
|
'provincia_denominazione' => $rec['provincia_denominazione'],
|
|
'regione_codice' => $rec['regione_codice'],
|
|
'regione_denominazione' => $rec['regione_denominazione'],
|
|
'updated_at' => Carbon::now(),
|
|
]);
|
|
} else {
|
|
DB::table('comuni_italiani')->insert(array_merge($rec, [
|
|
'created_at' => Carbon::now(),
|
|
'updated_at' => Carbon::now(),
|
|
]));
|
|
}
|
|
}
|
|
}
|
|
}
|