19 فبراير 2025·8 دقيقة قراءة

مخطط قاعدة بيانات الخطط والتفويضات للترقيات والإضافات

مخطط قاعدة بيانات للخطط والتفويضات يدعم الترقيات، الإضافات، التجارب، والإلغاءات بدون قواعد مشفرة ثابتة باستخدام جداول وفحوصات واضحة.

مخطط قاعدة بيانات الخطط والتفويضات للترقيات والإضافات

لماذا تصبح الخطط والميزات فوضوية بسرعة

تبدو الخطط بسيطة في صفحة التسعير: Basic وPro وEnterprise. تبدأ الفوضى فور محاولتك تحويل هذه الأسماء إلى قواعد وصول حقيقية داخل التطبيق.

التحقق المشفر صلبًا (مثل if plan = Pro then allow X) يعمل في النسخة الأولى. ثم يتغير التسعير. تنتقل ميزة من Pro إلى Basic، تظهر إضافة جديدة، أو تشمل صفقة مبيعات حزمة مخصصة. فجأة يصبح لديك نفس القاعدة منسوخة عبر واجهات برمجة التطبيقات، وواجهة المستخدم، وتطبيقات الموبايل، والمهام الخلفية. تغيّر مكان واحد وتنسى آخر. يلاحظ المستخدمون ذلك.

المشكلة الثانية هي الزمن. الاشتراكات ليست تسمية ثابتة؛ تتغير أثناء الدورة. يقوم شخص بالترقية اليوم، ثم يخفض المستوى الشهر المقبل، يوقف مؤقتًا، أو يلغى مع وقت مدفوع متبقّ. إذا خزنّت قاعدة البيانات فقط «الخطة الحالية»، تفقد الجدول الزمني ولا يمكنك الإجابة على أسئلة أساسية لاحقًا: ماذا كان لدى المستخدم يوم الثلاثاء الماضي؟ لماذا وافق الدعم على استرداد؟

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

هذه الحالات عادةً ما تكسر التصاميم الساذجة:

  • الترقية منتصف الدورة: يجب أن يتغير الوصول فورًا، وقد تتبع الفوترة قواعد اقتطاع مختلفة.
  • التخفيض المجدول: قد يبقى الوصول "أعلى" حتى نهاية الفترة المدفوعة.
  • الاحتفاظ للقدامى (grandfathering): العملاء القدامى يحتفظون بميزة لا يحصل عليها العملاء الجدد.
  • الصفقات المخصصة: حساب واحد يحصل على الميزة A وليس B، رغم تشابه أسماء الخطط.
  • احتياجات التدقيق: يطلب الدعم أو المالية أو الامتثال "ما الذي كان مفعلًا ومتى؟"

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

بنهاية هذا المقال ستحصل على نمط مخطط يمكنك نسخه: الخطط والإضافات تصبح مدخلات، والتفويضات تصبح المصدر الوحيد للحقيقة بشأن الوصول إلى الميزات. نفس النهج يناسب أدوات لا-كود مثل AppMaster لأنك تحتفظ بالقواعد في بيانات ويمكن استعلامها بشكل موحَّد من الباكند، الويب، وتطبيقات الموبايل.

مصطلحات أساسية: الخطة، الإضافة، التفويض، والوصول

تبدأ الكثير من مشاكل الاشتراكات كمشكلة مفردات. إذا استخدم كل شخص الكلمة نفسها ليعني أشياء مختلفة، يتحول مخططك إلى حالات خاصة.

المصطلحات التي يجب الحفاظ على فصلها في مخطط الخطط والتفويضات:

  • Plan: الحزمة الافتراضية التي يحصل عليها المشترك (مثلاً Basic أو Pro). عادة تحدد الخطة الحدود الأساسية والميزات المشمولة.
  • Add-on: شراء اختياري يغيّر الأساس (مثلاً "مقاعد إضافية" أو "تقارير متقدمة"). يجب أن تكون الإضافات قابلة للإرفاق والإزالة دون تغيير الخطة.
  • Entitlement (تفويض): النتيجة النهائية المحسوبة "ما لديهم الآن" بعد جمع الخطة + الإضافات + التجاوزات. هذا ما يجب على التطبيق استعلامه.
  • Permission (أو capability): فعل محدد يمكن للمستخدم القيام به (مثلاً "تصدير البيانات" أو "إدارة الفوترة"). كثيرا ما تعتمد الأذونات على الدور بالإضافة إلى التفويضات.
  • Access (الوصول): النتيجة العملية عندما يطبق التطبيق القواعد (تُعرض الميزة أو تُخفي الشاشة، يُسمح أو يُمنع استدعاء API، يُطبق حدّ).

أعلام الميزات (feature flags) مرتبطة لكن مختلفة. عادةً ما يكون feature flag مفتاحًا للتحكم بالمنتج (تجارب، إصدارات تدريجية، إيقاف ميزة أثناء حادث). أما entitlement فهو وصول خاص بالعميل يعتمد على ما يدفعه أو ما مُنح. استخدم الأعلام لتغيير السلوك لمجموعات دون المساس بالفوترة. استخدم التفويضات عندما يجب أن يتطابق الوصول مع اشتراك، فاتورة، أو عقد.

النطاق مصدر آخر للخلط. حافظ على هذه الأفكار واضحة:

  • User: شخص واحد. مفيد للأدوار (admin مقابل member) والحدود الشخصية.
  • Account (العميل): الكيان الدافع. مناسب لمعلومات الفوترة وملكية الاشتراك.
  • Workspace (مشروع/فريق): حيث تتم الأعمال. يطبّق كثير من المنتجات التفويضات هنا (مقاعد، تخزين، وحدات مُمكّنة).

الزمن مهم لأن الوصول يتغير. نمذه مباشرة:

  • Start و end: يمكن أن يكون التفويض نشطًا فقط ضمن نافذة زمنية (تجربة، ترويج، عقد سنوي).
  • التغيير المجدول: الترقيات قد تبدأ الآن؛ التخفيضات عادة تبدأ عند التجديد التالي.
  • الراحة والإلغاء: قد تسمح بوصول محدود بعد فشل الدفع، لكن فقط حتى تاريخ نهاية واضح.

مثال: شركة على Pro، تضيف "تقارير متقدمة" منتصف الشهر، ثم تحدد تخفيضًا إلى Basic في الدورة التالية. تتغير الخطة لاحقًا، تبدأ الإضافة الآن، وتبقى طبقة التفويض المكان الوحيد للسؤال: "هل يمكن لهذا workspace استخدام التقارير المتقدمة اليوم؟"

مخطط أساسي بسيط للخطط والميزات

يبدأ مخطط جيد للفِرق والحقوق صغيرًا: فصل ما تبيعه (خطط وإضافات) عن ما يمكن أن يفعله الناس (ميزات). إذا أبقيت هذين الفكرتين نظيفتين، تصبح الترقيات والإضافات تغييرات بيانات لا إعادة كتابة.

مجموعة جداول أساسية عملية تناسب معظم منتجات الاشتراك:

  • products: الشيء القابل للبيع (خطة أساسية، خطة فريق، إضافة مقاعد إضافية، إضافة دعم أولوية).
  • plans: اختياري، إذا أردت جعل الخطط نوعًا خاصًا من المنتجات مع حقول خاصة (فاصل الفوترة، ترتيب العرض العام). كثير من الفرق تخزن الخطط داخل products وتستخدم عمود product_type.
  • features: كتالوج القدرات (وصول API، أقصى مشاريع، تصدير، SSO، أرصدة SMS).
  • product_features (أو plan_features إذا فصلت الخطط): جدول ربط يحدد أي الميزات تأتي مع أي منتج، عادةً مع قيمة.

ذلك الجدول الرابط هو المكان الذي يكمن فيه معظم القوة. نادرًا ما تكون الميزات مجرد تشغيل/إيقاف. قد تتضمن الخطة max_projects = 10، بينما تضيف إضافة +5. لذا يجب أن يدعم product_features على الأقل:

  • feature_value (رقم، نص، JSON، أو أعمدة منفصلة)
  • value_type (boolean، integer، enum، json)
  • grant_mode (استبدال مقابل إضافة)، حتى تتمكن الإضافة من "إضافة 5 مقاعد" بدلاً من الكتابة فوق حد الأساس

نمذج الإضافات كمنتجات أيضًا. الاختلاف الوحيد هو كيفية شرائها. المنتج الأساسي مثلاً يُؤخذ "واحدًا في كل مرة"، بينما قد تسمح إضافة بكمية. لكن كلاهما يربط إلى الميزات بنفس الطريقة. هذا يتجنّب الحالات الخاصة مثل "إذا كانت الإضافة X إذن فعل Y" المبعثرة في الكود.

يجب أن تكون الميزات بيانات، لا ثوابت في الكود. إن قمت بتشفير فحوصات الميزات في خدمات متعددة، ستحصل في النهاية على اختلافات في الشحن (الويب يقول نعم، الموبايل يقول لا، الباكند يختلف). عندما تعيش الميزات في قاعدة البيانات، يمكن للتطبيق سؤال سؤال واحد متسق ويمكنك إجراء تغييرات بتحرير صفوف.

التسمية مهمة أكثر مما تتوقع. استخدم معرفات ثابتة لا تتغير أبدًا حتى لو تغير الاسم التسويقي:

  • feature_key مثل max_projects, sso, priority_support
  • product_code مثل plan_starter_monthly, addon_extra_seats

احتفظ بتسميات العرض منفصلة (feature_name, product_name). إذا كنت تستخدم AppMaster’s Data Designer مع PostgreSQL، فإن معاملة هذه المفاتيح كحقول فريدة تؤتي ثمارها فورًا: يمكنك إعادة التوليد بأمان مع الحفاظ على الاستقرار في التكاملات والتقارير.

طبقة التفويض: مكان واحد للسؤال "هل لهم؟"

تميل معظم أنظمة الاشتراك إلى الفوضى عندما يُخزن "ما اشتروا" في مكان واحد، لكن "ما يمكنهم فعله" يُحتسب في خمسة مسارات كود مختلفة. الحل هو طبقة التفويض: جدول واحد (أو عرض) يمثل الوصول الفعّال للموضوع في لحظة زمنية.

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

جدول تفويض عملي

فكر في كل صف كادعاء واحد: "هذا الموضوع لديه الوصول إلى هذه الميزة بهذه القيمة، من هذا الوقت إلى ذلك الوقت، ومن هذا المصدر." الشكل الشائع يبدو هكذا:

  • subject_type (مثل "account", "user", "org") و subject_id
  • feature_id
  • value (القيمة الفعالة لتلك الميزة)
  • source (من أين أتت: "direct", "plan", "addon", "default")
  • starts_at و ends_at (قابلة للـ null لنهاية الوصول المستمر)

يمكن تنفيذ القيمة بعدة طرق: عمود نص/JSON واحد مع value_type، أو أعمدة منفصلة مثل value_bool, value_int, value_text. اجعله بسيطًا وقابلًا للاستعلام.

أنواع القيم التي تغطي معظم المنتجات

الميزات ليست دائمًا تشغيل/إيقاف. هذه أنواع القيم تغطي احتياجات الفوترة والتحكم في الوصول:

  • Boolean: مفعلة/معطلة ("can_export" = true)
  • Quota number: حدّ ("seats" = 10، "api_calls" = 100000)
  • Tier level: مستوى ("support_tier" = 2)
  • String: وضع أو متغير ("data_retention" = "90_days")

الأسبقية: كيف تُحل التضارب

التضارب طبيعي. قد يكون المستخدم على خطة تسمح بـ5 مقاعد، يشتري إضافة تمنح 10 أخرى، ويحصل أيضًا على منحة يدوية من الدعم.

ضع قاعدة واضحة والتزم بها في كل مكان:

  1. المنح المباشرة تتجاوز الخطة
  2. ثم الإضافات
  3. ثم القيم الافتراضية

طريقة بسيطة هي تخزين كل الصفوف المرشحة (مشتقة من الخطة، مشتقة من الإضافة، مباشرة) وحساب "الفائز" النهائي لكل subject_id + feature_id بترتيب حسب أسبقية المصدر، ثم أحدث starts_at.

إليك سيناريو ملموس: زبون يخفض خطته اليوم، لكنه سبق واشتراه إضافة مدفوعة حتى نهاية الشهر. مع starts_at/ends_at في التفويضات، يسري التخفيض فورًا للميزات المعتمدة على الخطة، بينما تظل ميزة الإضافة فعّالة حتى نهايتها. يجيب التطبيق "هل لهم؟" باستعلام واحد بدلًا من منطق حالات خاصة.

الاشتراكات، العناصر، والوصول المحدود زمنياً

فصل الوصول عن الفوترة
ربط مدفوعات Stripe، ثم حدّث الوصول عبر التفويضات بدلاً من منطق الفواتير.
إضافة المدفوعات

كتالوج الخطط (خطط، إضافات، ميزات) هو "ما". الاشتراكات هي "من لديه ماذا، ومتى". إذا أبقيت هذه مفصولة، تتوقف الترقيات والإلغاءات عن كونها مخيفة.

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

جداول أساسية لنمذجة خط زمن الشراء

يمكنك إبقاؤها بسيطة بجدولين يسهل استعلامهما:

  • subscriptions: id, account_id, status (active, trialing, canceled, past_due), started_at, current_period_start, current_period_end, canceled_at (nullable)
  • subscription_items: id, subscription_id, item_type (plan, addon), plan_id/addon_id, quantity, started_at, ends_at (nullable), source (stripe, manual, promo)

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

أبقِ الاقتطاع والفوترة خارج منطق الوصول

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

بدلاً من ذلك، دع أحداث الفوترة تحدّث سجلات الاشتراك (مثل تمديد current_period_end، إنشاء صف subscription_item جديد، أو تعيين ends_at). يجيب تطبيقك عن أسئلة الوصول من خط زمن الاشتراك (ومؤخرًا من طبقة التفويض)، لا من حسابات الفوترة.

تغييرات مجدولة بلا مفاجآت

الترقيات والتخفيضات غالباً ما تسري في لحظة محددة:

  • أضف pending_plan_id و change_at على الاشتراكات لتغيير خطة مجدول واحد.
  • أو استخدم جدول subscription_changes (subscription_id, effective_at, from_plan_id, to_plan_id, reason) إذا احتجت التاريخ وسجل تغييرات مستقبلية متعددة.

هذا يمنع تشفير قواعد عشوائية مثل "التخفيضات تحدث في نهاية الفترة" في أجزاء مختلفة من الكود. الجدولة بيانات.

أين تناسب التجارب (Trials)

التجارب مجرد وصول محدد زمنياً بمصدر مختلف. خياران نظيفان:

  • تعامل التجربة كحالة اشتراك (trialing) مع trial_start/trial_end.
  • أو أنشئ عناصر/تفويضات مُنحت للتجربة مع started_at/ends_at و source = trial.

إذا بنيت هذا في AppMaster، تتطابق هذه الجداول مع Data Designer في PostgreSQL، وتجعل التواريخ من السهل استعلام "ما النشط الآن" دون حالات خاصة.

خطوة بخطوة: نفّذ النمط

بناء التفويضات كبيانات
نمذج الخطط والإضافات والتفويضات في PostgreSQL بأدوات مرئية، بدلاً من فحوصات مشفرة ثابتة.
جرب AppMaster

يبدأ مخطط جيد للخطط والتفويضات بوعد واحد: منطق الميزات يعيش في البيانات، لا مبعثرة عبر مسارات الكود. يجب أن يسأل تطبيقك سؤالًا واحدًا - "ما هي التفويضات الفعّالة الآن؟" - ويحصل على إجابة واضحة.

1) عرّف الميزات بمفاتيح ثابتة

أنشئ جدول feature بمفتاح مستقر قابل للقراءة البشرية لن تقوم بتغييره أبدًا (حتى لو تغيرت تسمية واجهة المستخدم). مفاتيح جيدة تبدو مثل export_csv, api_calls_per_month, أو seats.

أضف نوعًا حتى يعرف النظام كيفية التعامل مع القيمة: boolean (تشغيل/إيقاف) مقابل numeric (حدود/حصص). اجعلها بسيطة ومتسقة.

2) اربط الخطط والإضافات بالتفويضات

الآن تحتاج إلى مصدرين للحقيقة: ما تتضمنه الخطة، وما تمنحه كل إضافة.

تسلسل بسيط وعملي:

  • ضع كل الميزات في جدول feature بمفاتيح ثابتة ونوع القيمة.
  • أنشئ plan و plan_entitlement حيث يمنح كل صف قيمة ميزة (مثلاً seats = 5, export_csv = true).
  • أنشئ addon و addon_entitlement التي تمنح قيمًا إضافية (مثلاً seats + 10, api_calls_per_month + 50000, أو priority_support = true).
  • قرر كيفية دمج القيم: البوليان عادةً تستخدم OR، الحدود العددية غالبًا تستخدم MAX (الأعلى يفوز)، وكميات المقاعد غالبًا تجمع SUM.
  • سجّل متى تبدأ وتنتهي التفويضات حتى لا تكسر الترقيات والإلغاءات والتحويلات الجديدة فحوصات الوصول.

إذا بنيت هذا في AppMaster، يمكنك نمذجة هذه الجداول في Data Designer والجمع بين القواعد كجدول "سياسة" صغير أو enum يستخدمه منطق الـ Business Process.

3) أنتج "التفويضات الفعّالة"

لديك خياران: الحساب عند القراءة (استعلام ودمج في كل مرة) أو توليد لقطة مخزنة عند كل تغيير (تغيير خطة، شراء إضافة، تجديد، إلغاء). لمعظم التطبيقات، اللقطات أبسط للفهم وأسرع تحت الحمل.

نهج شائع هو جدول account_entitlement يخزن النتيجة النهائية لكل ميزة، مع valid_from و valid_to.

4) طبّق الوصول بفحص واحد

لا تشتت القواعد عبر الشاشات والنقاط النهائية والمهام الخلفية. ضع دالة واحدة في كود التطبيق تقرأ التفويضات الفعّالة وتقرر.

can(account_id, feature_key, needed_value=1):
  ent = get_effective_entitlement(account_id, feature_key, now)
  if ent.type == "bool": return ent.value == true
  if ent.type == "number": return ent.value \u003e= needed_value

بمجرد أن يستدعي كل شيء can(...)، تصبح الترقيات والإضافات تحديثات بيانات بدلًا من إعادة كتابة.

سيناريو مثال: ترقية وإضافة بدون مفاجآت

فريق دعم مكون من 6 أشخاص على خطة Starter. تتضمن Starter 3 مقاعد عملاء و1000 رسالة SMS شهريًا. منتصف الشهر يكبر الفريق إلى 6 وكلهم يريدون حزمة SMS إضافية 5000. تريد أن يعمل هذا دون كود حالة خاصة مثل "if plan = Pro then...".

اليوم 1: يبدؤون على Starter

تنشئ subscription للحساب مع فترة فوترة (مثلاً 1 يناير إلى 31 يناير). ثم تضيف عنصر subscription_item للخطة.

عند الدفع (أو عبر مهمة ليلية)، تكتب منح تفويض لذلك الفترة:

  • entitlement_grant: agent_seats, القيمة 3, البداية Jan 1, النهاية Jan 31
  • entitlement_grant: sms_messages, القيمة 1000, البداية Jan 1, النهاية Jan 31

لا يسأل تطبيقك "ما هي الخطة؟" بل يسأل "ما تفويضهم الفعّال الآن؟" فيعيد المقاعد = 3، الرسائل = 1000.

اليوم 15: الترقية إلى Pro، وإضافة حزمة SMS في نفس اليوم

في 15 يناير يترقون إلى Pro (تتضمن 10 مقاعد و2000 رسالة). لا تعدل المنح القديمة. تضيف سجلات جديدة:

  • أغلق عنصر الخطة القديم: ضع subscription_item (Starter) نهاية عند Jan 15
  • أنشئ عنصر خطة جديد: subscription_item (Pro) بداية Jan 15, نهاية Jan 31
  • أضف عنصر إضافة جديد: subscription_item (SMS Pack 5000) بداية Jan 15, نهاية Jan 31

ثم تُلحَق منح للفترة نفسها:

  • entitlement_grant: agent_seats, القيمة 10, البداية Jan 15, النهاية Jan 31
  • entitlement_grant: sms_messages, القيمة 2000, البداية Jan 15, النهاية Jan 31
  • entitlement_grant: sms_messages, القيمة 5000, البداية Jan 15, النهاية Jan 31

ما الذي يحدث فورًا في 15 يناير؟

  • المقاعد: يصبح العدد الفعّال 10 (تختار قاعدة مثل "خذ الأكبر للمقاعد"). يمكنهم إضافة 3 وكلائهم ذلك اليوم.
  • الرسائل: تصبح الرسائل الفعّالة 7000 لبقية الفترة (تختار "اجمع المنح" لحزم الرسائل).

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

اليوم 25: جدولة تخفيض، الاحتفاظ بالوصول حتى نهاية الفترة

في 25 يناير يحددون تخفيضًا إلى Starter يبدأ 1 فبراير. لا تمسح منح يناير. تنشئ عناصر مستقبلية (أو منح مستقبلية) للفترة القادمة:

  • subscription_item (Starter) بداية Feb 1, نهاية Feb 28
  • لا عنصر حزمة SMS يبدأ Feb 1

النتيجة: يحتفظون بمقاعد Pro وحزمة SMS حتى 31 يناير. في 1 فبراير، تنخفض المقاعد الفعالة إلى 3 وتعود الرسائل لحد Starter للفترة الجديدة. هذا منطقي وسهل التنبؤ، ويتوافق بسلاسة مع سير عمل لا-كودي في AppMaster: تغيير التواريخ ينشئ صفوف جديدة، واستعلام التفويض يبقى واحدًا.

أخطاء شائعة وفخاخ

قاعدة وصول واحدة في كل مكان
أنشئ فحص "هل لهم؟" واحدًا باستخدام Business Process يُشارك بين الويب والموبايل.
ابدأ البناء

معظم أخطاء الاشتراك ليست أخطاء فوترة، بل أخطاء وصول سببها تشتت المنطق عبر المنتج. أسرع طريقة لكسر المخطط هي الإجابة عن "هل لهم؟" في خمسة أماكن مختلفة.

فشل كلاسيكي هو تشفير القواعد في الواجهة، الـ API، والمهام الخلفية بشكل منفصل. الواجهة تُخفي زرًا، الـ API ينسى حظر نقطة النهاية، ومهمة ليلية ما تزال تعمل لأنها تتحقق من شيء آخر. ينتهي الأمر بتقارير "يعمل أحيانًا" يصعب إعادة إنتاجها.

فخ آخر هو استخدام فحوصات plan_id بدلًا من فحوصات الميزة. يبدو الأمر بسيطًا في البداية (الخطة A يمكنها التصدير، الخطة B لا)، لكنه ينهار حين تضيف إضافة، زبون مُحتَفَظ له قديمًا، تجربة مجانية، أو استثناء مؤسسة. إذا قلت يومًا "if plan is Pro then allow..." فأنت تبني متاهة ستصونها إلى الأبد.

حواف الزمن والإلغاء

يعلق الوصول عندما تخزن فقط بوليان مثل has_export = true ولا تُرفق تواريخ. الإلغاءات، الاستردادات، العكسات المالية، والتخفيضات منتصف الدورة كلها تحتاج نوافذ زمنية. من دون starts_at و ends_at ستمنح وصولًا دائمًا عن طريق الخطأ، أو تسحب الوصول مبكرًا.

فحص بسيط لتجنّب ذلك:

  • كل منحة تفويض يجب أن تحمل مصدرًا (plan, add-on, manual override) ونطاقًا زمنيًا.
  • كل قرار وصول يجب أن يستخدم "الآن بين البداية والنهاية" (مع قواعد واضحة للقيم الفارغة للنهايات).
  • المهمات الخلفية يجب أن تعيد التحقق من التفويضات عند التشغيل، لا تفترض حالة الأمس.

لا تخلط بين الفوترة والوصول

تتعرض الفرق للمشكلات عندما تخلط سجلات الفوترة وقواعد الوصول في نفس الجدول. تحتاج الفوترة إلى فواتير، ضرائب، اقتطاع، معرفات موفر، وحالات إعادة المحاولة. يحتاج الوصول إلى مفاتيح ميزات واضحة ونوافذ زمنية. عندما تتشابك، تصبح ترحيلات الفوترة سبب انقطاع المنتج.

أخيرًا، يتخطى كثير من الأنظمة أثر التدقيق. عندما يسأل مستخدم "لماذا يمكنني التصدير؟" تحتاج إجابة مثل: "مُفعل بواسطة Add-on X من 2026-01-01 إلى 2026-02-01" أو "مُنح يدويًا بواسطة الدعم، تذكرة 1842." من دون ذلك يخمّن الدعم والهندسة.

إذا بنيت هذا في AppMaster، احتفظ بحقول التدقيق في نموذج Data Designer واجعل فحص "هل لهم؟" Business Process واحد تُستخدمه الويب، الموبايل، والتدفقات المجدولة.

قائمة تحقق سريعة قبل الإطلاق

إدارة تغيّرات الأسعار بأمان
بنى شاشات إدارة لتعديل الميزات، وربط خطط، وتطبيق استثناءات دون لمس الكود.
ابنِ الآن

قبل إطلاق مخطط الخطط والتفويضات، قم بجولة أخيرة بأسئلة حقيقية، لا نظرية. الهدف أن يكون الوصول قابلًا للشرح، للاختبار، والتغيير بسهولة.

أسئلة فحص الواقع

اختر مستخدمًا واحدًا وميزة واحدة، ثم حاول شرح النتيجة كما لو تشرحها للدعم أو المالية. إذا كان بإمكانك الإجابة فقط "هم على Pro" (أو الأسوأ "الكود يقول ذلك"), ستشعر بالألم عند أول ترقية منتصف الدورة أو صفقة استثناء.

استخدم قائمة التحقق هذه:

  • هل يمكنك الإجابة "لماذا لدى هذا المستخدم وصول؟" باستخدام البيانات فقط (عناصر الاشتراك، الإضافات، التجاوزات، ونوافذ الزمن)، بدون قراءة كود التطبيق؟
  • هل كل فحوصات الوصول تستند إلى مفاتيح ميزات ثابتة (مثل feature.export_csv) بدلًا من أسماء الخطط (مثل "Starter" أو "Business")؟ أسماء الخطط تتغير؛ مفاتيح الميزات لا يجب أن تتغير.
  • هل للتفويضات أوقات بدء وانتهاء واضحة، بما في ذلك التجارب، فترات النعمة، والإلغاءات المجدولة؟ إذا كان الزمن مفقودًا تصبح التخفيضات مصدرًا للنزاع.
  • هل يمكنك منح أو إزالة وصول لعميل واحد باستخدام سجل تجاوز، دون تفرّع المنطق؟ هذه هي طريقة التعامل مع "أعطِهم 10 مقاعد إضافية هذا الشهر" دون كود مخصص.
  • هل يمكنك اختبار ترقية وتخفيض باستخدام بضعة صفوف نموذجية والحصول على نتائج متوقعة؟ إذا احتجت لسكريبت معقد لمحاكاة ذلك، فالنموذج ضمني للغاية.

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

إذا كنت تبني هذا في أداة مثل AppMaster، التزم بنفس القاعدة: اجعل مكانًا واحدًا (استعلام أو Business Process) مسؤولًا عن "هل لهم؟" حتى يستخدم كل من الويب والموبايل نفس الإجابة.

الخطوات التالية: اجعل الترقيات سهلة الصيانة

أفضل طريقة للحفاظ على الترقيات مرتبة هي البدء أصغر مما تعتقد. اختر مجموعة صغيرة من الميزات ذات القيمة الحقيقية (5-10 تكفي) وابنِ فحص تفويض واحد أو وظيفة تجيب على سؤال واحد: "هل يمكن لهذا الحساب القيام بـ X الآن؟" إذا لم تستطع الإجابة ذلك في مكان واحد، ستكون الترقيات دائمًا محفوفة بالمخاطر.

بمجرد أن يعمل هذا الفحص، عامل مسارات الترقية كسلوك منتج، لا مجرد سلوك فوترة. أسرع طريقة لالتقاط حالات الحواف الغريبة هي كتابة مجموعة صغيرة من اختبارات الوصول المبنية على تحركات عملاء حقيقية.

خطوات عملية تعود بالنفع سريعًا:

  • عرف كتالوج ميزات صغيرًا وعيّن كل خطة إلى مجموعة واضحة من التفويضات.
  • أضف الإضافات كـ "عناصر" منفصلة تمنح أو تمدد التفويضات، بدلًا من تضمينها داخل قواعد الخطة.
  • اكتب 5-10 اختبارات وصول لمسارات شائعة (ترقية منتصف الدورة، تخفيض عند التجديد، إضافة تُضاف ثم تُزال، من تجربة إلى مدفوع، فترة نعمة).
  • اجعل تغييرات التسعير بيانات فقط: حدّث صفوف الخطة، خرائط الميزات، ومنح التفويضات، لا كود التطبيق.
  • اعتمد عادة: كل خطة أو إضافة جديدة يجب أن ترافقها تجربة تثبت سلوك الوصول المتوقع.

إذا كنت تستخدم باكند لا-كودي، يمكنك نمذجة هذا النمط بوضوح. في AppMaster، Data Designer يناسب لبناء الجداول الأساسية (خطط، ميزات، اشتراكات، عناصر اشتراك، تفويضات). ثم Business Process Editor يمكنه احتضان تدفق قرار الوصول (تحميل التفويضات النشطة، تطبيق النوافذ الزمنية، إعادة السماح/المنع) حتى لا تضطر لكتابة فحوصات مبعثرة عبر نقاط النهاية.

العائد يظهر في المرة التالية لتغيير التسعير. بدلًا من إعادة كتابة القواعد، تعدّل البيانات: تنتقل ميزة من "Pro" إلى إضافة، تتغير مدة تفويض، أو تحتفظ خطة قديمة بمنحها. يبقى منطق الوصول ثابتًا، وتصبح الترقيات تحديثًا مسيطرًا، لا اندفاعًا لكتابة الكود.

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

من السهل أن تبدأ
أنشئ شيئًا رائعًا

تجربة مع AppMaster مع خطة مجانية.
عندما تكون جاهزًا ، يمكنك اختيار الاشتراك المناسب.

البدء