EGYADMIN commited on
Commit
b17d178
·
verified ·
1 Parent(s): bc8c650

Create web/pages/supply_chain.py

Browse files
Files changed (1) hide show
  1. web/pages/supply_chain.py +532 -0
web/pages/supply_chain.py ADDED
@@ -0,0 +1,532 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ import numpy as np
4
+ import plotly.express as px
5
+ import plotly.graph_objects as go
6
+
7
+ def show_supply_chain():
8
+ """
9
+ عرض صفحة تحليل سلاسل الإمداد
10
+ """
11
+ st.subheader("إدارة سلاسل الإمداد")
12
+
13
+ # إنشاء القائمة الجانبية للخيارات
14
+ options = st.sidebar.radio(
15
+ "اختر القسم",
16
+ ["تحليل الموردين", "تحليل المخاطر", "التكاليف والتسعير", "التحسين والتوقعات"]
17
+ )
18
+
19
+ if options == "تحليل الموردين":
20
+ show_vendor_analysis()
21
+ elif options == "تحليل المخاطر":
22
+ show_risk_analysis()
23
+ elif options == "التكاليف والتسعير":
24
+ show_cost_pricing()
25
+ elif options == "التحسين والتوقعات":
26
+ show_optimization()
27
+
28
+ def show_vendor_analysis():
29
+ """
30
+ عرض تحليل الموردين
31
+ """
32
+ st.markdown("## تحليل الموردين")
33
+
34
+ # إنشاء بيانات توضيحية للموردين
35
+ vendor_data = {
36
+ "المورد": [
37
+ "شركة الصناعات السعودية",
38
+ "مؤسسة الخليج للمقاولات",
39
+ "شركة الرياض للإنشاءات",
40
+ "الشركة العربية للمعدات",
41
+ "مصنع المنتجات الإسمنتية",
42
+ "شركة تقنيات البناء",
43
+ "مؤسسة المدار للتوريدات",
44
+ "شركة البنية التحتية المتكاملة"
45
+ ],
46
+ "الفئة": [
47
+ "مواد بناء",
48
+ "مقاولات",
49
+ "خدمات هندسية",
50
+ "معدات",
51
+ "مواد خام",
52
+ "تقنيات",
53
+ "مواد متنوعة",
54
+ "خدمات هندسية"
55
+ ],
56
+ "قيمة التوريدات (مليون ريال)": [25.4, 18.2, 12.7, 9.8, 8.5, 7.3, 6.1, 5.8],
57
+ "نسبة المحتوى المحلي (%)": [85, 92, 78, 65, 100, 70, 88, 75],
58
+ "متوسط وقت التسليم (أيام)": [14, 30, 21, 45, 7, 15, 10, 25],
59
+ "التقييم العام (5)": [4.2, 3.8, 4.5, 3.5, 4.0, 4.3, 3.7, 4.1]
60
+ }
61
+
62
+ vendor_df = pd.DataFrame(vendor_data)
63
+
64
+ # عرض بيانات الموردين
65
+ st.markdown("### بيانات الموردين الرئيسيين")
66
+ st.dataframe(vendor_df, use_container_width=True)
67
+
68
+ # تحليلات الموردين
69
+ col1, col2 = st.columns(2)
70
+
71
+ with col1:
72
+ # توزيع الموردين حسب الفئة
73
+ st.markdown("### توزيع الموردين حسب الفئة")
74
+
75
+ category_counts = vendor_df.groupby("الفئة")["قيمة التوريدات (مليون ريال)"].sum().reset_index()
76
+
77
+ fig1 = px.pie(
78
+ category_counts,
79
+ values="قيمة التوريدات (مليون ريال)",
80
+ names="الفئة",
81
+ title="توزيع قيمة التوريدات حسب الفئة",
82
+ color_discrete_sequence=px.colors.qualitative.Bold
83
+ )
84
+
85
+ fig1.update_traces(textposition="inside", textinfo="percent+label")
86
+
87
+ st.plotly_chart(fig1, use_container_width=True)
88
+
89
+ with col2:
90
+ # تقييم الموردين مقابل نسبة المحتوى المحلي
91
+ st.markdown("### تقييم الموردين مقابل نسبة المحتوى المحلي")
92
+
93
+ fig2 = px.scatter(
94
+ vendor_df,
95
+ x="نسبة المحتوى المحلي (%)",
96
+ y="التقييم العام (5)",
97
+ size="قيمة التوريدات (مليون ريال)",
98
+ color="الفئة",
99
+ hover_name="المورد",
100
+ title="تقييم الموردين مقابل نسبة المحتوى المحلي",
101
+ size_max=50
102
+ )
103
+
104
+ st.plotly_chart(fig2, use_container_width=True)
105
+
106
+ # تحليل أوقات التسليم
107
+ st.markdown("### تحليل أوقات التسليم")
108
+
109
+ fig3 = px.bar(
110
+ vendor_df.sort_values("متوسط وقت التسليم (أيام)"),
111
+ x="المورد",
112
+ y="متوسط وقت التسليم (أيام)",
113
+ color="متوسط وقت التسليم (أيام)",
114
+ color_continuous_scale="Viridis",
115
+ title="متوسط وقت التسليم حسب المورد"
116
+ )
117
+
118
+ st.plotly_chart(fig3, use_container_width=True)
119
+
120
+ # توصيات تحسين سلسلة الإمداد
121
+ st.markdown("### توصيات لتحسين سلسلة الإمداد")
122
+
123
+ recommendations = [
124
+ "تنويع قاعدة الموردين في فئة المعدات لتقليل المخاطر",
125
+ "العمل مع الموردين لتحسين أوقات التسليم خاصة مع الشركة العربي�� للمعدات",
126
+ "زيادة الاعتماد على الموردين ذوي نسب المحتوى المحلي الأعلى",
127
+ "وضع خطة لتقليل الاعتماد على الموردين ذوي التقييم المنخفض",
128
+ "تطوير برنامج لتحسين أداء الموردين من خلال التدريب والدعم الفني"
129
+ ]
130
+
131
+ for i, rec in enumerate(recommendations):
132
+ st.markdown(f"{i+1}. {rec}")
133
+
134
+ def show_risk_analysis():
135
+ """
136
+ عرض تحليل مخاطر سلسلة الإمداد
137
+ """
138
+ st.markdown("## تحليل مخاطر سلسلة الإمداد")
139
+
140
+ # إنشاء بيانات توضيحية للمخاطر
141
+ risk_data = {
142
+ "المخاطرة": [
143
+ "تأخر توريد المواد الرئيسية",
144
+ "ارتفاع تكلفة المواد الخام",
145
+ "تعطل وسائل النقل",
146
+ "مشاكل جودة المنتجات",
147
+ "نقص في المخزون",
148
+ "تغير متطلبات المشروع",
149
+ "مخاطر تقلبات العملة",
150
+ "أزمات الموردين المالية",
151
+ "الكوارث الطبيعية",
152
+ "المخاطر السياسية والتشريعية"
153
+ ],
154
+ "الاحتمالية": [0.4, 0.6, 0.3, 0.5, 0.4, 0.7, 0.2, 0.3, 0.1, 0.2],
155
+ "التأثير": [0.7, 0.6, 0.5, 0.8, 0.6, 0.5, 0.4, 0.7, 0.9, 0.8],
156
+ "الفئة": [
157
+ "توريد", "تكلفة", "لوجستيات", "جودة", "تخطيط",
158
+ "متطلبات", "مالية", "موردين", "خارجية", "تنظيمية"
159
+ ]
160
+ }
161
+
162
+ risk_df = pd.DataFrame(risk_data)
163
+
164
+ # إضافة درجة المخاطرة
165
+ risk_df["درجة المخاطرة"] = risk_df["الاحتمالية"] * risk_df["التأثير"]
166
+
167
+ # تصنيف المخاطر
168
+ conditions = [
169
+ (risk_df["درجة المخاطرة"] >= 0.4),
170
+ (risk_df["درجة المخاطرة"] >= 0.2),
171
+ (risk_df["درجة المخاطرة"] < 0.2)
172
+ ]
173
+ values = ["عالية", "متوسطة", "منخفضة"]
174
+ risk_df["مستوى المخاطرة"] = np.select(conditions, values)
175
+
176
+ # عرض مصفوفة المخاطر
177
+ st.markdown("### مصفوفة مخاطر سلسلة الإمداد")
178
+
179
+ fig1 = px.scatter(
180
+ risk_df,
181
+ x="الاحتمالية",
182
+ y="التأثير",
183
+ color="مستوى المخاطرة",
184
+ size="درجة المخاطرة",
185
+ hover_name="المخاطرة",
186
+ text="المخاطرة",
187
+ color_discrete_map={"عالية": "#FF5733", "متوسطة": "#FFC300", "منخفضة": "#33FF57"},
188
+ title="مصفوفة تحليل المخاطر",
189
+ size_max=50
190
+ )
191
+
192
+ fig1.update_layout(
193
+ xaxis_title="احتمالية الحدوث",
194
+ yaxis_title="مستوى التأثير",
195
+ xaxis=dict(range=[0, 1]),
196
+ yaxis=dict(range=[0, 1])
197
+ )
198
+
199
+ fig1.update_traces(
200
+ textposition="top center",
201
+ textfont=dict(size=10)
202
+ )
203
+
204
+ st.plotly_chart(fig1, use_container_width=True)
205
+
206
+ # عرض جدول المخاطر
207
+ st.markdown("### قائمة المخاطر مرتبة حسب درجة الخطورة")
208
+
209
+ sorted_risks = risk_df.sort_values("درجة المخاطرة", ascending=False)
210
+
211
+ # تنسيق العرض
212
+ formatted_risks = sorted_risks.copy()
213
+ formatted_risks["الاحتمالية"] = formatted_risks["الاحتمالية"].apply(lambda x: f"{x:.1%}")
214
+ formatted_risks["التأثير"] = formatted_risks["التأثير"].apply(lambda x: f"{x:.1%}")
215
+ formatted_risks["درجة المخاطرة"] = formatted_risks["درجة المخاطرة"].apply(lambda x: f"{x:.1%}")
216
+
217
+ st.dataframe(formatted_risks, use_container_width=True)
218
+
219
+ # المخاطر حسب الفئة
220
+ st.markdown("### المخاطر حسب الفئة")
221
+
222
+ category_risks = risk_df.groupby("الفئة")["درجة المخاطرة"].mean().reset_index()
223
+ category_risks = category_risks.sort_values("درجة المخاطرة", ascending=False)
224
+
225
+ fig2 = px.bar(
226
+ category_risks,
227
+ x="الفئة",
228
+ y="درجة المخاطرة",
229
+ color="درجة المخاطرة",
230
+ color_continuous_scale="Reds",
231
+ title="متوسط درجة المخاطرة حسب الفئة"
232
+ )
233
+
234
+ fig2.update_layout(yaxis_tickformat=".1%")
235
+
236
+ st.plotly_chart(fig2, use_container_width=True)
237
+
238
+ # استراتيجيات تخفيف المخاطر
239
+ st.markdown("### استراتيجيات تخفيف المخاطر ذات الأولوية العالية")
240
+
241
+ high_risks = sorted_risks[sorted_risks["مستوى المخاطرة"] == "عالية"]
242
+
243
+ mitigation_strategies = {
244
+ "تأخر توريد المواد الرئيسية": "إنشاء قاعدة موردين بديلة وتطوير خطط طوارئ للتوريد",
245
+ "ارتفاع تكلفة المواد الخام": "توقيع عقود طويلة الأجل وتأمين أسعار ثابتة",
246
+ "مشاكل جودة المنتجات": "تعزيز نظام فحص الجودة وتطوير معايير قبول صارمة",
247
+ "تغير متطلبات المشروع": "تحسين عمليات إدارة التغيير وتوثيق المتطلبات بشكل أفضل",
248
+ "أزمات الموردين المالية": "تقييم الصحة المالية للموردين بشكل دوري واستخدام ضمانات التنفيذ",
249
+ "الكوارث الطبيعية": "تطوير خطط استمرارية الأعمال واستخدام موردين من مناطق جغرافية متنوعة"
250
+ }
251
+
252
+ for _, risk in high_risks.iterrows():
253
+ risk_name = risk["المخاطرة"]
254
+ strategy = mitigation_strategies.get(risk_name, "وضع استراتيجية مخصصة للتخفيف من هذه المخاطر")
255
+
256
+ st.markdown(f"**{risk_name}** (درجة المخاطرة: {risk['درجة المخاطرة']})")
257
+ st.markdown(f"*استراتيجية التخفيف:* {strategy}")
258
+ st.markdown("---")
259
+
260
+ def show_cost_pricing():
261
+ """
262
+ عرض تحليل التكاليف والتسعير
263
+ """
264
+ st.markdown("## تحليل التكاليف والتسعير")
265
+
266
+ # إنشاء بيانات توضيحية للمواد
267
+ materials_data = {
268
+ "المادة": [
269
+ "حديد تسليح",
270
+ "إسمنت",
271
+ "خرسانة جاهزة",
272
+ "طوب",
273
+ "رمل",
274
+ "خشب",
275
+ "مواد عازلة",
276
+ "كابلات كهربائية",
277
+ "أنابيب",
278
+ "أصباغ"
279
+ ],
280
+ "متوسط السعر (ريال/وحدة)": [3200, 15, 240, 2.5, 75, 1200, 85, 120, 160, 65],
281
+ "الكمية المتوقعة": [150, 8000, 1200, 25000, 350, 200, 750, 2000, 1500, 300],
282
+ "نسبة التغير السعري (%)": [12, 5, 8, 2, 3, 15, 7, 10, 6, 4],
283
+ "المصدر": [
284
+ "محلي", "محلي", "محلي", "محلي", "محلي",
285
+ "مستورد", "مستورد", "محلي", "محلي", "مستورد"
286
+ ]
287
+ }
288
+
289
+ materials_df = pd.DataFrame(materials_data)
290
+
291
+ # حساب إجمالي التكلفة
292
+ materials_df["إجمالي التكلفة (ريال)"] = materials_df["متوسط السعر (ريال/وحدة)"] * materials_df["الكمية المتوقعة"]
293
+
294
+ # حساب تأثير التغير السعري
295
+ materials_df["تأثير التغير السعري (ريال)"] = materials_df["إجمالي التكلفة (ريال)"] * (materials_df["نسبة التغير السعري (%)"] / 100)
296
+
297
+ # عرض بيانات المواد
298
+ st.markdown("### تحليل تكاليف المواد الرئيسية")
299
+
300
+ # تنسيق العرض
301
+ formatted_materials = materials_df.copy()
302
+ formatted_materials["إجمالي التكلفة (ريال)"] = formatted_materials["إجمالي التكلفة (ريال)"].map(lambda x: f"{x:,.0f}")
303
+ formatted_materials["تأثير التغير السعري (ريال)"] = formatted_materials["تأثير التغير السعري (ريال)"].map(lambda x: f"{x:,.0f}")
304
+
305
+ st.dataframe(formatted_materials, use_container_width=True)
306
+
307
+ # إجمالي التكاليف والمؤشرات
308
+ total_cost = materials_df["إجمالي التكلفة (ريال)"].sum()
309
+ total_price_impact = materials_df["تأثير التغير السعري (ريال)"].sum()
310
+ avg_price_change = materials_df["نسبة التغير السعري (%)"].mean()
311
+
312
+ col1, col2, col3 = st.columns(3)
313
+
314
+ with col1:
315
+ st.metric(
316
+ label="إجمالي تكلفة المواد (ريال)",
317
+ value=f"{total_cost:,.0f}"
318
+ )
319
+
320
+ with col2:
321
+ st.metric(
322
+ label="تأثير التغير السعري (ريال)",
323
+ value=f"{total_price_impact:,.0f}",
324
+ delta=f"{total_price_impact / total_cost:.1%}"
325
+ )
326
+
327
+ with col3:
328
+ st.metric(
329
+ label="متوسط نسبة التغير السعري",
330
+ value=f"{avg_price_change:.1f}%"
331
+ )
332
+
333
+ # توزيع التكاليف حسب المواد
334
+ st.markdown("### توزيع تكاليف المواد")
335
+
336
+ fig1 = px.pie(
337
+ materials_df,
338
+ values="إجمالي التكلفة (ريال)",
339
+ names="المادة",
340
+ title="توزيع تكاليف المواد",
341
+ color_discrete_sequence=px.colors.qualitative.Bold
342
+ )
343
+
344
+ fig1.update_traces(textposition="inside", textinfo="percent+label")
345
+
346
+ st.plotly_chart(fig1, use_container_width=True)
347
+
348
+ # تأثير التغير السعري حسب المادة
349
+ st.markdown("### تأثير التغير السعري حسب المادة")
350
+
351
+ sorted_impact = materials_df.sort_values("تأثير التغير السعري (ريال)", ascending=False)
352
+
353
+ fig2 = px.bar(
354
+ sorted_impact,
355
+ x="المادة",
356
+ y="تأثير التغير السعري (ريال)",
357
+ color="نسبة التغير السعري (%)",
358
+ color_continuous_scale="Reds",
359
+ title="تأثير التغير السعري حسب المادة"
360
+ )
361
+
362
+ st.plotly_chart(fig2, use_container_width=True)
363
+
364
+ # مقارنة المواد المحلية والمستوردة
365
+ st.markdown("### مقارنة المواد المحلية والمستوردة")
366
+
367
+ source_comparison = materials_df.groupby("المصدر").agg({
368
+ "إجمالي التكلفة (ريال)": "sum",
369
+ "تأثير التغير السعري (ريال)": "sum",
370
+ "المادة": "count"
371
+ }).reset_index()
372
+
373
+ source_comparison.columns = ["المصدر", "إجمالي التكلفة (ريال)", "تأثير التغير السعري (ريال)", "عدد المواد"]
374
+
375
+ col1, col2 = st.columns(2)
376
+
377
+ with col1:
378
+ # نسبة التكلفة حسب المصدر
379
+ fig3 = px.pie(
380
+ source_comparison,
381
+ values="إجمالي التكلفة (ريال)",
382
+ names="المصدر",
383
+ title="توزيع التكاليف: محلي مقابل مستورد",
384
+ color_discrete_map={"محلي": "#1976D2", "مستورد": "#D32F2F"}
385
+ )
386
+
387
+ fig3.update_traces(textposition="inside", textinfo="percent+label")
388
+
389
+ st.plotly_chart(fig3, use_container_width=True)
390
+
391
+ with col2:
392
+ # متوسط تأثير التغير السعري حسب المصدر
393
+ source_comparison["متوسط تأثير التغير لكل مادة"] = source_comparison["تأثير التغير السعري (ريال)"] / source_comparison["عدد المواد"]
394
+
395
+ fig4 = px.bar(
396
+ source_comparison,
397
+ x="المصدر",
398
+ y="متوسط تأثير التغير لكل مادة",
399
+ color="المصدر",
400
+ title="متوسط تأثير التغير السعري حسب المصدر",
401
+ color_discrete_map={"محلي": "#1976D2", "مستورد": "#D32F2F"}
402
+ )
403
+
404
+ st.plotly_chart(fig4, use_container_width=True)
405
+
406
+ # توصيات لتحسين التكاليف
407
+ st.markdown("### توصيات لتحسين التكاليف")
408
+
409
+ recommendations = [
410
+ "إبرام عقود طويلة الأجل للمواد ذات التغير السعري المرتفع (الحديد والخشب)",
411
+ "البحث عن موردين محليين بديلين للمواد المستوردة لتقليل تأثير تقلبات الأسعار",
412
+ "شراء المواد ذات الاستهلاك العالي بكميات كبيرة للحصول على خصومات الكمية",
413
+ "تطوير استراتيجية تخزين للمواد ذات التأثير السعري المرتفع",
414
+ "استخدام نماذج التنبؤ لتوقيت الشراء بشكل أفضل وتجنب فترات ارتفاع الأسعار"
415
+ ]
416
+
417
+ for i, rec in enumerate(recommendations):
418
+ st.markdown(f"{i+1}. {rec}")
419
+
420
+ def show_optimization():
421
+ """
422
+ عرض تحسين سلسلة الإمداد والتوقعات
423
+ """
424
+ st.markdown("## تحسين سلسلة الإمداد والتوقعات")
425
+
426
+ # 1. تحسين المخزون
427
+ st.markdown("### تحسين مستويات المخزون")
428
+
429
+ # إنشاء بيانات توضيحية للمخزون
430
+ inventory_data = {
431
+ "المادة": [
432
+ "حديد تسليح", "إسمنت", "خرسانة جاهزة", "طوب", "رمل",
433
+ "خشب", "مواد عازلة", "كابلات كهربائية", "أنابيب", "أصباغ"
434
+ ],
435
+ "المخزون الحالي": [35, 1200, 80, 8000, 120, 45, 200, 450, 320, 85],
436
+ "الحد الأدنى المطلوب": [20, 800, 60, 5000, 100, 30, 150, 300, 250, 50],
437
+ "الحد الأقصى": [50, 2000, 120, 12000, 200, 60, 300, 600, 400, 120],
438
+ "متوسط الاستهلاك اليومي": [2, 60, 10, 400, 8, 3, 12, 25, 15, 5],
439
+ "وقت إعادة الطلب (أيام)": [15, 7, 3, 10, 5, 20, 15, 12, 10, 8]
440
+ }
441
+
442
+ inventory_df = pd.DataFrame(inventory_data)
443
+
444
+ # حساب مؤشرات المخزون
445
+ inventory_df["أيام التغطية المتبقية"] = inventory_df["المخزون الحالي"] / inventory_df["متوسط الاستهلاك اليومي"]
446
+ inventory_df["حالة المخزون"] = np.where(
447
+ inventory_df["المخزون الحالي"] < inventory_df["الحد الأدنى المطلوب"],
448
+ "منخفض",
449
+ np.where(
450
+ inventory_df["المخزون الحالي"] > inventory_df["الحد الأقصى"],
451
+ "مرتفع",
452
+ "مناسب"
453
+ )
454
+ )
455
+
456
+ inventory_df["توصية"] = np.where(
457
+ inventory_df["أيام التغطية المتبقية"] < inventory_df["وقت إعادة الطلب (أيام)"],
458
+ "يجب الطلب الآن",
459
+ "المخزون كافي"
460
+ )
461
+
462
+ # تنسيق العرض
463
+ formatted_inventory = inventory_df.copy()
464
+ formatted_inventory["أيام التغطية المتبقية"] = formatted_inventory["أيام التغطية المتبقية"].round(1)
465
+
466
+ # عرض بيانات المخزون
467
+ st.dataframe(formatted_inventory, use_container_width=True)
468
+
469
+ # تحليل حالة المخزون
470
+ col1, col2 = st.columns(2)
471
+
472
+ with col1:
473
+ # مخطط حالة المخزون
474
+ status_counts = inventory_df["حالة المخزون"].value_counts().reset_index()
475
+ status_counts.columns = ["الحالة", "العدد"]
476
+
477
+ fig1 = px.pie(
478
+ status_counts,
479
+ values="العدد",
480
+ names="الحالة",
481
+ title="توزيع حالة المخزون",
482
+ color_discrete_map={
483
+ "منخفض": "#D32F2F",
484
+ "مناسب": "#43A047",
485
+ "مرتفع": "#FFC107"
486
+ }
487
+ )
488
+
489
+ fig1.update_traces(textposition="inside", textinfo="percent+label")
490
+
491
+ st.plotly_chart(fig1, use_container_width=True)
492
+
493
+ with col2:
494
+ # أيام التغطية للمواد
495
+ st.markdown("### أيام التغطية المتبقية للمخزون")
496
+
497
+ fig2 = px.bar(
498
+ inventory_df.sort_values("أيام التغطية المتبقية"),
499
+ x="المادة",
500
+ y="أيام التغطية المتبقية",
501
+ color="حالة المخزون",
502
+ title="أيام التغطية المتبقية للمخزون",
503
+ color_discrete_map={
504
+ "منخفض": "#D32F2F",
505
+ "مناسب": "#43A047",
506
+ "مرتفع": "#FFC107"
507
+ }
508
+ )
509
+
510
+ # إضافة خط لوقت إعادة الطلب
511
+ for i, row in inventory_df.iterrows():
512
+ fig2.add_shape(
513
+ type="line",
514
+ x0=i-0.4,
515
+ x1=i+0.4,
516
+ y0=row["وقت إعادة الطلب (أيام)"],
517
+ y1=row["وقت إعادة الطلب (أيام)"],
518
+ line=dict(color="red", width=2, dash="dash")
519
+ )
520
+
521
+ st.plotly_chart(fig2, use_container_width=True)
522
+
523
+ # 2. تحليل التوقعات المستقبلية
524
+ st.markdown("### التوقعات المستقبلية للطلب والأسعار")
525
+
526
+ # إنشاء بيانات توضيحية للتوقعات
527
+ months = ["يناير", "فبراير", "مارس", "أبريل", "مايو", "يونيو",
528
+ "يوليو", "أغسطس", "سبتمبر", "أكتوبر", "نوفمبر", "ديسمبر"]
529
+
530
+ forecast_data = {
531
+ "الشهر": months,
532
+ "الطلب المتوقع (طن)": [250, 265,