@@ -1160,6 +1161,109 @@
}
}
+ // ── Import fornitori (CSV / incolla) → upsert per external_ref ──
+ function openImportModal() {
+ const ex = document.getElementById('importModalDyn');
+ if (ex) ex.remove();
+ const ov = document.createElement('div');
+ ov.id = 'importModalDyn';
+ ov.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,.5);display:flex;align-items:center;justify-content:center;z-index:1000;padding:16px;';
+ ov.innerHTML = `
+
+
+
Importa fornitori
+
+
+
+
+ Incolla un CSV o caricane uno. Prima riga = intestazioni. Colonne: name (obbligatoria),
+ vat_number, contact_email, contact_name,
+ service_type, criticality (low/medium/high/critical),
+ category_slug, external_ref. I record con stesso external_ref vengono aggiornati.
+
+
+
+
+
+
+
+
+
+
`;
+ document.body.appendChild(ov);
+ document.getElementById('importFile').addEventListener('change', (e) => {
+ const f = e.target.files[0];
+ if (!f) return;
+ const r = new FileReader();
+ r.onload = () => { document.getElementById('importCsv').value = r.result; };
+ r.readAsText(f);
+ });
+ }
+
+ function parseCsv(text) {
+ const rows = [];
+ const lines = text.replace(/\r\n/g, '\n').replace(/\r/g, '\n').split('\n').filter(l => l.trim() !== '');
+ if (lines.length < 2) return [];
+ const split = (line) => {
+ const out = []; let cur = ''; let inQ = false;
+ for (let i = 0; i < line.length; i++) {
+ const c = line[i];
+ if (inQ) {
+ if (c === '"' && line[i + 1] === '"') { cur += '"'; i++; }
+ else if (c === '"') inQ = false;
+ else cur += c;
+ } else {
+ if (c === '"') inQ = true;
+ else if (c === ',' || c === ';') { out.push(cur); cur = ''; }
+ else cur += c;
+ }
+ }
+ out.push(cur);
+ return out.map(s => s.trim());
+ };
+ const headers = split(lines[0]).map(h => h.toLowerCase());
+ for (let i = 1; i < lines.length; i++) {
+ const cells = split(lines[i]);
+ const obj = {};
+ headers.forEach((h, idx) => { if (h) obj[h] = cells[idx] ?? ''; });
+ if ((obj.name || '').trim() !== '') rows.push(obj);
+ }
+ return rows;
+ }
+
+ async function runSupplierImport() {
+ const txt = document.getElementById('importCsv').value || '';
+ const resEl = document.getElementById('importResult');
+ const btn = document.getElementById('importRunBtn');
+ const rows = parseCsv(txt);
+ if (rows.length === 0) {
+ resEl.innerHTML = 'Nessuna riga valida (serve intestazione + almeno un fornitore con "name").';
+ return;
+ }
+ if (rows.length > 1000) {
+ resEl.innerHTML = 'Troppi record (max 1000).';
+ return;
+ }
+ btn.disabled = true; btn.innerHTML = ' Importo...';
+ try {
+ const res = await api.importSuppliers(rows);
+ if (res.success) {
+ const d = res.data || {};
+ resEl.innerHTML = `Completato: creati ${d.created||0}, aggiornati ${d.updated||0}, saltati ${d.skipped||0}.`;
+ showNotification(`Import: ${d.created||0} creati, ${d.updated||0} aggiornati`, 'success');
+ loadSuppliers();
+ setTimeout(() => { const m = document.getElementById('importModalDyn'); if (m) m.remove(); }, 1800);
+ } else {
+ resEl.innerHTML = `${res.message || 'Errore import'}`;
+ }
+ } catch (e) {
+ resEl.innerHTML = `Errore: ${(e && e.message) || e}`;
+ } finally {
+ btn.disabled = false; btn.innerHTML = ' Importa';
+ }
+ }
+
// ── Init ────────────────────────────────────────────────
loadSuppliers();