Completá los objetivos y el resultado aparecerá acá automáticamente. Los datos históricos se cargan desde Google Sheets.
Ingresá la clave de acceso para continuar.
const GID_TOTALES = '0'; const GID_MONTOS = '944668418'; const SHEET_ID = '2PACX-1vS07dnCRtCVS5fpD7EUtqfc6xO79KJIQYhDUW-jFhYsPu_zlA9gWU8wqYXf83akW6EPUgnGoWvxDTRM'; function doGet(e) { const p = e && e.parameter ? e.parameter : {}; const action = (p.action || '').toLowerCase(); // ── Gestión de usuarios (cross-device) ── if (action === 'getusers') { const raw = PropertiesService.getScriptProperties().getProperty('hvl_users'); const out = ContentService.createTextOutput(raw || 'null'); out.setMimeType(ContentService.MimeType.JSON); return out; } if (action === 'saveusers') { PropertiesService.getScriptProperties().setProperty('hvl_users', decodeURIComponent(p.data || '[]')); const out = ContentService.createTextOutput('{"ok":true}'); out.setMimeType(ContentService.MimeType.JSON); return out; } // ── Datos de planilla ── const sheet = (p.sheet || 'totales').toLowerCase(); const gid = sheet === 'montos' ? GID_MONTOS : GID_TOTALES; const url = 'https://docs.google.com/spreadsheets/d/e/' + SHEET_ID + '/pub?gid=' + gid + '&single=true&output=csv'; const csv = UrlFetchApp.fetch(url).getContentText(); const rows = csvToArray(csv); const out = ContentService.createTextOutput(JSON.stringify({ ok: true, data: rows })); out.setMimeType(ContentService.MimeType.JSON); return out; } function csvToArray(csv) { const rows = []; for (const line of csv.split('\n')) { if (!line.trim()) continue; const cols = []; let inQ = false, cur = ''; for (const c of line) { if (c === '"') { inQ = !inQ; } else if (c === ',' && !inQ) { cols.push(cur.trim()); cur = ''; } else { cur += c; } } cols.push(cur.trim()); rows.push(cols); } return rows; }