HotPDF generează, detectează și validează facturi electronice ZUGFeRD și Factur-X din Delphi și C++Builder. AddFacturXAssociatedFile încorporează fișierul XML al facturii EN 16931 într-un container PDF/A-3, DetectFacturXInvoice recunoaște o factură hibridă de intrare, iar HPDFValidateEInvoice rulează regulile de afaceri oficiale Schematron EN 16931 pe baza XML-ului încorporat. Acest articol parcurge toți cei trei pași și expune clar limitele motorului de validare
Presiunea din spatele acestui set de caracteristici este de natură reglementară, nu tehnică. Germania și Franța introduc treptat facturarea electronică structurată obligatorie pentru tranzacțiile interne B2B, iar ambele mandate converg pe același model hibrid: factura PDF pe care ERP-ul dvs. o produce deja trebuie să conțină o copie XML lizibilă de către computer în interiorul ei. O aplicație de contabilitate sau ERP dezvoltată în Delphi care emite facturi simple PDF astăzi are un termen limită strict pentru a începe să emită Factur-X sau ZUGFeRD, iar diferența dintre cele două denumiri este mai mică decât sugerează marketingul — Factur-X și ZUGFeRD reprezintă același standard franco-german publicat sub două denumiri
Ce face ca un PDF să fie o factură Factur-X validă?
O factură Factur-X validă este un fișier PDF/A-3 (ISO 19005-3) care încorporează exact un fișier XML de factură structurat ca fișier asociat, îl înregistrează din catalogul de documente și îl declară în metadatele de extensie XMP. Trei straturi trebuie să fie în concordanță. În primul rând, containerul trebuie să fie conform cu PDF/A-3, profilul de arhivare care — spre deosebire de PDF/A-1 și PDF/A-2 — permite fișiere încorporate de orice tip. În al doilea rând, XML-ul facturii, numit factur-x.xml pentru profilele standard sau xrechnung.xml pentru varianta germană XRechnung, trebuie înregistrat în tabloul catalogului /AF și în arborele /Names /EmbeddedFiles, cu o intrare AFRelationship care precizează ce reprezintă atașamentul: Alternative înseamnă că XML-ul este o reprezentare echivalentă a facturii vizibile, care este semantica cerută de majoritatea profilelor. În al doilea rând, schema de extensie XMP Factur-X trebuie să numească fișierul încorporat, nivelul său de conformitate și tipul de document, astfel încât sistemul receptor să poată clasifica factura fără a analiza deloc fișierul XML
Sarcina utilă XML în sine urmează modelul semantic EN 16931, Norma Europeană care definește factura de bază: cumpărătorul, vânzătorul, articolele din factură, defalcarea taxelor, suma de plată, fiecare având un număr de termen de afaceri (BT-1 pentru numărul facturii, BT-5 pentru monedă și așa mai departe). Validarea EN 16931 are loc pe două straturi distincte. Validarea schemei XML verifică dacă documentul este un CII corect format cu numele corect al elementelor. Regulile de afaceri Schematron verifică dacă conținutul este coerent — că BR-CO-15 se respectă și totalul facturii este egal cu suma valorilor nete ale liniilor plus TVA, iar termenii obligatorii sunt prezenți pentru profilul declarat. Un fișier poate trece de validarea schemei și totuși să fie o factură nevalidă, motiv pentru care există stratul regulilor de afaceri
De ce ZUGFeRD 2.5 nu are nevoie de un container nou
ZUGFeRD 2.5 nu modifică nimic la nivelul containerului PDF: URN-urile directoare, schema XMP și tokenul de versiune sunt identice cu ZUGFeRD 2.3 / Factur-X 1.0. Acest lucru îi surprinde pe majoritatea implementatorilor, așa că merită citată sursa. Specificația Factur-X 1.09 precizează că numărul versiunii din URI-ul schemei de extensie PDF/A nu are legătură cu numărul versiunii specificației de date XML și că versiunea instanțelor de factură Factur-X rămâne 1.0 — atât în XMP fx:Version, cât și în BT-24 din factur-x.xml. Corpusul oficial de mostre ZUGFeRD 2.5 confirmă acest lucru: fiecare mostră încorporează factur-x.xml sub un URN director urn:factur-x.eu:1p0 cu fx:Version fiind 1.0. Ceea ce adaugă efectiv versiunea 2.5 se află în interiorul modelului de date XML — elemente noi precum linii de sub-factură și identificatori de lot — adică stratul de afaceri pe care îl generează aplicația dvs., nu stratul de container pe care îl gestionează biblioteca PDF
HotPDF codifică această constatare în mod direct. AddFacturXAssociatedFile acceptă un argument Version și îl normalizează prin HPDFFacturXNormalizeVersion înainte de a scrie XMP, astfel încât un apelant care transmite aliasul 2p5 emite în continuare tokenul conform cu specificația în loc să inventeze o versiune XMP 2p5 pe care niciun validator nu ar accepta-o. Ajutoarele de detecție tratează 2p5 ca echivalent la citire, astfel încât fluxul bidirecțional rămâne simetric. Dacă o bibliotecă sau un instrument vă spune că scrie un container special ZUGFeRD 2.5, specificația în sine precizează că nu există așa ceva
Încorporarea fișierului XML al facturii din Delphi
THotPDF.AddFacturXAssociatedFile transformă o generare obișnuită PDF/A-3 într-o factură Factur-X cu un singur apel: încorporează octeții XML ca fișier asociat, înregistrează factur-x.xml în tabloul catalogului /AF și în arborele /Names /EmbeddedFiles și emite metadatele potrivite de extensie XMP Factur-X. Desenați pagina facturii lizibilă pentru oameni cu API-ul de canvas HotPDF; configurarea containerului este o singură linie de cod între BeginDoc și EndDoc
var
Pdf: THotPDF;
InvoiceXML, UBLXML: TBytes;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.FileName := 'invoice-2026-0042.pdf';
Pdf.PDFACompliance := '3B'; // PDF/A-3b container
Pdf.BeginDoc;
// încorporează XML-ul facturii CII conform cu EN 16931 ca factur-x.xml
InvoiceXML := BuildInvoiceXML; // generat de stratul dvs. de afaceri
Pdf.AddFacturXAssociatedFile(InvoiceXML, 'EN 16931');
// opțional: atașați o vizualizare UBL ca reprezentare suplimentară
UBLXML := BuildUBLXML;
Pdf.AddUBLSupplementaryFile(UBLXML); // factur-xubl.xml, Alternative
// ... desenați pagina vizibilă a facturii aici ...
Pdf.EndDoc;
finally
Pdf.Free;
end;
end;
Valorile implicite urmează specificația: numele fișierului factur-x.xml, relația Alternative, versiunea 1.0. AddUBLSupplementaryFile implementează secțiunea 6.4 a specificației Factur-X 1.09, care permite ca o reprezentare UBL a aceleiași facturi să fie adăugată ca al doilea atașament numit factur-xubl.xml cu tipul MIME application/xml și relația Alternative. Ordinea contează aici, iar HotPDF impune constrângerea pe care o implică specificația: fișierul UBL este o vizualizare suplimentară, niciodată factura principală, prin urmare trebuie adăugat după ce AddFacturXAssociatedFile a înregistrat documentul master CII. Rețineți că pagina desenată și XML-ul încorporat trebuie să declare aceeași factură — un PDF care afișează un total și codifică un altul este exact modul de eroare pe care facturarea hibridă este concepută să îl prevină. Partea de PDF/A-3 a acestui flux de lucru, inclusiv OutputIntent și încorporarea fonturilor, este acoperită în detaliu în articolul însoțitor despre validarea PDF/A, PDF/X și PDF/UA în Delphi
Cum se detectează o factură Factur-X într-un PDF primit?
THotPDF.DetectFacturXInvoice răspunde părții de primire a mandatului: încărcați orice PDF și aflați dintr-un singur apel dacă este o factură hibridă, ce profil declară și ce atașamente conține. Funcția returnează o înregistrare THPDFFacturXInvoiceInfo cu numele fișierului XML încorporat, numele și tipul fișierului de document declarat în XMP, tokenul de versiune, nivelul de conformitate, URN-ul ghid și valoarea AFRelationship. Încă două câmpuri raportează vizualizările suplimentare: UBLFileName este completat când este prezent atașamentul factur-xubl.xml, iar EDIFACTFileName când este prezentă o vizualizare EDIFACT — niciuna dintre acestea nu afectează rezultatul detecției, deoarece o reprezentare suplimentară nu poate exista fără factura CII principală
var
Reader: THotPDF;
Info: THPDFFacturXInvoiceInfo;
begin
Reader := THotPDF.Create(nil);
try
if Reader.LoadFromFile('incoming-invoice.pdf') <= 0 then
raise Exception.Create('No pages loaded.');
if Reader.DetectFacturXInvoice(Info) then
begin
Writeln('XML factură: ', string(Info.FileName));
Writeln('Conformitate: ', string(Info.ConformanceLevel));
Writeln('URN ghid: ', string(Info.GuidelineID));
Writeln('Relație: ', string(Info.AFRelationship));
if Info.UBLFileName <> '' then
Writeln('Vizualizare UBL: ', string(Info.UBLFileName));
end
else
Writeln('Nu este o factură hibridă Factur-X / ZUGFeRD.');
finally
Reader.Free;
end;
end;
Detecția citește aceleși semnale pe care le citește un validator conform — schema de extensie XMP și registrul de fișiere asociate — în loc să ghicească doar pe baza numelor de fișiere. Același obiect document încărcat expune, de asemenea, metadatele XMP și dicționarul Info pentru inspecție sau corectare, un flux de lucru descris în articolul despre editarea metadatelor în documente PDF încărcate
Reguli de afaceri sau schemă: ce înseamnă validarea EN 16931?
HPDFValidateEInvoice, o funcție autonomă din unitatea HPDFEInvoiceValidator, rulează ambele straturi de validare în secvență: mai întâi verificarea structurii containerului prin ValidateFacturXInvoice, apoi regulile de afaceri Schematron EN 16931 pe baza XML-ului de factură extras. HotPDF livrează cele cinci fișiere oficiale de reguli Factur-X 1.09 — MINIMUM, BASIC WL, BASIC, EN 16931 și EXTENDED — sub folderul Lib/resources/Schematron/, iar HPDFSchematronFileForProfile alege fișierul potrivit cu nivelul de conformitate detectat, astfel încât o factură EN 16931 este verificată automat în raport cu Factur-X_1.09_EN16931.sch. Funcția returnează True numai când containerul este valid și nicio regulă de afaceri nu a eșuat
uses HPDFEInvoiceValidator;
var
Reader: THotPDF;
Report: THPDFEInvoiceValidationReport;
I: Integer;
begin
Reader := THotPDF.Create(nil);
try
Reader.LoadFromFile('incoming-invoice.pdf');
if HPDFValidateEInvoice(Reader, SchematronDir, Report) then
Writeln('Container și reguli de afaceri: OK')
else
Writeln('Validarea a găsit probleme.');
if Report.BusinessRulesEvaluated then
begin
Writeln(Report.BusinessSummary.Evaluated, ' reguli evaluate, ',
Report.BusinessSummary.Skipped, ' omiși (XPath 2.0)');
for I := 0 to High(Report.BusinessRules) do
if (not Report.BusinessRules[I].Skipped) and
(Report.BusinessRules[I].Severity = stsError) then
Writeln(string(Report.BusinessRules[I].RuleID), ': ',
string(Report.BusinessRules[I].Message));
end;
finally
Reader.Free;
end;
end;
Fiecare intrare în BusinessRules conține identificatorul regulii extras din textul aserțiunii — BR-45, BR-CO-17 și restul schemei de denumire EN 16931 — plus calea XPath a contextului regulii, expresia de test și o severitate care oglindește atributul Schematron flag. Acest lucru face ca raportul să fie utilizabil: în loc de un simplu succes/eșec, obțineți termenul exact de afaceri care este inconsistent, adică ceea ce are nevoie echipa dvs. de asistență atunci când un client întreabă de ce o factură a fost respinsă. Echipele care generează deja rapoarte de conformitate structurate pentru fișiere PDF de arhivare pot integra aceste rezultate în aceeași conductă descrisă în articolul despre automatizarea rapoartelor preflight PDF
Unde se oprește motorul de validare, în mod onest
Motorul Schematron este construit pe MSXML, care evaluează XPath 1.0. Fișierul de reguli EN 16931 declară queryBinding="xslt2" și conține 424 de aserțiuni, dintre care majoritatea utilizează numai funcții XPath 1.0 precum string-length și substring-after — acestea rulează nativ. O minoritate se bazează pe structuri XPath 2.0, cum ar fi conversiile xs:decimal sau exists(); HotPDF pre-scanează fiecare expresie de test pentru tokeni XPath 2.0 cunoscuți și marchează acele reguli ca Skipped cu nivel de severitate info, în loc să încerce o evaluare care ar da greș în mod silențios. Înregistrarea de rezumat raportează separat numărul de reguli evaluate și cel de reguli omise, astfel încât jurnalul dvs. declară întotdeauna cu exactitate cât de mult din setul de reguli a fost testat. Pe Delphi 7, unde legăturile MSXML nu sunt disponibile, unitatea compilează un ciot (stub) care raportează motorul ca fiind indisponibil, fără a perturba decizia privind containerul; motorul complet de validare necesită Delphi XE2 sau o versiune mai nouă
A doua limitare contează și mai mult. Un rezultat pe verde de la HPDFValidateEInvoice înseamnă că structura containerului este conformă și nicio regulă de afaceri evaluată nu a eșuat — nu este un aviz de conformitate fiscală. Regulile naționale de extindere, cerințele specifice destinatarului și obligațiile legale referitoare la conținutul facturii se află deasupra nucleului EN 16931 și în afara oricărei biblioteci. Tratați validatorul ca pe o barieră care ține facturile defecte din punct de vedere structural în afara casetei de trimitere (outbox) și semnalează facturile inconsistente în cea de primire (inbox), rulați un validator complet XPath 2.0 în fluxul de producție când practicarea o cere și lăsați consilierii fiscali să își asume responsabilitatea pentru conformitate. API-urile de încorporare, detecție și validare prezentate aici fac parte din versiunea standard a HotPDF Component pentru Delphi și C++Builder, cu un exemplu complet de factură electronică ce acoperă toate cele șapte profiluri ZUGFeRD și Factur-X