Spaces:
Running
Running
| import sys | |
| import os | |
| sys.stdout.reconfigure(encoding='utf-8') | |
| from sqlalchemy import create_engine, Column, Integer, String, Text, DateTime, ForeignKey, JSON, Float, Boolean, Date | |
| from sqlalchemy.orm import declarative_base, sessionmaker, relationship | |
| from datetime import datetime | |
| from passlib.context import CryptContext | |
| import os | |
| # ✅ التعديل هنا: استخدام SQLite افتراضياً للتشغيل المحلي | |
| SQLALCHEMY_DATABASE_URL = os.getenv("DATABASE_URL", "sqlite:///./blueprint.db") | |
| # دعم كل من PostgreSQL و SQLite | |
| if SQLALCHEMY_DATABASE_URL.startswith("postgresql"): | |
| engine = create_engine(SQLALCHEMY_DATABASE_URL) | |
| else: | |
| # SQLite يحتاج connect_args | |
| engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}) | |
| SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) | |
| Base = declarative_base() | |
| pwd_context = CryptContext(schemes=["sha256_crypt"], deprecated="auto") | |
| # ---------- نماذج المستخدمين والصلاحيات ---------- | |
| class User(Base): | |
| __tablename__ = "users" | |
| id = Column(Integer, primary_key=True, index=True) | |
| username = Column(String, unique=True, index=True, nullable=False) | |
| email = Column(String, unique=True, index=True, nullable=False) | |
| hashed_password = Column(String, nullable=False) | |
| full_name = Column(String) | |
| role = Column(String, default="viewer") # admin, engineer, viewer | |
| is_active = Column(Boolean, default=True) | |
| created_at = Column(DateTime, default=datetime.utcnow) | |
| projects = relationship("ProjectUser", back_populates="user") | |
| class ProjectUser(Base): | |
| __tablename__ = "project_users" | |
| id = Column(Integer, primary_key=True) | |
| project_id = Column(Integer, ForeignKey("projects.id")) | |
| user_id = Column(Integer, ForeignKey("users.id")) | |
| permission = Column(String, default="read") # read, write, admin | |
| user = relationship("User", back_populates="projects") | |
| project = relationship("Project", back_populates="users") | |
| # ---------- المشاريع ---------- | |
| class Project(Base): | |
| __tablename__ = "projects" | |
| id = Column(Integer, primary_key=True, index=True) | |
| name = Column(String, nullable=False, index=True) | |
| location = Column(String, nullable=True) | |
| created_at = Column(DateTime, default=datetime.utcnow) | |
| analyses = relationship("Analysis", back_populates="project", cascade="all, delete-orphan") | |
| site_reports = relationship("SiteReport", back_populates="project", cascade="all, delete-orphan") | |
| boq_items = relationship("BOQItem", back_populates="project", cascade="all, delete-orphan") | |
| files = relationship("UploadedFile", back_populates="project", cascade="all, delete-orphan") | |
| defects = relationship("Defect", back_populates="project", cascade="all, delete-orphan") | |
| users = relationship("ProjectUser", back_populates="project", cascade="all, delete-orphan") | |
| site_visits = relationship("SiteVisit", back_populates="project", cascade="all, delete-orphan") | |
| memory_entries = relationship("MemoryEntry", back_populates="project", cascade="all, delete-orphan") | |
| workflows = relationship("Workflow", back_populates="project", cascade="all, delete-orphan") | |
| tasks = relationship("Task", back_populates="project", cascade="all, delete-orphan") # NEW | |
| # ---------- التحليلات ---------- | |
| class Analysis(Base): | |
| __tablename__ = "analyses" | |
| id = Column(Integer, primary_key=True, index=True) | |
| project_id = Column(Integer, ForeignKey("projects.id"), index=True) | |
| task_type = Column(String) | |
| input_text = Column(Text) | |
| result_json = Column(JSON) | |
| safety_status = Column(String, default="Pending") | |
| created_at = Column(DateTime, default=datetime.utcnow, index=True) | |
| project = relationship("Project", back_populates="analyses") | |
| class SiteReport(Base): | |
| __tablename__ = "site_reports" | |
| id = Column(Integer, primary_key=True, index=True) | |
| project_id = Column(Integer, ForeignKey("projects.id")) | |
| report_date = Column(DateTime, default=datetime.utcnow) | |
| weather = Column(String) | |
| workers_count = Column(Integer) | |
| summary = Column(Text) | |
| issues = Column(Text) | |
| created_at = Column(DateTime, default=datetime.utcnow) | |
| project = relationship("Project", back_populates="site_reports") | |
| # ---------- حصر الكميات ---------- | |
| class BOQItem(Base): | |
| __tablename__ = "boq_items" | |
| id = Column(Integer, primary_key=True, index=True) | |
| project_id = Column(Integer, ForeignKey("projects.id"), index=True) | |
| description = Column(String) | |
| unit = Column(String) | |
| quantity = Column(Float) | |
| unit_price = Column(Float) | |
| total_price = Column(Float) | |
| project = relationship("Project", back_populates="boq_items") | |
| # ---------- الملفات المرفوعة ---------- | |
| class UploadedFile(Base): | |
| __tablename__ = "uploaded_files" | |
| id = Column(Integer, primary_key=True, index=True) | |
| project_id = Column(Integer, ForeignKey("projects.id"), index=True) | |
| filename = Column(String) | |
| file_type = Column(String) | |
| file_path = Column(String) | |
| analyzed = Column(Boolean, default=False) | |
| created_at = Column(DateTime, default=datetime.utcnow) | |
| project = relationship("Project", back_populates="files") | |
| # ---------- العيوب ---------- | |
| class Defect(Base): | |
| __tablename__ = "defects" | |
| id = Column(Integer, primary_key=True, index=True) | |
| project_id = Column(Integer, ForeignKey("projects.id"), index=True) | |
| description = Column(Text) | |
| severity = Column(String) # High, Medium, Low | |
| status = Column(String, default="Open") # Open, Resolved | |
| image_id = Column(Integer, ForeignKey("uploaded_files.id"), nullable=True) | |
| assigned_to = Column(Integer, ForeignKey("users.id"), nullable=True) | |
| created_at = Column(DateTime, default=datetime.utcnow) | |
| project = relationship("Project", back_populates="defects") | |
| assignee = relationship("User", foreign_keys=[assigned_to]) | |
| # ---------- إعدادات المشروع ---------- | |
| class ProjectSettings(Base): | |
| __tablename__ = "project_settings" | |
| id = Column(Integer, primary_key=True, index=True) | |
| project_id = Column(Integer, ForeignKey("projects.id"), unique=True, index=True) | |
| concrete_price = Column(Float, default=1000.0) | |
| steel_price = Column(Float, default=35000.0) | |
| preferred_ai_model = Column(String, default="gemini") | |
| created_at = Column(DateTime, default=datetime.utcnow) | |
| project = relationship("Project", backref="settings", uselist=False) | |
| # ---------- زيارات الموقع ---------- | |
| class SiteVisit(Base): | |
| __tablename__ = "site_visits" | |
| id = Column(Integer, primary_key=True, index=True) | |
| project_id = Column(Integer, ForeignKey("projects.id"), index=True) | |
| visit_date = Column(DateTime, default=datetime.utcnow) | |
| location_name = Column(String, nullable=True) | |
| latitude = Column(Float, nullable=True) | |
| longitude = Column(Float, nullable=True) | |
| notes = Column(Text, nullable=True) | |
| created_by = Column(Integer, ForeignKey("users.id"), nullable=True) | |
| created_at = Column(DateTime, default=datetime.utcnow) | |
| project = relationship("Project", back_populates="site_visits") | |
| creator = relationship("User", foreign_keys=[created_by]) | |
| images = relationship("SiteVisitImage", back_populates="site_visit", cascade="all, delete-orphan") | |
| class SiteVisitImage(Base): | |
| __tablename__ = "site_visit_images" | |
| id = Column(Integer, primary_key=True, index=True) | |
| site_visit_id = Column(Integer, ForeignKey("site_visits.id"), index=True) | |
| image_path = Column(String) | |
| caption = Column(String, nullable=True) | |
| timestamp = Column(DateTime, nullable=True) | |
| latitude = Column(Float, nullable=True) | |
| longitude = Column(Float, nullable=True) | |
| created_at = Column(DateTime, default=datetime.utcnow) | |
| site_visit = relationship("SiteVisit", back_populates="images") | |
| # ---------- الذاكرة طويلة المدى ---------- | |
| class MemoryEntry(Base): | |
| __tablename__ = "memory_entries" | |
| id = Column(Integer, primary_key=True, index=True) | |
| project_id = Column(Integer, ForeignKey("projects.id"), index=True) | |
| entry_type = Column(String) # decision, pattern, context, progress | |
| title = Column(String) | |
| content = Column(Text) | |
| tags = Column(String) # مفصول بفواصل | |
| created_at = Column(DateTime, default=datetime.utcnow) | |
| updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) | |
| project = relationship("Project", back_populates="memory_entries") | |
| # ---------- سير العمل الآلي ---------- | |
| class Workflow(Base): | |
| __tablename__ = "workflows" | |
| id = Column(Integer, primary_key=True, index=True) | |
| project_id = Column(Integer, ForeignKey("projects.id"), index=True) | |
| name = Column(String) | |
| trigger_event = Column(String) # image_upload, defect_created, design_completed | |
| action_type = Column(String) # notify, create_defect, update_boq, send_message | |
| action_params = Column(JSON) | |
| is_active = Column(Boolean, default=True) | |
| created_at = Column(DateTime, default=datetime.utcnow) | |
| project = relationship("Project", back_populates="workflows") | |
| class WorkflowLog(Base): | |
| __tablename__ = "workflow_logs" | |
| id = Column(Integer, primary_key=True, index=True) | |
| workflow_id = Column(Integer, ForeignKey("workflows.id")) | |
| triggered_by = Column(String) | |
| status = Column(String) # success, failed | |
| result = Column(JSON) | |
| created_at = Column(DateTime, default=datetime.utcnow) | |
| workflow = relationship("Workflow") | |
| # ---------- المهام (NEW) ---------- | |
| class Task(Base): | |
| __tablename__ = "tasks" | |
| id = Column(Integer, primary_key=True, index=True) | |
| project_id = Column(Integer, ForeignKey("projects.id"), index=True) | |
| description = Column(String, nullable=False) | |
| assignee = Column(String, nullable=False) | |
| due_date = Column(Date, nullable=False) | |
| priority = Column(String, nullable=False) # منخفضة، متوسطة، عالية | |
| status = Column(String, default="قيد الانتظار") # قيد الانتظار، جاري، منتهية | |
| created_at = Column(DateTime, default=datetime.utcnow) | |
| updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) | |
| project = relationship("Project", back_populates="tasks") | |
| # ---------- دالة تهيئة قاعدة البيانات ---------- | |
| def init_db(): | |
| Base.metadata.create_all(bind=engine) | |
| # ---------- دوال مساعدة للمستخدمين ---------- | |
| def get_password_hash(password): | |
| return pwd_context.hash(password) | |
| def verify_password(plain_password, hashed_password): | |
| return pwd_context.verify(plain_password, hashed_password) |