|
"""
|
|
وحدة إدارة المشاريع - نظام تحليل المناقصات
|
|
"""
|
|
|
|
import streamlit as st
|
|
import pandas as pd
|
|
import numpy as np
|
|
from datetime import datetime, timedelta
|
|
import os
|
|
import time
|
|
import io
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
|
|
sys.path.append(str(Path(__file__).parent.parent))
|
|
|
|
|
|
from styling.enhanced_ui import UIEnhancer
|
|
|
|
class ProjectsApp:
|
|
"""وحدة إدارة المشاريع"""
|
|
|
|
def __init__(self):
|
|
"""تهيئة وحدة إدارة المشاريع"""
|
|
self.ui = UIEnhancer(page_title="إدارة المشاريع - نظام تحليل المناقصات", page_icon="📋")
|
|
self.ui.apply_theme_colors()
|
|
|
|
|
|
if 'projects' not in st.session_state:
|
|
st.session_state.projects = self._generate_sample_projects()
|
|
|
|
def run(self):
|
|
"""تشغيل وحدة إدارة المشاريع"""
|
|
|
|
menu_items = [
|
|
{"name": "لوحة المعلومات", "icon": "house"},
|
|
{"name": "المناقصات والعقود", "icon": "file-text"},
|
|
{"name": "تحليل المستندات", "icon": "file-earmark-text"},
|
|
{"name": "نظام التسعير", "icon": "calculator"},
|
|
{"name": "حاسبة تكاليف البناء", "icon": "building"},
|
|
{"name": "الموارد والتكاليف", "icon": "people"},
|
|
{"name": "تحليل المخاطر", "icon": "exclamation-triangle"},
|
|
{"name": "إدارة المشاريع", "icon": "kanban"},
|
|
{"name": "الخرائط والمواقع", "icon": "geo-alt"},
|
|
{"name": "الجدول الزمني", "icon": "calendar3"},
|
|
{"name": "الإشعارات", "icon": "bell"},
|
|
{"name": "مقارنة المستندات", "icon": "files"},
|
|
{"name": "الترجمة", "icon": "translate"},
|
|
{"name": "المساعد الذكي", "icon": "robot"},
|
|
{"name": "التقارير", "icon": "bar-chart"},
|
|
{"name": "الإعدادات", "icon": "gear"}
|
|
]
|
|
|
|
|
|
selected = self.ui.create_sidebar(menu_items)
|
|
|
|
|
|
self.ui.create_header("إدارة المشاريع", "إدارة ومتابعة المشاريع والمناقصات")
|
|
|
|
|
|
tabs = st.tabs([
|
|
"قائمة المشاريع",
|
|
"إضافة مشروع جديد",
|
|
"تفاصيل المشروع",
|
|
"متابعة المشاريع"
|
|
])
|
|
|
|
with tabs[0]:
|
|
self._render_projects_list_tab()
|
|
|
|
with tabs[1]:
|
|
self._render_add_project_tab()
|
|
|
|
with tabs[2]:
|
|
self._render_project_details_tab()
|
|
|
|
with tabs[3]:
|
|
self._render_projects_tracking_tab()
|
|
|
|
def _render_projects_list_tab(self):
|
|
"""عرض تبويب قائمة المشاريع"""
|
|
|
|
st.markdown("### قائمة المشاريع")
|
|
|
|
|
|
col1, col2, col3 = st.columns(3)
|
|
|
|
with col1:
|
|
search_term = st.text_input("البحث في المشاريع", key="project_search")
|
|
|
|
with col2:
|
|
status_filter = st.multiselect(
|
|
"حالة المشروع",
|
|
["جديد", "قيد التسعير", "تم التقديم", "تمت الترسية", "قيد التنفيذ", "منتهي", "ملغي"],
|
|
default=["جديد", "قيد التسعير", "تم التقديم"],
|
|
key="project_status_filter"
|
|
)
|
|
|
|
with col3:
|
|
client_filter = st.multiselect(
|
|
"الجهة المالكة",
|
|
list(set([p['client'] for p in st.session_state.projects])),
|
|
key="project_client_filter"
|
|
)
|
|
|
|
|
|
filtered_projects = st.session_state.projects
|
|
|
|
if search_term:
|
|
filtered_projects = [p for p in filtered_projects if search_term.lower() in p['name'].lower() or search_term in p['number']]
|
|
|
|
if status_filter:
|
|
filtered_projects = [p for p in filtered_projects if p['status'] in status_filter]
|
|
|
|
if client_filter:
|
|
filtered_projects = [p for p in filtered_projects if p['client'] in client_filter]
|
|
|
|
|
|
if filtered_projects:
|
|
projects_df = pd.DataFrame(filtered_projects)
|
|
|
|
|
|
display_columns = [
|
|
'name', 'number', 'client', 'location', 'status',
|
|
'submission_date', 'tender_type', 'created_at'
|
|
]
|
|
|
|
|
|
column_names = {
|
|
'name': 'اسم المشروع',
|
|
'number': 'رقم المناقصة',
|
|
'client': 'الجهة المالكة',
|
|
'location': 'الموقع',
|
|
'status': 'الحالة',
|
|
'submission_date': 'تاريخ التقديم',
|
|
'tender_type': 'نوع المناقصة',
|
|
'created_at': 'تاريخ الإنشاء'
|
|
}
|
|
|
|
display_df = projects_df[display_columns].rename(columns=column_names)
|
|
|
|
|
|
date_columns = ['تاريخ التقديم', 'تاريخ الإنشاء']
|
|
for col in date_columns:
|
|
if col in display_df.columns:
|
|
display_df[col] = pd.to_datetime(display_df[col]).dt.strftime('%Y-%m-%d')
|
|
|
|
|
|
st.dataframe(display_df, use_container_width=True, hide_index=True)
|
|
|
|
|
|
if st.button("تصدير المشاريع إلى Excel"):
|
|
|
|
st.success("تم تصدير المشاريع بنجاح!")
|
|
else:
|
|
st.info("لا توجد مشاريع تطابق معايير البحث.")
|
|
|
|
def _render_add_project_tab(self):
|
|
"""عرض تبويب إضافة مشروع جديد"""
|
|
|
|
st.markdown("### إضافة مشروع جديد")
|
|
|
|
|
|
with st.form("new_project_form"):
|
|
col1, col2 = st.columns(2)
|
|
|
|
with col1:
|
|
project_name = st.text_input("اسم المشروع", key="new_project_name")
|
|
client = st.text_input("الجهة المالكة", key="new_project_client")
|
|
location = st.text_input("الموقع", key="new_project_location")
|
|
tender_type = st.selectbox(
|
|
"نوع المناقصة",
|
|
["عامة", "خاصة", "أمر مباشر"],
|
|
key="new_project_tender_type"
|
|
)
|
|
|
|
with col2:
|
|
tender_number = st.text_input("رقم المناقصة", key="new_project_number")
|
|
submission_date = st.date_input("تاريخ التقديم", key="new_project_submission_date")
|
|
pricing_method = st.selectbox(
|
|
"طريقة التسعير",
|
|
["قياسي", "غير متزن", "تنافسي", "موجه بالربحية"],
|
|
key="new_project_pricing_method"
|
|
)
|
|
status = st.selectbox(
|
|
"حالة المشروع",
|
|
["جديد", "قيد التسعير", "تم التقديم", "تمت الترسية", "قيد التنفيذ", "منتهي", "ملغي"],
|
|
index=0,
|
|
key="new_project_status"
|
|
)
|
|
|
|
description = st.text_area("وصف المشروع", key="new_project_description")
|
|
|
|
submitted = st.form_submit_button("إضافة المشروع")
|
|
|
|
if submitted:
|
|
|
|
if not project_name or not tender_number or not client:
|
|
st.error("يرجى تعبئة جميع الحقول الإلزامية (اسم المشروع، رقم المناقصة، الجهة المالكة).")
|
|
else:
|
|
|
|
new_project = {
|
|
'id': len(st.session_state.projects) + 1,
|
|
'name': project_name,
|
|
'number': tender_number,
|
|
'client': client,
|
|
'location': location,
|
|
'description': description,
|
|
'status': status,
|
|
'tender_type': tender_type,
|
|
'pricing_method': pricing_method,
|
|
'submission_date': submission_date,
|
|
'created_at': datetime.now(),
|
|
'created_by_id': 1
|
|
}
|
|
|
|
|
|
st.session_state.projects.append(new_project)
|
|
|
|
|
|
st.success(f"تم إضافة المشروع [{project_name}] بنجاح!")
|
|
|
|
|
|
st.session_state.current_project = new_project
|
|
|
|
def _render_project_details_tab(self):
|
|
"""عرض تبويب تفاصيل المشروع"""
|
|
|
|
st.markdown("### تفاصيل المشروع")
|
|
|
|
|
|
if 'current_project' not in st.session_state or st.session_state.current_project is None:
|
|
|
|
project_names = [p['name'] for p in st.session_state.projects]
|
|
selected_project_name = st.selectbox("اختر المشروع", project_names)
|
|
|
|
if selected_project_name:
|
|
selected_project = next((p for p in st.session_state.projects if p['name'] == selected_project_name), None)
|
|
if selected_project:
|
|
st.session_state.current_project = selected_project
|
|
else:
|
|
st.warning("لم يتم العثور على المشروع المحدد.")
|
|
return
|
|
else:
|
|
st.info("يرجى اختيار مشروع لعرض تفاصيله.")
|
|
return
|
|
|
|
|
|
project = st.session_state.current_project
|
|
|
|
|
|
col1, col2, col3 = st.columns(3)
|
|
|
|
with col1:
|
|
st.markdown(f"**اسم المشروع**: {project['name']}")
|
|
st.markdown(f"**رقم المناقصة**: {project['number']}")
|
|
st.markdown(f"**الجهة المالكة**: {project['client']}")
|
|
|
|
with col2:
|
|
st.markdown(f"**الموقع**: {project['location']}")
|
|
st.markdown(f"**نوع المناقصة**: {project['tender_type']}")
|
|
st.markdown(f"**حالة المشروع**: {project['status']}")
|
|
|
|
with col3:
|
|
st.markdown(f"**طريقة التسعير**: {project['pricing_method']}")
|
|
st.markdown(f"**تاريخ التقديم**: {project['submission_date'].strftime('%Y-%m-%d') if isinstance(project['submission_date'], datetime) else project['submission_date']}")
|
|
st.markdown(f"**تاريخ الإنشاء**: {project['created_at'].strftime('%Y-%m-%d') if isinstance(project['created_at'], datetime) else project['created_at']}")
|
|
|
|
|
|
st.markdown("#### وصف المشروع")
|
|
st.text_area("", value=project.get('description', ''), disabled=True, height=100)
|
|
|
|
|
|
st.markdown("#### مستندات المشروع")
|
|
|
|
if 'documents' in project and project['documents']:
|
|
docs_df = pd.DataFrame(project['documents'])
|
|
st.dataframe(docs_df, use_container_width=True, hide_index=True)
|
|
else:
|
|
st.info("لا توجد مستندات مرتبطة بهذا المشروع حاليًا.")
|
|
|
|
|
|
if st.button("إضافة مستندات"):
|
|
st.session_state.upload_documents = True
|
|
|
|
|
|
if 'upload_documents' in st.session_state and st.session_state.upload_documents:
|
|
st.markdown("#### تحميل مستندات جديدة")
|
|
|
|
uploaded_file = st.file_uploader("اختر ملفًا", type=['pdf', 'docx', 'xlsx', 'png', 'jpg', 'dwg'])
|
|
doc_type = st.selectbox("نوع المستند", ["كراسة شروط", "عقد", "مخططات", "جدول كميات", "مواصفات فنية", "تعديلات وملاحق"])
|
|
|
|
if uploaded_file and st.button("تحميل المستند"):
|
|
|
|
with st.spinner("جاري تحميل المستند..."):
|
|
time.sleep(2)
|
|
|
|
|
|
new_document = {
|
|
'filename': uploaded_file.name,
|
|
'type': doc_type,
|
|
'upload_date': datetime.now().strftime('%Y-%m-%d'),
|
|
'size': f"{uploaded_file.size / 1024:.1f} KB"
|
|
}
|
|
|
|
|
|
if 'documents' not in project:
|
|
project['documents'] = []
|
|
|
|
project['documents'].append(new_document)
|
|
|
|
st.success(f"تم تحميل المستند [{uploaded_file.name}] بنجاح!")
|
|
st.session_state.upload_documents = False
|
|
st.experimental_rerun()
|
|
|
|
|
|
st.markdown("#### بنود وكميات المشروع")
|
|
|
|
if 'items' in project and project['items']:
|
|
items_df = pd.DataFrame(project['items'])
|
|
st.dataframe(items_df, use_container_width=True, hide_index=True)
|
|
|
|
|
|
if st.button("تحويل البنود إلى وحدة التسعير"):
|
|
if 'manual_items' not in st.session_state:
|
|
st.session_state.manual_items = pd.DataFrame()
|
|
|
|
st.session_state.manual_items = items_df.copy()
|
|
st.success("تم تحويل البنود إلى وحدة التسعير بنجاح!")
|
|
else:
|
|
st.info("لا توجد بنود وكميات لهذا المشروع حاليًا.")
|
|
|
|
|
|
if st.button("استيراد البنود من تحليل المستندات"):
|
|
st.warning("ميزة استيراد البنود من تحليل المستندات قيد التطوير.")
|
|
|
|
|
|
col1, col2, col3 = st.columns(3)
|
|
|
|
with col1:
|
|
if st.button("تعديل المشروع"):
|
|
st.session_state.edit_project = True
|
|
st.experimental_rerun()
|
|
|
|
with col2:
|
|
if st.button("تصدير بيانات المشروع"):
|
|
st.success("تم تصدير بيانات المشروع بنجاح!")
|
|
|
|
with col3:
|
|
if st.button("إرسال للاعتماد"):
|
|
st.success("تم إرسال المشروع للاعتماد بنجاح!")
|
|
|
|
|
|
if 'edit_project' in st.session_state and st.session_state.edit_project:
|
|
st.markdown("#### تعديل المشروع")
|
|
|
|
with st.form("edit_project_form"):
|
|
col1, col2 = st.columns(2)
|
|
|
|
with col1:
|
|
project_name = st.text_input("اسم المشروع", value=project['name'])
|
|
client = st.text_input("الجهة المالكة", value=project['client'])
|
|
location = st.text_input("الموقع", value=project['location'])
|
|
tender_type = st.selectbox(
|
|
"نوع المناقصة",
|
|
["عامة", "خاصة", "أمر مباشر"],
|
|
index=["عامة", "خاصة", "أمر مباشر"].index(project['tender_type'])
|
|
)
|
|
|
|
with col2:
|
|
tender_number = st.text_input("رقم المناقصة", value=project['number'])
|
|
submission_date = st.date_input(
|
|
"تاريخ التقديم",
|
|
value=datetime.strptime(project['submission_date'], "%Y-%m-%d") if isinstance(project['submission_date'], str) else project['submission_date']
|
|
)
|
|
pricing_method = st.selectbox(
|
|
"طريقة التسعير",
|
|
["قياسي", "غير متزن", "تنافسي", "موجه بالربحية"],
|
|
index=["قياسي", "غير متزن", "تنافسي", "موجه بالربحية"].index(project['pricing_method'])
|
|
)
|
|
status = st.selectbox(
|
|
"حالة المشروع",
|
|
["جديد", "قيد التسعير", "تم التقديم", "تمت الترسية", "قيد التنفيذ", "منتهي", "ملغي"],
|
|
index=["جديد", "قيد التسعير", "تم التقديم", "تمت الترسية", "قيد التنفيذ", "منتهي", "ملغي"].index(project['status'])
|
|
)
|
|
|
|
description = st.text_area("وصف المشروع", value=project.get('description', ''))
|
|
|
|
col1, col2 = st.columns(2)
|
|
|
|
with col1:
|
|
submit = st.form_submit_button("حفظ التعديلات")
|
|
|
|
with col2:
|
|
cancel = st.form_submit_button("إلغاء")
|
|
|
|
if submit:
|
|
|
|
project['name'] = project_name
|
|
project['number'] = tender_number
|
|
project['client'] = client
|
|
project['location'] = location
|
|
project['description'] = description
|
|
project['status'] = status
|
|
project['tender_type'] = tender_type
|
|
project['pricing_method'] = pricing_method
|
|
project['submission_date'] = submission_date
|
|
|
|
st.success("تم تحديث بيانات المشروع بنجاح!")
|
|
st.session_state.edit_project = False
|
|
st.experimental_rerun()
|
|
|
|
elif cancel:
|
|
st.session_state.edit_project = False
|
|
st.experimental_rerun()
|
|
|
|
def _render_projects_tracking_tab(self):
|
|
"""عرض تبويب متابعة المشاريع"""
|
|
|
|
st.markdown("### متابعة المشاريع")
|
|
|
|
|
|
col1, col2, col3, col4 = st.columns(4)
|
|
|
|
projects = st.session_state.projects
|
|
|
|
with col1:
|
|
total_projects = len(projects)
|
|
self.ui.create_metric_card("إجمالي المشاريع", str(total_projects), None, self.ui.COLORS['primary'])
|
|
|
|
with col2:
|
|
active_projects = len([p for p in projects if p['status'] in ["قيد التسعير", "تم التقديم", "تمت الترسية", "قيد التنفيذ"]])
|
|
self.ui.create_metric_card("المشاريع النشطة", str(active_projects), None, self.ui.COLORS['success'])
|
|
|
|
with col3:
|
|
pending_submission = len([p for p in projects if p['status'] in ["جديد", "قيد التسعير"]])
|
|
self.ui.create_metric_card("مشاريع قيد التسعير", str(pending_submission), None, self.ui.COLORS['warning'])
|
|
|
|
with col4:
|
|
completed_projects = len([p for p in projects if p['status'] in ["منتهي"]])
|
|
self.ui.create_metric_card("المشاريع المنتهية", str(completed_projects), None, self.ui.COLORS['info'])
|
|
|
|
|
|
st.markdown("#### توزيع المشاريع حسب الحالة")
|
|
|
|
status_counts = {}
|
|
for p in projects:
|
|
status = p['status']
|
|
status_counts[status] = status_counts.get(status, 0) + 1
|
|
|
|
status_df = pd.DataFrame({
|
|
'الحالة': list(status_counts.keys()),
|
|
'عدد المشاريع': list(status_counts.values())
|
|
})
|
|
|
|
st.bar_chart(status_df.set_index('الحالة'))
|
|
|
|
|
|
st.markdown("#### المشاريع قيد المتابعة")
|
|
|
|
|
|
active_projects_list = [p for p in projects if p['status'] in ["قيد التسعير", "تم التقديم", "تمت الترسية", "قيد التنفيذ"]]
|
|
|
|
if active_projects_list:
|
|
|
|
for p in active_projects_list:
|
|
if isinstance(p['submission_date'], str):
|
|
p['submission_date'] = datetime.strptime(p['submission_date'], "%Y-%m-%d")
|
|
|
|
|
|
active_projects_list.sort(key=lambda x: x['submission_date'])
|
|
|
|
|
|
active_df = pd.DataFrame(active_projects_list)
|
|
|
|
|
|
display_columns = [
|
|
'name', 'number', 'client', 'status',
|
|
'submission_date', 'tender_type'
|
|
]
|
|
|
|
|
|
column_names = {
|
|
'name': 'اسم المشروع',
|
|
'number': 'رقم المناقصة',
|
|
'client': 'الجهة المالكة',
|
|
'status': 'الحالة',
|
|
'submission_date': 'تاريخ التقديم',
|
|
'tender_type': 'نوع المناقصة'
|
|
}
|
|
|
|
|
|
display_df = active_df[display_columns].rename(columns=column_names)
|
|
display_df['تاريخ التقديم'] = pd.to_datetime(display_df['تاريخ التقديم']).dt.strftime('%Y-%m-%d')
|
|
|
|
|
|
st.dataframe(display_df, use_container_width=True, hide_index=True)
|
|
else:
|
|
st.info("لا توجد مشاريع نشطة حاليًا.")
|
|
|
|
|
|
st.markdown("#### المواعيد المقبلة")
|
|
|
|
upcoming_events = []
|
|
today = datetime.now().date()
|
|
|
|
for p in projects:
|
|
submission_date = p['submission_date']
|
|
if isinstance(submission_date, str):
|
|
submission_date = datetime.strptime(submission_date, "%Y-%m-%d").date()
|
|
elif isinstance(submission_date, datetime):
|
|
submission_date = submission_date.date()
|
|
|
|
|
|
if today <= submission_date <= today + timedelta(days=14) and p['status'] in ["قيد التسعير"]:
|
|
days_left = (submission_date - today).days
|
|
upcoming_events.append({
|
|
'المشروع': p['name'],
|
|
'الحدث': 'موعد تقديم المناقصة',
|
|
'التاريخ': submission_date.strftime('%Y-%m-%d'),
|
|
'الأيام المتبقية': days_left
|
|
})
|
|
|
|
if upcoming_events:
|
|
events_df = pd.DataFrame(upcoming_events)
|
|
st.dataframe(events_df, use_container_width=True, hide_index=True)
|
|
else:
|
|
st.info("لا توجد مواعيد قريبة.")
|
|
|
|
def _generate_sample_projects(self):
|
|
"""توليد بيانات افتراضية للمشاريع"""
|
|
|
|
projects = [
|
|
{
|
|
'id': 1,
|
|
'name': "إنشاء مبنى مستشفى الولادة والأطفال بمنطقة الشرقية",
|
|
'number': "SHPD-2025-001",
|
|
'client': "وزارة الصحة",
|
|
'location': "الدمام، المنطقة الشرقية",
|
|
'description': "يشمل المشروع إنشاء وتجهيز مبنى مستشفى الولادة والأطفال بسعة 300 سرير، ويتكون المبنى من 4 طوابق بمساحة إجمالية 15,000 متر مربع.",
|
|
'status': "قيد التسعير",
|
|
'tender_type': "عامة",
|
|
'pricing_method': "قياسي",
|
|
'submission_date': (datetime.now() + timedelta(days=5)),
|
|
'created_at': datetime.now() - timedelta(days=10),
|
|
'created_by_id': 1,
|
|
'documents': [
|
|
{
|
|
'filename': "كراسة الشروط والمواصفات.pdf",
|
|
'type': "كراسة شروط",
|
|
'upload_date': (datetime.now() - timedelta(days=9)).strftime('%Y-%m-%d'),
|
|
'size': "5.2 MB"
|
|
},
|
|
{
|
|
'filename': "المخططات الهندسية.dwg",
|
|
'type': "مخططات",
|
|
'upload_date': (datetime.now() - timedelta(days=8)).strftime('%Y-%m-%d'),
|
|
'size': "25.7 MB"
|
|
},
|
|
{
|
|
'filename': "جدول الكميات.xlsx",
|
|
'type': "جدول كميات",
|
|
'upload_date': (datetime.now() - timedelta(days=7)).strftime('%Y-%m-%d'),
|
|
'size': "1.8 MB"
|
|
}
|
|
],
|
|
'items': [
|
|
{
|
|
'رقم البند': "A1",
|
|
'وصف البند': "أعمال الحفر والردم",
|
|
'الوحدة': "م3",
|
|
'الكمية': 12500
|
|
},
|
|
{
|
|
'رقم البند': "A2",
|
|
'وصف البند': "أعمال الخرسانة المسلحة للأساسات",
|
|
'الوحدة': "م3",
|
|
'الكمية': 3500
|
|
},
|
|
{
|
|
'رقم البند': "A3",
|
|
'وصف البند': "أعمال حديد التسليح",
|
|
'الوحدة': "طن",
|
|
'الكمية': 450
|
|
}
|
|
]
|
|
},
|
|
{
|
|
'id': 2,
|
|
'name': "صيانة وتطوير طريق الملك عبدالله",
|
|
'number': "MOT-2025-042",
|
|
'client': "وزارة النقل",
|
|
'location': "الرياض، المنطقة الوسطى",
|
|
'description': "صيانة وتطوير طريق الملك عبدالله بطول 25 كم، ويشمل المشروع إعادة الرصف وتحسين الإنارة وتركيب اللوحات الإرشادية.",
|
|
'status': "تم التقديم",
|
|
'tender_type': "عامة",
|
|
'pricing_method': "غير متزن",
|
|
'submission_date': (datetime.now() - timedelta(days=15)),
|
|
'created_at': datetime.now() - timedelta(days=45),
|
|
'created_by_id': 1
|
|
},
|
|
{
|
|
'id': 3,
|
|
'name': "إنشاء محطة معالجة مياه الصرف الصحي",
|
|
'number': "SWPC-2025-007",
|
|
'client': "شركة المياه الوطنية",
|
|
'location': "جدة، المنطقة الغربية",
|
|
'description': "إنشاء محطة معالجة مياه الصرف الصحي بطاقة استيعابية 50,000 م3/يوم، مع جميع الأعمال المدنية والكهروميكانيكية.",
|
|
'status': "تمت الترسية",
|
|
'tender_type': "عامة",
|
|
'pricing_method': "قياسي",
|
|
'submission_date': (datetime.now() - timedelta(days=90)),
|
|
'created_at': datetime.now() - timedelta(days=120),
|
|
'created_by_id': 1
|
|
},
|
|
{
|
|
'id': 4,
|
|
'name': "إنشاء منتزه الملك سلمان",
|
|
'number': "RAM-2025-015",
|
|
'client': "أمانة منطقة الرياض",
|
|
'location': "الرياض، المنطقة الوسطى",
|
|
'description': "إنشاء منتزه الملك سلمان على مساحة 500,000 متر مربع، ويشمل المشروع أعمال التشجير والتنسيق والمسطحات المائية والمباني الخدمية.",
|
|
'status': "قيد التنفيذ",
|
|
'tender_type': "عامة",
|
|
'pricing_method': "قياسي",
|
|
'submission_date': (datetime.now() - timedelta(days=180)),
|
|
'created_at': datetime.now() - timedelta(days=210),
|
|
'created_by_id': 1
|
|
},
|
|
{
|
|
'id': 5,
|
|
'name': "إنشاء مبنى مختبرات كلية العلوم",
|
|
'number': "KSU-2025-032",
|
|
'client': "جامعة الملك سعود",
|
|
'location': "الرياض، المنطقة الوسطى",
|
|
'description': "إنشاء مبنى المختبرات الجديد لكلية العلوم بمساحة 8,000 متر مربع، ويتكون من 3 طوابق ويشمل تجهيز المعامل والمختبرات العلمية.",
|
|
'status': "جديد",
|
|
'tender_type': "خاصة",
|
|
'pricing_method': "تنافسي",
|
|
'submission_date': (datetime.now() + timedelta(days=10)),
|
|
'created_at': datetime.now() - timedelta(days=5),
|
|
'created_by_id': 1
|
|
},
|
|
{
|
|
'id': 6,
|
|
'name': "توريد وتركيب أنظمة الطاقة الشمسية",
|
|
'number': "SEC-2025-098",
|
|
'client': "الشركة السعودية للكهرباء",
|
|
'location': "تبوك، المنطقة الشمالية",
|
|
'description': "توريد وتركيب أنظمة الطاقة الشمسية بقدرة 5 ميجاوات، مع جميع الأعمال المدنية والكهربائية.",
|
|
'status': "جديد",
|
|
'tender_type': "عامة",
|
|
'pricing_method': "قياسي",
|
|
'submission_date': (datetime.now() + timedelta(days=20)),
|
|
'created_at': datetime.now() - timedelta(days=2),
|
|
'created_by_id': 1
|
|
}
|
|
]
|
|
|
|
return projects
|
|
|
|
|
|
if __name__ == "__main__":
|
|
projects_app = ProjectsApp()
|
|
projects_app.run()
|
|
|