البدء السريع
الـ Base URL: https://financial.tadbeer.sa/api/v1
- اطلب OTP:
POST /auth/request-otpببعت{ "email": "..." } - تحقّق:
POST /auth/verify-otpببعت الـ email + code، تستلم Bearer token - استخدم الـ token: في كل request:
Authorization: Bearer <token> - لا تنسى: Header
Accept: application/jsonفي كل request
دليل الرموز
POST إنشاء / إجراء
PUT تحديث كامل
PATCH تحديث جزئي
DELETE حذف
🔑 Token يحتاج Bearer token
⭐ Plan يحتاج خطة معينة
🛡️ Admin role=admin فقط
- الفايدة (Purpose): ليه الـ endpoint ده موجود وإيه القيمة اللي بيقدّمها.
- إمتى تستخدمه: السيناريو العملي في الـ UI/Flow.
- الحقول (Fields): شرح كل حقل في الـ request body — إلزامي/اختياري ومعناه.
- ملاحظات (Notes): تفاصيل مهمة (rate limits, edge cases, gotchas).
تدفّق الـ Authentication كامل
دي السلسلة الكاملة من تسجيل الدخول لاستخدام الـ API:
# 1. Request OTP — يبعت OTP للإيميل
curl -X POST https://financial.tadbeer.sa/api/v1/auth/request-otp \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"email": "your@email.com"}'
# الـ response:
# { "message": "تم إرسال رمز التحقق...", "email": "your@email.com" }
# 2. Check email — افتح storage/logs/laravel.log في dev mode
# 3. Verify OTP — يرجّع Bearer token
curl -X POST https://financial.tadbeer.sa/api/v1/auth/verify-otp \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"email": "your@email.com", "code": "12345678", "device_name": "my-app"}'
# الـ response:
# { "token": "1|abc...xyz", "token_type": "Bearer", "user": {...} }
# 4. استخدم الـ token في كل request
curl https://financial.tadbeer.sa/api/v1/auth/me \
-H "Accept: application/json" \
-H "Authorization: Bearer 1|abc...xyz"
# 5. Logout لما تخلّص
curl -X POST https://financial.tadbeer.sa/api/v1/auth/logout \
-H "Accept: application/json" \
-H "Authorization: Bearer 1|abc...xyz"
1. Authentication
تسجيل دخول بـ OTP عبر الإيميل — يرجّع Sanctum Bearer token
/api/v1/auth/request-otp
🔓 Public
الوصف: يرسل رمز تحقق (OTP) من 8 أرقام إلى البريد الإلكتروني للمستخدم.
الفايدة (Purpose)
الخطوة الأولى في تسجيل الدخول. لو المستخدم جديد (إيميل غير مسجّل) يتم إنشاء account له تلقائياً.
إمتى تستخدمه
لما المستخدم يدخل إيميله في شاشة الـ Login. اطلب الـ OTP، خبّيه من المستخدم، انتظر يدخله في الخطوة التالية.
{
"email": "admin@tadbeer.sa"
}
شرح الحقول (1)
email |
إلزامي — البريد الإلكتروني الصحيح للمستخدم. لو غير مسجّل، يتم إنشاء حساب جديد. |
|---|
{
"message": "تم إرسال رمز التحقق إلى بريدك الإلكتروني.",
"email": "admin@tadbeer.sa",
"dev_otp": "33029284",
"dev_note": "الـ OTP ظاهر هنا فقط في بيئة التطوير — في production لازم تيجي من الإيميل.",
"expires_at": "2026-05-19T06:20:45+00:00"
}
ملاحظات مهمة
- ⏱️ الـ OTP صالح لمدة **10 دقائق فقط**.
- 🚫 Rate limit: **10 محاولات في الدقيقة** لكل IP/email. لو تجاوزت ترجع `429 Too Many Requests`.
- 🛠️ **في بيئة التطوير (APP_ENV != production)** الـ OTP بيتبعت في الـ response فيه field اسمه `dev_otp` عشان تختبر بدون ما تفتح الإيميل.
- 🚀 **في الإنتاج** الـ `dev_otp` و `dev_note` و `expires_at` بيتشالوا — الـ OTP بييجي بس عبر الإيميل.
- 📧 محلياً، الإيميل بيتسجّل في `storage/logs/laravel.log` بدل ما يتبعت فعلاً (MAIL_MAILER=log).
/api/v1/auth/verify-otp
🔓 Public
الوصف: يتحقق من صحة الـ OTP ويرجّع Bearer token لاستخدامه في كل الـ requests القادمة.
الفايدة (Purpose)
إصدار Sanctum token مرتبط بالمستخدم. الـ token هو الـ credential الوحيد بعد كده — احفظه في secure storage (Keychain/iOS, EncryptedSharedPreferences/Android, HttpOnly cookie/Web).
إمتى تستخدمه
بعد ما المستخدم يستلم الـ OTP في إيميله ويدخله في شاشة التحقق.
{
"email": "admin@tadbeer.sa",
"code": "12345678",
"device_name": "mobile-app"
}
شرح الحقول (3)
email |
إلزامي — نفس الإيميل اللي طلبت له OTP. |
|---|---|
code |
إلزامي — الـ 8 أرقام اللي وصلت في الإيميل. |
device_name |
اختياري — اسم الجهاز/التطبيق (مثل `iPhone 14 Pro`, `Web Browser`, `postman`). مفيد عشان تشوف كل الـ tokens النشطة وتلغي token معيّن. |
{
"token": "1|abc...xyz",
"token_type": "Bearer",
"user": {
"id": 1,
"email": "admin@tadbeer.sa",
"roles": [
"admin"
],
"current_plan": "premium"
}
}
ملاحظات مهمة
- ✅ بعد التحقق الناجح، يتم **مسح الـ OTP** من قاعدة البيانات (مرة استخدام واحدة).
- ✅ يتم تأكيد الإيميل تلقائياً (`email_verified_at`).
- 🔐 الـ token format: `<id>|<random_string>` — الجزء قبل `|` هو الـ id والجزء بعده هو الـ secret.
/api/v1/auth/me
🔑 Token
الوصف: يرجّع بيانات المستخدم الحالي المرتبط بالـ token.
الفايدة (Purpose)
تأكد إن الـ token لسه شغّال + احصل على معلومات المستخدم (roles, current_plan) عشان تبني الـ UI بناءً عليها.
إمتى تستخدمه
في أول لما الـ frontend يبدأ — للتأكد إن الـ user مسجّل دخول + لمعرفة صلاحياته. ممكن كمان بعد update لخطة الاشتراك.
{
"user": {
"id": 1,
"email": "admin@tadbeer.sa",
"roles": [
"admin"
],
"current_plan": "premium"
}
}
/api/v1/auth/logout
🔑 Token
الوصف: يلغي **الـ token الحالي فقط** (الـ token اللي بعتته في الـ request).
الفايدة (Purpose)
تسجيل خروج آمن من جهاز واحد بدون التأثير على باقي الأجهزة.
إمتى تستخدمه
لما المستخدم يضغط زرار "Logout" في التطبيق.
ملاحظات مهمة
- الجلسات على الأجهزة الأخرى **تفضل شغّالة**.
/api/v1/auth/logout-all
🔑 Token
الوصف: يلغي **كل الـ tokens** للمستخدم (تسجيل خروج من كل الأجهزة).
الفايدة (Purpose)
للحماية لو المستخدم شك إن حد دخل على حسابه — يلغي كل الـ sessions النشطة.
إمتى تستخدمه
في إعدادات الحساب: "تسجيل الخروج من كل الأجهزة"، أو بعد تغيير بيانات حساسة.
2. Lookups (Dropdowns)
البيانات الثابتة (dropdowns) المستخدمة في النماذج — متاحة بدون auth
/api/v1/lookups
🔓 Public
الوصف: كل الـ dropdowns في request واحد.
الفايدة (Purpose)
تحميل كل البيانات اللازمة لشاشة تسجيل المنشأة دفعة واحدة — يقلل عدد الـ API calls من 7+ لواحد.
إمتى تستخدمه
في بداية شاشة "تسجيل منشأة جديدة" — استدعيه مرة واحدة واحفظ النتيجة في memory/state عشان تستخدمها في كل الـ dropdowns.
{
"data_entries": "[4 items] — صفة مدخل البيانات (صاحب المنشأة، مدير مالي، محاسب، أخرى)",
"main_activities": "[8 items] — الأنشطة الرئيسية (المطاعم، العقاري، الطبي، إلخ)",
"sub_activities": "[33 items] — كل الأنشطة الفرعية (parent_id يربطها بالنشاط الرئيسي)",
"cities": "[16 items] — المدن السعودية + خيار \"أخرى\"",
"facility_sizes": "[6 items] — أحجام المنشأة حسب عدد الموظفين",
"facility_ages": "[5 items] — عمر المنشأة",
"filter_by_outlets": "[3 items] — نوع منفذ البيع (أرضي\/إلكتروني\/كلاهما)",
"products": "[26 items] — قائمة المنتجات (للأنشطة الصناعية والتجارية)"
}
ملاحظات مهمة
- 💡 كل entry فيه `id` + `titles: {ar, en}` + `title` (باللغة الحالية حسب Accept-Language).
- 🌐 تقدر تستخدم header `Accept-Language: en` لو عايز الإنجليزي.
/api/v1/lookups/sub-activities
🔓 Public
الوصف: الأنشطة الفرعية حسب النشاط الرئيسي المختار.
الفايدة (Purpose)
تنفيذ **Cascading dropdown** — لما المستخدم يختار النشاط الرئيسي تظهر الأنشطة الفرعية المرتبطة فقط.
إمتى تستخدمه
في حدث `change` على dropdown الـ main_activity_id. اعمل request وحدّث الـ sub_activity_id options.
main_activity_id |
1 — id النشاط الرئيسي |
|---|
{
"data": "[N items] — الأنشطة الفرعية اللي parent_id بتاعتها = main_activity_id"
}
/api/v1/lookups/products
🔓 Public
الوصف: قائمة الـ 26 منتج كاملة.
الفايدة (Purpose)
استدعاء قائمة المنتجات بمفردها لما النشاط المختار صناعي أو تجاري.
إمتى تستخدمه
لو محتاج المنتجات بس بدون باقي الـ lookups — مفيد لشاشة منفصلة لإدارة منتجات المنشأة.
ملاحظات مهمة
- تظهر للمستخدم فقط لو اختار نشاط من نوع "الصناعة" أو "التجارية".
3. Plans (الخطط)
عرض الخطط المتاحة للمستخدم
/api/v1/plans
🔓 Public
الوصف: كل الخطط النشطة مرتبة بالـ order.
الفايدة (Purpose)
عرض الخطط في صفحة "الاشتراكات" أو "الترقية".
إمتى تستخدمه
صفحة pricing/upgrade — قبل ما المستخدم يقرر يشترك.
{
"data": "[4 items] — كل خطة فيها: slug, ar_title, en_title, indicators_count, features {portfolio, year_changes, financing}, price"
}
/api/v1/plans/{plan}
🔓 Public
الوصف: تفاصيل خطة واحدة بالـ id.
الفايدة (Purpose)
صفحة تفاصيل الخطة قبل الاشتراك.
إمتى تستخدمه
لما المستخدم يضغط على خطة معينة لمعرفة تفاصيلها كاملة.
4. Company (المنشأة)
إدارة منشأة المستخدم — واحدة فقط لكل user
/api/v1/companies
🔑 Token
الوصف: منشأة المستخدم الحالي مع كل الـ relations + كل الـ accounts (السنوات المالية).
الفايدة (Purpose)
تحميل البيانات الكاملة للمنشأة في صفحة "ملفي" أو لما تبدأ التطبيق.
إمتى تستخدمه
بعد تسجيل الدخول مباشرة، للتأكد إن المستخدم له منشأة. لو ترجع `404` معناه لازم تعرض شاشة "سجّل منشأتك".
{
"data": "Company object مع: data_entry, main_activity, sub_activity, facility_size, facility_age, city, filter_by_outlet, products[], accounts[]"
}
/api/v1/companies
🔑 Token
الوصف: تسجيل منشأة جديدة (مرة واحدة فقط).
الفايدة (Purpose)
الخطوة الأولى لكل مستخدم بعد تسجيل الدخول. لو حاول يعمل create مرتين يرجّع `409 Conflict`.
إمتى تستخدمه
في شاشة "تسجيل منشأة جديدة" أول مرة المستخدم يدخل التطبيق.
{
"name": "شركتي التجارية",
"data_entry_id": 1,
"main_activity_id": 9,
"sub_activity_id": 10,
"facility_size_id": null,
"city_id": null,
"other_city": null,
"facility_age_id": null,
"filter_by_outlet_id": null,
"portfolio_code": null,
"excerpt": "نبذة عن المنشأة",
"agreement": true,
"product_ids": [
1,
2,
3
]
}
شرح الحقول (13)
name |
اختياري — اسم تجاري للمنشأة. لو فاضي يتعرض كـ "منشأة #ID". |
|---|---|
data_entry_id |
إلزامي — id من lookups.data_entries — صفة من يدخل البيانات. |
main_activity_id |
إلزامي — id من lookups.main_activities — النشاط الرئيسي. |
sub_activity_id |
إلزامي — id من lookups.sub_activities (parent_id لازم = main_activity_id). |
facility_size_id |
اختياري — حجم المنشأة. مهم للمقارنة في التقارير. |
city_id |
اختياري — المدينة. لو اخترت "أخرى" استخدم `other_city` لاسم نصي. |
other_city |
اختياري — اسم مدينة نصياً لو غير موجودة في القائمة. |
facility_age_id |
اختياري — عمر المنشأة. مهم للمقارنة. |
filter_by_outlet_id |
اختياري — نوع منفذ البيع. |
portfolio_code |
اختياري — كود محفظة خاصة (لـ Premium plan فقط) — لربط عدة منشآت بمحفظة. |
excerpt |
اختياري — وصف مختصر. |
agreement |
إلزامي — لازم `true` (موافقة على شروط الاستخدام). |
product_ids |
اختياري — array بـ ids المنتجات (للأنشطة الصناعية/التجارية فقط). |
ملاحظات مهمة
- ⚠️ كل مستخدم له منشأة واحدة فقط. لو حاولت تعمل تانية يرجّع `409`.
- 🛒 `product_ids` مفيد للأنشطة الصناعية أو التجارية لتحديد المنتجات اللي بتتعامل فيها.
/api/v1/companies
🔑 Token
الوصف: تحديث جزئي لبيانات المنشأة.
الفايدة (Purpose)
تعديل بيانات المنشأة بعد التسجيل (مثلاً تغيير الاسم، إضافة كود محفظة، تحديث المدينة).
إمتى تستخدمه
في صفحة "إعدادات المنشأة".
{
"name": "الاسم الجديد",
"excerpt": "نبذة محدّثة"
}
ملاحظات مهمة
- كل الحقول `sometimes` — ابعت اللي عايز تعدّله فقط.
5. Accounts (البيانات المالية السنوية)
إدخالات Excel Sheets 5 و 6 — 24 حقل لكل سنة مالية
كل entry لسنة واحدة، ولكل منشأة. المستخدم يقدر يدخل بيانات سنوات متعددة (سنة سابقة لمقارنتها بالحالية).
/api/v1/accounts
🔑 Token
الوصف: كل البيانات المالية لكل السنوات، مرتبة بالأحدث.
الفايدة (Purpose)
عرض جدول بكل السنوات اللي المستخدم سجّلها + المؤشرات المحسوبة لكل سنة.
إمتى تستخدمه
في صفحة "بياناتي المالية" — جدول للسنوات والمؤشرات لكل سنة.
{
"data": "[N items] — كل entry فيه: الـ 24 حقل + `computed` بـ 10 مؤشرات محسوبة"
}
ملاحظات مهمة
- ✨ كل entry فيه `computed` object فيه: `net_profit`, `profit_margin`, `expenses_ratio`, `marketing_ratio`, `customers_turnover`, `inventory_turnover`, `suppliers_turnover`, `return_on_investment`, `operating_cash_surplus`, `year_end_cash_surplus`
/api/v1/accounts/{year}
🔑 Token
الوصف: بيانات سنة محددة.
الفايدة (Purpose)
تحميل بيانات سنة واحدة لتعديلها أو لعرض تفاصيلها.
إمتى تستخدمه
في شاشة "تعديل بيانات سنة" — استدعي البيانات الحالية قبل عرض الـ form.
{
"data": "Account object كامل مع `computed`"
}
/api/v1/accounts
🔑 Token
الوصف: إنشاء أو تحديث بيانات سنة مالية (24 حقل من Excel Sheet 5).
الفايدة (Purpose)
الـ endpoint الأكثر استخداماً — لإدخال البيانات المالية. لو السنة موجودة بالفعل يتم **تحديث** بدل إنشاء (upsert).
إمتى تستخدمه
في شاشة "إدخال بيانات سنة" — بعد ما المستخدم يملا كل الحقول الإلزامية يضغط حفظ.
{
"fiscal_year": 2024,
"revenue": 1000000,
"purchases": 600000,
"cost": 500000,
"cost_goods_sold": 300000,
"cost_direct_salaries": 150000,
"cost_other_direct": 50000,
"general_expenses": 200000,
"gen_emp_expenses": 100000,
"gen_rent_expenses": 50000,
"gen_admin_expenses": 30000,
"gen_training_expenses": 20000,
"marketing_expenses": 100000,
"mkt_salaries_commissions": 60000,
"mkt_ads_campaigns": 40000,
"fixed_assets": 300000,
"customers_balance": 100000,
"inventory_balance": 200000,
"suppliers_balance": 150000,
"accrued_expenses": 50000,
"loans_balance": 200000,
"property_rights": 500000,
"loans_increase": 50000,
"capital_increase": 100000
}
شرح الحقول (24)
fiscal_year |
إلزامي — السنة المالية (مثلاً 2024). فريدة لكل منشأة. |
|---|---|
revenue |
إلزامي — إجمالي الإيرادات/المبيعات خلال السنة (بدون الضريبة). |
purchases |
اختياري — إجمالي المشتريات من الموردين. مهم! بيدخل في حساب دوران المخزون والموردين. |
cost |
إلزامي (إجمالي) — إجمالي التكلفة (المصروفات المباشرة). |
cost_goods_sold |
جزئي — تكلفة البضاعة المباعة (من البرنامج المحاسبي). |
cost_direct_salaries |
جزئي — رواتب مهنيين/فنيين/عمالة مباشرة. |
cost_other_direct |
جزئي — تكاليف مباشرة أخرى (استشاريين، عقود خدمات). |
general_expenses |
إلزامي (إجمالي) — المصروفات العمومية والإدارية. |
gen_emp_expenses |
جزئي — مصاريف الموظفين الإداريين. |
gen_rent_expenses |
جزئي — مصاريف الإيجارات. |
gen_admin_expenses |
جزئي — مصاريف إدارية متنوعة (رسوم، استشارات، صيانة، نقل، مطبوعات، ماء، كهرباء). |
gen_training_expenses |
جزئي — التطوير والتدريب. |
marketing_expenses |
إلزامي (إجمالي) — مصروفات التسويق. |
mkt_salaries_commissions |
جزئي — رواتب وعمولات التسويق والمبيعات. |
mkt_ads_campaigns |
جزئي — مصاريف المطبوعات والإعلانات والحملات. |
fixed_assets |
إلزامي — الأصول الثابتة (مباني، سيارات، أثاث، أجهزة — بدون الأراضي). يدخل في معادلة الفائض النقدي. |
customers_balance |
إلزامي — رصيد العملاء آخر السنة (مديونيات المبيعات الآجلة). |
inventory_balance |
إلزامي — رصيد المخزون آخر السنة. |
suppliers_balance |
إلزامي — رصيد الموردين آخر السنة (المشتريات الآجلة). |
accrued_expenses |
إلزامي — المصروفات المستحقة (رواتب/إيجارات لم تدفع). تطرح في الفائض النقدي. |
loans_balance |
إلزامي — رصيد القروض آخر السنة. |
property_rights |
إلزامي — رأس المال / حقوق الملكية (رأس المال + أرباح مبقاة). |
loans_increase |
إلزامي — الزيادة في القروض خلال السنة (قروض جديدة). |
capital_increase |
إلزامي — الزيادة في رأس المال خلال السنة. |
ملاحظات مهمة
- 🔄 **Upsert** — لو السنة موجودة يتم update، غير كده create.
- 📊 الحقول "الجزئي" اختيارية لكن مفيدة للـ Premium plan (المؤشرات التحليلية 14-21).
- 💡 الإجمالي ≥ مجموع الجزئيات (مفروض، لكن مفيش validation لذلك).
- 📎 لرفع ملف PDF (القوائم المالية) لازم تستخدم `multipart/form-data` بدل JSON، مع field اسمه `financial_statements_file`.
/api/v1/accounts/{year}
🔑 Token
الوصف: حذف بيانات سنة (soft delete — يمكن استرجاعها).
الفايدة (Purpose)
لو المستخدم أدخل بيانات سنة بالغلط، يقدر يحذفها. الحذف soft delete عشان نقدر نسترجعها من الأدمن لو احتجنا.
إمتى تستخدمه
في زرار "حذف" بجانب كل سنة في جدول البيانات المالية. اعرض confirmation قبل ما تستدعي الـ endpoint.
6. Reports (التقارير)
التقارير الـ 3 من Excel (Sheets 7, 8, 9) — 13 مؤشر لكل تقرير
- **Facility Report**: المنشأة الواحدة vs متوسط القطاع vs الأفضل (Benchmark)
- **Portfolio Report**: المحفظة (مجموعة منشآت) vs متوسط السوق vs الأفضل
- **Market Report**: متوسط السوق vs الأفضل (للجميع، بدون auth)
/api/v1/reports/facility
⭐ Plan: basic+
الوصف: تقرير المنشأة (Excel Sheet 7) — يقارن منشأتك بمتوسط القطاع وأفضل منشأة.
الفايدة (Purpose)
الـ endpoint الأهم للمستخدم — يحلل أداء منشأته. التقرير يرجّع 3 صفوف (my-company / avg / benchmark) × 13 مؤشر.
إمتى تستخدمه
في الصفحة الرئيسية للمستخدم بعد إدخال بيانات سنة. ممكن يفلتر بسنة معينة.
year |
2024 — *اختياري*، لو ما اتبعت يجيب آخر سنة |
|---|
{
"indicators": "[13 definitions] — تعريفات المؤشرات (slug, ar, en, unit, direction)",
"report": {
"my-company": "{revenue, profit_margin, expenses_ratio, ... year_end_cash_surplus}",
"avg": "{...متوسط القطاع لنفس النشاط\/المدينة\/الحجم}",
"benchmark": "{...أعلى قيمة في القطاع لكل مؤشر}"
},
"meta": "{company_id, company_name, fiscal_year}"
}
ملاحظات مهمة
- ⭐ يحتاج **plan: basic أو أعلى** — لو الخطة free يرجّع `403` مع `required_feature: basic`.
- 🎯 الفلترة في الـ avg/benchmark بتكون تلقائية حسب نفس النشاط/المدينة/الحجم/العمر بتاع المنشأة.
/api/v1/reports/portfolio/{portfolio}
⭐ Plan: portfolio+
الوصف: تقرير المحفظة (Excel Sheet 8) — يحلل أداء مجموعة منشآت كمحفظة استثمارية.
الفايدة (Purpose)
للمستثمر اللي عنده عدة منشآت — يشوف أداء المحفظة ككل ومقارنتها بالسوق.
إمتى تستخدمه
في صفحة "تقرير المحفظة" — بعد ما المستخدم ينشئ محفظة ويربطها بمنشآت.
year |
2024 — *اختياري* |
|---|
ملاحظات مهمة
- ⭐ يحتاج **plan: portfolio** — أعلى خطة في المنصة.
- 🔒 المستخدم يقدر يشوف محافظه فقط — لو حاول يشوف محفظة تانية يرجّع `403`.
/api/v1/reports/market
🔓 Public
الوصف: تقرير السوق (Excel Sheet 9) — متوسط السوق vs الأفضل، للجميع.
الفايدة (Purpose)
تقرير عام للجميع (بدون auth) — يخلي زوار الموقع يشوفوا قوة المنصة قبل ما يسجّلوا. كمان مفيد للمسجّلين عشان يبحثوا في قطاع معين.
إمتى تستخدمه
في الصفحة الرئيسية للموقع كـ teaser، أو في شاشة "ابحث في السوق" بفلاتر مختلفة.
main_activity_id |
*اختياري* |
|---|---|
sub_activity_id |
*اختياري* |
facility_size_id |
*اختياري* |
city_id |
*اختياري* |
facility_age_id |
*اختياري* |
filter_by_outlet_id |
*اختياري* |
fiscal_year |
*اختياري* |
ملاحظات مهمة
- 🌍 متاح للجميع — مفيد لـ SEO والـ teaser content.
7. Portfolios (المحافظ الاستثمارية)
مجموعة منشآت يديرها مستخدم واحد — يحتاج plan: portfolio
/api/v1/portfolios
⭐ Plan: portfolio+
الوصف: كل المحافظ بتاعة المستخدم.
الفايدة (Purpose)
عرض قائمة المحافظ في صفحة "محافظي".
{
"data": "[N items] — كل محفظة فيها: name, code (PF-XXXX), companies_count"
}
/api/v1/portfolios
⭐ Plan: portfolio+
الوصف: إنشاء محفظة جديدة.
الفايدة (Purpose)
إضافة محفظة جديدة. الـ code يتم إنشاؤه تلقائياً بصيغة `PF-XXXXXXXX`.
إمتى تستخدمه
لما المستخدم يضغط "محفظة جديدة" في صفحة المحافظ.
{
"name": "محفظة الشرقية"
}
شرح الحقول (1)
name |
إلزامي — اسم المحفظة. |
|---|
/api/v1/portfolios/{portfolio}
⭐ Plan: portfolio+
الوصف: تفاصيل المحفظة + كل الشركات المرتبطة بها.
الفايدة (Purpose)
صفحة عرض المحفظة — تشوف الشركات وتحلل الأداء.
/api/v1/portfolios/{portfolio}/companies
⭐ Plan: portfolio+
الوصف: إضافة شركة للمحفظة.
الفايدة (Purpose)
ربط شركة موجودة بمحفظة. الشركة لازم تكون بتاعة نفس المستخدم.
إمتى تستخدمه
في صفحة المحفظة، زرار "إضافة شركة".
{
"company_id": 1
}
/api/v1/portfolios/{portfolio}/companies/{company}
⭐ Plan: portfolio+
الوصف: إزالة شركة من المحفظة (مش حذف الشركة).
الفايدة (Purpose)
فك الربط بدون حذف الشركة نفسها.
/api/v1/portfolios/{portfolio}
⭐ Plan: portfolio+
الوصف: حذف المحفظة (الشركات تفضل موجودة).
الفايدة (Purpose)
لما المستخدم ميحتاجش المحفظة. الشركات بتاعتها تتفك تلقائياً.
8. Subscriptions (الاشتراكات)
إدارة اشتراك المستخدم
/api/v1/subscriptions
🔑 Token
الوصف: تاريخ اشتراكات المستخدم (الحالية والسابقة).
الفايدة (Purpose)
عرض تاريخ الاشتراكات في صفحة "حسابي".
{
"data": "[N items] — كل اشتراك فيه: plan, starts_at, ends_at, is_active, is_currently_active"
}
/api/v1/subscriptions
🔑 Token
الوصف: طلب اشتراك في خطة.
الفايدة (Purpose)
إنشاء طلب اشتراك. الـ workflow:
1. لو الخطة `price = 0` (مجاني) → يتفعّل تلقائياً (`is_active = true`)
2. لو الخطة مدفوعة → يتسجّل كـ pending وينتظر أدمن يفعّله
إمتى تستخدمه
لما المستخدم يضغط "اشترك في هذه الخطة" في صفحة Plans.
{
"plan_id": 3,
"notes": "محتاج Premium لاستخدام محاسبي"
}
شرح الحقول (2)
plan_id |
إلزامي — id الخطة المطلوبة. |
|---|---|
notes |
اختياري — ملاحظة للأدمن (مثلاً رقم العملية بعد الدفع). |
ملاحظات مهمة
- ⏳ بعد الإنشاء، الـ response.message هتقول "تم الإرسال" أو "ينتظر تفعيل" حسب نوع الخطة.
- 💳 المستخدم لازم يدفع خارج المنصة (تحويل بنكي مثلاً) ويبعت ملاحظة، ثم الأدمن يفعّل يدوياً.
9. Admin (لوحة الإدارة)
كل الـ endpoints بتاع الإدارة — يحتاج role: admin
/api/v1/admin/dashboard
🛡️ Admin only
الوصف: إحصائيات عامة عن المنصة.
الفايدة (Purpose)
صفحة الـ overview في لوحة الأدمن.
{
"counts": "{users, companies, accounts, portfolios, products, plans, active_subscriptions, pending_subscriptions}"
}
/api/v1/admin/subscriptions
🛡️ Admin only
الوصف: كل الاشتراكات (paginated).
الفايدة (Purpose)
صفحة إدارة الاشتراكات — اللي فيها الأدمن يشوف الاشتراكات المعلّقة ويفعّلها بعد تأكيد الدفع.
status |
*اختياري* — `active` أو `pending` للفلترة |
|---|
/api/v1/admin/subscriptions
🛡️ Admin only
الوصف: إنشاء اشتراك يدوي لمستخدم.
الفايدة (Purpose)
الأدمن يقدر يضيف اشتراك لمستخدم بدون ما يكون طلبه (مثلاً عميل خاص).
{
"user_id": 1,
"plan_id": 3,
"starts_at": "2026-05-19",
"ends_at": null,
"is_active": true,
"notes": "تفعيل من أدمن"
}
/api/v1/admin/subscriptions/{subscription}/toggle
🛡️ Admin only
الوصف: تفعيل أو إلغاء تفعيل اشتراك (toggle).
الفايدة (Purpose)
**أهم action في لوحة الأدمن** — تفعيل الاشتراكات المدفوعة المعلّقة بعد تأكيد الدفع.
إمتى تستخدمه
الأدمن يستقبل تأكيد الدفع → يدخل صفحة الاشتراكات → يضغط "تفعيل" بجانب الاشتراك.
/api/v1/admin/subscriptions/{subscription}
🛡️ Admin only
الوصف: حذف اشتراك.
/api/v1/admin/plans
🛡️ Admin only
الوصف: كل الخطط (بما في ذلك الـ inactive).
الفايدة (Purpose)
صفحة إدارة الخطط — تعديل الأسعار، إضافة خطط جديدة، تعطيل خطة قديمة.
/api/v1/admin/plans
🛡️ Admin only
الوصف: إنشاء خطة جديدة.
الفايدة (Purpose)
لإضافة خطة مخصصة (مثلاً Enterprise، أو Trial 7 أيام).
{
"slug": "enterprise",
"en_title": "Enterprise",
"ar_title": "مؤسسي",
"description": "خطة للشركات الكبيرة",
"indicators_count": 21,
"has_portfolio": true,
"has_year_changes": true,
"has_financing": true,
"price": 999,
"is_active": true,
"order": 5
}
/api/v1/admin/plans/{plan}
🛡️ Admin only
الوصف: تحديث خطة موجودة.
الفايدة (Purpose)
مثلاً تغيير سعر، أو تعطيل خطة قديمة، أو تعديل المميزات.
/api/v1/admin/plans/{plan}
🛡️ Admin only
الوصف: حذف خطة.
ملاحظات مهمة
- ⚠️ احذر — لو فيه اشتراكات نشطة على الخطة دي.
/api/v1/admin/products
🛡️ Admin only
الوصف: كل المنتجات (paginated).
الفايدة (Purpose)
إدارة قائمة المنتجات الـ 26 اللي تظهر للأنشطة الصناعية والتجارية.
/api/v1/admin/products
🛡️ Admin only
الوصف: إضافة منتج جديد.
{
"ar_title": "منتج جديد",
"en_title": "New Product",
"order": 27
}
/api/v1/admin/products/{product}
🛡️ Admin only
الوصف: تحديث منتج.
/api/v1/admin/products/{product}
🛡️ Admin only
الوصف: حذف منتج.
/api/v1/admin/constants
🛡️ Admin only
الوصف: كل الـ lookups (الـ dropdowns).
الفايدة (Purpose)
إدارة كل الـ dropdowns: الأنشطة، المدن، أحجام المنشآت، إلخ.
post_type |
*اختياري* — مثلاً `cities`, `main_activities`, `sub_activities` |
|---|---|
parent_id |
*اختياري* — للفلترة على الـ children (مثلاً sub_activities of activity X) |
/api/v1/admin/constants
🛡️ Admin only
الوصف: إضافة قيمة lookup جديدة.
الفايدة (Purpose)
مثلاً إضافة مدينة جديدة، أو نشاط فرعي جديد.
{
"ar_title": "نشاط جديد",
"en_title": "New Activity",
"post_type": "sub_activities",
"parent_id": 5,
"order": 99
}
/api/v1/admin/constants/{constant}
🛡️ Admin only
الوصف: تحديث lookup.
/api/v1/admin/constants/{constant}
🛡️ Admin only
الوصف: حذف lookup (soft delete).
/api/v1/admin/companies
🛡️ Admin only
الوصف: كل الشركات (paginated).
الفايدة (Purpose)
الأدمن يشوف كل الشركات المسجّلة في المنصة + يقدر يبحث.
search |
*اختياري* — بحث في اسم الشركة أو الـ code |
|---|
/api/v1/admin/companies/{company}
🛡️ Admin only
الوصف: تفاصيل شركة محددة + كل بياناتها المالية.
/api/v1/admin/companies/{company}
🛡️ Admin only
الوصف: حذف شركة (soft delete).
/api/v1/admin/users
🛡️ Admin only
الوصف: كل المستخدمين (paginated).
الفايدة (Purpose)
إدارة المستخدمين — عرض، بحث، فلتر بالـ role.
search |
*اختياري* — بحث في email أو name |
|---|---|
role |
*اختياري* — admin أو user |
{
"data": "[{ id, name, email, roles, current_plan, company, active_subscription }]"
}
/api/v1/admin/users
🛡️ Admin only
الوصف: إنشاء مستخدم جديد.
الفايدة (Purpose)
إضافة مستخدم يدوياً (مثلاً موظف جديد، أو مستخدم خاص).
{
"name": "اسم المستخدم",
"email": "new@tadbeer.sa",
"password": "secret-password",
"roles": [
"user"
]
}
شرح الحقول (4)
name |
إلزامي — اسم المستخدم. |
|---|---|
email |
إلزامي — لازم يكون فريد. |
password |
اختياري — لو فاضي يتم توليده عشوائياً (المستخدم يستخدم OTP). |
roles |
اختياري — array من admin/user. |
/api/v1/admin/users/{user}
🛡️ Admin only
الوصف: تفاصيل كاملة عن مستخدم.
الفايدة (Purpose)
صفحة تفاصيل المستخدم: roles + company + subscriptions + portfolios + active tokens.
{
"data": "{ id, name, email, email_verified_at, roles, current_plan, has_company, company, subscriptions_count, subscriptions, active_subscription, portfolios_count, tokens_count, created_at }"
}
/api/v1/admin/users/{user}
🛡️ Admin only
الوصف: تحديث بيانات المستخدم.
الفايدة (Purpose)
تعديل الاسم/الإيميل/كلمة المرور/الأدوار — كل الحقول `sometimes`.
{
"name": "اسم محدّث",
"email": "updated@tadbeer.sa",
"roles": [
"admin",
"user"
]
}
/api/v1/admin/users/{user}
🛡️ Admin only
الوصف: حذف مستخدم + إلغاء كل tokens.
ملاحظات مهمة
- ⚠️ الأدمن مش قادر يحذف حسابه الخاص (يرجع 422).
/api/v1/admin/users/{user}/roles
🛡️ Admin only
الوصف: إضافة دور للمستخدم.
الفايدة (Purpose)
ترقية مستخدم لأدمن مثلاً.
{
"role": "admin"
}
/api/v1/admin/users/{user}/roles/{role}
🛡️ Admin only
الوصف: إزالة دور من المستخدم.
الفايدة (Purpose)
إلغاء صلاحية الأدمن مثلاً.
/api/v1/admin/users/{user}/revoke-tokens
🛡️ Admin only
الوصف: إلغاء كل الـ tokens النشطة للمستخدم (force logout).
الفايدة (Purpose)
لو فيه شك في اختراق حساب — يجبر المستخدم على تسجيل دخول من جديد.
{
"message": "...",
"revoked_tokens": 3
}
/api/v1/admin/companies/{company}/accounts
🛡️ Admin only
الوصف: كل السنوات المالية لشركة محددة.
الفايدة (Purpose)
الأدمن يشوف كل البيانات المالية لأي شركة (مش بس بتاعته). كل entry فيه `computed` بالمؤشرات المحسوبة.
إمتى تستخدمه
في صفحة "تفاصيل شركة" في لوحة الأدمن — لمراجعة بيانات الشركة قبل تفعيل اشتراك أو حل مشكلة.
{
"company": {
"id": 1,
"name": "Test Co"
},
"data": "[N items] — كل سنة مع computed indicators"
}
/api/v1/admin/companies/{company}/accounts/{year}
🛡️ Admin only
الوصف: بيانات سنة مالية واحدة لشركة محددة.
الفايدة (Purpose)
استعراض تفاصيل سنة معينة لأي شركة.
/api/v1/admin/companies/{company}/accounts/{year}
🛡️ Admin only
الوصف: حذف بيانات سنة (soft delete).
الفايدة (Purpose)
لو الشركة دخلت بيانات غلط، الأدمن يقدر يحذفها.
/api/v1/admin/companies/{company}/report
🛡️ Admin only
الوصف: تقرير المنشأة لأي شركة (Sheet 7 — 13 مؤشر).
الفايدة (Purpose)
الأدمن يقدر يشوف تقرير أي شركة بدون قيود الـ plan. response.meta فيه `owner_email` لمعرفة المالك.
إمتى تستخدمه
لـ debugging أو دعم عملاء — تشوف نفس التقرير اللي العميل بيشوفه.
year |
2024 — *اختياري* |
|---|
{
"indicators": "[13 definitions]",
"report": {
"my-company": "...",
"avg": "...",
"benchmark": "..."
},
"meta": {
"company_id": 1,
"company_name": "...",
"owner_email": "...",
"fiscal_year": 2024
}
}
/api/v1/admin/portfolios/{portfolio}/report
🛡️ Admin only
الوصف: تقرير المحفظة لأي محفظة (Sheet 8).
الفايدة (Purpose)
الأدمن يشوف تقرير المحفظة لأي مستخدم بدون قيود.
year |
2024 — *اختياري* |
|---|
/api/v1/admin/users/{user}/report
🛡️ Admin only
الوصف: اختصار: تقرير المنشأة من user_id مباشرة.
الفايدة (Purpose)
بدلاً من جلب company_id الأول، يقدر تجيب التقرير من user_id مباشرة. مفيد لما تكون شغّال في صفحة "تفاصيل مستخدم".
year |
2024 — *اختياري* |
|---|
ملاحظات مهمة
- لو المستخدم ما عندوش منشأة → 404 مع رسالة واضحة.
/api/v1/admin/portfolios
🛡️ Admin only
الوصف: كل المحافظ عبر كل المستخدمين (paginated).
الفايدة (Purpose)
الأدمن يشوف كل المحافظ الموجودة في المنصة + إحصائيات.
search |
*اختياري* — بحث في name أو code |
|---|---|
user_id |
*اختياري* — فلتر بمستخدم معيّن |
/api/v1/admin/portfolios/{portfolio}
🛡️ Admin only
الوصف: تفاصيل محفظة + المالك + الشركات بداخلها.
الفايدة (Purpose)
استعراض كامل لمحفظة + بيانات مالكها.
/api/v1/admin/portfolios/{portfolio}
🛡️ Admin only
الوصف: حذف محفظة (الشركات بداخلها تتفك بدون حذف).
أكواد الأخطاء (HTTP Status Codes)
كل الـ errors بترجع بـ JSON بنفس الشكل الموحّد: {"message": "...", "errors": {...}}
| Code | المعنى | السبب الشائع | مثال response |
|---|---|---|---|
200 |
نجاح | الـ request اشتغل تمام | {"data": {...}} |
201 |
تم الإنشاء | POST لإنشاء resource جديد نجح | {"data": {...}} |
401 |
Unauthenticated | الـ token مفقود أو منتهي أو غلط | {"message": "Unauthenticated"} |
403 |
Forbidden | الخطة الحالية لا تسمح بهذا الـ endpoint | {"message": "...", "required_feature": "portfolio", "current_plan": "basic"} |
404 |
Not Found | الـ resource غير موجود (مثلاً user مفيش عنده منشأة) | {"message": "..."} |
409 |
Conflict | محاولة إنشاء resource موجود بالفعل (مثلاً منشأة تانية) | {"message": "Company already registered"} |
422 |
Validation Failed | الـ request body فيه أخطاء (missing fields, wrong types) | {"message": "...", "errors": {"email": ["..."]}} |
429 |
Rate Limited | تجاوزت العدد المسموح من الـ requests | {"message": "...", "retry_after": 60} |
500 |
Server Error | خطأ في السيرفر — راجع logs | — |
المؤشرات الـ 13 (من Excel Sheet 7)
دي المؤشرات اللي بتطلع في كل التقارير. كل مؤشر له unit (amount/ratio/percent) و direction (higher_better/lower_better).
| # | المؤشر | الـ Slug | الوحدة | الاتجاه الأفضل |
|---|---|---|---|---|
| 1 | الإيرادات (المبيعات) Revenue |
revenue |
amount | ⬆️ أعلى أفضل |
| 2 | هامش ربح المبيعات Profit Margin |
profit_margin |
percent | ⬆️ أعلى أفضل |
| 3 | نسبة المصروفات / الإيرادات Expenses / Revenue |
expenses_ratio |
percent | ⬇️ أقل أفضل |
| 4 | مصروفات التسويق Marketing Expenses |
marketing_ratio |
percent | ⬇️ أقل أفضل |
| 5 | صافي الربح / الخسارة Net Profit / Loss |
net_profit |
amount | ⬆️ أعلى أفضل |
| 6 | معدل دوران مديونيات العملاء Customer Receivables Turn |
customers_turnover |
ratio | ⬆️ أعلى أفضل |
| 7 | معدل دوران المخزون Inventory Turnover |
inventory_turnover |
ratio | ⬆️ أعلى أفضل |
| 8 | معدل دوران مديونيات الموردين Suppliers Payables Turn |
suppliers_turnover |
ratio | ⬆️ أعلى أفضل |
| 9 | رصيد القروض Loans Balance |
loans_balance |
amount | ⬆️ أعلى أفضل |
| 10 | رأس المال (حقوق الملكية) Capital / Equity |
property_rights |
amount | ⬇️ أقل أفضل |
| 11 | العائد / الاستثمار Return on Investment |
roi |
percent | ⬆️ أعلى أفضل |
| 12 | الفائض النقدي من التشغيل Operating Cash Surplus |
operating_cash_surplus |
amount | ⬆️ أعلى أفضل |
| 13 | الفائض النقدي آخر السنة Year-end Cash Surplus |
year_end_cash_surplus |
amount | ⬆️ أعلى أفضل |
- دوران المخزون =
purchases / inventory_balance(كانrevenue/inventoryفي النسخة القديمة) - دوران الموردين =
purchases / suppliers_balance(كانrevenue/suppliers) - 🆕 الفائض النقدي من التشغيل =
net_profit + (fixed_assets × 0.10) − accrued_expenses - 🆕 الفائض النقدي آخر السنة =
operating_cash + loans_increase + capital_increase
المعادلات الحسابية بالتفصيل
كل العمليات الحسابية المستخدمة في حساب المؤشرات والمقارنات
1. الحقول المُدخَلة من المستخدم (Inputs)
كل الحسابات بتعتمد على 24 حقل بيدخلهم المستخدم لكل سنة مالية:
| المتغير | المعنى |
|---|---|
revenue | إجمالي الإيرادات (المبيعات) خلال السنة — إلزامي |
purchases | إجمالي المشتريات من الموردين خلال السنة |
cost | التكلفة (المصروفات المباشرة) — إلزامي |
general_expenses | المصروفات العمومية والإدارية — إلزامي |
marketing_expenses | مصروفات التسويق — إلزامي |
fixed_assets | الأصول الثابتة (بدون الأراضي) — إلزامي |
customers_balance | رصيد العملاء آخر السنة |
inventory_balance | رصيد المخزون آخر السنة |
suppliers_balance | رصيد الموردين آخر السنة |
accrued_expenses | المصروفات المستحقة (لم تدفع) |
loans_balance | رصيد القروض آخر السنة |
property_rights | رأس المال / حقوق الملكية |
loans_increase | الزيادة في القروض خلال السنة |
capital_increase | الزيادة في رأس المال خلال السنة |
2. معادلات المؤشرات الـ 13
كل المؤشرات بتتحسب في App\Helpers\CompanyHelper::indicators():
1️⃣ الإيرادات (Revenue)
revenue = revenueقيمة مباشرة من الإدخال — مقدار ر.س.
2️⃣ هامش ربح المبيعات (Profit Margin)
profit_margin = (revenue - cost) / revenueنسبة (0–1) → تعرض كنسبة مئوية. مثال: 0.5 = 50%. الأعلى أفضل.
📌 لو revenue = 0 → النتيجة 0 (حماية من القسمة على صفر).
3️⃣ نسبة المصروفات / الإيرادات (Expenses Ratio)
expenses_ratio = (cost + general_expenses + marketing_expenses) / revenueنسبة من الإيرادات تذهب للمصروفات. الأقل أفضل.
4️⃣ نسبة مصروفات التسويق (Marketing Ratio)
marketing_ratio = marketing_expenses / revenueنسبة مصاريف التسويق من الإيرادات. الأقل أفضل.
5️⃣ صافي الربح/الخسارة (Net Profit) ⭐
net_profit = revenue - cost - general_expenses - marketing_expensesالمبلغ بالـ ر.س. أساسي لحساب ROI و Operating Cash Surplus.
6️⃣ معدل دوران مديونيات العملاء (Customers Turnover)
customers_turnover = revenue / customers_balanceعدد مرات تحصيل مديونيات العملاء سنوياً. الأعلى أفضل.
7️⃣ معدل دوران المخزون (Inventory Turnover) — ⚠️ تغيّر
inventory_turnover = purchases / inventory_balanceتغيير مهم: في النسخة القديمة كانت
revenue / inventory_balance، الآن استبدلناها بـ purchases لأنها الأدق محاسبياً.
8️⃣ معدل دوران مديونيات الموردين (Suppliers Turnover) — ⚠️ تغيّر
suppliers_turnover = purchases / suppliers_balanceتغيير مهم: كانت
revenue / suppliers_balance، الآن أصبحت تستخدم المشتريات.
9️⃣ رصيد القروض (Loans Balance)
loans_balance = loans_balanceقيمة مباشرة من الإدخال.
🔟 رأس المال (Property Rights / Capital)
property_rights = property_rightsقيمة مباشرة من الإدخال — رأس المال + الأرباح المبقاة.
1️⃣1️⃣ العائد على الاستثمار (ROI)
roi = net_profit / property_rights = (revenue - cost - general_expenses - marketing_expenses) / property_rightsنسبة (0–1) — تعرض كنسبة مئوية. الأعلى أفضل.
1️⃣2️⃣ الفائض النقدي من التشغيل (Operating Cash Surplus) 🆕
operating_cash_surplus = net_profit + (fixed_assets × 0.10) - accrued_expensesالمبلغ النقدي المتاح من العمليات التشغيلية.
التحليل المنطقي:
net_profit: الربح الصافي+ (fixed_assets × 0.10): إضافة استهلاك تقديري (10% من الأصول الثابتة) باعتباره مصروف غير نقدي- accrued_expenses: طرح المصروفات المستحقة (لم تُدفع نقداً)
1️⃣3️⃣ الفائض النقدي آخر السنة (Year-end Cash Surplus) 🆕
year_end_cash_surplus = operating_cash_surplus + loans_increase + capital_increase
= [net_profit + (fixed_assets × 0.10) - accrued_expenses]
+ loans_increase + capital_increase
إجمالي السيولة آخر السنة بعد إضافة التمويلات الجديدة.
3. عمليات التجميع (Aggregations)
كل تقرير بيقارن منشأة المستخدم بـ متوسط القطاع وأفضل منشأة. الـ aggregations بتتم في SQL:
متوسط القطاع (avg)
SELECT
AVG(revenue) as revenue,
AVG(cost) as cost,
AVG(purchases) as purchases,
AVG(general_expenses) as general_expenses,
...
FROM accounts
INNER JOIN companies ON companies.id = accounts.company_id
WHERE companies.deleted_at IS NULL
AND accounts.deleted_at IS NULL
AND companies.main_activity_id = ?
AND companies.sub_activity_id = ?
AND companies.facility_size_id = ?
AND companies.city_id = ?
AND companies.facility_age_id = ?
يحسب متوسط كل حقل لمنشآت نفس القطاع (نفس النشاط/المدينة/الحجم/العمر).
أفضل منشأة (benchmark / pioneer)
SELECT
MAX(revenue) as revenue,
MAX(cost) as cost,
...
FROM accounts INNER JOIN companies ...
WHERE [same filters as avg]
يحسب القيمة القصوى لكل حقل في نفس القطاع — تمثيل لـ "الرائد".
4. منطق المقارنة (Comparison Logic)
في الـ views/reports، كل قيمة بتتقارن بمتوسط السوق لتحديد إن كانت أعلى/مقاربة/أقل:
// نسبة الفرق
diff_percent = ((my_value - avg_value) / avg_value) × 100
// التصنيف
if (abs(diff_percent) <= 10):
analysis = "مقارب للمتوسط (± 10%)"
color = neutral (gray)
else if (diff_percent > 0):
// قيمتي أعلى من المتوسط
if (indicator.direction === "higher_better"):
analysis = "أعلى من المتوسط ✓"
color = positive (green)
else: // lower_better
analysis = "أعلى من المتوسط ✗"
color = negative (red)
else: // diff_percent < 0
// قيمتي أقل من المتوسط
if (indicator.direction === "lower_better"):
analysis = "أقل من المتوسط ✓"
color = positive (green)
else: // higher_better
analysis = "أقل من المتوسط ✗"
color = negative (red)
أمثلة عملية
| مؤشر | منشأتي | المتوسط | الفرق | الاتجاه | التحليل |
|---|---|---|---|---|---|
| هامش الربح | 50% | 35% | +42.9% | higher_better | أعلى ✓ |
| نسبة المصروفات | 80% | 85% | -5.9% | lower_better | مقارب |
| دوران المخزون | 3x | 5x | -40% | higher_better | أقل ✗ |
| رأس المال | 500K | 600K | -16.6% | lower_better | أقل ✓ |
5. اتجاه كل مؤشر (Direction)
في المؤشرات الـ 13، بعضها "الأعلى أفضل" وبعضها "الأقل أفضل":
| الاتجاه | المؤشرات | السبب |
|---|---|---|
| ⬆️ Higher Better (10) | revenue, profit_margin, net_profit, customers_turnover, inventory_turnover, suppliers_turnover, loans_balance, roi, operating_cash_surplus, year_end_cash_surplus |
كلها مؤشرات على نمو/كفاءة/ربحية أعلى |
| ⬇️ Lower Better (3) | expenses_ratio, marketing_ratio, property_rights |
الأقل = تحكّم أفضل في المصروفات / كفاءة أعلى في استخدام رأس المال |
loans_balance: حالياً مُصنف "higher_better" — قد يحتاج مراجعة (القروض الأقل عادة أفضل، لكن الأكثر يعني وصول أعلى لتمويل).
6. تنسيق الأرقام (Number Formatting)
في CompanyHelper::formatValue():
switch (unit):
case 'percent':
// المؤشرات: profit_margin, expenses_ratio, marketing_ratio, roi
return number_format(value × 100, 2) + '%'
// مثال: 0.4 → "40.00%"
case 'ratio':
// المؤشرات: customers_turnover, inventory_turnover, suppliers_turnover
return number_format(value, 2)
// مثال: 3.5 → "3.50"
case 'amount':
// المؤشرات: revenue, net_profit, loans_balance, property_rights,
// operating_cash_surplus, year_end_cash_surplus
return number_format(value, 2)
// مثال: 1000000 → "1,000,000.00"
7. أين تجد الكود
| الملف | الوظيفة |
|---|---|
app/Helpers/CompanyHelper.php | كل المعادلات الـ 13 + الـ aggregations في indicators() و buildAggregateQuery() |
app/Models/Account.php | نفس المعادلات كـ accessors على Eloquent model (مثلاً $account->net_profit) |
app/Helpers/CompanyHelper::facilityComparison() | تقرير المنشأة: my-company vs avg vs benchmark |
app/Helpers/CompanyHelper::portfolioComparison() | تقرير المحفظة |
app/Helpers/CompanyHelper::marketComparison() | تقرير السوق |
tests/Unit/CompanyHelperTest.php | 12 unit test يثبت صحة كل المعادلات |
8. مثال عملي كامل
منشأة بيانات السنة المالية 2024:
| الحقل | القيمة |
|---|---|
revenue | 1,000,000 |
purchases | 600,000 |
cost | 500,000 |
general_expenses | 200,000 |
marketing_expenses | 100,000 |
fixed_assets | 300,000 |
customers_balance | 100,000 |
inventory_balance | 200,000 |
suppliers_balance | 150,000 |
accrued_expenses | 50,000 |
property_rights | 500,000 |
loans_increase | 50,000 |
capital_increase | 100,000 |
المؤشرات المحسوبة:
| المؤشر | المعادلة | الناتج |
|---|---|---|
| profit_margin | (1,000,000 - 500,000) / 1,000,000 | 0.50 → 50% |
| expenses_ratio | (500K + 200K + 100K) / 1,000,000 | 0.80 → 80% |
| marketing_ratio | 100,000 / 1,000,000 | 0.10 → 10% |
| net_profit | 1M - 500K - 200K - 100K | 200,000 ر.س |
| customers_turnover | 1,000,000 / 100,000 | 10x |
| inventory_turnover | 600,000 / 200,000 | 3x |
| suppliers_turnover | 600,000 / 150,000 | 4x |
| roi | 200,000 / 500,000 | 0.40 → 40% |
| operating_cash_surplus | 200,000 + (300,000 × 0.10) - 50,000 = 200,000 + 30,000 - 50,000 | 180,000 ر.س |
| year_end_cash_surplus | 180,000 + 50,000 + 100,000 | 330,000 ر.س |