مناف حوراني
كلّ الأعمال

002

2025 — 2026

منظومة OUKITEL للأعمال

أربعة تطبيقات Flutter وعميل ويب يتشاركون واجهة NestJS خلفية واحدة، تغطّي مبيعات الشركات واستقبال الصيانة والمرتجعات.

تطبيقات Flutter
4
واجهة برمجية موحّدة
1
منشور
Play Store

البنية

بنية منظومة OUKITEL للأعمالأربعة تطبيقات Flutter وعميل ويب بـ Next.js تستدعي جميعها واجهة NestJS واحدة. تملك الواجهة قاعدة PostgreSQL عبر Prisma، وتصدر روابط موقَّعة مسبقاً كي ترفع الأجهزة الملفّات مباشرةً إلى S3 من دون المرور بالخادم، وتدفع المهامّ الخلفية إلى BullMQ فوق Redis، وترسل الإشعارات عبر Firebase.CLIENTSAPIDATAdirect upload · presigned URLBusinessFlutterRepairFlutterProgrammeFlutterReturnsFlutterWeb clientNext.jsNestJS APIrole-scoped surfacesPostgreSQLPrismaRedisBullMQ queuesAWS S3presignedFirebasepush
أربعة تطبيقات Flutter وعميل ويب بـ Next.js تستدعي جميعها واجهة NestJS واحدة. تملك الواجهة قاعدة PostgreSQL عبر Prisma، وتصدر روابط موقَّعة مسبقاً كي ترفع الأجهزة الملفّات مباشرةً إلى S3 من دون المرور بالخادم، وتدفع المهامّ الخلفية إلى BullMQ فوق Redis، وترسل الإشعارات عبر Firebase.
  • عميل
  • خدمة
  • مخزن بيانات
  • خارجي

المشكلة

احتاجت عمليات OUKITEL الإقليمية أدواتٍ لأدوارٍ مختلفة تتعامل جميعها مع المخزون وسجلّات العملاء نفسها — تطبيق مبيعات، وتطبيق تتبّع صيانة، وتطبيق برامج، ومسار عمل للمرتجعات.

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

المقاربة

واجهة NestJS واحدة بأسطح محدَّدة حسب الدور، وأربعة عملاء Flutter رقيقين يعرض كلّ منهم ما يحتاجه دوره فقط. وتنتقل الملفّات عبر روابط S3 موقَّعة مسبقاً بدل المرور بالواجهة البرمجية، فلا يشغل رفع صور الصيانة عاملَ معالجة طلبات. أمّا العمل البطيء — الإشعارات والتصدير وتوليد التقارير — فيذهب إلى طوابير BullMQ.

قرارات كان لها أثر

  1. 01

    واجهة واحدة، أربعة عملاء

    خدمة NestJS واحدة تملك المخطّط وتعرض أسطحاً محدَّدة حسب الدور، موثَّقة بـ Swagger. وكلّ تطبيق Flutter عميل رقيق فوقها. إضافة دور خامس تعني إضافة سطح، لا إضافة واجهة خلفية.

  2. 02

    رفعٌ بروابط موقَّعة مسبقاً

    تنتقل صور الصيانة من الجهاز إلى S3 مباشرةً عبر روابط موقَّعة مسبقاً. تُصدِر الواجهة البرمجية بيانات الاعتماد وتسجّل النتيجة، لكنّها لا تمرّر البايتات. وهكذا يتوقّف تنافس الرفع مع معالجة الطلبات على مجموعة العمّال نفسها.

  3. 03

    طوابير لكلّ ما هو بطيء

    توزيع الإشعارات وتصدير الجداول وتوليد التقارير تعمل على BullMQ فوق Redis. فالطلب الذي يطلق ألف إشعار يعود فوراً، ويُصرَّف العمل في الخلفية.

  4. 04

    الترجمة في الواجهة البرمجية لا في العملاء

    يحلّ `nestjs-i18n` اللغة في الخادم، فلا يحمل أربعة عملاء أربع نسخ متباعدة من دليل الرسائل نفسه.

مسائل صعبة

  1. 01

    أربعة تطبيقات، انضباط إصدار واحد

    تُستخرَج نماذج Dart المشتركة وطبقة HTTP الموحّدة من التطبيقات المنفردة، فيهبط أيّ تغيير في العقد مرّة واحدة لا أربع مرّات. أمّا البديل — نسخ النموذج ولصقه في أربعة مستودعات — فيفشل بصمت أوّل مرّة ينسى فيها أحدهم واحداً منها.

  2. 02

    ظروف الميدان

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

  3. 03

    تفويض يصمد أمام عميل مُفكَّك

    التحكّم بالأدوار داخل التطبيق يضبط ما يراه المستخدم؛ لكنّه ليس ما يمنعه. فكلّ نقطة نهاية تفرض حارسها الخاصّ في الخادم، على افتراض أنّ أيّ عميل قابل للتعديل.

دوري

المهندس الوحيد للواجهة الخلفية وتطبيقات Flutter الأربعة وعميل Next.js.

الحالة

تطبيق الأعمال منشور على Google Play. والمنظومة قيد الاستخدام الفعلي.

التقنيات

الهاتف
FlutterDartFirebase
الخلفية
NestJSPrismaPostgreSQLRedisBullMQSwagger
التخزين
AWS S3Presigned URLsMinIO
الواجهة
Next.jsTypeScript