forked from cardosofelipe/pragma-stack
Reformatted multiline function calls, object definitions, and queries for improved code readability and consistency. Adjusted imports and constraints where necessary.
87 lines
2.4 KiB
Python
87 lines
2.4 KiB
Python
# 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,
|
|
UniqueConstraint,
|
|
)
|
|
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
|
|
velocity = 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"),
|
|
# Ensure sprint numbers are unique within a project
|
|
UniqueConstraint("project_id", "number", name="uq_sprint_project_number"),
|
|
)
|
|
|
|
def __repr__(self) -> str:
|
|
return (
|
|
f"<Sprint {self.name} (#{self.number}) "
|
|
f"project={self.project_id} status={self.status.value}>"
|
|
)
|