EGYADMIN commited on
Commit
ef8b3c0
·
verified ·
1 Parent(s): 785e527

Update web/pages/tender_analysis.py

Browse files
Files changed (1) hide show
  1. web/pages/tender_analysis.py +120 -272
web/pages/tender_analysis.py CHANGED
@@ -1,290 +1,138 @@
1
  import streamlit as st
2
  import pandas as pd
3
  import numpy as np
4
- import plotly.express as px
5
- from datetime import datetime
6
- import os
7
 
8
- def show_tender_analysis():
9
  """
10
- عرض صفحة تحليل المناقصات
11
  """
12
- st.subheader("تحليل المناقصات")
 
13
 
14
- # تقسيم الشاشة إلى جزئين
15
- col1, col2 = st.columns([1, 2])
16
 
17
- with col1:
18
- # قسم رفع الملفات
19
- st.markdown("### رفع ملفات المناقصة")
20
-
21
- uploaded_files = st.file_uploader(
22
- "قم برفع ملفات المناقصة (PDF, DOCX, XLSX)",
23
- type=["pdf", "docx", "xlsx", "csv", "json"],
24
- accept_multiple_files=True
25
- )
26
-
27
- if uploaded_files:
28
- st.session_state.uploaded_files = uploaded_files
29
- st.success(f"تم رفع {len(uploaded_files)} ملفات بنجاح")
30
-
31
- # عرض قائمة الملفات
32
- st.markdown("### الملفات المرفوعة")
33
- for file in uploaded_files:
34
- st.markdown(f"- {file.name} ({file.size / 1024:.1f} KB)")
35
-
36
- # خيارات التحليل
37
- st.markdown("### خيارات التحليل")
38
-
39
- analysis_options = st.multiselect(
40
- "اختر أنواع التحليل",
41
- [
42
- "استخراج المتطلبات الرئيسية",
43
- "تحليل التكاليف التقديرية",
44
- "تحليل المخاطر",
45
- "تحليل المحتوى المحلي",
46
- "تحليل سلاسل الإمداد",
47
- "التحليل الزمني",
48
- "توقع احتمالية النجاح"
49
- ],
50
- default=["استخراج المتطلبات الرئيسية", "تحليل التكاليف التقديرية"]
51
- )
52
-
53
- # زر بدء التحليل
54
- if st.button("بدء التحليل"):
55
- if not uploaded_files:
56
- st.error("يرجى رفع ملفات المناقصة أولاً")
57
- elif not analysis_options:
58
- st.error("يرجى اختيار نوع التحليل المطلوب")
59
  else:
60
- # هنا سيتم استدعاء عمليات التحليل الفعلية
61
- # نستخدم هنا بيانات توضيحية للعرض فقط
62
- with st.spinner("جاري تحليل المناقصة... قد تستغرق العملية بضع دقائق..."):
63
- # محاكاة وقت المعالجة
64
- import time
65
- time.sleep(2)
66
-
67
- # تخزين نتائج التحليل في حالة الجلسة
68
- st.session_state.analysis_results = {
69
- "tender_id": "T-2025-" + str(np.random.randint(1000, 9999)),
70
- "analyzed_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
71
- "requirements": [
72
- "توريد وتركيب معدات البنية التحتية",
73
- "صيانة الشبكات لمدة سنتين",
74
- "تدريب الموظفين على الأنظمة الجديدة",
75
- "توفير قطع الغيار اللازمة",
76
- "الالتزام بمعايير الجودة ISO 9001"
77
- ],
78
- "cost_estimate": {
79
- "total": np.random.uniform(80, 150, 1)[0].round(2),
80
- "breakdown": {
81
- "مواد": np.random.uniform(30, 60, 1)[0].round(2),
82
- "عمالة": np.random.uniform(20, 40, 1)[0].round(2),
83
- "معدات": np.random.uniform(10, 30, 1)[0].round(2),
84
- "إدارة": np.random.uniform(5, 15, 1)[0].round(2),
85
- "أخرى": np.random.uniform(5, 10, 1)[0].round(2)
86
- }
87
- },
88
- "risks": [
89
- {"name": "تأخر التوريدات", "probability": 0.4, "impact": 0.7, "score": 0.28},
90
- {"name": "تغيير المواصفات", "probability": 0.3, "impact": 0.6, "score": 0.18},
91
- {"name": "نقص العمالة الماهرة", "probability": 0.5, "impact": 0.5, "score": 0.25},
92
- {"name": "تقلبات أسعار المواد", "probability": 0.6, "impact": 0.4, "score": 0.24},
93
- {"name": "ظروف جوية غير مناسبة", "probability": 0.2, "impact": 0.3, "score": 0.06}
94
- ],
95
- "local_content": {
96
- "estimated_percentage": np.random.uniform(50, 80, 1)[0].round(2),
97
- "required_percentage": np.random.uniform(40, 60, 1)[0].round(2),
98
- "breakdown": {
99
- "عمالة محلية": np.random.uniform(60, 90, 1)[0].round(2),
100
- "مواد محلية": np.random.uniform(40, 70, 1)[0].round(2),
101
- "خدمات محلية": np.random.uniform(50, 80, 1)[0].round(2),
102
- "تدريب وتطوير": np.random.uniform(30, 60, 1)[0].round(2)
103
- }
104
- },
105
- "success_probability": np.random.uniform(60, 90, 1)[0].round(2)
106
- }
107
-
108
- st.success("تم الانتهاء من تحليل المناقصة بنجاح!")
109
-
110
- with col2:
111
- # عرض نتائج التحليل إذا كانت متوفرة
112
- if "analysis_results" in st.session_state and st.session_state.analysis_results:
113
- results = st.session_state.analysis_results
114
-
115
- # عرض معلومات المناقصة
116
- st.markdown("### معلومات المناقصة")
117
- st.markdown(f"**رقم المناقصة:** {results['tender_id']}")
118
- st.markdown(f"**تاريخ التحليل:** {results['analyzed_at']}")
119
 
120
- # تبويب لعرض مختلف أنواع التحليل
121
- tabs = st.tabs([
122
- "المتطلبات",
123
- "التكاليف",
124
- "المخاطر",
125
- "المحتوى المحلي",
126
- "احتمالية النجاح"
127
- ])
128
 
129
- # تبويب المتطلبات
130
- with tabs[0]:
131
- st.markdown("### المتطلبات الرئيسية للمناقصة")
132
- for i, req in enumerate(results["requirements"]):
133
- st.markdown(f"{i+1}. {req}")
134
 
135
- # تبويب التكاليف
136
- with tabs[1]:
137
- st.markdown("### تحليل التكاليف التقديرية")
138
-
139
- # إجمالي التكلفة
140
- st.markdown(f"**إجمالي التكلفة التقديرية:** {results['cost_estimate']['total']} مليون ريال")
141
-
142
- # رسم بياني لتوزيع التكاليف
143
- cost_data = {
144
- "الفئة": list(results["cost_estimate"]["breakdown"].keys()),
145
- "القيمة (مليون ريال)": list(results["cost_estimate"]["breakdown"].values())
146
- }
147
-
148
- cost_df = pd.DataFrame(cost_data)
149
-
150
- fig = px.pie(
151
- cost_df,
152
- values="القيمة (مليون ريال)",
153
- names="الفئة",
154
- title="توزيع التكاليف التقديرية",
155
- color_discrete_sequence=px.colors.qualitative.Bold
156
- )
157
-
158
- st.plotly_chart(fig, use_container_width=True)
159
-
160
- # تبويب المخاطر
161
- with tabs[2]:
162
- st.markdown("### تحليل المخاطر")
163
-
164
- # جدول المخاطر
165
- risk_data = pd.DataFrame(results["risks"])
166
- risk_data.columns = ["المخاطرة", "الاحتمالية", "التأثير", "الدرجة"]
167
-
168
- st.table(risk_data.style.format({
169
- "الاحتمالية": "{:.1%}",
170
- "ا��تأثير": "{:.1%}",
171
- "الدرجة": "{:.1%}"
172
- }))
173
-
174
- # مصفوفة المخاطر
175
- st.markdown("### مصفوفة المخاطر")
176
-
177
- fig = px.scatter(
178
- risk_data,
179
- x="الاحتمالية",
180
- y="التأثير",
181
- size="الدرجة",
182
- text="المخاطرة",
183
- size_max=60,
184
- color="الدرجة",
185
- color_continuous_scale=px.colors.sequential.Reds,
186
- title="مصفوفة المخاطر",
187
- range_x=[0, 1],
188
- range_y=[0, 1]
189
- )
190
-
191
- fig.update_traces(textposition="top center")
192
- fig.update_layout(
193
- xaxis_title="احتمالية الحدوث",
194
- yaxis_title="مستوى التأثير"
195
- )
196
 
197
- st.plotly_chart(fig, use_container_width=True)
 
 
198
 
199
- # تبويب المحتوى المحلي
200
- with tabs[3]:
201
- st.markdown("### تحليل المحتوى المحلي")
202
-
203
- # نسب المحتوى المحلي
204
- est_pct = results["local_content"]["estimated_percentage"]
205
- req_pct = results["local_content"]["required_percentage"]
206
-
207
- col1, col2 = st.columns(2)
208
-
209
- with col1:
210
- # متطلبات المحتوى المحلي
211
- st.markdown(f"**نسبة المحتوى المحلي المطلوبة:** {req_pct}%")
212
- st.progress(req_pct / 100)
213
-
214
- with col2:
215
- # النسبة المتوقعة
216
- st.markdown(f"**نسبة المحتوى المحلي المتوقعة:** {est_pct}%")
217
- st.progress(est_pct / 100)
218
-
219
- # حالة المحتوى المحلي (هل يلبي المتطلبات)
220
- if est_pct >= req_pct:
221
- st.success(f"المحتوى المحلي المتوقع يتجاوز المتطلبات بنسبة {est_pct - req_pct:.1f}%")
222
- else:
223
- st.error(f"المحتوى المحلي المتوقع أقل من المتطلبات بنسبة {req_pct - est_pct:.1f}%")
224
-
225
- # رسم بياني لمكونات المحتوى المحلي
226
- local_data = {
227
- "الفئة": list(results["local_content"]["breakdown"].keys()),
228
- "النسبة (%)": list(results["local_content"]["breakdown"].values())
229
- }
230
-
231
- local_df = pd.DataFrame(local_data)
232
-
233
- fig = px.bar(
234
- local_df,
235
- x="الفئة",
236
- y="النسبة (%)",
237
- color="النسبة (%)",
238
- color_continuous_scale=px.colors.sequential.Viridis,
239
- title="مكونات المحتوى المحلي حسب الفئة"
240
- )
241
-
242
- st.plotly_chart(fig, use_container_width=True)
243
 
244
- # تبويب احتمالية النجاح
245
- with tabs[4]:
246
- st.markdown("### توقع احتمالية النجاح")
247
-
248
- # عرض احتمالية النجاح
249
- success_prob = results["success_probability"]
250
-
251
- # اختيار اللون حسب النسبة
252
- color = "green" if success_prob >= 80 else "orange" if success_prob >= 60 else "red"
253
-
254
- st.markdown(f"<h1 style='text-align: center; color: {color};'>{success_prob}%</h1>", unsafe_allow_html=True)
255
- st.progress(success_prob / 100)
256
-
257
- # نصائح لتحسين الاحتمالية
258
- st.markdown("### توصيات لتحسين فرص النجاح")
259
-
260
- recommendations = [
261
- "زيادة نسبة المحتوى المحلي بنسبة 5-10%",
262
- "تعزيز فريق المشروع بخبرات في مجال التقنية",
263
- "البحث عن موردين محليين بديلين للمواد الرئيسية",
264
- "وضع خطة واضحة للتعامل مع المخاطر ذات التأثير العالي",
265
- "تقديم حلول مبتكرة في المجالات التقنية"
266
- ]
267
-
268
- for rec in recommendations:
269
- st.markdown(f"- {rec}")
270
-
271
- # زر لحفظ التقرير
272
- if st.button("حفظ تقرير التحليل"):
273
- st.session_state.latest_analysis = results
274
- st.success("تم حفظ تقرير التحليل بنجاح!")
275
- else:
276
- # توجيهات للمستخدم
277
- st.info("قم برفع ملفات المناقصة واختر خيارات التحليل المطلوبة، ثم اضغط على زر 'بدء التحليل' لعرض النتائج هنا.")
278
 
279
- # عرض مثال توضيحي
280
- st.markdown("### مثال توضيحي لنتائج التحليل")
281
- st.image("https://via.placeholder.com/800x500?text=مثال+لنتائج+تحليل+المناقصة", caption="مثال لنتائج تحليل المناقصة")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
282
 
283
- # اختبار مستقل للصفحة
284
- if __name__ == "__main__":
285
- st.set_page_config(
286
- page_title="نظام تحليل المناقصات - تحليل المناقصات",
287
- page_icon="📊",
288
- layout="wide",
289
  )
290
- show_tender_analysis()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import streamlit as st
2
  import pandas as pd
3
  import numpy as np
4
+ import matplotlib.pyplot as plt
5
+ import seaborn as sns
 
6
 
7
+ def tender_analysis_page():
8
  """
9
+ صفحة تحليل العطاءات - تعرض تحليلات مختلفة للعطاءات
10
  """
11
+ st.title("تحليل العطاءات")
12
+ st.write("هذه الصفحة تعرض تحليلات مختلفة للعطاءات والمناقصات")
13
 
14
+ # يمكنك إضافة رفع ملف CSV أو Excel
15
+ uploaded_file = st.file_uploader("ارفع ملف بيانات العطاءات", type=["csv", "xlsx"])
16
 
17
+ if uploaded_file is not None:
18
+ # قراءة البيانات
19
+ try:
20
+ if uploaded_file.name.endswith('csv'):
21
+ df = pd.read_csv(uploaded_file)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  else:
23
+ df = pd.read_excel(uploaded_file)
24
+
25
+ # عرض البيانات الأولية
26
+ st.subheader("نظرة عامة على البيانات")
27
+ st.dataframe(df.head())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
 
29
+ # إحصائيات أساسية
30
+ st.subheader("إحصائيات أساسية")
31
+ st.write(df.describe())
 
 
 
 
 
32
 
33
+ # تحليل حسب نوع العطاء (مثال)
34
+ if 'نوع_العطاء' in df.columns:
35
+ st.subheader("تحليل حسب نوع العطاء")
36
+ tender_types = df['نوع_العطاء'].value_counts()
37
+ st.bar_chart(tender_types)
38
 
39
+ # تحليل القيمة حسب الشهر (مثال)
40
+ if 'تاريخ' in df.columns and 'قيمة_العطاء' in df.columns:
41
+ st.subheader("تحليل قيمة العطاءات حسب الشهر")
42
+ df['شهر'] = pd.to_datetime(df['تاريخ']).dt.month
43
+ monthly_values = df.groupby('شهر')['قيمة_العطاء'].sum()
44
+ st.line_chart(monthly_values)
45
+
46
+ # تحليل نسب النجاح (مثال)
47
+ if 'حالة_العطاء' in df.columns:
48
+ st.subheader("نسب نجاح العطاءات")
49
+ success_rate = df['حالة_العطاء'].value_counts(normalize=True) * 100
50
+ st.pie_chart(success_rate)
51
+
52
+ except Exception as e:
53
+ st.error(f"حدث خطأ أثناء تحليل البيانات: {e}")
54
+ else:
55
+ st.info("يرجى رفع ملف بيانات العطاءات لعرض التحليلات")
56
+
57
+ def contracts_page():
58
+ """
59
+ صفحة إدارة العقود - تعرض معلومات وتحليلات للعقود
60
+ """
61
+ st.title("إدارة العقود")
62
+ st.write("هذه الصفحة مخصصة لإدارة وتحليل العقود")
63
+
64
+ # يمكنك إضافة رفع ملف CSV أو Excel
65
+ uploaded_file = st.file_uploader("ارفع ملف بيانات العقود", type=["csv", "xlsx"])
66
+
67
+ if uploaded_file is not None:
68
+ # قراءة البيانات
69
+ try:
70
+ if uploaded_file.name.endswith('csv'):
71
+ df = pd.read_csv(uploaded_file)
72
+ else:
73
+ df = pd.read_excel(uploaded_file)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
 
75
+ # عرض البيانات الأولية
76
+ st.subheader("نظرة عامة على بيانات العقود")
77
+ st.dataframe(df.head())
78
 
79
+ # إحصائيات العقود
80
+ st.subheader("إحصائيات العقود")
81
+ st.write(df.describe())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
 
83
+ # تحليل حسب نوع العقد (مثال)
84
+ if 'نوع_العقد' in df.columns:
85
+ st.subheader("تحليل حسب نوع العقد")
86
+ contract_types = df['نوع_العقد'].value_counts()
87
+ st.bar_chart(contract_types)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
 
89
+ # تحليل قيمة العقود حسب الشهر (مثال)
90
+ if 'تاريخ_التوقيع' in df.columns and 'قيمة_العقد' in df.columns:
91
+ st.subheader("تحليل قيمة العقود حسب الشهر")
92
+ df['شهر'] = pd.to_datetime(df['تاريخ_التوقيع']).dt.month
93
+ monthly_values = df.groupby('شهر')['قيمة_العقد'].sum()
94
+ st.line_chart(monthly_values)
95
+
96
+ # تحليل العقود حسب المورد/العميل (مثال)
97
+ if 'المورد' in df.columns and 'قيمة_العقد' in df.columns:
98
+ st.subheader("تحليل العقود حسب المورد")
99
+ vendor_analysis = df.groupby('المورد')['قيمة_العقد'].sum().sort_values(ascending=False).head(10)
100
+ st.bar_chart(vendor_analysis)
101
+
102
+ # جدول العقود النشطة (مثال)
103
+ if 'حالة_العقد' in df.columns:
104
+ st.subheader("العقود النشطة")
105
+ active_contracts = df[df['حالة_العقد'] == 'نشط']
106
+ st.dataframe(active_contracts)
107
+
108
+ except Exception as e:
109
+ st.error(f"حدث خطأ أثناء تحليل بيانات العقود: {e}")
110
+ else:
111
+ st.info("يرجى رفع ملف بيانات العقود لعرض التحليلات")
112
 
113
+ def main():
114
+ st.sidebar.title("قائمة الصفحات")
115
+ page = st.sidebar.selectbox(
116
+ "اختر صفحة",
117
+ ["الصفحة الرئيسية", "تحليل العطاءات", "إدارة العقود", "المعلومات"]
 
118
  )
119
+
120
+ if page == "الصفحة الرئيسية":
121
+ home_page()
122
+ elif page == "تحليل العطاءات":
123
+ tender_analysis_page()
124
+ elif page == "إدارة العقود":
125
+ contracts_page()
126
+ elif page == "المعلومات":
127
+ about_page()
128
+
129
+ def home_page():
130
+ st.title("نظام تحليل العطاءات")
131
+ st.write("مرحباً بك في نظام تحليل العطاءات. استخدم القائمة الجانبية للتنقل بين الصفحات.")
132
+
133
+ def about_page():
134
+ st.title("عن النظام")
135
+ st.write("نظام تحليل العطاءات هو أداة لتحليل بيانات العطاءات والمناقصات.")
136
+
137
+ if __name__ == "__main__":
138
+ main()