Spaces:
Paused
Paused
| import os | |
| import json | |
| import re | |
| import numpy as np | |
| import pandas as pd | |
| from typing import Dict, List, Any, Union, Tuple, Optional | |
| from datetime import datetime | |
| class LocalContentCalculator: | |
| """ | |
| فئة لحساب وتحليل المحتوى المحلي في المناقصات | |
| """ | |
| def __init__(self): | |
| """ | |
| تهيئة حاسبة المحتوى المحلي | |
| """ | |
| # تحميل بيانات المحتوى المحلي | |
| self.local_content_data = self._load_local_content_data() | |
| # تحميل قاعدة بيانات الشركات المحلية | |
| self.local_companies = self._load_local_companies() | |
| # تحميل نطاقات الشركات | |
| self.nitaqat_data = self._load_nitaqat_data() | |
| # قائمة القطاعات | |
| self.sectors = [ | |
| "الإنشاءات", "تقنية المعلومات", "الاتصالات", "الصحة", | |
| "التعليم", "النقل", "الطاقة", "المياه", "البيئة", | |
| "الصناعة", "التجارة", "السياحة", "الخدمات المالية" | |
| ] | |
| def _load_local_content_data(self) -> Dict[str, Any]: | |
| """ | |
| تحميل بيانات المحتوى المحلي | |
| """ | |
| # في التطبيق الفعلي، قد تُحمل هذه البيانات من ملف أو قاعدة بيانات | |
| return { | |
| "sectors": { | |
| "الإنشاءات": { | |
| "min_percentage": 30, | |
| "target_percentage": 60, | |
| "weights": { | |
| "manpower": 0.35, | |
| "materials": 0.45, | |
| "services": 0.2 | |
| } | |
| }, | |
| "تقنية المعلومات": { | |
| "min_percentage": 25, | |
| "target_percentage": 50, | |
| "weights": { | |
| "manpower": 0.55, | |
| "materials": 0.15, | |
| "services": 0.3 | |
| } | |
| }, | |
| "عام": { | |
| "min_percentage": 20, | |
| "target_percentage": 40, | |
| "weights": { | |
| "manpower": 0.4, | |
| "materials": 0.3, | |
| "services": 0.3 | |
| } | |
| } | |
| }, | |
| "material_categories": { | |
| "local_manufacturing": 1.0, | |
| "local_assembly": 0.7, | |
| "imported_with_local_value_add": 0.4, | |
| "fully_imported": 0.0 | |
| }, | |
| "manpower_categories": { | |
| "saudi_employee": 1.0, | |
| "expat_employee": 0.0 | |
| }, | |
| "service_categories": { | |
| "local_service_provider": 1.0, | |
| "joint_venture": 0.6, | |
| "foreign_provider_with_local_partner": 0.3, | |
| "foreign_provider": 0.0 | |
| } | |
| } | |
| def _load_local_companies(self) -> Dict[str, Dict[str, Any]]: | |
| """ | |
| تحميل قاعدة بيانات الشركات المحلية | |
| """ | |
| # في التطبيق الفعلي، قد تُحمل هذه البيانات من ملف أو قاعدة بيانات | |
| return { | |
| "company1": { | |
| "name": "شركة البناء السعودية", | |
| "cr_number": "1010XXXXXX", | |
| "sector": "الإنشاءات", | |
| "local_content_certificate": True, | |
| "saudi_employees_percentage": 35, | |
| "nitaqat_category": "أخضر متوسط", | |
| "local_content_percentage": 45 | |
| }, | |
| "company2": { | |
| "name": "شركة تقنية المستقبل", | |
| "cr_number": "1020XXXXXX", | |
| "sector": "تقنية المعلومات", | |
| "local_content_certificate": True, | |
| "saudi_employees_percentage": 42, | |
| "nitaqat_category": "أخضر مرتفع", | |
| "local_content_percentage": 52 | |
| }, | |
| "company3": { | |
| "name": "مصنع المنتجات المعدنية", | |
| "cr_number": "1030XXXXXX", | |
| "sector": "الصناعة", | |
| "local_content_certificate": True, | |
| "saudi_employees_percentage": 28, | |
| "nitaqat_category": "أخضر منخفض", | |
| "local_content_percentage": 61 | |
| } | |
| } | |
| def _load_nitaqat_data(self) -> Dict[str, Dict[str, Any]]: | |
| """ | |
| تحميل بيانات نطاقات الشركات | |
| """ | |
| # في التطبيق الفعلي، قد تُحمل هذه البيانات من ملف أو قاعدة بيانات | |
| return { | |
| "الإنشاءات": { | |
| "صغيرة": { | |
| "أحمر": {"min": 0, "max": 5}, | |
| "أخضر منخفض": {"min": 6, "max": 10}, | |
| "أخضر متوسط": {"min": 11, "max": 15}, | |
| "أخضر مرتفع": {"min": 16, "max": 25}, | |
| "بلاتيني": {"min": 26, "max": 100} | |
| }, | |
| "متوسطة": { | |
| "أحمر": {"min": 0, "max": 7}, | |
| "أخضر منخفض": {"min": 8, "max": 14}, | |
| "أخضر متوسط": {"min": 15, "max": 20}, | |
| "أخضر مرتفع": {"min": 21, "max": 30}, | |
| "بلاتيني": {"min": 31, "max": 100} | |
| }, | |
| "كبيرة": { | |
| "أحمر": {"min": 0, "max": 9}, | |
| "أخضر منخفض": {"min": 10, "max": 16}, | |
| "أخضر متوسط": {"min": 17, "max": 23}, | |
| "أخضر مرتفع": {"min": 24, "max": 35}, | |
| "بلاتيني": {"min": 36, "max": 100} | |
| } | |
| }, | |
| "تقنية المعلومات": { | |
| "صغيرة": { | |
| "أحمر": {"min": 0, "max": 6}, | |
| "أخضر منخفض": {"min": 7, "max": 12}, | |
| "أخضر متوسط": {"min": 13, "max": 19}, | |
| "أخضر مرتفع": {"min": 20, "max": 29}, | |
| "بلاتيني": {"min": 30, "max": 100} | |
| }, | |
| "متوسطة": { | |
| "أحمر": {"min": 0, "max": 13}, | |
| "أخضر منخفض": {"min": 14, "max": 20}, | |
| "أخضر متوسط": {"min": 21, "max": 27}, | |
| "أخضر مرتفع": {"min": 28, "max": 35}, | |
| "بلاتيني": {"min": 36, "max": 100} | |
| }, | |
| "كبيرة": { | |
| "أحمر": {"min": 0, "max": 17}, | |
| "أخضر منخفض": {"min": 18, "max": 25}, | |
| "أخضر متوسط": {"min": 26, "max": 33}, | |
| "أخضر مرتفع": {"min": 34, "max": 40}, | |
| "بلاتيني": {"min": 41, "max": 100} | |
| } | |
| } | |
| } | |
| def calculate(self, extracted_data: Dict[str, Any], **kwargs) -> Dict[str, Any]: | |
| """ | |
| حساب نسبة المحتوى المحلي بناءً على البيانات المستخرجة من المستندات | |
| المعاملات: | |
| ---------- | |
| extracted_data : Dict[str, Any] | |
| البيانات المستخرجة من المستندات | |
| **kwargs : Dict[str, Any] | |
| معاملات إضافية مثل نوع المشروع، الميزانية، الموقع، المدة | |
| المخرجات: | |
| -------- | |
| Dict[str, Any] | |
| نتائج حساب المحتوى المحلي | |
| """ | |
| # تهيئة نتائج حساب المحتوى المحلي | |
| local_content_results = { | |
| "overall_percentage": 0.0, | |
| "breakdown": {}, | |
| "requirements": [], | |
| "recommendations": [], | |
| "nitaqat_analysis": {}, | |
| } | |
| # تحديد نوع المشروع والقطاع | |
| project_type = kwargs.get("project_type", "") | |
| sector = self._determine_sector(project_type, extracted_data) | |
| # استخراج متطلبات المحتوى المحلي من البيانات | |
| local_content_info = self._extract_local_content_info(extracted_data) | |
| # حساب المحتوى المحلي بناءً على القطاع | |
| sector_data = self.local_content_data["sectors"].get(sector, self.local_content_data["sectors"]["عام"]) | |
| # تحليل القوى العاملة (الموارد البشرية) | |
| manpower_analysis = self._analyze_manpower(extracted_data, sector_data) | |
| local_content_results["breakdown"]["manpower"] = manpower_analysis["percentage"] | |
| # تحليل المواد | |
| materials_analysis = self._analyze_materials(extracted_data, sector_data) | |
| local_content_results["breakdown"]["materials"] = materials_analysis["percentage"] | |
| # تحليل الخدمات | |
| services_analysis = self._analyze_services(extracted_data, sector_data) | |
| local_content_results["breakdown"]["services"] = services_analysis["percentage"] | |
| # حساب النسبة الإجمالية للمحتوى المحلي | |
| weights = sector_data["weights"] | |
| overall_percentage = ( | |
| weights["manpower"] * manpower_analysis["percentage"] + | |
| weights["materials"] * materials_analysis["percentage"] + | |
| weights["services"] * services_analysis["percentage"] | |
| ) | |
| local_content_results["overall_percentage"] = round(overall_percentage, 2) | |
| # تحليل الامتثال لمتطلبات نطاقات | |
| nitaqat_analysis = self._analyze_nitaqat_compliance(extracted_data, sector) | |
| local_content_results["nitaqat_analysis"] = nitaqat_analysis | |
| # إعداد متطلبات المحتوى المحلي | |
| requirements = self._prepare_local_content_requirements(sector_data, local_content_info) | |
| local_content_results["requirements"] = requirements | |
| # إعداد توصيات لتحسين المحتوى المحلي | |
| recommendations = self._generate_recommendations( | |
| overall_percentage, | |
| sector_data, | |
| manpower_analysis, | |
| materials_analysis, | |
| services_analysis, | |
| nitaqat_analysis | |
| ) | |
| local_content_results["recommendations"] = recommendations | |
| return local_content_results | |
| def _determine_sector(self, project_type: str, extracted_data: Dict[str, Any]) -> str: | |
| """ | |
| تحديد القطاع بناءً على نوع المشروع والبيانات المستخرجة | |
| """ | |
| # قاموس لتحويل أنواع المشاريع الشائعة إلى قطاعات | |
| project_to_sector = { | |
| "إنشاءات": "الإنشاءات", | |
| "مباني": "الإنشاءات", | |
| "طرق": "الإنشاءات", | |
| "جسور": "الإنشاءات", | |
| "تقنية معلومات": "تقنية المعلومات", | |
| "برمجيات": "تقنية المعلومات", | |
| "تطبيقات": "تقنية المعلومات", | |
| "اتصالات": "الاتصالات", | |
| "صحة": "الصحة", | |
| "مستشفى": "الصحة", | |
| "طبي": "الصحة", | |
| "تعليم": "التعليم", | |
| "مدارس": "التعليم", | |
| "جامعات": "التعليم", | |
| "نقل": "النقل", | |
| "مواصلات": "النقل", | |
| "طاقة": "الطاقة", | |
| "كهرباء": "الطاقة", | |
| "مياه": "المياه", | |
| "صرف صحي": "المياه", | |
| "بيئة": "البيئة", | |
| "صناعة": "الصناعة", | |
| "مصانع": "الصناعة", | |
| "تجارة": "التجارة", | |
| "أسواق": "التجارة", | |
| "سياحة": "السياحة", | |
| "فنادق": "السياحة", | |
| "مالية": "الخدمات المالية", | |
| "بنوك": "الخدمات المالية" | |
| } | |
| # محاولة تحديد القطاع من نوع المشروع | |
| if project_type: | |
| for key, value in project_to_sector.items(): | |
| if key in project_type.lower(): | |
| return value | |
| # إذا لم يتم تحديد القطاع من نوع المشروع، نحاول تحديده من البيانات المستخرجة | |
| if "text" in extracted_data: | |
| text = extracted_data["text"].lower() | |
| sector_scores = {} | |
| for sector in self.sectors: | |
| score = text.count(sector.lower()) | |
| sector_scores[sector] = score | |
| # اختيار القطاع الأكثر ذكراً | |
| if sector_scores: | |
| max_sector = max(sector_scores, key=sector_scores.get) | |
| if sector_scores[max_sector] > 0: | |
| return max_sector | |
| # القطاع الافتراضي إذا لم نتمكن من تحديده | |
| return "عام" | |
| def _extract_local_content_info(self, extracted_data: Dict[str, Any]) -> Dict[str, Any]: | |
| """ | |
| استخراج معلومات المحتوى المحلي من البيانات المستخرجة | |
| """ | |
| local_content_info = { | |
| "mentioned_percentage": None, | |
| "requirements": [], | |
| "companies": [] | |
| } | |
| # استخراج النسبة المذكورة للمحتوى المحلي | |
| if "local_content" in extracted_data and extracted_data["local_content"]: | |
| local_content_data = extracted_data["local_content"] | |
| # استخراج النسب المئوية | |
| percentages = local_content_data.get("percentages", []) | |
| if percentages: | |
| # اختيار أعلى نسبة مذكورة | |
| max_percentage = max(percentages, key=lambda x: x["value"]) | |
| local_content_info["mentioned_percentage"] = max_percentage["value"] | |
| # استخراج المتطلبات | |
| requirements = local_content_data.get("requirements", []) | |
| local_content_info["requirements"] = requirements | |
| # استخراج الشركات المحلية المذكورة | |
| if "entities" in extracted_data and "organizations" in extracted_data["entities"]: | |
| organizations = extracted_data["entities"]["organizations"] | |
| for org in organizations: | |
| org_name = org["name"].lower() | |
| # البحث في قاعدة بيانات الشركات المحلية | |
| for company_id, company_data in self.local_companies.items(): | |
| company_name = company_data["name"].lower() | |
| # إذا وجدنا تطابق | |
| if company_name in org_name or org_name in company_name: | |
| local_content_info["companies"].append(company_data) | |
| return local_content_info | |
| def _analyze_manpower(self, extracted_data: Dict[str, Any], sector_data: Dict[str, Any]) -> Dict[str, Any]: | |
| """ | |
| تحليل المحتوى المحلي للقوى العاملة | |
| """ | |
| manpower_analysis = { | |
| "percentage": 0.0, | |
| "saudi_employees": 0, | |
| "expat_employees": 0, | |
| "total_employees": 0 | |
| } | |
| # استخراج معلومات الموظفين من البيانات | |
| saudi_keywords = ["سعودي", "مواطن", "توطين", "سعودة"] | |
| expat_keywords = ["أجنبي", "وافد", "غير سعودي"] | |
| # لدينا بعض البيانات الافتراضية للتوضيح | |
| saudi_count = 0 | |
| expat_count = 0 | |
| # إذا كانت هناك شركات معروفة في البيانات المستخرجة، نستخدم نسب التوطين الخاصة بها | |
| if "entities" in extracted_data and "organizations" in extracted_data["entities"]: | |
| organizations = extracted_data["entities"]["organizations"] | |
| for org in organizations: | |
| org_name = org["name"].lower() | |
| for company_id, company_data in self.local_companies.items(): | |
| company_name = company_data["name"].lower() | |
| if company_name in org_name or org_name in company_name: | |
| saudi_percentage = company_data["saudi_employees_percentage"] / 100 | |
| saudi_count += 50 * saudi_percentage # افتراض 50 موظف كمتوسط | |
| expat_count += 50 * (1 - saudi_percentage) | |
| # إذا لم نجد شركات معروفة، نحاول تقدير النسب من النص | |
| if saudi_count == 0 and expat_count == 0 and "text" in extracted_data: | |
| text = extracted_data["text"].lower() | |
| # عدد مرات ذكر الموظفين السعوديين | |
| saudi_mentions = sum(text.count(keyword) for keyword in saudi_keywords) | |
| # عدد مرات ذكر الموظفين الأجانب | |
| expat_mentions = sum(text.count(keyword) for keyword in expat_keywords) | |
| # تقدير تقريبي للنسب | |
| total_mentions = saudi_mentions + expat_mentions | |
| if total_mentions > 0: | |
| saudi_ratio = saudi_mentions / total_mentions | |
| saudi_count = int(100 * saudi_ratio) | |
| expat_count = 100 - saudi_count | |
| # إذا لم نتمكن من تقدير النسب، نستخدم قيمة افتراضية | |
| if saudi_count == 0 and expat_count == 0: | |
| # القيمة الافتراضية بناءً على متوسط نسب التوطين في القطاع | |
| if "الإنشاءات" in sector_data: | |
| saudi_count = 25 | |
| elif "تقنية المعلومات" in sector_data: | |
| saudi_count = 35 | |
| else: | |
| saudi_count = 30 | |
| expat_count = 100 - saudi_count | |
| # حساب النسبة المئوية للمحتوى المحلي في القوى العاملة | |
| total_count = saudi_count + expat_count | |
| if total_count > 0: | |
| manpower_analysis["saudi_employees"] = saudi_count | |
| manpower_analysis["expat_employees"] = expat_count | |
| manpower_analysis["total_employees"] = total_count | |
| # حساب النسبة المئوية باستخدام الأوزان | |
| manpower_percentage = ( | |
| self.local_content_data["manpower_categories"]["saudi_employee"] * saudi_count + | |
| self.local_content_data["manpower_categories"]["expat_employee"] * expat_count | |
| ) / total_count * 100 | |
| manpower_analysis["percentage"] = round(manpower_percentage, 2) | |
| return manpower_analysis | |
| def _analyze_materials(self, extracted_data: Dict[str, Any], sector_data: Dict[str, Any]) -> Dict[str, Any]: | |
| """ | |
| تحليل المحتوى المحلي للمواد | |
| """ | |
| materials_analysis = { | |
| "percentage": 0.0, | |
| "local_manufacturing": 0, | |
| "local_assembly": 0, | |
| "imported_with_local_value_add": 0, | |
| "fully_imported": 0, | |
| "total_materials": 0 | |
| } | |
| # كلمات دلالية للفئات المختلفة من المواد | |
| local_manufacturing_keywords = ["تصنيع محلي", "منتج محلي", "صناعة محلية", "صنع في السعودية", "منشأ سعودي"] | |
| local_assembly_keywords = ["تجميع محلي", "مجمع محلياً", "تم تجميعه في السعودية"] | |
| imported_with_local_value_keywords = ["قيمة مضافة محلية", "معالجة محلية", "قيمة محلية"] | |
| fully_imported_keywords = ["مستورد", "استيراد كامل", "منتج أجنبي", "صنع في الخارج"] | |
| # تقدير نسب المواد من النص | |
| if "text" in extracted_data: | |
| text = extracted_data["text"].lower() | |
| # عدد مرات ذكر كل فئة | |
| local_manufacturing_count = sum(text.count(keyword) for keyword in local_manufacturing_keywords) | |
| local_assembly_count = sum(text.count(keyword) for keyword in local_assembly_keywords) | |
| imported_with_local_value_count = sum(text.count(keyword) for keyword in imported_with_local_value_keywords) | |
| fully_imported_count = sum(text.count(keyword) for keyword in fully_imported_keywords) | |
| # إجمالي عدد المرات | |
| total_count = (local_manufacturing_count + local_assembly_count + | |
| imported_with_local_value_count + fully_imported_count) | |
| if total_count > 0: | |
| materials_analysis["local_manufacturing"] = local_manufacturing_count | |
| materials_analysis["local_assembly"] = local_assembly_count | |
| materials_analysis["imported_with_local_value_add"] = imported_with_local_value_count | |
| materials_analysis["fully_imported"] = fully_imported_count | |
| materials_analysis["total_materials"] = total_count | |
| # إذا لم نتمكن من تقدير النسب، نستخدم قيم افتراضية بناءً على القطاع | |
| if materials_analysis["total_materials"] == 0: | |
| if "الإنشاءات" in sector_data: | |
| materials_analysis["local_manufacturing"] = 30 | |
| materials_analysis["local_assembly"] = 20 | |
| materials_analysis["imported_with_local_value_add"] = 15 | |
| materials_analysis["fully_imported"] = 35 | |
| elif "تقنية المعلومات" in sector_data: | |
| materials_analysis["local_manufacturing"] = 10 | |
| materials_analysis["local_assembly"] = 25 | |
| materials_analysis["imported_with_local_value_add"] = 15 | |
| materials_analysis["fully_imported"] = 50 | |
| else: | |
| materials_analysis["local_manufacturing"] = 20 | |
| materials_analysis["local_assembly"] = 20 | |
| materials_analysis["imported_with_local_value_add"] = 15 | |
| materials_analysis["fully_imported"] = 45 | |
| materials_analysis["total_materials"] = ( | |
| materials_analysis["local_manufacturing"] + | |
| materials_analysis["local_assembly"] + | |
| materials_analysis["imported_with_local_value_add"] + | |
| materials_analysis["fully_imported"] | |
| ) | |
| # حساب النسبة المئوية للمحتوى المحلي في المواد | |
| total_materials = materials_analysis["total_materials"] | |
| if total_materials > 0: | |
| material_categories = self.local_content_data["material_categories"] | |
| materials_percentage = ( | |
| material_categories["local_manufacturing"] * materials_analysis["local_manufacturing"] + | |
| material_categories["local_assembly"] * materials_analysis["local_assembly"] + | |
| material_categories["imported_with_local_value_add"] * materials_analysis["imported_with_local_value_add"] + | |
| material_categories["fully_imported"] * materials_analysis["fully_imported"] | |
| ) / total_materials * 100 | |
| materials_analysis["percentage"] = round(materials_percentage, 2) | |
| return materials_analysis | |
| def _analyze_services(self, extracted_data: Dict[str, Any], sector_data: Dict[str, Any]) -> Dict[str, Any]: | |
| """ | |
| تحليل المحتوى المحلي للخدمات | |
| """ | |
| services_analysis = { | |
| "percentage": 0.0, | |
| "local_service_provider": 0, | |
| "joint_venture": 0, | |
| "foreign_provider_with_local_partner": 0, | |
| "foreign_provider": 0, | |
| "total_services": 0 | |
| } | |
| # كلمات دلالية للفئات المختلفة من الخدمات | |
| local_provider_keywords = ["مزود خدمة محلي", "شركة محلية", "شركة سعودية", "مؤسسة محلية"] | |
| joint_venture_keywords = ["مشروع مشترك", "شراكة", "تحالف", "ائتلاف"] | |
| foreign_with_local_keywords = ["شريك محلي", "وكيل محلي", "وكيل سعودي", "تمثيل محلي"] | |
| foreign_provider_keywords = ["مزود خدمة أجنبي", "شركة أجنبية", "مقاول أجنبي"] | |
| # تقدير نسب الخدمات من النص | |
| if "text" in extracted_data: | |
| text = extracted_data["text"].lower() | |
| # عدد مرات ذكر كل فئة | |
| local_provider_count = sum(text.count(keyword) for keyword in local_provider_keywords) | |
| joint_venture_count = sum(text.count(keyword) for keyword in joint_venture_keywords) | |
| foreign_with_local_count = sum(text.count(keyword) for keyword in foreign_with_local_keywords) | |
| foreign_provider_count = sum(text.count(keyword) for keyword in foreign_provider_keywords) | |
| # إجمالي عدد المرات | |
| total_count = (local_provider_count + joint_venture_count + | |
| foreign_with_local_count + foreign_provider_count) | |
| if total_count > 0: | |
| services_analysis["local_service_provider"] = local_provider_count | |
| services_analysis["joint_venture"] = joint_venture_count | |
| services_analysis["foreign_provider_with_local_partner"] = foreign_with_local_count | |
| services_analysis["foreign_provider"] = foreign_provider_count | |
| services_analysis["total_services"] = total_count | |
| # إذا لم نتمكن من تقدير النسب، نستخدم قيم افتراضية بناءً على القطاع | |
| if services_analysis["total_services"] == 0: | |
| if "الإنشاءات" in sector_data: | |
| services_analysis["local_service_provider"] = 35 | |
| services_analysis["joint_venture"] = 25 | |
| services_analysis["foreign_provider_with_local_partner"] = 20 | |
| services_analysis["foreign_provider"] = 20 | |
| elif "تقنية المعلومات" in sector_data: | |
| services_analysis["local_service_provider"] = 30 | |
| services_analysis["joint_venture"] = 20 | |
| services_analysis["foreign_provider_with_local_partner"] = 25 | |
| services_analysis["foreign_provider"] = 25 | |
| else: | |
| services_analysis["local_service_provider"] = 30 | |
| services_analysis["joint_venture"] = 25 | |
| services_analysis["foreign_provider_with_local_partner"] = 20 | |
| services_analysis["foreign_provider"] = 25 | |
| services_analysis["total_services"] = ( | |
| services_analysis["local_service_provider"] + | |
| services_analysis["joint_venture"] + | |
| services_analysis["foreign_provider_with_local_partner"] + | |
| services_analysis["foreign_provider"] | |
| ) | |
| # حساب النسبة المئوية للمحتوى المحلي في الخدمات |