Wahbi-AI / modules /pricing /pricing_app.py
EGYADMIN's picture
Upload 70 files
d9e7bdd verified
from pathlib import Path
import streamlit as st
import pandas as pd
from datetime import datetime
from pricing_system.modules.analysis import smart_price_analysis as analysis_utils
from pricing_system.modules.catalogs import materials_catalog, equipment_catalog
from pricing_system.modules.indirect_support import overheads
from pricing_system.modules.pricing_strategies import balanced_pricing, profit_oriented
class PricingApp:
"""وحدة التسعير"""
def __init__(self):
"""تهيئة وحدة التسعير"""
if 'project_data' not in st.session_state:
st.session_state.project_data = {}
if 'bill_of_quantities' not in st.session_state:
st.session_state.bill_of_quantities = []
# Maintain existing session state for indirect costs and risks if available.
if 'indirect_costs' not in st.session_state:
st.session_state.indirect_costs = {
'overhead': 0.10, # نسبة المصاريف العمومية والإدارية
'profit': 0.15, # نسبة الربح
'contingency': 0.05, # نسبة الطوارئ
'bonds': 0.02, # نسبة الضمانات
'insurance': 0.03 # نسبة التأمين
}
if 'risks' not in st.session_state:
st.session_state.risks = []
def run(self):
"""تشغيل وحدة التسعير"""
st.title("وحدة التسعير")
# اختيار المشروع
self._select_project()
tabs = st.tabs([
"جدول الكميات",
"تحليل التكاليف",
"سيناريوهات التسعير",
"المحتوى المحلي"
])
with tabs[0]:
self._render_bill_of_quantities_tab()
with tabs[1]:
self._render_cost_analysis_tab()
with tabs[2]:
self._render_pricing_scenarios_tab()
with tabs[3]:
self._render_local_content_tab()
def _select_project(self):
"""اختيار المشروع"""
st.sidebar.markdown("### اختيار المشروع")
# جلب المشاريع من قاعدة البيانات
projects = self._get_projects_from_db()
if projects:
project_names = [p['name'] for p in projects]
selected_project = st.sidebar.selectbox(
"اختر المشروع",
project_names
)
# تحديث بيانات المشروع المحدد
project = next((p for p in projects if p['name'] == selected_project), None)
if project:
st.session_state.current_project = project
st.session_state.bill_of_quantities = project.get('boq_items', [])
else:
st.sidebar.warning("لا توجد مشاريع متاحة")
def _get_projects_from_db(self):
"""جلب المشاريع من قاعدة البيانات"""
# هنا يتم جلب المشاريع من قاعدة البيانات
# هذه بيانات تجريبية للتوضيح
return [
{
'id': 1,
'name': 'مشروع تطوير الطريق',
'client': 'وزارة النقل',
'boq_items': [
{
'code': 'A-001',
'description': 'أعمال الحفر',
'unit': 'م3',
'quantity': 1000,
'unit_price': 50,
'total_price': 50000
}
]
}
]
def _render_bill_of_quantities_tab(self):
"""عرض تبويب جدول الكميات"""
st.markdown("### جدول الكميات")
# عرض البنود الحالية
if st.session_state.bill_of_quantities:
df = pd.DataFrame(st.session_state.bill_of_quantities)
st.dataframe(df, use_container_width=True)
# إضافة بند جديد
st.markdown("### إضافة بند جديد")
col1, col2 = st.columns(2)
with col1:
code = st.text_input("كود البند")
description = st.text_area("وصف البند")
with col2:
unit = st.selectbox("الوحدة", ["م3", "م2", "متر طولي", "عدد"])
quantity = st.number_input("الكمية", min_value=0.0)
unit_price = st.number_input("سعر الوحدة", min_value=0.0)
if st.button("إضافة البند"):
if code and description and quantity > 0 and unit_price > 0:
new_item = {
'code': code,
'description': description,
'unit': unit,
'quantity': quantity,
'unit_price': unit_price,
'total_price': quantity * unit_price
}
st.session_state.bill_of_quantities.append(new_item)
st.success("تم إضافة البند بنجاح")
st.rerun()
def _render_cost_analysis_tab(self):
st.markdown("### تحليل التكاليف")
if len(st.session_state.bill_of_quantities) > 0:
# تحليل التكاليف حسب الفئة
category_costs = {}
total_cost = 0
for item in st.session_state.bill_of_quantities:
category = item.get('category', 'غير مصنف') # Handle missing category gracefully
cost = item['total_price']
if category in category_costs:
category_costs[category] += cost
else:
category_costs[category] = cost
total_cost += cost
# عرض إجمالي التكاليف
st.metric("إجمالي التكاليف", f"{total_cost:,.2f} ريال")
# عرض التكاليف حسب الفئة
st.markdown("#### التكاليف حسب الفئة")
for category, cost in category_costs.items():
percentage = (cost / total_cost) * 100
st.write(f"- {category}: {cost:,.2f} ريال ({percentage:.1f}%)")
else:
st.warning("لا توجد بنود في جدول الكميات")
def _render_pricing_scenarios_tab(self):
st.markdown("### سيناريوهات التسعير")
balanced_pricing.render_balanced_strategy()
def _render_local_content_tab(self):
st.markdown("### المحتوى المحلي")
overheads.render_local_content_ui()