Spaces:
Paused
Paused
Update modules/pricing/pricing_app.py
Browse files- modules/pricing/pricing_app.py +165 -43
modules/pricing/pricing_app.py
CHANGED
@@ -1105,54 +1105,28 @@ class PricingApp:
|
|
1105 |
import openai
|
1106 |
import os
|
1107 |
|
1108 |
-
# تهيئة عميل OpenAI
|
1109 |
api_key = os.environ.get("ai")
|
1110 |
-
|
1111 |
-
# للإصدارات الحديثة من المكتبة (1.0.0 وما فوق)
|
1112 |
-
client = openai.OpenAI(api_key=api_key)
|
1113 |
-
except TypeError:
|
1114 |
-
# للإصدارات القديمة من المكتبة (أقل من 1.0.0)
|
1115 |
-
openai.api_key = api_key
|
1116 |
-
client = openai
|
1117 |
|
1118 |
items_df = items.copy()
|
1119 |
prompt = f"""قم بتحليل الجدول التالي للبنود في مشروع إنشاء، وقدم توصية ذكية لتحسين التسعير وضمان التوازن المالي. الجدول يحتوي على البنود، الكميات، الأسعار، والإجماليات:\n\n{items_df.to_string(index=False)}\n\nالتوصية:\n"""
|
1120 |
|
1121 |
try:
|
1122 |
with st.spinner("جاري توليد التوصية..."):
|
1123 |
-
|
1124 |
-
|
1125 |
-
|
1126 |
-
|
1127 |
-
|
1128 |
-
|
1129 |
-
|
1130 |
-
|
1131 |
-
|
1132 |
-
|
1133 |
-
)
|
1134 |
-
except Exception as e:
|
1135 |
-
if "unexpected keyword argument" in str(e):
|
1136 |
-
# للإصدارات القديمة من المكتبة (أقل من 1.0.0)
|
1137 |
-
response = client.ChatCompletion.create(
|
1138 |
-
model="gpt-4",
|
1139 |
-
messages=[
|
1140 |
-
{"role": "system", "content": "أنت خبير في تسعير مشاريع البناء والبنية التحتية."},
|
1141 |
-
{"role": "user", "content": prompt}
|
1142 |
-
],
|
1143 |
-
temperature=0.4,
|
1144 |
-
max_tokens=500
|
1145 |
-
)
|
1146 |
-
else:
|
1147 |
-
raise e
|
1148 |
|
1149 |
-
# استخراج محتوى الرسالة
|
1150 |
-
|
1151 |
-
# للإصدارات الحديثة من المكتبة (1.0.0 وما فوق)
|
1152 |
-
recommendation = response.choices[0].message.content
|
1153 |
-
except AttributeError:
|
1154 |
-
# للإصدارات القديمة من المكتبة (أقل من 1.0.0)
|
1155 |
-
recommendation = response.choices[0].text
|
1156 |
|
1157 |
st.success("تم توليد التوصية بنجاح!")
|
1158 |
st.markdown("#### التوصية الذكية:")
|
@@ -3325,15 +3299,61 @@ class PricingApp:
|
|
3325 |
# حساب التكلفة الإجمالية
|
3326 |
st.session_state.local_content_products['التكلفة_الإجمالية'] = st.session_state.local_content_products['الكمية'] * st.session_state.local_content_products['سعر_الوحدة']
|
3327 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3328 |
# عرض جدول البنود مع إمكانية التعديل
|
|
|
3329 |
edited_products = st.data_editor(
|
3330 |
st.session_state.local_content_products,
|
3331 |
use_container_width=True,
|
3332 |
hide_index=True,
|
3333 |
-
|
3334 |
)
|
3335 |
st.session_state.local_content_products = edited_products
|
3336 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3337 |
# عرض ملخص المنتجات
|
3338 |
total_products_cost = edited_products['التكلفة_الإجمالية'].sum()
|
3339 |
avg_local_content = (edited_products['التكلفة_الإجمالية'] * edited_products['نسبة_المحتوى_المحلي']).sum() / total_products_cost if total_products_cost > 0 else 0
|
@@ -3365,15 +3385,52 @@ class PricingApp:
|
|
3365 |
'نسبة_المحتوى_المحلي': [0.90, 0.85, 0.90, 0.95, 0.95]
|
3366 |
})
|
3367 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3368 |
# عرض جدول الخدمات مع إمكانية التعديل
|
|
|
3369 |
edited_services = st.data_editor(
|
3370 |
st.session_state.local_content_services,
|
3371 |
use_container_width=True,
|
3372 |
hide_index=True,
|
3373 |
-
|
3374 |
)
|
3375 |
st.session_state.local_content_services = edited_services
|
3376 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3377 |
# عرض ملخص الخدمات
|
3378 |
total_services_cost = edited_services['التكلفة'].sum()
|
3379 |
avg_local_content = (edited_services['التكلفة'] * edited_services['نسبة_المحتوى_المحلي']).sum() / total_services_cost if total_services_cost > 0 else 0
|
@@ -3410,18 +3467,67 @@ class PricingApp:
|
|
3410 |
# حساب التكلفة الإجمالية
|
3411 |
st.session_state.local_content_labor['التكلفة_الإجمالية'] = st.session_state.local_content_labor['العدد'] * st.session_state.local_content_labor['الراتب_الشهري'] * st.session_state.local_content_labor['المدة_بالأشهر']
|
3412 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3413 |
# عرض جدول القوى العاملة مع إمكانية التعديل
|
|
|
3414 |
edited_labor = st.data_editor(
|
3415 |
st.session_state.local_content_labor,
|
3416 |
use_container_width=True,
|
3417 |
hide_index=True,
|
3418 |
-
|
3419 |
)
|
3420 |
|
3421 |
# إعادة حساب التكلفة الإجمالية بعد التعديل
|
3422 |
edited_labor['التكلفة_الإجمالية'] = edited_labor['العدد'] * edited_labor['الراتب_الشهري'] * edited_labor['المدة_بالأشهر']
|
3423 |
st.session_state.local_content_labor = edited_labor
|
3424 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3425 |
# عرض ملخص القوى العاملة
|
3426 |
total_labor_cost = edited_labor['التكلفة_الإجمالية'].sum()
|
3427 |
avg_local_content = (edited_labor['التكلفة_الإجمالية'] * edited_labor['نسبة_المحتوى_المحلي']).sum() / total_labor_cost if total_labor_cost > 0 else 0
|
@@ -3685,6 +3791,22 @@ class PricingApp:
|
|
3685 |
original_cost = result['التكلفة_الإجمالية']
|
3686 |
final_cost = result['السعر_المعدل']['إجمالي']
|
3687 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3688 |
factors = {
|
3689 |
"معامل الموقع": result['عوامل_التعديل']['location_factor'],
|
3690 |
"معامل الوقت": result['عوامل_التعديل']['time_factor'],
|
|
|
1105 |
import openai
|
1106 |
import os
|
1107 |
|
1108 |
+
# تهيئة عميل OpenAI - استخدام واجهة الإصدار الجديد فقط (1.0.0 وما فوق)
|
1109 |
api_key = os.environ.get("ai")
|
1110 |
+
client = openai.OpenAI(api_key=api_key)
|
|
|
|
|
|
|
|
|
|
|
|
|
1111 |
|
1112 |
items_df = items.copy()
|
1113 |
prompt = f"""قم بتحليل الجدول التالي للبنود في مشروع إنشاء، وقدم توصية ذكية لتحسين التسعير وضمان التوازن المالي. الجدول يحتوي على البنود، الكميات، الأسعار، والإجماليات:\n\n{items_df.to_string(index=False)}\n\nالتوصية:\n"""
|
1114 |
|
1115 |
try:
|
1116 |
with st.spinner("جاري توليد التوصية..."):
|
1117 |
+
# استخدام واجهة OpenAI الجديدة
|
1118 |
+
response = client.chat.completions.create(
|
1119 |
+
model="gpt-4o", # استخدام أحدث نموذج من OpenAI GPT-4o
|
1120 |
+
messages=[
|
1121 |
+
{"role": "system", "content": "أنت خبير في تسعير مشاريع البناء والبنية التحتية."},
|
1122 |
+
{"role": "user", "content": prompt}
|
1123 |
+
],
|
1124 |
+
temperature=0.4,
|
1125 |
+
max_tokens=500
|
1126 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1127 |
|
1128 |
+
# استخراج محتوى الرسالة من واجهة OpenAI الجديدة
|
1129 |
+
recommendation = response.choices[0].message.content
|
|
|
|
|
|
|
|
|
|
|
1130 |
|
1131 |
st.success("تم توليد التوصية بنجاح!")
|
1132 |
st.markdown("#### التوصية الذكية:")
|
|
|
3299 |
# حساب التكلفة الإجمالية
|
3300 |
st.session_state.local_content_products['التكلفة_الإجمالية'] = st.session_state.local_content_products['الكمية'] * st.session_state.local_content_products['سعر_الوحدة']
|
3301 |
|
3302 |
+
# نموذج إضافة منتج جديد
|
3303 |
+
st.markdown("#### إضافة منتج جديد")
|
3304 |
+
col1, col2, col3, col4 = st.columns(4)
|
3305 |
+
|
3306 |
+
with col1:
|
3307 |
+
new_product_name = st.text_input("اسم المنتج", key="new_product_name", value="")
|
3308 |
+
with col2:
|
3309 |
+
new_product_quantity = st.number_input("الكمية", key="new_product_quantity", min_value=0, value=0)
|
3310 |
+
with col3:
|
3311 |
+
new_product_price = st.number_input("سعر الوحدة", key="new_product_price", min_value=0, value=0)
|
3312 |
+
with col4:
|
3313 |
+
new_product_local_content = st.slider("نسبة المحتوى المحلي", key="new_product_local_content", min_value=0.0, max_value=1.0, value=0.8, step=0.01, format="%.2f")
|
3314 |
+
|
3315 |
+
if st.button("إضافة المنتج"):
|
3316 |
+
if new_product_name:
|
3317 |
+
# حساب التكلفة الإجمالية
|
3318 |
+
total_cost = new_product_quantity * new_product_price
|
3319 |
+
|
3320 |
+
# إضافة منتج جديد للجدول
|
3321 |
+
new_product = pd.DataFrame({
|
3322 |
+
'المنتج': [new_product_name],
|
3323 |
+
'الكمية': [new_product_quantity],
|
3324 |
+
'سعر_الوحدة': [new_product_price],
|
3325 |
+
'التكلفة_الإجمالية': [total_cost],
|
3326 |
+
'نسبة_المحتوى_المحلي': [new_product_local_content]
|
3327 |
+
})
|
3328 |
+
|
3329 |
+
# إضافة المنتج الجديد للجدول الحالي
|
3330 |
+
st.session_state.local_content_products = pd.concat([st.session_state.local_content_products, new_product], ignore_index=True)
|
3331 |
+
st.success(f"تم إضافة المنتج {new_product_name} بنجاح!")
|
3332 |
+
else:
|
3333 |
+
st.warning("يرجى إدخال اسم المنتج")
|
3334 |
+
|
3335 |
# عرض جدول البنود مع إمكانية التعديل
|
3336 |
+
st.markdown("#### جدول المنتجات")
|
3337 |
edited_products = st.data_editor(
|
3338 |
st.session_state.local_content_products,
|
3339 |
use_container_width=True,
|
3340 |
hide_index=True,
|
3341 |
+
key="products_editor"
|
3342 |
)
|
3343 |
st.session_state.local_content_products = edited_products
|
3344 |
|
3345 |
+
# زر لحذف المنتجات المحددة
|
3346 |
+
if st.button("حذف المنتجات المحددة"):
|
3347 |
+
st.session_state.local_content_products = pd.DataFrame({
|
3348 |
+
'المنتج': [],
|
3349 |
+
'الكمية': [],
|
3350 |
+
'سعر_الوحدة': [],
|
3351 |
+
'التكلفة_الإجمالية': [],
|
3352 |
+
'نسبة_المحتوى_المحلي': []
|
3353 |
+
})
|
3354 |
+
st.success("تم حذف جميع المنتجات!")
|
3355 |
+
st.rerun()
|
3356 |
+
|
3357 |
# عرض ملخص المنتجات
|
3358 |
total_products_cost = edited_products['التكلفة_الإجمالية'].sum()
|
3359 |
avg_local_content = (edited_products['التكلفة_الإجمالية'] * edited_products['نسبة_المحتوى_المحلي']).sum() / total_products_cost if total_products_cost > 0 else 0
|
|
|
3385 |
'نسبة_المحتوى_المحلي': [0.90, 0.85, 0.90, 0.95, 0.95]
|
3386 |
})
|
3387 |
|
3388 |
+
# نموذج إضافة خدمة جديدة
|
3389 |
+
st.markdown("#### إضافة خدمة جديدة")
|
3390 |
+
col1, col2, col3 = st.columns(3)
|
3391 |
+
|
3392 |
+
with col1:
|
3393 |
+
new_service_name = st.text_input("اسم الخدمة", key="new_service_name", value="")
|
3394 |
+
with col2:
|
3395 |
+
new_service_cost = st.number_input("التكلفة", key="new_service_cost", min_value=0, value=0)
|
3396 |
+
with col3:
|
3397 |
+
new_service_local_content = st.slider("نسبة المحتوى المحلي", key="new_service_local_content", min_value=0.0, max_value=1.0, value=0.8, step=0.01, format="%.2f")
|
3398 |
+
|
3399 |
+
if st.button("إضافة الخدمة"):
|
3400 |
+
if new_service_name:
|
3401 |
+
# إضافة خدمة جديدة للجدول
|
3402 |
+
new_service = pd.DataFrame({
|
3403 |
+
'الخدمة': [new_service_name],
|
3404 |
+
'التكلفة': [new_service_cost],
|
3405 |
+
'نسبة_المحتوى_المحلي': [new_service_local_content]
|
3406 |
+
})
|
3407 |
+
|
3408 |
+
# إضافة الخدمة الجديدة للجدول الحالي
|
3409 |
+
st.session_state.local_content_services = pd.concat([st.session_state.local_content_services, new_service], ignore_index=True)
|
3410 |
+
st.success(f"تم إضافة الخدمة {new_service_name} بنجاح!")
|
3411 |
+
else:
|
3412 |
+
st.warning("يرجى إدخال اسم الخدمة")
|
3413 |
+
|
3414 |
# عرض جدول الخدمات مع إمكانية التعديل
|
3415 |
+
st.markdown("#### جدول الخدمات")
|
3416 |
edited_services = st.data_editor(
|
3417 |
st.session_state.local_content_services,
|
3418 |
use_container_width=True,
|
3419 |
hide_index=True,
|
3420 |
+
key="services_editor"
|
3421 |
)
|
3422 |
st.session_state.local_content_services = edited_services
|
3423 |
|
3424 |
+
# زر لحذف الخدمات المحددة
|
3425 |
+
if st.button("حذف الخدمات المحددة"):
|
3426 |
+
st.session_state.local_content_services = pd.DataFrame({
|
3427 |
+
'الخدمة': [],
|
3428 |
+
'التكلفة': [],
|
3429 |
+
'نسبة_المحتوى_المحلي': []
|
3430 |
+
})
|
3431 |
+
st.success("تم حذف جميع الخدمات!")
|
3432 |
+
st.rerun()
|
3433 |
+
|
3434 |
# عرض ملخص الخدمات
|
3435 |
total_services_cost = edited_services['التكلفة'].sum()
|
3436 |
avg_local_content = (edited_services['التكلفة'] * edited_services['نسبة_المحتوى_المحلي']).sum() / total_services_cost if total_services_cost > 0 else 0
|
|
|
3467 |
# حساب التكلفة الإجمالية
|
3468 |
st.session_state.local_content_labor['التكلفة_الإجمالية'] = st.session_state.local_content_labor['العدد'] * st.session_state.local_content_labor['الراتب_الشهري'] * st.session_state.local_content_labor['المدة_بالأشهر']
|
3469 |
|
3470 |
+
# نموذج إضافة فئة عمالة جديدة
|
3471 |
+
st.markdown("#### إضافة فئة عمالة جديدة")
|
3472 |
+
col1, col2 = st.columns(2)
|
3473 |
+
|
3474 |
+
with col1:
|
3475 |
+
new_labor_category = st.text_input("فئة العمالة", key="new_labor_category", value="")
|
3476 |
+
new_labor_count = st.number_input("العدد", key="new_labor_count", min_value=0, value=0)
|
3477 |
+
|
3478 |
+
with col2:
|
3479 |
+
new_labor_salary = st.number_input("الراتب الشهري", key="new_labor_salary", min_value=0, value=0)
|
3480 |
+
new_labor_months = st.number_input("المدة بالأشهر", key="new_labor_months", min_value=1, value=12)
|
3481 |
+
|
3482 |
+
new_labor_local_content = st.slider("نسبة المحتوى المحلي", key="new_labor_local_content", min_value=0.0, max_value=1.0, value=0.8, step=0.01, format="%.2f")
|
3483 |
+
|
3484 |
+
if st.button("إضافة فئة العمالة"):
|
3485 |
+
if new_labor_category:
|
3486 |
+
# حساب التكلفة الإجمالية
|
3487 |
+
total_cost = new_labor_count * new_labor_salary * new_labor_months
|
3488 |
+
|
3489 |
+
# إضافة فئة عمالة جديدة للجدول
|
3490 |
+
new_labor = pd.DataFrame({
|
3491 |
+
'فئة_العمالة': [new_labor_category],
|
3492 |
+
'العدد': [new_labor_count],
|
3493 |
+
'الراتب_الشهري': [new_labor_salary],
|
3494 |
+
'المدة_بالأشهر': [new_labor_months],
|
3495 |
+
'نسبة_المحتوى_المحلي': [new_labor_local_content],
|
3496 |
+
'التكلفة_الإجمالية': [total_cost]
|
3497 |
+
})
|
3498 |
+
|
3499 |
+
# إضافة فئة العمالة الجديدة للجدول الحالي
|
3500 |
+
st.session_state.local_content_labor = pd.concat([st.session_state.local_content_labor, new_labor], ignore_index=True)
|
3501 |
+
st.success(f"تم إضافة فئة العمالة {new_labor_category} بنجاح!")
|
3502 |
+
else:
|
3503 |
+
st.warning("يرجى إدخال اسم فئة العمالة")
|
3504 |
+
|
3505 |
# عرض جدول القوى العاملة مع إمكانية التعديل
|
3506 |
+
st.markdown("#### جدول القوى العاملة")
|
3507 |
edited_labor = st.data_editor(
|
3508 |
st.session_state.local_content_labor,
|
3509 |
use_container_width=True,
|
3510 |
hide_index=True,
|
3511 |
+
key="labor_editor"
|
3512 |
)
|
3513 |
|
3514 |
# إعادة حساب التكلفة الإجمالية بعد التعديل
|
3515 |
edited_labor['التكلفة_الإجمالية'] = edited_labor['العدد'] * edited_labor['الراتب_الشهري'] * edited_labor['المدة_بالأشهر']
|
3516 |
st.session_state.local_content_labor = edited_labor
|
3517 |
|
3518 |
+
# زر لحذف فئات العمالة المحددة
|
3519 |
+
if st.button("حذف فئات العمالة المحددة"):
|
3520 |
+
st.session_state.local_content_labor = pd.DataFrame({
|
3521 |
+
'فئة_العمالة': [],
|
3522 |
+
'العدد': [],
|
3523 |
+
'الراتب_الشهري': [],
|
3524 |
+
'المدة_بالأشهر': [],
|
3525 |
+
'نسبة_المحتوى_المحلي': [],
|
3526 |
+
'التكلفة_الإجمالية': []
|
3527 |
+
})
|
3528 |
+
st.success("تم حذف جميع فئات العمالة!")
|
3529 |
+
st.rerun()
|
3530 |
+
|
3531 |
# عرض ملخص القوى العاملة
|
3532 |
total_labor_cost = edited_labor['التكلفة_الإجمالية'].sum()
|
3533 |
avg_local_content = (edited_labor['التكلفة_الإجمالية'] * edited_labor['نسبة_المحتوى_المحلي']).sum() / total_labor_cost if total_labor_cost > 0 else 0
|
|
|
3791 |
original_cost = result['التكلفة_الإجمالية']
|
3792 |
final_cost = result['السعر_المعدل']['إجمالي']
|
3793 |
|
3794 |
+
# التحقق من وجود العوامل، وإضافتها بقيم افتراضية إذا كانت غير موجودة
|
3795 |
+
if 'عوامل_التعديل' not in result:
|
3796 |
+
result['عوامل_التعديل'] = {}
|
3797 |
+
|
3798 |
+
# إضافة المفاتيح الناقصة بقيم افتراضية
|
3799 |
+
default_factors = {
|
3800 |
+
'location_factor': 1.0,
|
3801 |
+
'time_factor': 1.0,
|
3802 |
+
'risk_factor': 1.0,
|
3803 |
+
'market_factor': 1.0
|
3804 |
+
}
|
3805 |
+
|
3806 |
+
for key, default_value in default_factors.items():
|
3807 |
+
if key not in result['عوامل_التعديل']:
|
3808 |
+
result['عوامل_التعديل'][key] = default_value
|
3809 |
+
|
3810 |
factors = {
|
3811 |
"معامل الموقع": result['عوامل_التعديل']['location_factor'],
|
3812 |
"معامل الوقت": result['عوامل_التعديل']['time_factor'],
|