from sqlalchemy import Column, String, Integer, Text, DateTime, ForeignKey, CheckConstraint from sqlalchemy.orm import relationship from datetime import datetime import uuid from app.database.connection import Base def generate_id(): """Generate a unique ID.""" return str(uuid.uuid4()) class User(Base): """User model for authentication.""" __tablename__ = "users" id = Column(String, primary_key=True, default=generate_id) email = Column(String, unique=True, nullable=False, index=True) name = Column(String, nullable=True) password_hash = Column(String, nullable=True) # Nullable for OAuth users google_id = Column(String, unique=True, nullable=True, index=True) is_admin = Column(Integer, default=0) # 0 = regular user, 1 = admin created_at = Column(DateTime, default=datetime.utcnow) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) # Relationships sessions = relationship("Session", back_populates="user", cascade="all, delete-orphan") documents = relationship("Document", back_populates="user", cascade="all, delete-orphan") class Session(Base): """Chat session model.""" __tablename__ = "sessions" id = Column(String, primary_key=True, default=generate_id) user_id = Column(String, ForeignKey("users.id", ondelete="CASCADE"), nullable=True, index=True) title = Column(String, default="New Conversation") summary = Column(Text, nullable=True) created_at = Column(DateTime, default=datetime.utcnow) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) # Relationships user = relationship("User", back_populates="sessions") messages = relationship("Message", back_populates="session", cascade="all, delete-orphan") class Message(Base): """Chat message model.""" __tablename__ = "messages" id = Column(String, primary_key=True, default=generate_id) session_id = Column(String, ForeignKey("sessions.id", ondelete="CASCADE"), nullable=False, index=True) role = Column(String, nullable=False) # 'user' or 'assistant' content = Column(Text, nullable=False) meta = Column(Text, nullable=True) # JSON string for metadata (agent, sources, etc.) created_at = Column(DateTime, default=datetime.utcnow) # Relationships session = relationship("Session", back_populates="messages") # Constraint __table_args__ = ( CheckConstraint("role IN ('user', 'assistant')", name="check_role"), ) class Document(Base): """Uploaded document model.""" __tablename__ = "documents" id = Column(String, primary_key=True, default=generate_id) user_id = Column(String, ForeignKey("users.id", ondelete="CASCADE"), nullable=False, index=True) filename = Column(String, nullable=False) file_path = Column(String, nullable=False) file_type = Column(String, nullable=True) file_size = Column(Integer, nullable=True) created_at = Column(DateTime, default=datetime.utcnow) # Relationships user = relationship("User", back_populates="documents") class OfficialPolicy(Base): """Official policy document model (admin-only upload, visible to all).""" __tablename__ = "official_policies" id = Column(String, primary_key=True, default=generate_id) title = Column(String, nullable=False) description = Column(Text, nullable=True) filename = Column(String, nullable=False) file_path = Column(String, nullable=False) file_type = Column(String, nullable=True) file_size = Column(Integer, nullable=True) category = Column(String, nullable=True) # e.g., "OSHA", "Safety", "Building Codes" uploaded_by = Column(String, ForeignKey("users.id"), nullable=False) is_active = Column(Integer, default=1) # 0 = inactive, 1 = active created_at = Column(DateTime, default=datetime.utcnow) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) # Relationships chunks = relationship("PolicyChunk", back_populates="policy", cascade="all, delete-orphan") class PolicyChunk(Base): """Chunks of official policy text for database-backed retrieval.""" __tablename__ = "policy_chunks" id = Column(String, primary_key=True, default=generate_id) policy_id = Column(String, ForeignKey("official_policies.id", ondelete="CASCADE"), nullable=False, index=True) chunk_index = Column(Integer, nullable=False) content = Column(Text, nullable=False) created_at = Column(DateTime, default=datetime.utcnow) # Relationships policy = relationship("OfficialPolicy", back_populates="chunks") class UserSettings(Base): """User settings and preferences model.""" __tablename__ = "user_settings" id = Column(String, primary_key=True, default=generate_id) user_id = Column(String, ForeignKey("users.id", ondelete="CASCADE"), nullable=False, unique=True, index=True) # Profile settings bio = Column(Text, nullable=True) phone = Column(String, nullable=True) company = Column(String, nullable=True) # Appearance settings theme = Column(String, default="system") # light, dark, system # Notification settings email_notifications = Column(Integer, default=1) # 0 = off, 1 = on update_notifications = Column(Integer, default=1) # 0 = off, 1 = on created_at = Column(DateTime, default=datetime.utcnow) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) class Report(Base): """Generated reports model.""" __tablename__ = "reports" id = Column(String, primary_key=True, default=generate_id) user_id = Column(String, ForeignKey("users.id", ondelete="CASCADE"), nullable=True, index=True) template_id = Column(String, nullable=False) filename = Column(String, nullable=False) file_path = Column(String, nullable=False) created_at = Column(DateTime, default=datetime.utcnow) # Relationships user = relationship("User")