كيفية إنشاء وحدات Odoo مخصصة: دليل المطور لـ OWL وORM والميراث
عندما لا تغطي وحدات Odoo الرسمية البالغ عددها 82 وحدة وأكثر من 40.000 وحدة مجتمعية متطلبات عملك المحددة، فإن تطوير الوحدات المخصصة يسد الفجوة. يغطي هذا الدليل أساسيات بناء وحدات Odoo في عام 2026، بما في ذلك هيكل الوحدة وإطار عمل الواجهة الأمامية OWL وأنماط ORM وآليات الوراثة وأفضل الممارسات المتوافقة مع إرشادات OCA (جمعية مجتمع Odoo).
ما هي وحدة Odoo المخصصة؟
وحدة Odoo المخصصة عبارة عن حزمة قائمة بذاتها من منطق الواجهة الخلفية لـ Python، وتعريفات عرض XML، ومكونات الواجهة الأمامية لـ JavaScript، وقواعد الأمان التي تعمل على توسيع وظائف Odoo. يمكن للوحدات إضافة ميزات جديدة تمامًا، أو تعديل السلوك الحالي، أو دمج Odoo مع الأنظمة الخارجية. كل قطعة من Odoo بحد ذاتها عبارة عن وحدة نمطية، مما يجعل البنية قابلة للتوسيع بطبيعتها.
هيكل دليل الوحدة
تتبع الوحدة المنظمة جيدًا هذا الهيكل القياسي:
my_custom_module/
├── __init__.py # Python package init
├── __manifest__.py # Module metadata and dependencies
├── models/
│ ├── __init__.py
│ └── my_model.py # Business logic and data models
├── views/
│ ├── my_model_views.xml # Form, tree, and kanban views
│ └── menu.xml # Menu items and actions
├── security/
│ ├── ir.model.access.csv # Access control list
│ └── security.xml # Record rules and groups
├── data/
│ └── data.xml # Default data records
├── static/
│ └── src/
│ ├── js/ # OWL components
│ ├── css/ # Stylesheets
│ └── xml/ # QWeb templates
├── wizard/ # Transient models for wizards
├── reports/ # QWeb report templates
└── tests/ # Unit tests
ملف البيان
يحدد الملف __manifest__.py هوية الوحدة الخاصة بك:
{
'name': 'My Custom Module',
'version': '18.0.1.0.0',
'category': 'Custom',
'summary': 'Short description of what the module does',
'description': """
Long description with details about
features and configuration.
""",
'author': 'ECOSIRE',
'website': 'https://ecosire.com',
'license': 'LGPL-3',
'depends': ['base', 'sale', 'stock'],
'data': [
'security/ir.model.access.csv',
'views/my_model_views.xml',
'views/menu.xml',
'data/data.xml',
],
'assets': {
'web.assets_backend': [
'my_custom_module/static/src/js/**/*',
'my_custom_module/static/src/css/**/*',
'my_custom_module/static/src/xml/**/*',
],
},
'installable': True,
'application': False,
'auto_install': False,
}
اتفاقية الإصدار: {odoo_version}.{major}.{minor}.{patch} (على سبيل المثال، 18.0.1.0.0).
العمل مع ORM
يعد رسم الخرائط الارتباطية للكائنات (ORM) من Odoo هو أساس كل عمليات تطوير الواجهة الخلفية. يتم تعيين النماذج إلى جداول قاعدة البيانات، ويوفر ORM عمليات CRUD والحقول المحسوبة والقيود وإدارة سير العمل.
تحديد النموذج
from odoo import models, fields, api
class ProjectTask(models.Model):
_name = 'my_module.task'
_description = 'Project Task'
_order = 'priority desc, create_date desc'
name = fields.Char(string='Task Name', required=True)
description = fields.Html(string='Description')
state = fields.Selection([
('draft', 'Draft'),
('in_progress', 'In Progress'),
('done', 'Done'),
('cancelled', 'Cancelled'),
], default='draft', tracking=True)
assigned_to = fields.Many2one('res.users', string='Assigned To')
deadline = fields.Date(string='Deadline')
priority = fields.Selection([
('0', 'Normal'),
('1', 'Important'),
('2', 'Urgent'),
], default='0')
tag_ids = fields.Many2many('my_module.tag', string='Tags')
progress = fields.Float(compute='_compute_progress', store=True)
مرجع أنواع الحقول
| نوع الحقل | نوع بايثون | حالة الاستخدام | |---|---|---| | شار | شارع | نص قصير (الاسم، المرجع) | | نص | شارع | نص عادي طويل | | أتش تي أم أل | شارع | محتوى نصي منسق | | عدد صحيح | كثافة العمليات | الأعداد الصحيحة | | تعويم | تعويم | الأعداد العشرية | | منطقية | منطقي | علامات الصواب/الخطأ | | التاريخ | التاريخ | تاريخ بلا زمن | | التاريخ والوقت | التاريخ والوقت | التاريخ مع الوقت | | اختيار | شارع | اختيارات القائمة المنسدلة | | Many2one | كثافة العمليات | رابط لسجل واحد | | One2many | قائمة | عكس Many2one | | Many2many | قائمة | الارتباط بسجلات متعددة | | ثنائي | بايت | مرفقات الملفات |
الحقول والقيود المحسوبة
@api.depends('subtask_ids.state')
def _compute_progress(self):
for task in self:
total = len(task.subtask_ids)
done = len(task.subtask_ids.filtered(
lambda t: t.state == 'done'
))
task.progress = (done / total * 100) if total else 0
@api.constrains('deadline')
def _check_deadline(self):
for task in self:
if task.deadline and task.deadline < fields.Date.today():
raise ValidationError(
"Deadline cannot be in the past."
)
آليات الوراثة
يوفر Odoo ثلاثة أنواع من الميراث، يخدم كل منها غرضًا مختلفًا:
1. وراثة الطبقة (الامتداد)
قم بتوسيع نموذج موجود عن طريق إضافة حقول أو طرق متجاوزة. هذا هو النمط الأكثر شيوعا.
class SaleOrderExtend(models.Model):
_inherit = 'sale.order'
custom_reference = fields.Char(string='Custom Ref')
approved_by = fields.Many2one('res.users')
def action_confirm(self):
# Add custom logic before standard confirmation
for order in self:
if order.amount_total > 10000 and not order.approved_by:
raise UserError("Orders over $10,000 require approval.")
return super().action_confirm()
2. وراثة النموذج الأولي
قم بإنشاء نموذج جديد يقوم بنسخ كافة الحقول والأساليب من نموذج موجود.
class CustomPartner(models.Model):
_name = 'my_module.partner'
_inherit = 'res.partner' # Copies structure
_description = 'Custom Partner'
3. وراثة التفويض
قم بإنشاء نموذج جديد يقوم بتفويض نموذج موجود عبر رابط Many2one. تظهر حقول النموذج الأصلي في النموذج الفرعي بشفافية.
class LibraryMember(models.Model):
_name = 'library.member'
_inherits = {'res.partner': 'partner_id'}
partner_id = fields.Many2one('res.partner', required=True,
ondelete='cascade')
membership_date = fields.Date()
member_number = fields.Char()
إطار عمل OWL (الواجهة الأمامية)
يستخدم Odoo 18 OWL (مكتبة ويب Odoo) كإطار عمل للواجهة الأمامية. OWL هو إطار عمل قائم على المكونات يشبه React أو Vue ولكنه مصمم خصيصًا لتلبية احتياجات Odoo.
مكون OWL الأساسي
/** @odoo-module */
import { Component, useState } from "@odoo/owl";
import { registry } from "@web/core/registry";
class TaskDashboard extends Component {
static template = "my_module.TaskDashboard";
setup() {
this.state = useState({
tasks: [],
filter: 'all',
});
this.loadTasks();
}
async loadTasks() {
this.state.tasks = await this.env.services.orm.searchRead(
"my_module.task",
[["state", "!=", "cancelled"]],
["name", "state", "assigned_to", "deadline"]
);
}
get filteredTasks() {
if (this.state.filter === 'all') return this.state.tasks;
return this.state.tasks.filter(
t => t.state === this.state.filter
);
}
}
قالب QWeb (XML)
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="my_module.TaskDashboard">
<div class="o_task_dashboard">
<div class="task-filters">
<button t-on-click="() => state.filter = 'all'">All</button>
<button t-on-click="() => state.filter = 'in_progress'">
In Progress
</button>
</div>
<div class="task-list">
<t t-foreach="filteredTasks" t-as="task" t-key="task.id">
<div class="task-card">
<span t-esc="task.name"/>
</div>
</t>
</div>
</div>
</t>
</templates>
تكوين الأمان
يحتاج كل نموذج إلى قواعد وصول واضحة. وبدونها، لا يمكن لأي مستخدم الوصول إلى بيانات النموذج.
قائمة التحكم في الوصول (ir.model.access.csv)
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_task_user,task.user,model_my_module_task,base.group_user,1,1,1,0
access_task_manager,task.manager,model_my_module_task,my_module.group_manager,1,1,1,1
قواعد السجل (security.xml)
<record id="task_own_rule" model="ir.rule">
<field name="name">Own Tasks Only</field>
<field name="model_id" ref="model_my_module_task"/>
<field name="domain_force">
[('assigned_to', '=', user.id)]
</field>
<field name="groups" eval="[(4, ref('base.group_user'))]"/>
</record>
اختبار الوحدة الخاصة بك
يدعم Odoo اختبارات وحدة Python باستخدام إطار عمل unittest مع فئات اختبار خاصة بـ Odoo:
from odoo.tests.common import TransactionCase
class TestTask(TransactionCase):
def setUp(self):
super().setUp()
self.task = self.env['my_module.task'].create({
'name': 'Test Task',
'state': 'draft',
})
def test_task_creation(self):
self.assertEqual(self.task.state, 'draft')
self.assertEqual(self.task.progress, 0)
def test_deadline_constraint(self):
with self.assertRaises(ValidationError):
self.task.write({
'deadline': fields.Date.subtract(
fields.Date.today(), days=1
),
})
إجراء الاختبارات باستخدام: odoo-bin -d test_db --test-enable -i my_custom_module --stop-after-init
الأسئلة المتداولة
س: كم من الوقت يستغرق إنشاء وحدة Odoo مخصصة؟ تستغرق الوحدات البسيطة (الحقول الجديدة وطرق العرض الأساسية) من يوم إلى ثلاثة أيام. تستغرق الوحدات المتوسطة (النماذج الجديدة وسير العمل والتقارير) من 1 إلى 3 أسابيع. تستغرق الوحدات المعقدة (أنظمة متعددة النماذج، وعمليات التكامل الخارجية، ومكونات OWL المخصصة) من 4 إلى 12 أسبوعًا. بالنسبة للشركات التي تحتاج إلى وحدات مخصصة ولكنها تفتقر إلى مطوري Odoo الداخليين، قم بتعيين مطور Odoo ذو خبرة من فريقنا.
س: هل يجب علي تعديل كود Odoo الأساسي أو إنشاء وحدة منفصلة؟ قم دائمًا بإنشاء وحدة منفصلة. يؤدي تعديل التعليمات البرمجية الأساسية إلى قطع إمكانية الترقية وإنشاء تعارضات دمج أثناء تحديثات الإصدار. استخدم الوراثة لتوسيع النماذج وطرق العرض الموجودة من الوحدة المخصصة الخاصة بك.
س: ما هي إرشادات OCA؟ تنشر جمعية مجتمع Odoo (OCA) معايير الترميز لجودة الوحدة، بما في ذلك اصطلاحات التسمية، ومتطلبات التوثيق، وتوقعات تغطية الاختبار، وقواعد نمط التعليمات البرمجية. يضمن اتباع إرشادات OCA أن الوحدة الخاصة بك قابلة للصيانة ومتوافقة مع النظام البيئي للمجتمع الأوسع.
الحصول على مساعدة احترافية
يتطلب إنشاء وحدات Odoo المخصصة خبرة في Python، وJavaScript، وPostgreSQL، واتفاقيات إطار عمل Odoo. سواء كنت بحاجة إلى امتداد حقل بسيط أو نظام معقد متعدد الوحدات، فإن [خدمات تخصيص Odoo] (/services/odoo/customization) من ECOSIRE تقدم وحدات جاهزة للإنتاج تم تصميمها وفقًا لمعايير OCA.
اتصل بنا لمناقشة متطلبات الوحدة المخصصة الخاصة بك والحصول على تقدير التطوير.
بقلم
ECOSIRE Research and Development Team
بناء منتجات رقمية بمستوى المؤسسات في ECOSIRE. مشاركة رؤى حول تكاملات Odoo وأتمتة التجارة الإلكترونية وحلول الأعمال المدعومة بالذكاء الاصطناعي.
مقالات ذات صلة
تكامل Amazon.de Odoo: البيع في أكبر سوق في ألمانيا باستخدام Odoo ERP
كيفية دمج Amazon.de مع Odoo ERP للسوق الألمانية. يغطي FBA ألمانيا، والوفاء لعموم أوروبا، وضريبة القيمة المضافة الألمانية، والامتثال لـ VerpackG، وتسوية التسوية.
دخول سوق التجارة الإلكترونية الألمانية باستخدام Odoo: دليل خطوة بخطوة للبائعين الدوليين
الدليل الكامل للبائعين الدوليين الذين يدخلون سوق التجارة الإلكترونية الألمانية. يغطي تحليل السوق، والمتطلبات القانونية، وتسجيل ضريبة القيمة المضافة، واختيار السوق، وإعداد Odoo ERP للبيع للمستهلكين الألمان.
إدارة عوائد التجارة الإلكترونية الألمانية باستخدام Odoo: استراتيجيات الأسواق ذات العائدات العالية
كيفية التعامل مع معدلات عوائد التجارة الإلكترونية المرتفعة في ألمانيا باستخدام Odoo ERP. يغطي سير عمل معالجة المرتجعات، وتحليلات كود السبب، وإعادة أتمتة التخزين، والسياسات الخاصة بالسوق لـ Zalando، وOtto، وAmazon.de، وKaufland.