Articolul este disponibil doar în limba română.
Jumătatea deterministă trebuie să fie exactă
În teza „Munca dintre sisteme” am arătat că cincizeci de ani de integrări au automatizat jumătatea deterministă a muncii dintre sisteme și s-au oprit exact unde începe judecata. În România, o mare parte din această jumătate trece prin ANAF: facturile trimise și primite prin SPV, codurile UIT pentru transporturi. Aici nu există interpretare. Un XML e valid sau nu, un mesaj e preluat sau nu, un cod UIT e încă valabil sau a expirat.
De aceea regula noastră este simplă: partea deterministă trebuie să fie exactă înainte să punem AI pe ceva. Dacă o factură se pierde între ERP și SPV, nicio judecată, umană sau automată, nu o mai recuperează la timp.
Harta: cine vorbește cu cine
- ERP-ul trimite facturile emise în SPV și urmărește starea fiecăreia.
- SPV-ul ține facturile primite de la furnizori și mesajele de eroare; ERP-ul le preia.
- ERP-ul generează codurile UIT în RO e-Transport pentru mărfurile cu risc fiscal.
- Banca trimite extrasele; ERP-ul le potrivește cu facturile.
- Contabilitatea primește totul printr-un export.
Fiecare săgeată de mai sus are propriile moduri de a eșua. Restul articolului este despre ele.
Autentificarea: un token care expiră exact când nu te aștepți
Accesul la serviciile ANAF se face prin OAuth2, cu certificatul digital al unei persoane care are drepturi în SPV pentru firma respectivă. Aplicația se înregistrează în portalul ANAF, primește un client ID și o adresă de callback, iar autorizarea trece prin logincert.anaf.ro/anaf-oauth2/v1/authorize și .../v1/token, cu token_content_type=jwt.
Documentația ANAF spune clar cât trăiesc token-urile: token-ul de acces este emis pe 90 de zile (129.600 de minute), iar cel de refresh pe 365 de zile. Pe internet circulă și alte cifre; ne luăm după documentul oficial.
- Păstrăm token-urile criptat, separat pentru fiecare firmă.
- Reînnoim token-ul de acces înainte să expire, nu după prima eroare.
- Anunțăm firma cu câteva săptămâni înainte să expire token-ul de refresh, pentru că reautorizarea cere prezența persoanei cu certificatul.
- Ținem separat mediul de test al ANAF (
api.anaf.ro/test/...) de producție.
O greșeală frecventă: expirarea tratată ca o eroare oarecare. Când token-ul a expirat, nimic nu mai pleacă, iar termenul legal de transmitere curge.
Trimiterea: „încărcat” nu înseamnă „trimis”
Factura pleacă printr-un POST la upload?standard=UBL&cif=...; pentru facturile către persoane fizice există un serviciu separat, uploadb2c. Răspunsul nu confirmă că factura a fost primită; confirmă doar că a fost încărcată și îi dă un index de încărcare. Starea reală o afli ulterior, cu stareMesaj?id_incarcare=...: „în prelucrare”, „ok” sau „nok”.
Înainte de trimitere, trecem XML-ul prin serviciul de validare al ANAF, validare/FACT1. O factură care cade la validare nu lasă în SPV un mesaj de eroare pe care cineva trebuie apoi să-l explice.
- Factura intră într-o coadă de trimitere, cu o stare proprie: de trimis, încărcată, în prelucrare, acceptată, respinsă.
- Fiecare încărcare se leagă de factură prin indexul primit. O factură aflată „în prelucrare” nu se mai încarcă a doua oară, așa că în SPV nu apar dubluri.
- Erorile de rețea și cele temporare ale serverului se reîncearcă automat, cu pauze tot mai mari. Erorile de validare nu se reîncearcă: merg la un om, cu textul erorii tradus în limbaj obișnuit.
- După o respingere, factura se corectează și se retrimite. O factură acceptată nu se mai modifică; se corectează prin documentele prevăzute de lege.
Stările, pe scurt:
| Stare | Ce înseamnă | Ce face sistemul |
|---|---|---|
| de trimis | factura e emisă, încă nevalidată | o trece prin validare/FACT1 |
| încărcată | a primit index de încărcare | întreabă programat stareMesaj |
| în prelucrare | ANAF încă o procesează | nu o retrimite, întreabă din nou mai târziu |
| acceptată | starea „ok” | păstrează confirmarea lângă factură |
| respinsă | starea „nok” | trimite eroarea unui om, în limbaj obișnuit |
Recepția: 60 de zile de memorie
Facturile primite, erorile și mesajele se citesc cu listaMesajeFactura?zile=...&cif=..., cu filtre pentru erori, facturi trimise, facturi primite și mesaje. Parametrul zile acoperă cel mult ultimele 60 de zile; pentru intervale exacte există varianta cu paginare, listaMesajePaginatieFactura, care primește începutul și sfârșitul intervalului. Fiecare mesaj se descarcă apoi cu descarcare?id=..., ca arhivă cu XML-ul facturii și semnătura ANAF.
Fereastra de 60 de zile are o consecință practică: un sistem care nu a citit mesajele mai mult de 60 de zile nu le mai găsește în listă.
- Citim mesajele programat și alertăm dacă o citire nu a reușit.
- Eliminăm dublurile după identificatorul mesajului.
- Păstrăm arhiva descărcată exact cum a venit, pentru că documentul semnat este cel care contează.
- Transformăm XML-ul în factură de furnizor în ERP: furnizorul se găsește după CUI, liniile după codul produsului, iar tot ce nu se potrivește ajunge într-o listă de verificat, nu într-o factură greșită.
ANAF oferă și transformarea XML-ului în PDF, transformare/FACT1, utilă pentru oamenii care vor să vadă factura, nu fișierul.
Fiecare mesaj din listă are, printre altele, data creării, CIF-ul, identificatorul solicitării (id_solicitare), tipul, detaliile și identificatorul cu care se descarcă. Logica cititorului, în schiță:
pentru fiecare firmă:
token = token_valid(firma) # reînnoit înainte să expire
mesaje = listaMesajeFactura(zile, cif=firma.cif)
pentru fiecare mesaj necunoscut (după id):
arhiva = descarcare(mesaj.id)
pastreaza(arhiva) # originalul semnat, neschimbat
dacă mesaj.tip este factură primită:
ciorna = factura_furnizor_din(arhiva)
potriveste(ciorna) # furnizor după CUI, linii după cod
dacă citirea a eșuat:
alerta(firma)
e-Transport: un cod cu termen de valabilitate
Pentru mărfurile cu risc fiscal, transportul are nevoie de un cod UIT, generat prin serviciile RO e-Transport, cu aceeași schemă: încărcare, stare, listă, descărcare. Codul este valabil 5 zile calendaristice pentru transporturile naționale și 15 zile calendaristice pentru achizițiile intracomunitare și se poate genera cu cel mult 3 zile înainte de data declarată a transportului.
În ERP-ul de transport pe care îl dezvoltăm și îl întreținem, codul UIT se generează din comandă, cu datele deja introduse, iar sistemul avertizează înainte să expire. Nimeni nu mai completează același transport de două ori.
Termene și amenzi, pe scurt
Din 1 ianuarie 2026, factura se transmite în SPV în 5 zile lucrătoare de la emitere, atât între firme, cât și către persoane fizice. Nerespectarea termenului se amendează diferențiat: între 5.000 și 10.000 de lei pentru contribuabilii mari, între 2.500 și 5.000 de lei pentru cei mijlocii și între 1.000 și 2.500 de lei pentru ceilalți.
Reconcilierea de dimineață
Toate cele de mai sus se reduc la un singur raport, trimis dimineața:
- facturi emise care nu au încă index de încărcare;
- facturi încărcate care nu au ajuns la o stare finală;
- facturi respinse, cu motivul;
- facturi primite care nu au intrat în ERP;
- coduri UIT care expiră azi sau mâine.
Dacă raportul e gol, ziua începe liniștit. Dacă nu e, știi ce ai de făcut, înainte să curgă termenele.
Unde intră AI-ul, și unde nu
Nu în partea deterministă. Token-urile, XML-ul, stările și termenele au răspunsuri exacte, iar un model de limbaj n-are ce căuta acolo.
AI-ul intră unde e nevoie de judecată: facturile care nu vin ca UBL, de exemplu PDF-uri de la furnizori străini, și documentele de transport scanate, pe care le citim și le transformăm în date; potrivirea liniilor unui furnizor cu produsele din ERP când codurile diferă; explicarea unei erori de validare în limbaj obișnuit. Și atunci, după bucla din teză: AI-ul propune, regulile verifică, un om aprobă ce contează.
Ce să întrebi la orice integrare cu ANAF
- Cine reînnoiește token-urile și cine află înainte să expire?
- Ce se întâmplă cu o factură „în prelucrare” dacă sistemul cade?
- Poate aceeași factură să ajungă de două ori în SPV?
- Unde se păstrează XML-ul semnat al facturilor primite?
- Primești zilnic lista cu ce s-a respins și ce nu a intrat în ERP?
- Există un mediu de test separat de producție?
- Cine corectează o factură respinsă și în cât timp afli?
Dacă la vreuna nu primești un răspuns clar, acolo se vor pierde facturi.
Vrei asta în firma ta?
La auditul digital gratuit ne uităm cum lucrează firma ta acum și îți spunem ce se poate automatiza, cu sau fără AI, și cât costă.