«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) و تعداد ارقام را برای هر شرکت در تنظیمات ← شمارهگذاری اسناد تنظیم میکنید.
پیشنهادهای قیمت، سفارشهای مشتری، فاکتورها و اعتبارنامههای مشتری، بارنامههای تحویل، رسیدهای کالا و سفارشهای خرید پوشش داده میشوند. پیشوندها در تصویر فقط نمونهاند: 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» را میخواند و شماره را برای بار دوم اختصاص میدهد. قفل ترتیب را تنظیم کرد، اما دانش را بهروز نکرد.
راهحل یک خواندن دوم از طریق یک اتصال پایگاه دادهٔ جداگانهٔ کوتاهعمر است که همهٔ ردیفهای ازپیشتأییدشده را میبیند. مقدار بزرگتر از میان این دو برنده است. خواندن اول همچنان لازم است، چون فقط آن شمارههایی را میشناسد که همان تراکنش پیشتر اختصاص داده اما هنوز تأیید نکرده است، مثلاً هنگام واردسازی چند سند بهصورت یکجا.
ما این را با دو تراکنش آزمودیم که در آنها اثباتشده است دومی پیش از Commit اولی وضعیت خود را گرفته و سپس منتظر قفل مانده است. بدون خواندن دوم هر دو سفارش شمارهٔ یکسان گرفتند، با آن شمارههای 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بازتاب داده میشوند. تنظیمات پیشوندهای دارای فاصله یا رقم در انتها را رد میکنند. - ترجمه. ترجمهٔ آلمانی همراه است.
نصب و راهاندازی
- پوشهٔ
document_number_prefix_yearرا در مسیر Addons قرار دهید. - فهرست برنامهها را بهروز کنید، ماژول را نصب کنید. پیشنیازها فروش، خرید، انبار و حسابداری هستند.
- در تنظیمات ← شمارهگذاری اسناد پیشوندها، قالب سال و تعداد ارقام را وارد کنید.
- ابتدا روی یک کپی امتحان کنید. شمارهٔ یک سند را بعداً نمیتوان بهطور خودکار برگرداند و در فاکتورها شماره با تکلیف نگهداری و بازرسی گره خورده است.
محدودیتها
- پیشنهادهای قیمت هنگام ایجاد شماره میگیرند. پیشنهادهای قیمت حذفشده یا لغوشده شکاف بر جا میگذارند. همین در مورد هر سفارش مشتری که ماژول دیگری ایجاد کند صادق است: سبدهای خرید فروشگاه وب (
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، فهرست انسداد برای ترافیک حمله.
تاریخ بروزرسانی: ۳ نوامبر ۲۰۲۶. نسخهٔ ماژول 19.0.1.0.0. همهٔ شمارهها در مثالها و تصاویر آزادانه انتخاب شدهاند.