مقاله فنی

فاکتورهای الکترونیکی ZUGFeRD و Factur-X در دلفی با HotPDF

کامپوننت HotPDF فاکتورهای الکترونیکی ZUGFeRD و Factur-X را در دلفی و C++Builder تولید، شناسایی و اعتبارسنجی می‌کند. متد AddFacturXAssociatedFile فایل XML فاکتور EN 16931 را در یک کانتینر PDF/A-3 جاسازی می‌کند، متد DetectFacturXInvoice یک فاکتور ترکیبی ورودی را شناسایی می‌کند و HPDFValidateEInvoice قوانین تجاری رسمی EN 16931 Schematron را در برابر XML تعبیه‌شده اجرا می‌کند. این مقاله هر سه مرحله را بررسی می‌کند و صادقانه محدودیت‌های موتور اعتبارسنجی را توضیح می‌دهد

فشار پشت این مجموعه ویژگی‌ها، نظارتی است و نه فنی. آلمان و فرانسه در حال اجرای فازهای اجباری فاکتورهای الکترونیکی ساختاریافته برای تراکنش‌های داخلی B2B هستند و هر دو قانون به یک مدل ترکیبی واحد همگرا می‌شوند: فاکتور PDF که سیستم ERP شما در حال حاضر تولید می‌کند، باید حاوی یک فایل XML همزاد و ماشین‌خوان باشد. یک برنامه حسابداری یا ERP دلفی که امروزه فاکتورهای PDF ساده صادر می‌کند، ضرب‌الاجل سختی برای شروع صدور Factur-X یا ZUGFeRD دارد و تفاوت بین این دو نام کمتر از آن چیزی است که بازاریابی نشان می‌دهد — Factur-X و ZUGFeRD همان استاندارد فرانسوی-آلمانی هستند که تحت دو برچسب منتشر شده‌اند

چه چیزی یک PDF را به یک فاکتور معتبر Factur-X تبدیل می‌کند؟

یک فاکتور معتبر Factur-X یک فایل PDF/A-3 (ISO 19005-3) است که دقیقاً یک فایل XML فاکتور ساختاریافته را به عنوان فایل مرتبط تعبیه می‌کند، آن را از کاتالوگ سند لینک می‌کند و در متادیتای افزونه XMP اعلام می‌دارد. سه لایه باید با هم همخوانی داشته باشند. اول اینکه کانتینر باید با استاندارد PDF/A-3 مطابقت داشته باشد؛ پروفایل آرشیوی که — برخلاف PDF/A-1 و PDF/A-2 — اجازه می‌دهد فایل‌های تعبیه‌شده از هر نوعی وجود داشته باشند. دوم اینکه فایل XML فاکتور، با نام factur-x.xml برای پروفایل‌های استاندارد یا xrechnung.xml برای نسخه آلمانی XRechnung، باید در آرایه /AF کاتالوگ و درخت /Names /EmbeddedFiles ثبت شود، با یک ورودی AFRelationship که نوع پیوست را مشخص می‌کند: Alternative به این معنی است که XML یک نمایش معادل از فاکتور قابل مشاهده است، که این مفهوم در اکثر پروفایل‌ها لازم است. سوم اینکه طرحواره افزونه Factur-X XMP باید نام فایل تعبیه‌شده، سطح انطباق آن و نوع سند را مشخص کند تا یک سیستم دریافت‌کننده بتواند فاکتور را بدون تجزیه کل XML طبقه‌بندی کند

خود داده‌های XML از مدل معنایی EN 16931 پیروی می‌کنند، استاندارد اروپایی که فاکتور اصلی را تعریف می‌کند: خریدار، فروشنده، اقلام سطر، تفکیک مالیات، مبلغ قابل پرداخت، که هر کدام دارای شماره اصطلاح تجاری هستند (مانند BT-1 برای شماره فاکتور، BT-5 برای ارز، و غیره). بنابراین اعتبارسنجی EN 16931 در دو لایه متمایز انجام می‌شود. اعتبارسنجی طرحواره XML (schema validation) بررسی می‌کند که سند یک CII با ساختار صحیح و نام عناصر مناسب باشد. قوانین تجاری Schematron بررسی می‌کنند که محتوا منسجم باشد — به عنوان مثال قانون BR-CO-15 برقرار باشد و مجموع فاکتور واقعاً با مجموع مقادیر خالص سطرها به علاوه مالیات بر ارزش افزوده برابر باشد، و شرایط اجباری برای پروفایل اعلام‌شده وجود داشته باشد. یک فایل می‌تواند اعتبارسنجی طرحواره را پاس کند اما همچنان یک فاکتور نامعتبر باشد، به همین دلیل است که لایه قوانین تجاری وجود دارد

چرا ZUGFeRD 2.5 نیازی به کانتینر جدید ندارد

استاندارد ZUGFeRD 2.5 هیچ تغییری در سطح کانتینر PDF ایجاد نمی‌کند: URNهای راهنما، طرحواره XMP و توکن نسخه با ZUGFeRD 2.3 / Factur-X 1.0 یکسان هستند. این موضوع اکثر پیاده‌سازان را شگفت‌زده می‌کند، بنابراین ارزش دارد که به منبع استناد کنیم. مشخصات Factur-X 1.09 بیان می‌کند که شماره نسخه در URI طرحواره افزونه PDF/A به شماره نسخه مشخصات داده‌های XML مرتبط نیست و نسخه‌گذاری نمونه‌های فاکتور Factur-X همچنان 1.0 باقی می‌ماند — چه در متادیتای XMP fx:Version و چه در فیلد BT-24 از factur-x.xml. مجموعه نمونه رسمی ZUGFeRD 2.5 این موضوع را تأیید می‌کند: هر نمونه فایل factur-x.xml را در زیر URN راهنمای urn:factur-x.eu:1p0 با مقدار fx:Version برابر 1.0 تعبیه می‌کند. آنچه نسخه 2.5 در واقع اضافه می‌کند، در داخل مدل داده‌های XML زندگی می‌کند — عناصر جدید مانند سطرهای فرعی فاکتور و شناسه‌های دسته — که این لایه تجاری است که برنامه شما تولید می‌کند و نه لایه کانتینر که کتابخانه PDF مدیریت می‌کند

کامپوننت HotPDF این یافته را به طور مستقیم کدگذاری می‌کند. متد AddFacturXAssociatedFile یک آرگومان Version را می‌پذیرد و قبل از نوشتن XMP آن را از طریق HPDFFacturXNormalizeVersion نرمال‌سازی می‌کند، بنابراین فراخوان‌کننده‌ای که نام مستعار 2p5 را پاس می‌دهد، همچنان توکن سازگار با مشخصات را صادر می‌کند به جای اینکه یک نسخه XMP ساختگی با نام 2p5 اختراع کند که هیچ اعتبارسنجی آن را قبول نمی‌کند. هلپرهای شناسایی هنگام خواندن، مقدار 2p5 را به عنوان معادل در نظر می‌گیرند، بنابراین جریان رفت و برگشت متقارن باقی می‌ماند. اگر یک کتابخانه یا ابزار به شما بگوید که یک کانتینر مخصوص ZUGFeRD 2.5 می‌نویسد، خود مشخصات می‌گوید چنین چیزی وجود ندارد

جاسازی XML فاکتور از دلفی

متد THotPDF.AddFacturXAssociatedFile فرآیند تولید یک PDF/A-3 معمولی را با یک فراخوانی به یک فاکتور Factur-X تبدیل می‌کند: این متد بایت‌های XML را به عنوان یک فایل مرتبط تعبیه می‌کند، فایل factur-x.xml را در آرایه /AF کاتالوگ و درخت /Names /EmbeddedFiles ثبت می‌کند و متادیتای افزونه هماهنگ Factur-X XMP را صادر می‌کند. شما صفحه فاکتور قابل خواندن توسط انسان را با API معمولی بوم HotPDF رسم می‌کنید؛ کار کانتینر یک خط کد ساده بین BeginDoc و 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;

مقادیر پیش‌فرض از مشخصات پیروی می‌کنند: نام فایل factur-x.xml، رابطه Alternative، نسخه 1.0. متد AddUBLSupplementaryFile بخش ۶.۴ از مشخصات Factur-X 1.09 را پیاده‌سازی می‌کند، که اجازه می‌دهد یک نمایش UBL از همان فاکتور به عنوان پیوست دوم با نام factur-xubl.xml و با نوع MIME معادل application/xml و رابطه Alternative همراه باشد. ترتیب در اینجا اهمیت دارد و HotPDF محدودیتی را که مشخصات به آن اشاره دارد اعمال می‌کند: فایل UBL یک نمای کمکی است و هرگز فاکتور اصلی نیست، بنابراین باید پس از اینکه AddFacturXAssociatedFile فایل اصلی CII را ثبت کرد، اضافه شود. توجه داشته باشید که صفحه ترسیم شده و XML تعبیه شده باید اطلاعات فاکتور یکسانی را نشان دهند — یک فایل PDF که یک کل را نمایش می‌دهد و کل دیگری را کدگذاری می‌کند دقیقاً همان حالت خرابی است که فاکتوردهی ترکیبی برای جلوگیری از آن طراحی شده است. بخش PDF/A-3 این جریان کاری، از جمله OutputIntent و تعبیه فونت، با جزئیات بیشتر در مقاله همراه در مورد اعتبارسنجی PDF/A، PDF/X و PDF/UA در دلفی پوشش داده شده است

چگونه یک فاکتور Factur-X را در یک PDF ورودی شناسایی کنیم؟

متد THotPDF.DetectFacturXInvoice نیازهای بخش دریافت‌کننده را پاسخ می‌دهد: هر فایلی را بارگذاری کنید و با یک فراخوانی مطلع شوید که آیا این یک فاکتور ترکیبی است، چه پروفایلی را اعلام می‌کند و چه پیوست‌هایی را به همراه دارد. این تابع یک رکورد THPDFFacturXInvoiceInfo شامل نام فایل XML تعبیه شده، نام فایل و نوع سند اعلام شده در XMP، توکن نسخه، سطح انطباق، URN راهنما و مقدار AFRelationship را برمی‌گرداند. دو فیلد دیگر نماهای مکمل را گزارش می‌دهند: فیلد UBLFileName زمانی پر می‌شود که پیوست factur-xubl.xml وجود داشته باشد و EDIFACTFileName زمانی که نمای EDIFACT همراه باشد — هیچ‌کدام بر نتیجه شناسایی تأثیر نمی‌گذارند، زیرا یک نمایش مکمل بدون فاکتور اصلی CII نمی‌تواند وجود داشته باشد

شناسایی، همان سیگنال‌هایی را می‌خواند که یک اعتبارسنج استاندارد می‌خواند — طرحواره افزونه XMP و ثبت فایل‌های مرتبط — به جای اینکه صرفاً بر اساس نام فایل‌ها حدس بزند. همین شیء سند بارگذاری شده همچنین متادیتای دیکشنری XMP و Info را برای بازرسی یا تصحیح در دسترس قرار می‌دهد، جریانی کاری که در مقاله ویرایش متادیتا در اسناد بارگذاری شده PDF توضیح داده شده است

قوانین تجاری یا طرحواره: اعتبارسنجی EN 16931 به چه معناست؟

تابع HPDFValidateEInvoice که یک تابع مستقل در یونیت HPDFEInvoiceValidator است، هر دو لایه اعتبارسنجی را به ترتیب اجرا می‌کند: ابتدا بررسی ساختار کانتینر از طریق ValidateFacturXInvoice، سپس قوانین تجاری EN 16931 Schematron در برابر فایل XML استخراج‌شده فاکتور. HotPDF پنج فایل قانون رسمی Factur-X 1.09 را — شامل MINIMUM، BASIC WL، BASIC، EN 16931 و EXTENDED — در زیرمسیر Lib/resources/Schematron/ ارائه می‌دهد و متد HPDFSchematronFileForProfile فایل منطبق با سطح انطباق شناسایی شده را انتخاب می‌کند، بنابراین یک فاکتور EN 16931 به طور خودکار در برابر Factur-X_1.09_EN16931.sch بررسی می‌شود. این تابع تنها زمانی مقدار True را برمی‌گرداند که کانتینر معتبر باشد و هیچ قانون تجاری نقض نشده باشد

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;

هر ورودی در BusinessRules حاوی شناسه قانون تجزیه شده از متن ادعا است — مانند BR-45، BR-CO-17 و بقیه طرح نام‌گذاری EN 16931 — به علاوه ساختار زمینه قانون XPath، عبارت تست و شدت خطا که ویژگی پرچم Schematron را منعکس می‌کند. این امر گزارش را کاربردی می‌کند: به جای یک قبول/رد ساده، شما اصطلاح تجاری دقیقی را که ناسازگار است دریافت می‌کنید، که این همان چیزی است که تیم پشتیبانی شما در هنگام تماس مشتری برای رد شدن فاکتور نیاز دارد. تیم‌هایی که قبلاً گزارش‌های انطباق ساختاریافته برای فایل‌های PDF آرشیوی تولید می‌کنند، می‌توانند این نتایج را در همان جریان کاری توضیح داده شده در مقاله خودکارسازی گزارش‌های پیش‌پرواز PDF ادغام کنند

صادقانه بگویم، موتور اعتبارسنجی کجا متوقف می‌شود

موتور Schematron بر روی MSXML ساخته شده است که ساختار XPath 1.0 را ارزیابی می‌کند. فایل قانون EN 16931 بیانیه queryBinding="xslt2" را دارد و حاوی ۴۲۴ ادعا است که بیشتر آنها فقط از توابع XPath 1.0 مانند string-length و substring-after استفاده می‌کنند — که این توابع به صورت بومی اجرا می‌شوند. اقلیتی به ساختارهای XPath 2.0 مانند تبدیل‌های xs:decimal یا exists() متکی هستند؛ HotPDF قبل از اجرا، هر عبارت تست را برای توکن‌های شناخته‌شده XPath 2.0 اسکن می‌کند و آن قوانین را با شدت اطلاعات به صورت Skipped علامت‌گذاری می‌کند تا از ارزیابی که ممکن است بی سر و صدا با خطا مواجه شود، جلوگیری کند. رکورد خلاصه تعداد قوانین ارزیابی شده و نادیده گرفته شده را به طور جداگانه گزارش می‌دهد، بنابراین لاگ شما همیشه دقیقاً نشان می‌دهد چه مقدار از مجموعه قوانین اجرا شده است. در Delphi 7 که اتصال‌های MSXML در دسترس نیستند، یونیت یک کد نمونه را کامپایل می‌کند که موتور را به عنوان غیرقابل دسترس گزارش می‌دهد بدون اینکه بر حکم کانتینر تأثیر بگذارد؛ موتور کامل به Delphi XE2 یا بالاتر نیاز دارد

مرز دوم حتی بیشتر اهمیت دارد. نتیجه سبز از HPDFValidateEInvoice به این معنی است که ساختار کانتینر مطابقت دارد و هیچ قانون تجاری ارزیابی شده‌ای نقض نشده است — این تأییدیه انطباق مالیاتی نیست. قوانین توسعه ملی، شرایط خاص دریافت‌کننده و تعهدات قانونی پیرامون محتوای فاکتور بالاتر از هسته EN 16931 و خارج از هر کتابخانه‌ای قرار دارند. با اعتبارسنج به عنوان دروازه‌ای رفتار کنید که فاکتورهای دارای ساختار خراب را از پوشه خروجی شما دور نگه می‌دارد و موارد ناسازگار را در پوشه ورودی علامت‌گذاری می‌کند، زمانی که گواهی‌نامه ایجاب می‌کند یک اعتبارسنج کامل XPath 2.0 را در خط لوله انتشار خود اجرا کنید و اجازه دهید مشاوران مالیاتی شما مسئولیت مسئله انطباق را به عهده بگیرند. APIهای ثبت، شناسایی و اعتبارسنجی نشان داده شده در اینجا بخشی از کامپوننت استاندارد HotPDF Component برای دلفی و C++Builder با یک نمونه کامل فاکتور الکترونیکی هستند که تمام هفت پروفایل ZUGFeRD و Factur-X را پوشش می‌دهد