Sukladan elektronički račun nije PDF s pričvršćenom XML datotekom sa strane. To je jedan jedini PDF/A-3 dokument koji nosi račun dvaput: jednom kao stranicu koju čita čovjek, i jednom kao strojno čitljiv Cross Industry Invoice XML pohranjen unutar datoteke kao pridružena datoteka. Ta dva prikaza opisuju isti račun. Ta dvojna narav je sva poanta porodica formata koje europski propisi sada zahtijevaju: Factur-X u Francuskoj i Njemačkoj, ZUGFeRD na tržištima njemačkog govornog područja, i XRechnung za njemačko javno naručivanje. Ovaj članak prolazi kroz to kako PDF Library for Delphi sastavlja takav hibridni račun u Delphiju, gdje standardi ostavljaju prostora za pogrešku, i zašto jedan profil u katalogu treba potpuno zaseban XML graditelj
Što je hibridni račun zapravo
Vidljiva stranica i ugrađeni XML služe različitim čitateljima. Referent koji odobrava plaćanje gleda iscrtanu stranicu. Sustav za obveze prema dobavljačima učitava XML, čita ukupne iznose i porezni raspored kao strukturirana polja, te knjiži stavku bez da čovjek išta upisuje. Semantički sadržaj tog XML-a uređuje EN 16931, europska norma koja definira model podataka računa: koja polja postoje, što znače, i koja su obvezna. EN 16931 je semantički model, a ne format datoteke. Factur-X, ZUGFeRD 2.x i XRechnung svi realiziraju taj model kao UN/CEFACT Cross Industry Invoice dokument, sintaksu koja nosi EN 16931 polja na žici
Da bi dokument bio i arhivabilan i samoopisujući, spremnik je PDF/A-3, definiran normom ISO 19005-3. PDF/A-3 je razina sukladnosti koja dopušta proizvoljne ugrađene datoteke, a upravo to XML računa mora biti. PDF/A-2 zabranjuje ugrađivanje datoteka koje same nisu PDF/A, pa Factur-X račun ne može biti PDF/A-2. Izbor PDF/A-3 stoga nije stvar preferencije, nego zahtjev koji izravno proizlazi iz želje da se u arhivski dokument ugrade podaci koji nisu PDF
Zašto je odnos Alternative
Ugrađivanje bajtova lakši je dio. ISO 32000 §7.11.4 definira stream ugrađene datoteke, objekt koji sadrži sirovi XML i njegove parametre. Dio koji datoteku čini valjanom pridruženom datotekom je §14.13, koji dodaje pojam pridružene datoteke i ključ /AFRelationship. Taj ključ navodi kako se ugrađeni podaci odnose prema sadržaju uz koji su pridruženi, a vrijednost koju Factur-X propisuje je Alternative
Izbor je važan jer bi druge vrijednosti tvrdile nešto neistinito o dokumentu. Source bi značilo da je XML materijal iz kojeg je generiran vidljivi sadržaj, izvornik iz kojeg stranica proizlazi. Supplement bi značilo da XML dodaje informacije izvan onoga što stranica prikazuje, dodatak koji nije sadržan u iscrtavanju. Nijedno od toga nije ono što Factur-X račun jest. XML i stranica dva su ravnopravna izraza jednog računa, koji nose isti pravni sadržaj u dva oblika. Alternative je vrijednost koja upravo to kaže: ravnopravan alternativni prikaz vidljivog sadržaja. Validator koji na Factur-X datoteci pročita bilo koji drugi odnos odbacit će je, i to opravdano, jer je taj odnos strojno čitljiva tvrdnja o tome čemu privitak služi
Katalog profila
Primjer E-Invoice koji se isporučuje s PDFlibPasom vodi isti put generiranja kroz šest profila, definiranih kao niz zapisa u InvoiceModel.pas. Svaki profil nosi vrijednosti koje pisaču trebaju: prikazni naziv, naziv ugrađene datoteke, razinu sukladnosti, /AFRelationship, verziju, neobavezan kod države, i GuidelineID URN koji XML objavljuje unutar svog konteksta dokumenta
Tih šest su Factur-X EN16931, Factur-X BASIC, Factur-X EXTENDED za Francusku, XRechnung 3.0, ZUGFeRD 1.0 COMFORT i ZUGFeRD 2.0 BASIC. GuidelineID je polje koje primatelju precizno govori koji profil očekivati, a vrijednosti su specifične. Factur-X EN16931 objavljuje urn:cen.eu:en16931:2017. XRechnung 3.0 objavljuje urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0. ZUGFeRD 2.0 BASIC objavljuje urn:cen.eu:en16931:2017#compliant#urn:zugferd.de:2p0:basic. Naziv ugrađene datoteke također je dio ugovora. Factur-X profili ugrađuju factur-x.xml, XRechnung ugrađuje xrechnung.xml, a ZUGFeRD profili ugrađuju ZUGFeRD-invoice.xml ili zugferd-invoice.xml. Primatelj pretražuje nazive privitaka kako bi pronašao račun, pa naziv datoteke nije kozmetički detalj
Jedan detalj u katalogu vrijedi pažljivo pročitati. Većina profila koristi odnos Alternative, ali unos za XRechnung 3.0 u primjeru koristi Source. Ta dva formata odgovaraju različitim validatorima i konvencijama, a primjer postavlja odnos svakog profila iz kataloga umjesto da tvrdo kodira jednu vrijednost, zbog čega polje po profilu postoji umjesto konstante
Zamka ZUGFeRD 1.0
Primamljivo je pretpostaviti da je svaki profil EN 16931 Cross Industry Invoice s manjim varijacijama u broju neobaveznih polja koja popunjavate. To vrijedi za pet od šest. Ne vrijedi za ZUGFeRD 1.0 COMFORT, a razlog je strukturne, a ne kozmetičke naravi
Moderni profili emitiraju UN/CEFACT Cross Industry Invoice s verzijom imenskog prostora :100, čiji je korijenski element rsm:CrossIndustryInvoice. ZUGFeRD 1.0 prethodi toj shemi. To je CrossIndustryDocument iz 2014. godine s verzijom imenskog prostora :1p0, a njegov korijenski element je rsm:CrossIndustryDocument. URN-ovi imenskog prostora se razlikuju, korijenski element se razlikuje, a stablo elemenata razlikuje se posvuda: shema :1p0 grupira podatke pod ApplicableSupplyChainTradeAgreement, ApplicableSupplyChainTradeDelivery i ApplicableSupplyChainTradeSettlement, dok :100 koristi ApplicableHeaderTradeAgreement, ApplicableHeaderTradeDelivery i ApplicableHeaderTradeSettlement. Imenovanje je dovoljno slično da zavede, a dovoljno različito da se slomi
Riječ COMFORT u nazivu profila opisuje koliko su podaci bogati, profil razine automatizacije s potpunim stavkama, poreznim rasporedom i uvjetima plaćanja, a ne koju shemu nosi. Zato ne možete uzeti :100 dokument i samo ga preimenovati u ZUGFeRD 1.0. Primjer to rješava zastavicom na svakom zapisu profila i dvjema odvojenim graditeljskim funkcijama, birajući ispravnu prije nego što se generira ikakav XML
function BuildInvoiceXMLText(const AProfile: TeInvoiceProfile;
const Data: TInvoiceData): string;
begin
// XMLFamily = 1 znači zastarjelu ZUGFeRD 1.0 :1p0 shemu; svaki
// drugi profil je moderni UN/CEFACT :100 Cross Industry Invoice.
if AProfile.XMLFamily = 1 then
Result := BuildZUGFeRD1Text(AProfile, Data)
else
Result := BuildCII100Text(AProfile, Data);
end;
Ta podjela nije samo implementacijska finoća. Predavanje :100 stabla ZUGFeRD 1.0 primatelju proizvodi dokument koji ne prolazi validaciju sheme već na korijenskom elementu, pa obje porodice mora graditi kod koji zna koju od njih piše
Odabir razine PDF/A-3
PDF/A-3 ima tri razine sukladnosti, a PDF Library for Delphi ih odabire kroz SetPDFAMode. Način 5 je PDF/A-3b, razina koja jamči pouzdanu vizualnu reprodukciju. Način 6 je PDF/A-3a, koji dodaje strukturu s oznakama i zahtjeve pristupačnosti razine a. Način 7 je PDF/A-3u, koji zahtijeva da se sav tekst mapira u Unicode. Uključivanje načina također ugrađuje knjižničnu ugrađenu sRGB izlaznu namjeru, karakterizaciju boje koju PDF/A zahtijeva kako bi iscrtana boja bila definirana, a ne ovisna o uređaju
Većina tokova računa radi na 3b, što je dovoljno za vjernu vidljivu stranicu uz ugrađeni XML. Ako trebate izričit ICC profil umjesto ugrađenog, LoadOutputIntentProfile ga zamjenjuje nakon što je način postavljen. Primjer na taj način učitava repozitorijski sRGB profil i vraća se na ugrađenu namjeru kada datoteka nije dostupna, pa je izlazna namjera uvijek prisutna
PDF := TPDFlib.Create;
try
// Način 5 = PDF/A-3b, 6 = PDF/A-3a, 7 = PDF/A-3u.
if PDF.SetPDFAMode(5) <> 1 then
raise Exception.Create('PDF/A-3 mode could not be enabled');
// Neobavezno: zamijeni ugrađenu sRGB namjeru izričitim ICC profilom.
if PDF.LoadOutputIntentProfile(ICCFile, 'DeviceRGB') <> 1 then
{ vrati se na ugrađenu sRGB namjeru koju je ugradio SetPDFAMode };
finally
// ... nastavi graditi dokument
end;
Izgradnja hibridnog računa
Kad je spremnik konfiguriran, ostatak su tri koraka redom: postavite način PDF/A-3, iscrtajte stranicu čitljivu čovjeku, zatim pridružite XML kao pridruženu datoteku. Vidljiva stranica je obični sadržaj. Jedino ograničenje vrijedno pamćenja je da PDF/A zabranjuje neugrađene Standard 14 fontove, pa stranica mora ugraditi pravi font umjesto da upućuje na ugrađeni
Pridruživanje je jedan poziv. AddFacturXAssociatedFileFromString uzima sirove UTF-8 XML bajtove i metapodatke profila, piše stream ugrađene datoteke, registrira ga u nizu /AF Kataloga koji PDF/A-3 zahtijeva, primjenjuje /AFRelationship, i generira XMP e-invoice metapodatke koji dokument identificiraju kao Factur-X, ZUGFeRD ili XRechnung. Također provjerava odgovara li guideline ID iz XML-a razini sukladnosti koju ste zatražili, pa se neslaganje između izgrađenog XML-a i imenovanog profila uhvati, umjesto da tiho ode dalje
// 1. Način rada PDF/A-3 i namjera izlaza već su postavljeni
// 2. Iscrtaj vidljivu stranicu (ugrađuje pravi TrueType font)
DrawInvoicePage(PDF, AProfile, Data);
// 3. Izradi XML usklađen s profilom i priloži ga kao
// povezanu datoteku s /AFRelationship = Alternative
InvoiceXML := BuildInvoiceXML(AProfile, Data); // AnsiString UTF-8 bajtova
FileID := PDF.AddFacturXAssociatedFileFromString(
InvoiceXML,
AProfile.ConformanceLevel, // e.g. 'EN16931'
AProfile.FileName, // 'factur-x.xml'
AProfile.Description,
AProfile.Relationship, // 'Alternative'
AProfile.Version, // '1.0'
AProfile.CountryCode); // '' or 'DE' or 'FR'
if FileID <= 0 then
raise Exception.Create('Invoice XML could not be attached');
PDF.SaveToFile(TargetFile);
Jedna suptilnost na putu podataka je kodiranje. Ugrađeni XML deklarira encoding="UTF-8", a metoda njegove bajtove uzima kao AnsiString, pa ne-ASCII naziv prodavatelja ili kupca do poziva mora stići kao sirovi UTF-8 oktet. Obično pretvaranje kroz sistemsku ANSI kodnu stranicu iskvarilo bi te znakove i tiho proizvelo račun čiji se XML više ne slaže s vlastitom deklaracijom. Primjer eksplicitno kodira u UTF-8 prije predaje bajtova, što je siguran način hranjenja bilo kojeg bajtno orijentiranog PDF API-ja Unicode nizom string
Za pridruživanje XML-a koji nije prepoznati profil e-računa, AddPDFA3AssociatedFileFromString je generička istoznačnica. Uzima naziv datoteke, MIME tip, opis, odnos i bajtove, te piše običnu PDF/A-3 pridruženu datoteku bez ikakvih metapodataka specifičnih za račun ili provjera smjernica. Koristite je za dodatne podatke; za račune koristite Factur-X metodu, kako bi metapodaci profila i podudaranje smjernice bili napisani umjesto vas
Kad je dokument proizveden, sljedeća pitanja su prolazi li PDF/A i validaciju pristupačnosti, te može li se potpisati bez narušavanja sukladnosti. To je obrađeno u prolasku kroz PDF/A i PDF/UA preflight i radnoj stanici za sukladnost i potpisivanje. Sve se ovo isporučuje kao dio PDF Library for Delphi Delphi PDF Library, uz PDF/A, označavanje i API-je svojstava dokumenta na kojima se temelji put e-računa