|
""" |
|
وحدة تحليل البيانات - التطبيق الرئيسي |
|
""" |
|
|
|
import streamlit as st |
|
import pandas as pd |
|
import numpy as np |
|
import matplotlib.pyplot as plt |
|
import plotly.express as px |
|
import plotly.graph_objects as go |
|
from datetime import datetime |
|
import time |
|
import io |
|
import os |
|
import json |
|
import base64 |
|
from pathlib import Path |
|
|
|
class DataAnalysisApp: |
|
"""وحدة تحليل البيانات""" |
|
|
|
def __init__(self): |
|
"""تهيئة وحدة تحليل البيانات""" |
|
|
|
|
|
if 'uploaded_data' not in st.session_state: |
|
st.session_state.uploaded_data = None |
|
|
|
if 'data_sources' not in st.session_state: |
|
st.session_state.data_sources = [ |
|
{ |
|
'id': 1, |
|
'name': 'بيانات المناقصات السابقة', |
|
'type': 'CSV', |
|
'rows': 250, |
|
'columns': 15, |
|
'last_updated': '2024-03-01', |
|
'description': 'بيانات المناقصات السابقة للشركة خلال الثلاث سنوات الماضية' |
|
}, |
|
{ |
|
'id': 2, |
|
'name': 'بيانات المنافسين', |
|
'type': 'Excel', |
|
'rows': 120, |
|
'columns': 10, |
|
'last_updated': '2024-02-15', |
|
'description': 'بيانات المنافسين الرئيسيين في السوق وأسعارهم التنافسية' |
|
}, |
|
{ |
|
'id': 3, |
|
'name': 'بيانات أسعار المواد', |
|
'type': 'CSV', |
|
'rows': 500, |
|
'columns': 8, |
|
'last_updated': '2024-03-10', |
|
'description': 'بيانات أسعار المواد الرئيسية المستخدمة في المشاريع' |
|
}, |
|
{ |
|
'id': 4, |
|
'name': 'بيانات الموردين', |
|
'type': 'Excel', |
|
'rows': 80, |
|
'columns': 12, |
|
'last_updated': '2024-02-20', |
|
'description': 'بيانات الموردين الرئيسيين وأسعارهم وجودة منتجاتهم' |
|
}, |
|
{ |
|
'id': 5, |
|
'name': 'بيانات المشاريع المنجزة', |
|
'type': 'CSV', |
|
'rows': 150, |
|
'columns': 20, |
|
'last_updated': '2024-03-15', |
|
'description': 'بيانات المشاريع المنجزة وتكاليفها الفعلية ومدة تنفيذها' |
|
} |
|
] |
|
|
|
if 'sample_data' not in st.session_state: |
|
|
|
np.random.seed(42) |
|
|
|
|
|
n_tenders = 50 |
|
tender_ids = [f"T-{2021 + i//20}-{i%20 + 1:03d}" for i in range(n_tenders)] |
|
tender_types = np.random.choice(["مبنى إداري", "مبنى سكني", "مدرسة", "مستشفى", "طرق", "جسور", "بنية تحتية"], n_tenders) |
|
tender_locations = np.random.choice(["الرياض", "جدة", "الدمام", "مكة", "المدينة", "أبها", "تبوك"], n_tenders) |
|
tender_areas = np.random.randint(1000, 10000, n_tenders) |
|
tender_durations = np.random.randint(6, 36, n_tenders) |
|
tender_budgets = np.random.randint(1000000, 50000000, n_tenders) |
|
tender_costs = np.array([budget * np.random.uniform(0.8, 1.1) for budget in tender_budgets]) |
|
tender_profits = tender_budgets - tender_costs |
|
tender_profit_margins = tender_profits / tender_budgets * 100 |
|
tender_statuses = np.random.choice(["فائز", "خاسر", "قيد التنفيذ", "منجز"], n_tenders) |
|
tender_dates = [f"202{1 + i//20}-{np.random.randint(1, 13):02d}-{np.random.randint(1, 29):02d}" for i in range(n_tenders)] |
|
|
|
|
|
tenders_data = { |
|
"رقم المناقصة": tender_ids, |
|
"نوع المشروع": tender_types, |
|
"الموقع": tender_locations, |
|
"المساحة (م2)": tender_areas, |
|
"المدة (شهر)": tender_durations, |
|
"الميزانية (ريال)": tender_budgets, |
|
"التكلفة (ريال)": tender_costs, |
|
"الربح (ريال)": tender_profits, |
|
"هامش الربح (%)": tender_profit_margins, |
|
"الحالة": tender_statuses, |
|
"تاريخ التقديم": tender_dates |
|
} |
|
|
|
st.session_state.sample_data = { |
|
"tenders": pd.DataFrame(tenders_data) |
|
} |
|
|
|
|
|
n_materials = 30 |
|
material_ids = [f"M-{i+1:03d}" for i in range(n_materials)] |
|
material_names = [ |
|
"خرسانة جاهزة", "حديد تسليح", "طابوق", "أسمنت", "رمل", "بحص", "خشب", "ألمنيوم", "زجاج", "دهان", |
|
"سيراميك", "رخام", "جبس", "عازل مائي", "عازل حراري", "أنابيب PVC", "أسلاك كهربائية", "مفاتيح كهربائية", |
|
"إنارة", "تكييف", "مصاعد", "أبواب خشبية", "أبواب حديدية", "نوافذ ألمنيوم", "نوافذ زجاجية", |
|
"أرضيات خشبية", "أرضيات بلاط", "أرضيات رخام", "أرضيات سيراميك", "أرضيات بورسلين" |
|
] |
|
material_units = np.random.choice(["م3", "طن", "م2", "كجم", "لتر", "قطعة", "متر"], n_materials) |
|
material_prices_2021 = np.random.randint(50, 5000, n_materials) |
|
material_prices_2022 = np.array([price * np.random.uniform(1.0, 1.2) for price in material_prices_2021]) |
|
material_prices_2023 = np.array([price * np.random.uniform(1.0, 1.15) for price in material_prices_2022]) |
|
material_prices_2024 = np.array([price * np.random.uniform(0.95, 1.1) for price in material_prices_2023]) |
|
|
|
|
|
materials_data = { |
|
"رمز المادة": material_ids, |
|
"اسم المادة": material_names, |
|
"الوحدة": material_units, |
|
"سعر 2021 (ريال)": material_prices_2021, |
|
"سعر 2022 (ريال)": material_prices_2022, |
|
"سعر 2023 (ريال)": material_prices_2023, |
|
"سعر 2024 (ريال)": material_prices_2024, |
|
"نسبة التغير 2021-2024 (%)": (material_prices_2024 - material_prices_2021) / material_prices_2021 * 100 |
|
} |
|
|
|
st.session_state.sample_data["materials"] = pd.DataFrame(materials_data) |
|
|
|
|
|
n_competitors = 10 |
|
competitor_ids = [f"C-{i+1:02d}" for i in range(n_competitors)] |
|
competitor_names = [ |
|
"شركة الإنشاءات المتطورة", "شركة البناء الحديث", "شركة التطوير العمراني", "شركة الإعمار الدولية", |
|
"شركة البنية التحتية المتكاملة", "شركة المقاولات العامة", "شركة التشييد والبناء", "شركة الهندسة والإنشاءات", |
|
"شركة المشاريع الكبرى", "شركة التطوير العقاري" |
|
] |
|
competitor_specialties = np.random.choice(["مباني", "طرق", "جسور", "بنية تحتية", "متعددة"], n_competitors) |
|
competitor_sizes = np.random.choice(["صغيرة", "متوسطة", "كبيرة"], n_competitors) |
|
competitor_market_shares = np.random.uniform(1, 15, n_competitors) |
|
competitor_win_rates = np.random.uniform(10, 60, n_competitors) |
|
competitor_avg_margins = np.random.uniform(5, 20, n_competitors) |
|
|
|
|
|
competitors_data = { |
|
"رمز المنافس": competitor_ids, |
|
"اسم المنافس": competitor_names, |
|
"التخصص": competitor_specialties, |
|
"الحجم": competitor_sizes, |
|
"حصة السوق (%)": competitor_market_shares, |
|
"معدل الفوز (%)": competitor_win_rates, |
|
"متوسط هامش الربح (%)": competitor_avg_margins |
|
} |
|
|
|
st.session_state.sample_data["competitors"] = pd.DataFrame(competitors_data) |
|
|
|
def render(self): |
|
"""عرض واجهة وحدة تحليل البيانات""" |
|
|
|
st.markdown("<h1 class='module-title'>وحدة تحليل البيانات</h1>", unsafe_allow_html=True) |
|
|
|
tabs = st.tabs([ |
|
"لوحة المعلومات", |
|
"تحليل المناقصات", |
|
"تحليل الأسعار", |
|
"تحليل المنافسين", |
|
"استيراد وتصدير البيانات" |
|
]) |
|
|
|
with tabs[0]: |
|
self._render_dashboard_tab() |
|
|
|
with tabs[1]: |
|
self._render_tenders_analysis_tab() |
|
|
|
with tabs[2]: |
|
self._render_price_analysis_tab() |
|
|
|
with tabs[3]: |
|
self._render_competitors_analysis_tab() |
|
|
|
with tabs[4]: |
|
self._render_import_export_tab() |
|
|
|
def _render_dashboard_tab(self): |
|
"""عرض تبويب لوحة المعلومات""" |
|
|
|
st.markdown("### لوحة المعلومات") |
|
|
|
|
|
st.markdown("#### مؤشرات الأداء الرئيسية") |
|
|
|
|
|
tenders_df = st.session_state.sample_data["tenders"] |
|
|
|
|
|
total_tenders = len(tenders_df) |
|
won_tenders = len(tenders_df[tenders_df["الحالة"] == "فائز"]) |
|
win_rate = won_tenders / total_tenders * 100 |
|
avg_profit_margin = tenders_df["هامش الربح (%)"].mean() |
|
total_profit = tenders_df["الربح (ريال)"].sum() |
|
|
|
|
|
col1, col2, col3, col4 = st.columns(4) |
|
|
|
with col1: |
|
st.metric("إجمالي المناقصات", f"{total_tenders}") |
|
|
|
with col2: |
|
st.metric("معدل الفوز", f"{win_rate:.1f}%") |
|
|
|
with col3: |
|
st.metric("متوسط هامش الربح", f"{avg_profit_margin:.1f}%") |
|
|
|
with col4: |
|
st.metric("إجمالي الربح", f"{total_profit:,.0f} ريال") |
|
|
|
|
|
st.markdown("#### توزيع المناقصات حسب الحالة") |
|
|
|
status_counts = tenders_df["الحالة"].value_counts().reset_index() |
|
status_counts.columns = ["الحالة", "العدد"] |
|
|
|
fig = px.pie( |
|
status_counts, |
|
values="العدد", |
|
names="الحالة", |
|
title="توزيع المناقصات حسب الحالة", |
|
color="الحالة", |
|
color_discrete_map={ |
|
"فائز": "#2ecc71", |
|
"خاسر": "#e74c3c", |
|
"قيد التنفيذ": "#3498db", |
|
"منجز": "#f39c12" |
|
} |
|
) |
|
|
|
st.plotly_chart(fig, use_container_width=True) |
|
|
|
|
|
st.markdown("#### توزيع المناقصات حسب نوع المشروع") |
|
|
|
type_counts = tenders_df["نوع المشروع"].value_counts().reset_index() |
|
type_counts.columns = ["نوع المشروع", "العدد"] |
|
|
|
fig = px.bar( |
|
type_counts, |
|
x="نوع المشروع", |
|
y="العدد", |
|
title="توزيع المناقصات حسب نوع المشروع", |
|
color="نوع المشروع", |
|
text_auto=True |
|
) |
|
|
|
st.plotly_chart(fig, use_container_width=True) |
|
|
|
|
|
st.markdown("#### تطور هامش الربح عبر الزمن") |
|
|
|
|
|
tenders_df["السنة"] = tenders_df["تاريخ التقديم"].str[:4] |
|
|
|
|
|
profit_margin_by_year = tenders_df.groupby("السنة")["هامش الربح (%)"].mean().reset_index() |
|
|
|
fig = px.line( |
|
profit_margin_by_year, |
|
x="السنة", |
|
y="هامش الربح (%)", |
|
title="تطور متوسط هامش الربح عبر السنوات", |
|
markers=True |
|
) |
|
|
|
st.plotly_chart(fig, use_container_width=True) |
|
|
|
|
|
st.markdown("#### توزيع المناقصات حسب الموقع") |
|
|
|
location_counts = tenders_df["الموقع"].value_counts().reset_index() |
|
location_counts.columns = ["الموقع", "العدد"] |
|
|
|
fig = px.bar( |
|
location_counts, |
|
x="الموقع", |
|
y="العدد", |
|
title="توزيع المناقصات حسب الموقع", |
|
color="الموقع", |
|
text_auto=True |
|
) |
|
|
|
st.plotly_chart(fig, use_container_width=True) |
|
|
|
|
|
st.markdown("#### العلاقة بين الميزانية والتكلفة") |
|
|
|
fig = px.scatter( |
|
tenders_df, |
|
x="الميزانية (ريال)", |
|
y="التكلفة (ريال)", |
|
color="الحالة", |
|
size="المساحة (م2)", |
|
hover_name="رقم المناقصة", |
|
hover_data=["نوع المشروع", "الموقع", "هامش الربح (%)"], |
|
title="العلاقة بين الميزانية والتكلفة", |
|
color_discrete_map={ |
|
"فائز": "#2ecc71", |
|
"خاسر": "#e74c3c", |
|
"قيد التنفيذ": "#3498db", |
|
"منجز": "#f39c12" |
|
} |
|
) |
|
|
|
|
|
max_value = max(tenders_df["الميزانية (ريال)"].max(), tenders_df["التكلفة (ريال)"].max()) |
|
fig.add_trace( |
|
go.Scatter( |
|
x=[0, max_value], |
|
y=[0, max_value], |
|
mode="lines", |
|
line=dict(color="gray", dash="dash"), |
|
name="الميزانية = التكلفة" |
|
) |
|
) |
|
|
|
st.plotly_chart(fig, use_container_width=True) |
|
|
|
def _render_tenders_analysis_tab(self): |
|
"""عرض تبويب تحليل المناقصات""" |
|
|
|
st.markdown("### تحليل المناقصات") |
|
|
|
|
|
tenders_df = st.session_state.sample_data["tenders"] |
|
|
|
|
|
st.markdown("#### خيارات التصفية") |
|
|
|
col1, col2, col3 = st.columns(3) |
|
|
|
with col1: |
|
selected_status = st.multiselect( |
|
"الحالة", |
|
options=tenders_df["الحالة"].unique(), |
|
default=tenders_df["الحالة"].unique() |
|
) |
|
|
|
with col2: |
|
selected_types = st.multiselect( |
|
"نوع المشروع", |
|
options=tenders_df["نوع المشروع"].unique(), |
|
default=tenders_df["نوع المشروع"].unique() |
|
) |
|
|
|
with col3: |
|
selected_locations = st.multiselect( |
|
"الموقع", |
|
options=tenders_df["الموقع"].unique(), |
|
default=tenders_df["الموقع"].unique() |
|
) |
|
|
|
|
|
filtered_df = tenders_df[ |
|
tenders_df["الحالة"].isin(selected_status) & |
|
tenders_df["نوع المشروع"].isin(selected_types) & |
|
tenders_df["الموقع"].isin(selected_locations) |
|
] |
|
|
|
|
|
st.markdown("#### البيانات المصفاة") |
|
|
|
st.dataframe(filtered_df, use_container_width=True, hide_index=True) |
|
|
|
|
|
st.markdown("#### إحصائيات البيانات المصفاة") |
|
|
|
col1, col2, col3, col4 = st.columns(4) |
|
|
|
with col1: |
|
st.metric("عدد المناقصات", f"{len(filtered_df)}") |
|
|
|
with col2: |
|
won_count = len(filtered_df[filtered_df["الحالة"] == "فائز"]) |
|
win_rate = won_count / len(filtered_df) * 100 if len(filtered_df) > 0 else 0 |
|
st.metric("معدل الفوز", f"{win_rate:.1f}%") |
|
|
|
with col3: |
|
avg_profit_margin = filtered_df["هامش الربح (%)"].mean() |
|
st.metric("متوسط هامش الربح", f"{avg_profit_margin:.1f}%") |
|
|
|
with col4: |
|
total_profit = filtered_df["الربح (ريال)"].sum() |
|
st.metric("إجمالي الربح", f"{total_profit:,.0f} ريال") |
|
|
|
|
|
st.markdown("#### تحليل هامش الربح حسب نوع المشروع") |
|
|
|
profit_margin_by_type = filtered_df.groupby("نوع المشروع")["هامش الربح (%)"].mean().reset_index() |
|
|
|
fig = px.bar( |
|
profit_margin_by_type, |
|
x="نوع المشروع", |
|
y="هامش الربح (%)", |
|
title="متوسط هامش الربح حسب نوع المشروع", |
|
color="نوع المشروع", |
|
text_auto=".1f" |
|
) |
|
|
|
st.plotly_chart(fig, use_container_width=True) |
|
|
|
|
|
st.markdown("#### تحليل هامش الربح حسب الموقع") |
|
|
|
profit_margin_by_location = filtered_df.groupby("الموقع")["هامش الربح (%)"].mean().reset_index() |
|
|
|
fig = px.bar( |
|
profit_margin_by_location, |
|
x="الموقع", |
|
y="هامش الربح (%)", |
|
title="متوسط هامش الربح حسب الموقع", |
|
color="الموقع", |
|
text_auto=".1f" |
|
) |
|
|
|
st.plotly_chart(fig, use_container_width=True) |
|
|
|
|
|
st.markdown("#### تحليل معدل الفوز حسب نوع المشروع") |
|
|
|
|
|
win_rate_by_type = [] |
|
|
|
for project_type in filtered_df["نوع المشروع"].unique(): |
|
type_df = filtered_df[filtered_df["نوع المشروع"] == project_type] |
|
won_count = len(type_df[type_df["الحالة"] == "فائز"]) |
|
total_count = len(type_df) |
|
win_rate = won_count / total_count * 100 if total_count > 0 else 0 |
|
win_rate_by_type.append({ |
|
"نوع المشروع": project_type, |
|
"معدل الفوز (%)": win_rate, |
|
"عدد المناقصات": total_count |
|
}) |
|
|
|
win_rate_by_type_df = pd.DataFrame(win_rate_by_type) |
|
|
|
fig = px.bar( |
|
win_rate_by_type_df, |
|
x="نوع المشروع", |
|
y="معدل الفوز (%)", |
|
title="معدل الفوز حسب نوع المشروع", |
|
color="نوع المشروع", |
|
text_auto=".1f", |
|
hover_data=["عدد المناقصات"] |
|
) |
|
|
|
st.plotly_chart(fig, use_container_width=True) |
|
|
|
|
|
st.markdown("#### العلاقة بين حجم المشروع وهامش الربح") |
|
|
|
fig = px.scatter( |
|
filtered_df, |
|
x="الميزانية (ريال)", |
|
y="هامش الربح (%)", |
|
color="الحالة", |
|
size="المساحة (م2)", |
|
hover_name="رقم المناقصة", |
|
hover_data=["نوع المشروع", "الموقع", "المدة (شهر)"], |
|
title="العلاقة بين حجم المشروع وهامش الربح", |
|
color_discrete_map={ |
|
"فائز": "#2ecc71", |
|
"خاسر": "#e74c3c", |
|
"قيد التنفيذ": "#3498db", |
|
"منجز": "#f39c12" |
|
} |
|
) |
|
|
|
|
|
fig.update_layout( |
|
shapes=[ |
|
dict( |
|
type="line", |
|
xref="x", |
|
yref="y", |
|
x0=filtered_df["الميزانية (ريال)"].min(), |
|
y0=filtered_df["هامش الربح (%)"].mean(), |
|
x1=filtered_df["الميزانية (ريال)"].max(), |
|
y1=filtered_df["هامش الربح (%)"].mean(), |
|
line=dict(color="gray", dash="dash") |
|
) |
|
] |
|
) |
|
|
|
st.plotly_chart(fig, use_container_width=True) |
|
|
|
|
|
st.markdown("#### العلاقة بين مدة المشروع وهامش الربح") |
|
|
|
fig = px.scatter( |
|
filtered_df, |
|
x="المدة (شهر)", |
|
y="هامش الربح (%)", |
|
color="الحالة", |
|
size="الميزانية (ريال)", |
|
hover_name="رقم المناقصة", |
|
hover_data=["نوع المشروع", "الموقع", "المساحة (م2)"], |
|
title="العلاقة بين مدة المشروع وهامش الربح", |
|
color_discrete_map={ |
|
"فائز": "#2ecc71", |
|
"خاسر": "#e74c3c", |
|
"قيد التنفيذ": "#3498db", |
|
"منجز": "#f39c12" |
|
} |
|
) |
|
|
|
st.plotly_chart(fig, use_container_width=True) |
|
|
|
def _render_price_analysis_tab(self): |
|
"""عرض تبويب تحليل الأسعار""" |
|
|
|
st.markdown("### تحليل الأسعار") |
|
|
|
|
|
materials_df = st.session_state.sample_data["materials"] |
|
|
|
|
|
st.markdown("#### بيانات أسعار المواد") |
|
|
|
st.dataframe(materials_df, use_container_width=True, hide_index=True) |
|
|
|
|
|
st.markdown("#### تطور أسعار المواد عبر السنوات") |
|
|
|
|
|
selected_materials = st.multiselect( |
|
"اختر المواد للعرض", |
|
options=materials_df["اسم المادة"].unique(), |
|
default=materials_df["اسم المادة"].unique()[:5] |
|
) |
|
|
|
if selected_materials: |
|
|
|
filtered_materials = materials_df[materials_df["اسم المادة"].isin(selected_materials)] |
|
|
|
|
|
melted_df = pd.melt( |
|
filtered_materials, |
|
id_vars=["رمز المادة", "اسم المادة", "الوحدة"], |
|
value_vars=["سعر 2021 (ريال)", "سعر 2022 (ريال)", "سعر 2023 (ريال)", "سعر 2024 (ريال)"], |
|
var_name="السنة", |
|
value_name="السعر (ريال)" |
|
) |
|
|
|
|
|
melted_df["السنة"] = melted_df["السنة"].str.extract(r"سعر (\d{4})") |
|
|
|
|
|
fig = px.line( |
|
melted_df, |
|
x="السنة", |
|
y="السعر (ريال)", |
|
color="اسم المادة", |
|
title="تطور أسعار المواد عبر السنوات", |
|
markers=True, |
|
hover_data=["الوحدة"] |
|
) |
|
|
|
st.plotly_chart(fig, use_container_width=True) |
|
|
|
|
|
st.markdown("#### نسبة التغير في أسعار المواد (2021-2024)") |
|
|
|
|
|
sorted_materials = materials_df.sort_values("نسبة التغير 2021-2024 (%)", ascending=False) |
|
|
|
fig = px.bar( |
|
sorted_materials, |
|
x="اسم المادة", |
|
y="نسبة التغير 2021-2024 (%)", |
|
title="نسبة التغير في أسعار المواد (2021-2024)", |
|
color="نسبة التغير 2021-2024 (%)", |
|
color_continuous_scale="RdYlGn_r", |
|
text_auto=".1f" |
|
) |
|
|
|
st.plotly_chart(fig, use_container_width=True) |
|
|
|
|
|
st.markdown("#### توزيع أسعار المواد حسب الفئة") |
|
|
|
|
|
materials_df["فئة المادة"] = materials_df["اسم المادة"].apply( |
|
lambda x: "مواد إنشائية" if x in ["خرسانة جاهزة", "حديد تسليح", "طابوق", "أسمنت", "رمل", "بحص", "خشب"] |
|
else "مواد تشطيب" if x in ["ألمنيوم", "زجاج", "دهان", "سيراميك", "رخام", "جبس", "عازل مائي", "عازل حراري"] |
|
else "مواد كهربائية" if x in ["أنابيب PVC", "أسلاك كهربائية", "مفاتيح كهربائية", "إنارة"] |
|
else "مواد ميكانيكية" if x in ["تكييف", "مصاعد"] |
|
else "أبواب ونوافذ" if x in ["أبواب خشبية", "أبواب حديدية", "نوافذ ألمنيوم", "نوافذ زجاجية"] |
|
else "أرضيات" if x in ["أرضيات خشبية", "أرضيات بلاط", "أرضيات رخام", "أرضيات سيراميك", "أرضيات بورسلين"] |
|
else "أخرى" |
|
) |
|
|
|
|
|
category_change = materials_df.groupby("فئة المادة")["نسبة التغير 2021-2024 (%)"].mean().reset_index() |
|
|
|
fig = px.bar( |
|
category_change, |
|
x="فئة المادة", |
|
y="نسبة التغير 2021-2024 (%)", |
|
title="متوسط نسبة التغير في أسعار المواد حسب الفئة (2021-2024)", |
|
color="فئة المادة", |
|
text_auto=".1f" |
|
) |
|
|
|
st.plotly_chart(fig, use_container_width=True) |
|
|
|
|
|
st.markdown("#### تحليل تأثير تغير الأسعار على تكاليف المشاريع") |
|
|
|
|
|
cost_distribution = { |
|
"الفئة": [ |
|
"مواد إنشائية", |
|
"مواد تشطيب", |
|
"مواد كهربائية", |
|
"مواد ميكانيكية", |
|
"أبواب ونوافذ", |
|
"أرضيات", |
|
"عمالة", |
|
"معدات", |
|
"نفقات عامة" |
|
], |
|
"النسبة من التكلفة (%)": [30, 20, 10, 15, 5, 5, 10, 3, 2] |
|
} |
|
|
|
cost_distribution_df = pd.DataFrame(cost_distribution) |
|
|
|
|
|
impact_data = [] |
|
|
|
for index, row in cost_distribution_df.iterrows(): |
|
category = row["الفئة"] |
|
cost_percentage = row["النسبة من التكلفة (%)"] |
|
|
|
if category in category_change["فئة المادة"].values: |
|
price_change = category_change[category_change["فئة المادة"] == category]["نسبة التغير 2021-2024 (%)"].values[0] |
|
else: |
|
|
|
price_change = 10 if category == "عمالة" else 5 |
|
|
|
impact = cost_percentage * price_change / 100 |
|
|
|
impact_data.append({ |
|
"الفئة": category, |
|
"النسبة من التكلفة (%)": cost_percentage, |
|
"نسبة التغير في الأسعار (%)": price_change, |
|
"التأثير على التكلفة الإجمالية (%)": impact |
|
}) |
|
|
|
impact_df = pd.DataFrame(impact_data) |
|
|
|
|
|
total_impact = impact_df["التأثير على التكلفة الإجمالية (%)"].sum() |
|
|
|
st.metric("إجمالي التأثير على التكلفة", f"{total_impact:.1f}%") |
|
|
|
|
|
st.dataframe(impact_df, use_container_width=True, hide_index=True) |
|
|
|
|
|
fig = px.bar( |
|
impact_df, |
|
x="الفئة", |
|
y="التأثير على التكلفة الإجمالية (%)", |
|
title="تأثير تغير الأسعار على التكلفة الإجمالية للمشاريع", |
|
color="الفئة", |
|
text_auto=".1f" |
|
) |
|
|
|
st.plotly_chart(fig, use_container_width=True) |
|
|
|
|
|
st.markdown("#### توصيات لإدارة تغير الأسعار") |
|
|
|
st.markdown(""" |
|
1. **التعاقد المسبق مع الموردين:** التعاقد المسبق مع الموردين لتثبيت الأسعار لفترة زمنية محددة. |
|
2. **تنويع مصادر التوريد:** تنويع مصادر التوريد لتقليل مخاطر ارتفاع الأسعار من مصدر واحد. |
|
3. **شراء المواد مقدماً:** شراء المواد الرئيسية مقدماً للمشاريع المستقبلية عندما تكون الأسعار منخفضة. |
|
4. **استخدام مواد بديلة:** استخدام مواد بديلة ذات جودة مماثلة وأسعار أقل. |
|
5. **تضمين بند تعديل الأسعار في العقود:** تضمين بند تعديل الأسعار في العقود لتغطية التغيرات الكبيرة في أسعار المواد. |
|
6. **تحسين كفاءة استخدام المواد:** تحسين كفاءة استخدام المواد لتقليل الهدر وتقليل التكاليف. |
|
7. **مراقبة اتجاهات الأسعار:** مراقبة اتجاهات الأسعار بشكل مستمر واتخاذ القرارات بناءً على التوقعات المستقبلية. |
|
""") |
|
|
|
def _render_competitors_analysis_tab(self): |
|
"""عرض تبويب تحليل المنافسين""" |
|
|
|
st.markdown("### تحليل المنافسين") |
|
|
|
|
|
competitors_df = st.session_state.sample_data["competitors"] |
|
|
|
|
|
st.markdown("#### بيانات المنافسين") |
|
|
|
st.dataframe(competitors_df, use_container_width=True, hide_index=True) |
|
|
|
|
|
st.markdown("#### حصص السوق للمنافسين") |
|
|
|
|
|
sorted_competitors = competitors_df.sort_values("حصة السوق (%)", ascending=False) |
|
|
|
fig = px.pie( |
|
sorted_competitors, |
|
values="حصة السوق (%)", |
|
names="اسم المنافس", |
|
title="حصص السوق للمنافسين", |
|
hover_data=["التخصص", "الحجم"] |
|
) |
|
|
|
st.plotly_chart(fig, use_container_width=True) |
|
|
|
|
|
st.markdown("#### معدلات الفوز للمنافسين") |
|
|
|
|
|
sorted_by_win_rate = competitors_df.sort_values("معدل الفوز (%)", ascending=False) |
|
|
|
fig = px.bar( |
|
sorted_by_win_rate, |
|
x="اسم المنافس", |
|
y="معدل الفوز (%)", |
|
title="معدلات الفوز للمنافسين", |
|
color="معدل الفوز (%)", |
|
text_auto=".1f", |
|
hover_data=["التخصص", "الحجم", "حصة السوق (%)"] |
|
) |
|
|
|
st.plotly_chart(fig, use_container_width=True) |
|
|
|
|
|
st.markdown("#### متوسط هوامش الربح للمنافسين") |
|
|
|
|
|
sorted_by_margin = competitors_df.sort_values("متوسط هامش الربح (%)", ascending=False) |
|
|
|
fig = px.bar( |
|
sorted_by_margin, |
|
x="اسم المنافس", |
|
y="متوسط هامش الربح (%)", |
|
title="متوسط هوامش الربح للمنافسين", |
|
color="متوسط هامش الربح (%)", |
|
text_auto=".1f", |
|
hover_data=["التخصص", "الحجم", "حصة السوق (%)"] |
|
) |
|
|
|
st.plotly_chart(fig, use_container_width=True) |
|
|
|
|
|
st.markdown("#### تحليل المنافسين حسب التخصص") |
|
|
|
|
|
specialty_analysis = competitors_df.groupby("التخصص").agg({ |
|
"معدل الفوز (%)": "mean", |
|
"متوسط هامش الربح (%)": "mean", |
|
"حصة السوق (%)": "sum" |
|
}).reset_index() |
|
|
|
|
|
st.dataframe(specialty_analysis, use_container_width=True, hide_index=True) |
|
|
|
|
|
fig = px.scatter( |
|
specialty_analysis, |
|
x="معدل الفوز (%)", |
|
y="متوسط هامش الربح (%)", |
|
size="حصة السوق (%)", |
|
color="التخصص", |
|
hover_name="التخصص", |
|
title="العلاقة بين معدل الفوز وهامش الربح حسب التخصص", |
|
text="التخصص" |
|
) |
|
|
|
st.plotly_chart(fig, use_container_width=True) |
|
|
|
|
|
st.markdown("#### تحليل المنافسين حسب الحجم") |
|
|
|
|
|
size_analysis = competitors_df.groupby("الحجم").agg({ |
|
"معدل الفوز (%)": "mean", |
|
"متوسط هامش الربح (%)": "mean", |
|
"حصة السوق (%)": "sum" |
|
}).reset_index() |
|
|
|
|
|
st.dataframe(size_analysis, use_container_width=True, hide_index=True) |
|
|
|
|
|
fig = px.scatter( |
|
size_analysis, |
|
x="معدل الفوز (%)", |
|
y="متوسط هامش الربح (%)", |
|
size="حصة السوق (%)", |
|
color="الحجم", |
|
hover_name="الحجم", |
|
title="العلاقة بين معدل الفوز وهامش الربح حسب الحجم", |
|
text="الحجم" |
|
) |
|
|
|
st.plotly_chart(fig, use_container_width=True) |
|
|
|
|
|
st.markdown("#### تحليل نقاط القوة والضعف للمنافسين الرئيسيين") |
|
|
|
|
|
top_competitors = competitors_df.sort_values("حصة السوق (%)", ascending=False).head(3) |
|
|
|
for index, competitor in top_competitors.iterrows(): |
|
with st.expander(f"{competitor['اسم المنافس']} - حصة السوق: {competitor['حصة السوق (%)']:.1f}%"): |
|
st.markdown(f"**التخصص:** {competitor['التخصص']}") |
|
st.markdown(f"**الحجم:** {competitor['الحجم']}") |
|
st.markdown(f"**معدل الفوز:** {competitor['معدل الفوز (%)']:.1f}%") |
|
st.markdown(f"**متوسط هامش الربح:** {competitor['متوسط هامش الربح (%)']:.1f}%") |
|
|
|
st.markdown("**نقاط القوة:**") |
|
if competitor["الحجم"] == "كبيرة": |
|
st.markdown("- قدرة مالية كبيرة") |
|
st.markdown("- خبرة واسعة في المشاريع الكبيرة") |
|
st.markdown("- سمعة قوية في السوق") |
|
st.markdown("- شبكة علاقات واسعة") |
|
elif competitor["الحجم"] == "متوسطة": |
|
st.markdown("- مرونة في التعامل مع المشاريع") |
|
st.markdown("- تكاليف تشغيلية أقل") |
|
st.markdown("- تخصص في مجالات محددة") |
|
st.markdown("- سرعة في اتخاذ القرارات") |
|
else: |
|
st.markdown("- مرونة عالية") |
|
st.markdown("- تكاليف تشغيلية منخفضة") |
|
st.markdown("- خدمة عملاء متميزة") |
|
st.markdown("- تخصص دقيق في مجال محدد") |
|
|
|
st.markdown("**نقاط الضعف:**") |
|
if competitor["الحجم"] == "كبيرة": |
|
st.markdown("- بطء في اتخاذ القرارات") |
|
st.markdown("- تكاليف تشغيلية عالية") |
|
st.markdown("- أقل مرونة في التعامل مع التغييرات") |
|
st.markdown("- تركيز على المشاريع الكبيرة فقط") |
|
elif competitor["الحجم"] == "متوسطة": |
|
st.markdown("- قدرة مالية محدودة مقارنة بالشركات الكبيرة") |
|
st.markdown("- صعوبة في المنافسة على المشاريع الكبيرة") |
|
st.markdown("- محدودية الموارد البشرية") |
|
st.markdown("- صعوبة في الحصول على تمويل") |
|
else: |
|
st.markdown("- قدرة مالية محدودة جداً") |
|
st.markdown("- صعوبة في المنافسة على المشاريع المتوسطة والكبيرة") |
|
st.markdown("- محدودية الموارد البشرية والفنية") |
|
st.markdown("- صعوبة في الحصول على تمويل") |
|
|
|
|
|
st.markdown("#### توصيات للتعامل مع المنافسين") |
|
|
|
st.markdown(""" |
|
1. **التركيز على نقاط القوة:** التركيز على نقاط القوة الخاصة بالشركة والتي تميزها عن المنافسين. |
|
2. **استهداف شرائح سوقية محددة:** استهداف شرائح سوقية محددة والتركيز على تلبية احتياجاتها بشكل أفضل من المنافسين. |
|
3. **تطوير علاقات قوية مع العملاء:** تطوير علاقات قوية مع العملاء لضمان ولائهم وتكرار التعامل معهم. |
|
4. **الابتكار في الخدمات والحلول:** تقديم حلول مبتكرة وخدمات متميزة تلبي احتياجات العملاء بشكل أفضل من المنافسين. |
|
5. **تحسين الكفاءة التشغيلية:** تحسين الكفاءة التشغيلية لتقليل التكاليف وزيادة القدرة التنافسية. |
|
6. **بناء تحالفات استراتيجية:** بناء تحالفات استراتيجية مع شركات أخرى لتعزيز القدرة التنافسية. |
|
7. **مراقبة المنافسين باستمرار:** مراقبة المنافسين باستمرار وتحليل استراتيجياتهم وتحركاتهم في السوق. |
|
""") |
|
|
|
def _render_import_export_tab(self): |
|
"""عرض تبويب استيراد وتصدير البيانات""" |
|
|
|
st.markdown("### استيراد وتصدير البيانات") |
|
|
|
|
|
st.markdown("#### مصادر البيانات الحالية") |
|
|
|
|
|
sources_df = pd.DataFrame(st.session_state.data_sources) |
|
|
|
|
|
st.dataframe( |
|
sources_df, |
|
column_config={ |
|
"id": st.column_config.NumberColumn("الرقم"), |
|
"name": st.column_config.TextColumn("اسم المصدر"), |
|
"type": st.column_config.TextColumn("النوع"), |
|
"rows": st.column_config.NumberColumn("عدد الصفوف"), |
|
"columns": st.column_config.NumberColumn("عدد الأعمدة"), |
|
"last_updated": st.column_config.DateColumn("تاريخ التحديث"), |
|
"description": st.column_config.TextColumn("الوصف") |
|
}, |
|
use_container_width=True, |
|
hide_index=True |
|
) |
|
|
|
|
|
st.markdown("#### استيراد بيانات جديدة") |
|
|
|
col1, col2 = st.columns(2) |
|
|
|
with col1: |
|
data_type = st.selectbox( |
|
"نوع البيانات", |
|
["بيانات المناقصات", "بيانات المنافسين", "بيانات أسعار المواد", "بيانات الموردين", "بيانات المشاريع", "أخرى"] |
|
) |
|
|
|
with col2: |
|
file_format = st.selectbox( |
|
"صيغة الملف", |
|
["CSV", "Excel", "JSON"] |
|
) |
|
|
|
uploaded_file = st.file_uploader(f"قم بتحميل ملف {file_format}", type=["csv", "xlsx", "json"]) |
|
|
|
if uploaded_file is not None: |
|
if st.button("استيراد البيانات"): |
|
|
|
with st.spinner("جاري استيراد البيانات..."): |
|
time.sleep(2) |
|
|
|
|
|
new_id = max([source["id"] for source in st.session_state.data_sources]) + 1 |
|
|
|
st.session_state.data_sources.append({ |
|
"id": new_id, |
|
"name": f"{data_type} - {uploaded_file.name}", |
|
"type": file_format, |
|
"rows": np.random.randint(50, 500), |
|
"columns": np.random.randint(5, 20), |
|
"last_updated": time.strftime("%Y-%m-%d"), |
|
"description": f"بيانات تم استيرادها من ملف {uploaded_file.name}" |
|
}) |
|
|
|
st.success("تم استيراد البيانات بنجاح!") |
|
st.rerun() |
|
|
|
|
|
st.markdown("#### تصدير البيانات") |
|
|
|
col1, col2 = st.columns(2) |
|
|
|
with col1: |
|
export_data_type = st.selectbox( |
|
"نوع البيانات للتصدير", |
|
["بيانات المناقصات", "بيانات المنافسين", "بيانات أسعار المواد", "بيانات الموردين", "بيانات المشاريع", "تقرير تحليلي شامل"] |
|
) |
|
|
|
with col2: |
|
export_format = st.selectbox( |
|
"صيغة التصدير", |
|
["CSV", "Excel", "JSON", "PDF"] |
|
) |
|
|
|
if st.button("تصدير البيانات"): |
|
|
|
with st.spinner("جاري تصدير البيانات..."): |
|
time.sleep(2) |
|
st.success(f"تم تصدير {export_data_type} بصيغة {export_format} بنجاح!") |
|
|
|
|
|
if export_data_type == "بيانات المناقصات": |
|
df = st.session_state.sample_data["tenders"] |
|
elif export_data_type == "بيانات المنافسين": |
|
df = st.session_state.sample_data["competitors"] |
|
elif export_data_type == "بيانات أسعار المواد": |
|
df = st.session_state.sample_data["materials"] |
|
else: |
|
|
|
df = pd.DataFrame({ |
|
"البيان": ["بيان 1", "بيان 2", "بيان 3"], |
|
"القيمة": [100, 200, 300] |
|
}) |
|
|
|
|
|
csv = df.to_csv(index=False) |
|
b64 = base64.b64encode(csv.encode()).decode() |
|
href = f'<a href="data:file/csv;base64,{b64}" download="{export_data_type}.csv">انقر هنا لتنزيل الملف</a>' |
|
st.markdown(href, unsafe_allow_html=True) |
|
|
|
|
|
st.markdown("#### تكامل البيانات مع الوحدات الأخرى") |
|
|
|
st.markdown(""" |
|
يمكن تكامل البيانات مع الوحدات الأخرى في النظام من خلال: |
|
|
|
1. **إرسال البيانات إلى وحدة التسعير:** إرسال بيانات أسعار المواد وبيانات المناقصات السابقة إلى وحدة التسعير لتحسين دقة التسعير. |
|
2. **إرسال البيانات إلى وحدة تحليل المخاطر:** إرسال بيانات المناقصات السابقة وبيانات المنافسين إلى وحدة تحليل المخاطر لتحسين تقييم المخاطر. |
|
3. **إرسال البيانات إلى وحدة الذكاء الاصطناعي:** إرسال البيانات إلى وحدة الذكاء الاصطناعي لتدريب النماذج وتحسين دقة التنبؤات. |
|
4. **إرسال البيانات إلى وحدة إدارة المشاريع:** إرسال بيانات المشاريع المنجزة إلى وحدة إدارة المشاريع لتحسين تخطيط وإدارة المشاريع المستقبلية. |
|
5. **إرسال البيانات إلى وحدة التقارير:** إرسال البيانات إلى وحدة التقارير لإنشاء تقارير تحليلية شاملة. |
|
""") |
|
|
|
col1, col2, col3 = st.columns(3) |
|
|
|
with col1: |
|
if st.button("إرسال إلى وحدة التسعير"): |
|
st.success("تم إرسال البيانات إلى وحدة التسعير بنجاح!") |
|
|
|
with col2: |
|
if st.button("إرسال إلى وحدة تحليل المخاطر"): |
|
st.success("تم إرسال البيانات إلى وحدة تحليل المخاطر بنجاح!") |
|
|
|
with col3: |
|
if st.button("إرسال إلى وحدة الذكاء الاصطناعي"): |
|
st.success("تم إرسال البيانات إلى وحدة الذكاء الاصطناعي بنجاح!") |
|
|