دراسة حالة · Odoo هيدلس
متجر هيدلس وبوابة B2B فوق Odoo 19
كيف وضعنا أمام Odoo 19 متجرًا سريعًا بعشر لغات وبوابة B2B بمصادقة، دون تحريك نظام السجل — عبر وحدة Odoo كتبناها لهذا الغرض ووسيط على الخادم يبقي نظام ERP بعيدًا عن الإنترنت العام.
- العميل
- VARS Su Ürünleri
- القطاع
- استيراد وتوزيع الأحياء المائية
- دورنا
- العمارة البرمجية، تطوير وحدات Odoo، الواجهة الأمامية، السيو، النشر
- السنة
- ٢٠٢٦

المشكلة
تعتمد VARS على Odoo 19 Enterprise كنظام سجل: المنتجات والأسعار والمخزون وإدارة العملاء وأوامر البيع والمستندات الجمركية كلها هناك، ولم يكن نقلها واردًا. أما المتطلب التجاري فكان واجهة تصدير بعشر لغات، سريعة ومنظّمة بما يكفي ليجدها المشترون الدوليون، إضافة إلى بوابة يرى فيها العملاء الحاليون طلباتهم ومستنداتهم.
لم تكن وحدة الموقع في Odoo قادرة على حمل ذلك. تقديم كتالوج بعشر لغات عبر نظام ERP يعني أن سرعة الموقع التسويقي وجاهزيته تصبحان سرعة ERP وجاهزيته، ويضع قاعدة بيانات حسّاسة مباشرة على الإنترنت العام. والبديل — نسخ الكتالوج إلى نظام محتوى منفصل — ينشئ مصدرَي حقيقة للسعر والمخزون، وهو تحديدًا ما وُجد نظام ERP لمنعه.
القرار: بنية هيدلس ونظام ERP خلف وسيط
أبقينا Odoo مصدر الحقيقة الوحيد ووضعنا أمامه واجهة أمامية منفصلة. يُولَّد الكتالوج العام بشكل ثابت فيُقدَّم كـ HTML سريع، بينما تُرندَر صفحات البوابة على الخادم مع كل طلب لأنها تعرض بيانات عميل بعينه. كلاهما يعمل من تطبيق TanStack Start نفسه، ولهذا أمكن هذا الفصل دون صيانة قاعدتَي شفرة.
القيد الجوهري أن المتصفح لا يتحدث إلى Odoo إطلاقًا. كل نداء يعبر إلى نظام ERP يمر عبر دالة على الخادم تعمل كوسيط للواجهة الأمامية. هذه القاعدة وحدها تلغي إعداد CORS تمامًا، وتبقي كعكة جلسة Odoo بعيدة عن سكربتات المتصفح، وتعني أن نظام ERP لا يحتاج أن يكون متاحًا للعموم أصلًا.
الوضع الأمني
ثلاثة قرارات تحمل معظم المخاطر، وكل منها موثّق في المستودع المسلَّم كسجل قرار معماري:
- تُصادَق كتابة العملاء المحتملين برمز يُحفظ على الخادم فقط. يرسل المتصفح إلى نقطة النهاية الخاصة بنا، فتتحقق وتصفّي ثم تمرّر إلى Odoo. الرمز لا يصل إلى المتصفح أبدًا.
- مصادقة العميل توسّط جلسة Odoo نفسها: تذهب البيانات إلى دالة على الخادم، ويصادق Odoo عليها، ويُضبط معرّف الجلسة العائد ككعكة HttpOnly وSecure وSameSite. لا تستطيع سكربتات الصفحة قراءتها.
- الدفع ينشئ أمر بيع مسودة في Odoo ويحوّل المشتري إلى بوابة الدفع الخاصة بـ Odoo. لا توجد حزمة دفع ولا مستقبِل webhook في الواجهة الأمامية، فهي لا تلمس بيانات البطاقات وتبقى خارج نطاق PCI.
طبقة التكامل التي بنيناها
تتحدث الواجهة الأمامية إلى شيء واحد: `varsco_content_api`، وهي وحدة Odoo 19 كتبناها لهذا المشروع. تعرض سطحًا مُصدَّرًا بإصدار `/api/v1` بدل السماح للواجهة بالوصول المباشر إلى نماذج Odoo، فيصبح العقد بين النظامين صريحًا وقابلًا للاختبار.
يغطي: الكتالوج العام ومنتجات المتجر، كتابة العملاء المحتملين برمز إلى CRM، نقاط نهاية البوابة بمصادقة الجلسة للطلبات والملف الشخصي، عناوين التسليم، قائمة الرغبات، تقييمات المنتجات، الاشتراك في النشرة، تتبع الطلب والدفع — لكل منها ملف اختبار خاص ضمن مجموعة اختبارات الوحدة.
وحدتان أخريان تكملان الصورة: `midvex_sale_payment_link` التي تنتج رابط بوابة الدفع، و`midvex_customs_op` التي تعرض المستندات الجمركية واللوجستية داخل بوابة العميل — وهو متطلب خاص بتجارة الاستيراد والتصدير لا يغطيه أي متجر جاهز.
عشر لغات، وبوابات تحفظ صدقها
يعمل الموقع بعشر لغات عبر ٤٥ ملف مسار، بينها العربية والفارسية من اليمين إلى اليسار. تغطية الترجمة ليست مسألة نوايا حسنة: تُشغّل عملية البناء خمس بوابات لغوية تفشل عند تسرّب حروف لغة إلى أخرى، أو رموز تعبيرية عالقة، أو تغطية ترجمة ناقصة، أو ترجمة مقالات ناقصة، أو انحراف بين المتجر ومصدر بياناته.
وإلى جانبها تعمل اختبارات الوحدة، ومجموعة اختبارات شاملة، ومجموعة مخصّصة لإتاحة الوصول، واختبار عقد يثبّت أنواع الواجهة وخططها على عقد API الموثّق — فأي انحراف بين ما تتوقعه الواجهة وما جرى الاتفاق عليه يُلتقط في CI لا في بيئة الإنتاج.
إسناد يصل إلى نظام إدارة العملاء
كل إرسال نموذج يلتقط الصفحة واللغة ومعطيات الحملة التي أنتجته، وتكتب وحدة API الحملة والمصدر والوسيط والبلد واللغة في حقول CRM الحقيقية على سجل العميل المحتمل في Odoo، وتسجّل الصفحة التي جاء منها على السجل نفسه. النتيجة العملية أن الصفقة في خط الأنابيب يمكن تتبّعها رجوعًا إلى الصفحة واللغة اللتين ولّدتاها — وهو القياس الذي تدّعيه معظم مواقع B2B وينفّذه قليلون.
التقنيات وسطح التكامل
- Odoo 19 Enterprise — نظام السجل (منتجات، أسعار، مخزون، CRM، طلبات، جمارك)
- varsco_content_api — وحدة Odoo 19 مخصّصة تعرض عقد /api/v1 مُصدَّرًا بإصدار
- midvex_sale_payment_link · midvex_customs_op — وحدات Odoo مخصّصة
- TanStack Start (React 19 + Vite) — متجر ثابت، بوابة مُرندَرة على الخادم، وسيط BFF
- TanStack Query · TanStack Router · Tailwind CSS · TypeScript صارم
- Vitest · Playwright · مجموعة إتاحة الوصول · اختبار عقد API · خمس بوابات لغوية
- Docker، منشور على Dokploy
ما جرى تسليمه
- متجر عام بعشر لغات وبوابة عملاء B2B بمصادقة، يعملان فوق Odoo 19، دون مصدر حقيقة ثانٍ للسعر أو المخزون.
- نسخة Odoo لم تعد بحاجة لأن تكون متاحة للعموم، وواجهة أمامية تبقى خارج نطاق PCI.
- مسار عملاء محتملين يحمل فيه كل استفسار في CRM الصفحة واللغة والحملة التي أنتجته.
- طبقة تكامل قابلة لإعادة الاستخدام عن قصد: موقع العميل التالي هو واجهة أمامية جديدة موجَّهة إلى Odoo يشغّل الوحدة نفسها، لا إعادة كتابة.
أرقام الزيارات والتحويل غائبة عن قصد. لم تكن أدوات التحليل مفعّلة في نسخة الإنتاج قبل سبتمبر ٢٠٢٦، فأي رقم يُذكر عن تلك الفترة سيكون اختلاقًا. ستُضاف النتائج المقيسة هنا متى اكتملت خلفها فترة تقارير كاملة.
المرحلة التالية
مسار طلبات المنصات، بحيث تصل الطلبات القادمة من المنصات التركية إلى خط Odoo نفسه الذي تصل إليه طلبات المتجر والبوابة.
هل تديرون نظام ERP لا يمكن وضعه على الإنترنت العام؟
هذا هو السبب الأكثر شيوعًا لكون البنية الهيدلس منطقية. أخبرونا ما هو نظام السجل لديكم وما الذي تحتاجونه أمامه.