Files
PROJECT-CONTORL/backend/app/models/task_dependency.py
2026-01-11 08:37:21 +08:00

74 lines
2.3 KiB
Python

import uuid
from sqlalchemy import Column, String, Integer, Enum, DateTime, ForeignKey, UniqueConstraint
from sqlalchemy.orm import relationship, synonym
from sqlalchemy.sql import func
from app.core.database import Base
import enum
class DependencyType(str, enum.Enum):
"""
Task dependency types for Gantt chart.
FS (Finish-to-Start): Predecessor must finish before successor starts (most common)
SS (Start-to-Start): Predecessor must start before successor starts
FF (Finish-to-Finish): Predecessor must finish before successor finishes
SF (Start-to-Finish): Predecessor must start before successor finishes (rare)
"""
FS = "FS" # Finish-to-Start
SS = "SS" # Start-to-Start
FF = "FF" # Finish-to-Finish
SF = "SF" # Start-to-Finish
class TaskDependency(Base):
"""
Represents a dependency relationship between two tasks.
The predecessor task affects when the successor task can be scheduled,
based on the dependency_type. This is used for Gantt chart visualization
and date validation.
"""
__tablename__ = "pjctrl_task_dependencies"
__table_args__ = (
UniqueConstraint('predecessor_id', 'successor_id', name='uq_predecessor_successor'),
)
id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
predecessor_id = Column(
String(36),
ForeignKey("pjctrl_tasks.id", ondelete="CASCADE"),
nullable=False,
index=True
)
successor_id = Column(
String(36),
ForeignKey("pjctrl_tasks.id", ondelete="CASCADE"),
nullable=False,
index=True
)
dependency_type = Column(
Enum("FS", "SS", "FF", "SF", name="dependency_type_enum"),
default="FS",
nullable=False
)
lag_days = Column(Integer, default=0, nullable=False)
created_at = Column(DateTime, server_default=func.now(), nullable=False)
# Relationships
predecessor = relationship(
"Task",
foreign_keys=[predecessor_id],
back_populates="successors"
)
successor = relationship(
"Task",
foreign_keys=[successor_id],
back_populates="predecessors"
)
# Backward-compatible aliases for legacy field names
task_id = synonym("successor_id")
depends_on_task_id = synonym("predecessor_id")