Wahbi-AI / pricing_system /tests /test_integrated_system.py
EGYADMIN's picture
Upload 70 files
d9e7bdd verified
import unittest
import sys
import os
import pandas as pd
import numpy as np
import streamlit as st
from unittest.mock import patch, MagicMock
# إضافة مسار الوحدات
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
# استيراد الوحدات للاختبار
from pricing_system.integration_framework import IntegrationFramework
from pricing_system.modules.catalogs.equipment_catalog import EquipmentCatalog
from pricing_system.modules.catalogs.materials_catalog import MaterialsCatalog
from pricing_system.modules.catalogs.labor_catalog import LaborCatalog
from pricing_system.modules.catalogs.subcontractors_catalog import SubcontractorsCatalog
from pricing_system.modules.analysis.smart_price_analysis import SmartPriceAnalysis
from pricing_system.modules.indirect_support.indirect_support_management import IndirectSupportManagement
from pricing_system.modules.pricing_strategies.pricing_strategies import PricingStrategies
class TestIntegratedSystem(unittest.TestCase):
"""
اختبارات النظام المتكامل للتأكد من عمل جميع المكونات معًا بشكل صحيح
"""
def setUp(self):
"""
إعداد بيئة الاختبار
"""
# تهيئة حالة الجلسة الوهمية
st.session_state = {}
# إنشاء مثيلات من الوحدات للاختبار
self.equipment_catalog = EquipmentCatalog()
self.materials_catalog = MaterialsCatalog()
self.labor_catalog = LaborCatalog()
self.subcontractors_catalog = SubcontractorsCatalog()
self.smart_price_analysis = SmartPriceAnalysis()
self.indirect_support = IndirectSupportManagement()
self.pricing_strategies = PricingStrategies()
# إنشاء مثيل من إطار التكامل
self.integration_framework = IntegrationFramework()
# إعداد بيانات اختبار المشروع
self.project_data = {
'name': 'مشروع اختبار',
'location': 'الرياض',
'client': 'وزارة الإسكان',
'start_date': '2025-01-01',
'end_date': '2025-12-31',
'budget': 10000000.0,
'boq_items': [
{
'item_code': 'B001',
'description': 'حفر وردم',
'unit': 'م3',
'quantity': 1000.0,
'unit_price': 50.0,
'total_price': 50000.0
},
{
'item_code': 'B002',
'description': 'خرسانة مسلحة',
'unit': 'م3',
'quantity': 500.0,
'unit_price': 1200.0,
'total_price': 600000.0
},
{
'item_code': 'B003',
'description': 'أعمال تشطيبات',
'unit': 'م2',
'quantity': 2000.0,
'unit_price': 300.0,
'total_price': 600000.0
}
],
'resources': [],
'pricing_strategy': 'standard',
'indirect_costs': {},
'profit_margin': 0.15,
'local_content_target': 0.40
}
# إضافة بيانات اختبار للكتالوجات
self._add_test_data_to_catalogs()
def _add_test_data_to_catalogs(self):
"""
إضافة بيانات اختبار إلى الكتالوجات
"""
# إضافة معدات للاختبار
equipment_data = [
{
'name': 'حفار',
'type': 'حفار',
'description': 'حفار هيدروليكي',
'price_per_hour': 200.0,
'price_per_day': 1600.0,
'price_per_week': 8000.0,
'price_per_month': 30000.0,
'is_local': True
},
{
'name': 'لودر',
'type': 'لودر',
'description': 'لودر متوسط الحجم',
'price_per_hour': 150.0,
'price_per_day': 1200.0,
'price_per_week': 6000.0,
'price_per_month': 22000.0,
'is_local': False
},
{
'name': 'شاحنة نقل',
'type': 'شاحنة',
'description': 'شاحنة نقل ثقيلة',
'price_per_hour': 120.0,
'price_per_day': 960.0,
'price_per_week': 4800.0,
'price_per_month': 18000.0,
'is_local': True
}
]
for equipment in equipment_data:
self.equipment_catalog.add_equipment(equipment['name'], equipment)
# إضافة مواد للاختبار
materials_data = [
{
'name': 'اسمنت',
'description': 'اسمنت بورتلاندي',
'unit': 'طن',
'price': 600.0,
'is_local': True
},
{
'name': 'حديد تسليح',
'description': 'حديد تسليح قطر 16 مم',
'unit': 'طن',
'price': 3500.0,
'is_local': True
},
{
'name': 'رمل',
'description': 'رمل ناعم للخرسانة',
'unit': 'م3',
'price': 80.0,
'is_local': True
},
{
'name': 'بلاط سيراميك',
'description': 'بلاط سيراميك للأرضيات',
'unit': 'م2',
'price': 120.0,
'is_local': False
}
]
for material in materials_data:
self.materials_catalog.add_material(material['name'], material)
# إضافة عمالة للاختبار
labor_data = [
{
'name': 'مهندس مدني',
'type': 'مهندس مدني',
'description': 'مهندس مدني خبرة 5 سنوات',
'price_per_hour': 100.0,
'price_per_day': 800.0,
'price_per_week': 4000.0,
'price_per_month': 15000.0,
'is_local': True
},
{
'name': 'عامل بناء',
'type': 'عامل بناء',
'description': 'عامل بناء ماهر',
'price_per_hour': 20.0,
'price_per_day': 160.0,
'price_per_week': 800.0,
'price_per_month': 3000.0,
'is_local': False
},
{
'name': 'فني كهرباء',
'type': 'كهربائي',
'description': 'فني كهرباء خبرة 3 سنوات',
'price_per_hour': 30.0,
'price_per_day': 240.0,
'price_per_week': 1200.0,
'price_per_month': 4500.0,
'is_local': True
}
]
for labor in labor_data:
self.labor_catalog.add_labor(labor['name'], labor)
# إضافة مقاولي باطن للاختبار
subcontractors_data = [
{
'name': 'شركة الأعمال الكهربائية',
'specialization': 'أعمال كهربائية',
'description': 'شركة متخصصة في الأعمال الكهربائية',
'contact_info': '[email protected]',
'is_local': True
},
{
'name': 'مؤسسة أنظمة التكييف',
'specialization': 'أعمال تكييف',
'description': 'مؤسسة متخصصة في أنظمة التكييف',
'contact_info': '[email protected]',
'is_local': True
},
{
'name': 'شركة أنظمة المراقبة',
'specialization': 'أعمال CCTV',
'description': 'شركة متخصصة في أنظمة المراقبة والكاميرات',
'contact_info': '[email protected]',
'is_local': False
}
]
for subcontractor in subcontractors_data:
self.subcontractors_catalog.add_subcontractor(subcontractor['name'], subcontractor)
# إضافة إدارات مساندة للاختبار
departments_data = [
{
'name': 'إدارة المشاريع',
'description': 'إدارة متابعة وتنفيذ المشاريع',
'monthly_cost': 100000.0,
'employees_count': 10,
'allocation_percentage': 20.0
},
{
'name': 'إدارة المشتريات',
'description': 'إدارة المشتريات والتوريدات',
'monthly_cost': 80000.0,
'employees_count': 8,
'allocation_percentage': 15.0
},
{
'name': 'الإدارة المالية',
'description': 'الإدارة المالية والمحاسبة',
'monthly_cost': 70000.0,
'employees_count': 7,
'allocation_percentage': 10.0
}
]
for department in departments_data:
self.indirect_support.add_department(department['name'], department)
def test_equipment_catalog_integration(self):
"""
اختبار تكامل كتالوج المعدات
"""
# التحقق من وجود المعدات في الكتالوج
equipment_list = self.equipment_catalog.get_equipment_list()
self.assertEqual(len(equipment_list), 3)
self.assertIn('حفار', equipment_list)
self.assertIn('لودر', equipment_list)
self.assertIn('شاحنة نقل', equipment_list)
# التحقق من تفاصيل المعدات
حفار_details = self.equipment_catalog.get_equipment_details('حفار')
self.assertEqual(حفار_details['price_per_day'], 1600.0)
self.assertTrue(حفار_details['is_local'])
لودر_details = self.equipment_catalog.get_equipment_details('لودر')
self.assertEqual(لودر_details['price_per_day'], 1200.0)
self.assertFalse(لودر_details['is_local'])
def test_materials_catalog_integration(self):
"""
اختبار تكامل كتالوج المواد
"""
# التحقق من وجود المواد في الكتالوج
materials_list = self.materials_catalog.get_materials_list()
self.assertEqual(len(materials_list), 4)
self.assertIn('اسمنت', materials_list)
self.assertIn('حديد تسليح', materials_list)
self.assertIn('رمل', materials_list)
self.assertIn('بلاط سيراميك', materials_list)
# التحقق من تفاصيل المواد
اسمنت_details = self.materials_catalog.get_material_details('اسمنت')
self.assertEqual(اسمنت_details['price'], 600.0)
self.assertEqual(اسمنت_details['unit'], 'طن')
self.assertTrue(اسمنت_details['is_local'])
بلاط_details = self.materials_catalog.get_material_details('بلاط سيراميك')
self.assertEqual(بلاط_details['price'], 120.0)
self.assertEqual(بلاط_details['unit'], 'م2')
self.assertFalse(بلاط_details['is_local'])
def test_labor_catalog_integration(self):
"""
اختبار تكامل كتالوج العمالة
"""
# التحقق من وجود العمالة في الكتالوج
labor_list = self.labor_catalog.get_labor_list()
self.assertEqual(len(labor_list), 3)
self.assertIn('مهندس مدني', labor_list)
self.assertIn('عامل بناء', labor_list)
self.assertIn('فني كهرباء', labor_list)
# التحقق من تفاصيل العمالة
مهندس_details = self.labor_catalog.get_labor_details('مهندس مدني')
self.assertEqual(مهندس_details['price_per_month'], 15000.0)
self.assertTrue(مهندس_details['is_local'])
عامل_details = self.labor_catalog.get_labor_details('عامل بناء')
self.assertEqual(عامل_details['price_per_day'], 160.0)
self.assertFalse(عامل_details['is_local'])
def test_subcontractors_catalog_integration(self):
"""
اختبار تكامل كتالوج مقاولي الباطن
"""
# التحقق من وجود مقاولي الباطن في الكتالوج
subcontractors_list = self.subcontractors_catalog.get_subcontractors_list()
self.assertEqual(len(subcontractors_list), 3)
self.assertIn('شركة الأعمال الكهربائية', subcontractors_list)
self.assertIn('مؤسسة أنظمة التكييف', subcontractors_list)
self.assertIn('شركة أنظمة المراقبة', subcontractors_list)
# التحقق من تفاصيل مقاولي الباطن
كهرباء_details = self.subcontractors_catalog.get_subcontractor_details('شركة الأعمال الكهربائية')
self.assertEqual(كهرباء_details['specialization'], 'أعمال كهربائية')
self.assertTrue(كهرباء_details['is_local'])
مراقبة_details = self.subcontractors_catalog.get_subcontractor_details('شركة أنظمة المراقبة')
self.assertEqual(مراقبة_details['specialization'], 'أعمال CCTV')
self.assertFalse(مراقبة_details['is_local'])
def test_indirect_support_integration(self):
"""
اختبار تكامل إدارة الإدارات المساندة
"""
# التحقق من وجود الإدارات المساندة
departments = self.indirect_support.get_departments()
self.assertEqual(len(departments), 3)
self.assertIn('إدارة المشاريع', departments)
self.assertIn('إدارة المشتريات', departments)
self.assertIn('الإدارة المالية', departments)
# التحقق من تفاصيل الإدارات المساندة
مشاريع_details = self.indirect_support.get_department_details('إدارة المشاريع')
self.assertEqual(مشاريع_details['monthly_cost'], 100000.0)
self.assertEqual(مشاريع_details['allocation_percentage'], 20.0)
# التحقق من حساب التكاليف الإجمالية
total_monthly_cost = self.indirect_support.get_total_monthly_cost()
self.assertEqual(total_monthly_cost, 250000.0)
total_allocated_cost = self.indirect_support.get_total_allocated_cost()
self.assertEqual(total_allocated_cost, 45000.0) # (100000*0.2 + 80000*0.15 + 70000*0.1)
def test_smart_price_analysis_integration(self):
"""
اختبار تكامل التحليل الذكي للأسعار
"""
# إضافة تحليل لبنود المشروع
for i, item in enumerate(self.project_data['boq_items']):
analysis = {
'direct_cost': item['total_price'] * 0.7, # 70% من السعر الإجمالي
'indirect_cost': item['total_price'] * 0.15, # 15% من السعر الإجمالي
'profit_margin': item['total_price'] * 0.15, # 15% من السعر الإجمالي
'total_price': item['total_price'],
'materials': [
{
'name': 'اسمنت',
'quantity': 10,
'unit': 'طن',
'price': 600.0,
'total': 6000.0,
'is_local': True
},
{
'name': 'حديد تسليح',
'quantity': 5,
'unit': 'طن',
'price': 3500.0,
'total': 17500.0,
'is_local': True
}
],
'equipment': [
{
'name': 'حفار',
'duration': 5,
'duration_unit': 'يوم',
'price': 1600.0,
'total': 8000.0,
'is_local': True
}
],
'labor': [
{
'name': 'عامل بناء',
'duration': 20,
'duration_unit': 'يوم',
'price': 160.0,
'total': 3200.0,
'is_local': False
}
],
'materials_cost': 23500.0,
'equipment_cost': 8000.0,
'labor_cost': 3200.0,
'subcontractors_cost': 0.0
}
self.smart_price_analysis.add_item_analysis(i, analysis)
# التحقق من تحليل البنود
all_analyses = self.smart_price_analysis.get_all_items_analysis()
self.assertEqual(len(all_analyses), 3)
# التحقق من تحليل التكاليف الإجمالية للمشروع
cost_analysis = self.smart_price_analysis.get_project_cost_analysis()
self.assertEqual(cost_analysis['total_materials_cost'], 23500.0 * 3)
self.assertEqual(cost_analysis['total_equipment_cost'], 8000.0 * 3)
self.assertEqual(cost_analysis['total_labor_cost'], 3200.0 * 3)
# التحقق من المواد الأكثر تكلفة
top_materials = self.smart_price_analysis.get_top_materials(limit=2)
self.assertEqual(len(top_materials), 2)
self.assertEqual(top_materials[0]['name'], 'حديد تسليح')
self.assertEqual(top_materials[0]['total_cost'], 17500.0 * 3)
def test_pricing_strategies_integration(self):
"""
اختبار تكامل استراتيجيات التسعير
"""
# تطبيق استراتيجية التسعير القياسي
result = self.pricing_strategies.apply_strategy(
'standard',
self.project_data,
self.smart_price_analysis
)
self.assertTrue(result['success'])
self.assertEqual(len(result['items_result']), 3)
# التحقق من نتائج تطبيق الاستراتيجية
total_cost = sum(item['cost'] for item in result['items_result'])
total_price = sum(item['price'] for item in result['items_result'])
profit_margin = total_price - total_cost
self.assertEqual(result['total_cost'], total_cost)
self.assertEqual(result['total_price'], total_price)
self.assertEqual(result['profit_margin'], profit_margin)
# مقارنة استراتيجيات التسعير
comparison_result = self.pricing_strategies.compare_strategies(
self.project_data,
self.smart_price_analysis
)
self.assertTrue(comparison_result['success'])
self.assertEqual(len(comparison_result['strategies_result']), 6) # 6 استراتيجيات
def test_local_content_analysis_integration(self):
"""
اختبار تكامل تحليل المحتوى المحلي
"""
# تحليل المحتوى المحلي
local_content_analysis = self.pricing_strategies.analyze_local_content(
self.project_data,
self.smart_price_analysis
)
self.assertTrue(local_content_analysis['success'])
# التحقق من نتائج تحليل المحتوى المحلي
self.assertIn('local_content_percentage', local_content_analysis)
self.assertIn('resources_local_content', local_content_analysis)
# التحقق من تحليل المحتوى المحلي حسب نوع الموارد
resources_local_content = local_content_analysis['resources_local_content']
self.assertIn('materials', resources_local_content)
self.assertIn('equipment', resources_local_content)
self.assertIn('labor', resources_local_content)
# التحقق من التوصيات
if local_content_analysis['local_content_percentage'] < self.project_data['local_content_target']:
self.assertIn('recommendations', local_content_analysis)
self.assertTrue(len(local_content_analysis['recommendations']) > 0)
def test_integration_framework(self):
"""
اختبار إطار التكامل
"""
# تهيئة حالة الجلسة
st.session_state = {}
# إنشاء مثيلات وهمية من PricingApp و ResourcesApp
pricing_app_mock = MagicMock()
pricing_app_mock.tabs = ["جدول الكميات", "تحليل التكاليف", "سيناريوهات التسعير", "التحليل التنافسي", "التقارير"]
pricing_app_mock._render_bill_of_quantities_tab = MagicMock()
pricing_app_mock._render_cost_analysis_tab = MagicMock()
pricing_app_mock._render_pricing_scenarios_tab = MagicMock()
pricing_app_mock._render_competitive_analysis_tab = MagicMock()
pricing_app_mock._render_reports_tab = MagicMock()
resources_app_mock = MagicMock()
# ربط إطار التكامل مع التطبيقات الوهمية
self.integration_framework.connect_pricing_app(pricing_app_mock)
self.integration_framework.connect_resources_app(resources_app_mock)
# التحقق من إضافة علامات التبويب الجديدة
self.assertEqual(len(pricing_app_mock.tabs), 8) # 5 علامات أصلية + 3 جديدة
self.assertIn("كتالوجات الموارد", pricing_app_mock.tabs)
self.assertIn("الإدارات المساندة", pricing_app_mock.tabs)
self.assertIn("المحتوى المحلي", pricing_app_mock.tabs)
# التحقق من إضافة الدوال الجديدة
self.assertTrue(hasattr(pricing_app_mock, '_render_resource_catalogs_tab'))
self.assertTrue(hasattr(pricing_app_mock, '_render_indirect_support_tab'))
self.assertTrue(hasattr(pricing_app_mock, '_render_local_content_tab'))
if __name__ == '__main__':
unittest.main()