"""Database models for AI Software Factory.""" from datetime import datetime from enum import Enum from typing import List, Optional import logging from sqlalchemy import ( Column, Integer, String, Text, Boolean, ForeignKey, DateTime, JSON ) from sqlalchemy.orm import relationship, declarative_base from config import settings Base = declarative_base() logger = logging.getLogger(__name__) class ProjectStatus(str, Enum): """Project status enumeration.""" INITIALIZED = "initialized" STARTED = "started" RUNNING = "running" COMPLETED = "completed" ERROR = "error" class ProjectHistory(Base): """Main project tracking table.""" __tablename__ = "project_history" id = Column(Integer, primary_key=True) project_id = Column(String(255), nullable=False) project_name = Column(String(255), nullable=True) features = Column(Text, default="") description = Column(String(255), default="") status = Column(String(50), default='started') progress = Column(Integer, default=0) message = Column(String(500), default="") current_step = Column(String(255), nullable=True) total_steps = Column(Integer, nullable=True) current_step_description = Column(String(1024), nullable=True) current_step_details = Column(Text, nullable=True) error_message = Column(Text, nullable=True) created_at = Column(DateTime, default=datetime.utcnow) started_at = Column(DateTime, default=datetime.utcnow) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) completed_at = Column(DateTime, nullable=True) # Relationships project_logs = relationship("ProjectLog", back_populates="project_history", cascade="all, delete-orphan") ui_snapshots = relationship("UISnapshot", back_populates="project_history", cascade="all, delete-orphan") pull_requests = relationship("PullRequest", back_populates="project_history", cascade="all, delete-orphan") pull_request_data = relationship("PullRequestData", back_populates="project_history", cascade="all, delete-orphan") class ProjectLog(Base): """Detailed log entries for projects.""" __tablename__ = "project_logs" id = Column(Integer, primary_key=True) history_id = Column(Integer, ForeignKey("project_history.id"), nullable=False) log_level = Column(String(50), default="INFO") # INFO, WARNING, ERROR log_message = Column(String(500), nullable=False) timestamp = Column(DateTime, nullable=True) project_history = relationship("ProjectHistory", back_populates="project_logs") class UISnapshot(Base): """UI snapshots for projects.""" __tablename__ = "ui_snapshots" id = Column(Integer, primary_key=True) history_id = Column(Integer, ForeignKey("project_history.id"), nullable=False) snapshot_data = Column(JSON, nullable=False) created_at = Column(DateTime, default=datetime.utcnow) project_history = relationship("ProjectHistory", back_populates="ui_snapshots") class PullRequest(Base): """Pull request data for projects.""" __tablename__ = "pull_requests" id = Column(Integer, primary_key=True) history_id = Column(Integer, ForeignKey("project_history.id"), nullable=False) pr_number = Column(Integer, nullable=False) pr_title = Column(String(500), nullable=False) pr_body = Column(Text) base = Column(String(255), nullable=False) user = Column(String(255), nullable=False) pr_url = Column(String(500), nullable=False) merged = Column(Boolean, default=False) merged_at = Column(DateTime, nullable=True) pr_state = Column(String(50), nullable=False) created_at = Column(DateTime, default=datetime.utcnow) project_history = relationship("ProjectHistory", back_populates="pull_requests") class PullRequestData(Base): """Pull request data for audit API.""" __tablename__ = "pull_request_data" id = Column(Integer, primary_key=True) history_id = Column(Integer, ForeignKey("project_history.id"), nullable=False) pr_number = Column(Integer, nullable=False) pr_title = Column(String(500), nullable=False) pr_body = Column(Text) pr_state = Column(String(50), nullable=False) pr_url = Column(String(500), nullable=False) created_at = Column(DateTime, default=datetime.utcnow) project_history = relationship("ProjectHistory", back_populates="pull_request_data") class SystemLog(Base): """System-wide log entries.""" __tablename__ = "system_logs" id = Column(Integer, primary_key=True) component = Column(String(50), nullable=False) log_level = Column(String(50), default="INFO") log_message = Column(String(500), nullable=False) user_agent = Column(String(255), nullable=True) ip_address = Column(String(45), nullable=True) created_at = Column(DateTime, default=datetime.utcnow) class AuditTrail(Base): """Audit trail entries for system-wide logging.""" __tablename__ = "audit_trail" id = Column(Integer, primary_key=True) component = Column(String(50), nullable=True) log_level = Column(String(50), default="INFO") message = Column(String(500), nullable=False) created_at = Column(DateTime, default=datetime.utcnow) project_id = Column(String(255), nullable=True) action = Column(String(100), nullable=True) actor = Column(String(100), nullable=True) action_type = Column(String(50), nullable=True) details = Column(Text, nullable=True) metadata_json = Column(JSON, nullable=True) class UserAction(Base): """User action audit entries.""" __tablename__ = "user_actions" id = Column(Integer, primary_key=True) history_id = Column(Integer, ForeignKey("project_history.id"), nullable=True) user_id = Column(String(100), nullable=True) action_type = Column(String(100), nullable=True) actor_type = Column(String(50), nullable=True) actor_name = Column(String(100), nullable=True) action_description = Column(String(500), nullable=True) action_data = Column(JSON, nullable=True) created_at = Column(DateTime, default=datetime.utcnow) class AgentAction(Base): """Agent action audit entries.""" __tablename__ = "agent_actions" id = Column(Integer, primary_key=True) agent_name = Column(String(100), nullable=False) action_type = Column(String(100), nullable=False) success = Column(Boolean, default=True) message = Column(String(500), nullable=True) timestamp = Column(DateTime, default=datetime.utcnow)