# app/models/syndarix/sprint.py """ Sprint model for Syndarix AI consulting platform. A Sprint represents a time-boxed iteration for organizing and delivering work. """ from sqlalchemy import Column, Date, Enum, ForeignKey, Index, Integer, String, Text from sqlalchemy.dialects.postgresql import UUID as PGUUID from sqlalchemy.orm import relationship from app.models.base import Base, TimestampMixin, UUIDMixin from .enums import SprintStatus class Sprint(Base, UUIDMixin, TimestampMixin): """ Sprint model representing a time-boxed iteration. Tracks: - Sprint metadata (name, number, goal) - Date range (start/end) - Progress metrics (planned vs completed points) """ __tablename__ = "sprints" # Foreign key to project project_id = Column( PGUUID(as_uuid=True), ForeignKey("projects.id", ondelete="CASCADE"), nullable=False, index=True, ) # Sprint identification name = Column(String(255), nullable=False) number = Column(Integer, nullable=False) # Sprint number within project # Sprint goal (what we aim to achieve) goal = Column(Text, nullable=True) # Date range start_date = Column(Date, nullable=False, index=True) end_date = Column(Date, nullable=False, index=True) # Status status: Column[SprintStatus] = Column( Enum(SprintStatus), default=SprintStatus.PLANNED, nullable=False, index=True, ) # Progress metrics planned_points = Column(Integer, nullable=True) # Sum of story points at start completed_points = Column(Integer, nullable=True) # Sum of completed story points # Relationships project = relationship("Project", back_populates="sprints") issues = relationship("Issue", back_populates="sprint") __table_args__ = ( Index("ix_sprints_project_status", "project_id", "status"), Index("ix_sprints_project_number", "project_id", "number"), Index("ix_sprints_date_range", "start_date", "end_date"), ) def __repr__(self) -> str: return ( f"" )