EGYADMIN commited on
Commit
36d0568
·
verified ·
1 Parent(s): 874bfcc

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +198 -221
app.py CHANGED
@@ -603,250 +603,147 @@ def home_page():
603
  legend_title_font_size=16
604
  )
605
  st.plotly_chart(fig, use_container_width=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
606
 
607
- with col2:
608
- # نسب النجاح المتوقعة للمناقصات النشطة
609
- active_tenders = st.session_state.tenders_df[st.session_state.tenders_df['الحالة'].isin(['جديدة', 'مفتوحة', 'قيد التقييم'])]
610
- active_tenders = active_tenders.sort_values('نسبة النجاح المتوقعة', ascending=False).head(8)
611
-
612
- fig = px.bar(
613
- active_tenders,
614
- x='نسبة النجاح المتوقعة',
615
- y='رقم المناقصة',
616
- title='نسب النجاح المتوقعة للمناقصات النشطة',
617
- color='نسبة النجاح المتوقعة',
618
- color_continuous_scale='Viridis',
619
- orientation='h'
620
- )
621
- fig.update_layout(
622
- title_font_size=20,
623
- title_font_family="Tajawal",
624
- title_x=0.5,
625
- yaxis={'categoryorder':'total ascending'}
626
- )
627
- st.plotly_chart(fig, use_container_width=True)
628
 
629
  with tab2:
 
 
 
 
630
  col1, col2 = st.columns(2)
631
 
632
  with col1:
633
- # توزيع قيم العقود
634
- fig = px.histogram(
635
- st.session_state.contracts_df,
636
- x='القيمة',
637
- nbins=10,
638
- title='توزيع قيم العقود',
639
- color_discrete_sequence=['#3498db']
640
- )
641
- fig.update_layout(
642
- title_font_size=20,
643
- title_font_family="Tajawal",
644
- title_x=0.5,
645
- xaxis_title="القيمة (ريال)",
646
- yaxis_title="عدد العقود"
647
- )
648
- st.plotly_chart(fig, use_container_width=True)
649
 
650
  with col2:
651
- # نسب المحتوى المحلي
652
- fig = px.scatter(
653
- st.session_state.contracts_df,
654
- x='القيمة',
655
- y='المحتوى المحلي',
656
- size='نسبة الإنجاز',
657
- color='مستوى المخاطر',
658
- hover_name='رقم العقد',
659
- title='نسب المحتوى المحلي للعقود',
660
- color_discrete_map={
661
- 'منخفض': '#2ecc71',
662
- 'متوسط': '#f39c12',
663
- 'عالي': '#e74c3c'
664
- }
665
- )
666
- fig.update_layout(
667
- title_font_size=20,
668
- title_font_family="Tajawal",
669
- title_x=0.5,
670
- xaxis_title="القيمة (ريال)",
671
- yaxis_title="نسبة المحتوى المحلي (%)"
672
- )
673
- st.plotly_chart(fig, use_container_width=True)
674
 
675
  with tab3:
676
- col1, col2 = st.columns(2)
677
 
678
- with col1:
679
- # مصفوفة المخاطر
680
- risk_matrix = pd.crosstab(
681
- st.session_state.risks_df['التأثير'],
682
- st.session_state.risks_df['الاحتمالية'],
683
- margins=False
684
- )
685
-
686
- # تحويل القيم إلى حرارية
687
- risk_severity = {
688
- ('منخفض', 'منخفضة'): 1,
689
- ('منخفض', 'متوسطة'): 2,
690
- ('منخفض', 'عالية'): 3,
691
- ('متوسط', 'منخفضة'): 2,
692
- ('متوسط', 'متوسطة'): 4,
693
- ('متوسط', 'عالية'): 6,
694
- ('عالي', 'منخفضة'): 3,
695
- ('عالي', 'متوسطة'): 6,
696
- ('عالي', 'عالية'): 9,
697
- ('حرج', 'منخفضة'): 4,
698
- ('حرج', 'متوسطة'): 8,
699
- ('حرج', 'عالية'): 12
700
- }
701
-
702
- # تحضير بيانات المصفوفة
703
- impact_order = ['منخفض', 'متوسط', 'عالي', 'حرج']
704
- probability_order = ['منخفضة', 'متوسطة', 'عالية']
705
-
706
- # إنشاء مصفوفة حرارية
707
- heat_values = []
708
- annotations = []
709
-
710
- for impact in impact_order:
711
- heat_row = []
712
- for prob in probability_order:
713
- try:
714
- value = risk_matrix.loc[impact, prob]
715
- except:
716
- value = 0
717
- heat_row.append(risk_severity.get((impact, prob), 0))
718
- annotations.append(dict(
719
- text=str(value),
720
- x=prob,
721
- y=impact,
722
- showarrow=False
723
- ))
724
- heat_values.append(heat_row)
725
-
726
- # إنشاء الرسم البياني
727
- fig = go.Figure(data=go.Heatmap(
728
- z=heat_values,
729
- x=probability_order,
730
- y=impact_order,
731
- colorscale=[
732
- [0.0, "#2ecc71"], # أخضر للمخاطر المنخفضة
733
- [0.33, "#f1c40f"], # أصفر للمخاطر المتوسطة
734
- [0.66, "#e67e22"], # برتقالي للمخاطر العالية
735
- [1.0, "#e74c3c"] # أحمر للمخاطر الحرجة
736
- ],
737
- showscale=False
738
- ))
739
-
740
- # إضافة النصوص
741
- for annotation in annotations:
742
- fig.add_annotation(annotation)
743
-
744
- fig.update_layout(
745
- title='مصفوفة المخاطر',
746
- title_font_size=20,
747
- title_font_family="Tajawal",
748
- title_x=0.5,
749
- xaxis_title="الاحتمالية",
750
- yaxis_title="التأثير"
751
  )
 
752
 
753
- st.plotly_chart(fig, use_container_width=True)
754
 
755
- with col2:
756
- # توزيع المخاطر حسب استراتيجية المعالجة
757
- treatment_counts = st.session_state.risks_df['المعالجة'].value_counts().reset_index()
758
- treatment_counts.columns = ['المعالجة', 'العدد']
759
-
760
- fig = px.bar(
761
- treatment_counts,
762
- x='المعالجة',
763
- y='العدد',
764
- title='استراتيجيات معالجة المخاطر',
765
- color='المعالجة',
766
- color_discrete_sequence=px.colors.qualitative.Pastel
767
- )
768
- fig.update_layout(
769
- title_font_size=20,
770
- title_font_family="Tajawal",
771
- title_x=0.5,
772
- xaxis_title="استراتيجية المعالجة",
773
- yaxis_title="عدد المخاطر"
774
- )
775
- st.plotly_chart(fig, use_container_width=True)
776
 
777
- # قسم المناقصات القادمة
778
- st.markdown("## 📅 المناقصات القادمة للإغلاق")
779
- upcoming_tenders = st.session_state.tenders_df[
780
- (pd.to_datetime(st.session_state.tenders_df['تاريخ الإغلاق']) > datetime.now()) &
781
- (pd.to_datetime(st.session_state.tenders_df['تاريخ الإغلاق']) <= datetime.now() + timedelta(days=14))
782
- ]
783
- upcoming_tenders = upcoming_tenders.sort_values('تاريخ الإغلاق')
784
 
785
- if not upcoming_tenders.empty:
786
- # عرض المناقصات في جدول
787
- upcoming_display = upcoming_tenders[['رقم المناقصة', 'العنوان', 'تاريخ الإغلاق', 'القيمة التقديرية', 'نسبة النجاح المتوقعة']]
788
- upcoming_display['أيام متبقية'] = (pd.to_datetime(upcoming_display['تاريخ الإغلاق']) - datetime.now()).dt.days
789
- upcoming_display['القيمة التقديرية'] = upcoming_display['القيمة التقديرية'].apply(lambda x: f"{x:,.0f} ريال")
790
- upcoming_display['نسبة النجاح المتوقعة'] = upcoming_display['نسبة النجاح المتوقعة'].apply(lambda x: f"{x}%")
791
-
792
- st.dataframe(
793
- upcoming_display,
794
- hide_index=True,
795
- use_container_width=True
796
- )
797
- else:
798
- st.info("لا توجد مناقصات ستغلق خلال الأسبوعين القادمين")
799
 
800
- # قسم تحليل الذكاء الاصطناعي
801
- st.markdown("## 🤖 تحليلات الذكاء الاصطناعي")
802
 
803
- col1, col2 = st.columns(2)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
804
 
805
  with col1:
806
- st.markdown("### التنبؤ بنجاح المناقصات")
807
- st.markdown("""
808
- تستخدم خوارزميات الذكاء الاصطناعي لتحليل البيانات التاريخية وتحديد العوامل المؤثرة في نجاح المناقصات.
809
- يمكن للنظام التنبؤ بنسب النجاح المتوقعة للمناقصات الجديدة بناءً على خصائصها ومتطلباتها.
810
- """)
811
-
812
- if st.button("تحليل مناقصة جديدة", key="analyze_new_tender"):
813
- with st.spinner("جاري تحليل المناقصة..."):
814
- time.sleep(2) # محاكاة وقت المعالجة
815
- st.success("تم التحليل بنجاح!")
816
- st.info("نسبة النجاح المتوقعة للمناقصة: 78.5%")
817
- st.markdown("""
818
- **العوامل المؤثرة في النتيجة:**
819
- - قدرة عالية على تلبية المتطلبات الفنية (+15%)
820
- - توافق المنتج مع المعايير المطلوبة (+12%)
821
- - خبرة سابقة مع نفس الجهة (+10%)
822
- - المنافسة المتوقعة قوية (-7%)
823
- """)
824
 
825
  with col2:
826
- st.markdown("### تحليل المتطلبات")
827
- st.markdown("""
828
- يقوم النظام بتحليل وثائق المتطلبات باستخدام تقنيات معالجة اللغة الطبيعية لاستخراج البنود المهمة والمخاطر المحتملة.
829
- يساعد هذا التحليل في تقييم مدى تعقيد المتطلبات وتحديد النقاط التي تحتاج إلى اهتمام خاص.
830
- """)
831
 
832
- uploaded_file = st.file_uploader("رفع ملف متطلبات للتحليل", type=['pdf', 'docx', 'txt'])
833
- if uploaded_file is not None:
834
- with st.spinner("جاري تحليل المتطلبات..."):
835
- time.sleep(3) # محاكاة وقت المعالجة
836
- st.success("تم تحليل المتطلبات بنجاح!")
837
-
838
- # عرض نتائج التحليل
839
- col1, col2 = st.columns(2)
840
- with col1:
841
- st.metric("عدد المتطلبات", "27")
842
- st.metric("المتطلبات الوظيفية", "19")
843
- st.metric("المتطلبات غير الوظيفية", "8")
844
-
845
- with col2:
846
- st.metric("درجة التعقيد", "متوسطة")
847
- st.metric("المخاطر المحتملة", "4")
848
- st.metric("البنود الغامضة", "3")
849
-
850
  def dashboard_page():
851
  """صفحة لوحة المؤشرات"""
852
  st.markdown("# 📊 لوحة المؤشرات")
@@ -1003,6 +900,86 @@ def dashboard_page():
1003
  st.dataframe(upcoming_display, hide_index=True, use_container_width=True)
1004
  else:
1005
  st.info("لا توجد مناقصات قادمة خلال الثلاثين يوماً القادمة.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1006
 
1007
  def procurement_page():
1008
  """صفحة المناقصات والعقود"""
 
603
  legend_title_font_size=16
604
  )
605
  st.plotly_chart(fig, use_container_width=True)
606
+
607
+ def settings_page():
608
+ """صفحة الإعدادات"""
609
+ st.markdown("# ⚙️ الإعدادات")
610
+
611
+ st.markdown("""
612
+ ## إعدادات النظام
613
+
614
+ يمكنك من خلال هذه الصفحة تخصيص إعدادات النظام بما يتناسب مع احتياجاتك.
615
+ """)
616
+
617
+ tab1, tab2, tab3 = st.tabs(["إعدادات عامة", "إعدادات الحساب", "الدعم والمساعدة"])
618
+
619
+ with tab1:
620
+ st.markdown("### الإعدادات العامة")
621
 
622
+ st.markdown("#### إعدادات اللغة")
623
+ lang = st.radio(
624
+ "اللغة الافتراضية للنظام:",
625
+ ["العربية", "English"],
626
+ index=0
627
+ )
628
+
629
+ st.markdown("#### إعدادات العرض")
630
+ theme = st.selectbox(
631
+ "السمة:",
632
+ ["السمة الافتراضية", "الوضع الداكن", "الوضع الفاتح"],
633
+ index=0
634
+ )
635
+
636
+ st.markdown("#### إعدادات الإشعارات")
637
+ st.checkbox("تفعيل الإشعارات داخل النظام", value=True)
638
+ st.checkbox("تفعيل الإشعارات عبر البريد الإلكتروني", value=True)
639
+
640
+ if st.button("حفظ الإعدادات العامة"):
641
+ st.success("تم حفظ الإعدادات بنجاح")
 
642
 
643
  with tab2:
644
+ st.markdown("### إعدادات الحساب")
645
+
646
+ st.markdown("#### البيانات الشخصية")
647
+
648
  col1, col2 = st.columns(2)
649
 
650
  with col1:
651
+ st.text_input("الاسم:", value="محمد أحمد")
652
+ st.text_input("البريد الإلكتروني:", value="mohammed@example.com")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
653
 
654
  with col2:
655
+ st.text_input("المسمى الوظيفي:", value="مدير مشاريع")
656
+ st.text_input("رقم الهاتف:", value="0555555555")
657
+
658
+ st.markdown("#### تغيير كلمة المرور")
659
+ st.password_input("كلمة المرور الحالية:")
660
+ st.password_input("كلمة المرور الجديدة:")
661
+ st.password_input("تأكيد كلمة المرور الجديدة:")
662
+
663
+ if st.button("تحديث البيانات"):
664
+ st.success("تم تحديث البيانات بنجاح")
665
+
666
+ st.markdown("#### إعدادات الأمان")
667
+ st.checkbox("تفعيل المصادقة الثنائية", value=False)
 
 
 
 
 
 
 
 
 
 
668
 
669
  with tab3:
670
+ st.markdown("### الدعم والمساعدة")
671
 
672
+ st.markdown("""
673
+ #### كيفية استخدام النظام
674
+
675
+ يوفر النظام مجموعة من الأدوات والتحليلات التي تساعدك في إدارة المناقصات والعقود وتحليل المخاطر.
676
+ يمكنك الاطلاع على دليل الاستخدام للحصول على شرح تفصيلي لكافة الوظائف.
677
+ """)
678
+
679
+ st.download_button(
680
+ "تحميل دليل الاستخدام",
681
+ data="محتوى دليل الاستخدام",
682
+ file_name="user_guide.pdf",
683
+ mime="application/pdf"
684
+ )
685
+
686
+ st.markdown("#### التواصل مع الدعم الفني")
687
+
688
+ with st.form("support_form"):
689
+ st.text_input("العنوان:")
690
+ st.text_area("الرسالة:")
691
+ st.selectbox(
692
+ "نوع المشكلة:",
693
+ ["استفسار عام", "مشكلة فنية", "اقتراح تحسين", "أخرى"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
694
  )
695
+ st.file_uploader("إرفاق ملف (اختياري):")
696
 
697
+ submit_support = st.form_submit_button("إرسال")
698
 
699
+ if submit_support:
700
+ st.success("تم إرسال رسالتك بنجاح، سيتم التواصل معك قريباً")
701
+
702
+ def about_page():
703
+ """صفحة حول النظام"""
704
+ st.markdown("# ℹ️ حول النظام")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
705
 
706
+ st.markdown("""
707
+ ## نظام إدارة المناقصات والعقود
 
 
 
 
 
708
 
709
+ ### نبذة عن النظام
 
 
 
 
 
 
 
 
 
 
 
 
 
710
 
711
+ نظام متكامل لإدارة المناقصات والعقود يعتمد على أحدث التقنيات والذكاء الاصطناعي لتحسين كفاءة العمليات وزيادة فرص النجاح.
712
+ يوفر النظام مجموعة من الأدوات والتحليلات التي تساعد في اتخاذ القرارات وإدارة المخاطر وتحسين المحتوى المحلي.
713
 
714
+ ### المميزات الرئيسية
715
+
716
+ * إدارة المناقصات والفرص التجارية
717
+ * تحليل وإدارة المخاطر
718
+ * قياس وتحسين المحتوى المحلي
719
+ * توقع احتمالية النجاح في المناقصات
720
+ * إدارة وتحليل العقود
721
+ * تخطيط سلسلة التوريد
722
+ * تحليل المتطلبات
723
+
724
+ ### فريق التطوير
725
+
726
+ تم تطوير هذا النظام بواسطة فريق من الخبراء المتخصصين في مجالات البرمجة والذكاء الاصطناعي وإدارة المشاريع والعقود.
727
+
728
+ ### التواصل
729
+
730
+ للمزيد من المعلومات أو الاستفسارات، يرجى التواصل عبر:
731
+
732
+ * البريد الإلكتروني: [email protected]
733
+ * رقم الهاتف: 0123456789
734
+ """)
735
+
736
+ col1, col2, col3 = st.columns(3)
737
 
738
  with col1:
739
+ st.info("إصدار النظام: 1.0.0")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
740
 
741
  with col2:
742
+ st.info("تاريخ الإطلاق: 2024/03/15")
743
+
744
+ with col3:
745
+ st.info("آخر تحديث: 2024/03/18")
 
746
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
747
  def dashboard_page():
748
  """صفحة لوحة المؤشرات"""
749
  st.markdown("# 📊 لوحة المؤشرات")
 
900
  st.dataframe(upcoming_display, hide_index=True, use_container_width=True)
901
  else:
902
  st.info("لا توجد مناقصات قادمة خلال الثلاثين يوماً القادمة.")
903
+
904
+ def procurement_page():
905
+ """صفحة المناقصات والعقود"""
906
+ st.markdown("# 📑 المناقصات والعقود")
907
+
908
+ tab1, tab2 = st.tabs(["المناقصات", "العقود"])
909
+
910
+ with tab1:
911
+ st.markdown("## إدارة المناقصات")
912
+
913
+ # أزرار الإجراءات
914
+ col1, col2, col3, col4 = st.columns(4)
915
+ with col1:
916
+ if st.button("🆕 إضافة مناقصة جديدة"):
917
+ st.session_state.show_add_tender = True
918
+
919
+ with col2:
920
+ st.button("🔍 بحث متقدم")
921
+
922
+ with col3:
923
+ st.button("📊 تصدير التقرير")
924
+
925
+ with col4:
926
+ st.button("🔄 تحديث البيانات")
927
+
928
+ # عرض جدول المناقصات
929
+ st.markdown("### قائمة المناقصات")
930
+
931
+ # فلاتر
932
+ col1, col2, col3 = st.columns(3)
933
+ with col1:
934
+ status_filter = st.multiselect(
935
+ "الحالة:",
936
+ ["الكل"] + list(st.session_state.tenders_df['الحالة'].unique()),
937
+ default=["الكل"]
938
+ )
939
+
940
+ with col2:
941
+ date_range = st.date_input(
942
+ "تاريخ الإعلان:",
943
+ value=(
944
+ (datetime.now() - timedelta(days=60)).date(),
945
+ datetime.now().date()
946
+ )
947
+ )
948
+
949
+ with col3:
950
+ min_value, max_value = st.slider(
951
+ "القيمة التقديرية (ريال):",
952
+ 0,
953
+ int(st.session_state.tenders_df['القيمة التقديرية'].max()),
954
+ (0, int(st.session_state.tenders_df['القيمة التقديرية'].max())),
955
+ step=100000
956
+ )
957
+
958
+ # تطبيق الفلاتر
959
+ filtered_df = st.session_state.tenders_df.copy()
960
+
961
+ # فلتر الحالة
962
+ if "الكل" not in status_filter:
963
+ filtered_df = filtered_df[filtered_df['الحالة'].isin(status_filter)]
964
+
965
+ # فلتر التاريخ
966
+ filtered_df = filtered_df[
967
+ (pd.to_datetime(filtered_df['تاريخ الإعلان']) >= pd.Timestamp(date_range[0])) &
968
+ (pd.to_datetime(filtered_df['تاريخ الإعلان']) <= pd.Timestamp(date_range[1]))
969
+ ]
970
+
971
+ # فلتر القيمة
972
+ filtered_df = filtered_df[
973
+ (filtered_df['القيمة التقد��رية'] >= min_value) &
974
+ (filtered_df['القيمة التقديرية'] <= max_value)
975
+ ]
976
+
977
+ # عرض الجدول
978
+ st.dataframe(
979
+ filtered_df,
980
+ use_container_width=True,
981
+ hide_index=True
982
+ )
983
 
984
  def procurement_page():
985
  """صفحة المناقصات والعقود"""