/** * FirmeAPI.ro pentru Google Sheets * * Formule noi in foaia ta: * =FIRMA("33741906"; "denumire") orice camp din datele firmei * =FIRMA("33741906"; "adresa_sediu_social.judet") campurile din interior, cu puncte * =BILANT("33741906"; "cifra_afaceri") ultimul an depus * =BILANT("33741906"; "profit_net"; 2023) un an anume * =FIRMEAPI("restante/33741906"; "") orice ruta din documentatie, orice camp * * Instalare: Extensii > Apps Script, lipesti acest cod, salvezi, apoi din * meniul „FirmeAPI” al foii alegi „Seteaza cheia API”. Cheia ramane in contul * tau Google (proprietatile utilizatorului), nu in foaie. * * Raspunsurile se tin minte 6 ore: aceeasi formula, recalculata, nu consuma * credite de fiecare data. */ var FIRMEAPI_ADRESA = 'https://www.firmeapi.ro/api/v1/'; var FIRMEAPI_CACHE_SECUNDE = 6 * 60 * 60; // Indicatorii din bilant, dupa denumirea lor (codurile I1…I20 difera dupa tipul formularului). var FIRMEAPI_INDICATORI = { cifra_afaceri: /cifra de afaceri/, venituri_totale: /venituri totale/, cheltuieli_totale: /cheltuieli totale/, profit_brut: /profit brut/, pierdere_bruta: /pierdere bruta/, profit_net: /profit net/, pierdere_neta: /pierdere neta/, active_imobilizate: /active imobilizate/, active_circulante: /active circulante/, stocuri: /stocuri/, creante: /creante/, casa_banci: /casa/, datorii: /datorii/, capitaluri: /capitaluri/, angajati: /salariati/, }; function onOpen() { SpreadsheetApp.getUi() .createMenu('FirmeAPI') .addItem('Setează cheia API', 'firmeapiSeteazaCheia') .addItem('Golește memoria (recitește datele)', 'firmeapiGolesteMemoria') .addToUi(); } function firmeapiSeteazaCheia() { var ui = SpreadsheetApp.getUi(); var r = ui.prompt('Cheia API FirmeAPI', 'O găsești în contul tău, la „Chei API”.', ui.ButtonSet.OK_CANCEL); if (r.getSelectedButton() === ui.Button.OK) { PropertiesService.getUserProperties().setProperty('FIRMEAPI_CHEIE', r.getResponseText().trim()); ui.alert('Gata. Formulele =FIRMA(...) și =BILANT(...) folosesc acum cheia ta.'); } } function firmeapiGolesteMemoria() { PropertiesService.getUserProperties().setProperty('FIRMEAPI_GENERATIE', String(Date.now())); SpreadsheetApp.getUi().alert('Gata. Formulele vor citi din nou datele (consumă credite).'); } /** * Un camp din datele firmei (registru, ANAF, TVA, adresa). * * @param {string} cui CUI-ul firmei, cu sau fara RO * @param {string} camp ex. denumire, stare, cod_caen, nr_reg_com, adresa, tva.platitor, adresa_sediu_social.judet * @return valoarea * @customfunction */ function FIRMA(cui, camp) { return firmeapiCampul(firmeapiCere('firma/' + firmeapiCui(cui)).data, camp || 'denumire'); } /** * Un indicator din bilantul unei firme. * * @param {string} cui CUI-ul firmei * @param {string} camp ex. cifra_afaceri, profit_net, venituri_totale, datorii, capitaluri, angajati, sau un cod (I13) * @param {number} an optional: anul bilantului; fara el, ultimul an depus * @return valoarea * @customfunction */ function BILANT(cui, camp, an) { var ani = (firmeapiCere('bilant/' + firmeapiCui(cui)).data || {}).ani || {}; var lista = Object.keys(ani).map(function (k) { return ani[k]; }).filter(function (a) { return a && a.an; }); if (!lista.length) throw new Error('Firma nu are bilanțuri depuse.'); lista.sort(function (a, b) { return b.an - a.an; }); var bilant = an ? lista.filter(function (a) { return String(a.an) === String(an); })[0] : lista[0]; if (!bilant) throw new Error('Nu există bilanț pe ' + an + '.'); var cheie = String(camp || '').trim(); if (cheie === 'an' || cheie === 'denumire' || cheie === 'caen' || cheie === 'denumire_caen') return bilant[cheie]; var tipar = FIRMEAPI_INDICATORI[cheie.toLowerCase()]; var detalii = bilant.detalii || []; for (var i = 0; i < detalii.length; i++) { var d = detalii[i]; var nume = firmeapiFaraDiacritice(d.val_den_indicator || ''); if ((tipar && tipar.test(nume)) || String(d.indicator).toUpperCase() === cheie.toUpperCase()) return d.val_indicator; } throw new Error('Indicatorul „' + camp + '” nu există în bilanțul pe ' + bilant.an + '.'); } /** * Orice ruta din API, orice camp din raspuns. * * @param {string} ruta ex. "restante/33741906" sau "caen/33741906" * @param {string} cale campul, cu puncte: ex. "caen_principal.cod"; gol = tot raspunsul, ca text * @return valoarea * @customfunction */ function FIRMEAPI(ruta, cale) { var data = firmeapiCere(String(ruta).replace(/^\/+/, '').replace(/^(api\/)?v1\//, '')).data; if (!cale) return JSON.stringify(data); return firmeapiCampul(data, cale); } /* ── Intern ─────────────────────────────────────────────────────────── */ function firmeapiCui(cui) { var c = String(cui).replace(/\D/g, ''); if (!c) throw new Error('CUI lipsă sau greșit.'); return c; } function firmeapiFaraDiacritice(s) { return String(s).toLowerCase().normalize('NFD').replace(/[̀-ͯ]/g, ''); } function firmeapiCampul(data, cale) { var v = String(cale).split('.').reduce(function (o, k) { return o == null ? null : o[k]; }, data); if (v === undefined) throw new Error('Câmpul „' + cale + '” nu există în răspuns.'); return v != null && typeof v === 'object' ? JSON.stringify(v) : v; } function firmeapiCere(ruta) { var p = PropertiesService.getUserProperties(); var cheie = p.getProperty('FIRMEAPI_CHEIE'); if (!cheie) throw new Error('Setează cheia: meniul FirmeAPI > Setează cheia API.'); var cache = CacheService.getUserCache(); var cheieCache = 'f:' + (p.getProperty('FIRMEAPI_GENERATIE') || '0') + ':' + ruta; var tinut = cache.get(cheieCache); if (tinut) return JSON.parse(tinut); var r = UrlFetchApp.fetch(FIRMEAPI_ADRESA + ruta, { headers: { 'X-API-KEY': cheie, Accept: 'application/json' }, muteHttpExceptions: true, }); var corp = r.getContentText(); var json; try { json = JSON.parse(corp); } catch (e) { throw new Error('Răspuns neașteptat (' + r.getResponseCode() + ').'); } if (r.getResponseCode() >= 400 || json.success === false) { throw new Error((json.error && (json.error.message || json.error)) || json.message || ('Eroare ' + r.getResponseCode())); } if (corp.length < 90000) cache.put(cheieCache, corp, FIRMEAPI_CACHE_SECUNDE); return json; }