مقدمة
التواريخ والطوابع الزمنية جزء لا يتجزأ من أي نشاط تجاري: وقت إصدار الطلب، موعد التسليم، وقت تسجيل الموظف عند الدخول... في Odoo، هناك حقل مخصص لهذا الغرض يجمع بين التاريخ والساعة لتخزين هذه المعلومات بدقة.
هناك فرق مهم بين حقل التاريخ الذي يكتفي بالتاريخ التقويمي فقط، وحقل التاريخ والوقت الذي يسجل أيضاً التوقيت بالساعة والدقيقة والثانية. هذا الاختلاف يصبح حاسماً عندما يعمل فريق موزع عبر مناطق زمنية مختلفة أو عندما تؤثر الدقائق الأولى والثانية على عمليات الأعمال.
الدليل هذا يشرح كل شيء عملياً عن حقل التاريخ والوقت في Odoo: ما الذي يخزنه، كيف يتصرف داخل نموذج البيانات، كيف تضيفه عبر Studio أو عبر كود Python، ومتى تستخدمه في سير العمل اليومي.
ما هو حقل التاريخ والوقت في Odoo
في طبقة ORM الخاصة بـ Odoo، يُعرَّف الحقل عبر fields.Datetime ويخزن تاريخاً ووقتاً كاملاً بدقة الثانية. في قاعدة البيانات يتم تمثيله عادةً كعمود TIMESTAMP في PostgreSQL. داخلياً تحفظ Odoo القيم بتوقيت UTC وتقوم بعرضها بحسب المنطقة الزمنية المعرّفة لكل مستخدم.
بالنسبة للمستخدم، يظهر الحقل كأداة اختيار تجمع بين تقويم وإدخال وقت في نفس العنصر داخل النماذج. في الجداول والتقارير تُعرض القيمة بتنسيق ينسجم مع لغة المستخدم وإعدادات منطقته الزمنية.
مثال على تعريف الحقل في نموذج Python:
from odoo import fields, models
class SaleOrder(models.Model):
_inherit = 'sale.order'
x_confirmed_on = fields.Datetime(
string='Confirmed On',
default=fields.Datetime.now,
readonly=True,
copy=False,
)
معامل string يحدد اسم الحقل الظاهر في الواجهة. default يملأ الحقل تلقائياً بالوقت الحالي عند إنشاء سجل جديد. وreadonly يجعله غير قابل للتعديل يدوياً، وهو أمر شائع لطوابع التدقيق.
في Odoo Studio يظهر هذا النوع باسم Date & Time. الحقول المضافة عبر Studio تُعطى اسماً فنياً يبدأ بـ x_studio_ تلقائياً، بينما عند إنشائها برمجياً تختار أنت الاسم التقني.
كيف يعمل الحقل
عند تعريف الحقل، يقوم إطار العمل بإنشاء العمود المناسب في قاعدة البيانات أثناء تثبيت أو تحديث الوحدة، فلا حاجة لكتابة استعلامات SQL يدوياً.
طريقة تعامل Odoo مع المناطق الزمنية قد تفاجئ البعض: يُخزّن كل شيء بتوقيت UTC. إذ يضع مستخدم في باريس موعداً على 15:00، يخزن النظام 13:00 UTC. مستخدم في نيويورك عند الاطلاع سيراه حسب منطقته (مثلاً 09:00). التحويل يتم شفافاً بناءً على إعدادات زمن المستخدم.
السمات الأساسية للحقل
أهم الخصائص التي يجب معرفتها عن حقل التاريخ والوقت في إطار Odoo هي:
- default: عادةً ما يضع المطورون
fields.Datetime.nowلملء الحقل تلقائياً بالوقت الحالي عند إنشاء السجل. - required: يجعل الحقل إلزامياً في النماذج وعلى مستوى النموذج.
- readonly: يمنع تحرير الحقل من الواجهة، مفيد لطوابع غير قابلة للتغيير.
- compute: يربط الحقل بدالة Python تحسب قيمته اعتماداً على حقول أخرى أو منطق تجاري.
- store: عند استخدامها مع
computeتجعل النتيجة محفوظة في القاعدة لتسهيل البحث والتقارير. - copy: تحدد ما إذا كانت القيمة تُنسخ عند تكرار سجل؛ افتراضياً
True. استخدمFalseللطوابع الزمنية التي لا ينبغي نقلها مع النسخ. - index: ينشئ فهرساً في قاعدة البيانات؛ مفيد للحقول التي تُستخدم بكثرة في عوامل التصفية على جداول كبيرة.
كيف يظهر الحقل في الواجهات
في نماذج الإدخال يظهر الحقل كمحدد تاريخ ووقت موحد: تقويم لاختيار اليوم وحقل لتحديد الساعة والدقيقة. في قوائم السجلات تُعرض القيم كنص منسق حسب لغة المستخدم. وفي البحث تدعم الحقول نطاقات مثل قبل أو بعد أو بين فترتين.
يمكن أيضاً ربط حقل التاريخ والوقت بالأداة date_range لتمكين اختيار نافذة زمنية مباشرة داخل النموذج، وهو مفيد للمهام المجدولة أو النوافذ الزمنية.
التفرقة بين Date و Datetime: متى تختار أيهما
قاعدة بسيطة: استخدم fields.Date عندما لا يهمك توقيت اليوم، واستخدم fields.Datetime عندما تحتاج دقة بالساعات أو الدقائق.
استخدم Date لحالات مثل: مواعيد استحقاق الفواتير، تواريخ الميلاد، تواريخ انتهاء الصلاحية للمنتجات، تواريخ تجديد العقود.
استخدم Datetime لحالات مثل: طوابع تأكيد الطلبات، بداية الاجتماعات، سجلات حضور الموظفين، عمليات التخزين المجدولة.
استخدام Datetime بدون حاجة يضيف تعقيد التعامل مع المناطق الزمنية دون فائدة. اسأل نفسك دائماً: هل توقيت اليوم مهم فعلاً لهذه العملية؟
حالات استخدام عملية
يظهر حقل التاريخ والوقت في معظم وحدات Odoo. فيما يلي أمثلة عملية توضح كيف تُستخدم في سير العمل.
CRM: تتبع نشاط العملاء المحتملين
في وحدة إدارة العلاقات، تُستخدم حقول Datetime لتسجيل متى تم فتح فرصة أو تحديد موعد متابعة. هذه البيانات تساعد المدراء على قياس زمن الاستجابة، اكتشاف الفرص المتوقفة، وإعداد تقارير نشاط الفريق. يمكن إضافة حقول مخصصة لتسجيل وقت إرسال عرض أو مكالمة محددة.
المبيعات: طوابع تأكيد الطلب
حقل date_order في سجلات المبيعات يسجل اللحظة الدقيقة لتأكيد الطلب. قيمة مهمة للتقارير اليومية أو الزمنية، لحساب زمن معالجة الطلبات، ولأغراض التدقيق عند مراجعة تغييرات ما بعد التأكيد.
المخازن: تواريخ النقل المجدولة
حقل scheduled_date في سندات النقل يساعد فرق المخازن على جدولة استلام أو شحن البضائع. يمكن تشغيل إجراءات آلية بناءً على مقارنة هذا التاريخ بالوقت الحالي، مثل إرسال رسالة تذكير عند تأخر الشحنة لساعات محددة.
التصنيع: أوقات بدء وانتهاء الإنتاج
أوامر التصنيع تستخدم حقول Datetime لتوثيق أوقات بدء وانتهاء العمليات، ما يغذي تخطيط السعة وتقارير الكفاءة. في بيئات العمل بنوبات مختلفة تصبح الدقائق والساعات ضرورية لفهم الفجوات وأماكن الاختناق في العملية الإنتاجية.
الموارد البشرية: الحضور وإدارة الإجازات
تستخدم وحدات الحضور حقول Datetime لتسجيل وقت دخول وخروج الموظفين، وتُستخدم أيضاً لتحديد بدايات ونهايات الإجازات. تعتمد حسابات الرواتب والعمل الإضافي على دقة هذه القياسات، لذلك أي نقص أو خطأ في الطوابع الزمنية يؤثر مباشرة على تعويضات الموظفين.
إنشاء أو تعديل حقل التاريخ والوقت
ثلاث طرق أساسية لإضافة حقل Datetime لنموذج Odoo، حسب مستوى الوصول التقني ورغبتك في الكود أو لا-كود.
باستخدام Odoo Studio (بدون كود)
Odoo Studio أداة التخصيص المدمجة التي تتيح إضافة حقول دون كتابة كود. خطوات إضافة حقل Datetime عبر Studio:
- افتح Odoo Studio من القائمة الرئيسية.
- انتقل إلى النموذج الذي تريد إضافة الحقل إليه.
- اسحب عنصر Date & Time من الشريط الجانبي وأفلته في النموذج.
- حدد التسمية، حالة الإلزام، واختياريًا قيمة افتراضية في لوحة خصائص الحقل.
- احفظ وغلق Studio.
Studio ينشئ الحقل تلقائياً باسم يبدأ بـ x_studio_ ويضيفه للواجهة. لا حاجة لهجرة يدوية للقاعدة؛ Odoo يتكفل بكل شيء. هذه الطريقة مناسبة للمستخدمين غير التقنيين الذين يريدون توثيق طابع زمني سريعاً.
باستخدام Python في موديل مخصص
للمطورين الذين يبنون وحدات Odoo، تُعرّف الحقول في ملفات Python. هذا الأسلوب مناسب عندما تحتاج للسيطرة على الإصدار والنشر عبر بيئات مختلفة:
from odoo import fields, models
class ResPartner(models.Model):
_inherit = 'res.partner'
x_last_contact_date = fields.Datetime(
string='Last Contact Date',
default=fields.Datetime.now,
copy=False,
)
بعد تعريف الحقل في النموذج، أضفه إلى ملف XML للعرض حتى يظهر في الواجهة. Odoo ينشئ عمود TIMESTAMP تلقائياً عند تثبيت أو تحديث الوحدة.
باستخدام XML-RPC API
إذا كنت تدير تخصيصات Odoo برمجياً — كجزء من خط نشر أو سكربت تكوين — يمكنك إنشاء حقول Datetime عبر XML-RPC:
field_id = models.execute_kw(
ODOO_DB, uid, ODOO_API_KEY,
'ir.model.fields', 'create',
[{
'name': 'x_last_contact_date',
'field_description': 'Last Contact Date',
'model_id': model_id,
'ttype': 'datetime',
'state': 'manual',
}]
)
القيمة ttype: datetime تخبر Odoo بإنشاء حقل تاريخ-وقت. وstate: manual تعني أن الحقل أنشئ خارج إطار وحدة، وهو الإعداد الصحيح للحقول المُضافة عبر Studio أو API.
ممارسات موصى بها
1. استخدم fields.Datetime.now كمراجعَة دالة، لا استدعاءً
عند ضبط قيمة افتراضية اكتب default=fields.Datetime.now بدون أقواس. إذا استخدمت الأقواس فإن الدالة تُنفذ مرة عند تحميل الكلاس وستستعمل نفس الطابع لكل السجلات التالية—نتيجة خاطئة تظهر لاحقاً.
2. ضع copy=False على طوابع الأحداث
إذا كان الحقل يسجل وقت وقوع حدث مثل تأكيد أو إكمال، اجعل copy=False. عند تكرار السجل لا ينبغي أن تنتقل طوابع الحدث من الأصل إلى النسخة، والا ستتلوّث السجلات التاريخية.
3. أرسل دائماً توقيت UTC عند الكتابة عبر الـ API
عند إنشاء أو تحديث سجلات عبر XML-RPC أرسل القيم بتوقيت UTC بصيغة YYYY-MM-DD HH:MM:SS. الـ API لا يجري تحويلات زمنية على الكتابة؛ أي تاريخ محلي يُرسل سيُخزّن كما لو كان UTC مما يولّد انحرافات يصعب اكتشافها.
4. استخدم readonly للطوابع المولدة آلياً
الحقول التي توثق أحداثاً فعلية يجب أن تكون عادةً للقراءة فقط في الواجهة لمنع التعديل اليدوي. إن دعت الحاجة للتعديل، ضَع ضوابط عبر أذونات الحقول بدلاً من تركها قابلة للتغيير للجميع.
5. اختر Date بدل Datetime عندما لا تحتاج الوقت
إن كانت الحاجة تقتصر على تاريخ تقويمي فقط، استخدم fields.Date. Datetime يضيف عبء احتساب المناطق الزمنية دون فائدة، وتبسيط نوع الحقل يسهل فهم النموذج وصيانته.
مشاكل شائعة
ارتباك المناطق الزمنية عند قراءة القيم الخام
أكثر الأخطاء شيوعاً هو قراءة القيم من القاعدة أو عبر API واعتبارها وقت المستخدم؛ في الواقع سترى دائماً القيمة المخزنة بUTC. عند بناء تقارير أو تكاملات تأكد من تحويل التوقيت على جهة العميل قبل العرض.
كتابة أوقات محلية عبر الـ API
إرسال قيمة بتوقيت محلي إلى API يجعلها تُخزن كما لو كانت UTC. نتيجةً لذلك، موعداً معيناً في باريس 15:00 قد يظهر لاحقاً للمستخدم الباريسي بتوقيت خاطئ حسب التوقيت الصيفي/الشتوي. هذا النوع من الأخطاء يظهر فقط في الإنتاج عند الاستخدام الحقيقي.
استخدام default=fields.Datetime.now() مع أقواس
إضافة الأقواس خطأ دقيق لكنه خطير: fields.Datetime.now() يُقيّم مرة عند تحميل الكلاس، فتتشارك كافة السجلات في نفس الطابع المجمد طيلة زمن عمل العامل. المشكلة صامتة وتظهر لاحقاً في تحليلات زمن الإنشاء.
نسيان copy=False على طوابع الأحداث
بدون copy=False تنتقل طوابع التاريخ والوقت عند تكرار السجل، مما يلوث التقارير التاريخية ويجعل آثار التدقيق غير موثوقة. تفصيلة صغيرة تأثيرها كبير على جودة البيانات.
استخدام Datetime عندما يكفي Date
اختيار Datetime لحقل مثل موعد استحقاق الفاتورة يضيف تعقيداً غير ضروري؛ تظهر قيمة وقت لا فائدة منها، وتعمل تحويلات المناطق الزمنية بلا سبب، كما يصبح واجهة المستخدم أقل بساطة.
خاتمة
حقل التاريخ والوقت أداة قوية في Odoo عندما تكون الدقة مطلوبة. من تتبع فتح الفرص إلى تسجيل أوقات الإنتاج وحضور الموظفين، فهو حاضر في أغلب وحدات النظام.
المفهوم الأساسي الذي يجب أن تستوعبه هو أن كل شيء يُخزّن بتوقيت UTC. الواجهة تقوم بالعرض بحسب مناطق المستخدمين، لكن أي قراءة أو كتابة خارجية عبر API يجب أن تأخذ هذا في الحسبان — معظم أخطاء المناطق الزمنية تكون ناجمة عن سوء فهم هذه النقطة.
إلى جانب ذلك، استخدام الصيغة الصحيحة للـ default، وضع copy=False عند الحاجة، واختيار Date عندما لا تكون الساعة ضرورية، كلها ممارسات تحافظ على نموذج بيانات نظيف وتقارير موثوقة.
في Dasolo نساعد الشركات على تطبيق وتخصيص وتحسين Odoo عبر جميع الأقسام. سواء احتجت مساعدة بتصميم نموذج بيانات متين، إضافة حقول مخصصة لسير العمل، أو بناء وحدة Odoo كاملة، فريقنا جاهز لدعمك. تواصل معنا لنتحدث عن مشروع Odoo الخاص بك.