/* global window, document, CSS, fetch */ // NetGescon — GESCON Mapping JS (extracted from Blade) (function () { 'use strict'; const CFG = window.GESCON_MAPPING || {}; const R = (k) => (CFG.routes || {})[k] || ''; const LEGACY = CFG.legacyCode || ''; const CSRF = CFG.csrf || ''; // Utilities function escapeHtml(s) { return String(s) .replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>') .replaceAll('"', '"').replaceAll("'", '''); } function formatEuro(value) { if (value === null || value === undefined || value === '') { return ''; } const num = Number(value); if (!Number.isFinite(num)) { return String(value); } try { return new Intl.NumberFormat('it-IT', { style: 'currency', currency: 'EUR' }).format(num); } catch (e) { return num.toFixed(2); } } function toggleInlineCreate(trigger, show = true) { const row = trigger && typeof trigger.closest === 'function' ? trigger.closest('.mapping-tab-row, .mapping-voce-row') : null; if (!row) return; const ui = row.querySelector('.inline-create-ui'); if (!ui) return; if (show) { ui.classList.remove('hidden'); const focusTarget = ui.querySelector('.new-col-name'); if (focusTarget) { setTimeout(() => focusTarget.focus(), 0); } } else { ui.classList.add('hidden'); } } // ===== Mapping filtering & UI ===== let __mappingVisibilityMode = 'all'; let __searchTerm = ''; function filterLegacyList(term) { const t = (term || '').toLowerCase(); document.querySelectorAll('#legacy-list > li').forEach(li => { const key = (li.getAttribute('data-key') || '').toLowerCase(); const txt = (li.innerText || '').toLowerCase(); li.style.display = (!t || key.includes(t) || txt.includes(t)) ? '' : 'none'; }); } function applyMappingVisibility() { document.querySelectorAll('#mapping-rows .mapping-row').forEach(row => { const sel = row.querySelector('select.mapping-select'); const mapped = !!(sel && sel.value); let show = true; if (__mappingVisibilityMode === 'mapped') show = mapped; else if (__mappingVisibilityMode === 'unmapped') show = !mapped; if (show && __searchTerm) { const term = __searchTerm.toLowerCase(); const key = (row.getAttribute('data-key') || '').toLowerCase(); const nameEl = row.querySelector('label small'); const nameTxt = ((nameEl && nameEl.textContent) || '').toLowerCase(); let selectedLabel = '', selectedValue = ''; if (sel && sel.selectedIndex >= 0) { const opt = sel.options[sel.selectedIndex]; selectedLabel = (opt.text || '').toLowerCase(); selectedValue = (opt.value || '').toLowerCase(); } if (!(key.includes(term) || nameTxt.includes(term) || selectedLabel.includes(term) || selectedValue.includes(term))) { show = false; } } row.style.display = show ? '' : 'none'; }); } function setMappingFilter(mode) { __mappingVisibilityMode = mode || 'all'; document.querySelectorAll('#mapping-visibility-buttons button').forEach(btn => { if (btn.getAttribute('data-mode') === __mappingVisibilityMode) btn.classList.add('active'); else btn.classList.remove('active'); }); applyMappingVisibility(); } function syncMappingSearch(term) { __searchTerm = term || ''; try { const lf = document.getElementById('legacy-filter-input'); if (lf && lf.value !== term) lf.value = term; const tf = document.getElementById('target-filter-input'); if (tf && tf.value !== term) tf.value = term; } catch (e) { } filterLegacyList(term); applyMappingVisibility(); } function buildTargetSelect(name) { let html = ''; return html; } function promptAddField() { const key = prompt('Chiave campo legacy (es. telefono_amministratore):'); if (!key) return; const name = prompt('Etichetta leggibile (opzionale):', key.replace(/[_-]/g, ' ')); addLegacyField(key, name || key); } function addLegacyField(key, label) { if (document.querySelector('#mapping-rows .mapping-row[data-key="' + key + '"]')) return; const li = document.createElement('li'); li.className = 'flex justify-between items-center'; li.style.borderBottom = '1px solid #eee'; li.style.padding = '.5rem'; li.setAttribute('data-key', key); li.innerHTML = '
' + escapeHtml(label) + '
' + escapeHtml(key) + '
Sorgente'; const ul = document.getElementById('legacy-list'); if (ul) ul.appendChild(li); const row = document.createElement('div'); row.className = 'grid md:grid-cols-12 gap-3 items-center mb-2 mapping-row'; row.setAttribute('data-key', key); row.innerHTML = '
' + escapeHtml(key) + '
' + '
' + buildTargetSelect('mapping[' + key + ']') + '
'; const container = document.getElementById('mapping-rows'); if (container) container.appendChild(row); } function updateMappingPreviews() { document.querySelectorAll('#mapping-form .mapping-row').forEach(row => { const key = row.getAttribute('data-key'); const valEl = document.querySelector('.legacy-value[data-field-value="' + CSS.escape(key) + '"]'); const preview = row.querySelector('.import-preview'); if (preview) preview.textContent = valEl ? (valEl.textContent || '—') : '—'; }); } // ===== Manual Values ===== function getManualContainer() { return document.getElementById('manual-values-container'); } function refreshManualEmptyState() { const container = getManualContainer(); if (!container) return; const rows = container.querySelectorAll('.manual-value-row'); const placeholder = container.querySelector('.manual-value-empty'); if (rows.length === 0) { if (placeholder) { placeholder.classList.remove('hidden'); } else { const info = document.createElement('div'); info.className = 'manual-value-empty text-xs text-gray-500 border rounded p-2 bg-slate-50'; info.textContent = 'Nessun valore manuale configurato.'; container.appendChild(info); } } else if (placeholder) { placeholder.classList.add('hidden'); } } function syncManualValueRow(selectEl) { if (!selectEl) return; const row = selectEl.closest('.manual-value-row'); if (!row) return; const input = row.querySelector('.manual-value-input'); if (!input) return; const target = (selectEl.value || '').trim(); if (target) { input.name = 'manual_target_values[' + target + ']'; row.dataset.target = target; } else { input.name = ''; row.dataset.target = ''; } } function addManualValueRow(target = '', value = '') { const container = getManualContainer(); if (!container) return; const tmpl = document.getElementById('manual-value-row-template'); if (!tmpl) return; const cloneRoot = (() => { if (tmpl.content && tmpl.content.firstElementChild) { return tmpl.content.firstElementChild.cloneNode(true); } const wrapper = document.createElement('div'); wrapper.innerHTML = (tmpl.innerHTML || '').trim(); return wrapper.firstElementChild ? wrapper.firstElementChild.cloneNode(true) : null; })(); if (!cloneRoot) return; container.appendChild(cloneRoot); const select = cloneRoot.querySelector('.manual-value-target'); const input = cloneRoot.querySelector('.manual-value-input'); if (select) { select.value = target || ''; syncManualValueRow(select); } if (input) input.value = value || ''; refreshManualEmptyState(); if (select) { setTimeout(() => select.focus(), 0); } else if (input) { setTimeout(() => input.focus(), 0); } } function removeManualValueRow(triggerEl) { const row = triggerEl ? triggerEl.closest('.manual-value-row') : null; if (row) row.remove(); refreshManualEmptyState(); } function initializeManualValueRows() { const container = getManualContainer(); if (!container) return; container.querySelectorAll('.manual-value-row .manual-value-target').forEach(selectEl => { syncManualValueRow(selectEl); }); const defaults = (CFG.manualTargetValues && typeof CFG.manualTargetValues === 'object') ? CFG.manualTargetValues : null; if (container.querySelectorAll('.manual-value-row').length === 0 && defaults) { Object.keys(defaults).forEach(key => { addManualValueRow(key, defaults[key]); }); } refreshManualEmptyState(); } // ===== Samples & Presets ===== let __sampleIndex = 0; async function loadSample(idx) { const box = document.getElementById('legacy-sample'); if (box) box.innerHTML = '
Caricamento…
'; try { const params = new URLSearchParams({ index: String(idx) }); if (LEGACY) params.set('legacy_code', LEGACY); const res = await fetch(R('sample') + '?' + params.toString()); const j = await res.json(); if (!j.ok) { if (box) box.innerHTML = '
' + escapeHtml(j.error || 'Errore caricamento') + '
'; return; } __sampleIndex = j.index || 0; const data = j.data || {}; document.querySelectorAll('.legacy-value[data-field-value]').forEach(el => { const key = el.getAttribute('data-field-value'); el.textContent = (key in data) ? String(data[key] ?? '') : '—'; }); try { const legacyBankBadge = document.getElementById('bank-count-legacy'); if (legacyBankBadge) { const keys = Object.keys(data || {}); const ibanKeys = keys.filter(k => /iban/.test(String(k).toLowerCase())); const count = ibanKeys.filter(k => String(data[k] ?? '').trim().length > 0).length; legacyBankBadge.textContent = 'Banche presenti: ' + count; legacyBankBadge.style.display = ''; } } catch (e) { } updateMappingPreviews(); try { populateGestioneRatesFromData(data); } catch (e) { } if (box) box.innerHTML = ''; } catch (e) { if (box) box.innerHTML = '
Errore
'; } } function browseSample(delta) { __sampleIndex = Math.max(0, __sampleIndex + (delta || 0)); return loadSample(__sampleIndex); } function syncLegacyPreview() { return loadSample(__sampleIndex || 0); } function applyPreset() { const sel = document.getElementById('preset-select'); const key = (sel?.value || '').trim(); const preset = (CFG.mappingPresets || {})[key]; document.getElementById('preset_key').value = key; if (!preset) { updatePresetMeta(); return; } const mapping = preset.mapping || {}; document.querySelectorAll('#mapping-form .mapping-row').forEach(row => { const legacyKey = row.getAttribute('data-key'); const sel2 = row.querySelector('select.mapping-select'); if (!legacyKey || !sel2) return; const target = mapping[legacyKey]; if (target) { sel2.value = target; } }); const meta = Object.assign({}, preset.meta || {}); document.getElementById('preset_meta').value = JSON.stringify(meta); } function updatePresetMeta() { const sel = document.getElementById('preset-select'); const key = (sel?.value || '').trim(); const preset = (CFG.mappingPresets || {})[key]; const base = preset?.meta || {}; const meta = Object.assign({}, base); document.getElementById('preset_meta').value = JSON.stringify(meta); document.getElementById('preset_key').value = key; } // ===== Segments ===== function switchSegment(seg) { const segments = ['stabili', 'gestioni', 'finanziari', 'unita', 'tabelle', 'voci']; segments.forEach(s => { const el = document.getElementById('segment-' + s); if (el) { if (s === seg) el.classList.remove('d-none'); else el.classList.add('d-none'); } document.querySelectorAll('.mapping-steps [data-segment="' + s + '"]').forEach(li => { if (s === seg) li.classList.add('active'); else li.classList.remove('active'); }); }); if (LEGACY) { if (seg === 'unita') { refreshUnitaPreview(); } if (seg === 'gestioni') { if (!Array.isArray(__gestioniYears) || !__gestioniYears.length) { // try to fetch years then load data (async () => { try { const res = await fetch(R('years') + '?legacy_code=' + encodeURIComponent(LEGACY)); if (res.ok) { const js = await res.json(); __gestioniYears = Array.isArray(js.years) ? js.years : []; __gestioniYearIndex = Math.max(0, __gestioniYears.length - 1); updateGestioneYearUI(); } } catch (e) { } try { await loadGestioneYearData(); } catch (e) { } })(); } else { loadGestioneYearData(); } } if (seg === 'finanziari') { loadLegacyCasse(); } if (seg === 'tabelle' && typeof window.reloadTabelleColumns === 'function') { try { window.reloadTabelleColumns(); } catch (_) { } } if (seg === 'voci' && typeof window.reloadVociColumns === 'function') { try { window.reloadVociColumns(); } catch (_) { } } } } // ===== Gestione anni (generale_stabile) ===== function ensureRow(id) { const tr = document.getElementById(id); if (!tr) return null; if (tr.children.length < 13) { for (let i = tr.children.length; i < 13; i++) { const td = document.createElement('td'); td.className = 'text-center text-xs'; td.dataset.mese = i; td.textContent = ''; tr.appendChild(td); } } return tr; } function populateGestioneRatesFromData(data) { if (!data) return; const rowOrd = ensureRow('row-ord'); const rowRis = ensureRow('row-ris'); for (let i = 1; i <= 12; i++) { const ko = 'ord_rata_' + i; const kr = 'ris_rata_' + i; if (rowOrd) { const td = rowOrd.children[i]; if (td) td.textContent = (ko in data && String(data[ko] || '0') !== '0') ? '✓' : ''; } if (rowRis) { const td = rowRis.children[i]; if (td) td.textContent = (kr in data && String(data[kr] || '0') !== '0') ? '✓' : ''; } } const annoO = data['anno_o'] || data['anno_or'] || ''; const annoR = data['anno_r'] || ''; const goAnno = document.getElementById('go-anno'); if (goAnno) goAnno.textContent = annoO ? '(' + annoO + ')' : ''; const grAnno = document.getElementById('gr-anno'); if (grAnno) grAnno.textContent = annoR ? '(' + annoR + ')' : ''; const cellAnnoO = document.getElementById('gg-anno-o'); if (cellAnnoO) cellAnnoO.textContent = annoO || '—'; const cellAnnoR = document.getElementById('gg-anno-r'); if (cellAnnoR) cellAnnoR.textContent = annoR || '—'; const statoO = data['stato_o'] || (annoO ? 'aperta' : '—'); const statoR = data['stato_r'] || (annoR ? 'aperta' : '—'); const cellStatoO = document.getElementById('gg-stato-o'); if (cellStatoO) cellStatoO.textContent = statoO; const cellStatoR = document.getElementById('gg-stato-r'); if (cellStatoR) cellStatoR.textContent = statoR; } let __gestioniYears = Array.isArray(CFG.availableYears) ? CFG.availableYears : []; let __gestioniYearIndex = 0; function browseGestioneYear(delta) { if (!__gestioniYears || __gestioniYears.length === 0) return; __gestioniYearIndex = Math.min(Math.max(0, __gestioniYearIndex + delta), __gestioniYears.length - 1); updateGestioneYearUI(); loadGestioneYearData(); } function updateGestioneYearUI() { const lbl = document.getElementById('gestione-year-label'); if (lbl) { lbl.textContent = (__gestioniYears && __gestioniYears.length) ? __gestioniYears[__gestioniYearIndex] : '—'; } } async function loadGestioneYearData() { const year = __gestioniYears[__gestioniYearIndex]; if (!year || !LEGACY) return; try { const url = R('gestioniYear') + '?legacy_code=' + encodeURIComponent(LEGACY) + '&anno=' + encodeURIComponent(year); const res = await fetch(url); if (!res.ok) throw new Error('Errore caricamento gestioni'); const js = await res.json(); // Wire Staging Loader Unità link if possible try { const btn = document.getElementById('btn-unita-loader'); const base = R('archiveUi') || ''; if (btn && base) { const p = (js.meta && js.meta.path_singolo_anno) ? String(js.meta.path_singolo_anno) : ''; const q = new URLSearchParams(); if (p) q.set('mdb_path', p); // Pre-fill doesn't support table param explicitly, but UI lets user pick tables; this opens with mdb preselected btn.href = base + (q.toString() ? ('?' + q.toString()) : ''); } } catch (_) { } const data = {}; if (js.ordinaria && js.ordinaria.rate) { Object.keys(js.ordinaria.rate).forEach(k => { data['ord_rata_' + k] = 1; }); data.anno_o = js.ordinaria.anno; data.stato_o = js.ordinaria.stato; } if (js.riscaldamento && js.riscaldamento.rate) { Object.keys(js.riscaldamento.rate).forEach(k => { data['ris_rata_' + k] = 1; }); data.anno_r = js.riscaldamento.anno; data.stato_r = js.riscaldamento.stato; } populateGestioneRatesFromData(data, year); const tbody = document.querySelector('#straordinarie-table tbody'); if (tbody) { const list = js.straordinarie || []; if (list.length === 0) { tbody.innerHTML = `(Nessuna straordinaria per ${year})`; } else { tbody.innerHTML = list.map(s => `${s.id || '—'}${escapeHtml(s.descrizione || '—')}${s.data_inizio || '—'}${s.data_fine || '—'}${(s.rate_emesse || 0)}/${(s.rate_totali || 0)}${s.periodicita || ''}`).join(''); } } const annoS = document.getElementById('gg-anno-s'); if (annoS) annoS.textContent = year; } catch (e) { console.warn(e); } } // ===== Finanziari (casse/banche) ===== let __legacyCasse = []; async function loadLegacyCasse() { const tb = document.querySelector('#legacy-casse-table tbody'); if (!tb) return; tb.innerHTML = 'Caricamento...'; try { const url = R('casse') + '?legacy_code=' + encodeURIComponent(LEGACY); const res = await fetch(url); if (!res.ok) throw new Error('HTTP ' + res.status); const js = await res.json(); __legacyCasse = (js.casse || []).map(c => ({ codice: c.codice, descrizione: c.descrizione, abi: c.abi, cab: c.cab, cin: c.cin || c.CIN || null, cuc: c.cuc || c.CUC || c.codice_cuc || null, iban: c.iban, swift: c.swift || c.SWIFT || c.bic || c.BIC || null, conto: c.numero_conto || c.conto || null, intestatario: c.intestatario || c.intestazione || null, filiale: c.filiale || c.filiale_descr || null, indirizzo: c.indirizzo || c.indirizzo_filiale || null, cap: c.cap || c.cap_filiale || null, citta: c.citta || c.comune || null, provincia: c.provincia || c.prov || null, telefono: c.telefono || c.telefono_ufficio || null, email: c.email || null, pec: c.pec || c.email_pec || null, valuta: c.valuta || c.currency || null, saldo: c.saldo_iniziale_euro ?? c.saldo_iniziale ?? c.saldo ?? null, saldo_euro: c.saldo_iniziale_euro ?? null, data_saldo: c.data_saldo || c.data_saldo_iniziale || null, note: c.note || null })); if (!__legacyCasse.find(c => c.codice === 'CON')) { __legacyCasse.unshift({ codice: 'CON', descrizione: 'CASSA CONTANTI', abi: null, cab: null, cin: null, cuc: null, iban: null, swift: null, conto: 'CON', intestatario: null, valuta: 'EUR', saldo: null, saldo_euro: null, data_saldo: null, note: null }); } renderLegacyCasse(); ensureBancheMappingRows(); ensureMandatoryConMapping(); } catch (e) { tb.innerHTML = 'Errore caricamento'; } } function renderLegacyCasse(term) { const tbody = document.querySelector('#legacy-casse-table tbody'); if (!tbody) return; const t = (term || '').toLowerCase(); const rows = __legacyCasse.filter(c => !t || c.codice.toLowerCase().includes(t) || (c.descrizione || '').toLowerCase().includes(t)); if (rows.length === 0) { tbody.innerHTML = 'Nessun conto'; return; } tbody.innerHTML = rows.map(c => { const saldoFormatted = formatEuro(c.saldo_euro ?? c.saldo); return ` ${escapeHtml(c.codice || '')} ${escapeHtml(c.descrizione || '')} ${escapeHtml(c.abi || '')} ${escapeHtml(c.cab || '')} ${escapeHtml(c.cuc || '')} ${escapeHtml(c.iban || '')} ${escapeHtml(saldoFormatted || '')} `; }).join(''); try { const badge = document.getElementById('bank-count-legacy'); if (badge) { const exclCon = __legacyCasse.filter(c => c.codice !== 'CON').length; const hasCon = __legacyCasse.some(c => c.codice === 'CON'); badge.style.display = 'inline-block'; badge.textContent = 'Legacy conti: ' + String(exclCon) + (hasCon ? ' (+CON)' : ''); } } catch (e) { } } function filterLegacyCasse(term) { renderLegacyCasse(term); } function ensureBancheMappingRows() { const container = document.getElementById('banche-mapping-rows'); if (!container) return; const saved = Array.isArray(CFG.savedBancheMapping) ? CFG.savedBancheMapping : []; if (!container.querySelector('.banca-mapping-row')) { if (saved.length) { container.innerHTML = ''; saved.forEach(bm => { if (!bm || !bm.codice_legacy) return; addBancaMapping(String(bm.codice_legacy), bm); }); syncBancheJson(); } else { renderBanchePlaceholder(container); } } } function renderBanchePlaceholder(container) { if (!container) return; container.innerHTML = '
Seleziona una cassa legacy a sinistra per iniziare la configurazione.
'; } function addBancaMapping(codice, data) { if (!codice) return null; const container = document.getElementById('banche-mapping-rows'); if (!container) return null; const existing = container.querySelector(`[data-mapping-cod='${CSS.escape(codice)}']`); if (existing) { if (data) populateBancaMappingRow(existing, data); return existing; } if (container.querySelector('.placeholder-banche')) { container.innerHTML = ''; } const legacy = (__legacyCasse.find(x => x.codice === codice) || {}); const idx = container.querySelectorAll('.banca-mapping-row').length; const legacyDescr = (data?.descrizione_legacy) || (data?.legacy?.descrizione) || legacy.descrizione || ''; const legacyIban = data?.legacy?.iban || data?.iban || legacy.iban || ''; const legacyAbi = data?.legacy?.abi || legacy.abi || ''; const legacyCab = data?.legacy?.cab || legacy.cab || ''; const legacyCuc = data?.legacy?.cuc || data?.cuc || legacy.cuc || ''; const legacyCin = data?.legacy?.cin || legacy.cin || ''; const legacySwift = data?.legacy?.swift || legacy.swift || ''; const legacyConto = data?.legacy?.conto || legacy.conto || ''; const legacyIntestatario = data?.legacy?.intestatario || legacy.intestatario || ''; const legacyFiliale = data?.legacy?.filiale || data?.filiale || legacy.filiale || ''; const legacyIndirizzo = data?.legacy?.indirizzo || data?.indirizzo || legacy.indirizzo || ''; const legacyCap = data?.legacy?.cap || data?.cap || legacy.cap || ''; const legacyCitta = data?.legacy?.citta || data?.citta || legacy.citta || ''; const legacyProvincia = data?.legacy?.provincia || data?.provincia || legacy.provincia || ''; const legacyTelefono = data?.legacy?.telefono || data?.telefono || legacy.telefono || ''; const legacyEmail = data?.legacy?.email || data?.email || legacy.email || ''; const legacyPec = data?.legacy?.pec || data?.pec || legacy.pec || ''; const legacySaldo = (legacy.saldo_euro ?? legacy.saldo ?? ''); const hasLegacySaldo = legacySaldo !== '' && legacySaldo !== null && legacySaldo !== undefined; const legacyBadges = [ legacyIban ? `IBAN: ${escapeHtml(legacyIban)}` : '', (legacyAbi || legacyCab) ? `ABI/CAB: ${escapeHtml([legacyAbi, legacyCab].filter(Boolean).join(' • '))}` : '', legacyCuc ? `CUC: ${escapeHtml(legacyCuc)}` : '', legacySwift ? `SWIFT: ${escapeHtml(legacySwift)}` : '', legacyConto ? `Conto: ${escapeHtml(legacyConto)}` : '', hasLegacySaldo ? `Saldo: ${escapeHtml(formatEuro(legacySaldo) || '')}` : '', legacyFiliale ? `Filiale: ${escapeHtml(legacyFiliale)}` : '' ].filter(Boolean).join(''); const row = document.createElement('div'); row.className = 'banca-mapping-row border border-slate-200 rounded-lg p-4 bg-white shadow-sm hover:shadow transition-shadow'; row.setAttribute('data-mapping-cod', codice); row.setAttribute('data-descrizione-legacy', legacyDescr || ''); row.innerHTML = `
${escapeHtml(codice)} — ${escapeHtml(legacyDescr || 'Conto senza descrizione')}
${legacyBadges || 'Dati legacy non disponibili'}
Anagrafica contatto / Filiale
`; container.appendChild(row); if (data) { populateBancaMappingRow(row, data, legacy); } enforceDefaultForRow(row, legacy, codice); syncBancheJson(); return row; } function enforceDefaultForRow(row, legacy, codice) { if (!row) return; const tipo = row.querySelector('select[name*="[tipo_conto]"]'); if (tipo && !tipo.value) { tipo.value = (codice === 'CON') ? 'contanti' : 'bancario'; } const denominazione = row.querySelector('input[name*="[denominazione_banca]"]'); if (denominazione && !denominazione.value) { denominazione.value = legacy?.descrizione || (codice === 'CON' ? 'Cassa contanti' : ''); } const intestazione = row.querySelector('input[name*="[intestazione_conto]"]'); if (intestazione && !intestazione.value) { intestazione.value = legacy?.intestatario || ''; } const numero = row.querySelector('input[name*="[numero_conto]"]'); if (numero && !numero.value) { numero.value = legacy?.conto || codice; } const cucInput = row.querySelector('input[name*="[target][cuc]"]'); if (cucInput && !cucInput.value && legacy?.cuc) { cucInput.value = legacy.cuc; } const stato = row.querySelector('select[name*="[stato_conto]"]'); if (stato) { stato.value = 'attivo'; } const valuta = row.querySelector('input[name*="[valuta]"]'); if (valuta && !valuta.value) { valuta.value = 'EUR'; } const saldo = row.querySelector('input[name*="[saldo_iniziale]"]'); const saldoLegacy = (legacy?.saldo_euro ?? legacy?.saldo); if (saldo && !saldo.value && saldoLegacy !== undefined && saldoLegacy !== null && saldoLegacy !== '') { saldo.value = saldoLegacy; } const dataSaldo = row.querySelector('input[name*="[data_saldo_iniziale]"]'); if (dataSaldo && !dataSaldo.value && legacy?.data_saldo) { try { const d = new Date(legacy.data_saldo); if (!Number.isNaN(d.getTime())) { dataSaldo.value = d.toISOString().substring(0, 10); } } catch (e) { dataSaldo.value = legacy.data_saldo; } } const principale = row.querySelector('input[name*="[is_nostro_conto]"]'); if (principale && codice === 'CON') { principale.checked = true; } const filiale = row.querySelector('input[name*="[target][filiale]"]'); if (filiale && !filiale.value && legacy?.filiale) { filiale.value = legacy.filiale; } const indirizzo = row.querySelector('input[name*="[target][indirizzo]"]'); if (indirizzo && !indirizzo.value && legacy?.indirizzo) { indirizzo.value = legacy.indirizzo; } const cap = row.querySelector('input[name*="[target][cap]"]'); if (cap && !cap.value && legacy?.cap) { cap.value = legacy.cap; } const citta = row.querySelector('input[name*="[target][citta]"]'); if (citta && !citta.value && legacy?.citta) { citta.value = legacy.citta; } const provincia = row.querySelector('input[name*="[target][provincia]"]'); if (provincia && !provincia.value && legacy?.provincia) { provincia.value = legacy.provincia; } const telefono = row.querySelector('input[name*="[target][telefono_ufficio]"]'); if (telefono && !telefono.value && legacy?.telefono) { telefono.value = legacy.telefono; } const email = row.querySelector('input[name*="[target][email]"]'); if (email && !email.value && legacy?.email) { email.value = legacy.email; } const pec = row.querySelector('input[name*="[target][pec]"]'); if (pec && !pec.value && legacy?.pec) { pec.value = legacy.pec; } } function populateBancaMappingRow(row, data, legacyDefaults) { if (!row || !data) return; const target = data.target || {}; const tipoSelect = row.querySelector('select[name*="[tipo_conto]"]'); const tipoValue = target.tipo_conto || data.tipo_conto || (row.getAttribute('data-mapping-cod') === 'CON' ? 'contanti' : 'bancario'); if (tipoSelect && tipoValue) tipoSelect.value = tipoValue; const mapping = { '[denominazione_banca]': target.denominazione_banca || data.denominazione_banca || data.descrizione_legacy || legacyDefaults?.descrizione || '', '[intestazione_conto]': target.intestazione_conto || data.intestazione_conto || legacyDefaults?.intestatario || '', '[numero_conto]': target.numero_conto || data.numero_conto || data.target_cod_cassa || legacyDefaults?.conto || data.codice_legacy || row.getAttribute('data-mapping-cod'), '[iban]': target.iban || data.iban || data.legacy?.iban || legacyDefaults?.iban || '', '[bic_swift]': target.bic_swift || data.swift || data.bic_swift || legacyDefaults?.swift || '', '[abi]': target.abi || data.abi || data.legacy?.abi || legacyDefaults?.abi || '', '[cab]': target.cab || data.cab || data.legacy?.cab || legacyDefaults?.cab || '', '[target][cuc]': target.cuc || data.cuc || data.legacy?.cuc || legacyDefaults?.cuc || '', '[cin]': target.cin || data.cin || data.legacy?.cin || legacyDefaults?.cin || '', '[valuta]': target.valuta || data.valuta || 'EUR', '[saldo_iniziale]': target.saldo_iniziale ?? data.saldo_iniziale ?? '', '[data_saldo_iniziale]': target.data_saldo_iniziale || data.data_saldo_iniziale || '', '[note]': target.note || data.note || '', '[target][filiale]': target.filiale || data.filiale || data.target_filiale || legacyDefaults?.filiale || '', '[target][indirizzo]': target.indirizzo || data.indirizzo || data.target_indirizzo || legacyDefaults?.indirizzo || '', '[target][cap]': target.cap || data.cap || data.target_cap || legacyDefaults?.cap || '', '[target][citta]': target.citta || data.citta || data.target_citta || legacyDefaults?.citta || '', '[target][provincia]': target.provincia || data.provincia || data.target_provincia || legacyDefaults?.provincia || '', '[target][telefono_ufficio]': target.telefono_ufficio || data.telefono_ufficio || data.telefono || legacyDefaults?.telefono || '', '[target][email]': target.email || data.email || data.target_email || legacyDefaults?.email || '', '[target][pec]': target.pec || data.pec || data.target_pec || legacyDefaults?.pec || '' }; Object.entries(mapping).forEach(([suffix, value]) => { const selector = suffix === '[note]' ? `textarea[name*="${suffix}"]` : `input[name*="${suffix}"]`; const el = row.querySelector(selector); if (el !== null && value !== undefined && value !== null) { if (el.type === 'date' && typeof value === 'string' && value.includes('/')) { const [d, m, y] = value.split(/[\/\-]/); if (d && m && y) { const iso = `${y.length === 2 ? '20' + y : y}-${String(m).padStart(2, '0')}-${String(d).padStart(2, '0')}`; el.value = iso; } else { el.value = value; } } else { el.value = String(value); } } }); const stato = row.querySelector('select[name*="[stato_conto]"]'); if (stato) { stato.value = target.stato_conto || data.stato_conto || 'attivo'; } const principale = row.querySelector('input[name*="[is_nostro_conto]"]'); if (principale) { const checked = target.is_nostro_conto ?? data.is_nostro_conto ?? data.target_is_nostro_conto ?? (row.getAttribute('data-mapping-cod') === 'CON'); principale.checked = Boolean(checked); } } function removeBancaMappingRow(trigger) { const row = trigger?.closest('.banca-mapping-row'); const container = row?.parentElement; if (row) row.remove(); if (container && !container.querySelector('.banca-mapping-row')) { renderBanchePlaceholder(container); } syncBancheJson(); } function ensureMandatoryConMapping() { if (__legacyCasse.find(c => c.codice === 'CON')) { const container = document.getElementById('banche-mapping-rows'); if (container && !container.querySelector('[data-mapping-cod="CON"]')) { addBancaMapping('CON'); } const conRow = container?.querySelector('[data-mapping-cod="CON"]'); if (conRow) { const tipo = conRow.querySelector('select[name*="[tipo_conto]"]'); if (tipo) tipo.value = 'contanti'; const principale = conRow.querySelector('input[name*="[is_nostro_conto]"]'); if (principale) principale.checked = true; } syncBancheJson(); } } function collectValue(row, selector) { const el = row.querySelector(selector); if (!el) return null; const value = el.value; if (typeof value === 'string') { const trimmed = value.trim(); return trimmed === '' ? null : trimmed; } return value ?? null; } function syncBancheJson() { const container = document.getElementById('banche-mapping-rows'); const rows = [...(container?.querySelectorAll('.banca-mapping-row') || [])]; const normalized = rows.map(row => { const legacy = { descrizione: collectValue(row, 'input[name*="[legacy][descrizione]"]'), iban: collectValue(row, 'input[name*="[legacy][iban]"]'), abi: collectValue(row, 'input[name*="[legacy][abi]"]'), cab: collectValue(row, 'input[name*="[legacy][cab]"]'), cin: collectValue(row, 'input[name*="[legacy][cin]"]'), cuc: collectValue(row, 'input[name*="[legacy][cuc]"]'), conto: collectValue(row, 'input[name*="[legacy][conto]"]'), intestatario: collectValue(row, 'input[name*="[legacy][intestatario]"]'), swift: collectValue(row, 'input[name*="[legacy][swift]"]') }; Object.keys(legacy).forEach(key => { if (legacy[key] === null) delete legacy[key]; }); const target = { tipo_conto: collectValue(row, 'select[name*="[tipo_conto]"]'), denominazione_banca: collectValue(row, 'input[name*="[denominazione_banca]"]'), intestazione_conto: collectValue(row, 'input[name*="[intestazione_conto]"]'), numero_conto: collectValue(row, 'input[name*="[numero_conto]"]'), iban: collectValue(row, 'input[name*="[target][iban]"]'), bic_swift: collectValue(row, 'input[name*="[bic_swift]"]'), abi: collectValue(row, 'input[name*="[abi]"]'), cab: collectValue(row, 'input[name*="[cab]"]'), cuc: collectValue(row, 'input[name*="[target][cuc]"]'), cin: collectValue(row, 'input[name*="[cin]"]'), valuta: collectValue(row, 'input[name*="[valuta]"]'), saldo_iniziale: collectValue(row, 'input[name*="[saldo_iniziale]"]'), data_saldo_iniziale: collectValue(row, 'input[name*="[data_saldo_iniziale]"]'), note: collectValue(row, 'textarea[name*="[note]"]'), stato_conto: collectValue(row, 'select[name*="[stato_conto]"]'), filiale: collectValue(row, 'input[name*="[target][filiale]"]'), indirizzo: collectValue(row, 'input[name*="[target][indirizzo]"]'), cap: collectValue(row, 'input[name*="[target][cap]"]'), citta: collectValue(row, 'input[name*="[target][citta]"]'), provincia: collectValue(row, 'input[name*="[target][provincia]"]'), telefono_ufficio: collectValue(row, 'input[name*="[target][telefono_ufficio]"]'), email: collectValue(row, 'input[name*="[target][email]"]'), pec: collectValue(row, 'input[name*="[target][pec]"]'), is_nostro_conto: row.querySelector('input[name*="[is_nostro_conto]"]')?.checked || false }; Object.keys(target).forEach(key => { const value = target[key]; if (key === 'is_nostro_conto') { if (!value) delete target[key]; return; } if (value === null || value === undefined || value === '') { delete target[key]; } }); const entry = { codice_legacy: row.getAttribute('data-mapping-cod') || null, descrizione_legacy: row.getAttribute('data-descrizione-legacy') || null, tipo_conto: target.tipo_conto || 'bancario', legacy: Object.keys(legacy).length ? legacy : null, target }; entry.iban = target.iban || legacy.iban || null; entry.swift = target.bic_swift || legacy.swift || null; entry.cuc = target.cuc || legacy.cuc || null; entry.numero_conto = target.numero_conto || null; entry.is_nostro_conto = Boolean(target.is_nostro_conto); return entry; }); const hidden = document.getElementById('banche_mapping_json'); if (hidden) hidden.value = JSON.stringify(normalized); } async function saveBancheMapping(e) { e.preventDefault(); syncBancheJson(); const form = e.target; const fd = new FormData(form); try { const res = await fetch(R('mappingSave'), { method: 'POST', headers: { 'X-CSRF-TOKEN': CSRF }, body: fd }); if (res.redirected) { window.location.href = res.url; return false; } alert(res.ok ? 'Mapping banche salvato' : 'Errore salvataggio banche'); } catch (err) { alert('Errore rete'); } return false; } // ===== Unità (singolo_anno.mdb / condomin) ===== let __legacyYears = []; let __currentUnitaYearIdx = 0; async function loadLegacyYears() { const nav = document.getElementById('unita-year-nav'); const label = document.getElementById('unita-year-label'); const badges = document.getElementById('years-badges'); if (!nav || !label) return; try { const url = R('years') + '?legacy_code=' + encodeURIComponent(LEGACY); const res = await fetch(url); if (!res.ok) throw new Error('HTTP ' + res.status); const js = await res.json(); __legacyYears = Array.isArray(js.years) ? js.years.map(y => String(y)) : []; if (__legacyYears.length) { nav.style.display = 'flex'; __currentUnitaYearIdx = __legacyYears.length - 1; label.textContent = __legacyYears[__currentUnitaYearIdx]; const l2 = document.getElementById('unita-anno-label-2'); if (l2) l2.textContent = label.textContent; // Render years badges if container exists if (badges) { badges.innerHTML = 'Anni:' + __legacyYears.map(y => '' + escapeHtml(y) + '').join(''); } // Pre-set Staging Loader base URL (without specific file) try { const btn = document.getElementById('btn-unita-loader'); if (btn && R('archiveUi')) { btn.href = R('archiveUi'); } } catch (_) { } try { await refreshUnitaPreview(); } catch (e) { } } else { // Nessun anno rilevato: mostra la nav con placeholder e prova fallback su staging (senza anno) nav.style.display = 'flex'; label.textContent = '—'; const l2 = document.getElementById('unita-anno-label-2'); if (l2) l2.textContent = '—'; if (badges) { badges.innerHTML = ''; } try { const btn = document.getElementById('btn-unita-loader'); if (btn && R('archiveUi')) { btn.href = R('archiveUi'); } } catch (_) { } try { await refreshUnitaPreview(); } catch (e) { } } } catch (e) { // In caso di errore nel recupero anni, visualizza comunque la nav e tenta preview fallback nav.style.display = 'flex'; label.textContent = '—'; const l2 = document.getElementById('unita-anno-label-2'); if (l2) l2.textContent = '—'; if (badges) { badges.innerHTML = ''; } try { const btn = document.getElementById('btn-unita-loader'); if (btn && R('archiveUi')) { btn.href = R('archiveUi'); } } catch (_) { } try { await refreshUnitaPreview(); } catch (_) { } } } function browseUnitaYear(delta) { if (!__legacyYears.length) return; __currentUnitaYearIdx = Math.min(__legacyYears.length - 1, Math.max(0, __currentUnitaYearIdx + (delta || 0))); const label = document.getElementById('unita-year-label'); if (label) label.textContent = __legacyYears[__currentUnitaYearIdx] || '—'; const l2 = document.getElementById('unita-anno-label-2'); if (l2) l2.textContent = label?.textContent || '—'; } async function syncUnitaCurrentYear() { const year = __legacyYears[__currentUnitaYearIdx]; if (!year) { alert('Nessun anno disponibile.'); return; } if (!confirm('Sincronizzare le unità per l\'anno ' + year + '? L\'operazione è idempotente.')) return; try { const payload = { legacy_code: LEGACY, steps: ['unita', 'soggetti', 'diritti'], anno: Number(year), dry_run: false }; const res = await fetch(R('importUnita'), { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': CSRF }, body: JSON.stringify(payload) }); const js = await res.json().catch(() => ({})); if (!res.ok || js.ok === false) { const failing = (js.results || []).filter(r => r && r.ok === false).map(r => r.step).join(', '); alert('Sync Unità fallita: ' + (js.error || failing || res.status)); return; } alert('Sync Unità eseguita su ' + year + ': ' + (js.results || []).map(r => r.step + ':' + (r.ok ? 'OK' : 'FAIL')).join(' | ')); } catch (e) { alert('Errore rete sync unità'); } } async function refreshUnitaPreview() { const years = __legacyYears || []; const idx = __currentUnitaYearIdx || 0; const year = years[idx]; const lbl2 = document.getElementById('unita-anno-label-2'); if (lbl2) lbl2.textContent = year || '—'; const head = document.getElementById('unita-legacy-head'); const body = document.getElementById('unita-legacy-body'); if (!LEGACY || !head || !body) { if (body) body.innerHTML = 'Dati non disponibili.'; return; } body.innerHTML = 'Caricamento…'; try { let url = R('unitaYear') + '?legacy_code=' + encodeURIComponent(LEGACY) + '&limit=50'; if (year) { url += '&anno=' + encodeURIComponent(year); } const res = await fetch(url); const js = await res.json().catch(() => ({})); if (!res.ok || js.ok === false) { head.innerHTML = '—'; body.innerHTML = 'Errore o nessun dato'; return; } renderUnitaPreview(js.headers || [], js.rows || []); } catch (e) { head.innerHTML = '—'; body.innerHTML = 'Errore rete'; } } function renderUnitaPreview(headers, rows) { const head = document.getElementById('unita-legacy-head'); const body = document.getElementById('unita-legacy-body'); if (!head || !body) { return; } const shown = (headers || []).filter(h => !/^memo$/i.test(h)).slice(0, 12); if (!shown.length) { head.innerHTML = '—'; body.innerHTML = 'Nessun dato.'; return; } head.innerHTML = shown.map(h => '' + escapeHtml(h) + '').join(''); if (!rows || !rows.length) { body.innerHTML = 'Nessuna riga.'; return; } body.innerHTML = rows.map(r => '' + shown.map(h => '' + escapeHtml(String(r[h] ?? '')) + '').join('') + '').join(''); } // ===== Import & actions ===== function handleImportConfirm(form, blocked, legacyCode) { if (blocked) { return false; } if (!legacyCode) { return confirm('Importare lo STABILE (solo anagrafica)?'); } return confirm('Importare lo STABILE (solo anagrafica) per il legacy ' + legacyCode + '?'); } function saveMapping() { return true; } function resetMapping() { document.querySelectorAll('#mapping-form select').forEach(s => s.value = ''); } async function giCreaGestione() { try { const anno = parseInt(document.getElementById('giAnno').value || (new Date()).getFullYear()); const tipo = document.getElementById('giTipo').value; const legacy = document.getElementById('giLegacy').value || ''; const mesi = {}; document.querySelectorAll('.giMese').forEach(c => { if (c.checked) { mesi[c.dataset.mese] = 'on'; } }); const url = CFG.routes.stabiliGestioneStore || '#'; if (!url || url === '#') throw new Error('Nessuno stabile selezionato'); const res = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': CSRF }, body: JSON.stringify({ anno_gestione: anno, tipo_gestione: tipo, codice_archivio_legacy: legacy, mesi }) }); if (!res.ok) throw new Error('Errore durante la creazione'); window.location.href = (CFG.routes.stabileShow || '') + '#tab-gestioni'; } catch (e) { alert(e.message || 'Errore'); } } async function applyMappingImport(legacyCode, stabileId) { if (!legacyCode || !stabileId) return; if (!confirm('Applicare il mapping (conti + gestioni) allo stabile selezionato?')) return; try { const payload = { legacy_code: legacyCode, stabile_id: stabileId }; const res = await fetch(R('applyMapping'), { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': CSRF }, body: JSON.stringify(payload) }); const js = await res.json().catch(() => ({})); if (!res.ok || !js.ok) { alert('Errore applicazione mapping: ' + (js.error || res.status)); return; } alert('Mapping applicato. Conti creati: ' + js.conti.created + ' (upd ' + js.conti.updated + '). Gestioni create: ' + js.gestioni.created + ' (upd ' + js.gestioni.updated + ').'); setTimeout(() => { if (CFG.routes.stabileShow) { window.location.href = CFG.routes.stabileShow + '#tab-gestioni'; } }, 600); } catch (e) { alert('Errore rete / runtime'); } } async function quickSaveAdminCf() { try { const url = CFG.routes.stabileAdminQuick || ''; if (!url) { alert('Stabile non selezionato'); return; } const cf = (document.getElementById('quickAdminCf')?.value || '').trim(); const res = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': CSRF }, body: JSON.stringify({ cod_fisc_amministratore: cf }) }); const js = await res.json().catch(() => ({})); if (!res.ok || js.ok === false) { alert('Errore salvataggio CF amministratore'); return; } alert('CF amministratore aggiornato'); } catch (e) { alert('Errore rete'); } } async function quickImportStabile(legacy) { if (!legacy) return; if (!confirm('Eseguire import rapido per lo stabile ' + legacy + '?')) return; try { const res = await fetch(R('quickStabile'), { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': CSRF }, body: JSON.stringify({ legacy_code: legacy }) }); const js = await res.json().catch(() => ({})); if (!res.ok || !js.ok) { alert('Errore import rapido: ' + (js.error || res.status)); return; } alert('Import rapido OK: ' + (js.created ? 'Creato' : 'Aggiornato') + ' ID ' + js.stabile_id); setTimeout(() => window.location.reload(), 600); } catch (e) { alert('Errore rete import rapido'); } } async function microImportStabile(legacy) { if (!legacy) return; if (!confirm('Eseguire MICRO import per lo stabile ' + legacy + '?')) return; try { const res = await fetch(R('microImportStabile'), { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': CSRF }, body: JSON.stringify({ legacy_code: legacy }) }); const js = await res.json().catch(() => ({})); if (!res.ok || !js.ok) { alert('Errore micro import: ' + (js.error || res.status)); return; } alert('Micro import OK: ' + (js.created ? 'Creato' : 'Aggiornato') + ' ID ' + js.stabile_id + '\nFonte: ' + (js.source || '-')); setTimeout(() => window.location.reload(), 600); } catch (e) { alert('Errore rete micro import'); } } // Expose minimal API for inline handlers in markup window.switchSegment = switchSegment; window.syncMappingSearch = syncMappingSearch; window.setMappingFilter = setMappingFilter; window.applyPreset = applyPreset; window.updatePresetMeta = updatePresetMeta; window.updateMappingPreviews = updateMappingPreviews; window.promptAddField = promptAddField; window.browseSample = function (delta) { return browseSample(delta); }; window.loadSample = function (idx) { return loadSample(idx); }; window.syncLegacyPreview = syncLegacyPreview; window.__toggleInlineCreate = function (trigger, show) { toggleInlineCreate(trigger, show !== false); }; window.handleImportConfirm = handleImportConfirm; window.saveMapping = saveMapping; window.resetMapping = resetMapping; window.populateGestioneRatesFromData = populateGestioneRatesFromData; window.browseGestioneYear = browseGestioneYear; window.loadGestioneYearData = loadGestioneYearData; window.loadLegacyCasse = loadLegacyCasse; window.renderLegacyCasse = renderLegacyCasse; window.filterLegacyCasse = filterLegacyCasse; window.addBancaMapping = addBancaMapping; window.removeBancaMappingRow = removeBancaMappingRow; window.syncBancheJson = syncBancheJson; window.saveBancheMapping = saveBancheMapping; window.loadLegacyYears = loadLegacyYears; window.browseUnitaYear = browseUnitaYear; window.syncUnitaCurrentYear = syncUnitaCurrentYear; window.refreshUnitaPreview = refreshUnitaPreview; window.giCreaGestione = giCreaGestione; window.applyMappingImport = applyMappingImport; window.quickSaveAdminCf = quickSaveAdminCf; window.quickImportStabile = quickImportStabile; window.microImportStabile = microImportStabile; window.addManualValueRow = addManualValueRow; window.syncManualValueRow = syncManualValueRow; window.removeManualValueRow = removeManualValueRow; window.escapeHtml = escapeHtml; // Init on DOM ready document.addEventListener('DOMContentLoaded', function () { // Export target fields window.__targetFields = Array.isArray(CFG.targetFields) ? CFG.targetFields : []; initializeManualValueRows(); // Presets try { const sel = document.getElementById('preset-select'); if (sel) { sel.value = CFG.savedPresetKey || (CFG.defaultPreset || 'stabili_full'); document.getElementById('preset_key').value = sel.value || ''; updatePresetMeta(); if (!CFG.savedPresetKey) applyPreset(); } } catch (e) { } // Initial sample browseSample(0); // Init filter state setMappingFilter('all'); // Init years and casse if legacy selected if (LEGACY) { loadLegacyYears(); loadLegacyCasse(); (async () => { try { const hasYears = Array.isArray(CFG.availableYears) && CFG.availableYears.length; if (!hasYears) { const res = await fetch(R('years') + '?legacy_code=' + encodeURIComponent(LEGACY)); if (res.ok) { const js = await res.json(); const yrs = Array.isArray(js.years) ? js.years : []; if (yrs.length) { __gestioniYears = yrs; __gestioniYearIndex = Math.max(0, __gestioniYears.length - 1); updateGestioneYearUI(); try { await loadGestioneYearData(); } catch (e) { } } } } else { try { await loadGestioneYearData(); } catch (e) { } } } catch (e) { } })(); } // Progress bar feedback on import submits document.querySelectorAll('.js-import-form').forEach(f => { f.addEventListener('submit', () => { const box = document.getElementById('import-progress'); if (box) box.classList.remove('d-none'); let p = 15; const bar = document.getElementById('import-progress-bar'); const timer = setInterval(() => { p = Math.min(90, p + Math.random() * 7); if (bar) bar.style.width = p + '%'; }, 400); f.querySelectorAll('button[type="submit"]').forEach(b => b.setAttribute('disabled', 'disabled')); }, { once: true }); }); // Year UI update (function () { const lbl = document.getElementById('gestione-year-label'); if (lbl) { updateGestioneYearUI(); } })(); }); // Diagnostic: capture JS errors to help debug window.addEventListener('error', function (ev) { try { const boxId = 'gescon-mapping-diagnostics'; let box = document.getElementById(boxId); if (!box) { box = document.createElement('div'); box.id = boxId; box.style.cssText = 'position:fixed;bottom:6px;right:6px;z-index:9999;background:#fee;border:1px solid #f99;padding:6px 10px;font:12px monospace;max-width:420px;max-height:180px;overflow:auto;'; box.innerHTML = 'JS Error
'; document.body.appendChild(box); } box.innerHTML += (ev.message + ' @' + (ev.filename || '') + ':' + ev.lineno + '
'); } catch (e) { } }); })();