HotPDF generuje, deteguje a overuje elektronické faktúry ZUGFeRD a Factur-X v Delphi a C++Builder. Metóda AddFacturXAssociatedFile vkladá XML faktúry podľa normy EN 16931 do kontajnera PDF/A-3, DetectFacturXInvoice rozpoznáva prichádzajúcu hybridnú faktúru a HPDFValidateEInvoice spúšťa oficiálne obchodné pravidlá Schematron EN 16931 voči vloženému XML. Tento článok vás prevedie všetkými tromi krokmi a úprimne poukáže na limity overovacieho enginu
Tlak na túto sadu funkcií je legislatívny a nie technický. Nemecko a Francúzsko postupne zavádzajú povinnú štruktúrovanú elektronickú fakturáciu pre domáce transakcie B2B a oba mandáty sa zhodujú na rovnakom hybridnom modeli: PDF faktúra, ktorú váš ERP systém už produkuje, musí niesť vo vnútri strojovo čitateľné dvojča XML. Účtovná alebo ERP aplikácia v Delphi, ktorá dnes generuje obyčajné PDF faktúry, má pevný termín, dokedy musí začať generovať Factur-X alebo ZUGFeRD. Rozdiel medzi týmito dvoma názvami je menší, než naznačuje marketing – Factur-X a ZUGFeRD predstavujú rovnaký francúzsko-nemecký štandard publikovaný pod dvoma označeniami
Čo robí z PDF platnú faktúru Factur-X?
Platná faktúra Factur-X je súbor PDF/A-3 (ISO 19005-3), ktorý vkladá presne jedno štruktúrované XML faktúry ako pridružený súbor (associated file), odkazuje naň z katalógu dokumentu a deklaruje ho v rozširujúcich metadátach XMP. Tri vrstvy musia súhlasiť. Po prvé, kontajner musí zodpovedať PDF/A-3, archívnemu profilu, ktorý — na rozdiel od PDF/A-1 a PDF/A-2 — povoľuje vložené súbory akéhokoľvek typu. Po druhé, XML faktúry s názvom factur-x.xml pre štandardné profily alebo xrechnung.xml pre nemeckú verziu XRechnung, musí byť zaregistrované v katalógovom poli /AF a v strome /Names /EmbeddedFiles s položkou AFRelationship, ktorá uvádza, o akú prílohu ide: Alternative znamená, že XML je ekvivalentnou reprezentáciou viditeľnej faktúry, čo je sémantika vyžadovaná väčšinou profilov. Po tretie, rozširujúca schéma Factur-X XMP musí pomenovať vložený súbor, jeho úroveň zhody (conformance level) a typ dokumentu, aby prijímací systém mohol klasifikovať faktúru aj bez čítania XML
Samotný obsah XML sa riadi sémantickým modelom EN 16931, európskou normou definujúcou základnú faktúru: kupujúci, predávajúci, položky riadkov, rozpis daní, splatná suma, každý s číslom obchodného výrazu (business term number, BT-1 pre číslo faktúry, BT-5 pre menu atď.). Overenie EN 16931 sa preto uskutočňuje na dvoch odlišných vrstvách. Validácia XML schémy overuje, či je dokument správne formátovaný CII so správnymi názvami elementov. Obchodné pravidlá Schematron kontrolujú koherentnosť obsahu — napríklad či platí BR-CO-15 a celková suma faktúry sa skutočne rovná súčtu čistých súm riadkov plus DPH, či sú prítomné povinné výrazy pre deklarovaný profil. Súbor môže prejsť validáciou schémy a stále byť neplatnou faktúrou, a to je presne dôvod, prečo existuje vrstva obchodných pravidiel
Prečo ZUGFeRD 2.5 nepotrebuje nový kontajner
ZUGFeRD 2.5 nemení nič na úrovni kontajnera PDF: smerodajné URN, schéma XMP a token verzie sú totožné so ZUGFeRD 2.3 / Factur-X 1.0. To väčšinu vývojárov prekvapuje, preto stojí za to citovať zdroj. Špecifikácia Factur-X 1.09 uvádza, že číslo verzie v URI rozširujúcej schémy PDF/A nesúvisí s číslom verzie dátovej špecifikácie XML a že verzia inštancií faktúr Factur-X zostáva 1.0 — rovnako v XMP fx:Version ako aj v BT-24 súboru factur-x.xml. Oficiálny súbor vzoriek ZUGFeRD 2.5 to potvrdzuje: každá vzorka vkladá factur-x.xml pod smerodajným URN urn:factur-x.eu:1p0 s verziou fx:Version nastavenou na 1.0. To, čo verzia 2.5 v skutočnosti prináša, žije vo vnútri dátového modelu XML — nové elementy ako riadky subfaktúr a identifikátory šarží — čo je obchodná vrstva, ktorú generuje vaša aplikácia, a nie vrstva kontajnera, ktorú spravuje knižnica PDF
HotPDF kóduje toto zistenie priamo. Metóda AddFacturXAssociatedFile prijíma argument Version a pred zápisom XMP ho normalizuje pomocou HPDFFacturXNormalizeVersion, takže volajúci odovzdávajúci alias 2p5 stále vygeneruje token vyhovujúci špecifikácii, namiesto toho, aby vymyslel verziu XMP 2p5, ktorú by žiadny validátor neakceptoval. Pomocné funkcie pre detekciu považujú pri čítaní 2p5 za ekvivalentné, takže prechody tam a späť zostávajú symetrické. Ak vám nejaká knižnica alebo nástroj tvrdí, že zapisuje špeciálny kontajner ZUGFeRD 2.5, samotná špecifikácia hovorí, že nič také neexistuje
Vkladanie XML faktúry z Delphi
Metóda THotPDF.AddFacturXAssociatedFile zmení bežný zápis PDF/A-3 na faktúru Factur-X jediným volaním: vloží bajty XML ako pridružený súbor (associated file), zaregistruje factur-x.xml v katalógovom poli /AF a v strome /Names /EmbeddedFiles a vygeneruje zodpovedajúce rozširujúce metadáta Factur-X XMP. Vizuálnu časť faktúry pre čitateľa vykreslíte pomocou štandardného canvas API knižnice HotPDF; práca s kontajnerom je záležitosťou jediného riadku medzi BeginDoc a 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;
// embed the EN 16931 CII invoice XML as factur-x.xml
InvoiceXML := BuildInvoiceXML; // produced by your business layer
Pdf.AddFacturXAssociatedFile(InvoiceXML, 'EN 16931');
// optional: attach a UBL view as a supplementary representation
UBLXML := BuildUBLXML;
Pdf.AddUBLSupplementaryFile(UBLXML); // factur-xubl.xml, Alternative
// ... draw the visible invoice page here ...
Pdf.EndDoc;
finally
Pdf.Free;
end;
end;
Predvolené nastavenia zodpovedajú špecifikácii: názov súboru factur-x.xml, vzťah Alternative, verzia 1.0. Metóda AddUBLSupplementaryFile implementuje sekciu 6.4 špecifikácie Factur-X 1.09, ktorá umožňuje, aby reprezentácia tej istej faktúry v UBL formáte išla ako druhá príloha s názvom factur-xubl.xml, MIME typom application/xml a vzťahom Alternative. Na poradí tu záleží a HotPDF vynucuje obmedzenie, ktoré špecifikácia predpokladá: súbor UBL je doplnkovým zobrazením, nikdy nie hlavnou faktúrou, preto musí byť pridaný až po tom, čo AddFacturXAssociatedFile zaregistroval CII master. Upozorňujeme, že nakreslená stránka a vložené XML musia vyjadrovať rovnakú faktúru — PDF, ktoré zobrazuje jednu celkovú sumu a kóduje inú, je presne tým chybovým stavom, ktorému má hybridná fakturácia zabrániť. Strana PDF/A-3 tohto pracovného postupu, vrátane OutputIntent a vkladania písiem, je podrobnejšie popísaná v sprievodnom článku o overovaní PDF/A, PDF/X a PDF/UA v Delphi
Ako detegovať faktúru Factur-X v prichádzajúcom PDF?
Metóda THotPDF.DetectFacturXInvoice rieši prijímaciu stranu povinnosti: načítajte akékoľvek PDF a zistite jediným volaním, či ide o hybridnú faktúru, aký profil deklaruje a aké prílohy nesie. Funkcia vracia záznam THPDFFacturXInvoiceInfo s názvom vloženého súboru XML, názvom a typom dokumentu deklarovaným v XMP, tokenom verzie, úrovňou zhody (conformance level), smerodajným URN a hodnotou AFRelationship. Ďalšie dve polia hlásia doplnkové zobrazenia: UBLFileName sa vyplní, ak je prítomná príloha factur-xubl.xml, a EDIFACTFileName, ak je priložené zobrazenie EDIFACT — ani jedno neovplyvňuje verdikt detekcie, keďže doplnkové zobrazenie nemôže existovať bez primárnej CII faktúry
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('Invoice XML: ', string(Info.FileName));
Writeln('Conformance: ', string(Info.ConformanceLevel));
Writeln('Guideline URN: ', string(Info.GuidelineID));
Writeln('Relationship: ', string(Info.AFRelationship));
if Info.UBLFileName <> '' then
Writeln('UBL view: ', string(Info.UBLFileName));
end
else
Writeln('Not a Factur-X / ZUGFeRD hybrid invoice.');
finally
Reader.Free;
end;
end;
Detekcia číta rovnaké signály, aké kontroluje vyhovujúci validátor — rozširujúcu schému XMP a register pridružených súborov — namiesto toho, aby hádala len podľa názvov súborov. Rovnaký objekt načítaného dokumentu sprístupňuje na kontrolu alebo úpravu aj metadáta v XMP a Info slovníku, čo je pracovný postup popísaný v článku o úprave metadát v načítaných dokumentoch PDF
Obchodné pravidlá alebo schéma: čo znamená validácia EN 16931?
Metóda HPDFValidateEInvoice, samostatná funkcia v jednotke HPDFEInvoiceValidator, spúšťa obe vrstvy overovania za sebou: najprv kontrolu štruktúry kontajnera cez ValidateFacturXInvoice a potom obchodné pravidlá Schematron EN 16931 voči extrahovanému XML faktúry. HotPDF dodáva päť oficiálnych súborov pravidiel pre Factur-X 1.09 — MINIMUM, BASIC WL, BASIC, EN 16931 a EXTENDED — v priečinku Lib/resources/Schematron/, a funkcia HPDFSchematronFileForProfile zvolí súbor zodpovedajúci zistenej úrovni zhody, takže faktúra EN 16931 sa automaticky kontroluje voči Factur-X_1.09_EN16931.sch. Funkcia vráti True iba vtedy, ak je kontajner platný a žiadne obchodné pravidlo nebolo porušené
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 and business rules: OK')
else
Writeln('Validation found issues.');
if Report.BusinessRulesEvaluated then
begin
Writeln(Report.BusinessSummary.Evaluated, ' rules evaluated, ',
Report.BusinessSummary.Skipped, ' skipped (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;
Každá položka v BusinessRules nesie identifikátor pravidla analyzovaný z textu tvrdenia — BR-45, BR-CO-17 a zvyšok schémy pomenovania EN 16931 — plus kontext XPath pravidla, testovací výraz a závažnosť (severity) zrkadliacu atribút flag zo Schematronu. Vďaka tomu je správa prakticky použiteľná: namiesto prostého vyjadrenia vyhovel/nevyhovel dostanete presný obchodný výraz, ktorý je nekonzistentný, čo vaša technická podpora potrebuje, keď sa zákazník pýta, prečo bola faktúra odmietnutá. Tímy, ktoré už generujú štruktúrované správy o zhode pre archívne PDF, môžu tieto výsledky začleniť do rovnakého reťazca popísaného v článku o automatizácii kontrolných preflight reportov PDF
Kde validátor úprimne končí
Schematron engine je postavený na MSXML, ktorý vyhodnocuje XPath 1.0. Súbor pravidiel EN 16931 deklaruje queryBinding="xslt2" a obsahuje 424 tvrdení (assertions), z ktorých väčšina používa iba funkcie XPath 1.0, ako string-length a substring-after — tie bežia natívne. Menšina sa spolieha na konštrukcie XPath 2.0, ako napríklad pretypovanie xs:decimal alebo funkciu exists(); HotPDF vopred skenuje každý testovací výraz na známe tokeny XPath 2.0 a tieto pravidlá označí ako Skipped so závažnosťou info, namiesto pokusu o vyhodnotenie, ktoré by potichu zlyhalo. Súhrnný záznam reportuje počty vyhodnotených a preskočených pravidiel samostatne, takže váš denník (log) vždy presne uvádza, aká časť pravidiel bola spustená. Na Delphi 7, kde väzby MSXML nie sú k dispozícii, jednotka kompiluje stub (zástupnú procedúru), ktorá ohlási engine ako nedostupný bez ovplyvnenia verdiktu o kontajneri; plnohodnotný engine vyžaduje Delphi XE2 alebo novší
Druhá hranica je ešte dôležitejšia. Zelený výsledok z HPDFValidateEInvoice znamená, že štruktúra kontajnera vyhovuje a žiadne z vyhodnotených obchodných pravidiel nebolo porušené — nejde o potvrdenie daňovej zhody. Národné rozširujúce pravidlá, špecifické požiadavky príjemcov a zákonné povinnosti týkajúce sa obsahu faktúr stoja nad jadrom EN 16931 a mimo akejkoľvek knižnice. Považujte validátor za bránu, ktorá nepustí štrukturálne poškodené faktúry z vašej pošty na odoslanie a označí nekonzistentné faktúry v doručenej pošte, spustite plnohodnotný validátor XPath 2.0 vo vašom nasadzovacom reťazci (release pipeline), ak to vyžaduje certifikácia, a otázku legislatívnej zhody prenechajte svojim daňovým poradcom. API pre vkladanie, detekciu a overovanie zobrazené v tomto článku sú súčasťou štandardného komponentu losLab PDF Component pre Delphi a C++Builder, s kompletnou ukážkou elektronickej fakturácie pokrývajúcou všetkých sedem profilov ZUGFeRD a Factur-X