En overensstemmende elektronisk faktura er ikke en PDF med en XML-fil hæftet på siden. Det er et enkelt PDF/A-3-dokument, der bærer fakturaen to gange: én gang som en side et menneske læser, og én gang som en maskinlæsbar Cross Industry Invoice-XML gemt inde i filen som en tilknyttet fil. De to repræsentationer beskriver den samme faktura. Den dobbelte natur er hele pointen med de formiliefamilier, som europæiske mandater nu kræver, Factur-X i Frankrig og Tyskland, ZUGFeRD på tværs af tysktalende markeder og XRechnung til tysk offentlig sektor-fakturering. Denne artikel gennemgår, hvordan PDFlibPas samler en sådan hybridfaktura i Delphi, hvor standarderne efterlader plads til at gøre det forkert, og hvorfor én profil i kataloget kræver en fuldstændig separat XML-bygger
Hvad en hybridfaktura rent faktisk er
Den synlige side og den indlejrede XML tjener forskellige læsere. En kontorassistent, der godkender en betaling, kigger på den gengivne side. Et kreditorsystem indtager XML'en, læser totalerne og momsfordelingen som strukturerede felter og bogfører posteringen uden et menneske taster noget. Det semantiske indhold af den XML er styret af EN 16931, den europæiske standard, der definerer fakturadatamodellen: hvilke felter der findes, hvad de betyder, og hvilke der er obligatoriske. EN 16931 er en semantisk model, ikke et filformat. Factur-X, ZUGFeRD 2.x og XRechnung realiserer alle den model som et UN/CEFACT Cross Industry Invoice-dokument, syntaksen der bærer EN 16931-felterne på tråden
For at dokumentet kan være både arkiverbart og selvbeskrivende, er containeren PDF/A-3, defineret af ISO 19005-3. PDF/A-3 er det overensstemmelsesniveau, der tillader vilkårlige indlejrede filer, hvilket er præcis, hvad en faktura-XML har brug for at være. PDF/A-2 forbyder indlejring af filer, der ikke selv er PDF/A, så en Factur-X-faktura kan ikke være PDF/A-2. Valget af PDF/A-3 er derfor ikke en præference, det er et krav, der følger direkte af at ville indlejre ikke-PDF-data i et arkivdokument
Hvorfor forholdet er Alternative
At indlejre bytene er den nemme del. ISO 32000 §7.11.4 definerer den indlejrede fil-stream, det objekt der holder den rå XML og dens parametre. Den del, der gør filen til en gyldig tilknyttet fil, er §14.13, som tilføjer konceptet om en tilknyttet fil og /AFRelationship-nøglen. Den nøgle angiver, hvordan de indlejrede data forholder sig til det indhold, de er vedhæftet, og den værdi, Factur-X dikterer, er Alternative
Valget betyder noget, fordi de andre værdier ville påstå noget falsk om dokumentet. Source ville betyde, at XML'en er det materiale, som det synlige indhold blev genereret ud fra, en master som siden afledes af. Supplement ville betyde, at XML'en tilføjer information ud over, hvad siden viser, en ekstra-ting, der ikke er indeholdt i gengivelsen. Ingen af dem er, hvad en Factur-X-faktura er. XML'en og siden er to ækvivalente udtryk for én faktura, der bærer det samme juridiske indhold i to former. Alternative er den værdi, der siger præcis det: en ækvivalent alternativ repræsentation af det synlige indhold. En validator, der læser et hvilket som helst andet forhold på en Factur-X-fil, vil afvise den, og med rette, fordi forholdet er en maskinlæsbar påstand om, hvad vedhæftningen er til for
Profilkataloget
E-Invoice-eksemplet, der leveres med PDFlibPas, kører den samme genereringssti på tværs af seks profiler, defineret som et array af records i InvoiceModel.pas. Hver profil bærer de værdier, forfatteren har brug for: et visningsnavn, det indlejrede filnavn, et overensstemmelsesniveau, /AFRelationship, en version, en valgfri landekode, og den GuidelineID-URN, som XML'en annoncerer inde i sin dokumentkontekst
De seks er Factur-X EN16931, Factur-X BASIC, Factur-X EXTENDED for Frankrig, XRechnung 3.0, ZUGFeRD 1.0 COMFORT og ZUGFeRD 2.0 BASIC. GuidelineID er feltet, der fortæller en modtager præcist hvilken profil, der skal forventes, og værdierne er specifikke. Factur-X EN16931 annoncerer urn:cen.eu:en16931:2017. XRechnung 3.0 annoncerer urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0. ZUGFeRD 2.0 BASIC annoncerer urn:cen.eu:en16931:2017#compliant#urn:zugferd.de:2p0:basic. Det indlejrede filnavn er også en del af kontrakten. Factur-X-profiler indlejrer factur-x.xml, XRechnung indlejrer xrechnung.xml, og ZUGFeRD-profilerne indlejrer ZUGFeRD-invoice.xml eller zugferd-invoice.xml. En modtager scanner vedhæftningsnavnene for at finde fakturaen, så filnavnet er ikke kosmetisk
Én detalje i kataloget er værd at læse omhyggeligt. De fleste profiler bruger Alternative-forholdet, men XRechnung 3.0-posten i eksemplet bruger Source. De to formater svarer til forskellige validatorer og konventioner, og eksemplet sætter hver profils forhold fra kataloget frem for at hard-kode en enkelt værdi, hvilket er grunden til, at det per-profil felt eksisterer frem for en konstant
ZUGFeRD 1.0-fælden
Det er fristende at antage, at enhver profil er den EN 16931 Cross Industry Invoice med mindre variationer i, hvor mange valgfrie felter man udfylder. Det gælder for fem af de seks. Det gælder ikke for ZUGFeRD 1.0 COMFORT, og årsagen er strukturel frem for kosmetisk
De moderne profiler udsender en UN/CEFACT Cross Industry Invoice med namespaceversion :100, hvis rodelement er rsm:CrossIndustryInvoice. ZUGFeRD 1.0 går forud for det skema. Det er 2014 CrossIndustryDocument med namespaceversion :1p0, og dets rodelement er rsm:CrossIndustryDocument. Namespace-URN'erne adskiller sig, rodelementet adskiller sig, og elementtræet adskiller sig hele vejen igennem: :1p0-skemaet grupperer data under ApplicableSupplyChainTradeAgreement, ApplicableSupplyChainTradeDelivery og ApplicableSupplyChainTradeSettlement, hvor :100 bruger ApplicableHeaderTradeAgreement, ApplicableHeaderTradeDelivery og ApplicableHeaderTradeSettlement. Navngivningen ligner nok til at vildlede og adskiller sig nok til at fejle
Ordet COMFORT i profilnavnet beskriver, hvor rige dataene er, en automations-grad profil med fulde linjeelementer, momsfordeling og betalingsbetingelser, ikke hvilket skema der bærer den. Så du kan ikke tage et :100-dokument og om-etikettere det til ZUGFeRD 1.0. Eksemplet håndterer dette med et flag på hver profil-record og to separate bygge-funktioner, idet den vælger den rigtige, før nogen XML genereres
Opdelingen er ikke en implementerings-finurlighed. At fodre et :100-træ til en ZUGFeRD 1.0-modtager producerer et dokument, der dumper skemavalidering ved rodelementet, så de to familier skal bygges af kode, der ved, hvilken en den skriver
Valg af PDF/A-3-niveauet
PDF/A-3 har tre overensstemmelsesniveauer, og PDFlibPas vælger dem via SetPDFAMode. Mode 5 er PDF/A-3b, det niveau, der garanterer pålidelig visuel reproduktion. Mode 6 er PDF/A-3a, som tilføjer tagged-struktur- og tilgængelighedskravene fra niveau a. Mode 7 er PDF/A-3u, som kræver, at al tekst er mappet til Unicode. Aktivering af tilstanden indlejrer også bibliotekets indbyggede sRGB-output-intent, den farvekarakterisering, PDF/A kræver, så gengivet farve er defineret frem for enhedsafhængig
De fleste fakturaflows kører på 3b, hvilket er tilstrækkeligt for en trofast synlig side plus den indlejrede XML. Hvis du har brug for en eksplicit ICC-profil frem for den indbyggede, skifter LoadOutputIntentProfile den ind, efter at tilstanden er sat. Eksemplet indlæser repository'ets sRGB-profil på denne måde og falder tilbage på det indbyggede intent, når filen ikke kan nås, så output-intentet altid er til stede
Opbygning af hybridfakturaen
Med containeren konfigureret er resten tre trin i rækkefølge: sæt PDF/A-3-tilstanden, tegn den menneskelæsbare side, og vedhæft derefter XML'en som en tilknyttet fil. Den synlige side er almindeligt indhold. Den ene begrænsning, det er værd at huske, er at PDF/A forbyder de ikke-indlejrede Standard 14-skrifttyper, så siden skal indlejre et ægte skrifttypesnit frem for at referere til et indbygget
Vedhæftningen er et enkelt kald. AddFacturXAssociatedFileFromString tager de rå UTF-8 XML-bytes plus profilmetadataene, skriver den indlejrede fil-stream, registrerer den i Catalog /AF-arrayet, som PDF/A-3 kræver, anvender /AFRelationship og genererer XMP e-faktura-metadataene, der identificerer dokumentet som Factur-X, ZUGFeRD eller XRechnung. Den tjekker også, at XML'ens guideline-ID matcher det overensstemmelsesniveau, du bad om, så et misforhold mellem den XML, du byggede, og profilen, du navngav, fanges i stedet for at blive sendt stiltiende afsted
En subtilitet i datastiden er kodningen. Den indlejrede XML deklarerer encoding="UTF-8", og metoden tager sine bytes som en AnsiString, så et ikke-ASCII sælger- eller købernavn skal nå kaldet som rå UTF-8-oktetter. En simpel cast gennem systemets ANSI-tegnsæt ville ødelægge de tegn og stiltiende producere en faktura, hvis XML ikke længere matcher sin egen deklaration. Eksemplet koder eksplicit til UTF-8, før det overdrager bytene, hvilket er den sikre måde at fodre enhver byte-orienteret PDF-API fra en Unicode-string
Til vedhæftning af XML, der ikke er en genkendt e-fakturaprofil, er AddPDFA3AssociatedFileFromString det generiske modstykke. Det tager et filnavn, MIME-type, beskrivelse, forhold og bytes, og skriver en almindelig PDF/A-3-tilknyttet fil uden nogen fakturaspecifik metadata eller guideline-tjek. Brug det til supplerende data; brug Factur-X-metoden til fakturaer, så profilmetadataene og guideline-matchet skrives for dig
Når dokumentet er produceret, er de næste spørgsmål, om det består PDF/A- og tilgængelighedsvalidering, og om det kan signeres uden at bryde overensstemmelsen. Disse er dækket i PDF/A- og PDF/UA-preflight-gennemgangen og overensstemmelses- og signerings-arbejdsbænken. Alt dette leveres som del af Delphi PDF Library til Delphi og C++Builder, ved siden af de PDF/A-, kodnings- og dokumentegenskabs-API'er, som e-fakturastien bygger på