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

003

2024 — 2025

Netlastik

تطبيق تجارة إطارات بين الشركات للموزّعين، منشور على App Store وGoogle Play.

منشور على
iOS + Android
متجرا تطبيقات، كلاهما منشور
2
وحدة وظيفية
17

البنية

Netlastik — تطبيق الموزّعين ومسار الدفعيفتح الموزّع تطبيق Flutter ويختار الحساب الذي يشتري لصالحه، وهذا الاختيار يحدّد نطاق الكتالوج والتسعير وكشف الحساب طوال الجلسة. ويتحدّث التطبيق إلى واجهة HTTP واحدة عبر عميل dio مشترك، تخدم الكتالوج وحساب الموزّع الجاري معاً. أمّا الدفع فيغادر التطبيق كلّياً: إدخال البطاقة يجري داخل صفحة البنك نفسها، ولا يُسوّى الطلب إلّا حين تعود النتيجة.1 · account scope2 · pay3 · settledFlutter appiOS · AndroidNetlastik APIHTTP · dioCataloguetyres · pricingCari hesapledger · receiptsBank webviewcard entry
يفتح الموزّع تطبيق Flutter ويختار الحساب الذي يشتري لصالحه، وهذا الاختيار يحدّد نطاق الكتالوج والتسعير وكشف الحساب طوال الجلسة. ويتحدّث التطبيق إلى واجهة HTTP واحدة عبر عميل dio مشترك، تخدم الكتالوج وحساب الموزّع الجاري معاً. أمّا الدفع فيغادر التطبيق كلّياً: إدخال البطاقة يجري داخل صفحة البنك نفسها، ولا يُسوّى الطلب إلّا حين تعود النتيجة.
  • عميل
  • خدمة
  • مخزن بيانات
  • خارجي

المشكلة

Netlastik تاجر إطارات يبيع للموزّعين لا لسائقي السيارات. والتطبيق منشور على المتجرين تحت حسابات المطوّر الخاصّة بالعميل، وقد بُني ليكون واجهة الموزّعين لكتالوجه ونظامه المحاسبي القائمين.

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

المقاربة

عميل Flutter مبنيّ على سبع عشرة وحدة وظيفية فوق نواة مشتركة واحدة: Bloc لإدارة الحالة، وget_it للتركيب، وgo_router للتنقّل، وعميل dio واحد تمرّ منه كلّ الوحدات. والحساب الذي يختاره الموزّع هو حالة جلسة تحدّد نطاق كلّ ما يليها، فلا تحتاج أيّ شاشة إلى تذكّر التصفية به. أمّا الدفع فيُسلَّم إلى صفحة البنك نفسها بدل إعادة بنائه، فلا تصل بيانات البطاقة إلى التطبيق أصلاً.

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

  1. 01

    بنية واحدة، مكرّرة سبع عشرة مرّة

    بنية واحدة، مكرّرة. لكلّ وحدة وظيفية الشكل نفسه: Bloc للحالة، وget_it للإنشاء، وgo_router للدخول، وdio للنقل. وسبع عشرة وحدة عددٌ كافٍ ليكون لسؤال «كيف أبني شاشة؟» جواب واحد فقط، وإلّا صارت الشيفرة سبع عشرة لهجة.

  2. 02

    الأخطاء قيَم لا استثناءات

    الأخطاء قيَم لا استثناءات. تُعيد الطلبات نوع Either من dartz، فيصبح الفشل شيئاً على المستدعي أن يفكّكه قبل أن يصل إلى الواجهة. فـ try/catch منسيّ يفشل بصمت، أمّا Either غير المعالَج فلا يُترجَم أصلاً.

  3. 03

    الحساب المختار حالة جلسة

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

  4. 04

    الحساب الجاري سطح من الدرجة الأولى

    الحساب الجاري سطح من الدرجة الأولى. لحركات الرصيد والإيصالات والمدفوعات الناجحة والفاشلة وجهاتها الخاصّة بدل دفنها في سجلّ الطلبات — لأنّ الشاشة التي يفتحها الموزّع يومياً هي كشف الحساب لا الكتالوج.

  5. 05

    إدخال البطاقة لا يحدث داخل التطبيق

    يجري مسار 3-D Secure داخل صفحة البنك نفسها، لا في نموذج بطاقة من صنعي. فبيانات البطاقة لا تدخل عملية التطبيق أصلاً، وبالتالي لا يخزّنها العميل ولا ينقلها ولا يعالجها — فالجزء الذي يحمل أثقل عبء امتثالي في أيّ تكامل دفع غائب ببساطة، والمسار الذي كان ضبطه أصعب شيء هو المسار الذي لم أكتبه. أمّا الكلفة فهي أنّ النتيجة تصل لاحقاً وبشكل غير متزامن، وهذا ما يحوّل مسارات العودة الثلاثة أدناه إلى مشكلة حقيقية لا افتراضية.

مسائل صعبة

  1. 01

    السعر دالّة على هويّة السائل

    التسعير بين الشركات خاصّ بكلّ حساب، فلا يمكن تخزين سعر «نهائي» لأيّ منتج. فكلّ سعر دالّة على هويّة السائل، وهذا يستبعد معظم أساليب التخزين المؤقّت البديهية للكتالوج ويجعل تبديل الحساب حدّاً للذاكرة المؤقّتة.

  2. 02

    الدفعة قد تعود بثلاث صور

    الدفعة التي تغادر التطبيق قد تعود بثلاث صور: مسوّاة، أو مرفوضة، أو لا تعود إطلاقاً حين يغلق الموزّع صفحة البنك في منتصف العملية. لذا للنجاح والفشل وجهتان منفصلتان بحالتيهما، ولا تُقرأ الدفعة المهجورة نجاحاً بصمت.

  3. 03

    متجران وفرع واحد

    متجران ومسارا مراجعة وقاعدة شيفرة واحدة. يفترق iOS وأندرويد في الأذونات وسلوك الـ webview وإيقاع الإصدار، وكان على كليهما أن يبقى قابلاً للإطلاق من الفرع نفسه.

دوري

المهندس الوحيد على العميل. البنية، وإدارة الحالة، والتنقّل، والوحدات الوظيفية السبع عشرة كلّها، وتسليم الدفع، وإصدارا المتجرين.

الحالة

منشور وفعّال على Google Play وApp Store. بُني وأُطلق بين 2024 و2025، ثمّ سُلّم ويتولّى صيانته آخرون.

التقنيات

الهاتف
FlutterDartBloc / Cubitgo_routerget_itdio
البيانات
dartzequatableshared_preferences
الواجهة
flutter_screenutilflutter_svgcached_network_imageinfinite_scroll_paginationpinputwebview_flutter