EGYADMIN commited on
Commit
f5d8f9a
·
verified ·
1 Parent(s): 1a83ba4

Create web/pages/requirements_analysis.py

Browse files
Files changed (1) hide show
  1. web/pages/requirements_analysis.py +192 -1
web/pages/requirements_analysis.py CHANGED
@@ -23,4 +23,195 @@ def show_requirements_analysis():
23
  sample_requirements = [
24
  {"المتطلب": "توريد وتركيب معدات الشبكة", "النوع": "فني", "الأولوية": "عالية", "التخصص": "تقنية المعلومات"},
25
  {"المتطلب": "تدريب الموظفين", "النوع": "إداري", "الأولوية": "متوسطة", "التخصص": "تدريب"},
26
- {"المتطلب": "توفير الصي
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  sample_requirements = [
24
  {"المتطلب": "توريد وتركيب معدات الشبكة", "النوع": "فني", "الأولوية": "عالية", "التخصص": "تقنية المعلومات"},
25
  {"المتطلب": "تدريب الموظفين", "النوع": "إداري", "الأولوية": "متوسطة", "التخصص": "تدريب"},
26
+ {"المتطلب": "توفير الصيانة لمدة 3 سنوات", "النوع": "تعاقدي", "الأولوية": "عالية", "التخصص": "صيانة"},
27
+ {"المتطلب": "الالتزام بمعايير الأمن السيبراني", "النوع": "تنظيمي", "الأولوية": "عالية", "التخصص": "أمن المعلومات"},
28
+ {"المتطلب": "نسبة محتوى محلي لا تقل عن 50%", "النوع": "تنظيمي", "الأولوية": "عالية", "التخصص": "محتوى محلي"},
29
+ {"المتطلب": "تقديم ضمان بنكي بنسبة 10%", "النوع": "مالي", "الأولوية": "متوسطة", "التخصص": "مالي"},
30
+ {"المتطلب": "تنفيذ المشروع في مدة لا تتجاوز 18 شهر", "النوع": "زمني", "الأولوية": "عالية", "التخصص": "إدارة مشاريع"},
31
+ ]
32
+
33
+ sample_df = pd.DataFrame(sample_requirements)
34
+ st.table(sample_df)
35
+ return
36
+
37
+ # عرض معلومات المناقصة
38
+ results = st.session_state.analysis_results
39
+ st.markdown(f"### تحليل متطلبات المناقصة رقم {results['tender_id']}")
40
+
41
+ # إنشاء بيانات المتطلبات (نستخدم البيانات المتاحة أو نضيف تفاصيل إضافية)
42
+ # في التطبيق الفعلي، ستكون هذه البيانات من نتائج التحليل الحقيقي
43
+ requirements = []
44
+
45
+ for i, req in enumerate(results.get("requirements", [])):
46
+ # إنشاء تفاصيل عشوائية لكل متطلب للتوضيح
47
+ req_type = np.random.choice(["فني", "إداري", "تعاقدي", "تنظيمي", "مالي", "زمني"])
48
+ priority = np.random.choice(["عالية", "متوسطة", "منخفضة"], p=[0.5, 0.3, 0.2])
49
+
50
+ specializations = {
51
+ "فني": ["هندسة", "تقنية المعلومات", "اتصالات", "كهرباء", "ميكانيكا"],
52
+ "إداري": ["إدارة مشاريع", "موارد بشرية", "تدريب", "جودة"],
53
+ "تعاقدي": ["قانوني", "مشتريات", "عقود", "صيانة"],
54
+ "تنظيمي": ["امتثال", "أمن المعلومات", "محتوى محلي", "بيئة"],
55
+ "مالي": ["محاسبة", "ضمانات", "تمويل", "مالي"],
56
+ "زمني": ["إدارة مشاريع", "جدولة", "تخطيط"]
57
+ }
58
+
59
+ specialization = np.random.choice(specializations.get(req_type, ["عام"]))
60
+
61
+ requirements.append({
62
+ "المتطلب": req,
63
+ "النوع": req_type,
64
+ "الأولوية": priority,
65
+ "التخصص": specialization
66
+ })
67
+
68
+ # إذا لم تكن هناك متطلبات، إنشاء بيانات توضيحية
69
+ if not requirements:
70
+ requirements = [
71
+ {"المتطلب": "توريد وتركيب معدات", "النوع": "فني", "الأولوية": "عالية", "التخصص": "هندسة"},
72
+ {"المتطلب": "تدريب الموظفين", "النوع": "إداري", "الأولوية": "متوسطة", "التخصص": "تدريب"},
73
+ {"المتطلب": "صيانة دورية", "النوع": "تعاقدي", "الأولوية": "متوسطة", "التخصص": "صيانة"},
74
+ {"المتطلب": "الامتثال للمعايير", "النوع": "تنظيمي", "الأولوية": "عالية", "التخصص": "امتثال"},
75
+ {"المتطلب": "تقديم ضمانات مالية", "النوع": "مالي", "الأولوية": "عالية", "التخصص": "مالي"}
76
+ ]
77
+
78
+ # تحويل البيانات إلى DataFrame
79
+ requirements_df = pd.DataFrame(requirements)
80
+
81
+ # تبويبات لعرض المتطلبات بطرق مختلفة
82
+ tab1, tab2, tab3 = st.tabs(["قائمة المتطلبات", "تصنيف المتطلبات", "تحليل المتطلبات"])
83
+
84
+ # تبويب قائمة المتطلبات
85
+ with tab1:
86
+ st.markdown("### قائمة متطلبات المناقصة")
87
+ st.dataframe(requirements_df, use_container_width=True)
88
+
89
+ # خيار تصفية المتطلبات
90
+ st.markdown("### تصفية المتطلبات")
91
+
92
+ col1, col2 = st.columns(2)
93
+
94
+ with col1:
95
+ selected_type = st.selectbox(
96
+ "تصفية حسب النوع",
97
+ ["الكل"] + sorted(requirements_df["النوع"].unique().tolist())
98
+ )
99
+
100
+ with col2:
101
+ selected_priority = st.selectbox(
102
+ "تصفية حسب الأولوية",
103
+ ["الكل"] + sorted(requirements_df["الأولوية"].unique().tolist())
104
+ )
105
+
106
+ # تطبيق التصفية
107
+ filtered_df = requirements_df.copy()
108
+
109
+ if selected_type != "الكل":
110
+ filtered_df = filtered_df[filtered_df["النوع"] == selected_type]
111
+
112
+ if selected_priority != "الكل":
113
+ filtered_df = filtered_df[filtered_df["الأولوية"] == selected_priority]
114
+
115
+ if selected_type != "الكل" or selected_priority != "الكل":
116
+ st.markdown("### المتطلبات المصفاة")
117
+ st.dataframe(filtered_df, use_container_width=True)
118
+
119
+ # تبويب تصنيف المتطلبات
120
+ with tab2:
121
+ st.markdown("### تصنيف المتطلبات حسب النوع والأولوية")
122
+
123
+ # رسم بياني للمتطلبات حسب النوع
124
+ type_counts = requirements_df["النوع"].value_counts().reset_index()
125
+ type_counts.columns = ["النوع", "العدد"]
126
+
127
+ fig1 = px.bar(
128
+ type_counts,
129
+ x="النوع",
130
+ y="العدد",
131
+ color="النوع",
132
+ title="توزيع المتطلبات حسب النوع"
133
+ )
134
+
135
+ st.plotly_chart(fig1, use_container_width=True)
136
+
137
+ # رسم بياني للمتطلبات حسب الأولوية
138
+ priority_counts = requirements_df["الأولوية"].value_counts().reset_index()
139
+ priority_counts.columns = ["الأولوية", "العدد"]
140
+
141
+ # ترتيب الأولويات
142
+ priority_order = {"عالية": 1, "متوسطة": 2, "منخفضة": 3}
143
+ priority_counts["الترتيب"] = priority_counts["الأولوية"].map(priority_order)
144
+ priority_counts = priority_counts.sort_values("الترتيب")
145
+
146
+ # اختيار الألوان حسب الأولوية
147
+ color_map = {"عالية": "#FF5733", "متوسطة": "#FFC300", "منخفضة": "#33FF57"}
148
+ colors = priority_counts["الأولوية"].map(color_map)
149
+
150
+ fig2 = px.bar(
151
+ priority_counts,
152
+ x="الأولوية",
153
+ y="العدد",
154
+ color="الأولوية",
155
+ color_discrete_map=color_map,
156
+ title="توزيع المتطلبات حسب الأولوية"
157
+ )
158
+
159
+ st.plotly_chart(fig2, use_container_width=True)
160
+
161
+ # تبويب تحليل المتطلبات
162
+ with tab3:
163
+ st.markdown("### تحليل المتطلبات")
164
+
165
+ # توزيع المتطلبات حسب التخصص
166
+ specialization_counts = requirements_df["التخصص"].value_counts().reset_index()
167
+ specialization_counts.columns = ["التخصص", "العدد"]
168
+
169
+ fig3 = px.pie(
170
+ specialization_counts,
171
+ values="العدد",
172
+ names="التخصص",
173
+ title="توزيع المتطلبات حسب التخصص",
174
+ color_discrete_sequence=px.colors.qualitative.Bold
175
+ )
176
+
177
+ fig3.update_traces(textposition="inside", textinfo="percent+label")
178
+
179
+ st.plotly_chart(fig3, use_container_width=True)
180
+
181
+ # مصفوفة المتطلبات (النوع × الأولوية)
182
+ heatmap_data = pd.crosstab(
183
+ requirements_df["النوع"],
184
+ requirements_df["الأولوية"],
185
+ margins=True,
186
+ margins_name="الإجمالي"
187
+ )
188
+
189
+ # ترتيب الأعمدة (الأولويات)
190
+ priority_columns = ["عالية", "متوسطة", "منخفضة", "الإجمالي"]
191
+ heatmap_data = heatmap_data.reindex(columns=priority_columns, fill_value=0)
192
+
193
+ st.markdown("### مصفوفة المتطلبات (النوع × الأولوية)")
194
+ st.dataframe(heatmap_data, use_container_width=True)
195
+
196
+ # خيارات إضافية
197
+ st.markdown("### خيارات إضافية")
198
+
199
+ col1, col2 = st.columns(2)
200
+
201
+ with col1:
202
+ if st.button("تصدير المتطلبات إلى Excel"):
203
+ st.success("تم تصدير المتطلبات إلى ملف Excel بنجاح!")
204
+
205
+ with col2:
206
+ if st.button("العودة إلى تحليل المناقصة"):
207
+ st.session_state.page = "تحليل المناقصات"
208
+ st.experimental_rerun()
209
+
210
+ # اختبار مستقل للصفحة
211
+ if __name__ == "__main__":
212
+ st.set_page_config(
213
+ page_title="نظام تحليل المناقصات - تحليل المتطلبات",
214
+ page_icon="📊",
215
+ layout="wide",
216
+ )
217
+ show_requirements_analysis()