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 # ملاحظة: تم نقل إعداد الصفحة إلى ملف app.py الرئيسي # لتجنب أخطاء set_page_config يجب أن يكون في ملف واحد فقط st.title("عرض تحسينات واجهة المستخدم") # بيانات تجريبية للعرض @st.cache_data def get_sample_data(): items = pd.DataFrame({ 'رقم البند': ['UB1', 'UB2', 'UB3', 'UB4', 'UB5'], 'وصف البند': ['حفر أساسات', 'صب خرسانة مسلحة', 'أعمال طوب', 'أعمال تشطيبات', 'أعمال كهرباء'], 'الوحدة': ['م3', 'م3', 'م2', 'م2', 'نقطة'], 'الكمية': [350.0, 120.0, 500.0, 800.0, 150.0], 'سعر الوحدة': [80.0, 950.0, 45.0, 120.0, 90.0], 'الإجمالي': [28000.0, 114000.0, 22500.0, 96000.0, 13500.0], 'إستراتيجية التسعير': ['نقص', 'زيادة', 'متوازن', 'زيادة', 'نقص'] }) return items items = get_sample_data() # 1. عرض الجدول مع تنسيق محسن st.markdown("

بنود التسعير غير المتوازن

", unsafe_allow_html=True) # تعيين ألوان للإستراتيجيات وتنسيق الجدول بشكل متقدم def highlight_row(row): strategy = row['إستراتيجية التسعير'] styles = [''] * len(row) # تطبيق لون خلفية لكل صف حسب الإستراتيجية if strategy == 'زيادة': background = 'linear-gradient(90deg, rgba(168, 230, 207, 0.3), rgba(168, 230, 207, 0.1))' text_color = '#1F7A8C' elif strategy == 'نقص': background = 'linear-gradient(90deg, rgba(255, 154, 162, 0.3), rgba(255, 154, 162, 0.1))' text_color = '#9D2A45' else: background = 'linear-gradient(90deg, rgba(220, 237, 255, 0.3), rgba(220, 237, 255, 0.1))' text_color = '#555555' # تطبيق النمط على جميع الخلايا في الصف for i in range(len(styles)): styles[i] = f'background: {background}; color: {text_color}; border-bottom: 1px solid #ddd;' # تطبيق نمط خاص على خلية الإستراتيجية if strategy == 'زيادة': styles[list(row.index).index('إستراتيجية التسعير')] = 'background-color: #a8e6cf; color: #007263; font-weight: bold; border-radius: 5px; text-align: center;' elif strategy == 'نقص': styles[list(row.index).index('إستراتيجية التسعير')] = 'background-color: #ff9aa2; color: #9D2A45; font-weight: bold; border-radius: 5px; text-align: center;' else: styles[list(row.index).index('إستراتيجية التسعير')] = 'background-color: #dceeff; color: #555555; font-weight: bold; border-radius: 5px; text-align: center;' # تنسيق عمود السعر price_idx = list(row.index).index('سعر الوحدة') styles[price_idx] = styles[price_idx] + 'font-weight: bold;' # تنسيق عمود الإجمالي total_idx = list(row.index).index('الإجمالي') styles[total_idx] = styles[total_idx] + 'font-weight: bold;' return styles # تطبيق التنسيق على الجدول styled_items = items.style.apply(highlight_row, axis=1) # تنسيق تنسيق الأرقام styled_items = styled_items.format({ 'الكمية': '{:,.2f}', 'سعر الوحدة': '{:,.2f}', 'الإجمالي': '{:,.2f}' }) st.dataframe(styled_items, use_container_width=True, height=None) # 2. عرض المقارنة مع تصميم محسن st.markdown("

مقارنة التسعير المتوازن وغير المتوازن

", unsafe_allow_html=True) # بيانات المقارنة original_items = items.copy() original_items['سعر الوحدة'] = [70.0, 820.0, 45.0, 100.0, 110.0] original_items['الإجمالي'] = original_items['الكمية'] * original_items['سعر الوحدة'] original_total = original_items['الإجمالي'].sum() unbalanced_total = items['الإجمالي'].sum() # عرض بطاقات المقارنة بتصميم متقدم st.markdown(""" """, unsafe_allow_html=True) col1, col2, col3 = st.columns(3) with col1: st.markdown("""
إجمالي التسعير المتوازن
{:,.2f} ريال
التسعير الأصلي
""".format(original_total), unsafe_allow_html=True) with col2: st.markdown("""
إجمالي التسعير غير المتوازن
{:,.2f} ريال
بعد إعادة توزيع الأسعار
""".format( unbalanced_total, "positive-delta" if unbalanced_total > original_total else "negative-delta" if unbalanced_total < original_total else "neutral-delta" ), unsafe_allow_html=True) with col3: diff = unbalanced_total - original_total delta_percent = diff/original_total*100 if original_total > 0 else 0 st.markdown("""
الفرق بين التسعيرين
{:,.2f} ريال
نسبة الفرق: {:+.1f}%
""".format( diff, "positive-delta" if diff > 0 else "negative-delta" if diff < 0 else "neutral-delta", delta_percent ), unsafe_allow_html=True) # 3. رسم بياني للمقارنة st.markdown("

تحليل بصري للتسعير غير المتوازن

", unsafe_allow_html=True) # إعداد البيانات للرسم البياني chart_data = pd.DataFrame({ 'وصف البند': original_items['وصف البند'], 'التسعير المتوازن': original_items['الإجمالي'], 'التسعير غير المتوازن': items['الإجمالي'] }) # إضافة عمود للنسبة المئوية للتغيير chart_data['نسبة التغيير'] = (chart_data['التسعير غير المتوازن'] - chart_data['التسعير المتوازن']) / chart_data['التسعير المتوازن'] * 100 # تحديد لون الأعمدة بناءً على نسبة التغيير bar_colors = [] for change in chart_data['نسبة التغيير']: if change > 5: # زيادة كبيرة bar_colors.append('#1F7A8C') # أزرق مخضر elif change > 0: # زيادة صغيرة bar_colors.append('#81B29A') # أخضر فاتح elif change > -5: # نقص صغير bar_colors.append('#F2CC8F') # أصفر else: # نقص كبير bar_colors.append('#E07A5F') # أحمر # التبويب بين مخططات مختلفة للمقارنة chart_tabs = st.tabs(["مخطط شريطي", "مخطط مقارنة", "مخطط نسبة التغيير"]) with chart_tabs[0]: # رسم بياني شريطي # رسم بياني شريطي للمقارنة fig = go.Figure() fig.add_trace(go.Bar( x=chart_data['وصف البند'], y=chart_data['التسعير المتوازن'], name='التسعير المتوازن', marker_color='rgba(55, 83, 109, 0.7)' )) fig.add_trace(go.Bar( x=chart_data['وصف البند'], y=chart_data['التسعير غير المتوازن'], name='التسعير غير المتوازن', marker_color=bar_colors )) fig.update_layout( title='مقارنة بين التسعير المتوازن وغير المتوازن', xaxis_tickfont_size=14, yaxis=dict( title='الإجمالي (ريال)', titlefont_size=16, tickfont_size=14, ), legend=dict( x=0.01, y=0.99, bgcolor='rgba(255, 255, 255, 0.8)', bordercolor='rgba(0, 0, 0, 0.1)', borderwidth=1 ), barmode='group', bargap=0.15, bargroupgap=0.1, plot_bgcolor='rgba(240, 249, 255, 0.5)', margin=dict(t=50, b=50, l=20, r=20) ) st.plotly_chart(fig, use_container_width=True) with chart_tabs[1]: # رسم مقارنة # رسم مقارنة بين التسعيرين fig = go.Figure() # إضافة خط للتسعير المتوازن fig.add_trace(go.Scatter( x=chart_data['وصف البند'], y=chart_data['التسعير المتوازن'], name='التسعير المتوازن', mode='lines+markers', line=dict(color='rgb(55, 83, 109)', width=3), marker=dict(size=10, color='rgb(55, 83, 109)') )) # إضافة نقاط للتسعير غير المتوازن fig.add_trace(go.Scatter( x=chart_data['وصف البند'], y=chart_data['التسعير غير المتوازن'], name='التسعير غير المتوازن', mode='lines+markers', line=dict(color='rgb(26, 118, 255)', width=3), marker=dict( size=12, color=bar_colors, line=dict(width=2, color='white') ) )) # تحديثات التخطيط fig.update_layout( title='مقارنة مرئية بين استراتيجيات التسعير', xaxis_tickfont_size=14, yaxis=dict( title='القيمة الإجمالية (ريال)', titlefont_size=16, tickfont_size=14, gridcolor='rgba(200, 200, 200, 0.2)' ), legend=dict( x=0.01, y=0.99, bgcolor='rgba(255, 255, 255, 0.8)', bordercolor='rgba(0, 0, 0, 0.1)', borderwidth=1 ), plot_bgcolor='rgba(240, 249, 255, 0.5)', margin=dict(t=50, b=50, l=20, r=20) ) st.plotly_chart(fig, use_container_width=True) with chart_tabs[2]: # مخطط نسبة التغيير # مخطط للنسبة المئوية للتغيير fig = go.Figure() # إضافة أعمدة لنسبة التغيير مع ألوان مختلفة حسب القيمة fig.add_trace(go.Bar( x=chart_data['وصف البند'], y=chart_data['نسبة التغيير'], name='نسبة التغيير', marker_color=bar_colors, text=[f"{val:.1f}%" for val in chart_data['نسبة التغيير']], textposition='auto' )) # إضافة خط أفقي عند الصفر fig.add_shape( type="line", x0=-0.5, y0=0, x1=len(chart_data['وصف البند'])-0.5, y1=0, line=dict( color="black", width=2, dash="dash", ) ) # تحديثات التخطيط fig.update_layout( title='نسبة التغيير في أسعار البنود (%)', xaxis_tickfont_size=14, yaxis=dict( title='نسبة التغيير (%)', titlefont_size=16, tickfont_size=14, gridcolor='rgba(200, 200, 200, 0.2)', zeroline=True, zerolinecolor='black', zerolinewidth=2 ), plot_bgcolor='rgba(240, 249, 255, 0.5)', margin=dict(t=50, b=50, l=20, r=20) ) st.plotly_chart(fig, use_container_width=True) # إضافة جدول مع نسب التغيير st.markdown("#### جدول مفصل بنسب التغيير") # إعداد بيانات الجدول table_data = chart_data[['وصف البند', 'التسعير المتوازن', 'التسعير غير المتوازن', 'نسبة التغيير']] # تنسيق الجدول def highlight_change(row): change = row['نسبة التغيير'] if change > 5: return ['', '', '', 'background-color: rgba(31, 122, 140, 0.3); color: #1F7A8C; font-weight: bold;'] elif change > 0: return ['', '', '', 'background-color: rgba(129, 178, 154, 0.3); color: #2A9D8F; font-weight: bold;'] elif change > -5: return ['', '', '', 'background-color: rgba(242, 204, 143, 0.3); color: #BC6C25; font-weight: bold;'] else: return ['', '', '', 'background-color: rgba(224, 122, 95, 0.3); color: #AE2012; font-weight: bold;'] # تطبيق التنسيق styled_table = table_data.style.apply(highlight_change, axis=1).format({ 'التسعير المتوازن': '{:,.2f} ريال', 'التسعير غير المتوازن': '{:,.2f} ريال', 'نسبة التغيير': '{:+.1f}%' }) st.dataframe(styled_table, use_container_width=True) # 4. أزرار الحفظ والتصدير مع تصميم محسن st.markdown("
", unsafe_allow_html=True) st.markdown("

حفظ وتصدير البيانات

", unsafe_allow_html=True) st.markdown(""" """, unsafe_allow_html=True) col1, col2 = st.columns(2) with col1: # بطاقة حفظ التسعير st.markdown("""
💾
حفظ التسعير غير المتوازن
قم بحفظ التسعير الحالي في المشروع لاستخدامه لاحقاً في التقارير وفي إجمالي التسعير.
""", unsafe_allow_html=True) # زر حفظ التسعير غير المتوازن if st.button("حفظ التسعير غير المتوازن", type="primary", use_container_width=True): st.success("تم حفظ التسعير غير المتوازن بنجاح!") st.balloons() # إضافة تأثير احتفالي عند الحفظ with col2: # بطاقة تصدير التسعير st.markdown("""
📊
تصدير البيانات
قم بتصدير جدول التسعير الحالي بصيغة CSV لاستخدامه في برامج أخرى مثل Excel.
""", unsafe_allow_html=True) # زر تصدير التسعير export_button = st.button("تجهيز ملف للتصدير", use_container_width=True) if export_button: # تحويل البيانات إلى CSV csv = items.to_csv(index=False) st.success("تم تجهيز ملف التصدير بنجاح! يمكنك تنزيله الآن.") # تقديم البيانات للتنزيل st.download_button( label="تنزيل ملف CSV", data=csv, file_name="unbalanced_pricing.csv", mime="text/csv", use_container_width=True )