/* ===== RadiusOntParser.js (Vue 3 + TT-Core) ===== */ const RadiusOntParser = { name: 'RadiusOntParser', template: `
Schritt 1 · Excel (XLSX) Upload
Laden Sie eine XLSX-Datei mit Ihren Kundendaten.
Schritt 2 · Spaltenzuordnung
Schritt 3 · Ergebnisse
{{ processedData.length }} Zeilen verarbeitet
`, data: () => ({ step: 1, headers: [], parsedData: [], processedData: [], selectedColumns: { kundennummer: 'crmPartner', anschlussstrasse: 'AnlStrasse', anschlussplz: 'AnlPlz', anschlusscity: 'AnlOrt' }, requiredFields: [ { key: 'kundennummer', label: 'Kundennummer' }, { key: 'anschlussstrasse', label: 'Anschlussstraße' }, { key: 'anschlussplz', label: 'Anschluss PLZ' }, { key: 'anschlusscity', label: 'Anschluss City' } ], loading: false, progress: 0, currentRow: 0, totalRows: 0, currentCustomerNumber: '' }), methods: { async readXlsx(file) { await window.TT_CORE.loadScript('https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.17.0/xlsx.full.min.js'); const fr = new FileReader(); fr.onload = (e) => { const wb = XLSX.read(new Uint8Array(e.target.result), { type: 'array' }); this.parsedData = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]); this.headers = Object.keys(this.parsedData[0] || {}); this.step = 2; }; fr.readAsArrayBuffer(file); }, async startProcessing() { this.step = 3; this.loading = true; this.totalRows = this.parsedData.length; this.processedData = []; this.currentRow = 0; const p = []; const b = window.TT_CONFIG.BASE_PATH; loop: for (let i = 0; i < this.parsedData.length; i++) { this.currentRow = i; this.progress = ((i + 1) / this.totalRows) * 100; const row = { ...this.parsedData[i] }; this.currentCustomerNumber = row[this.selectedColumns.kundennummer] || ''; try { const { data: users } = await axios.get(`${b}/Radius/proxyUnsecureHTTPRequestToRadius`, { params: { custnume: row[this.selectedColumns.kundennummer] } }); if (users.length === 0) { row.ont_sn = 'N/A - Kein Benutzer'; } else if (users.length === 1) { const { data: d } = await axios.get(`${b}/Radius/proxyUnsecureHTTPRequestToRadius`, { params: { skipAdditional: 'true', action2: 'fetchRadacct', username: users[0].username } }); row.ont_sn = d.ont_sn || 'N/A - Keine ONT SN'; } else { const [s, pl, c] = [row[this.selectedColumns.anschlussstrasse], row[this.selectedColumns.anschlussplz], row[this.selectedColumns.anschlusscity]]; for (let u of users) { if (window.TT_CORE.validateData(s, pl, c, u.info || users[0].info || '')) { const { data: d } = await axios.get(`${b}/Radius/proxyUnsecureHTTPRequestToRadius`, { params: { skipAdditional: 'true', action2: 'fetchRadacct', username: u.username } }); row.ont_sn = d.ont_sn || 'N/A - Keine ONT SN'; p.push(row); continue loop; } } row.ont_sn = 'N/A - Anschluss nicht zugeordnet'; } } catch { row.ont_sn = 'N/A - Fehler'; } p.push(row); if ((i + 1) % 20 === 0) await new Promise(r => setTimeout(r, 20)); } this.loading = false; this.processedData = p; }, downloadResults() { const ws = XLSX.utils.json_to_sheet(this.processedData); const wb = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(wb, ws, 'Results'); XLSX.writeFile(wb, 'results.xlsx'); }, resetLocal() { Object.assign(this.$data, this.$options.data.call(this)); } } }; // Register component with Vue 3 app if (window.VueApp) { window.VueApp.component('radius-ont-parser', RadiusOntParser); }