175 lines
6.6 KiB
Python
175 lines
6.6 KiB
Python
"""
|
|
SQLAlchemy ORM models for Foxy Dev Team.
|
|
"""
|
|
|
|
import enum
|
|
from datetime import datetime, timezone
|
|
from typing import Optional, List
|
|
|
|
from sqlalchemy import (
|
|
String, Text, Integer, DateTime, ForeignKey, Enum, JSON
|
|
)
|
|
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
|
|
|
from app.database import Base
|
|
|
|
|
|
# ─── Enums ─────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
class ProjectStatus(str, enum.Enum):
|
|
PENDING = "PENDING"
|
|
AWAITING_CONDUCTOR = "AWAITING_CONDUCTOR"
|
|
CONDUCTOR_RUNNING = "CONDUCTOR_RUNNING"
|
|
AWAITING_ARCHITECT = "AWAITING_ARCHITECT"
|
|
ARCHITECT_RUNNING = "ARCHITECT_RUNNING"
|
|
AWAITING_DEV = "AWAITING_DEV"
|
|
DEV_RUNNING = "DEV_RUNNING"
|
|
AWAITING_UIUX = "AWAITING_UIUX"
|
|
UIUX_RUNNING = "UIUX_RUNNING"
|
|
AWAITING_QA = "AWAITING_QA"
|
|
QA_RUNNING = "QA_RUNNING"
|
|
AWAITING_DEPLOY = "AWAITING_DEPLOY"
|
|
DEPLOY_RUNNING = "DEPLOY_RUNNING"
|
|
COMPLETED = "COMPLETED"
|
|
FAILED = "FAILED"
|
|
PAUSED = "PAUSED"
|
|
|
|
|
|
class WorkflowType(str, enum.Enum):
|
|
SOFTWARE_DESIGN = "SOFTWARE_DESIGN"
|
|
SYSADMIN_DEBUG = "SYSADMIN_DEBUG"
|
|
DEVOPS_SETUP = "DEVOPS_SETUP"
|
|
SYSADMIN_ADJUST = "SYSADMIN_ADJUST"
|
|
|
|
|
|
class TaskStatus(str, enum.Enum):
|
|
PENDING = "PENDING"
|
|
IN_PROGRESS = "IN_PROGRESS"
|
|
IN_REVIEW = "IN_REVIEW"
|
|
REJECTED = "REJECTED"
|
|
READY_FOR_DEPLOY = "READY_FOR_DEPLOY"
|
|
DONE = "DONE"
|
|
BLOCKED = "BLOCKED"
|
|
|
|
|
|
class TaskType(str, enum.Enum):
|
|
BACKEND = "BACKEND"
|
|
FRONTEND = "FRONTEND"
|
|
INFRA = "INFRA"
|
|
TEST = "TEST"
|
|
DESIGN = "DESIGN"
|
|
|
|
|
|
class TaskPriority(str, enum.Enum):
|
|
P1 = "P1"
|
|
P2 = "P2"
|
|
P3 = "P3"
|
|
|
|
|
|
class AgentExecutionStatus(str, enum.Enum):
|
|
RUNNING = "RUNNING"
|
|
SUCCESS = "SUCCESS"
|
|
FAILED = "FAILED"
|
|
TIMEOUT = "TIMEOUT"
|
|
|
|
|
|
def _utcnow() -> datetime:
|
|
return datetime.now(timezone.utc)
|
|
|
|
|
|
# ─── Models ────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
class Project(Base):
|
|
__tablename__ = "projects"
|
|
|
|
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
|
name: Mapped[str] = mapped_column(String(200), nullable=False)
|
|
slug: Mapped[str] = mapped_column(String(200), unique=True, nullable=False, index=True)
|
|
description: Mapped[str] = mapped_column(Text, default="")
|
|
status: Mapped[ProjectStatus] = mapped_column(
|
|
Enum(ProjectStatus), default=ProjectStatus.PENDING, nullable=False
|
|
)
|
|
workflow_type: Mapped[WorkflowType] = mapped_column(
|
|
Enum(WorkflowType), default=WorkflowType.SOFTWARE_DESIGN, nullable=False
|
|
)
|
|
test_mode: Mapped[bool] = mapped_column(default=False)
|
|
gitea_repo: Mapped[Optional[str]] = mapped_column(String(500), nullable=True)
|
|
deployment_target: Mapped[Optional[str]] = mapped_column(String(200), nullable=True)
|
|
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=_utcnow)
|
|
updated_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True), default=_utcnow, onupdate=_utcnow
|
|
)
|
|
|
|
# Relationships
|
|
tasks: Mapped[List["Task"]] = relationship(
|
|
back_populates="project", cascade="all, delete-orphan", lazy="selectin"
|
|
)
|
|
audit_logs: Mapped[List["AuditLog"]] = relationship(
|
|
back_populates="project", cascade="all, delete-orphan", lazy="selectin"
|
|
)
|
|
agent_executions: Mapped[List["AgentExecution"]] = relationship(
|
|
back_populates="project", cascade="all, delete-orphan", lazy="selectin"
|
|
)
|
|
|
|
|
|
class Task(Base):
|
|
__tablename__ = "tasks"
|
|
|
|
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
|
project_id: Mapped[int] = mapped_column(ForeignKey("projects.id"), nullable=False)
|
|
task_id: Mapped[str] = mapped_column(String(50), nullable=False) # e.g. TASK-001
|
|
type: Mapped[TaskType] = mapped_column(Enum(TaskType), default=TaskType.BACKEND)
|
|
title: Mapped[str] = mapped_column(String(500), nullable=False)
|
|
priority: Mapped[TaskPriority] = mapped_column(Enum(TaskPriority), default=TaskPriority.P3)
|
|
assigned_to: Mapped[Optional[str]] = mapped_column(String(100), nullable=True)
|
|
status: Mapped[TaskStatus] = mapped_column(
|
|
Enum(TaskStatus), default=TaskStatus.PENDING, nullable=False
|
|
)
|
|
dependencies: Mapped[Optional[dict]] = mapped_column(JSON, default=list)
|
|
acceptance_criteria: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
|
|
agent_payloads: Mapped[Optional[dict]] = mapped_column(JSON, default=dict)
|
|
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=_utcnow)
|
|
updated_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True), default=_utcnow, onupdate=_utcnow
|
|
)
|
|
|
|
# Relationships
|
|
project: Mapped["Project"] = relationship(back_populates="tasks")
|
|
|
|
|
|
class AgentExecution(Base):
|
|
__tablename__ = "agent_executions"
|
|
|
|
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
|
project_id: Mapped[int] = mapped_column(ForeignKey("projects.id"), nullable=False)
|
|
agent_name: Mapped[str] = mapped_column(String(100), nullable=False)
|
|
status: Mapped[AgentExecutionStatus] = mapped_column(
|
|
Enum(AgentExecutionStatus), default=AgentExecutionStatus.RUNNING
|
|
)
|
|
pid: Mapped[Optional[int]] = mapped_column(Integer, nullable=True)
|
|
started_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=_utcnow)
|
|
finished_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), nullable=True)
|
|
exit_code: Mapped[Optional[int]] = mapped_column(Integer, nullable=True)
|
|
error_output: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
|
|
|
|
# Relationships
|
|
project: Mapped["Project"] = relationship(back_populates="agent_executions")
|
|
|
|
|
|
class AuditLog(Base):
|
|
__tablename__ = "audit_logs"
|
|
|
|
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
|
project_id: Mapped[int] = mapped_column(ForeignKey("projects.id"), nullable=False)
|
|
timestamp: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=_utcnow)
|
|
agent: Mapped[str] = mapped_column(String(100), nullable=False)
|
|
action: Mapped[str] = mapped_column(String(100), nullable=False)
|
|
target: Mapped[Optional[str]] = mapped_column(String(100), nullable=True)
|
|
message: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
|
|
source: Mapped[str] = mapped_column(String(100), default="api")
|
|
|
|
# Relationships
|
|
project: Mapped["Project"] = relationship(back_populates="audit_logs")
|