مشروع Kotlin Multiplatform (KMP) + SQLDelight + Jetpack Compose، حسب القرارات المتفق عليها:
- يعمل حاليًا على Android، والبنية جاهزة لإضافة Desktop/iOS لاحقًا بدون إعادة كتابة قاعدة البيانات
- Offline-first بالكامل: كل البيانات تُخزَّن محليًا فورًا عبر SQLDelight، والتطبيق يعمل ١٠٠٪ بدون إنترنت
- مصادقة ومزامنة سحابية عبر Supabase (Postgres): حساب واحد يفتحه المستخدم من أي جهاز (أندرويد/آيفون/كمبيوتر)، والمزامنة تصير تلقائيًا لما يتوفر اتصال — بدون ما توقف العمل المحلي
- كل جدول يحتوي
businessIdلدعم تعدد الأنشطة التجارية مستقبلاً (ميزة "رجل الأعمال")؛ حاليًاbusinessId = معرّف المستخدم بـ Supabase(حساب واحد = نشاط تجاري واحد)
- من supabase.com — أنشئ حساب ومشروع مجاني (بدون بطاقة بنكية)
- من القائمة الجانبية SQL Editor → New query → الصق محتوى
supabase/schema.sqlكامل → Run- هذا الملف ينشئ الجداول (product, customer, invoice, invoice_item, payment, expense) + سياسات RLS التي تضمن إن كل مستخدم يشوف بياناته فقط
- من Authentication → Providers: تأكد إن "Email" مفعّل (مفعّل افتراضيًا)
- الـ
Project URLوالـanon/publishable keyمُضمّنين مسبقًا بـSupabaseClientProvider.kt(آمنين للتضمين بالعميل لأن كل الصلاحيات مفروضة عبر RLS)
تنبيه مهم (خطة Supabase المجانية): أي مشروع ما يستقبل طلبات لمدة 7 أيام متتالية يتوقف تلقائيًا (pause) لحد ما تدخل للوحة التحكم وتفعّله يدويًا. البيانات ما تنمسح، بس المزامنة تتوقف مؤقتًا. الحل: جدولة "نبضة" أسبوعية بسيطة (مثلاً عبر GitHub Actions) أو الاعتماد على فتح المستخدم للتطبيق بشكل دوري.
Bayan/
├── settings.gradle.kts
├── build.gradle.kts
├── supabase/
│ └── schema.sql ← مخطط Postgres + RLS (يُشغَّل يدويًا بلوحة تحكم Supabase)
├── shared/ ← المنطق المشترك (يُعاد استخدامه لاحقًا مع Desktop/iOS)
│ ├── build.gradle.kts
│ └── src/
│ ├── commonMain/
│ │ ├── sqldelight/com/bayan/app/db/
│ │ │ ├── Business.sq ← جدول الأنشطة التجارية
│ │ │ ├── Product.sq ← جدول المنتجات
│ │ │ ├── Customer.sq ← جدول العملاء/الموردين
│ │ │ ├── Invoice.sq ← الفواتير وبنودها
│ │ │ ├── Payment.sq ← دفعات/تسديدات يدوية (كشف الحساب)
│ │ │ └── Expense.sq ← المصروفات
│ │ └── kotlin/com/bayan/app/
│ │ ├── domain/
│ │ │ ├── model/ (Product, Party, Invoice, Expense, AuthUser...)
│ │ │ └── repository/ (واجهات المستودعات، منها AuthRepository)
│ │ └── data/
│ │ ├── DatabaseDriverFactory.kt (expect)
│ │ ├── remote/SupabaseClientProvider.kt ← إعداد عميل Supabase (URL + key)
│ │ └── repository/ (التنفيذ الفعلي، منها AuthRepositoryImpl)
│ └── androidMain/
│ └── kotlin/com/bayan/app/data/DatabaseDriverFactory.kt (actual)
└── androidApp/ ← واجهة Android (Compose)
└── src/main/
├── AndroidManifest.xml
└── kotlin/com/bayan/app/android/
├── MainActivity.kt ← بوابة المصادقة + التنقل بين الشاشات
├── auth/ ← تسجيل الدخول / حساب جديد
├── dashboard/, sales/, invoices/, expenses/, products/, parties/
- المنتجات: عرض، إضافة، حذف (soft delete)، تنبيه انخفاض المخزون
- العملاء والموردون (نفس الجدول، مفصولين بـ type): عرض، إضافة، حذف، رصيد (له/عليه)
- فاتورة البيع: سلة + عميل اختياري + دفع (نقد/تحويل/دين) → تنقص المخزون وتحدّث دين العميل تلقائيًا بعملية واحدة (transaction)
- قائمة الفواتير السابقة + تفاصيل كل فاتورة (الأصناف، الكمية × السعر، الربح المحقق)
- كشف حساب موحّد لكل عميل/مورد (فواتير + دفعات يدوية) مع إمكانية تسجيل تسديد/دفعة-سلفة
- شاشة مصروفات مستقلة: سجل كامل، فلترة بالتصنيف (تلقائية حسب بياناتك)، حذف مباشر
- لوحة التحكم: مبيعات/أرباح/مصروفات اليوم، صافي اليوم، إجمالي الديون، منتجات قليلة، إضافة مصروف سريع
- تسجيل الدخول / حساب جديد عبر Supabase (بريد + كلمة سر)، بحيث نفس الحساب يفتح نفس البيانات من أي جهاز
- قاعدة بيانات محلية حقيقية (SQLDelight) تعمل بدون إنترنت بالكامل
- دعم RTL كامل للعربية بالواجهة
المرحلة الحالية أضافت المصادقة فقط (تسجيل دخول/حساب موحّد يحدد businessId). البيانات نفسها لسا محلية بالكامل (SQLDelight) ولسا ما فيه رفع/سحب تلقائي مع جداول Supabase. الخطوة الجاية:
- طبقة "Sync Engine" تراقب التغييرات المحلية (إضافة/تعديل/حذف) وترفعها لجداول Supabase لما يتوفر اتصال
- سحب التغييرات القادمة من جهاز آخر لنفس الحساب وتطبيقها محليًا (conflict resolution بسيط بالاعتماد على
updatedAt) - مؤشر بالواجهة يوضح حالة المزامنة (متزامن / جارِ الرفع / بدون اتصال)