تخطي للذهاب إلى المحتوى

أرقام مستندات Odoo 19 من بادئة وسنة وعدّاد – وحدة document_number_prefix_year والفخ عند الإنشاء المتزامن

3 نوفمبر 2026 | Odoo 19 Community | تطوير ذاتي
3 نوفمبر 2026 بواسطة
أرقام مستندات Odoo 19 من بادئة وسنة وعدّاد – وحدة document_number_prefix_year والفخ عند الإنشاء المتزامن

وحدة Odoo 19 المسماة document_number_prefix_year: أرقام مستندات من بادئة وسنة وعدّاد

«AN26000001» يقول أكثر من «S00001»: إنه عرض سعر، ومن عام 2026، وهو الأول. تريد شركات كثيرة، خصوصاً تلك التي تنتقل من نظام أقدم إلى Odoo، أن تحتفظ بأرقام مستنداتها بهذا الشكل بالضبط. أما Odoo نفسه فيرقّم عروض الأسعار والطلبات وسندات التسليم بتسلسلات خاصة (S00001 وWH/OUT/00001 وP00001) والفواتير ببادئة دفتر اليومية والسنة (INV/2026/00001).

ولذلك كتبنا الوحدة Document Numbering by Prefix and Year (document_number_prefix_year) لـ Odoo 19. وهي متوفرة كبرمجية حرة بموجب رخصة LGPL-3 على GitHub:

github.com/Alex0176/odoo-document-number-prefix-year

توضيح صريح في البداية: نحن لا نستخدم الوحدة في Biricon IT Services. وننشرها لأنها جاهزة وموثَّقة ومزوَّدة باختبارات ويمكن أن توفر العمل على الآخرين. ومن يستخدمها ينبغي أن يقرأ الأقسام الخاصة بـ الحدود و الاختبارات .

مخطط الترقيم

يتكون كل رقم من ثلاثة أجزاء: بادئة لكل نوع مستند، والسنة، وعدّاد بعدد خانات ثابت. أما البادئة وصيغة السنة (26 أو 2026) وعدد الخانات فتضبطونها لكل شركة تحت الإعدادات ← ترقيم المستندات.

بنية رقم المستند AN26000001 من بادئة وسنة وعدّاد، مع جدول بأنواع المستندات

تُعالَج عروض الأسعار وطلبات العملاء وفواتير العملاء والإشعارات الدائنة وسندات التسليم وإيصالات الاستلام وأوامر الشراء. والبادئات في الصورة أمثلة فقط: AN وAU وRE وGU وLI وWE وBE. ومن يترك بادئة فارغة يحتفظ لهذا النوع من المستندات بالترقيم القياسي في Odoo. أي أن الوحدة لا تفعل شيئاً إلى أن تضبطوها.

كيف تتصرف الأرقام

  • من جديد كل سنة. يبدأ العدّاد عند 1 مرة أخرى مع تغير السنة.
  • المواصلة بعد الأرقام المستوردة. تبحث الوحدة عن أعلى رقم موجود بالبادئة والسنة نفسيهما، مهما كان طوله. فإذا كان في قاعدة البيانات من النظام القديم AN26119، يكون عرض السعر التالي AN26000120. وهذا هو سبب صلاحية الوحدة لعمليات الانتقال: تُستورد المستندات القديمة بأرقامها الأصلية، وتتصل المستندات الجديدة بها بسلاسة.
  • رقم طلب جديد عند التأكيد. يحصل عرض السعر المؤكَّد عند الرغبة على رقم من تسلسل الطلبات. ويبقى رقم عرض السعر محفوظاً في الحقل رقم عرض السعر في الطلب، وهو ظاهر في النموذج والقائمة والبحث.
  • الفواتير عند الترحيل. تحصل فواتير العملاء والإشعارات الدائنة على رقمها عند الترحيل فقط، لا عند الإنشاء. ولذلك لا تترك المسودات المحذوفة فجوة. وتأتي السنة من تاريخ الفاتورة: فاتورة بتاريخ 30.12.2025 تُرحَّل في 2.1.2026 تسمى RE25….
  • كل شيء آخر يبقى. فواتير الموردين والمدفوعات وقيود اليومية وأوامر التصنيع تحتفظ بالتسلسلات القياسية في Odoo. ولا تُعاد كتابة الأسماء الموجودة أبداً، حتى لو أوقفتم الوحدة.

الجزء الحساس: مستخدمان في الوقت نفسه

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

الحماية البديهية هي القفل. تأخذ الوحدة لكل شركة وبادئة وسنة قفلاً على قاعدة البيانات (PostgreSQL Advisory Lock) يبقى حتى نهاية المعاملة. وينتظر المستخدم الثاني حتى ينتهي الأول. لكن هذا لا يكفي، وقد اكتشفنا ذلك بتجربة على نسخة من قاعدة البيانات الإنتاجية:

التسلسل الزمني لمستخدمين: بدون قراءة ثانية يمنح كلاهما الرقم نفسه، ومع قراءة ثانية يحصل الثاني على الرقم التالي

يعمل Odoo بمستوى العزل REPEATABLE READ. فحالة قاعدة البيانات التي تراها المعاملة تُجمَّد عند أول استعلام لها. والمستخدم B يملك هذه الحالة بالفعل قبل أن ينتهي A. وإذا انتظر B بعد ذلك القفل وحصل عليه، فإنه يقرأ بحالته القديمة «أعلى رقم = 0» ويمنح الرقم مرة ثانية. لقد نظّم القفل الترتيب، لكنه لم يحدّث المعرفة.

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

فحصنا ذلك بمعاملتين تسحب الثانية فيهما حالتها قبل تأكيد الأولى بشكل مثبت ثم تنتظر القفل. وبدون القراءة الثانية حصل الطلبان على الرقم نفسه، ومعها حصلا على الرقمين 1 و2.

مهم للتقييم: هذه التجربة فحص يدوي. وهي ليست جزءاً من الاختبارات الآلية، لأنها تتطلب اتصالين حقيقيين بقاعدة البيانات لا توفرهما بيئة اختبار Odoo (معاملة واحدة لكل اختبار).

التنفيذ التقني

المستندنقطة الربط
عرض السعرsale.order.create، عندما يكون الاسم فارغاً أو / أو New
طلب العميلsale.order.action_confirm، قبل التأكيد القياسي
الفاتورة، الإشعار الدائنaccount.move._set_next_sequence، تُستدعى عند الترحيل
سند التسليم، إيصال الاستلامstock.picking.create حسب نوع العملية
أمر الشراءpurchase.order.create
  • العدّاد. يجد أعلى رقم تعبير نمطي (^<Stamm>([0-9]{1,15})$، ويُهرَّب الجذر) لكل شركة، بما في ذلك الأسماء دون شركة.
  • الفواتير. تكتب _set_next_sequence الاسم وتستدعي _compute_split_sequence كي يظل منطق تسلسل Odoo (البادئة والرقم وتمييز السنة للفاتورة التالية في دفتر اليومية) متسقاً.
  • الإعدادات. تُعكس حقول الشركة document_number_* في res.config.settings. وترفض الإعدادات البادئات التي تحتوي على مسافة أو التي تنتهي برقم.
  • الترجمة. الترجمة الألمانية مضمَّنة.

التثبيت والإعداد

  1. ضعوا المجلد document_number_prefix_year في مسار الوحدات الإضافية (Addons).
  2. حدّثوا قائمة التطبيقات وثبّتوا الوحدة. والمتطلبات هي المبيعات والمشتريات والمخزون والمحاسبة.
  3. أدخلوا تحت الإعدادات ← ترقيم المستندات البادئات وصيغة السنة وعدد الخانات.
  4. جرّبوا أولاً على نسخة. لا يمكن لاحقاً التراجع تلقائياً عن رقم المستند، وفي الفواتير يرتبط بالرقم واجب الحفظ والفحص.

الحدود

ست حدود للوحدة: سلال التسوق، وصيغة السنة، وسلسلة واحدة لكل شركة، وقواعد البادئات، واختبارات قليلة، والمستندات المذكورة فقط

  • تُرقَّم عروض الأسعار عند الإنشاء. تترك عروض الأسعار المحذوفة أو الملغاة فجوات. وينطبق الأمر نفسه على كل طلب عميل تنشئه وحدة أخرى: فـسلال تسوق المتجر الإلكتروني (website_sale) هي طلبات بحالة عرض سعر وتستهلك كل منها رقماً. والفواتير والإشعارات الدائنة وحدها خالية من الفجوات، لأنها تُرقَّم عند الترحيل.
  • لا تغيّروا صيغة السنة أثناء التشغيل. مع الجذر AN26 تقرأ الوحدة AN2026000001 الموجود كعدّاد 26000001. حدّدوا الصيغة قبل أول مستند.
  • العدّاد 15 خانة كحد أقصى. تُتجاهل تسلسلات الأرقام الأطول بعد الجذر عند البحث عن أعلى رقم.
  • لا سلاسل منفصلة لكل دفتر يومية أو مخزن. يسري العدّاد لكل شركة وبادئة وسنة. وتتشارك عدة دفاتر مبيعات عدّاد الفواتير.
  • البادئات يجب ألا تحتوي على مسافة وألا تنتهي برقم، وإلا لا يعود بالإمكان فصل البادئة والسنة والعدّاد.
  • تُعالَج أنواع المستندات المذكورة فقط.

الاختبارات

تأتي الوحدة مع عشرة اختبارات آلية. وهي تفحص:

  • عرض السعر والتأكيد: رقم عرض السعر ورقم الطلب، والاحتفاظ برقم عرض السعر
  • مواصلة العدّ بعد رقم مستورد (AN26119 ← AN26000120)
  • لا إعادة ترقيم لاحقة للمستندات الموجودة
  • الفاتورة والإشعار الدائن وتغير السنة حسب تاريخ الفاتورة
  • أمر الشراء وسندات التسليم
  • بادئة فارغة: يبقى الرقم القياسي في Odoo
  • سنة من أربع خانات
  • بادئة بأحرف خاصة
  • عدة أرقام في معاملة واحدة
  • تُتجاهل تسلسلات الأرقام الطويلة جداً

الاستدعاء:

odoo-bin -d <Testdatenbank> -i document_number_prefix_year --test-enable --test-tags=/document_number_prefix_year --stop-after-init

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

تنبيه قانوني بشأن رقم الفاتورة

يجب أن تحمل الفواتير وفق § 11 UStG رقماً متسلسلاً يُمنح لمرة واحدة لتعريف الفاتورة. وتُرقّم الوحدة الفواتير عند الترحيل وبعدّاد خاص لكل بادئة وسنة، وهو ما يتوافق مع ذلك. أما ما إذا كان إعدادكم الفعلي (عدة دفاتر يومية، وإشعارات دائنة ببادئة خاصة، وتغير السنة) يستوفي متطلبات مستشاركم الضريبي، فعليكم توضيحه معه. وهذا المقال ليس استشارة قانونية.

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

لماذا لا نعدّل تسلسلات Odoo ببساطة؟

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

هل يُستبدل الترقيم الموجود؟

لا. الوحدة تمنح أرقاماً جديدة فقط. وتبقى الأسماء المحفوظة بالفعل دون تغيير، حتى عند إيقاف الوحدة.

كيف أوقفها مجدداً؟

أفرغوا بادئة نوع المستند. عندها يعود Odoo إلى ترقيمه بنفسه. كما أن إزالة التثبيت لا تغيّر أي أرقام ممنوحة.

هل تستخدمونها بأنفسكم؟

لا. لدينا تعمل أرقام Odoo القياسية. وقد فحصنا الوحدة بالاختبارات الآلية والتجربة اليدوية الموصوفة، لكن ليس في تشغيل فعلي مع مستخدمين كثيرين.

هل تعمل مع Odoo 17 أو 18؟

اختبرناها فقط مع Odoo 19.0 Community. وقد تناسب الإصدارات الأخرى أو لا تناسب، ولم نفحصها.

تحت أي رخصة تتوفر؟

تحت LGPL-3. والأخطاء والتحسينات مرحَّب بها كمسألة (Issue) في مستودع GitHub .

الدعم من Biricon IT Services

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

تواصلوا معنا الآن

الحالة بتاريخ: 3 نوفمبر 2026. إصدار الوحدة 19.0.1.0.0. جميع الأرقام في الأمثلة والصور مختارة اعتباطياً.