Technical Article

ZUGFeRD i Factur-X e-računi u Delphiju pomoću HotPDF-a

HotPDF generira, detektira i validira ZUGFeRD i Factur-X elektroničke račune iz Delphija i C++Builder-a. AddFacturXAssociatedFile ugrađuje XML računa EN 16931 u PDF/A-3 spremnik, DetectFacturXInvoice prepoznaje dolazni hibridni račun, a HPDFValidateEInvoice pokreće službena EN 16931 Schematron poslovna pravila nad ugrađenim XML-om. Ovaj članak prolazi kroz sva tri koraka i iskreno govori o tome gdje se mehanizam za validaciju zaustavlja

Pritisak iza ovog skupa značajki je regulatorni, a ne tehnički. Njemačka i Francuska postupno uvode obvezno strukturirano e-fakturiranje za domaće B2B transakcije, a oba se mandata podudaraju u istom hibridnom modelu: PDF račun koji vaš ERP već proizvodi mora u sebi nositi strojno čitljiv XML blizanac. Delphi računovodstvena ili ERP aplikacija koja danas izdaje obične PDF račune ima strog rok za početak izdavanja Factur-X ili ZUGFeRD računa, a razlika između ova dva naziva manja je nego što marketing sugerira — Factur-X i ZUGFeRD su isti francusko-njemački standard objavljen pod dvijema oznakama

Što PDF čini valjanim Factur-X računom?

Valjani Factur-X račun je PDF/A-3 datoteka (ISO 19005-3) koja ugrađuje točno jedan strukturirani XML računa kao pridruženu datoteku, povezuje ga iz kataloga dokumenta i deklarira u XMP metapodacima proširenja. Tri se sloja moraju usuglasiti. Prvo, spremnik mora biti u skladu s PDF/A-3, arhivskim profilom koji — za razliku od PDF/A-1 and PDF/A-2 — dopušta ugrađene datoteke bilo koje vrste. Drugo, XML računa, nazvan factur-x.xml za standardne profile ili xrechnung.xml za njemačku varijantu XRechnung, mora biti registriran u katalogu u nizu /AF i stablu /Names /EmbeddedFiles, s unosom AFRelationship koji navodi što je privitak: Alternative znači da je XML ekvivalentan prikaz vidljivog računa, što je semantika koju većina profila zahtijeva. Treće, Factur-X XMP shema proširenja mora imenovati ugrađenu datoteku, njezinu razinu sukladnosti i vrstu dokumenta, tako da primateljski sustav može klasificirati račun bez potrebe za analiziranjem samog XML-a

Zašto ZUGFeRD 2.5 ne treba novi spremnik

ZUGFeRD 2.5 ne mijenja ništa na razini PDF spremnika: URN smjernice, XMP shema i token verzije identični su onima za ZUGFeRD 2.3 / Factur-X 1.0. To iznenađuje većinu implementatora, stoga vrijedi citirati izvor. Specifikacija Factur-X 1.09 navodi da broj verzije u URI-ju PDF/A sheme proširenja nije povezan s brojem verzije XML specifikacije podataka, te da verziranje instanci Factur-X računa ostaje 1.0 — podjednako u XMP fx:Version i u BT-24 datoteke factur-x.xml. Službeni korpus uzoraka ZUGFeRD 2.5 to potvrđuje: svaki uzorak ugrađuje factur-x.xml pod URN-om smjernice urn:factur-x.eu:1p0 s fx:Version od 1.0. Ono što 2.5 zapravo dodaje živi unutar XML modela podataka — novi elementi kao što su podreci računa i identifikatori serije — što je poslovni sloj koji vaša aplikacija generira, a ne sloj spremnika kojim upravlja PDF knjižnica

HotPDF encodes this finding directly. AddFacturXAssociatedFile prihvaća argument Version i normalizira ga kroz HPDFFacturXNormalizeVersion prije pisanja XMP-a, tako da pozivatelj koji proslijedi alias 2p5 i dalje emitira sukladan token umjesto izmišljanja verzije XMP-a 2p5 koju nijedan validator ne bi prihvatio. Pomoćnici za detekciju tretiraju 2p5 kao ekvivalent pri čitanju, pa povratna putovanja ostaju simetrična. Ako vam knjižnica ili alat kaže da piše poseban spremnik za ZUGFeRD 2.5, sama specifikacija kaže da takvo što ne postoji

Ugradnja XML-a računa iz Delphija

THotPDF.AddFacturXAssociatedFile pretvara uobičajeni proces stvaranja PDF/A-3 datoteke u Factur-X račun jednim pozivom: ugrađuje bajtove XML-a kao pridruženu datoteku, registrira factur-x.xml u nizu kataloga /AF i stablu /Names /EmbeddedFiles, te emitira odgovarajuće Factur-X XMP metapodatke proširenja. Vi crtate ljudima čitljivu stranicu računa pomoću uobičajenog HotPDF API-ja za platno (canvas); rad sa spremnikom svodi se na jedan redak između 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;
    // 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;

Zadane vrijednosti prate specifikaciju: naziv datoteke factur-x.xml, odnos Alternative, verzija 1.0. AddUBLSupplementaryFile implementira odjeljak 6.4 specifikacije Factur-X 1.09, koji dopušta da UBL prikaz istog računa ide kao drugi privitak nazvan factur-xubl.xml s MIME tipom application/xml i odnosom Alternative. Redoslijed je ovdje važan, a HotPDF provodi ograničenje koje specifikacija implicira: UBL datoteka je dopunski prikaz, nikada primarni račun, pa se mora dodati nakon što je AddFacturXAssociatedFile registrirao CII glavni dokument. Imajte na umu da iscrtana stranica i ugrađeni XML moraju navoditi isti račun — PDF koji prikazuje jedan ukupni iznos, a kodira drugi, upravo je onaj način neuspjeha koji hibridno fakturiranje nastoji spriječiti. PDF/A-3 strana ovog tijeka rada, uključujući OutputIntent i ugradnju fonta, detaljnije je pokrivena u pratećem članku o PDF/A, PDF/X i PDF/UA validaciji u Delphiju

Kako otkriti Factur-X račun u dolaznom PDF-u?

THotPDF.DetectFacturXInvoice odgovara na primateljsku stranu mandata: učitajte bilo koji PDF i u jednom pozivu saznajte radi li se o hibridnom računu, koji profil deklarira i koje privitke nosi. Funkcija vraća zapis THPDFFacturXInvoiceInfo s nazivom ugrađene XML datoteke, nazivom i vrstom dokumenta deklariranom u XMP-u, tokenom verzije, razinom sukladnosti, URN-om smjernice i vrijednošću AFRelationship. Još dva polja izvještavaju o dopunskim prikazima: UBLFileName se popunjava kada je prisutan privitak factur-xubl.xml, a EDIFACTFileName kada ide i EDIFACT prikaz — niti jedno ne utječe na odluku o detekciji, jer dopunski prikaz ne može postojati bez primarnog CII računa

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;

Detekcija čita iste signale koje čita i sukladan validator — shemu XMP proširenja i registar pridruženih datoteka — umjesto da pogađa samo na temelju naziva datoteka. Isti učitani objekt dokumenta također izlaže XMP i Info rječnik metapodatke za pregled ili ispravak, što je tijek rada opisan u članku o uređivanju metapodataka u učitanim PDF dokumentima

Poslovna pravila ili shema: što znači validacija prema EN 16931?

HPDFValidateEInvoice, samostalna funkcija u jedinici HPDFEInvoiceValidator, pokreće oba sloja validacije u slijedu: najprije provjeru strukture spremnika spremnika putem ValidateFacturXInvoice, a zatim EN 16931 Schematron poslovna pravila nad izvađenim XML-om računa. HotPDF isporučuje pet službenih datoteka s pravilima za Factur-X 1.09 — MINIMUM, BASIC WL, BASIC, EN 16931 i EXTENDED — pod Lib/resources/Schematron/, a HPDFSchematronFileForProfile odabire datoteku koja odgovara detektiranoj razini sukladnosti, tako da se EN 16931 račun automatski provjerava u odnosu na Factur-X_1.09_EN16931.sch. Funkcija vraća True samo kada je spremnik valjan i kada se nijedno poslovno pravilo nije aktiviralo

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;

Svaki unos u BusinessRules nosi identifikator pravila raščlanjen iz teksta tvrdnje — BR-45, BR-CO-17 i ostatak EN 16931 sheme imenovanja — plus XPath konteksta pravila, testni izraz i ozbiljnost (severity) koja odražava atribut oznake Schematrona. To čini izvješće korisnim za poduzimanje koraka: umjesto pukog prolaza/pada dobivate točan poslovni pojam koji je nedosljedan, što je ono što vaša podrška treba kada kupac pita zašto je račun odbijen. Timovi koji već generiraju strukturirana izvješća o sukladnosti za arhivske PDF-ove mogu ugraditi ove rezultate u isti cjevovod opisan u članku o automatizaciji izvješća o provjeri PDF-a prije leta (preflight)

Gdje se validator zaustavlja, iskreno

Mehanizam Schematrona izgrađen je na MSXML-u, koji evaluira XPath 1.0. Datoteka s pravilima EN 16931 deklarira queryBinding="xslt2" i nosi 424 tvrdnje, od kojih većina koristi samo funkcije XPath 1.0 kao što su string-length i substring-after — one se izvode izvorno. Manji dio oslanja se na konstrukcije XPath 2.0 poput pretvorbi xs:decimal ili exists(); HotPDF unaprijed skenira svaki testni izraz tražeći poznate tokene XPath 2.0 i označava ta pravila kao Skipped s ozbiljnošću info, umjesto pokušaja evaluacije koja bi tiho zakazala. Zapis sažetka izvještava o evaluiranom i preskočenom broju zasebno, tako da vaš zapisnik (log) uvijek navodi točno koliki je dio skupa pravila izvršen. Na Delphiju 7, gdje MSXML povezivanja nisu dostupna, jedinica prevodi 'stub' koji javlja da je mehanizam nedostupan bez ometanja odluke o samom spremniku; puni mehanizam zahtijeva Delphi XE2 or noviji

Druga granica je još važnija. Zeleni rezultat iz HPDFValidateEInvoice znači da je struktura spremnika sukladna i da se nijedno evaluirano poslovno pravilo nije aktiviralo — to nije potvrda porezne usklađenosti. Nacionalna pravila proširenja, zahtjevi specifični za primatelja i zakonske obveze oko sadržaja računa nalaze se iznad jezgre EN 16931 i izvan bilo koje knjižnice. Tretirajte validator kao vrata koja sprječavaju slanje strukturno pokvarenih računa iz vašeg sandučića za slanje i označavaju nedosljedne račune u vašem dolaznom sandučiću, pokrenite puni XPath 2.0 validator u svom cjevovodu za izdavanje kada certifikacija to zahtijeva, a pitanje usklađenosti prepustite svojim poreznim savjetnicima. API-ji za ugradnju, detekciju i validaciju prikazani ovdje dio su standardne HotPDF komponente za Delphi i C++Builder, s cjelovitim uzorkom e-računa koji pokriva svih sedam profila ZUGFeRD-a i Factur-X-a