مقالة تقنية

فواتير 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 من أن المستند هو 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 وتطبعها من خلال HPDFFacturXNormalizeVersion قبل كتابة XMP, لذا فإن المستدعي الذي يمرر الاسم المستعار 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 المطابقة. وترسم صفحة الفاتورة القابلة للقراءة البشرية باستخدام واجهة برمجة تطبيقات لوحة 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 القسم 6.4 من مواصفات 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 على جانب الاستلام من الولاية: قم بتحميل أي ملف PDF واعرف باستدعاء واحد ما إذا كان فاتورة هجينة، وأي ملف تعريف تعلن عنه، وأي المرفقات تحمل. تعيد الوظيفة سجلاً من نوع THPDFFacturXInvoiceInfo مع اسم ملف XML المضمن، واسم ونوع ملف المستند المعلن عنه في XMP، ورمز الإصدار، ومستوى التوافق، ومعيار URN للتوجيه، وقيمة AFRelationship. ويبلغ حقلان آخران عن عروض تكميلية: يتم ملء UBLFileName عند وجود مرفق factur-xubl.xml، وملف EDIFACTFileName عند وجود عرض EDIFACT — ولا يؤثر أي منهما على حكم الكشف، لأن التمثيل التكميلي لا يمكن أن يوجد بدون فاتورة CII الأساسية

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;

يقرأ الكشف نفس الإشارات التي يقرأها المدقق المتوافق — نظام ملحق XMP وسجل الملفات المرتبطة — بدلاً من التخمين من أسماء الملفات وحدها. كما يكشف كائن المستند المحمل نفسه عن بيانات تعريف XMP وقاموس المعلومات للفحص أو التصحيح، وهو تدفق عمل موضح في المقالة الخاصة بتحرير بيانات التعريف في مستندات 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" ويحمل 424 تأكيداً، يستخدم معظمها وظائف 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 كامل في خط إنتاج الإصدار الخاص بك عندما يتطلب الترخيص ذلك، ودع مستشاري الضرائب لديك يمتلكون سؤال الامتثال. واجهات برمجة تطبيقات التضمين والكشف والتحقق الموضحة هنا هي جزء من مكون HotPDF القياسي لدلفي وC++Builder، مع عينة فاتورة إلكترونية كاملة تغطي جميع ملفات ZUGFeRD وFactur-X السبعة