netgescon-day0/resources/views/admin/gescon-import/tabs/dashboard.blade.php

651 lines
34 KiB
PHP

<!-- STATISTICHE SINTETICHE (stile NetGescon) -->
<div class="grid gap-3 md:grid-cols-2 lg:grid-cols-4 mb-3">
<div class="col-span-1">
<div class="netgescon-card h-100">
<div class="netgescon-card-body">
<div class="flex items-start justify-between">
<div>
<div class="text-gray-500 uppercase text-sm">Stabili importati</div>
<div class="h3 mb-0">{{ number_format($stats['stabili']['totali']) }}</div>
<div class="text-sm text-gray-500 mt-1">Attivi: <strong>{{ $stats['stabili']['attivi'] }}</strong></div>
</div>
<span class="netgescon-badge netgescon-badge-primary"><i class="mdi mdi-home-group"></i></span>
</div>
</div>
<div class="netgescon-card-footer flex justify-end">
<a href="#stabili" onclick="showGesconTab('stabili'); return false;">Visualizza dettagli</a>
</div>
</div>
</div>
<div class="col-span-1">
<div class="netgescon-card h-100">
<div class="netgescon-card-body">
<div class="flex items-start justify-between">
<div>
<div class="text-gray-500 uppercase text-sm">Unità immobiliari</div>
<div class="h3 mb-0">{{ number_format($stats['unita']['totali']) }}</div>
<div class="text-sm text-gray-500 mt-1">Con millesimi: <strong>{{ $stats['unita']['con_millesimi'] }}</strong></div>
</div>
<span class="netgescon-badge netgescon-badge-success"><i class="mdi mdi-home-variant"></i></span>
</div>
</div>
<div class="netgescon-card-footer flex justify-end">
<a href="#unita" onclick="showGesconTab('unita'); return false;">Visualizza dettagli</a>
</div>
</div>
</div>
<div class="col-span-1">
<div class="netgescon-card h-100">
<div class="netgescon-card-body">
<div class="flex items-start justify-between">
<div>
<div class="text-gray-500 uppercase text-sm">Soggetti</div>
<div class="h3 mb-0">{{ number_format($stats['soggetti']['totali']) }}</div>
<div class="text-sm text-gray-500 mt-1">Proprietari: <strong>{{ $stats['soggetti']['proprietari'] }}</strong></div>
</div>
<span class="netgescon-badge netgescon-badge-info"><i class="mdi mdi-account-group"></i></span>
</div>
</div>
<div class="netgescon-card-footer flex justify-end">
<a href="#soggetti" onclick="showGesconTab('soggetti'); return false;">Visualizza dettagli</a>
</div>
</div>
</div>
<div class="col-span-1">
<div class="netgescon-card h-100">
<div class="netgescon-card-body">
<div class="flex items-start justify-between">
<div>
<div class="text-gray-500 uppercase text-sm">Fornitori</div>
<div class="h3 mb-0">{{ number_format($stats['fornitori']['totali']) }}</div>
<div class="text-sm text-gray-500 mt-1">Attivi: <strong>{{ $stats['fornitori']['attivi'] }}</strong></div>
</div>
<span class="netgescon-badge netgescon-badge-warning"><i class="mdi mdi-store"></i></span>
</div>
</div>
<div class="netgescon-card-footer flex justify-end">
<a href="#fornitori" onclick="showGesconTab('fornitori'); return false;">Visualizza dettagli</a>
</div>
</div>
</div>
</div>
<!-- INFORMAZIONI AMMINISTRATORE -->
<div class="mb-3">
<div class="">
<div class="netgescon-card">
<div class="netgescon-card-header">
<h3 class="card-title mb-0"><i class="mdi mdi-account-tie me-2"></i> Informazioni Amministratore</h3>
</div>
<div class="netgescon-card-body">
<div class="grid md:grid-cols-2 gap-4">
<div class="grid grid-cols-12 gap-2 items-center">
<div class="col-span-4 text-gray-600">Nome:</div>
<div class="col-span-8">{{ $amministratore->nome }} {{ $amministratore->cognome }}</div>
<div class="col-span-4 text-gray-600">Codice Univoco:</div>
<div class="col-span-8"><span class="netgescon-badge netgescon-badge-primary">{{ $amministratore->codice_univoco }}</span></div>
<div class="col-span-4 text-gray-600">Email Studio:</div>
<div class="col-span-8">{{ $amministratore->email_studio ?? 'Non specificata' }}</div>
</div>
<div class="grid grid-cols-12 gap-2 items-center">
<div class="col-span-4 text-gray-600">Denominazione Studio:</div>
<div class="col-span-8">{{ $amministratore->denominazione_studio ?? 'Non specificata' }}</div>
<div class="col-span-4 text-gray-600">Ultimo Accesso:</div>
<div class="col-span-8">{{ $amministratore->ultimo_accesso ? $amministratore->ultimo_accesso->format('d/m/Y H:i') : 'Mai' }}</div>
<div class="col-span-4 text-gray-600">Stato:</div>
<div class="col-span-8">
@if($amministratore->attivo)
<span class="netgescon-badge netgescon-badge-success">Attivo</span>
@else
<span class="netgescon-badge netgescon-badge-danger">Non attivo</span>
@endif
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- DATI RECENTI -->
<div class="grid md:grid-cols-2 gap-4">
<!-- Ultimi Stabili -->
<div class="">
<div class="netgescon-card">
<div class="netgescon-card-header flex justify-between items-center">
<h3 class="card-title mb-0"><i class="mdi mdi-home-group me-2"></i> Ultimi Stabili Importati</h3>
<button type="button" class="netgescon-btn netgescon-btn-sm netgescon-btn-outline-secondary" onclick="showGesconTab('stabili')">
<i class="mdi mdi-eye"></i> Vedi tutti
</button>
</div>
<div class="netgescon-card-body p-0">
<div class="table-responsive">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>Denominazione</th>
<th>Indirizzo</th>
<th>Unità</th>
<th>Data Import</th>
</tr>
</thead>
<tbody>
@forelse($datiRecenti['ultimi_stabili'] as $stabile)
<tr>
<td>
<strong>{{ $stabile->denominazione }}</strong>
@if($stabile->codice_interno)
<br><small class="text-gray-500">{{ $stabile->codice_interno }}</small>
@endif
</td>
<td>
{{ $stabile->indirizzo }}
@if($stabile->numero_civico)
{{ $stabile->numero_civico }}
@endif
<br>
<small class="text-gray-500">
{{ $stabile->cap }} {{ $stabile->citta ?? '' }} @if(!empty($stabile->provincia)) ({{ $stabile->provincia }}) @endif
</small>
</td>
<td>
<span class="netgescon-badge">{{ $stabile->numero_unita ?? 0 }}</span>
</td>
<td>
<small>{{ $stabile->created_at->format('d/m/Y H:i') }}</small>
</td>
</tr>
@empty
<tr>
<td colspan="4" class="text-center text-gray-500 py-3">
Nessun stabile importato
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
</div>
</div>
<!-- Ultime Unità -->
<div class="">
<div class="netgescon-card">
<div class="netgescon-card-header flex justify-between items-center">
<h3 class="card-title mb-0"><i class="mdi mdi-home-variant me-2"></i> Ultime Unità Importate</h3>
<button type="button" class="netgescon-btn netgescon-btn-sm netgescon-btn-outline-secondary" data-bs-toggle="tab" data-bs-target="#unita">
<i class="mdi mdi-eye"></i> Vedi tutte
</button>
</div>
<div class="netgescon-card-body p-0">
<div class="table-responsive">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>Codice</th>
<th>Stabile</th>
<th>Posizione</th>
<th>Superficie</th>
</tr>
</thead>
<tbody>
@forelse($datiRecenti['ultime_unita'] as $unita)
<tr>
<td>
<strong>{{ $unita->codice_unita }}</strong>
</td>
<td>
<small>{{ $unita->stabile->denominazione ?? 'N/A' }}</small>
</td>
<td>
@if($unita->scala)
Scala {{ $unita->scala }}
@endif
@if($unita->piano)
Piano {{ $unita->piano }}
@endif
@if($unita->interno)
Int. {{ $unita->interno }}
@endif
</td>
<td>
@if($unita->superficie)
{{ number_format($unita->superficie, 0) }}
@else
<span class="text-gray-500">N/D</span>
@endif
</td>
</tr>
@empty
<tr>
<td colspan="4" class="text-center text-gray-500 py-3">
Nessuna unità importata
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<!-- AZIONI RAPIDE + SYNC -->
<div class="mt-4 grid gap-4 lg:grid-cols-2">
<div class="netgescon-card">
<div class="netgescon-card-header">
<h3 class="card-title mb-0"><i class="mdi mdi-flash me-2"></i> Azioni Rapide Import</h3>
</div>
<div class="netgescon-card-body">
<div class="grid sm:grid-cols-2 gap-3">
<button type="button" class="netgescon-btn netgescon-btn-primary netgescon-btn-block" onclick="showGesconTab('stabili')">
<i class="mdi mdi-database-import me-1"></i>
Pipeline Import
</button>
<button type="button" class="netgescon-btn netgescon-btn-outline-primary netgescon-btn-block" onclick="showGesconTab('mapping')">
<i class="mdi mdi-table-link me-1"></i>
Mapping Campi
</button>
<button type="button" class="netgescon-btn netgescon-btn-success netgescon-btn-block" onclick="showGesconTab('unita'); if(window.showImportUnitaModal){ window.showImportUnitaModal(); }">
<i class="mdi mdi-home-variant me-1"></i>
Import Unità
</button>
<a href="{{ route('admin.fornitori.index') }}" class="netgescon-btn netgescon-btn-warning netgescon-btn-block">
<i class="mdi mdi-store me-1"></i>
Gestione Fornitori
</a>
</div>
</div>
</div>
<div class="netgescon-card">
<div class="netgescon-card-header flex items-center justify-between">
<h3 class="card-title mb-0"><i class="mdi mdi-sync me-2"></i> Sincronizzazione Rapida</h3>
<span class="netgescon-badge netgescon-badge-info text-xs">Beta</span>
</div>
<div class="netgescon-card-body space-y-3">
<p class="text-sm text-gray-600">Apri il pannello di sincronizzazione per scegliere uno stabile legacy, abilitare l'auto-sync e lanciare la pipeline completa oppure i singoli step (Stabili, Unità, Soggetti, Diritti, Millesimi, Banche).</p>
<button type="button" class="netgescon-btn netgescon-btn-primary w-full" onclick="window.openSyncModal && window.openSyncModal()">
<i class="mdi mdi-refresh-circle me-1"></i>
Sincronizza intero stabile
</button>
<div class="text-xs text-gray-500">Hai a disposizione {{ number_format(count($legacyPreview ?? [])) }} codici legacy rilevati automaticamente.</div>
<div class="grid grid-cols-2 md:grid-cols-3 gap-2">
@foreach(['stabili' => 'Stabili', 'unita' => 'Unità', 'soggetti' => 'Soggetti', 'diritti' => 'Diritti', 'millesimi' => 'Millesimi', 'banche' => 'Banche'] as $actionKey => $label)
<button type="button" class="netgescon-btn netgescon-btn-sm netgescon-btn-outline-secondary" data-prefill-action="{{ $actionKey }}" onclick="window.openSyncModal && window.openSyncModal('{{ $actionKey }}')">
<i class="mdi mdi-play-circle-outline me-1"></i>{{ $label }}
</button>
@endforeach
</div>
<div class="text-xs text-gray-500">
Suggerimento: attiva la casella «Mantieni stabile sincronizzato» nel pannello per lasciare che NetGescon ripeta automaticamente l'allineamento quando rileva modifiche nell'archivio legacy.
</div>
</div>
</div>
</div>
<!-- CHECKLIST MIGRAZIONI + MDB -->
<div class="mt-4">
<div class="netgescon-card">
<div class="netgescon-card-header flex items-center justify-between">
<h3 class="card-title mb-0"><i class="mdi mdi-clipboard-check-outline me-2"></i> Checklist Migrazione & MDB</h3>
@if(!empty($legacyBasePath))
<span class="text-xs text-gray-500">Archivio base: <code>{{ $legacyBasePath }}</code></span>
@endif
</div>
<div class="netgescon-card-body text-sm text-gray-600 space-y-3">
<p>Prima di ogni sincronizzazione assicurati di aver eseguito i seguenti step. Questo riduce errori dovuti a schema non aggiornato o MDB non caricato.</p>
<ol class="list-decimal list-inside space-y-2">
<li>
<strong>Allinea il database applicativo</strong><br>
<code>php artisan migrate --force</code><br>
Garantisce che tutte le tabelle/relazioni richieste dalla pipeline siano presenti.
</li>
<li>
<strong>Carica lo staging da singolo_anno.mdb</strong><br>
<code>php artisan gescon:load-mdb --mdb=/percorso/singolo_anno.mdb --table=condomin --stabile=XXXX --truncate</code><br>
Usa il codice legacy corretto e il file dell'anno che vuoi importare. Ripeti per altre tabelle (rate, incassi, ecc.) se necessario.
</li>
<li>
<strong>Esegui la sincronizzazione desiderata</strong><br>
Usa i pulsanti sopra per scegliere fra sync completo o step specifici e monitora l'output per eventuali avvisi.
</li>
</ol>
<div class="bg-slate-50 border border-dashed border-slate-200 rounded p-3 text-xs text-slate-500">
Suggerimento: salva i percorsi MDB definitivi in <em>Configurazione Import</em> per evitare di reinserirli. Se lavori da shell, puoi usare il file <code>sync-complete-netgescon.sh</code> come riferimento.
</div>
</div>
</div>
</div>
<!-- GESTIONE DOCUMENTALE: Documenti collegati recenti -->
<div class="mt-4">
<div class="">
<div class="netgescon-card">
<div class="netgescon-card-header flex justify-between items-center">
<h3 class="card-title mb-0"><i class="mdi mdi-file-document-outline me-2"></i> Documenti Collegati recenti</h3>
@if(isset($amministratore))
<a class="netgescon-btn netgescon-btn-sm netgescon-btn-outline-primary" href="{{ route('admin.stabili.index') }}">Vai a Stabili</a>
@endif
</div>
<div class="netgescon-card-body p-0">
<div class="table-responsive">
<table class="table table-striped table-hover mb-0">
<thead class="table-light">
<tr>
<th>Protocollo</th>
<th>Titolo</th>
<th>Tipo</th>
<th>Stabile</th>
<th>Scadenza</th>
<th class="text-end" style="width: 140px;">Azioni</th>
</tr>
</thead>
<tbody>
@forelse(($datiRecenti['ultimi_documenti'] ?? []) as $doc)
<tr>
<td><code>{{ $doc->protocollo_formattato ?? ($doc->numero_protocollo ?? '') }}</code></td>
<td>{{ $doc->titolo ?? '' }}</td>
<td><span class="netgescon-badge text-uppercase">{{ $doc->tipo_documento ?? '' }}</span></td>
<td>{{ $doc->stabile->denominazione ?? '' }}</td>
<td>
@if($doc->data_scadenza)
<span class="netgescon-badge @switch($doc->stato_scadenza)
@case('scadenza_imminente') netgescon-badge-warning @break
@case('disdetta_imminente') netgescon-badge-danger @break
@case('scaduto') netgescon-badge-secondary @break
@default netgescon-badge-success @endswitch">
{{ $doc->data_scadenza->format('d/m/Y') }}
</span>
@else
<span class="text-gray-500">—</span>
@endif
</td>
<td class="text-end">
<a class="netgescon-btn netgescon-btn-sm netgescon-btn-outline-secondary" href="{{ route('admin.documenti-collegati.download', $doc->id) }}">
<i class="mdi mdi-download"></i>
Download
</a>
</td>
</tr>
@empty
<tr>
<td colspan="6" class="text-center text-gray-500 py-3">
Nessun documento collegato recente
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
@php
$syncLegacyOptions = collect($legacyPreview ?? [])->map(function ($row) {
$legacy = is_array($row) ? ($row['legacy_code'] ?? null) : ($row->legacy_code ?? null);
$den = is_array($row) ? ($row['denominazione'] ?? null) : ($row->denominazione ?? null);
return [
'code' => trim((string)($legacy ?? '')),
'label' => trim((string)($den ?? '')),
];
})->filter(fn ($row) => $row['code'] !== '')->unique('code')->values()->take(600);
@endphp
<!-- Modal sincronizzazione rapida -->
<div id="sync-stabile-modal" class="fixed inset-0 bg-black/40 items-center justify-center p-4 hidden" style="z-index: 70;">
<div class="bg-white w-full max-w-4xl rounded-lg shadow-2xl">
<div class="px-5 py-3 border-b flex items-center justify-between">
<div>
<h4 class="text-lg font-semibold">Sincronizzazione GESCON</h4>
<p class="text-xs text-gray-500">Seleziona uno stabile legacy e scegli se eseguire il sync completo o i singoli step.</p>
</div>
<button type="button" class="netgescon-btn netgescon-btn-sm netgescon-btn-outline-secondary" onclick="window.closeSyncModal && window.closeSyncModal()">
<i class="mdi mdi-close"></i>
</button>
</div>
<div class="p-5 space-y-4">
<div class="grid md:grid-cols-2 gap-4">
<div>
<label class="block text-sm font-medium text-slate-600 mb-1">Codice legacy stabile</label>
<input type="text" id="sync-legacy-input" class="netgescon-input w-full" list="sync-legacy-datalist" placeholder="es. 0021" autocomplete="off">
<datalist id="sync-legacy-datalist">
@foreach($syncLegacyOptions as $opt)
<option value="{{ $opt['code'] }}">{{ $opt['code'] }}{{ $opt['label'] ? ' · '.$opt['label'] : '' }}</option>
@endforeach
</datalist>
<small class="text-xs text-slate-500">Sono mostrati i primi {{ number_format($syncLegacyOptions->count()) }} codici rilevati.</small>
</div>
<div>
<label class="block text-sm font-medium text-slate-600 mb-1">Denominazione legacy</label>
<div id="sync-legacy-label" class="bg-slate-100 border border-dashed border-slate-200 rounded px-3 py-2 text-sm text-slate-600">—</div>
</div>
</div>
<div class="grid md:grid-cols-2 gap-3">
<label class="inline-flex items-center gap-2 text-sm">
<input type="checkbox" id="sync-auto-checkbox" class="form-checkbox">
Mantieni stabile sincronizzato automaticamente
</label>
<label class="inline-flex items-center gap-2 text-sm">
<input type="checkbox" id="sync-dry-run" class="form-checkbox">
Esegui come Dry-run (non scrive in dominio)
</label>
</div>
<div class="grid md:grid-cols-2 gap-3">
<label class="inline-flex items-center gap-2 text-sm">
<input type="checkbox" id="sync-with-gestioni" class="form-checkbox" checked>
Includi gestioni e rate (solo sync completo)
</label>
<label class="inline-flex items-center gap-2 text-sm">
<input type="checkbox" id="sync-with-banche" class="form-checkbox" checked>
Includi banche/casse (solo sync completo)
</label>
</div>
<div class="grid md:grid-cols-3 gap-3">
<button type="button" class="netgescon-btn netgescon-btn-primary" data-sync-action="full">
<i class="mdi mdi-refresh-circle me-1"></i> Sync intero stabile
</button>
<button type="button" class="netgescon-btn netgescon-btn-outline-secondary" data-sync-action="stabili">
<i class="mdi mdi-home-city-outline me-1"></i> Solo stabili
</button>
<button type="button" class="netgescon-btn netgescon-btn-outline-secondary" data-sync-action="millesimi">
<i class="mdi mdi-chart-bell-curve me-1"></i> Millesimi
</button>
<button type="button" class="netgescon-btn netgescon-btn-outline-secondary" data-sync-action="unita">
<i class="mdi mdi-home-variant-outline me-1"></i> Unità
</button>
<button type="button" class="netgescon-btn netgescon-btn-outline-secondary" data-sync-action="soggetti">
<i class="mdi mdi-account-multiple-outline me-1"></i> Soggetti
</button>
<button type="button" class="netgescon-btn netgescon-btn-outline-secondary" data-sync-action="diritti">
<i class="mdi mdi-vector-link me-1"></i> Diritti
</button>
<button type="button" class="netgescon-btn netgescon-btn-outline-secondary" data-sync-action="banche">
<i class="mdi mdi-bank me-1"></i> Banche
</button>
<button type="button" class="netgescon-btn netgescon-btn-outline-secondary" data-sync-action="reports">
<i class="mdi mdi-file-chart me-1"></i> Solo log (dry)
</button>
<button type="button" class="netgescon-btn netgescon-btn-outline-dark" onclick="window.closeSyncModal && window.closeSyncModal()">
<i class="mdi mdi-close-circle-outline me-1"></i> Chiudi
</button>
</div>
<div id="sync-status" class="text-sm text-slate-600"></div>
<div id="sync-log-wrapper" class="hidden">
<pre id="sync-log" class="bg-gray-900 text-green-200 text-xs p-3 rounded max-h-72 overflow-auto"></pre>
</div>
</div>
</div>
</div>
<script>
window.GESCON_SYNC = Object.assign({
legacy: @json($syncLegacyOptions->toArray()),
syncStatus: @json($syncByLegacy ?? []),
routes: {
sync: @json(route('admin.gescon-import.sync')),
execute: @json(route('admin.gescon-import.execute')),
importUnita: @json(route('admin.gescon-import.import-unita')),
mappingSave: @json(route('admin.gescon-import.mapping.save')),
},
csrf: @json(csrf_token()),
}, window.GESCON_SYNC || {});
(function(){
const modal = document.getElementById('sync-stabile-modal');
const legacyInput = document.getElementById('sync-legacy-input');
const legacyLabel = document.getElementById('sync-legacy-label');
const autoCheckbox = document.getElementById('sync-auto-checkbox');
const dryCheckbox = document.getElementById('sync-dry-run');
const gestCheckbox = document.getElementById('sync-with-gestioni');
const bancheCheckbox = document.getElementById('sync-with-banche');
const statusBox = document.getElementById('sync-status');
const logWrapper = document.getElementById('sync-log-wrapper');
const logPre = document.getElementById('sync-log');
let pendingAction = null;
function legacyMeta(code){
if (!code) return null;
const list = window.GESCON_SYNC.legacy || [];
return list.find(row => row.code === code) || null;
}
function updateLegacyLabel(){
const code = legacyInput.value.trim();
const meta = legacyMeta(code);
legacyLabel.textContent = meta && meta.label ? meta.label : (code ? '' : 'Seleziona un codice');
autoCheckbox.checked = Boolean(window.GESCON_SYNC.syncStatus && window.GESCON_SYNC.syncStatus[code]);
}
window.openSyncModal = function(prefill){
pendingAction = prefill || null;
modal.classList.remove('hidden');
modal.classList.add('flex');
statusBox.textContent = pendingAction ? `Azione selezionata: ${pendingAction}` : '';
logWrapper.classList.add('hidden');
logPre.textContent = '';
updateLegacyLabel();
};
window.closeSyncModal = function(){
modal.classList.remove('flex');
modal.classList.add('hidden');
};
legacyInput && legacyInput.addEventListener('change', updateLegacyLabel);
legacyInput && legacyInput.addEventListener('blur', updateLegacyLabel);
autoCheckbox && autoCheckbox.addEventListener('change', async function(){
const code = legacyInput.value.trim();
if (!code) {
alert('Seleziona un codice legacy prima di abilitare la sincronizzazione automatica.');
autoCheckbox.checked = !autoCheckbox.checked;
return;
}
try {
const fd = new FormData();
fd.append('_mapping_only', '1');
fd.append('_legacy_code', code);
fd.append('sync_enabled', autoCheckbox.checked ? '1' : '0');
await fetch(window.GESCON_SYNC.routes.mappingSave, {
method: 'POST',
headers: { 'X-CSRF-TOKEN': window.GESCON_SYNC.csrf },
body: fd,
});
window.GESCON_SYNC.syncStatus = window.GESCON_SYNC.syncStatus || {};
window.GESCON_SYNC.syncStatus[code] = autoCheckbox.checked;
statusBox.textContent = 'Preferenza auto-sync aggiornata';
} catch (err) {
console.error(err);
alert('Errore durante il salvataggio della preferenza auto-sync.');
}
});
function appendLog(line){
logWrapper.classList.remove('hidden');
logPre.textContent += line + '\n';
logPre.scrollTop = logPre.scrollHeight;
}
async function handleSyncAction(action){
const code = legacyInput.value.trim();
if (!code) {
alert('Inserisci un codice legacy valido.');
return;
}
statusBox.textContent = `Esecuzione ${action} in corso...`;
logWrapper.classList.remove('hidden');
logPre.textContent = '';
try {
let response;
if (action === 'full') {
const fd = new FormData();
fd.append('legacy_code', code);
fd.append('dry', dryCheckbox.checked ? '1' : '0');
fd.append('with_gestioni', gestCheckbox.checked ? '1' : '0');
fd.append('with_banche', bancheCheckbox.checked ? '1' : '0');
response = await fetch(window.GESCON_SYNC.routes.sync, {
method: 'POST',
headers: { 'X-CSRF-TOKEN': window.GESCON_SYNC.csrf, 'Accept': 'application/json' },
body: fd,
});
const data = await response.json();
if (!data.ok) throw new Error(data.error || 'Sync fallito');
appendLog(JSON.stringify(data, null, 2));
} else if (['stabili', 'millesimi', 'banche'].includes(action)) {
const fd = new FormData();
fd.append('_ajax', '1');
fd.append('tipo_import', 'stabili');
fd.append('legacy_code', code);
fd.append('solo', action);
fd.append('test_mode', dryCheckbox.checked ? '1' : '0');
response = await fetch(window.GESCON_SYNC.routes.execute, {
method: 'POST',
headers: { 'X-CSRF-TOKEN': window.GESCON_SYNC.csrf, 'Accept': 'application/json', 'X-Requested-With': 'XMLHttpRequest' },
body: fd,
});
const text = await response.text();
appendLog(text.slice(0, 4000));
if (!response.ok) throw new Error('Import non completato');
} else if (['unita', 'soggetti', 'diritti'].includes(action)) {
const payload = {
legacy_code: code,
steps: [action],
dry_run: dryCheckbox.checked,
};
response = await fetch(window.GESCON_SYNC.routes.importUnita, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': window.GESCON_SYNC.csrf,
'Accept': 'application/json'
},
body: JSON.stringify(payload),
});
const data = await response.json();
appendLog(JSON.stringify(data, null, 2));
if (!data.ok) throw new Error('Pipeline unità con errori');
} else if (action === 'reports') {
appendLog('Nessuna azione eseguita. Usa questa voce per annotare note durante i dry-run.');
} else {
appendLog('Azione non riconosciuta.');
}
statusBox.textContent = `Azione ${action} completata.`;
} catch (err) {
console.error(err);
statusBox.textContent = 'Errore: ' + err.message;
appendLog('Errore: ' + err.message);
}
}
document.querySelectorAll('#sync-stabile-modal [data-sync-action]').forEach(btn => {
btn.addEventListener('click', () => {
const action = btn.getAttribute('data-sync-action');
handleSyncAction(action);
});
});
})();
</script>