EGYADMIN commited on
Commit
4e06652
·
verified ·
1 Parent(s): 4d074e6

Update modules/cost_risk_analyzer.py

Browse files
Files changed (1) hide show
  1. modules/cost_risk_analyzer.py +296 -1
modules/cost_risk_analyzer.py CHANGED
@@ -1,4 +1,299 @@
1
- "deviation_percentage": deviation_percentage,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  "risk_level": risk_level,
3
  "impact": "تأثير على هامش الربح وزيادة التكاليف الإجمالية",
4
  "mitigation": self._generate_overrun_mitigation(category, deviation_percentage)
 
1
+ local_content_percentage = (local_content / total_cost * 100) if total_cost > 0 else 0
2
+
3
+ # حساب المحتوى المحلي حسب الفئة
4
+ categories = {}
5
+ for item in items:
6
+ category = item.get("category", "أخرى")
7
+ cost = item.get("cost", 0)
8
+ local_contribution = item.get("local_content_contribution", 0)
9
+ local_amount = cost * local_contribution / 100
10
+
11
+ if category in categories:
12
+ categories[category]["total"] += cost
13
+ categories[category]["local"] += local_amount
14
+ else:
15
+ categories[category] = {
16
+ "total": cost,
17
+ "local": local_amount
18
+ }
19
+
20
+ local_content_by_category = {}
21
+ for category, data in categories.items():
22
+ local_content_by_category[category] = (data["local"] / data["total"] * 100) if data["total"] > 0 else 0
23
+
24
+ # الهدف المرجعي للمحتوى المحلي
25
+ target_local_content = self.reference_data.get("target_local_content", 40)
26
+ local_content_gap = target_local_content - local_content_percentage
27
+
28
+ # إمكانية التحسين
29
+ import_items = [item for item in items if item.get("source_type") == "import"]
30
+ improvement_potential = sum(item.get("cost", 0) for item in import_items) / total_cost * 100 if total_cost > 0 else 0
31
+
32
+ return {
33
+ "local_content_percentage": local_content_percentage,
34
+ "local_content_by_category": local_content_by_category,
35
+ "target_local_content": target_local_content,
36
+ "local_content_gap": local_content_gap,
37
+ "improvement_potential": improvement_potential
38
+ }
39
+
40
+ def _identify_procurement_improvements(self, procurement_costs: Dict[str, Any],
41
+ suppliers_analysis: Dict[str, Any],
42
+ local_content_analysis: Dict[str, Any]) -> List[str]:
43
+ """
44
+ تحديد فرص تحسين المشتريات
45
+
46
+ المعاملات:
47
+ ----------
48
+ procurement_costs : Dict[str, Any]
49
+ تحليل تكاليف المشتريات
50
+ suppliers_analysis : Dict[str, Any]
51
+ تحليل الموردين
52
+ local_content_analysis : Dict[str, Any]
53
+ تحليل المحتوى المحلي
54
+
55
+ المخرجات:
56
+ --------
57
+ List[str]
58
+ فرص تحسين المشتريات
59
+ """
60
+ improvements = []
61
+
62
+ # تحسين تكاليف المشتريات
63
+ if procurement_costs["cost_efficiency"] < 0:
64
+ improvements.append("تحسين كفاءة تكاليف المشتريات من خلال إعادة التفاوض مع الموردين وتوحيد الطلبات.")
65
+
66
+ # تحسين تنوع الموردين
67
+ if suppliers_analysis["supplier_diversity"] < 30:
68
+ improvements.append("زيادة تنوع الموردين لتقليل مخاطر سلسلة الإمداد وتحسين المرونة.")
69
+
70
+ # تحسين نسبة الموردين المحليين
71
+ if suppliers_analysis["local_percentage"] < 50:
72
+ improvements.append("زيادة نسبة الموردين المحليين لتعزيز المحتوى المحلي وتقليل تكاليف النقل.")
73
+
74
+ # تحسين المحتوى المحلي
75
+ if local_content_analysis["local_content_gap"] > 0:
76
+ improvements.append(f"سد فجوة المحتوى المحلي البالغة {local_content_analysis['local_content_gap']:.1f}% للوصول إلى الهدف.")
77
+
78
+ # تحسين تركيز الموردين
79
+ high_concentration = [supplier for supplier, percentage in suppliers_analysis["supplier_concentration"].items() if percentage > 30]
80
+ if high_concentration:
81
+ improvements.append(f"تقليل الاعتماد على الموردين الرئيسيين ({', '.join(high_concentration)}) لتقليل المخاطر.")
82
+
83
+ # إضافة توصيات عامة
84
+ improvements.extend([
85
+ "تطبيق نظام تقييم الموردين وتحفيز الأداء المتميز.",
86
+ "تحسين عملية التخطيط للمشتريات لتقليل الطلبات العاجلة والتكاليف الإضافية.",
87
+ "تطوير قاعدة بيانات للموردين وتعزيز الشفافية في عملية اختيار الموردين.",
88
+ "الاستفادة من التكنولوجيا لأتمتة عمليات المشتريات وتحسين الكفاءة."
89
+ ])
90
+
91
+ return improvements
92
+
93
+ def _generate_procurement_summary(self, procurement_costs: Dict[str, Any],
94
+ suppliers_analysis: Dict[str, Any],
95
+ local_content_analysis: Dict[str, Any]) -> str:
96
+ """
97
+ إعداد ملخص لتقرير المشتريات
98
+
99
+ المعاملات:
100
+ ----------
101
+ procurement_costs : Dict[str, Any]
102
+ تحليل تكاليف المشتريات
103
+ suppliers_analysis : Dict[str, Any]
104
+ تحليل الموردين
105
+ local_content_analysis : Dict[str, Any]
106
+ تحليل المحتوى المحلي
107
+
108
+ المخرجات:
109
+ --------
110
+ str
111
+ ملخص تقرير المشتريات
112
+ """
113
+ summary = "ملخص تقرير المشتريات:\n\n"
114
+
115
+ # ملخص التكاليف
116
+ summary += "1. تكاليف المشتريات:\n"
117
+ summary += f" - إجمالي تكاليف المشتريات: {procurement_costs['total_procurement_cost']:,.0f} ريال\n"
118
+ summary += f" - نسبة المشتريات المحلية: {procurement_costs['local_percentage']:.1f}%\n"
119
+ if procurement_costs['cost_efficiency'] > 0:
120
+ summary += f" - كفاءة التكلفة: {procurement_costs['cost_efficiency']:.1f}% (وفر عن المتوسط)\n"
121
+ else:
122
+ summary += f" - كفاءة التكلفة: {-procurement_costs['cost_efficiency']:.1f}% (تجاوز عن المتوسط)\n"
123
+
124
+ # ملخص الموردين
125
+ summary += "\n2. تحليل الموردين:\n"
126
+ summary += f" - عدد الموردين: {suppliers_analysis['total_suppliers']}\n"
127
+ summary += f" - نسبة الموردين المحليين: {suppliers_analysis['local_percentage']:.1f}%\n"
128
+ summary += f" - تنوع الموردين: {suppliers_analysis['supplier_diversity']:.1f}%\n"
129
+
130
+ # ملخص المحتوى المحلي
131
+ summary += "\n3. تحليل المحتوى المحلي:\n"
132
+ summary += f" - نسبة المحتوى المحلي الحالية: {local_content_analysis['local_content_percentage']:.1f}%\n"
133
+ summary += f" - نسبة المحتوى المحلي المستهدفة: {local_content_analysis['target_local_content']:.1f}%\n"
134
+ summary += f" - فجوة المحتوى المحلي: {local_content_analysis['local_content_gap']:.1f}%\n"
135
+ summary += f" - إمكانية تحسين المحتوى المحلي: {local_content_analysis['improvement_potential']:.1f}%\n"
136
+
137
+ return summary
138
+
139
+ def _generate_default_mitigation(self, risk: Dict[str, Any]) -> str:
140
+ """
141
+ إنشاء استراتيجية تخفيف افتراضية للمخاطرة
142
+
143
+ المعاملات:
144
+ ----------
145
+ risk : Dict[str, Any]
146
+ المخاطرة
147
+
148
+ المخرجات:
149
+ --------
150
+ str
151
+ استراتيجية التخفيف
152
+ """
153
+ # استخراج نوع المخاطرة
154
+ risk_name = risk.get("name", "").lower()
155
+ risk_type = risk.get("type", "").lower()
156
+
157
+ if "أسعار" in risk_name or "تكلفة" in risk_name:
158
+ return "تأمين عقود توريد بأسعار ثابتة وإعداد ميزانية احتياطية للتغييرات المحتملة في الأسعار."
159
+ elif "دفعات" in risk_name or "تمويل" in risk_name or "سيولة" in risk_name:
160
+ return "وضع شروط دفع واضحة في العقد وتأمين تسهيلات ائتمانية احتياطية وإعداد خطة للتدفق النقدي."
161
+ elif "عملات" in risk_name or "صرف" in risk_name:
162
+ return "استخدام آليات التحوط والتعاقد بالعملة المحلية حيثما أمكن."
163
+ elif risk_type == "financial":
164
+ return "إعداد خطة مالية بديلة وتخصيص احتياطي طوارئ مالي بنسبة مناسبة من قيمة المشروع."
165
+ else:
166
+ return "تحديد وتقييم المخاطر بشكل دوري ووضع خطط بديلة للتعامل معها."
167
+
168
+ def _generate_overrun_mitigation(self, category: str, deviation_percentage: float) -> str:
169
+ """
170
+ إنشاء استراتيجية تخفيف لتجاوز التكاليف
171
+
172
+ المعاملات:
173
+ ----------
174
+ category : str
175
+ فئة التكلفة
176
+ deviation_percentage : float
177
+ نسبة التجاوز
178
+
179
+ المخرجات:
180
+ --------
181
+ str
182
+ استراتيجية التخفيف
183
+ """
184
+ category = category.lower()
185
+
186
+ if "مواد" in category:
187
+ return "البحث عن موردين بديلين وإعادة التفاوض على الأسعار وتحسين إدارة المخزون."
188
+ elif "عمالة" in category:
189
+ return "تحسين إنتاجية العمالة وإع��دة توزيع المهام وتقييم إمكانية الاستعانة بمقاولي الباطن."
190
+ elif "معدات" in category:
191
+ return "تحسين استغلال المعدات ومراجعة خيارات الشراء مقابل الإيجار وتقليل أوقات التوقف."
192
+ elif "مقاولين" in category or "باطن" in category:
193
+ return "مراجعة عقود مقاولي الباطن وإعادة التفاوض على الأسعار وتحسين إدارة العقود."
194
+ elif "إدارة" in category or "غير مباشرة" in category:
195
+ return "ترشيد المصاريف الإدارية وتقليل التكاليف غير المباشرة ومراجعة الهيكل التنظيمي."
196
+ else:
197
+ return "مراجعة بنود التكلفة وتحديد فرص التوفير وتطبيق إجراءات ضبط التكاليف."
198
+
199
+ def _generate_deviation_recommendation(self, category: str, expected_deviation: float) -> str:
200
+ """
201
+ إنشاء توصية للتعامل مع الانحراف المتوقع
202
+
203
+ المعاملات:
204
+ ----------
205
+ category : str
206
+ فئة التكلفة
207
+ expected_deviation : float
208
+ الانحراف المتوقع
209
+
210
+ المخرجات:
211
+ --------
212
+ str
213
+ التوصية
214
+ """
215
+ category = category.lower()
216
+
217
+ if expected_deviation > 0:
218
+ # توصيات لتجاوز التكاليف
219
+ if "مواد" in category:
220
+ return "مراجعة بدائل المواد وتوحيد المشتريات للاستفادة من وفورات الحجم وتأمين العقود مسبقًا."
221
+ elif "عمالة" in category:
222
+ return "تحسين جدولة العمالة وزيادة الإنتاجية وتقييم إمكانية الاستعانة بمقاولي الباطن."
223
+ elif "معدات" in category:
224
+ return "تحسين إدارة المعدات وزيادة كفاءة الاستخدام ومراجعة خيارات الإيجار بدلاً من الشراء."
225
+ else:
226
+ return "تنفيذ إجراءات ضبط التكاليف ومراقبة الإنفاق بشكل دوري ومراجعة الميزانية."
227
+ else:
228
+ # توصيات للوفر في التكاليف
229
+ if abs(expected_deviation) > 10:
230
+ return "مراجعة تقديرات التكلفة لضمان عدم المبالغة وإعادة توزيع الموارد للأنشطة الحرجة."
231
+ else:
232
+ return "الاستفادة من الوفر المتوقع في تعزيز جودة المشروع أو تغطية تجاوزات محتملة في بنود أخرى."
233
+
234
+ def _load_reference_data(self) -> Dict[str, Any]:
235
+ """
236
+ تحميل البيانات المرجعية
237
+
238
+ المخرجات:
239
+ --------
240
+ Dict[str, Any]
241
+ البيانات المرجعية
242
+ """
243
+ try:
244
+ file_path = 'data/templates/cost_reference_data.json'
245
+ if os.path.exists(file_path):
246
+ with open(file_path, 'r', encoding='utf-8') as f:
247
+ return json.load(f)
248
+ else:
249
+ logger.warning(f"ملف البيانات المرجعية غير موجود: {file_path}")
250
+ # إنشاء بيانات مرجعية افتراضية
251
+ return self._create_default_reference_data()
252
+ except Exception as e:
253
+ logger.error(f"فشل في تحميل البيانات المرجعية: {str(e)}")
254
+ return self._create_default_reference_data()
255
+
256
+ def _create_default_reference_data(self) -> Dict[str, Any]:
257
+ """
258
+ إنشاء بيانات مرجعية افتراضية
259
+
260
+ المخرجات:
261
+ --------
262
+ Dict[str, Any]
263
+ البيانات المرجعية الافتراضية
264
+ """
265
+ return {
266
+ "avg_direct_percentage": 75.0,
267
+ "avg_indirect_percentage": 25.0,
268
+ "avg_profit_margin": 15.0,
269
+ "avg_cost_revenue_ratio": 85.0,
270
+ "avg_roi": 20.0,
271
+ "avg_procurement_cost": 1000000,
272
+ "target_local_content": 40.0,
273
+ "sector_benchmarks": {
274
+ "construction": {
275
+ "profit_margin": 12.0,
276
+ "cost_revenue_ratio": 88.0,
277
+ "direct_percentage": 80.0
278
+ },
279
+ "infrastructure": {
280
+ "profit_margin": 10.0,
281
+ "cost_revenue_ratio": 90.0,
282
+ "direct_percentage": 85.0
283
+ },
284
+ "services": {
285
+ "profit_margin": 20.0,
286
+ "cost_revenue_ratio": 80.0,
287
+ "direct_percentage": 65.0
288
+ }
289
+ },
290
+ "cost_overrun_statistics": {
291
+ "avg_overrun_percentage": 15.0,
292
+ "materials_overrun": 12.0,
293
+ "labor_overrun": 18.0,
294
+ "equipment_overrun": 10.0
295
+ }
296
+ } "deviation_percentage": deviation_percentage,
297
  "risk_level": risk_level,
298
  "impact": "تأثير على هامش الربح وزيادة التكاليف الإجمالية",
299
  "mitigation": self._generate_overrun_mitigation(category, deviation_percentage)