Commit 08f1efaf authored by Mahmoud Aglan's avatar Mahmoud Aglan

Sync Admin SystemSettings schema with actual DB keys

The hardcoded schema used different key names (tax_rate, default_locale,
grace_period_participants, etc.) than what the seeder + DB actually stores.
Aligned all keys, added missing groups (pricing), and seeded
platform_fee_customer_pays into production.
Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
parent cb8476a3
......@@ -19,56 +19,138 @@ class SystemSettings extends Component
'general' => [
'academy_name_ar' => ['type' => 'string', 'label' => 'اسم الأكاديمية (عربي)'],
'academy_name_en' => ['type' => 'string', 'label' => 'اسم الأكاديمية (إنجليزي)'],
'default_locale' => ['type' => 'select', 'label' => 'اللغة الافتراضية', 'options' => ['ar' => 'العربية', 'en' => 'English']],
'timezone' => ['type' => 'select', 'label' => 'المنطقة الزمنية', 'options' => ['Africa/Cairo' => 'القاهرة', 'Asia/Riyadh' => 'الرياض', 'Asia/Dubai' => 'دبي', 'UTC' => 'UTC']],
'default_language' => ['type' => 'select', 'label' => 'اللغة الافتراضية', 'options' => ['ar' => 'العربية', 'en' => 'English']],
'date_format' => ['type' => 'select', 'label' => 'صيغة التاريخ', 'options' => ['Y-m-d' => 'Y-m-d', 'd/m/Y' => 'd/m/Y']],
'time_format' => ['type' => 'select', 'label' => 'صيغة الوقت', 'options' => ['H:i' => '24 ساعة', 'h:i A' => '12 ساعة']],
'week_starts_on' => ['type' => 'select', 'label' => 'أول يوم في الأسبوع', 'options' => ['6' => 'السبت', '0' => 'الأحد', '1' => 'الإثنين']],
'pagination_size' => ['type' => 'number', 'label' => 'عدد العناصر في كل صفحة', 'step' => '1', 'min' => 10, 'max' => 100],
'session_timeout_minutes' => ['type' => 'number', 'label' => 'مهلة انتهاء الجلسة (دقيقة)', 'step' => '1', 'min' => 15],
],
'financial' => [
'currency_code' => ['type' => 'select', 'label' => 'رمز العملة', 'options' => ['EGP' => 'جنيه مصري (EGP)', 'SAR' => 'ريال سعودي (SAR)', 'AED' => 'درهم إماراتي (AED)', 'USD' => 'دولار أمريكي (USD)']],
'tax_rate' => ['type' => 'number', 'label' => 'نسبة الضريبة (%)', 'step' => '0.01', 'min' => 0, 'max' => 100],
'currency_symbol' => ['type' => 'string', 'label' => 'رمز العملة للعرض'],
'tax_enabled' => ['type' => 'boolean', 'label' => 'تفعيل الضريبة'],
'tax_percentage' => ['type' => 'number', 'label' => 'نسبة الضريبة (%)', 'step' => '0.01', 'min' => 0, 'max' => 100],
'tax_registration_number' => ['type' => 'string', 'label' => 'رقم التسجيل الضريبي'],
'invoice_prefix' => ['type' => 'string', 'label' => 'بادئة رقم الفاتورة'],
'receipt_prefix' => ['type' => 'string', 'label' => 'بادئة رقم الإيصال'],
'payment_due_days' => ['type' => 'number', 'label' => 'أيام استحقاق الدفع', 'step' => '1', 'min' => 1],
'max_discount_percent' => ['type' => 'number', 'label' => 'الحد الأقصى للخصم (%)', 'step' => '1', 'min' => 0, 'max' => 100],
'wallet_enabled' => ['type' => 'boolean', 'label' => 'تفعيل المحفظة'],
'platform_fee_customer_pays' => ['type' => 'boolean', 'label' => 'رسوم المنصة يدفعها العميل', 'hint' => 'مفعّل: العميل يدفع الرسوم (تُضاف للإجمالي) — معطّل: الأكاديمية تتحمل الرسوم (تُخصم من الإيراد)'],
'refund_requires_approval' => ['type' => 'boolean', 'label' => 'الاسترداد يتطلب موافقة'],
'refund_approval_threshold' => ['type' => 'number', 'label' => 'حد مبلغ الاسترداد للموافقة (قروش)', 'step' => '1', 'min' => 0],
'installment_late_fee' => ['type' => 'number', 'label' => 'غرامة تأخير القسط (قروش)', 'step' => '1', 'min' => 0],
'auto_overdue_after_days' => ['type' => 'number', 'label' => 'أيام لتحويل الفاتورة لمتأخرة', 'step' => '1', 'min' => 1],
],
'attendance' => [
'grace_period_participants' => ['type' => 'number', 'label' => 'فترة السماح للمشتركين (دقيقة)', 'step' => '1', 'min' => 0],
'grace_period_trainers' => ['type' => 'number', 'label' => 'فترة السماح للمدربين (دقيقة)', 'step' => '1', 'min' => 0],
'auto_absent_delay' => ['type' => 'number', 'label' => 'تأخير الغياب التلقائي (ساعة)', 'step' => '1', 'min' => 1],
'consecutive_absence_threshold' => ['type' => 'number', 'label' => 'حد الغياب المتتالي', 'step' => '1', 'min' => 1],
'min_attendance_percentage' => ['type' => 'number', 'label' => 'الحد الأدنى لنسبة الحضور (%)', 'step' => '1', 'min' => 0, 'max' => 100],
'participant_grace_period_minutes' => ['type' => 'number', 'label' => 'فترة السماح للمشتركين (دقيقة)', 'step' => '1', 'min' => 0],
'trainer_grace_period_minutes' => ['type' => 'number', 'label' => 'فترة السماح للمدربين (دقيقة)', 'step' => '1', 'min' => 0],
'auto_absent_after_hours' => ['type' => 'number', 'label' => 'تأخير الغياب التلقائي (ساعة)', 'step' => '1', 'min' => 1],
'consecutive_absences_for_suspend' => ['type' => 'number', 'label' => 'حد الغياب المتتالي للإيقاف', 'step' => '1', 'min' => 1],
'min_attendance_percent' => ['type' => 'number', 'label' => 'الحد الأدنى لنسبة الحضور (%)', 'step' => '1', 'min' => 0, 'max' => 100],
'notify_guardian_on_absence' => ['type' => 'boolean', 'label' => 'إشعار ولي الأمر عند الغياب'],
'allow_excuse_after_hours' => ['type' => 'number', 'label' => 'صلاحية تقديم عذر (ساعة)', 'step' => '1', 'min' => 1],
'qr_check_in_enabled' => ['type' => 'boolean', 'label' => 'تسجيل حضور بـ QR Code'],
],
'notifications' => [
'sms_enabled' => ['type' => 'boolean', 'label' => 'تفعيل الرسائل القصيرة'],
'email_enabled' => ['type' => 'boolean', 'label' => 'تفعيل البريد الإلكتروني'],
'digest_time' => ['type' => 'time', 'label' => 'وقت الملخص اليومي'],
'sms_rate_limit' => ['type' => 'number', 'label' => 'حد الرسائل القصيرة (بالساعة)', 'step' => '1', 'min' => 1],
'sms_enabled' => ['type' => 'boolean', 'label' => 'تفعيل الرسائل القصيرة'],
'sms_provider' => ['type' => 'select', 'label' => 'مزود SMS', 'options' => ['log' => 'سجل فقط', 'twilio' => 'Twilio', 'vonage' => 'Vonage']],
'sms_rate_limit_per_hour' => ['type' => 'number', 'label' => 'حد الرسائل القصيرة (بالساعة)', 'step' => '1', 'min' => 1],
'digest_mode_enabled' => ['type' => 'boolean', 'label' => 'تفعيل وضع الملخص اليومي'],
'digest_send_time' => ['type' => 'time', 'label' => 'وقت الملخص اليومي'],
'notify_admin_on_payment' => ['type' => 'boolean', 'label' => 'إشعار المدير عند الدفع'],
'notify_guardian_on_enrollment' => ['type' => 'boolean', 'label' => 'إشعار ولي الأمر عند التسجيل'],
'payment_reminder_days_before' => ['type' => 'number', 'label' => 'أيام تذكير قبل الاستحقاق', 'step' => '1', 'min' => 1],
],
'pricing' => [
'global_max_discount' => ['type' => 'number', 'label' => 'الحد الأقصى للخصم الكلي (%)', 'step' => '1', 'min' => 0, 'max' => 100],
'allow_price_override' => ['type' => 'boolean', 'label' => 'السماح بتجاوز السعر يدوياً'],
'auto_apply_family_discount' => ['type' => 'boolean', 'label' => 'تطبيق خصم العائلة تلقائياً'],
'family_discount_start_child' => ['type' => 'number', 'label' => 'رقم الطفل لبدء خصم العائلة', 'step' => '1', 'min' => 2],
'trial_period_days' => ['type' => 'number', 'label' => 'مدة الفترة التجريبية (أيام)', 'step' => '1', 'min' => 0],
'early_enrollment_days' => ['type' => 'number', 'label' => 'أيام التسجيل المبكر (للخصم)', 'step' => '1', 'min' => 0],
'coupon_max_uses_default' => ['type' => 'number', 'label' => 'الحد الافتراضي لاستخدام الكوبون', 'step' => '1', 'min' => 1],
],
'enrollment' => [
'allow_waitlist' => ['type' => 'boolean', 'label' => 'تفعيل قائمة الانتظار'],
'max_waitlist_per_group' => ['type' => 'number', 'label' => 'الحد الأقصى لقائمة الانتظار لكل مجموعة', 'step' => '1', 'min' => 0],
'auto_promote_waitlist' => ['type' => 'boolean', 'label' => 'ترقية تلقائية من قائمة الانتظار'],
'require_medical_report' => ['type' => 'boolean', 'label' => 'إلزام تقرير طبي'],
'require_guardian_for_minors' => ['type' => 'boolean', 'label' => 'إلزام ولي أمر للقاصرين'],
'minor_age_threshold' => ['type' => 'number', 'label' => 'سن التسجيل بدون ولي أمر', 'step' => '1', 'min' => 1],
'max_groups_per_participant' => ['type' => 'number', 'label' => 'الحد الأقصى للمجموعات لكل مشترك', 'step' => '1', 'min' => 1],
'allow_transfer_between_groups' => ['type' => 'boolean', 'label' => 'السماح بنقل بين المجموعات'],
'freeze_max_days' => ['type' => 'number', 'label' => 'أقصى مدة تجميد (أيام)', 'step' => '1', 'min' => 1],
'freeze_max_times' => ['type' => 'number', 'label' => 'أقصى عدد مرات التجميد', 'step' => '1', 'min' => 1],
'enrollment_expiry_days' => ['type' => 'number', 'label' => 'مدة صلاحية الاشتراك (أيام)', 'step' => '1', 'min' => 1],
],
];
protected array $defaults = [
// general
'academy_name_ar' => '',
'academy_name_en' => '',
'default_locale' => 'ar',
'timezone' => 'Africa/Cairo',
'default_language' => 'ar',
'date_format' => 'Y-m-d',
'time_format' => 'H:i',
'week_starts_on' => '6',
'pagination_size' => '25',
'session_timeout_minutes' => '120',
// financial
'currency_code' => 'EGP',
'tax_rate' => '14',
'currency_symbol' => 'ج.م',
'tax_enabled' => '0',
'tax_percentage' => '14',
'tax_registration_number' => '',
'invoice_prefix' => 'INV',
'receipt_prefix' => 'RCP',
'payment_due_days' => '7',
'max_discount_percent' => '50',
'wallet_enabled' => '0',
'grace_period_participants' => '15',
'grace_period_trainers' => '10',
'auto_absent_delay' => '2',
'consecutive_absence_threshold' => '5',
'min_attendance_percentage' => '75',
'sms_enabled' => '0',
'wallet_enabled' => '1',
'platform_fee_customer_pays' => '1',
'refund_requires_approval' => '1',
'refund_approval_threshold' => '50000',
'installment_late_fee' => '500',
'auto_overdue_after_days' => '3',
// attendance
'participant_grace_period_minutes' => '15',
'trainer_grace_period_minutes' => '10',
'auto_absent_after_hours' => '2',
'consecutive_absences_for_suspend' => '5',
'min_attendance_percent' => '75',
'notify_guardian_on_absence' => '1',
'allow_excuse_after_hours' => '48',
'qr_check_in_enabled' => '0',
// notifications
'email_enabled' => '1',
'digest_time' => '08:00',
'sms_rate_limit' => '100',
'sms_enabled' => '0',
'sms_provider' => 'log',
'sms_rate_limit_per_hour' => '100',
'digest_mode_enabled' => '0',
'digest_send_time' => '08:00',
'notify_admin_on_payment' => '1',
'notify_guardian_on_enrollment' => '1',
'payment_reminder_days_before' => '3',
// pricing
'global_max_discount' => '50',
'allow_price_override' => '0',
'auto_apply_family_discount' => '1',
'family_discount_start_child' => '2',
'trial_period_days' => '7',
'early_enrollment_days' => '14',
'coupon_max_uses_default' => '100',
// enrollment
'allow_waitlist' => '1',
'max_waitlist_per_group' => '10',
'auto_promote_waitlist' => '1',
'require_medical_report' => '0',
'require_guardian_for_minors' => '1',
'minor_age_threshold' => '18',
'max_groups_per_participant' => '5',
'allow_transfer_between_groups' => '1',
'freeze_max_days' => '30',
'freeze_max_times' => '2',
'enrollment_expiry_days' => '30',
];
public function mount(): void
......@@ -131,6 +213,7 @@ public function render()
'financial' => __('مالي'),
'attendance' => __('الحضور'),
'notifications' => __('الإشعارات'),
'pricing' => __('التسعير'),
'enrollment' => __('التسجيل'),
];
......
......@@ -43,6 +43,7 @@ public function run(): void
['group' => 'financial', 'key' => 'wallet_enabled', 'value' => '1', 'type' => 'boolean', 'description_ar' => 'تفعيل نظام المحفظة الإلكترونية'],
['group' => 'financial', 'key' => 'installment_late_fee', 'value' => '500', 'type' => 'integer', 'description_ar' => 'غرامة التأخير على الأقساط (بالقروش)'],
['group' => 'financial', 'key' => 'auto_overdue_after_days', 'value' => '3', 'type' => 'integer', 'description_ar' => 'عدد الأيام بعد تاريخ الاستحقاق لتحويل الفاتورة لمتأخرة'],
['group' => 'financial', 'key' => 'platform_fee_customer_pays', 'value' => '1', 'type' => 'boolean', 'description_ar' => 'رسوم المنصة يدفعها العميل (مفعّل: تُضاف للإجمالي — معطّل: تُخصم من إيراد الأكاديمية)'],
// Attendance
['group' => 'attendance', 'key' => 'participant_grace_period_minutes', 'value' => '15', 'type' => 'integer', 'description_ar' => 'فترة السماح بالتأخير للمشاركين (بالدقائق)'],
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment