Teknik Makale

E-Faturaları Doğrulama: Delphi'de veraPDF ve Mustang

Bir Factur-X veya ZUGFeRD faturası, tek bir dosya adı giyen iki belgedir. Dış belge, bir arşiv okuyucusunun önümüzdeki on yıl boyunca kabul etmek zorunda olduğu PDF/A-3 bir kapsayıcıdır. İç belge, alıcının muhasebe sisteminin EN 16931'e göre ayrıştırmak zorunda olduğu XML bir faturadır. Bozuk faturaları üretime gönderen hata, ilkini doğru yapmanın ikincisini bedavaya getirdiğine inanmaktır. Getirmez. Bir dosya kusursuz bir PDF/A-3 olabilir ve yine de hiçbir vergi dairesinin kabul etmeyeceği XML taşıyabilir; arşiv doğrulamasında başarısız olan bir kapsayıcının içinde de ders kitabı niteliğinde EN 16931 XML'i taşıyabilir. İki katmanı, birbirinden habersiz iki farklı araç doğrular ve gerçek bir boru hattı her ikisini de tatmin etmek zorundadır

İki doğrulayıcı, iki farklı soru

veraPDF, PDF/A için referans uygulamadır. Bunu bir faturaya yöneltin, tek bir soruyu yanıtlar: bu, uyumlu bir PDF/A-3 dosyası mı. ISO 19005-3'ün önemsediği şeyleri kontrol eder. Her yazı tipi gömülü mü. Bir OutputIntent var mı. XMP meta verileri doğru bölümü ve uygunluk düzeyini beyan ediyor mu. Bir e-fatura için ayrıca PDF/A-3'ün gerektirdiği ilişkili-dosya tesisatını da denetler; çünkü XML, bir /AFRelationship ve belge kataloğunun /AF dizisinde bir girdi ile gömülü dosya olarak yol alır. veraPDF, fatura toplamının tutup tutmadığı hakkında hiçbir şey söylemez; çünkü bu onun yetki alanında değildir

Mustang, Mustangproject'in açık kaynak doğrulayıcısıdır. Ortogonal soruyu sorar: gömülü XML geçerli bir fatura mı. XML'i beyan edilen profilin şemasına karşı çalıştırır; ardından üzerine katmanlanmış EN 16931 iş kurallarını ve ülkeye özgü kural kümelerini — XRechnung'un CIUS'u da aralarında — uygular. Toplamlar bir satıcı KDV tanımlayıcısı gerektirdiğinde bunun mevcut olup olmadığına, indirim ve masraf tutarlarının belge toplamıyla uzlaşıp uzlaşmadığına, XML'deki profil URN'sinin dosyanın iddia ettiği şeyle eşleşip eşleşmediğine bakar. Mustang, çevresindeki PDF'in yazı tiplerini gömüp gömmediğiyle ilgilenmez; çünkü o iş veraPDF'indir

Hiçbir araç diğerinin üst kümesi değildir. veraPDF, saçma XML'in etrafındaki yapısal olarak mükemmel bir kapsayıcıyı geçirir. Mustang, OutputIntent'i eksik bir kapsayıcıya sarılmış mükemmel XML'i geçirir. Her biri, tam olarak diğerinin kör olduğu hata sınıfını yakalar; ciddi bir doğrulama düzeneğinin ikisini birden çalıştırmasının ve bir dosyayı yalnızca ikisi de aynı fikirdeyken gönderilebilir saymasının tüm nedeni budur

PDF Library for Delphi: Bir Factur-X e-fatura dosyasının katmanlı şeması: /AFRelationship ve /AF altyapısına sahip dış PDF/A-3 arşiv kapsayıcısı veraPDF tarafından, içerideki factur-x.xml EN 16931 fatura XML'i Mustang tarafından incelenir ve hiçbir araç diğer katmanı kapsamaz
Dış PDF/A-3 katmanı veraPDF'ye hesap verir; Mustang ise gömülü EN 16931 XML'ini yargılar ve iki kontrolün hiçbiri diğerini ima etmez

Doğrulama matrisi kurmak

Üretilen dosyaların her iki kapıdan da sağ çıktığını kanıtlamak için bir matris kurun. Altı fatura profili, bir Avrupa boru hattının pratikte karşılaştığı aralığı kapsar: Factur-X EN 16931, Factur-X BASIC, Factur-X EXTENDED France B2B varyantı, XRechnung 3.0, ZUGFeRD 1.0 COMFORT ve ZUGFeRD 2.0 BASIC. Her profil iki PDF/A alt uygunluk seviyesine, 3b ve 3u'ya karşı üretilir; çünkü B ve U seviyesi gereksinimleri Unicode eşlemesinde ayrışır ve birini geçen bir dosya diğerinde başarısız olabilir. Altı profil çarpı iki seviye on iki dosya eder ve bunların her biri, uygulamanızın kullandığı aynı kod yolu tarafından headless üretilmelidir; böylece test altındaki eserler test için elle ayarlanmamış olur

Her dosyayı iki doğrulayıcıya da verin ve kırılım görünür hâle gelir. Her yerde doğru olan kapsayıcı tesisatı — kayıtlı ilişkili dosyalar, beyan edilmiş XMP uygunluğu, yerinde output intent'ler — her dosyada veraPDF'den geçer; oysa yapısal olarak geçerli bir PDF/A-3, iş kuralı doğrulayıcısının reddettiği XML'i hâlâ taşıyabilir. İki araçlı yaklaşımın var olma nedeni tam olarak bu kırılımı yüzeye çıkarmaktır: yalnızca veraPDF'ye güvenen bir düzenek o dosyaları bitmiş sayardı

PDF Library for Delphi: Doğrulama matrisi özeti: Factur-X EN 16931'den ZUGFeRD 2.0 BASIC'e altı fatura profilinin 3b ve 3u düzeylerinde üretilmesi on iki dosya verir; veraPDF on ikisinden de geçerken Mustang yalnızca sekizinden geçer ve uyumluluk belirteci ile zorunlu toplama öğeleri için iki düzeltme farkı kapatır
İki uygunluk düzeyinde altı profil on iki dosya verir: on ikisi de veraPDF'de yeşil, yalnızca sekizi Mustang'de yeşildir

veraPDF'i geçip Mustang'i geçemeyen iki tuzak

İkisi de bu profilleri kendiniz üretmeden önce bilmenize değer ayrıntılardır

İlki Factur-X EXTENDED France B2B profilidir. Uygunluk düzeyi olarak dahili bir etiketi, kılavuz olarak dahili bir URN'yi geçirirseniz Mustang, dosyayı önce geçersiz-uygunluk-değeri hatasıyla, ardından desteklenmeyen-profil-türü hatasıyla reddeder. Bunun nedeni, XMP fx:ConformanceLevel alanının kendi profil adlandırmanız için serbest metin bir yuva olmamasıdır. Factur-X bu alan için tam olarak beş standart değer tanımlar: MINIMUM, BASIC WL, BASIC, EN 16931 ve EXTENDED. Fransa'ya özgü bir B2B faturası, XMP meta verileri açısından hâlâ EXTENDED profilli bir belgedir. Faturanın Fransız karakteri, altıncı bir uygunluk değeri icat edilerek ifade edilmez. Ülke kodu FR ile ve XML'in içindeki, EN 16931'e uyumlu bir CIUS'u işaretleyen urn:cen.eu:en16931:2017#conformant# önekini taşıması gereken kılavuz tanımlayıcısıyla ifade edilir. Standart EXTENDED değerini, ülke kodu olarak FR ve doğru kılavuz URN'siyle geçirmek dosyayı uyumlu kılar

Kitaplık API'sinde bu, uygunluğun, ülkenin ve kılavuzun hizalandığı bir AddFacturXAssociatedFileFromString çağrısıdır. Uygunluk düzeyi argümanı standart belirteci taşır, ülke kodu argümanı FR taşır ve kılavuz URN'si geçirdiğiniz XML baytlarında yaşar

var
  FileID: Integer;
begin
  PDF.SetPDFAMode(5);            // PDF/A-3b
  PDF.NewDocument;
  // ... insan tarafından okunabilir fatura sayfasını çiz ...
  // ExtendedXML şu biçimde bir EN 16931 kılavuz URN'si taşır
  //   urn:cen.eu:en16931:2017#conformant#urn:factur-x.eu:1p0:extended
  FileID := PDF.AddFacturXAssociatedFileFromString(
    ExtendedXML,
    'EXTENDED',          // dahili bir etiket değil, standart fx:ConformanceLevel
    'factur-x.xml',
    'Factur-X EXTENDED invoice',
    'Alternative',       // /AFRelationship
    '1.0',
    'FR');               // Fransa B2B ülke koduyla işaretlenir, uyumlulukla değil
  if FileID = 0 then
    raise Exception.Create('Factur-X attachment rejected');
  PDF.SaveToFile('02_Factur-X-EXTENDED-FR_PDFA-3b.pdf');
end;

İkincisi ZUGFeRD 1.0 COMFORT profilidir ve meta verilerle hiçbir ilgisi yoktur. ZUGFeRD 1.0, :1p0 XSD'sine karşı doğrulanır; bu şema, düz yazı özetlerinin ima ettiğinden daha katı bir kardinalite anlayışı taşır. XSD, başlıktaki ödeme toplamının — ram:SpecifiedTradeSettlementMonetarySummation'ın — ram:ChargeTotalAmount ve ram:AllowanceTotalAmount öğelerinin her birini tam olarak bir kez içermesini zorunlu kılar. İkisini de bırakırsanız Mustang, öğelerin tam olarak bir kez geçmesi gerektiğini bildirir. Şema minOccurs değerinin bir olduğunu söylüyorsa bunlar isteğe bağlı değildir. Hiç masraf veya indirim yokken değer olarak 0.00 verip ikisini de, ram:LineTotalAmount'un hemen ardından XSD sırasına göre yaymak şemayı tatmin eder. Sıfır, mevcut bir öğedir; eksik öğe ise şema ihlalidir

Geçersizi geçerliye çeviren XRechnung alanları

XRechnung kendi başına bir notu hak eder; çünkü Alman CIUS'u, temel EN 16931 kümesinde olmayan iş kuralları ekler ve bu kurallar, belgeye ilk bakışta hiçbir sorun yokmuş gibi görünen biçimlerde başarısız olur. Bunlardan ikisi elektronik adreslerle ilgilidir. BT-34 satıcının elektronik adresi, BT-49 alıcının elektronik adresidir; bir Alman kamu sektörü portalının faturayı teslim etmek ve onaylamak için kullandığı yönlendirme uç noktaları. Temel EN 16931 modeli bunları isteğe bağlı sayar. XRechnung saymaz. Herhangi birini atlarsanız fatura iyi biçimlendirilmiş ve şema açısından geçerli olur — ve reddedilir

Üçüncüsü, satıcının iletişim telefon numarasının bulunmasını gerektiren BR-DE-6 kuralıdır. Veri yerine sunum gibi hissettirdiği için geliştiricinin gözden düşürdüğü türden bir alandır; yokluğu da bariz eksik bir şey yerine satıcı iletişim grubunu işaret eden bir doğrulama hatası üretir. BT-34'ü, BT-49'u ve satıcı telefon numarasını sağlamak, bir XRechnung dosyasını Mustang altında geçersizden geçerliye taşıyan şeydir ve bunların hiçbiri veraPDF'in gördüğünü değiştirmez; çünkü üçü de XML'de yaşar

Kitaplık çıktısını bir doğrulayıcıya bağlamak

Düzeneğin arkasındaki mimari nokta herhangi bir iş sistemine geneller. PDF kütüphanesi uyumlu bir kapsayıcı yazar ve XML'i gömer. EN 16931 iş kuralı otoritesi olmaya çalışmaz ve çalışmamalıdır da. Kütüphanedeki ValidateFacturXInvoice, kapsayıcı tutarlılığını denetler: katalog /AF dizisi, gömülü-dosya ad ağacı, XMP DocumentFileName, profil, kılavuz ve /AFRelationship hepsinin uyuşup uyuşmadığına bakar; ama vergi kodlarını doğrulamaz, tutarları da uzlaştırmaz. Doğru iş bölümü, iş sisteminin XML'i çıkarıp özel bir fatura doğrulayıcısına vermesidir; tıpkı düzeneğin Mustang'e verdiği gibi

Dosyayı geri okumak, gerçekte ne yazıldığını söyler. DetectFacturXInvoice bir faturanın tanınıp tanınmadığını bildirir; GetFacturXInvoiceInfo meta veri alanlarını etikete göre okur: etiket 1 gömülü dosya adı, etiket 2 XMP DocumentFileName, etiket 5 uygunluk düzeyi, etiket 6 kılavuz tanımlayıcısı, etiket 7 /AFRelationship. Geri okuduğunuz uygunluk düzeyinin dahili bir etiket değil standart belirteç olduğunu teyit etmek, EXTENDED hatasını bir dosya derlemenizden ayrılmadan yakalamanın en ucuz yoludur

PDF Library for Delphi hattı şeması: kitaplık çıktısını dış doğrulayıcılara bağlar; üreteç invoice.pdf'yi başsız yazar, veraPDF kapsayıcıyı kapıdan geçirir, ExtractFacturXXMLToString Mustang'e EN 16931 iş kurallarını besler ve sevkiyat kapısı yalnızca her iki doğrulayıcı da geçtiğinde sıfırla çıkar
İşlem hattı headless üretir, aynı artefaktı her iki doğrulayıcıya verir ve yalnızca birleşik kararları yeşil olduğunda gönderir
function ExtractAndInspect(const PdfPath: string): AnsiString;
var
  Profile, Guideline: WideString;
begin
  Result := '';
  PDF.LoadFromFile(PdfPath);
  if PDF.DetectFacturXInvoice = 1 then
  begin
    Profile   := PDF.GetFacturXInvoiceInfo(5);  // fx:ConformanceLevel
    Guideline := PDF.GetFacturXInvoiceInfo(6);  // XML kılavuz kimliği
    Writeln('Profile:   ', Profile);
    Writeln('Guideline: ', Guideline);
    // Ham XML'i özel bir EN 16931 / Mustang doğrulayıcısına ver
    Result := PDF.ExtractFacturXXMLToString;
  end;
end;

ExtractFacturXXMLToString, ham XML baytlarını bir AnsiString olarak döndürür; bir dosyaya yazmaya veya bir doğrulayıcı sürecine akıtmaya hazırdır. Test düzeneğinde hedef, komut satırı jar'ı üzerinden çağrılan Mustang'dir; veraPDF aynı geçişte aynı dosya üzerinde çalışır. Bağlantı küçüktür: EInvoiceValidation.dpr adlı konsol üreteci, örnekteki paylaşılan fatura modelini kullanarak on iki dosyayı yazar; run-validation.ps1 adlı betik, iki doğrulayıcıyı çıktı dizini üzerinde yönlendirir ve geçti/kaldı tablosu yazdırır. Kütüphaneyle üret, harici doğrulayıcılarla doğrula biçimindeki aynı iki adımlı yapı, fatura üretiminde her değişiklikte bir sürekli entegrasyon işinin çalıştırması gereken şeydir; çünkü bir dosyanın her iki katmanı da karşıladığını bilmenin tek yolu iki araca da sormaktır

Boru hattınız imzalamadan önce kapsayıcıyı sertifikalandırmak zorundaysa, bu işin preflight tarafı Delphi'de PDF/A ve PDF/UA preflight anlatımızda ele alınır; daha geniş sertifikala-sonra-imzala akışı uyumluluk ve imzalama çalışma masasında anlatılır. Her ikisi de, Delphi ve C++Builder için Delphi PDF Library'nin parçası olarak gelen aynı üretim yoluna ve burada kullanılan PDF/A, ilişkili-dosya ve meta veri API'lerine dayanır