Qoyod
الأسعار

 دليل المعرفة

أخطاء التحقق (Validation Errors)

حين يرفض نظام الفوترة الإلكترونية فاتورتك، لا يأتي الرفض دائمًا بسبب ملف XML مكسور. كثير من حالات الرفض تحدث بينما يكون ملف XML سليم البنية تمامًا، لكنه يحمل خطأً منطقيًا أو حسابيًا. هذه هي أخطاء التحقق من قواعد العمل (Business Rules Validation)، وهي طبقة مختلفة كليًا عن أخطاء البنية. هذا الدليل موجّه للمطوّرين الذين يبنون تكاملًا مع منصة فاتورة في المرحلة الثانية، ويشرح أشهر رموز قواعد العمل التي ترفض فاتورتك، رسالة كل رمز، وكيف تصلحه قبل أن يصل الطلب إلى الهيئة.

هذا الدليل جزء من دليل الفوترة الإلكترونية من قيود، ويكمّل دليل قواعد التحقق (Validation Rules) للفاتورة الذي يشرح القواعد كمواصفة كاملة. هنا نركّز على الجانب العملي: قراءة رسالة الخطأ، تحديد سببها، وإصلاحها.

آخر تحديث: 24 يونيو 2026.

أخطاء التحقق ليست أخطاء XML

قبل أن نغوص في الرموز، يجب أن يكون الفصل بين الطبقتين واضحًا في ذهنك. الخلط بينهما هو أول سبب لإضاعة الوقت في تتبّع الأخطاء.

الطبقة الأولى هي التحقق البنيوي عبر مخطط XSD. وظيفته أن يجيب على سؤال واحد: «هل بنية المستند صحيحة؟». هل العناصر موجودة؟ هل ترتيبها سليم؟ هل نوع البيانات في كل حقل مطابق؟ هذه الأخطاء تظهر برسائل المُحلّل (parser) ولا تحمل رمز قاعدة عمل. تناولناها بالتفصيل في دليل أخطاء XML المنفصل، وهو المستوى الذي تجب معالجته أولًا.

الطبقة الثانية هي التحقق المنطقي عبر قواعد العمل. تعمل بعد اجتياز المخطط، وتأخذ القيم التي مرّت من XSD وتتحقق من علاقاتها: هل المجموع صحيح؟ هل قيمة الضريبة تساوي الوعاء مضروبًا في النسبة؟ هل الحقل الذي يصبح إلزاميًا عند فئة ضريبية معيّنة موجود؟ هذه الأسئلة لا يستطيع XSD الإجابة عليها لأنها تحتاج حسابًا ومقارنة بين عدة حقول.

الخلاصة في جملة: المخطط يضمن أن الفاتورة مكتوبة بشكل صحيح، وقواعد العمل تضمن أنها صحيحة فعلًا. فاتورة سليمة البنية تمامًا قد تُرفض لأنها تحمل خطأ حسابيًا واحدًا. هذا الدليل عن النوع الثاني حصرًا.

من أين تأتي رموز قواعد العمل؟

كل رمز ترفض به الهيئة فاتورتك يأتي من أحد مصدرين. المصدر الأول هو المعيار الأوروبي EN 16931 الذي يحدد النموذج الدلالي الأساسي للفاتورة. قواعده تبدأ ببادئة BR للقواعد الأساسية، و BR-CO للترابط الحسابي، و BR-S و BR-Z و BR-E لفئات الضريبة القياسية والصفرية والمعفاة. الفاتورة السعودية تُبنى فوق هذا الأساس عبر معيار UBL 2.1.

المصدر الثاني هو القواعد الخاصة بالمملكة التي تضيفها الهيئة فوق المعيار الأوروبي، وتحمل بادئة BR-KSA. تعالج متطلبات محلية مثل صيغة الرقم الضريبي السعودي، وحقول التوقيع والختم، ورمز QR، ونوع الفاتورة. مهمة نظامك أن يطبّق المصدرين معًا داخليًا قبل الإرسال.

تدقيق المخطط مقابل قواعد العمل
طبقتان مختلفتان للتحقق، وأخطاء التحقق في الثانية.
المعيار تدقيق المخطط (XSD) قواعد العمل (BR)
النطاق بنية المستند منطق وصحة البيانات
المرجع مخطط XSD رموز BR-KSA
مثال الخطأ عنصر مفقود/ترتيب مجموع غير مطابق
أخطاء التحقق منطقية تأتي بعد اجتياز البنية.

العائلات الخمس لقواعد العمل

قواعد العمل كثيرة، لكنها تقع منطقيًا في خمس عائلات. فهم العائلة قبل القاعدة الفردية يجعل قراءة الرفض أسرع، ويساعدك على بناء محرّك تحقق منظّم بدلًا من قائمة شروط مبعثرة.

العائلة الأولى: الوجود الشرطي (Conditional Mandatory). تجعل حقلًا إلزاميًا فقط عند تحقق شرط ما. المثال الأشهر حقل سبب الإعفاء: لا يُطلب في الفاتورة العادية، لكنه يصبح واجبًا فور أن تصبح الفئة الضريبية لأحد البنود معفاة أو خارج النطاق.

العائلة الثانية: الترابط الحسابي (Calculation). أهم عائلة وأكثرها تسبّبًا في الرفض. تتحقق من أن المجاميع متّسقة عبر الفاتورة. تحمل بادئة BR-CO. سنخصّص لها قسمًا كاملًا لأنها تستحق ذلك.

العائلة الثالثة: الصيغة والنمط (Format). تتحقق من أن قيمة الحقل تتبع نمطًا محددًا، وقد تشمل منطقًا لا يعبّر عنه XSD مثل خوارزمية تحقق من رقم. المثال السعودي الكلاسيكي هو الرقم الضريبي.

العائلة الرابعة: التاريخ والتسلسل (Date and Sequence). تتحقق من منطقية التواريخ وتسلسل الفواتير. في المرحلة الثانية يدخل بُعد إضافي: ربط الفاتورة بسابقتها عبر المعرّف الفريد UUID وتجزئة الفاتورة السابقة.

العائلة الخامسة: القوائم المغلقة (Code List). تتحقق من أن قيمة الحقل تنتمي إلى قائمة معتمدة. رمز العملة من قائمة ISO 4217، ورمز نوع الفاتورة من القائمة التي تحددها الهيئة، ورمز الفئة الضريبية من المجموعة المعتمدة.

أخطاء الترابط الحسابي (BR-CO): الأكثر شيوعًا في الإنتاج

إن كنت ستركّز على عائلة واحدة، فاجعلها هذه. قواعد BR-CO ترفض أكثر الفواتير في بيئة الإنتاج السعودية، وغالبًا بسبب فرق تقريب صغير لا ينتبه إليه المطوّر.

المنطق صارم لكنه بسيط. مجموع صافي البنود يجب أن يساوي إجمالي الفاتورة قبل الضريبة. مجموع الضريبة لكل فئة يجب أن يساوي إجمالي الضريبة. الإجمالي المستحق يجب أن يساوي الإجمالي قبل الضريبة زائد الضريبة ناقص أي مدفوعات مسبقة. أي انحراف يتجاوز هامش التقريب المسموح يعني رفضًا فوريًا.

إليك أشهر رموز هذه العائلة ومعناها العملي:

  • BR-CO-10: مجموع صافي البنود يجب أن يساوي إجمالي قيمة البنود في الفاتورة.
  • BR-CO-13: الإجمالي الخاضع للضريبة يجب أن يساوي إجمالي الفاتورة بدون ضريبة.
  • BR-CO-15: الإجمالي المستحق يجب أن يساوي الإجمالي بدون ضريبة زائد إجمالي الضريبة.
  • BR-CO-17: قيمة الضريبة لكل فئة يجب أن تساوي الوعاء الخاضع للفئة مضروبًا في النسبة مقسومة على مئة.

رسالة خطأ حسابي كما تصل من المنصة

حين يرفض نظام الهيئة فاتورة لخطأ حسابي، يأتي الرد بمصفوفة أخطاء، كل خطأ يحمل رمز القاعدة المكسورة ورسالتها. هذا مثال واقعي على رفض BR-CO-15:

{
  "validationResults": {
    "status": "ERROR",
    "errorMessages": [
      {
        "type": "ERROR",
        "code": "BR-CO-15",
        "category": "BR",
        "message": "Invoice total amount with VAT (LegalMonetaryTotal/TaxInclusiveAmount) = Invoice total amount without VAT + Invoice total VAT amount"
      }
    ]
  }
}

اقرأها من الأعلى للأسفل. الحقل status يخبرك أن الفاتورة رُفضت. الحقل code هو رمز القاعدة المكسورة، وهو مفتاحك للبحث في وثيقة قواعد الهيئة. الحقل category يصنّف القاعدة. الحقل message يشرح القاعدة كمعادلة. الإصلاح هنا واضح: أعد حساب الإجمالي المستحق بحيث يساوي الوعاء زائد الضريبة بالضبط.

السبب الخفي وراء معظم أخطاء BR-CO: التقريب

أكثر خطأ نراه في هذه العائلة هو فرق التقريب. لو قرّبت كل بند على حدة ثم جمعت، قد تحصل على مجموع يختلف بهلّلة واحدة عن الناتج الذي تتوقعه الهيئة. القاعدة تسمح عادة بهامش تقريب ضئيل (غالبًا 0.01 ر.س)، لكن تجاوزه يعني رفضًا.

لنوضّح بمثال رقمي. افترض فاتورة فيها بندان: الأول 33.33 ر.س والثاني 33.34 ر.س، وكلاهما خاضع للنسبة القياسية 15%. ضريبة البند الأول 5.00 ر.س بعد التقريب، وضريبة البند الثاني 5.00 ر.س، فيكون مجموع الضريبة على مستوى البنود 10.00 ر.س. لكن لو حسبت الضريبة على الوعاء الإجمالي 66.67 ر.س مباشرة، تحصل على 10.0005 ر.س التي تُقرّب إلى 10.00 ر.س. هنا تطابقا. غيّر القيم قليلًا وستجد انحرافًا يتجاوز الهامش.

الدرس الأول: احسب الضريبة على مستوى الفئة المجمّعة لا على مستوى البند المنفرد. هذا ما تتوقعه قاعدة BR-CO-17.

الدرس الثاني يخصّ نوع البيانات في الكود. استخدام نوع عائم (float) في حساب المبالغ يُدخل أخطاء دقة خفية تتراكم عبر عشرات البنود. استخدم نوعًا عشريًا دقيقًا (decimal أو ما يكافئه في لغتك)، وحدّد عدد المنازل العشرية صراحة عند التقريب النهائي. هذا وحده يزيل نسبة كبيرة من حالات رفض BR-CO.

الدرس الثالث يخصّ الخصومات على مستوى الفاتورة. كثير من حالات رفض BR-CO-13 تأتي من خصم يُطبَّق على إجمالي الفاتورة دون توزيعه بشكل صحيح على الأوعية الضريبية لكل فئة. القاعدة تتوقع أن يكون الإجمالي الخاضع للضريبة لكل فئة متّسقًا مع البنود بعد الخصم. لو طرحت الخصم من الإجمالي النهائي فقط دون أن تعكسه في وعاء كل فئة، ينكسر الترابط ويأتي الرفض. وزّع الخصم على مستوى الفئة، ثم احسب الضريبة على الوعاء بعد الخصم لا قبله.

مثال ثانٍ على الترابط: فاتورة بفئتين، الأولى قياسية 15% بوعاء 1,000 ر.س والثانية معفاة بوعاء 200 ر.س. الإجمالي قبل الضريبة 1,200 ر.س، والضريبة 150 ر.س على الفئة القياسية فقط، والإجمالي المستحق 1,350 ر.س. لو حسبت الضريبة على الإجمالي كله بالخطأ (1,200 × 15%)، تحصل على 180 ر.س وترفضك القاعدة BR-CO-17 لأن الفئة المعفاة لا تخضع للنسبة. الضريبة تُحسب لكل فئة على حدة، لا على الإجمالي.

# خطأ شائع: float يراكم انحراف دقة
line_tax = 33.33 * 0.15        # 4.9995 -> دقة float غير موثوقة

# الصواب: decimal بدقة محددة ثم تقريب صريح
from decimal import Decimal, ROUND_HALF_UP
rate = Decimal("0.15")
base = Decimal("66.67")                       # وعاء الفئة المجمّع
tax  = (base * rate).quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)
# tax = 10.00  -> يطابق توقّع BR-CO-17

كيف يساعدك قيود

قيود يطبّق قيود قواعد العمل والترابط الحسابي محليًا قبل إرسال الفاتورة، فلا تصل فاتورتك إلى منصة فاتورة إلا وهي خالية من أخطاء BR. حساب الضريبة على مستوى الفئة، التقريب بالهامش الصحيح، والتحقق من المعادلات الثلاث للإجمالي، كلها تُطبَّق داخليًا. أنت تُصدر الفاتورة، والقواعد نتولّاها نحن. ولأن قيود معتمد رسميًا من هيئة الزكاة والضريبة والجمارك، فالتحقق المحلي مطابق لما يطبّقه نظام الهيئة فعليًا.

أخطاء صيغة الرقم الضريبي (BR-KSA-39 و BR-KSA-40)

الرقم الضريبي السعودي هو أكثر حقل يفشل في عائلة الصيغة. القاعدة لا تكتفي بأنه نص من 15 خانة، بل تشترط أن يبدأ بالرقم 3 وينتهي بالرقم 3، وأن تكون الخانات الوسطى صحيحة. كثير من المطوّرين يمرّر رقمًا من 15 خانة فيجتاز XSD، ثم يُرفض على مستوى قاعدة العمل لأنه لا يطابق النمط.

هذا مثال على رفض رقم ضريبي للبائع لا يطابق الصيغة:

{
  "validationResults": {
    "status": "ERROR",
    "errorMessages": [
      {
        "type": "ERROR",
        "code": "BR-KSA-39",
        "category": "BR-KSA",
        "message": "Seller VAT registration number must be 15 digits, start with 3 and end with 3"
      }
    ]
  }
}

الإصلاح هو التحقق من الرقم محليًا قبل بناء المستند، باستخدام النمط التالي:

# قاعدة الرقم الضريبي السعودي
# - طول ثابت: 15 خانة
# - يبدأ بـ 3 وينتهي بـ 3
import re
VAT_PATTERN = re.compile(r"^3[0-9]{13}3$")

def is_valid_vat(number: str) -> bool:
    return bool(VAT_PATTERN.match(number))

is_valid_vat("300000000000003")  # True
is_valid_vat("123456789012345")  # False -> سيُرفض بـ BR-KSA-39

القاعدة BR-KSA-40 مرتبطة بالرقم الضريبي للمشتري في حالات معيّنة. المبدأ نفسه: تحقق من النمط محليًا قبل الإرسال، ولا تعتمد على XSD لالتقاطه لأنه يرى الرقم نصًا صحيحًا بنيويًا.

انتبه أيضًا إلى أن متطلب الرقم الضريبي للمشتري يتغيّر بحسب نوع الفاتورة. في الفاتورة الضريبية الموجَّهة لمنشأة (B2B) يصبح رقم المشتري إلزاميًا في حالات الحدّ المعيّن، بينما في الفاتورة المبسّطة الموجَّهة للمستهلك (B2C) لا يُطلب. هذا تقاطع بين عائلة الصيغة وعائلة الوجود الشرطي: الحقل لا يُتحقق من نمطه فقط، بل من وجوده أصلًا حسب سياق الفاتورة. اربط هذه الشروط في طبقتك المحلية بحسب نوع المستند، لا كقاعدة ثابتة واحدة لكل الفواتير.

أخطاء الوجود الشرطي وفئات الضريبة (BR-S و BR-Z و BR-E)

هذه القواعد تربط رمز الفئة الضريبية بالحقول التي يجب أن ترافقه. الفئة القياسية S تتطلب وعاءً موجبًا ونسبة صحيحة. الفئة صفرية النسبة Z لها قواعدها. الفئة المعفاة E تتطلب نص سبب إعفاء.

أشهر رموز هذه العائلة:

  • BR-S-08: الوعاء الخاضع للفئة القياسية يجب أن يكون موجبًا. فئة S دون وعاء موجب تُرفض.
  • BR-Z-05: قاعدة خاصة بفئة النسبة الصفرية تربط النسبة بصفر.
  • BR-E-05 و BR-E-10: قواعد الفئة المعفاة، وأبرزها وجوب نص سبب الإعفاء.

المثال الأوضح هو حقل سبب الإعفاء. القاعدة تقول: إذا كان رمز الفئة الضريبية يساوي E (معفى)، فيجب وجود نص سبب الإعفاء. لو أصدرت بندًا معفى دون هذا النص، تمرّ من XSD لكن قاعدة العمل ترفضك.

{
  "validationResults": {
    "status": "ERROR",
    "errorMessages": [
      {
        "type": "ERROR",
        "code": "BR-E-10",
        "category": "BR",
        "message": "An Exempt VAT category line must have a VAT exemption reason"
      }
    ]
  }
}

الإصلاح بسيط في المنطق: اربط ظهور الحقل بقيمة الفئة. متى صارت الفئة E، فعّل إلزامية حقل سبب الإعفاء في طبقة التحقق المحلي لديك قبل بناء المستند.

أخطاء الوجود الشرطي حسب فئة الضريبة
متى يصبح حقل سبب الإعفاء إلزامياً.
القواعد الشرطية

الفئة S (خاضعة 15%): لا حاجة لسبب إعفاء

الفئة Z (صفرية): قد يلزم سبب

الفئة E (معفاة): سبب الإعفاء إلزامي (BR-E-10)

غياب السبب في E يرفض الفاتورة

كل فئة ضريبة لها قواعد حقول شرطية مختلفة.

أخطاء نوع الفاتورة والقوائم المغلقة (BR-KSA-15)

رمز نوع الفاتورة يجب أن يكون من القائمة التي تحددها الهيئة: 388 لفاتورة ضريبية، 383 لإشعار مدين، 381 لإشعار دائن. القاعدة BR-KSA-15 تتحقق من توافق رمز نوع الفاتورة مع الحقول المرفقة. لو أرسلت رمز نوع فاتورة لا يطابق المحتوى الفعلي، تُرفض هنا.

مثال: إشعار دائن (381) يجب أن يحمل مرجعًا للفاتورة الأصلية التي يعدّلها. لو أرسلته دون هذا المرجع، يكسر قاعدة الترابط بين نوع المستند وحقوله.

{
  "validationResults": {
    "status": "ERROR",
    "errorMessages": [
      {
        "type": "ERROR",
        "code": "BR-KSA-15",
        "category": "BR-KSA",
        "message": "Invoice type code is not consistent with the document content"
      }
    ]
  }
}

هناك أيضًا رمز يستحق الانتباه: BR-KSA-EN16931. يظهر حين تكسر قيمة سعودية قاعدة من المعيار الأوروبي الأصلي. أي أن القاعدة الأساسية والقاعدة المحلية تتعارضان في حالتك، وهذا يعني غالبًا أن أحد الحقول السعودية أُدخل بقيمة لا يقبلها المعيار الدلالي الأساسي.

أخطاء التاريخ والتسلسل في المرحلة الثانية

قواعد التاريخ تتحقق من منطقية التواريخ: تاريخ الإصدار لا يجوز أن يكون في المستقبل، وتاريخ الاستحقاق يجب ألّا يسبق تاريخ الإصدار. في المرحلة الثانية يضيف نظام الربط بُعدًا حرجًا: تسلسل الفواتير وربطها.

كل فاتورة تحمل عدّادًا (ICV) يجب أن يتزايد دون فجوات، ومعرّفًا فريدًا (UUID)، وتجزئة (hash) للفاتورة السابقة تربطها في سلسلة. أي كسر في هذه السلسلة، كأن يتكرر عدّاد أو تنقطع التجزئة، يُلتقط في هذه العائلة. القاعدة المبسّطة:

# قواعد التسلسل (مبسّطة)
IssueDate <= today            # تاريخ الإصدار لا يكون في المستقبل
DueDate   >= IssueDate        # الاستحقاق لا يسبق الإصدار
ICV       == previous_ICV + 1 # العدّاد يتزايد دون فجوات
PIH       == hash(previous_invoice)  # تجزئة الفاتورة السابقة

الدرس العملي هنا أن مصدر هذه الأخطاء غالبًا حالة سباق (race condition) في توليد العدّاد، أو فقدان حالة الفاتورة السابقة بعد إعادة تشغيل الخدمة. عالج العدّاد والتجزئة كحالة دائمة (persistent) لا كقيمة في الذاكرة. أي حلّ يحفظ العدّاد في الذاكرة فقط سيفشل عند أول إعادة نشر أو تشغيل متوازٍ لأكثر من نسخة من الخدمة.

نقطة ثانية كثيرًا ما تُهمَل: تزامن إصدار الفواتير. لو أصدر مستخدمان فاتورتين في اللحظة نفسها، وقرأت الخدمة العدّاد السابق قبل أن يكتب أحدهما قيمته الجديدة، يحصل المستخدمان على العدّاد نفسه فترفض الهيئة الثانية. الحل قفل على مستوى قاعدة البيانات عند توليد العدّاد، أو تسلسل (sequence) ذرّي تضمن قاعدة البيانات تفرّده.

كيف تبني طبقة تحقق محلية تمنع الرفض قبل حدوثه

أفضل استراتيجية ليست إصلاح الرفض بعد وقوعه، بل منعه. ابنِ في نظامك طبقة تحقق محلية تحاكي قواعد العمل قبل بناء المستند النهائي وإرساله. هذه الطبقة توفّر دورات شبكية كاملة، وتكشف الخطأ في بيئتك حيث يسهل تتبّعه.

رتّب هذه الطبقة حسب العائلات الخمس بالترتيب نفسه الذي ينفّذه نظام الهيئة. ابدأ بالصيغة والقوائم المغلقة لأنها الأرخص حسابيًا: تحقق من الرقم الضريبي، ورمز نوع الفاتورة، ورمز العملة، ورموز الفئات الضريبية. ثم انتقل إلى الوجود الشرطي: لكل فئة ضريبية، تحقق من وجود الحقول التي تستوجبها. بعدها نفّذ الترابط الحسابي لأنه الأغلى والأكثر حساسية للتقريب. أخيرًا تحقق من التاريخ والتسلسل.

هذا الترتيب ليس اعتباطيًا. تنفيذ الفحوص الرخيصة أولًا يعني أنك تكتشف معظم الأخطاء قبل الوصول إلى الحساب المكلف. كما أن مطابقة ترتيبك لترتيب الهيئة يجعل رسائل الرفض التي تصلك من المنصة، إن وصلت، متّسقة مع ما يلتقطه نظامك محليًا، فتقلّ المفاجآت.

# خط تحقق محلي مرتّب حسب العائلات (الأرخص أولًا)
def validate_invoice(inv) -> list[str]:
    errors = []
    errors += check_formats(inv)        # BR-KSA-39/40, code lists
    errors += check_conditional(inv)    # BR-S/Z/E exemption reason
    errors += check_calculation(inv)    # BR-CO-10/13/15/17
    errors += check_sequence(inv)       # ICV, UUID, PIH
    return errors

# لا تُرسل إلا فاتورة بلا أخطاء
issues = validate_invoice(invoice)
if issues:
    log.warning("blocked locally: %s", issues)
else:
    submit_to_platform(invoice)

سجّل كل خطأ تلتقطه محليًا برمز القاعدة المقابل في نظام الهيئة. هذا يخلق لغة موحّدة بين فريقك ووثائق الهيئة، ويجعل أي رفض لاحق قابلًا للربط مباشرة بموضع الفحص في كودك. الفريق الذي يتكلم لغة الرموز نفسها يصلح الأخطاء أسرع بكثير من فريق يصفها بكلماته الخاصة.

الاختبار في بيئة المطوّر قبل الإنتاج

قبل أن تُصدر فاتورة حقيقية، اختبر تكاملك في بيئة الاختبار التي توفّرها المنصة. الهدف أن ترى رسائل الرفض الفعلية على حالات حافّة مصمّمة عمدًا، لا أن تكتشفها مع أول عميل.

صمّم مجموعة حالات اختبار تكسر كل عائلة عمدًا. فاتورة بمجموع لا يطابق لتثبت أنك تلتقط BR-CO-15. فاتورة برقم ضريبي خاطئ لـ BR-KSA-39. بند معفى دون سبب إعفاء لـ BR-E-10. فاتورة برمز نوع غير متوافق لـ BR-KSA-15. كل حالة يجب أن تنتج الرمز المتوقع، وإلا فطبقة تحققك المحلية لا تطابق سلوك الهيئة.

احتفظ بهذه المجموعة كاختبارات تراجع (regression tests) دائمة. كلما حدّثت الهيئة قواعدها، أعد تشغيلها لتكتشف أي انحراف فورًا. التكامل مع الفوترة الإلكترونية ليس مشروعًا يُنجز مرة، بل نظامًا يتطوّر مع تحديثات الهيئة، وطبقة الاختبار هي ما يحميك من الانكسار الصامت.

منهجية موحّدة لقراءة أي رفض من المنصة

مهما تنوّعت الرموز، فالمنهجية واحدة. حين يصلك رد رفض، اتبع هذه الخطوات بالترتيب بدلًا من التخمين:

  1. اقرأ الحقل code أولًا. هو هويّة القاعدة المكسورة ومفتاح البحث في وثيقة الهيئة.
  2. اقرأ category لتعرف العائلة: BR حسابية أساسية، أم BR-KSA محلية. هذا يوجّهك للموضع الصحيح في كودك.
  3. اقرأ message كمعادلة أو شرط، لا كجملة عابرة. كل رسالة تصف العلاقة المكسورة بدقة.
  4. أعد إنتاج الحالة محليًا بنفس القيم. الخطأ الحسابي قابل لإعادة الإنتاج دائمًا.
  5. أصلح المنطق في طبقة التحقق المحلي، لا في بناء XML فقط، حتى لا يتكرر الخطأ في فواتير أخرى.

الفرق بين فريق يصلح الأخطاء بسرعة وآخر يدور في حلقة هو هذه المنهجية. الرمز ليس عقبة، بل عنوان دقيق لموضع الخطأ في منطقك.

وتذكّر أن رسالة الرفض قد تحمل أكثر من خطأ في المصفوفة الواحدة. عالجها جميعًا قبل إعادة الإرسال، لا واحدًا في كل دورة. إصلاح خطأ واحد ثم إعادة الإرسال لتكتشف الخطأ التالي يضاعف عدد الدورات بلا داعٍ، ويبطئ تكاملك في بيئة الإنتاج. اقرأ المصفوفة كاملة، رتّب الأخطاء حسب عائلاتها، وأصلحها دفعة واحدة. هذا يحوّل التكامل من سلسلة محاولات متعثّرة إلى عملية منضبطة تصل فيها الفاتورة من المحاولة الأولى.

أكثر رموز BR شيوعاً وكيفية إصلاحها
الرموز الأكثر تكراراً في الرفض وحلّها السريع.
الرمز الإصلاح
BR-CO-15/17 طابق المجاميع مع البنود
BR-S-08 تحقّق من حساب ضريبة 15%
BR-E-10 أضف سبب الإعفاء
BR-KSA-* راجع متطلبات الهيئة الخاصة
الاعتماد على الرمز يقود مباشرة للإصلاح الصحيح.
ابدأ اليوم

دع التحقق من قواعد العمل لنا

قيود يطبّق قواعد العمل والترابط الحسابي محليًا قبل الإرسال، فلا تصل فاتورتك للهيئة إلا وهي خالية من أخطاء BR. أنت تُصدر، ونحن نتولّى القواعد.

ابدأ تجربتك المجانية

أين تذهب بعد هذا الدليل؟

هذا الدليل غطّى الطبقة المنطقية. لإكمال الصورة، توجّه إلى الموارد التالية حسب احتياجك:

الأسئلة الشائعة

ما الفرق بين أخطاء XML وأخطاء التحقق؟

أخطاء XML بنيوية: عنصر مفقود أو نوع بيانات خاطئ، وتلتقطها طبقة المخطط XSD. أخطاء التحقق منطقية وحسابية: مجموع لا يطابق أو ضريبة محسوبة خطأ أو حقل شرطي غائب، وتلتقطها طبقة قواعد العمل بعد اجتياز المخطط. فاتورة سليمة البنية قد تُرفض بخطأ تحقق.

لماذا تُرفض فاتورتي برمز BR-CO رغم أن الأرقام تبدو صحيحة؟

السبب الأشهر هو فرق التقريب. حساب الضريبة على مستوى البند المنفرد ثم جمعها قد ينتج مجموعًا يختلف بهلّلة عن المتوقع. احسب الضريبة على مستوى الفئة المجمّعة، واستخدم نوعًا عشريًا دقيقًا (decimal) لا عائمًا (float).

ماذا تعني بادئة BR-KSA؟

هي قواعد العمل الخاصة بالمملكة التي تضيفها الهيئة فوق المعيار الأوروبي EN 16931. تعالج متطلبات محلية مثل صيغة الرقم الضريبي، ورمز QR، وأنواع الفواتير، وحقول المرحلة الثانية. القواعد ذات البادئة BR و BR-CO تأتي من المعيار الأوروبي الأساسي.

كيف أتحقق من الرقم الضريبي السعودي قبل الإرسال؟

تحقق من النمط محليًا: طول ثابت 15 خانة، يبدأ بالرقم 3 وينتهي بالرقم 3، وفق التعبير النمطي ^3[0-9]{13}3$. لا تعتمد على XSD لالتقاط الخطأ لأنه يرى الرقم نصًا صحيحًا بنيويًا، بينما ترفضه قاعدة BR-KSA-39.

هل يمكنني اكتشاف أخطاء التحقق محليًا قبل إرسالها للهيئة؟

نعم، وهذا هو النهج الصحيح. طبّق قواعد الترابط الحسابي والوجود الشرطي وصيغة الحقول داخل نظامك قبل بناء المستند النهائي. قيود يفعل ذلك تلقائيًا، فلا تصل الفاتورة إلى منصة فاتورة إلا بعد اجتياز التحقق المحلي.

ما رمز نوع الفاتورة الصحيح لكل نوع مستند؟

388 للفاتورة الضريبية، 383 لإشعار مدين، 381 لإشعار دائن. يجب أن يطابق الرمز محتوى المستند وحقوله، وإلا تُرفض الفاتورة برمز BR-KSA-15. الإشعار الدائن مثلًا يجب أن يحمل مرجعًا للفاتورة الأصلية.

مركز المساعدة

لم تجد ما تبحث عنه؟

لا تقلق، لدينا المزيد من أدوات المساعدة.

ندوات مباشرة يقدمها فريق قيود لمساعدتك في استخدام البرنامج بسهولة والرد على أسئلتك.

تعرّف على أحدث تحديثات فيود والتحسينات المستمرة والخصائص الجديدة في مكان واحد.

فريقنا جاهز لمساعدتك وتقديم الدعم الفوري لأي مشكلة تواجهها على مدار الساعة