EGYADMIN commited on
Commit
4e55f23
·
verified ·
1 Parent(s): 8c12ee3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +2210 -124
app.py CHANGED
@@ -1,158 +1,2244 @@
1
- """
2
- نظام تحليل المناقصات وسلاسل الإمداد والتوقعات المستقبلية
3
- تطبيق خاص بشركة شبه الجزيرة للمقاولات
4
-
5
- مهندس التطوير: م. تامر الجوهري
6
- """
7
-
8
  import os
9
  import sys
10
- import yaml
11
- import json
12
- import logging
13
- from datetime import datetime
14
- from pathlib import Path
15
-
16
  import streamlit as st
 
17
  import pandas as pd
18
  import numpy as np
 
 
19
  import plotly.express as px
20
  import plotly.graph_objects as go
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
 
22
- # إضافة المجلد الرئيسي للمسار
23
- current_dir = Path(__file__).parent
24
- sys.path.append(str(current_dir))
25
-
26
- # استيراد المكونات الضرورية
27
- from web.pages.home import show_home_page
28
- from web.pages.tender_analysis import show_tender_analysis
29
- from web.pages.requirements_analysis import show_requirements_analysis
30
- from web.pages.cost_estimation import show_cost_estimation
31
- from web.pages.risk_analysis import show_risk_analysis
32
- from web.pages.timeline import show_timeline
33
- from web.pages.local_content import show_local_content
34
- from web.pages.supply_chain import show_supply_chain
35
- from web.pages.procurement import show_procurement
36
- from web.pages.vendors import show_vendors
37
- from web.pages.future_projects import show_future_projects
38
- from web.pages.success_prediction import show_success_prediction
39
- from web.pages.reports import show_reports
40
-
41
- from web.components.sidebar import create_sidebar
42
- from web.components.header import create_header
43
-
44
- from utils.file_handler import setup_logging
45
-
46
- # إعداد التسجيل
47
- setup_logging()
48
- logger = logging.getLogger("TenderAnalysisSystem")
49
-
50
- # تحميل الإعدادات
51
- def load_config():
52
- config_path = os.path.join(current_dir, "config", "config.yaml")
53
- if os.path.exists(config_path):
54
- with open(config_path, 'r', encoding='utf-8') as f:
55
- return yaml.safe_load(f)
56
- return {}
57
-
58
- # تهيئة حالة الجلسة
59
- def initialize_session():
60
- if 'config' not in st.session_state:
61
- st.session_state.config = load_config()
62
-
63
- if 'page' not in st.session_state:
64
- st.session_state.page = "الرئيسية"
65
-
66
- if 'uploaded_files' not in st.session_state:
67
- st.session_state.uploaded_files = []
68
-
69
- if 'analysis_results' not in st.session_state:
70
- st.session_state.analysis_results = {}
71
-
72
- if 'current_tender' not in st.session_state:
73
- st.session_state.current_tender = None
74
-
75
- if 'user_info' not in st.session_state:
76
- st.session_state.user_info = {
77
- "company": "شركة شبه الجزيرة للمقاولات",
78
- "user_name": "المستخدم الحالي",
79
- "role": "محلل مناقصات"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
 
82
- if 'latest_predictions' not in st.session_state:
83
- st.session_state.latest_predictions = None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
 
85
- # إعداد صفحة Streamlit
86
- def setup_page():
87
- st.set_page_config(
88
- page_title="نظام تحليل المناقصات - شركة شبه الجزيرة للمقاولات",
89
- page_icon="📊",
90
- layout="wide",
91
- initial_sidebar_state="expanded",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  )
93
 
94
- # إضافة CSS المخصص
95
- with open(os.path.join(current_dir, "web", "styles", "main.css")) as f:
96
- st.markdown(f"<style>{f.read()}</style>", unsafe_allow_html=True)
 
97
 
98
- # إضافة CSS للغة العربية
99
- with open(os.path.join(current_dir, "web", "styles", "rtl.css")) as f:
100
- st.markdown(f"<style>{f.read()}</style>", unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
 
 
101
 
102
- # التطبيق الرئيسي
103
- def main():
104
- # تهيئة الجلسة وإعداد الصفحة
105
- initialize_session()
106
- setup_page()
107
 
108
- # إنشاء الشريط الجانبي
109
- selected_page = create_sidebar()
110
 
111
- # إنشاء رأس الصفحة
112
- create_header()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
 
114
- # عرض الصفحة المحددة
115
- if selected_page == "الرئيسية":
116
- show_home_page()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
117
 
118
- elif selected_page == "تحليل المناقصات":
119
- show_tender_analysis()
 
 
 
 
 
120
 
121
- elif selected_page == "تحليل المتطلبات":
122
- show_requirements_analysis()
123
 
124
- elif selected_page == "تقدير التكاليف":
125
- show_cost_estimation()
 
 
 
 
 
 
 
 
 
 
 
 
126
 
127
- elif selected_page == "تحليل المخاطر":
128
- show_risk_analysis()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
129
 
130
- elif selected_page == "الجدول الزمني":
131
- show_timeline()
132
 
133
- elif selected_page == "المحتوى المحلي":
134
- show_local_content()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
135
 
136
- elif selected_page == "سلاسل الإمداد":
137
- show_supply_chain()
138
 
139
- elif selected_page == "المشتريات":
140
- show_procurement()
141
 
142
- elif selected_page == "الموردون والمقاولون":
143
- show_vendors()
144
 
145
- elif selected_page == "المشاريع المستقبلية":
146
- show_future_projects()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
 
148
- elif selected_page == "توقع احتمالية النجاح":
149
- show_success_prediction()
150
 
151
- elif selected_page == "التقارير":
152
- show_reports()
153
 
154
- # تسجيل زيارة الصفحة
155
- logger.info(f"تمت زيارة صفحة {selected_page}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
156
 
157
  if __name__ == "__main__":
158
  main()
 
 
 
 
 
 
 
 
1
  import os
2
  import sys
 
 
 
 
 
 
3
  import streamlit as st
4
+ import logging
5
  import pandas as pd
6
  import numpy as np
7
+ from datetime import datetime, timedelta
8
+ import time
9
  import plotly.express as px
10
  import plotly.graph_objects as go
11
+ from plotly.subplots import make_subplots
12
+ import json
13
+ import base64
14
+ from io import BytesIO
15
+
16
+ # إضافة المسار الرئيسي للمشروع إلى PATH
17
+ sys.path.append(os.path.dirname(os.path.abspath(__file__)))
18
+
19
+ # تكوين الصفحة
20
+ st.set_page_config(
21
+ page_title="نظام WAHBi-AI-V2",
22
+ page_icon="📋",
23
+ layout="wide",
24
+ initial_sidebar_state="expanded"
25
+ )
26
+
27
+ # إضافة CSS للدعم العربي وتحسين المظهر
28
+ def add_custom_css():
29
+ custom_css = """
30
+ @import url('https://fonts.googleapis.com/css2?family=Tajawal:wght@400;500;700&display=swap');
31
+
32
+ * {
33
+ font-family: 'Tajawal', sans-serif;
34
+ }
35
+
36
+ html {
37
+ direction: rtl;
38
+ }
39
+
40
+ .stApp {
41
+ direction: rtl;
42
+ }
43
+
44
+ .css-1d391kg, .css-1cpxqw2 {
45
+ direction: rtl;
46
+ text-align: right;
47
+ }
48
+
49
+ div[data-testid="stVerticalBlock"] {
50
+ direction: rtl;
51
+ }
52
+
53
+ button[data-testid="baseButton-secondary"] {
54
+ background-color: #1e88e5;
55
+ border-color: #1e88e5;
56
+ color: white;
57
+ }
58
+
59
+ button[data-testid="baseButton-primary"] {
60
+ background-color: #28a745;
61
+ border-color: #28a745;
62
+ }
63
+
64
+ div[data-testid="stMetricValue"] {
65
+ font-size: 1.5rem;
66
+ font-weight: bold;
67
+ color: #1e88e5;
68
+ }
69
+
70
+ div[data-testid="stMetricDelta"] {
71
+ font-size: 0.9rem;
72
+ }
73
+
74
+ div[data-testid="stMetricLabel"] {
75
+ font-weight: 500;
76
+ }
77
+
78
+ h1, h2, h3, h4, h5, h6 {
79
+ font-family: 'Tajawal', sans-serif;
80
+ font-weight: 700;
81
+ }
82
+
83
+ .dashboard-title {
84
+ text-align: center;
85
+ margin-bottom: 2rem;
86
+ }
87
+
88
+ .insights-box {
89
+ border: 1px solid #e0e0e0;
90
+ border-radius: 5px;
91
+ padding: 1rem;
92
+ background-color: #f9f9f9;
93
+ }
94
+
95
+ .stTabs [data-baseweb="tab-list"] {
96
+ direction: rtl;
97
+ }
98
+
99
+ .stTabs [data-baseweb="tab"] {
100
+ direction: rtl;
101
+ text-align: right;
102
+ }
103
+
104
+ /* تصحيح مشكلة الجداول */
105
+ .stDataFrame {
106
+ direction: rtl;
107
+ }
108
+
109
+ /* تصحيح الاتجاه في فلاتر متعدد الاختيار */
110
+ div[data-testid="stMultiSelect"] {
111
+ direction: rtl;
112
+ text-align: right;
113
+ }
114
+ """
115
+ st.markdown(f'<style>{custom_css}</style>', unsafe_allow_html=True)
116
+
117
+ # إضافة CSS
118
+ add_custom_css()
119
+
120
+ # إعداد نظام التسجيل
121
+ def setup_app_logging():
122
+ """إعداد نظام التسجيل"""
123
+ try:
124
+ log_dir = "logs"
125
+ os.makedirs(log_dir, exist_ok=True)
126
+ logging.basicConfig(
127
+ filename=os.path.join(log_dir, f"app_{datetime.now().strftime('%Y%m%d')}.log"),
128
+ level=logging.INFO,
129
+ format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
130
+ )
131
+ return logging.getLogger(__name__)
132
+ except Exception as e:
133
+ st.error(f"خطأ في إعداد التسجيل: {str(e)}")
134
+ return logging.getLogger(__name__)
135
+
136
+ logger = setup_app_logging()
137
+
138
+ # دوال ونماذج محاكاة للوحدات الفعلية
139
+ def get_config():
140
+ """محاكاة لوحدة config.config.get_config"""
141
+ return {
142
+ "app": {
143
+ "name": "نظام WAHBi-AI-V2 لإدارة المناقصات والعقود",
144
+ "version": "1.2.0",
145
+ "description": "نظام متكامل لإدارة المناقصات والعقود مدعوم بالذكاء الاصطناعي"
146
+ },
147
+ "paths": {
148
+ "logs_dir": "logs",
149
+ "data_dir": "data",
150
+ "models_dir": "models",
151
+ "reports_dir": "reports"
152
+ },
153
+ "database": {
154
+ "host": "localhost",
155
+ "port": 5432,
156
+ "name": "wahbi_ai_db",
157
+ "user": "db_user"
158
+ },
159
+ "api": {
160
+ "base_url": "https://api.wahbi-ai.org",
161
+ "version": "v1",
162
+ "timeout": 30
163
+ },
164
+ "ai": {
165
+ "models": {
166
+ "text_analysis": "ar_nlp_v2",
167
+ "risk_assessment": "risk_model_v1",
168
+ "prediction": "tender_prediction_v3"
169
+ },
170
+ "parameters": {
171
+ "confidence_threshold": 0.75,
172
+ "batch_size": 16
173
+ }
174
+ }
175
+ }
176
+
177
+ def load_local_content():
178
+ """محاكاة لوحدة modules.local_content.load_local_content"""
179
+ logger.info("تحميل بيانات المحتوى المحلي")
180
+ return True
181
+
182
+ def load_ai_models():
183
+ """محاكاة لوحدة modules.ai_models.load_ai_models"""
184
+ logger.info("تحميل نماذج الذكاء الاصطناعي")
185
+ return True
186
+
187
+ def process_document(document_path):
188
+ """محاكاة لوحدة modules.document_processor.process_document"""
189
+ logger.info(f"معالجة المستند: {document_path}")
190
+ return {
191
+ "success": True,
192
+ "pages": 12,
193
+ "entities": 45,
194
+ "requirements": 32
195
+ }
196
+
197
+ def analyze_requirements(req_text):
198
+ """محاكاة لوحدة modules.requirement_analyzer.analyze_requirements"""
199
+ logger.info("تحليل المتطلبات")
200
+ return {
201
+ "functional": [],
202
+ "non_functional": [],
203
+ "constraints": [],
204
+ "risks": []
205
+ }
206
+
207
+ def analyze_cost_risk(project_data):
208
+ """محاكاة لوحدة modules.cost_risk_analyzer.analyze_cost_risk"""
209
+ logger.info("تحليل مخاطر التكلفة")
210
+ return {
211
+ "total_risk_score": 0.65,
212
+ "cost_overrun_probability": 0.35,
213
+ "schedule_delay_probability": 0.42
214
+ }
215
+
216
+ def init_database():
217
+ """محاكاة لوحدة utils.database.init_database"""
218
+ logger.info("تهيئة قاعدة البيانات")
219
+ return True
220
 
221
+ def setup_logging():
222
+ """محاكاة لوحدة utils.helpers.setup_logging"""
223
+ logger.info("إعداد نظام التسجيل")
224
+ return True
225
+
226
+ def handle_uploaded_files(files):
227
+ """محاكاة لوحدة utils.file_handler.handle_uploaded_files"""
228
+ logger.info(f"معالجة الملفات المرفوعة: {len(files)} ملفات")
229
+ return {
230
+ "success": True,
231
+ "processed": len(files)
232
+ }
233
+
234
+ def setup_api_connections():
235
+ """محاكاة لوحدة utils.api_integrations.setup_api_connections"""
236
+ logger.info("إعداد اتصالات API")
237
+ return True
238
+
239
+ def get_procurement_plan(tender_id):
240
+ """محاكاة لوحدة supply_chain.procurement_planner.get_procurement_plan"""
241
+ logger.info(f"الحصول على خطة المشتريات للمناقصة: {tender_id}")
242
+ return {
243
+ "phases": [
244
+ {"name": "التخطيط", "start": "2024-04-01", "end": "2024-04-15"},
245
+ {"name": "طرح المناقصة", "start": "2024-04-16", "end": "2024-05-15"},
246
+ {"name": "التقييم", "start": "2024-05-16", "end": "2024-06-01"},
247
+ {"name": "الترسية", "start": "2024-06-02", "end": "2024-06-10"},
248
+ {"name": "التعاقد", "start": "2024-06-11", "end": "2024-06-25"}
249
+ ],
250
+ "estimated_cost": 3500000,
251
+ "local_content_target": 60
252
+ }
253
+
254
+ def analyze_project_requirements(req_file):
255
+ """محاكاة لوحدة analysis.requirement_analyzer.analyze_project_requirements"""
256
+ logger.info(f"تحليل متطلبات المشروع: {req_file}")
257
+ return {
258
+ "total_requirements": 32,
259
+ "functional_requirements": 24,
260
+ "non_functional_requirements": 8,
261
+ "complexity": "متوسطة",
262
+ "effort_estimate": "85 يوم عمل"
263
+ }
264
+
265
+ def analyze_risks(project_data):
266
+ """محاكاة لوحدة analysis.risk_analyzer.analyze_risks"""
267
+ logger.info("تحليل المخاطر")
268
+ return {
269
+ "risk_count": 12,
270
+ "high_risks": 3,
271
+ "medium_risks": 5,
272
+ "low_risks": 4
273
+ }
274
+
275
+ def estimate_costs(project_scope):
276
+ """محاكاة لوحدة analysis.cost_estimator.estimate_costs"""
277
+ logger.info("تقدير التكاليف")
278
+ return {
279
+ "total_cost": 4250000,
280
+ "labor_cost": 2800000,
281
+ "material_cost": 850000,
282
+ "overhead_cost": 600000
283
+ }
284
+
285
+ def analyze_local_content(supply_chain_data):
286
+ """محاكاة لوحدة analysis.local_content_analyzer.analyze_local_content"""
287
+ logger.info("تحليل المحتوى المحلي")
288
+ return {
289
+ "average_local_content": 62.5,
290
+ "potential_increase": 15.8,
291
+ "suppliers_count": {
292
+ "local": 12,
293
+ "foreign": 5,
294
+ "joint": 3
295
  }
296
+ }
297
+
298
+ # تحميل بيانات العرض التوضيحي
299
+ def load_demo_data():
300
+ """تحميل بيانات توضيحية للعرض"""
301
+ # بيانات المناقصات
302
+ tenders_data = {
303
+ "رقم المناقصة": [f"RFP-2024-{i:03d}" for i in range(1, 21)],
304
+ "العنوان": [
305
+ "توريد معدات تقنية", "خدمات صيانة", "تطوير نظام إلكتروني",
306
+ "توريد أجهزة طبية", "خدمات استشارية", "تنفيذ مشروع بنية تحتية",
307
+ "خدمات أمن المعلومات", "توريد أثاث مكتبي", "تطوير تطبيقات موبايل",
308
+ "خدمات تدريب", "توريد وتركيب أنظمة مراقبة", "صيانة مباني",
309
+ "تطوير محتوى تعليمي", "خدمات نظافة", "توريد سيارات",
310
+ "تنفيذ حملة إعلامية", "تطوير موقع إلكتروني", "خدمات لوجستية",
311
+ "توريد مستلزمات مكتبية", "تركيب أنظمة تكييف"
312
+ ],
313
+ "تاريخ الإعلان": [
314
+ (datetime.now() - timedelta(days=np.random.randint(1, 60))).strftime('%Y-%m-%d')
315
+ for _ in range(20)
316
+ ],
317
+ "تاريخ الإغلاق": [
318
+ (datetime.now() + timedelta(days=np.random.randint(5, 45))).strftime('%Y-%m-%d')
319
+ for _ in range(20)
320
+ ],
321
+ "القيمة التقديرية": [
322
+ round(np.random.uniform(100000, 5000000), -3)
323
+ for _ in range(20)
324
+ ],
325
+ "الحالة": np.random.choice(
326
+ ["جديدة", "مفتوحة", "قيد التقييم", "معلقة", "مغلقة", "ملغاة"],
327
+ size=20,
328
+ p=[0.15, 0.25, 0.25, 0.1, 0.2, 0.05]
329
+ ),
330
+ "نسبة النجاح المتوقعة": [
331
+ round(np.random.uniform(30, 95), 1)
332
+ for _ in range(20)
333
+ ]
334
+ }
335
+
336
+ # بيانات العقود
337
+ contracts_data = {
338
+ "رقم العقد": [f"CONT-2024-{i:03d}" for i in range(1, 16)],
339
+ "رقم المناقصة": [f"RFP-2024-{i:03d}" for i in range(1, 16)],
340
+ "المورد": [
341
+ "شركة التقنية المتطورة", "مؤسسة الحلول الذكية", "شركة الخدمات المتكاملة",
342
+ "مجموعة الإبداع التقني", "شركة التطوير الرقمي", "مؤسسة الجودة الشاملة",
343
+ "شركة الاتصالات المتقدمة", "مؤسسة البناء الحديث", "شركة التقنيات الذكية",
344
+ "مجموعة الخدمات الاستشارية", "شركة الحلول الهندسية", "مؤسسة التطوير والابتكار",
345
+ "شركة الأنظمة المتكاملة", "مجموعة الخدمات اللوجستية", "شركة المشاريع التقنية"
346
+ ],
347
+ "تاريخ البدء": [
348
+ (datetime.now() - timedelta(days=np.random.randint(1, 120))).strftime('%Y-%m-%d')
349
+ for _ in range(15)
350
+ ],
351
+ "تاريخ الانتهاء": [
352
+ (datetime.now() + timedelta(days=np.random.randint(30, 365))).strftime('%Y-%m-%d')
353
+ for _ in range(15)
354
+ ],
355
+ "القيمة": [
356
+ round(np.random.uniform(80000, 4500000), -3)
357
+ for _ in range(15)
358
+ ],
359
+ "نسبة الإنجاز": [
360
+ round(np.random.uniform(0, 100), 1)
361
+ for _ in range(15)
362
+ ],
363
+ "المحتوى المحلي": [
364
+ round(np.random.uniform(20, 95), 1)
365
+ for _ in range(15)
366
+ ],
367
+ "مستوى المخاطر": np.random.choice(
368
+ ["منخفض", "متوسط", "عالي"],
369
+ size=15,
370
+ p=[0.4, 0.4, 0.2]
371
+ )
372
+ }
373
+
374
+ # بيانات المخاطر
375
+ risks_data = {
376
+ "الرمز": [f"RISK-{i:02d}" for i in range(1, 13)],
377
+ "الوصف": [
378
+ "تأخر في تسليم المواد", "تجاوز الميزانية المخططة", "مشاكل في جودة المنتجات",
379
+ "تغيير في المتطلبات", "مشاكل في توفر الموارد", "تضارب في الجدول الزمني",
380
+ "مشاكل فنية غير متوقعة", "تغييرات في الأنظمة واللوائح", "تأخر في الموافقات",
381
+ "مشاكل مع الموردين الفرعيين", "صعوبات في الحصول على التصاريح", "نقص في المهارات المطلوبة"
382
+ ],
383
+ "التأثير": np.random.choice(
384
+ ["منخفض", "متوسط", "عالي", "حرج"],
385
+ size=12,
386
+ p=[0.2, 0.4, 0.3, 0.1]
387
+ ),
388
+ "الاحتمالية": np.random.choice(
389
+ ["منخفضة", "متوسطة", "عالية"],
390
+ size=12,
391
+ p=[0.3, 0.5, 0.2]
392
+ ),
393
+ "المعالجة": np.random.choice(
394
+ ["تجنب", "تخفيف", "نقل", "قبول"],
395
+ size=12
396
+ ),
397
+ "المسؤول": [
398
+ "مدير المشروع", "مدير المشتريات", "مدير الجودة", "مدير المالية",
399
+ "مدير تقنية المعلومات", "مدير الموارد البشرية", "مدير العمليات",
400
+ "المستشار القانوني", "مدير المشروع", "مدير المشتريات",
401
+ "مدير الجودة", "مدير المالية"
402
+ ],
403
+ "الحالة": np.random.choice(
404
+ ["جديدة", "قيد المعالجة", "معالجة", "مغلقة"],
405
+ size=12,
406
+ p=[0.25, 0.4, 0.25, 0.1]
407
+ )
408
+ }
409
 
410
+ # بيانات المحتوى المحلي
411
+ local_content_data = {
412
+ "الفئة": ["توظيف", "توطين التقنية", "سلاسل التوريد", "البحث والتطوير", "التدريب"],
413
+ "النسبة المستهدفة": [60, 40, 55, 25, 45],
414
+ "النسبة الحالية": [53.2, 35.8, 48.7, 18.4, 42.1],
415
+ "التغير السنوي": ["+8.2%", "+5.5%", "+3.2%", "+7.1%", "+9.3%"]
416
+ }
417
+
418
+ # بيانات التحليل المالي
419
+ financial_data = {
420
+ "الشهر": [f"شهر {i}" for i in range(1, 13)],
421
+ "المخطط": [
422
+ round(np.random.uniform(1000000, 1500000), -3)
423
+ for _ in range(12)
424
+ ],
425
+ "الفعلي": [
426
+ round(np.random.uniform(800000, 1600000), -3)
427
+ for _ in range(12)
428
+ ]
429
+ }
430
+
431
+ financial_df = pd.DataFrame(financial_data)
432
+ financial_df["الفرق"] = financial_df["الفعلي"] - financial_df["المخطط"]
433
+ financial_df["نسبة الانحراف"] = (financial_df["الفرق"] / financial_df["المخطط"] * 100).round(1)
434
+
435
+ return pd.DataFrame(tenders_data), pd.DataFrame(contracts_data), pd.DataFrame(risks_data), pd.DataFrame(local_content_data), financial_df
436
 
437
+ def initialize_app():
438
+ """تهيئة التطبيق وتحميل المتطلبات الأساسية"""
439
+ try:
440
+ # إعداد متغيرات الجلسة
441
+ if 'is_initialized' not in st.session_state:
442
+ st.session_state.is_initialized = False
443
+
444
+ config = get_config()
445
+ st.session_state.app_name = config["app"]["name"]
446
+ st.session_state.app_version = config["app"]["version"]
447
+ st.session_state.user_role = "مدير النظام"
448
+
449
+ # محاكاة تهيئة النظام
450
+ init_database()
451
+ load_local_content()
452
+ load_ai_models()
453
+ setup_api_connections()
454
+
455
+ # تحميل البيانات التوضيحية وتخزينها في الجلسة
456
+ tenders_df, contracts_df, risks_df, local_content_df, financial_df = load_demo_data()
457
+ st.session_state.tenders_df = tenders_df
458
+ st.session_state.contracts_df = contracts_df
459
+ st.session_state.risks_df = risks_df
460
+ st.session_state.local_content_df = local_content_df
461
+ st.session_state.financial_df = financial_df
462
+
463
+ st.session_state.is_initialized = True
464
+
465
+ # تسجيل بدء تشغيل التطبيق
466
+ logger.info(f"تم بدء تشغيل {st.session_state.app_name} v{st.session_state.app_version}")
467
+
468
+ return True
469
+ except Exception as e:
470
+ logger.error(f"خطأ في تهيئة التطبيق: {str(e)}")
471
+ st.error(f"خطأ في تهيئة التطبيق: {str(e)}")
472
+ return False
473
+
474
+ def render_sidebar():
475
+ """عرض القائمة الجانبية"""
476
+ with st.sidebar:
477
+ # عنوان التطبيق
478
+ st.title(f"📋 {st.session_state.app_name}")
479
+ st.caption(f"الإصدار: {st.session_state.app_version}")
480
+
481
+ st.markdown("---")
482
+
483
+ # القائمة الرئيسية
484
+ selected_page = st.radio(
485
+ "القائمة الرئيسية:",
486
+ ["الرئيسية", "المناقصات والعقود", "تحليل المتطلبات", "تخطيط سلسلة التوريد", "تحليل المخاطر", "توقع النجاح", "المحتوى المحلي", "التقارير", "لوحة المؤشرات"]
487
+ )
488
+
489
+ st.markdown("---")
490
+
491
+ # إحصائيات سريعة
492
+ st.subheader("إحصائيات سريعة")
493
+
494
+ # عرض بعض الإحصائيات
495
+ col1, col2 = st.columns(2)
496
+ with col1:
497
+ active_tenders = len(st.session_state.tenders_df[st.session_state.tenders_df['الحالة'].isin(['جديدة', 'مفتوحة', 'قيد التقييم'])])
498
+ st.metric(label="المناقصات النشطة", value=active_tenders)
499
+
500
+ with col2:
501
+ active_contracts = len(st.session_state.contracts_df[pd.to_datetime(st.session_state.contracts_df['تاريخ الانتهاء']) > datetime.now()])
502
+ st.metric(label="العقود الجارية", value=active_contracts)
503
+
504
+ st.markdown("---")
505
+
506
+ # معلومات المستخدم
507
+ st.subheader("معلومات المستخدم")
508
+ st.write(f"**المستخدم:** {st.session_state.user_role}")
509
+ st.write(f"**تاريخ الدخول:** {datetime.now().strftime('%Y-%m-%d %H:%M')}")
510
+
511
+ st.markdown("---")
512
+
513
+ # معلومات النظام
514
+ st.caption("© 2024 جميع الحقوق محفوظة")
515
+ st.caption("فريق تطوير البرمجيات")
516
+
517
+ return selected_page
518
+
519
+ def render_header():
520
+ """عرض رأس الصفحة"""
521
+ col1, col2, col3 = st.columns([2, 5, 2])
522
+
523
+ with col1:
524
+ st.write("## 📋")
525
+
526
+ with col2:
527
+ st.title("نظام WAHBi-AI-V2")
528
+ st.caption("منصة متكاملة لإدارة المناقصات والعقود مدعومة بالذكاء الاصطناعي")
529
+
530
+ with col3:
531
+ st.write(f"**التاريخ:** {datetime.now().strftime('%Y-%m-%d')}")
532
+ st.write(f"**المستخدم:** {st.session_state.user_role}")
533
+
534
+ st.markdown("---")
535
+
536
+ def home_page():
537
+ """صفحة الرئيسية"""
538
+ # العنوان الرئيسي
539
+ st.markdown("<h1 style='text-align: center;'>نظام WAHBi-AI-V2 لإدارة المناقصات والعقود</h1>", unsafe_allow_html=True)
540
+ st.markdown("<p style='text-align: center; font-size: 1.2em;'>مدعوم بتقنيات الذكاء الاصطناعي والتحليل المتقدم</p>", unsafe_allow_html=True)
541
+
542
+ # مؤشرات الأداء الرئيسية
543
+ st.markdown("## 📊 مؤشرات الأداء الرئيسية")
544
+
545
+ col1, col2, col3, col4 = st.columns(4)
546
+
547
+ with col1:
548
+ active_tenders = len(st.session_state.tenders_df[st.session_state.tenders_df['الحالة'].isin(['جديدة', 'مفتوحة', 'قيد التقييم'])])
549
+ st.metric(
550
+ "المناقصات النشطة",
551
+ active_tenders,
552
+ "+3"
553
+ )
554
+
555
+ with col2:
556
+ active_contracts = len(st.session_state.contracts_df[pd.to_datetime(st.session_state.contracts_df['تاريخ الانتهاء']) > datetime.now()])
557
+ st.metric(
558
+ "العقود الجارية",
559
+ active_contracts,
560
+ "+1"
561
+ )
562
+
563
+ with col3:
564
+ avg_success = round(st.session_state.tenders_df['نسبة النجاح المتوقعة'].mean(), 1)
565
+ st.metric(
566
+ "متوسط نسبة النجاح المتوقعة",
567
+ f"{avg_success}%",
568
+ "+2.5%"
569
+ )
570
+
571
+ with col4:
572
+ avg_local_content = round(st.session_state.contracts_df['المحتوى المحلي'].mean(), 1)
573
+ st.metric(
574
+ "متوسط المحتوى المحلي",
575
+ f"{avg_local_content}%",
576
+ "+5.3%"
577
+ )
578
+
579
+ # رسوم بيانية
580
+ st.markdown("## 📈 تحليل البيانات")
581
+
582
+ tab1, tab2, tab3 = st.tabs(["📑 المناقصات", "📝 العقود", "⚠️ المخاطر"])
583
+
584
+ with tab1:
585
+ col1, col2 = st.columns(2)
586
+
587
+ with col1:
588
+ # توزيع المناقصات حسب الحالة
589
+ status_counts = st.session_state.tenders_df['الحالة'].value_counts().reset_index()
590
+ status_counts.columns = ['الحالة', 'العدد']
591
+
592
+ fig = px.pie(
593
+ status_counts,
594
+ values='العدد',
595
+ names='الحالة',
596
+ title='توزيع المناقصات حسب الحالة',
597
+ color_discrete_sequence=px.colors.qualitative.Bold
598
+ )
599
+ fig.update_layout(
600
+ title_font_size=20,
601
+ title_font_family="Tajawal",
602
+ title_x=0.5,
603
+ legend_title_font_size=16
604
+ )
605
+ st.plotly_chart(fig, use_container_width=True)
606
+
607
+ with col2:
608
+ # نسب النجاح المتوقعة للمناقصات النشطة
609
+ active_tenders = st.session_state.tenders_df[st.session_state.tenders_df['الحالة'].isin(['جديدة', 'مفتوحة', 'قيد التقييم'])]
610
+ active_tenders = active_tenders.sort_values('نسبة النجاح المتوقعة', ascending=False).head(8)
611
+
612
+ fig = px.bar(
613
+ active_tenders,
614
+ x='نسبة النجاح المتوقعة',
615
+ y='رقم المناقصة',
616
+ title='نسب النجاح المتوقعة للمناقصات النشطة',
617
+ color='نسبة النجاح المتوقعة',
618
+ color_continuous_scale='Viridis',
619
+ orientation='h'
620
+ )
621
+ fig.update_layout(
622
+ title_font_size=20,
623
+ title_font_family="Tajawal",
624
+ title_x=0.5,
625
+ yaxis={'categoryorder':'total ascending'}
626
+ )
627
+ st.plotly_chart(fig, use_container_width=True)
628
+
629
+ with tab2:
630
+ col1, col2 = st.columns(2)
631
+
632
+ with col1:
633
+ # توزيع قيم العقود
634
+ fig = px.histogram(
635
+ st.session_state.contracts_df,
636
+ x='القيمة',
637
+ nbins=10,
638
+ title='توزيع قيم العقود',
639
+ color_discrete_sequence=['#3498db']
640
+ )
641
+ fig.update_layout(
642
+ title_font_size=20,
643
+ title_font_family="Tajawal",
644
+ title_x=0.5,
645
+ xaxis_title="القيمة (ريال)",
646
+ yaxis_title="عدد العقود"
647
+ )
648
+ st.plotly_chart(fig, use_container_width=True)
649
+
650
+ with col2:
651
+ # نسب المحتوى المحلي
652
+ fig = px.scatter(
653
+ st.session_state.contracts_df,
654
+ x='القيمة',
655
+ y='المحتوى المحلي',
656
+ size='نسبة الإنجاز',
657
+ color='مستوى المخاطر',
658
+ hover_name='رقم العقد',
659
+ title='نسب المحتوى المحلي للعقود',
660
+ color_discrete_map={
661
+ 'منخفض': '#2ecc71',
662
+ 'متوسط': '#f39c12',
663
+ 'عالي': '#e74c3c'
664
+ }
665
+ )
666
+ fig.update_layout(
667
+ title_font_size=20,
668
+ title_font_family="Tajawal",
669
+ title_x=0.5,
670
+ xaxis_title="القيمة (ريال)",
671
+ yaxis_title="نسبة المحتوى المحلي (%)"
672
+ )
673
+ st.plotly_chart(fig, use_container_width=True)
674
+
675
+ with tab3:
676
+ col1, col2 = st.columns(2)
677
+
678
+ with col1:
679
+ # مصفوفة المخاطر
680
+ risk_matrix = pd.crosstab(
681
+ st.session_state.risks_df['التأثير'],
682
+ st.session_state.risks_df['الاحتمالية'],
683
+ margins=False
684
+ )
685
+
686
+ # تحويل القيم إلى حرارية
687
+ risk_severity = {
688
+ ('منخفض', 'منخفضة'): 1,
689
+ ('منخفض', 'متوسطة'): 2,
690
+ ('منخفض', 'عالية'): 3,
691
+ ('متوسط', 'منخفضة'): 2,
692
+ ('متوسط', 'متوسطة'): 4,
693
+ ('متوسط', 'عالية'): 6,
694
+ ('عالي', 'منخفضة'): 3,
695
+ ('عالي', 'متوسطة'): 6,
696
+ ('عالي', 'عالية'): 9,
697
+ ('حرج', 'منخفضة'): 4,
698
+ ('حرج', 'متوسطة'): 8,
699
+ ('حرج', 'عالية'): 12
700
+ }
701
+
702
+ # تحضير بيانات المصفوفة
703
+ impact_order = ['منخفض', 'متوسط', 'عالي', 'حرج']
704
+ probability_order = ['منخفضة', 'متوسطة', 'عالية']
705
+
706
+ # إنشاء مصفوفة حرارية
707
+ heat_values = []
708
+ annotations = []
709
+
710
+ for impact in impact_order:
711
+ heat_row = []
712
+ for prob in probability_order:
713
+ try:
714
+ value = risk_matrix.loc[impact, prob]
715
+ except:
716
+ value = 0
717
+ heat_row.append(risk_severity.get((impact, prob), 0))
718
+ annotations.append(dict(
719
+ text=str(value),
720
+ x=prob,
721
+ y=impact,
722
+ showarrow=False
723
+ ))
724
+ heat_values.append(heat_row)
725
+
726
+ # إنشاء الرسم البياني
727
+ fig = go.Figure(data=go.Heatmap(
728
+ z=heat_values,
729
+ x=probability_order,
730
+ y=impact_order,
731
+ colorscale=[
732
+ [0.0, "#2ecc71"], # أخضر للمخاطر المنخفضة
733
+ [0.33, "#f1c40f"], # أصفر للمخاطر المتوسطة
734
+ [0.66, "#e67e22"], # برتقالي للمخاطر العالية
735
+ [1.0, "#e74c3c"] # أحمر للمخاطر الحرجة
736
+ ],
737
+ showscale=False
738
+ ))
739
+
740
+ # إضافة النصوص
741
+ for annotation in annotations:
742
+ fig.add_annotation(annotation)
743
+
744
+ fig.update_layout(
745
+ title='مصفوفة المخاطر',
746
+ title_font_size=20,
747
+ title_font_family="Tajawal",
748
+ title_x=0.5,
749
+ xaxis_title="الاحتمالية",
750
+ yaxis_title="التأثير"
751
+ )
752
+
753
+ st.plotly_chart(fig, use_container_width=True)
754
+
755
+ with col2:
756
+ # توزيع المخاطر حسب استراتيجية المعالجة
757
+ treatment_counts = st.session_state.risks_df['المعالجة'].value_counts().reset_index()
758
+ treatment_counts.columns = ['المعالجة', 'العدد']
759
+
760
+ fig = px.bar(
761
+ treatment_counts,
762
+ x='المعالجة',
763
+ y='العدد',
764
+ title='استراتيجيات معالجة المخاطر',
765
+ color='المعالجة',
766
+ color_discrete_sequence=px.colors.qualitative.Pastel
767
+ )
768
+ fig.update_layout(
769
+ title_font_size=20,
770
+ title_font_family="Tajawal",
771
+ title_x=0.5,
772
+ xaxis_title="استراتيجية المعالجة",
773
+ yaxis_title="عدد المخاطر"
774
+ )
775
+ st.plotly_chart(fig, use_container_width=True)
776
+
777
+ # قسم المناقصات القادمة
778
+ st.markdown("## 📅 المناقصات القادمة للإغلاق")
779
+ upcoming_tenders = st.session_state.tenders_df[
780
+ (pd.to_datetime(st.session_state.tenders_df['تاريخ الإغلاق']) > datetime.now()) &
781
+ (pd.to_datetime(st.session_state.tenders_df['تاريخ الإغلاق']) <= datetime.now() + timedelta(days=14))
782
+ ]
783
+ upcoming_tenders = upcoming_tenders.sort_values('تاريخ الإغلاق')
784
+
785
+ if not upcoming_tenders.empty:
786
+ # عرض المناقصات في جدول
787
+ upcoming_display = upcoming_tenders[['رقم المناقصة', 'العنوان', 'تاريخ الإغلاق', 'القيمة التقديرية', 'نسبة النجاح المتوقعة']]
788
+ upcoming_display['أيام متبقية'] = (pd.to_datetime(upcoming_display['تاريخ الإغلاق']) - datetime.now()).dt.days
789
+ upcoming_display['القيمة التقديرية'] = upcoming_display['القيمة التقديرية'].apply(lambda x: f"{x:,.0f} ريال")
790
+ upcoming_display['نسبة النجاح المتوقعة'] = upcoming_display['نسبة النجاح المتوقعة'].apply(lambda x: f"{x}%")
791
+
792
+ st.dataframe(
793
+ upcoming_display,
794
+ hide_index=True,
795
+ use_container_width=True
796
+ )
797
+ else:
798
+ st.info("لا توجد مناقصات ستغلق خلال الأسبوعين القادمين")
799
+
800
+ # قسم تحليل الذكاء الاصطناعي
801
+ st.markdown("## 🤖 تحليلات الذكاء الاصطناعي")
802
+
803
+ col1, col2 = st.columns(2)
804
+
805
+ with col1:
806
+ st.markdown("### التنبؤ بنجاح المناقصات")
807
+ st.markdown("""
808
+ تستخدم خوارزميات الذكاء الاصطناعي لتحليل البيانات التاريخية وتحديد العوامل المؤثرة في نجاح المناقصات.
809
+ يمكن للنظام التنبؤ بنسب النجاح المتوقعة للمناقصات الجديدة بناءً على خصائصها ومتطلباتها.
810
+ """)
811
+
812
+ if st.button("تحليل مناقصة جديدة", key="analyze_new_tender"):
813
+ with st.spinner("جاري تحليل المناق��ة..."):
814
+ time.sleep(2) # محاكاة وقت المعالجة
815
+ st.success("تم التحليل بنجاح!")
816
+ st.info("نسبة النجاح المتوقعة للمناقصة: 78.5%")
817
+ st.markdown("""
818
+ **العوامل المؤثرة في النتيجة:**
819
+ - قدرة عالية على تلبية المتطلبات الفنية (+15%)
820
+ - توافق المنتج مع المعايير المطلوبة (+12%)
821
+ - خبرة سابقة مع نفس الجهة (+10%)
822
+ - المنافسة المتوقعة قوية (-7%)
823
+ """)
824
+
825
+ with col2:
826
+ st.markdown("### تحليل المتطلبات")
827
+ st.markdown("""
828
+ يقوم النظام بتحليل وثائق المتطلبات باستخدام تقنيات معالجة اللغة الطبيعية لاستخراج البنود المهمة والمخاطر المحتملة.
829
+ يساعد هذا التحليل في تقييم مدى تعقيد المتطلبات وتحديد النقاط التي تحتاج إلى اهتمام خاص.
830
+ """)
831
+
832
+ uploaded_file = st.file_uploader("رفع ملف متطلبات للتحليل", type=['pdf', 'docx', 'txt'])
833
+ if uploaded_file is not None:
834
+ with st.spinner("جاري تحليل المتطلبات..."):
835
+ time.sleep(3) # محاكاة وقت المعالجة
836
+ st.success("تم تحليل المتطلبات بنجاح!")
837
+
838
+ # عرض نتائج التحليل
839
+ col1, col2 = st.columns(2)
840
+ with col1:
841
+ st.metric("عدد المتطلبات", "27")
842
+ st.metric("المتطلبات الوظيفية", "19")
843
+ st.metric("المتطلبات غير الوظيفية", "8")
844
+
845
+ with col2:
846
+ st.metric("درجة التعقيد", "متوسطة")
847
+ st.metric("المخاطر المحتملة", "4")
848
+ st.metric("البنود الغامضة", "3")
849
+
850
+ def dashboard_page():
851
+ """صفحة لوحة المؤشرات"""
852
+ st.markdown("# 📊 لوحة المؤشرات")
853
+
854
+ st.markdown("""
855
+ ## لوحة مؤشرات الأداء الرئيسية
856
+
857
+ استخدم هذه اللوحة لمراقبة أداء المؤشرات الرئيسية للنظام واستعراض الإحصائيات والاتجاهات.
858
+ """)
859
+
860
+ # المؤشرات الرئيسية
861
+ col1, col2, col3, col4 = st.columns(4)
862
+
863
+ with col1:
864
+ avg_success = round(st.session_state.tenders_df['نسبة النجاح المتوقعة'].mean(), 1)
865
+ st.metric(
866
+ "متوسط نسبة النجاح",
867
+ f"{avg_success}%",
868
+ "+2.5%"
869
+ )
870
+
871
+ with col2:
872
+ avg_local_content = round(st.session_state.contracts_df['المحتوى المحلي'].mean(), 1)
873
+ st.metric(
874
+ "متوسط المحتوى المحلي",
875
+ f"{avg_local_content}%",
876
+ "+5.3%"
877
+ )
878
+
879
+ with col3:
880
+ active_contracts = len(st.session_state.contracts_df[pd.to_datetime(st.session_state.contracts_df['تاريخ الانتهاء']) > datetime.now()])
881
+ avg_contract_value = round(st.session_state.contracts_df['القيمة'].mean() / 1000000, 2)
882
+ st.metric(
883
+ "متوسط قيمة العقود",
884
+ f"{avg_contract_value} مليون",
885
+ "+0.8 مليون"
886
+ )
887
+
888
+ with col4:
889
+ high_risks = len(st.session_state.risks_df[st.session_state.risks_df['التأثير'].isin(['عالي', 'حرج']) & st.session_state.risks_df['الاحتمالية'].isin(['متوسطة', 'عالية'])])
890
+ st.metric(
891
+ "المخاطر العالية",
892
+ high_risks,
893
+ "-2"
894
+ )
895
+
896
+ # الرسوم البيانية الرئيسية
897
+ st.markdown("## تحليلات رئيسية")
898
+
899
+ col1, col2 = st.columns(2)
900
+
901
+ with col1:
902
+ # توزيع المناقصات حسب الحالة
903
+ status_counts = st.session_state.tenders_df['الحالة'].value_counts().reset_index()
904
+ status_counts.columns = ['الحالة', 'العدد']
905
+
906
+ fig = px.pie(
907
+ status_counts,
908
+ values='العدد',
909
+ names='الحالة',
910
+ title='توزيع المناقصات حسب الحالة',
911
+ color_discrete_sequence=px.colors.qualitative.Bold
912
+ )
913
+ fig.update_layout(
914
+ title_font_size=20,
915
+ title_font_family="Tajawal",
916
+ title_x=0.5,
917
+ legend_title_font_size=16
918
+ )
919
+ st.plotly_chart(fig, use_container_width=True)
920
+
921
+ with col2:
922
+ # تحليل المحتوى المحلي
923
+ local_df = st.session_state.local_content_df
924
+
925
+ fig = go.Figure()
926
+
927
+ fig.add_trace(go.Bar(
928
+ x=local_df['الفئة'],
929
+ y=local_df['النسبة الحالية'],
930
+ name='النسبة الحالية',
931
+ marker_color='#3498db'
932
+ ))
933
+
934
+ fig.add_trace(go.Bar(
935
+ x=local_df['الفئة'],
936
+ y=local_df['النسبة المستهدفة'],
937
+ name='النسبة المستهدفة',
938
+ marker_color='#2ecc71'
939
+ ))
940
+
941
+ fig.update_layout(
942
+ barmode='group',
943
+ title_text='تحليل المحتوى المحلي',
944
+ title_font_size=20,
945
+ title_font_family="Tajawal",
946
+ title_x=0.5,
947
+ xaxis_title="الفئة",
948
+ yaxis_title="النسبة المئوية (%)",
949
+ legend_title="النسبة",
950
+ height=400
951
+ )
952
+
953
+ st.plotly_chart(fig, use_container_width=True)
954
+
955
+ # تحليل المالي
956
+ st.markdown("## التحليل المالي والموازنة")
957
+
958
+ financial_df = st.session_state.financial_df
959
+
960
+ fig = go.Figure()
961
+
962
+ fig.add_trace(go.Scatter(
963
+ x=financial_df['الشهر'],
964
+ y=financial_df['المخطط'],
965
+ name='المخطط',
966
+ line=dict(color='#3498db', width=2)
967
+ ))
968
+
969
+ fig.add_trace(go.Scatter(
970
+ x=financial_df['الشهر'],
971
+ y=financial_df['الفعلي'],
972
+ name='الفعلي',
973
+ line=dict(color='#e74c3c', width=2)
974
+ ))
975
+
976
+ fig.update_layout(
977
+ title_text='مقارنة التكاليف المخططة والفعلية',
978
+ title_font_size=20,
979
+ title_font_family="Tajawal",
980
+ title_x=0.5,
981
+ xaxis_title="الشهر",
982
+ yaxis_title="التكلفة (ريال)",
983
+ legend_title="النوع",
984
+ height=400
985
  )
986
 
987
+ st.plotly_chart(fig, use_container_width=True)
988
+
989
+ # المشاريع القادمة
990
+ st.markdown("## المشاريع والمناقصات القادمة")
991
 
992
+ upcoming_tenders = st.session_state.tenders_df[
993
+ (pd.to_datetime(st.session_state.tenders_df['تاريخ الإغلاق']) > datetime.now()) &
994
+ (pd.to_datetime(st.session_state.tenders_df['تاريخ الإغلاق']) <= datetime.now() + timedelta(days=30))
995
+ ]
996
+
997
+ if not upcoming_tenders.empty:
998
+ upcoming_display = upcoming_tenders[['رقم المناقصة', 'العنوان', 'تاريخ الإغلاق', 'القيمة التقديرية', 'نسبة النجاح المتوقعة']]
999
+ upcoming_display['أيام متبقية'] = (pd.to_datetime(upcoming_display['تاريخ الإغلاق']) - datetime.now()).dt.days
1000
+ upcoming_display['القيمة التقديرية'] = upcoming_display['القيمة التقديرية'].apply(lambda x: f"{x:,.0f} ريال")
1001
+ upcoming_display['نسبة النجاح المتوقعة'] = upcoming_display['نسبة النجاح المتوقعة'].apply(lambda x: f"{x}%")
1002
+
1003
+ st.dataframe(upcoming_display, hide_index=True, use_container_width=True)
1004
+ else:
1005
+ st.info("لا توجد مناقصات قادمة خلال الثلاثين يوماً القادمة.")
1006
 
1007
+ def procurement_page():
1008
+ """صفحة المناقصات والعقود"""
1009
+ st.markdown("# 📑 المناقصات والعقود")
 
 
1010
 
1011
+ tab1, tab2 = st.tabs(["المناقصات", "العقود"])
 
1012
 
1013
+ with tab1:
1014
+ st.markdown("## إدارة المناقصات")
1015
+
1016
+ # أزرار الإجراءات
1017
+ col1, col2, col3, col4 = st.columns(4)
1018
+ with col1:
1019
+ if st.button("🆕 إضافة مناقصة جديدة"):
1020
+ st.session_state.show_add_tender = True
1021
+
1022
+ with col2:
1023
+ st.button("🔍 بحث متقدم")
1024
+
1025
+ with col3:
1026
+ st.button("📊 تصدير التقرير")
1027
+
1028
+ with col4:
1029
+ st.button("🔄 تحديث البيانات")
1030
+
1031
+ # عرض جدول المناقصات
1032
+ st.markdown("### قائمة المناقصات")
1033
+
1034
+ # فلاتر
1035
+ col1, col2, col3 = st.columns(3)
1036
+ with col1:
1037
+ status_filter = st.multiselect(
1038
+ "الحالة:",
1039
+ ["الكل"] + list(st.session_state.tenders_df['الحالة'].unique()),
1040
+ default=["الكل"]
1041
+ )
1042
+
1043
+ with col2:
1044
+ date_range = st.date_input(
1045
+ "تاريخ الإعلان:",
1046
+ value=(
1047
+ (datetime.now() - timedelta(days=60)).date(),
1048
+ datetime.now().date()
1049
+ )
1050
+ )
1051
+
1052
+ with col3:
1053
+ min_value, max_value = st.slider(
1054
+ "القيمة التقديرية (ريال):",
1055
+ 0,
1056
+ int(st.session_state.tenders_df['القيمة التقديرية'].max()),
1057
+ (0, int(st.session_state.tenders_df['القيمة التقديرية'].max())),
1058
+ step=100000
1059
+ )
1060
+
1061
+ # تطبيق الفلاتر
1062
+ filtered_df = st.session_state.tenders_df.copy()
1063
+
1064
+ # فلتر الحالة
1065
+ if "الكل" not in status_filter:
1066
+ filtered_df = filtered_df[filtered_df['الحالة'].isin(status_filter)]
1067
+
1068
+ # فلتر التاريخ
1069
+ filtered_df = filtered_df[
1070
+ (pd.to_datetime(filtered_df['تاريخ الإعلان']) >= pd.Timestamp(date_range[0])) &
1071
+ (pd.to_datetime(filtered_df['تاريخ الإعلان']) <= pd.Timestamp(date_range[1]))
1072
+ ]
1073
+
1074
+ # فلتر القيمة
1075
+ filtered_df = filtered_df[
1076
+ (filtered_df['القيمة التقديرية'] >= min_value) &
1077
+ (filtered_df['القيمة التقديرية'] <= max_value)
1078
+ ]
1079
+
1080
+ # عرض الجدول
1081
+ st.dataframe(
1082
+ filtered_df,
1083
+ use_container_width=True,
1084
+ hide_index=True
1085
+ )
1086
+
1087
+ # نموذج إضافة مناقصة جديدة
1088
+ if 'show_add_tender' in st.session_state and st.session_state.show_add_tender:
1089
+ st.markdown("### إضافة مناقصة جديدة")
1090
+ with st.form("add_tender_form"):
1091
+ col1, col2 = st.columns(2)
1092
+
1093
+ with col1:
1094
+ tender_id = st.text_input("رقم المناقصة", f"RFP-2024-{len(st.session_state.tenders_df) + 1:03d}")
1095
+ title = st.text_input("عنوان المناقصة", "")
1096
+ start_date = st.date_input("تاريخ الإعلان", datetime.now())
1097
+
1098
+ with col2:
1099
+ end_date = st.date_input("تاريخ الإغلاق", datetime.now() + timedelta(days=30))
1100
+ estimated_value = st.number_input("القيمة التقديرية", min_value=0, value=1000000, step=100000)
1101
+ status = st.selectbox("الحالة", ["جديدة", "مفتوحة", "قيد التقييم", "معلقة", "مغلقة", "ملغاة"])
1102
+
1103
+ submitted = st.form_submit_button("حفظ المناقصة")
1104
+ cancel = st.form_submit_button("إلغاء")
1105
+
1106
+ if submitted:
1107
+ st.success("تم إضافة المناقصة بنجاح")
1108
+ st.session_state.show_add_tender = False
1109
+
1110
+ if cancel:
1111
+ st.session_state.show_add_tender = False
1112
 
1113
+ with tab2:
1114
+ st.markdown("## إدارة العقود")
1115
+
1116
+ # أزرار الإجراءات
1117
+ col1, col2, col3, col4 = st.columns(4)
1118
+ with col1:
1119
+ st.button("🆕 إضافة عقد جديد")
1120
+
1121
+ with col2:
1122
+ st.button("🔍 بحث متقدم", key="search_contracts")
1123
+
1124
+ with col3:
1125
+ st.button("📊 تصدير التقرير", key="export_contracts")
1126
+
1127
+ with col4:
1128
+ st.button("🔄 تحديث البيانات", key="refresh_contracts")
1129
+
1130
+ # عرض جدول العقود
1131
+ st.markdown("### قائمة العقود")
1132
+
1133
+ # فلاتر
1134
+ col1, col2 = st.columns(2)
1135
+ with col1:
1136
+ risk_filter = st.multiselect(
1137
+ "مستوى المخاطر:",
1138
+ ["الكل"] + list(st.session_state.contracts_df['مستوى المخاطر'].unique()),
1139
+ default=["الكل"]
1140
+ )
1141
+
1142
+ with col2:
1143
+ local_content_range = st.slider(
1144
+ "نسبة المحتوى المحلي (%):",
1145
+ 0, 100,
1146
+ (0, 100),
1147
+ step=10
1148
+ )
1149
+
1150
+ # تطبيق الفلاتر
1151
+ filtered_df = st.session_state.contracts_df.copy()
1152
+
1153
+ # فلتر مستوى المخاطر
1154
+ if "الكل" not in risk_filter:
1155
+ filtered_df = filtered_df[filtered_df['مستوى المخاطر'].isin(risk_filter)]
1156
+
1157
+ # فلتر المحتوى المحلي
1158
+ filtered_df = filtered_df[
1159
+ (filtered_df['المحتوى المحلي'] >= local_content_range[0]) &
1160
+ (filtered_df['المحتوى المحلي'] <= local_content_range[1])
1161
+ ]
1162
+
1163
+ # عرض الجدول
1164
+ st.dataframe(
1165
+ filtered_df,
1166
+ use_container_width=True,
1167
+ hide_index=True
1168
+ )
1169
+
1170
+ def requirements_analysis_page():
1171
+ """صفحة تحليل المتطلبات"""
1172
+ st.markdown("# 🔍 تحليل المتطلبات")
1173
+
1174
+ st.markdown("""
1175
+ ## نظام تحليل المتطلبات بالذكاء الاصطناعي
1176
 
1177
+ يقوم هذا النظام بتحليل وثائق المتطلبات باستخدام تقنيات معالجة اللغة الطبيعية والذكاء الاصطناعي لاستخراج:
1178
+ - المتطلبات الوظيفية وغير الوظيفية
1179
+ - التبعيات بين المتطلبات
1180
+ - المخاطر المحتملة
1181
+ - الشروط والقيود
1182
+ - تقدير الجهد والتكلفة
1183
+ """)
1184
 
1185
+ col1, col2 = st.columns(2)
 
1186
 
1187
+ with col1:
1188
+ st.markdown("### تحميل وثائق المتطلبات")
1189
+ uploaded_file = st.file_uploader("اختر ملف", type=['pdf', 'docx', 'txt'])
1190
+
1191
+ if uploaded_file is not None:
1192
+ st.success(f"تم تحميل الملف: {uploaded_file.name}")
1193
+
1194
+ if st.button("بدء التحليل"):
1195
+ with st.spinner("جاري تحليل المتطلبات..."):
1196
+ time.sleep(3) # محاكاة وقت المعالجة
1197
+ st.success("تم تحليل المستند بنجاح!")
1198
+
1199
+ # عرض نتائج التحليل في الجانب الآخر
1200
+ st.session_state.show_analysis_results = True
1201
 
1202
+ with col2:
1203
+ if 'show_analysis_results' in st.session_state and st.session_state.show_analysis_results:
1204
+ st.markdown("### نتائج التحليل")
1205
+
1206
+ tab1, tab2, tab3 = st.tabs(["ملخص", "المتطلبات المستخرجة", "المخاطر"])
1207
+
1208
+ with tab1:
1209
+ col1, col2 = st.columns(2)
1210
+ with col1:
1211
+ st.metric("إجمالي المتطلبات", "34")
1212
+ st.metric("المتطلبات الوظيفية", "26")
1213
+ st.metric("المتطلبات غير الوظيفية", "8")
1214
+
1215
+ with col2:
1216
+ st.metric("تقدير الجهد", "87 يوم عمل")
1217
+ st.metric("التكلفة التقديرية", "435,000 ريال")
1218
+ st.metric("درجة التعقيد", "متوسطة")
1219
+
1220
+ with tab2:
1221
+ requirements_demo = pd.DataFrame({
1222
+ "المعرف": [f"REQ-{i:03d}" for i in range(1, 11)],
1223
+ "النوع": ["وظيفي", "وظيفي", "غير وظيفي", "وظيفي", "وظيفي", "غير وظيفي", "وظيفي", "وظيفي", "غير وظيفي", "وظيفي"],
1224
+ "الوصف": [
1225
+ "يجب أن يوفر النظام واجهة لإدارة المستخدمين",
1226
+ "يجب أن يتيح النظام إمكانية إضافة مناقصات جديدة",
1227
+ "يجب أن يدعم النظام اللغة العربية",
1228
+ "يجب أن يوفر النظام تقارير عن حالة المناقصات",
1229
+ "يجب أن يقوم النظام بحساب نسبة المحتوى المحلي",
1230
+ "يجب أن يستجيب النظام في أقل من 3 ثواني",
1231
+ "يجب أن يدعم النظام تحميل المستندات",
1232
+ "يجب أن يوفر النظام واجهة لإدارة العقود",
1233
+ "يجب أن يعمل النظام على متصفحات الويب الحديثة",
1234
+ "يجب أن يوفر النظام نظام تنبيهات للمواعيد النهائية"
1235
+ ],
1236
+ "الأولوية": ["عالية", "عالية", "متوسطة", "عالية", "عالية", "منخفضة", "متوسطة", "عالية", "متوسطة", "متوسطة"],
1237
+ "التعقيد": ["متوسط", "بسيط", "بسيط", "متوسط", "معقد", "بسيط", "متوسط", "معقد", "بسيط", "متوسط"]
1238
+ })
1239
+
1240
+ st.dataframe(requirements_demo, use_container_width=True, hide_index=True)
1241
+
1242
+ with tab3:
1243
+ risks_demo = pd.DataFrame({
1244
+ "المعرف": [f"RISK-{i:03d}" for i in range(1, 6)],
1245
+ "الوصف": [
1246
+ "غموض في متطلبات حساب المحتوى المحلي",
1247
+ "تعارض بين متطلبات الأداء والوظائف المطلوبة",
1248
+ "عدم وضوح آلية تكامل النظام مع الأنظمة الخارجية",
1249
+ "تعقيد في متطلبات التقارير",
1250
+ "متطلبات أمنية غير محددة بوضوح"
1251
+ ],
1252
+ "المتطلبات المتأثرة": [
1253
+ "REQ-005",
1254
+ "REQ-006, REQ-003",
1255
+ "REQ-010",
1256
+ "REQ-004",
1257
+ "REQ-001, REQ-007"
1258
+ ],
1259
+ "الخطورة": ["عالية", "متوسطة", "عالية", "متوسطة", "عالية"],
1260
+ "التوصية": [
1261
+ "طلب توضيح تفصيلي من العميل",
1262
+ "إعادة تحديد أولويات المتطلبات",
1263
+ "عقد ورشة عمل للتكامل",
1264
+ "طلب نماذج للتقارير المطلوبة",
1265
+ "إضافة متطلبات أمنية تفصيلية"
1266
+ ]
1267
+ })
1268
+
1269
+ st.dataframe(risks_demo, use_container_width=True, hide_index=True)
1270
+ else:
1271
+ st.markdown("### ملخص المتطلبات")
1272
+ st.info("قم بتحميل ملف المتطلبات وبدء التحليل لعرض النتائج هنا")
1273
+
1274
+ def supply_chain_page():
1275
+ """صفحة تخطيط سلسلة التوريد"""
1276
+ st.markdown("# 🔄 تخطيط سلسلة التوريد")
1277
 
1278
+ tab1, tab2, tab3 = st.tabs(["تحليل المحتوى المحلي", "إدارة الموردين", "التخطيط للمشتريات"])
 
1279
 
1280
+ with tab1:
1281
+ st.markdown("## تحليل وتحسين المحتوى المحلي")
1282
+
1283
+ col1, col2 = st.columns(2)
1284
+
1285
+ with col1:
1286
+ st.markdown("### نسب المحتوى المحلي حسب الفئة")
1287
+
1288
+ # الرسم البياني
1289
+ fig = go.Figure()
1290
+
1291
+ local_df = st.session_state.local_content_df
1292
+
1293
+ # إضافة الأعمدة
1294
+ fig.add_trace(go.Bar(
1295
+ x=local_df['الفئة'],
1296
+ y=local_df['النسبة الحالية'],
1297
+ name='النسبة الحالية',
1298
+ marker_color='#3498db'
1299
+ ))
1300
+
1301
+ fig.add_trace(go.Bar(
1302
+ x=local_df['الفئة'],
1303
+ y=local_df['النسبة المستهدفة'],
1304
+ name='النسبة المستهدفة',
1305
+ marker_color='#2ecc71'
1306
+ ))
1307
+
1308
+ # تخصيص الرسم البياني
1309
+ fig.update_layout(
1310
+ barmode='group',
1311
+ title_text='مقارنة المحتوى المحلي الحالي والمستهدف',
1312
+ title_font_size=16,
1313
+ xaxis_title="الفئة",
1314
+ yaxis_title="النسبة المئوية (%)",
1315
+ legend_title="النسبة",
1316
+ height=400
1317
+ )
1318
+
1319
+ st.plotly_chart(fig, use_container_width=True)
1320
+
1321
+ with col2:
1322
+ st.markdown("### فرص تحسين المحتوى المحلي")
1323
+
1324
+ for i, row in local_df.iterrows():
1325
+ gap = row['النسبة المستهدفة'] - row['النسبة الحالية']
1326
+
1327
+ if gap > 5:
1328
+ st.markdown(f"""
1329
+ **تحسين {row['الفئة']}**
1330
+ - الفجوة الحالية: {gap:.1f}%
1331
+ - التغير السنوي: {row['التغير السنوي']}
1332
+ - توصية: زيادة الاعتماد على الموردين المحليين في هذه الفئة
1333
+ """)
1334
+
1335
+ st.markdown("### تقدير التأثير الاقتصادي")
1336
+ st.metric(
1337
+ "القيمة المضافة المحلية المتوقعة",
1338
+ "3.2 مليون ريال",
1339
+ "+12.5%"
1340
+ )
1341
+
1342
+ with tab2:
1343
+ st.markdown("## إدارة الموردين")
1344
+
1345
+ # أزرار الإجراءات
1346
+ col1, col2, col3 = st.columns(3)
1347
+ with col1:
1348
+ st.button("إضافة مورد جديد")
1349
+
1350
+ with col2:
1351
+ st.button("تصدير قائمة الموردين")
1352
+
1353
+ with col3:
1354
+ st.button("تقييم الموردين")
1355
+
1356
+ # بيانات الموردين التوضيحية
1357
+ suppliers_data = {
1358
+ "اسم المورد": [
1359
+ "شركة التقنية المتطورة", "مؤسسة الحلول الذكية", "شركة الخدمات المتكاملة",
1360
+ "مجموعة الإبداع التقني", "شركة التطوير الرقمي", "مؤسسة الجودة الشاملة",
1361
+ "شركة الاتصالات المتقدمة", "مؤسسة البناء الحديث"
1362
+ ],
1363
+ "التصنيف": [
1364
+ "محلي", "محلي", "أجنبي",
1365
+ "محلي", "محلي مشترك", "محلي",
1366
+ "أجنبي", "محلي"
1367
+ ],
1368
+ "المنتجات/الخدمات": [
1369
+ "أنظمة تقنية", "خدمات استشارية", "معدات وأجهزة",
1370
+ "برمجيات", "حلول تقنية", "خدمات صيانة",
1371
+ "أنظمة اتصالات", "إنشاءات"
1372
+ ],
1373
+ "درجة التقييم": [
1374
+ "A", "A", "B",
1375
+ "B", "A", "C",
1376
+ "B", "A"
1377
+ ],
1378
+ "المحتوى المحلي": [
1379
+ "87%", "92%", "34%",
1380
+ "79%", "63%", "95%",
1381
+ "28%", "91%"
1382
+ ],
1383
+ "تاريخ آخر تعامل": [
1384
+ "2024-01-15", "2024-02-20", "2023-11-05",
1385
+ "2024-03-10", "2024-02-25", "2023-09-18",
1386
+ "2024-01-30", "2024-03-05"
1387
+ ]
1388
+ }
1389
+
1390
+ suppliers_df = pd.DataFrame(suppliers_data)
1391
+
1392
+ # تصفية البيانات
1393
+ local_filter = st.multiselect(
1394
+ "التصنيف:",
1395
+ ["الكل"] + list(suppliers_df['التصنيف'].unique()),
1396
+ default=["الكل"]
1397
+ )
1398
+
1399
+ filtered_suppliers = suppliers_df.copy()
1400
+ if "الكل" not in local_filter:
1401
+ filtered_suppliers = filtered_suppliers[filtered_suppliers['التصنيف'].isin(local_filter)]
1402
+
1403
+ # عرض الجدول
1404
+ st.dataframe(filtered_suppliers, use_container_width=True, hide_index=True)
1405
+
1406
+ with tab3:
1407
+ st.markdown("## التخطيط للمشتريات")
1408
+
1409
+ st.markdown("""
1410
+ ### التخطيط الاستراتيجي للمشتريات
1411
+
1412
+ استخدم هذا القسم لتخطيط المشتريات المستقبلية وتحليل الاحتياجات وفرص توفير التكاليف.
1413
+ """)
1414
+
1415
+ col1, col2 = st.columns(2)
1416
+
1417
+ with col1:
1418
+ st.markdown("### توزيع المشتريات حسب الفئة")
1419
+
1420
+ categories = ["أجهزة ومعدات", "خدمات استشارية", "برمجيات", "خدمات صيانة", "مستلزمات مكتبية"]
1421
+ values = [45, 25, 15, 10, 5]
1422
+
1423
+ fig = px.pie(
1424
+ names=categories,
1425
+ values=values,
1426
+ title="توزيع المشتريات حسب الفئة",
1427
+ color_discrete_sequence=px.colors.qualitative.Pastel
1428
+ )
1429
+
1430
+ fig.update_layout(
1431
+ title_font_size=16,
1432
+ legend_title=""
1433
+ )
1434
+
1435
+ st.plotly_chart(fig, use_container_width=True)
1436
+
1437
+ with col2:
1438
+ st.markdown("### التكاليف الشهرية المتوقعة")
1439
+
1440
+ # بيانات مالية توضيحية
1441
+ financial_df = st.session_state.financial_df
1442
+
1443
+ # تحويل البيانات المالية إلى صيغة مناسبة للرسم البياني
1444
+ fig = go.Figure()
1445
+
1446
+ fig.add_trace(go.Scatter(
1447
+ x=financial_df['الشهر'],
1448
+ y=financial_df['المخطط'],
1449
+ name='المخطط',
1450
+ line=dict(color='#3498db', width=2)
1451
+ ))
1452
+
1453
+ fig.add_trace(go.Scatter(
1454
+ x=financial_df['الشهر'],
1455
+ y=financial_df['الفعلي'],
1456
+ name='الفعلي',
1457
+ line=dict(color='#e74c3c', width=2)
1458
+ ))
1459
+
1460
+ fig.update_layout(
1461
+ title_text='مقارنة التكاليف المخططة والفعلية',
1462
+ title_font_size=16,
1463
+ xaxis_title="الشهر",
1464
+ yaxis_title="التكلفة (ريال)",
1465
+ legend_title="النوع",
1466
+ height=400
1467
+ )
1468
+
1469
+ st.plotly_chart(fig, use_container_width=True)
1470
+
1471
+ def risk_analysis_page():
1472
+ """صفحة تحليل المخاطر"""
1473
+ st.markdown("# ⚠️ تحليل المخاطر")
1474
+
1475
+ st.markdown("""
1476
+ ## نظام تحليل وإدارة المخاطر
1477
+
1478
+ يقوم هذا النظام بتحديد وتقييم وإدارة المخاطر المرتبطة بالمناقصات والعقود.
1479
+ يمكنك من خلاله تحليل المخاطر المختلفة وتحديد استراتيجيات الاستجابة المناسبة.
1480
+ """)
1481
+
1482
+ col1, col2 = st.columns([1, 2])
1483
+
1484
+ with col1:
1485
+ st.markdown("### تصنيف المخاطر")
1486
+
1487
+ risk_options = [
1488
+ "مخاطر قانونية",
1489
+ "مخاطر مالية",
1490
+ "مخاطر تشغيلية",
1491
+ "مخاطر فنية",
1492
+ "مخاطر تعاقدية",
1493
+ "مخاطر خارجية"
1494
+ ]
1495
+
1496
+ selected_risk = st.radio("اختر نوع المخاطر:", risk_options)
1497
+
1498
+ st.markdown("### تحليل ذكي")
1499
+ if st.button("تحليل المخاطر بالذكاء الاصطناعي"):
1500
+ with st.spinner("جاري التحليل..."):
1501
+ time.sleep(2)
1502
+ st.success("تم التحليل بنجاح!")
1503
+
1504
+ ai_results = {
1505
+ "مخاطر قانونية": """
1506
+ - احتمالية عالية لتغير اللوائح التنظيمية خلال فترة المشروع
1507
+ - مخاطر متوسطة لوجود ثغرات في صياغة العقد
1508
+ - مخاطر منخفضة لنزاعات قضائية
1509
+ """,
1510
+ "مخاطر مالية": """
1511
+ - مخاطر عالية لتقلبات أسعار المواد الخام
1512
+ - مخاطر متوسطة لتغير أسعار الصرف
1513
+ - مخاطر عالية للتأخر في السداد
1514
+ """,
1515
+ "مخاطر تشغيلية": """
1516
+ - مخاطر متوسطة لتأخر جدول المشروع
1517
+ - مخاطر عالية لنقص الكوادر المؤهلة
1518
+ - مخاطر منخفضة للأعطال التقنية
1519
+ """,
1520
+ "مخاطر فنية": """
1521
+ - مخاطر عالية لعدم وضوح المتطلبات الفنية
1522
+ - مخاطر متوسطة لتعارض تقني مع أنظمة قائمة
1523
+ - مخاطر منخفضة لأداء النظام
1524
+ """,
1525
+ "مخاطر تعاقدية": """
1526
+ - مخاطر عالية لغموض نطاق العمل
1527
+ - مخاطر متوسطة لتغيير متطلبات العميل
1528
+ - مخاطر متوسطة لمعايير القبول
1529
+ """,
1530
+ "مخاطر خارجية": """
1531
+ - مخاطر منخفضة للعوامل البيئية
1532
+ - مخاطر متوسطة للعوامل السياسية
1533
+ - مخاطر منخفضة للكوارث الطبيعية
1534
+ """
1535
+ }
1536
+
1537
+ st.info(ai_results[selected_risk])
1538
+
1539
+ with col2:
1540
+ st.markdown("### سجل المخاطر")
1541
+
1542
+ # عرض جدول المخاطر
1543
+ st.dataframe(
1544
+ st.session_state.risks_df,
1545
+ use_container_width=True,
1546
+ hide_index=True
1547
+ )
1548
+
1549
+ # مصفوفة المخاطر
1550
+ st.markdown("### مصفوفة المخاطر")
1551
+
1552
+ risk_matrix = pd.crosstab(
1553
+ st.session_state.risks_df['التأثير'],
1554
+ st.session_state.risks_df['الاحتمالية'],
1555
+ margins=False
1556
+ )
1557
+
1558
+ # تحويل القيم إلى حرارية
1559
+ risk_severity = {
1560
+ ('منخفض', 'منخفضة'): 1,
1561
+ ('منخفض', 'متوسطة'): 2,
1562
+ ('منخفض', 'عالية'): 3,
1563
+ ('متوسط', 'منخفضة'): 2,
1564
+ ('متوسط', 'متوسطة'): 4,
1565
+ ('متوسط', 'عالية'): 6,
1566
+ ('عالي', 'منخفضة'): 3,
1567
+ ('عالي', 'متوسطة'): 6,
1568
+ ('عالي', 'عالية'): 9,
1569
+ ('حرج', 'منخفضة'): 4,
1570
+ ('حرج', 'متوسطة'): 8,
1571
+ ('حرج', 'عالية'): 12
1572
+ }
1573
+
1574
+ # تحضير بيانات المصفوفة
1575
+ impact_order = ['منخفض', 'متوسط', 'عالي', 'حرج']
1576
+ probability_order = ['منخفضة', 'متوسطة', 'عالية']
1577
+
1578
+ # إنشاء مصفوفة حرارية
1579
+ heat_values = []
1580
+ annotations = []
1581
+
1582
+ for impact in impact_order:
1583
+ heat_row = []
1584
+ for prob in probability_order:
1585
+ try:
1586
+ value = risk_matrix.loc[impact, prob]
1587
+ except:
1588
+ value = 0
1589
+ heat_row.append(risk_severity.get((impact, prob), 0))
1590
+ annotations.append(dict(
1591
+ text=str(value),
1592
+ x=prob,
1593
+ y=impact,
1594
+ showarrow=False
1595
+ ))
1596
+ heat_values.append(heat_row)
1597
+
1598
+ # إنشاء الرسم البياني
1599
+ fig = go.Figure(data=go.Heatmap(
1600
+ z=heat_values,
1601
+ x=probability_order,
1602
+ y=impact_order,
1603
+ colorscale=[
1604
+ [0.0, "#2ecc71"], # أخضر للمخاطر المنخفضة
1605
+ [0.33, "#f1c40f"], # أصفر للمخاطر المتوسطة
1606
+ [0.66, "#e67e22"], # برتقالي للمخاطر العالية
1607
+ [1.0, "#e74c3c"] # أحمر للمخاطر الحرجة
1608
+ ],
1609
+ showscale=False
1610
+ ))
1611
+
1612
+ # إضافة النصوص
1613
+ for annotation in annotations:
1614
+ fig.add_annotation(annotation)
1615
+
1616
+ fig.update_layout(
1617
+ title_font_size=16,
1618
+ title_x=0.5,
1619
+ xaxis_title="الاحتمالية",
1620
+ yaxis_title="التأثير"
1621
+ )
1622
+
1623
+ st.plotly_chart(fig, use_container_width=True)
1624
+
1625
+ def local_content_page():
1626
+ """صفحة المحتوى المحلي"""
1627
+ st.markdown("# 🏠 المحتوى المحلي")
1628
 
1629
+ st.markdown("""
1630
+ ## قياس وتحسين المحتوى المحلي
1631
 
1632
+ يتيح النظام إمكانية قياس نسبة المحتوى المحلي في المشاريع والمناقصات وتحديد فرص التحسين.
1633
+ """)
1634
 
1635
+ tab1, tab2 = st.tabs(["تحليل المحتوى المحلي", "فرص التحسين"])
 
1636
 
1637
+ with tab1:
1638
+ # تحليل المحتوى المحلي حسب الفئة
1639
+ local_df = st.session_state.local_content_df
1640
+
1641
+ col1, col2 = st.columns([2, 1])
1642
+
1643
+ with col1:
1644
+ fig = go.Figure()
1645
+
1646
+ fig.add_trace(go.Bar(
1647
+ x=local_df['الفئة'],
1648
+ y=local_df['النسبة الحالية'],
1649
+ name='النسبة الحالية',
1650
+ marker_color='#3498db'
1651
+ ))
1652
+
1653
+ fig.add_trace(go.Bar(
1654
+ x=local_df['الفئة'],
1655
+ y=local_df['النسبة المستهدفة'],
1656
+ name='النسبة المستهدفة',
1657
+ marker_color='#2ecc71'
1658
+ ))
1659
+
1660
+ fig.update_layout(
1661
+ barmode='group',
1662
+ title_text='تحليل المحتوى المحلي حسب الفئة',
1663
+ title_font_size=20,
1664
+ title_x=0.5,
1665
+ xaxis_title="الفئة",
1666
+ yaxis_title="النسبة المئوية (%)",
1667
+ legend_title="النسبة"
1668
+ )
1669
+
1670
+ st.plotly_chart(fig, use_container_width=True)
1671
+
1672
+ with col2:
1673
+ total_current = local_df['النسبة الحالية'].mean()
1674
+ total_target = local_df['النسبة المستهدفة'].mean()
1675
+ gap = total_target - total_current
1676
+
1677
+ st.markdown("### المحتوى المحلي الإجمالي")
1678
+ st.metric(
1679
+ "النسبة الحالية",
1680
+ f"{total_current:.1f}%",
1681
+ delta=None
1682
+ )
1683
+
1684
+ st.metric(
1685
+ "النسبة المستهدفة",
1686
+ f"{total_target:.1f}%",
1687
+ delta=None
1688
+ )
1689
+
1690
+ st.metric(
1691
+ "الفجوة",
1692
+ f"{gap:.1f}%",
1693
+ delta=None
1694
+ )
1695
+
1696
+ # تحليل المحتوى المحلي حسب العقود
1697
+ st.markdown("### تحليل المحتوى المحلي في العقود")
1698
+
1699
+ sorted_contracts = st.session_state.contracts_df.sort_values('المحتوى المحلي', ascending=False)
1700
+
1701
+ fig = px.bar(
1702
+ sorted_contracts.head(10),
1703
+ x='رقم العقد',
1704
+ y='المحتوى المحلي',
1705
+ color='المحتوى المحلي',
1706
+ color_continuous_scale=px.colors.sequential.Viridis,
1707
+ title="أعلى 10 عقود من حيث المحتوى المحلي"
1708
+ )
1709
+
1710
+ fig.update_layout(
1711
+ title_font_size=16,
1712
+ title_x=0.5,
1713
+ xaxis_title="رقم العقد",
1714
+ yaxis_title="نسبة المحتوى المحلي (%)"
1715
+ )
1716
+
1717
+ st.plotly_chart(fig, use_container_width=True)
1718
+
1719
+ with tab2:
1720
+ st.markdown("### فرص تحسين المحتوى المحلي")
1721
+
1722
+ col1, col2 = st.columns(2)
1723
+
1724
+ with col1:
1725
+ st.markdown("""
1726
+ #### مجالات التحسين
1727
+
1728
+ 1. **توظيف الكوادر المحلية**
1729
+ - توظيف مهندسين محليين
1730
+ - التعاقد مع خبراء محليين للاستشارات
1731
+ - برامج تدريب للكوادر المحلية
1732
+
1733
+ 2. **شراء المواد والمعدات المحلية**
1734
+ - تفضيل الموردين المحليين
1735
+ - دعم المصنعين المحليين
1736
+ - تطوير سلاسل التوريد المحلية
1737
+
1738
+ 3. **نقل التقنية**
1739
+ - توطين التقنيات الحديثة
1740
+ - تطوير الخبرات المحلية
1741
+ - الشراكة مع الجامعات المحلية
1742
+ """)
1743
+
1744
+ with col2:
1745
+ st.markdown("### أكبر الفجوات في المحتوى المحلي")
1746
+
1747
+ # البيانات
1748
+ categories = []
1749
+ gaps = []
1750
+
1751
+ for i, row in local_df.iterrows():
1752
+ gap = row['النسبة المستهدفة'] - row['النسبة الحالية']
1753
+ categories.append(row['الفئة'])
1754
+ gaps.append(gap)
1755
+
1756
+ # ترتيب البيانات
1757
+ gap_df = pd.DataFrame({
1758
+ 'الفئة': categories,
1759
+ 'الفجوة': gaps
1760
+ })
1761
+
1762
+ sorted_gap_df = gap_df.sort_values('الفجوة', ascending=False)
1763
+
1764
+ fig = px.bar(
1765
+ sorted_gap_df,
1766
+ x='الفئة',
1767
+ y='الفجوة',
1768
+ color='الفجوة',
1769
+ color_continuous_scale=px.colors.sequential.Reds,
1770
+ title="الفجوات في المحتوى المحلي حسب الفئة"
1771
+ )
1772
+
1773
+ fig.update_layout(
1774
+ title_font_size=16,
1775
+ title_x=0.5,
1776
+ xaxis_title="الفئة",
1777
+ yaxis_title="الفجوة (%)"
1778
+ )
1779
+
1780
+ st.plotly_chart(fig, use_container_width=True)
1781
+
1782
+ def success_prediction_page():
1783
+ """صفحة توقع احتمالية النجاح"""
1784
+ st.markdown("# 🎯 توقع احتمالية النجاح")
1785
+
1786
+ st.markdown("""
1787
+ ## نظام التنبؤ بنجاح المناقصات
1788
+
1789
+ يستخدم هذا النظام خوارزميات الذكاء الاصطناعي لتحليل عوامل نجاح المناقصات وتوقع احتمالية الفوز بها.
1790
+ """)
1791
+
1792
+ col1, col2 = st.columns([1, 2])
1793
+
1794
+ with col1:
1795
+ st.markdown("### تحليل مناقصة جديدة")
1796
+
1797
+ with st.form("prediction_form"):
1798
+ tender_type = st.selectbox(
1799
+ "نوع المناقصة:",
1800
+ ["مناقصة عامة", "مناقصة محدودة", "منافسة محدودة", "شراء مباشر"]
1801
+ )
1802
+
1803
+ tender_sector = st.selectbox(
1804
+ "القطاع:",
1805
+ ["حكومي", "شبه حكومي", "خاص"]
1806
+ )
1807
+
1808
+ tender_value = st.number_input(
1809
+ "القيمة التقديرية (ريال):",
1810
+ min_value=100000,
1811
+ max_value=100000000,
1812
+ value=1000000,
1813
+ step=100000
1814
+ )
1815
+
1816
+ competitors_count = st.slider(
1817
+ "عدد المنافسين المتوقع:",
1818
+ min_value=1,
1819
+ max_value=20,
1820
+ value=5
1821
+ )
1822
+
1823
+ technical_weight = st.slider(
1824
+ "وزن التقييم الفني (%):",
1825
+ min_value=0,
1826
+ max_value=100,
1827
+ value=60
1828
+ )
1829
+
1830
+ previous_experience = st.checkbox("خبرة سابقة مع نفس الجهة")
1831
+
1832
+ local_content_value = st.slider(
1833
+ "نسبة المحتوى المحلي المقدمة (%):",
1834
+ min_value=0,
1835
+ max_value=100,
1836
+ value=65
1837
+ )
1838
+
1839
+ submit_button = st.form_submit_button("توقع احتمالية النجاح")
1840
+
1841
+ if submit_button:
1842
+ with st.spinner("جاري تحليل المناقصة..."):
1843
+ time.sleep(2) # محاكاة وقت المعالجة
1844
+
1845
+ # حساب احتمالية النجاح (محاكاة)
1846
+ base_probability = 70 # احتمالية أساسية
1847
+
1848
+ # العوامل المؤثرة
1849
+ factors = {}
1850
+
1851
+ # نوع المناقصة
1852
+ if tender_type == "مناقصة عامة":
1853
+ factors["نوع المناقصة"] = -5 # منافسة أكبر
1854
+ elif tender_type == "مناقصة محدودة":
1855
+ factors["نوع المناقصة"] = 5
1856
+ elif tender_type == "منافسة محدودة":
1857
+ factors["نوع المناقصة"] = 10
1858
+ else: # شراء مباشر
1859
+ factors["نوع المناقصة"] = 15
1860
+
1861
+ # القطاع
1862
+ if tender_sector == "حكومي":
1863
+ factors["القطاع"] = 0
1864
+ elif tender_sector == "شبه حكومي":
1865
+ factors["القطاع"] = 5
1866
+ else: # خاص
1867
+ factors["القطاع"] = -5
1868
+
1869
+ # القيمة التقديرية
1870
+ if tender_value < 500000:
1871
+ factors["القيمة"] = 5
1872
+ elif tender_value < 2000000:
1873
+ factors["القيمة"] = 0
1874
+ elif tender_value < 10000000:
1875
+ factors["القيمة"] = -5
1876
+ else:
1877
+ factors["القيمة"] = -10
1878
+
1879
+ # عدد المنافسين
1880
+ if competitors_count <= 3:
1881
+ factors["المنافسين"] = 10
1882
+ elif competitors_count <= 7:
1883
+ factors["المنافسين"] = 0
1884
+ else:
1885
+ factors["المنافسين"] = -10
1886
+
1887
+ # وزن التقييم الفني
1888
+ if technical_weight >= 70:
1889
+ factors["التقييم الفني"] = 10
1890
+ elif technical_weight >= 50:
1891
+ factors["التقييم الفني"] = 5
1892
+ else:
1893
+ factors["التقييم الفني"] = 0
1894
+
1895
+ # خبرة سابقة
1896
+ if previous_experience:
1897
+ factors["خبرة سابقة"] = 15
1898
+ else:
1899
+ factors["خبرة سابقة"] = 0
1900
+
1901
+ # المحتوى المحلي
1902
+ if local_content_value >= 80:
1903
+ factors["المحتوى المحلي"] = 10
1904
+ elif local_content_value >= 60:
1905
+ factors["المحتوى المحلي"] = 5
1906
+ elif local_content_value >= 40:
1907
+ factors["المحتوى المحلي"] = 0
1908
+ else:
1909
+ factors["المحتوى المحلي"] = -5
1910
+
1911
+ # حساب الاحتمالية النهائية
1912
+ final_probability = base_probability + sum(factors.values())
1913
+
1914
+ # تعديل النتيجة ضمن النطاق المقبول
1915
+ final_probability = max(min(final_probability, 99), 1)
1916
+
1917
+ # عرض النتيجة
1918
+ st.success(f"احتمالية النجاح في المناقصة: {final_probability}%")
1919
+
1920
+ # عرض تفاصيل التحليل
1921
+ st.markdown("### تفاصيل التحليل")
1922
+
1923
+ for factor, value in factors.items():
1924
+ icon = "🔼" if value > 0 else "🔽" if value < 0 else "◀▶"
1925
+ st.text(f"{icon} {factor}: {value:+d}%")
1926
+
1927
+ with col2:
1928
+ st.markdown("### العوامل المؤثرة في نجاح المناقصات")
1929
+
1930
+ # بيانات توضيحية للعوامل المؤثرة
1931
+ factors_df = pd.DataFrame({
1932
+ "العامل": [
1933
+ "المحتوى المحلي",
1934
+ "السعر التنافسي",
1935
+ "الخبرة السابقة",
1936
+ "الحلول التقنية",
1937
+ "القدرات الفنية",
1938
+ "سرعة التنفيذ",
1939
+ "جودة المقترح الفني",
1940
+ "الامتثال للمتطلبات"
1941
+ ],
1942
+ "تأثير إيجابي": [
1943
+ 0.85, 0.78, 0.72, 0.65, 0.62, 0.58, 0.52, 0.48
1944
+ ]
1945
+ })
1946
+
1947
+ fig = px.bar(
1948
+ factors_df,
1949
+ x="تأثير إيجابي",
1950
+ y="العامل",
1951
+ orientation='h',
1952
+ color="تأثير إيجابي",
1953
+ color_continuous_scale=px.colors.sequential.Viridis,
1954
+ title="تأثير العوامل المختلفة على احتمالية النجاح"
1955
+ )
1956
+
1957
+ fig.update_layout(
1958
+ title_font_size=16,
1959
+ title_x=0.5,
1960
+ xaxis_title="مستوى التأثير الإيجابي",
1961
+ yaxis_title=""
1962
+ )
1963
+
1964
+ st.plotly_chart(fig, use_container_width=True)
1965
+
1966
+ st.markdown("### إحصائيات المناقصات السابقة")
1967
+
1968
+ # بيانات توضيحية للمناقصات السابقة
1969
+ historical_df = pd.DataFrame({
1970
+ "الشهر": [
1971
+ "يناير", "فبراير", "مارس", "أبريل", "مايو",
1972
+ "يونيو", "يوليو", "أغسطس", "سبتمبر", "أكتوبر"
1973
+ ],
1974
+ "عدد المناقصات": [5, 7, 4, 6, 9, 8, 6, 7, 10, 8],
1975
+ "معدل النجاح": [0.6, 0.57, 0.75, 0.67, 0.44, 0.5, 0.67, 0.71, 0.6, 0.75]
1976
+ })
1977
+
1978
+ fig = make_subplots(specs=[[{"secondary_y": True}]])
1979
+
1980
+ fig.add_trace(
1981
+ go.Bar(
1982
+ x=historical_df["الشهر"],
1983
+ y=historical_df["عدد المناقصات"],
1984
+ name="عدد المناقصات",
1985
+ marker_color="#3498db"
1986
+ ),
1987
+ secondary_y=False
1988
+ )
1989
+
1990
+ fig.add_trace(
1991
+ go.Scatter(
1992
+ x=historical_df["الشهر"],
1993
+ y=historical_df["معدل النجاح"],
1994
+ name="معدل النجاح",
1995
+ mode="lines+markers",
1996
+ marker_color="#e74c3c",
1997
+ line=dict(width=3)
1998
+ ),
1999
+ secondary_y=True
2000
+ )
2001
+
2002
+ fig.update_layout(
2003
+ title_text="إحصائيات المناقصات السابقة",
2004
+ title_font_size=16,
2005
+ title_x=0.5,
2006
+ legend_title="",
2007
+ xaxis_title="الشهر"
2008
+ )
2009
+
2010
+ fig.update_yaxes(title_text="عدد المناقصات", secondary_y=False)
2011
+ fig.update_yaxes(title_text="معدل النجاح", secondary_y=True)
2012
+
2013
+ st.plotly_chart(fig, use_container_width=True)
2014
+
2015
+ def settings_page():
2016
+ """صفحة الإعدادات"""
2017
+ st.markdown("# ⚙️ الإعدادات")
2018
+
2019
+ st.markdown("""
2020
+ ## إعدادات النظام
2021
+
2022
+ يمكنك من خلال هذه الصفحة تخصيص إعدادات النظام بما يتناسب مع احتياجاتك.
2023
+ """)
2024
+
2025
+ tab1, tab2, tab3 = st.tabs(["إعدادات عامة", "إعدادات الحساب", "الدعم والمساعدة"])
2026
+
2027
+ with tab1:
2028
+ st.markdown("### الإعدادات العامة")
2029
+
2030
+ st.markdown("#### إعدادات اللغة")
2031
+ lang = st.radio(
2032
+ "اللغة الافتراضية للنظام:",
2033
+ ["العربية", "English"],
2034
+ index=0
2035
+ )
2036
+
2037
+ st.markdown("#### إعدادات العرض")
2038
+ theme = st.selectbox(
2039
+ "السمة:",
2040
+ ["السمة الافتراضية", "الوضع الداكن", "الوضع الفاتح"],
2041
+ index=0
2042
+ )
2043
+
2044
+ st.markdown("#### إعدادات الإشعارات")
2045
+ st.checkbox("تفعيل الإشعارات داخل النظام", value=True)
2046
+ st.checkbox("تفعيل الإشعارات عبر البريد الإلكتروني", value=True)
2047
+
2048
+ if st.button("حفظ الإعدادات العامة"):
2049
+ st.success("تم حفظ الإعدادات بنجاح")
2050
+
2051
+ with tab2:
2052
+ st.markdown("### إعدادات الحساب")
2053
+
2054
+ st.markdown("#### البيانات الشخصية")
2055
+
2056
+ col1, col2 = st.columns(2)
2057
+
2058
+ with col1:
2059
+ st.text_input("الاسم:", value="محمد أحمد")
2060
+ st.text_input("البريد الإلكتروني:", value="mohammed@example.com")
2061
+
2062
+ with col2:
2063
+ st.text_input("المسمى الوظيفي:", value="مدير مشاريع")
2064
+ st.text_input("رقم الهاتف:", value="0555555555")
2065
+
2066
+ st.markdown("#### تغيير كلمة المرور")
2067
+ st.password_input("كلمة المرور الحالية:")
2068
+ st.password_input("كلمة المرور الجديدة:")
2069
+ st.password_input("تأكيد كلمة المرور الجديدة:")
2070
+
2071
+ if st.button("تحديث البيانات"):
2072
+ st.success("تم تحديث البيانات بنجاح")
2073
+
2074
+ st.markdown("#### إعدادات الأمان")
2075
+ st.checkbox("تفعيل المصادقة الثنائية", value=False)
2076
+
2077
+ with tab3:
2078
+ st.markdown("### الدعم والمساعدة")
2079
+
2080
+ st.markdown("""
2081
+ #### كيفية استخدام النظام
2082
+
2083
+ يوفر النظام مجموعة من الأدوات والتحليلات التي تساعدك في إدارة المناقصات والعقود وتحليل المخاطر.
2084
+ يمكنك الاطلاع على دليل الاستخدام للحصول على شرح تفصيلي لكافة الوظائف.
2085
+ """)
2086
+
2087
+ st.download_button(
2088
+ "تحميل دليل الاستخدام",
2089
+ data="محتوى دليل الاستخدام",
2090
+ file_name="user_guide.pdf",
2091
+ mime="application/pdf"
2092
+ )
2093
+
2094
+ st.markdown("#### التواصل مع الدعم الفني")
2095
+
2096
+ with st.form("support_form"):
2097
+ st.text_input("العنوان:")
2098
+ st.text_area("الرسالة:")
2099
+ st.selectbox(
2100
+ "نوع المشكلة:",
2101
+ ["استفسار عام", "مشكلة فنية", "اقتراح تحسين", "أخرى"]
2102
+ )
2103
+ st.file_uploader("إرفاق ملف (اختياري):")
2104
+
2105
+ submit_support = st.form_submit_button("إرسال")
2106
+
2107
+ if submit_support:
2108
+ st.success("تم إرسال رسالتك بنجاح، سيتم التواصل معك قريباً")
2109
+
2110
+ def about_page():
2111
+ """صفحة حول النظام"""
2112
+ st.markdown("# ℹ️ حول النظام")
2113
+
2114
+ st.markdown("""
2115
+ ## نظام إدارة المناقصات والعقود
2116
+
2117
+ ### نبذة عن النظام
2118
+
2119
+ نظام متكامل لإدارة المناقصات والعقود يعتمد على أحدث التقنيات والذكاء الاصطناعي لتحسين كفاءة العمليات وزيادة فرص النجاح.
2120
+ يوفر النظام مجموعة من الأدوات والتحليلات التي تساعد في اتخاذ القرارات وإدارة المخاطر وتحسين المحتوى المحلي.
2121
+
2122
+ ### المميزات الرئيسية
2123
+
2124
+ * إدارة المناقصات والفرص التجارية
2125
+ * تحليل وإدارة المخاطر
2126
+ * قياس وتحسين المحتوى المحلي
2127
+ * توقع احتمالية النجاح في المناقصات
2128
+ * إدارة وتحليل العقود
2129
+ * تخطيط سلسلة التوريد
2130
+ * تحليل المتطلبات
2131
+
2132
+ ### فريق التطوير
2133
+
2134
+ تم تطوير هذا النظام بواسطة فريق من الخبراء المتخصصين في مجالات البرمجة والذكاء الاصطناعي وإدارة المشاريع والعقود.
2135
+
2136
+ ### التواصل
2137
+
2138
+ للمزيد من المعلومات أو الاستفسارات، يرجى التواصل عبر:
2139
+
2140
+ * البريد الإلكتروني: info@tenderssystem.com
2141
+ * رقم الهاتف: 0123456789
2142
+ """)
2143
+
2144
+ col1, col2, col3 = st.columns(3)
2145
+
2146
+ with col1:
2147
+ st.info("إصدار النظام: 1.0.0")
2148
+
2149
+ with col2:
2150
+ st.info("تاريخ الإطلاق: 2024/03/15")
2151
+
2152
+ with col3:
2153
+ st.info("آخر تحديث: 2024/03/18")
2154
+
2155
+ # تكوين القائمة الجانبية
2156
+ def setup_sidebar():
2157
+ """إعداد القائمة الجانبية"""
2158
+ with st.sidebar:
2159
+ st.image("logo.png", width=150)
2160
+ st.title("نظام إدارة المناقصات")
2161
+
2162
+ # معلومات المستخدم
2163
+ st.markdown("### أهلاً م تامر الجوهري ")
2164
+ st.markdown("مدير المناقصات والعقود")
2165
+
2166
+ st.markdown("---")
2167
+
2168
+ # القائمة الرئيسية
2169
+ page = st.radio(
2170
+ "القائمة الرئيسية",
2171
+ [
2172
+ "📊 الرئيسية",
2173
+ "📋 المناقصات",
2174
+ "📑 العقود",
2175
+ "🔍 تحليل المتطلبات",
2176
+ "🔄 تخطيط سلسلة التوريد",
2177
+ "⚠️ تحليل المخاطر",
2178
+ "🏠 المحتوى المحلي",
2179
+ "🎯 توقع احتمالية النجاح",
2180
+ "⚙️ الإعدادات",
2181
+ "ℹ️ حول النظام"
2182
+ ]
2183
+ )
2184
+
2185
+ st.markdown("---")
2186
+
2187
+ # الإحصائيات
2188
+ st.markdown("### إحصائيات سريعة")
2189
+
2190
+ col1, col2 = st.columns(2)
2191
+ with col1:
2192
+ st.metric("المناقصات", "28")
2193
+ with col2:
2194
+ st.metric("العقود", "14")
2195
+
2196
+ col1, col2 = st.columns(2)
2197
+ with col1:
2198
+ st.metric("قيد الدراسة", "7")
2199
+ with col2:
2200
+ st.metric("معدل النجاح", "64%")
2201
+
2202
+ return page
2203
+
2204
+ # الدالة الرئيسية للتطبيق
2205
+ def main():
2206
+ """الدالة الرئيسية للتطبيق"""
2207
+ # إعداد الصفحة
2208
+ st.set_page_config(
2209
+ page_title="نظام إدارة المناقصات والعقود",
2210
+ page_icon="📊",
2211
+ layout="wide",
2212
+ initial_sidebar_state="expanded"
2213
+ )
2214
 
2215
+ # التأكد من وجود بيانات الجلسة
2216
+ initialize_session_state()
2217
 
2218
+ # إعداد القائمة الجانبية
2219
+ page = setup_sidebar()
2220
 
2221
+ # عرض الصفحة المناسبة
2222
+ if page == "📊 الرئيسية":
2223
+ home_page()
2224
+ elif page == "📋 المناقصات":
2225
+ tenders_page()
2226
+ elif page == "📑 العقود":
2227
+ contracts_page()
2228
+ elif page == "🔍 تحليل المتطلبات":
2229
+ requirements_page()
2230
+ elif page == "🔄 تخطيط سلسلة التوريد":
2231
+ supply_chain_page()
2232
+ elif page == "⚠️ تحليل المخاطر":
2233
+ risk_analysis_page()
2234
+ elif page == "🏠 المحتوى المحلي":
2235
+ local_content_page()
2236
+ elif page == "🎯 توقع احتمالية النجاح":
2237
+ success_prediction_page()
2238
+ elif page == "⚙️ الإعدادات":
2239
+ settings_page()
2240
+ elif page == "ℹ️ حول النظام":
2241
+ about_page()
2242
 
2243
  if __name__ == "__main__":
2244
  main()