"""Add start_date to tasks and create task dependencies table for Gantt view Revision ID: 013 Revises: 012 Create Date: 2026-01-05 FEAT-003: Add Gantt view support with task dependencies and start dates. """ from typing import Sequence, Union from alembic import op import sqlalchemy as sa revision: str = '013' down_revision: Union[str, None] = '012' branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: # Add start_date column to pjctrl_tasks op.add_column( 'pjctrl_tasks', sa.Column('start_date', sa.DateTime, nullable=True) ) # Create dependency_type_enum dependency_type_enum = sa.Enum( 'FS', 'SS', 'FF', 'SF', name='dependency_type_enum' ) dependency_type_enum.create(op.get_bind(), checkfirst=True) # Create pjctrl_task_dependencies table op.create_table( 'pjctrl_task_dependencies', sa.Column('id', sa.String(36), primary_key=True), sa.Column( 'predecessor_id', sa.String(36), sa.ForeignKey('pjctrl_tasks.id', ondelete='CASCADE'), nullable=False ), sa.Column( 'successor_id', sa.String(36), sa.ForeignKey('pjctrl_tasks.id', ondelete='CASCADE'), nullable=False ), sa.Column( 'dependency_type', dependency_type_enum, default='FS', nullable=False ), sa.Column('lag_days', sa.Integer, default=0, nullable=False), sa.Column('created_at', sa.DateTime, server_default=sa.func.now(), nullable=False), # Unique constraint to prevent duplicate dependencies sa.UniqueConstraint('predecessor_id', 'successor_id', name='uq_predecessor_successor'), ) # Create indexes for efficient dependency lookups op.create_index( 'ix_pjctrl_task_dependencies_predecessor_id', 'pjctrl_task_dependencies', ['predecessor_id'] ) op.create_index( 'ix_pjctrl_task_dependencies_successor_id', 'pjctrl_task_dependencies', ['successor_id'] ) def downgrade() -> None: # Drop indexes op.drop_index( 'ix_pjctrl_task_dependencies_successor_id', table_name='pjctrl_task_dependencies' ) op.drop_index( 'ix_pjctrl_task_dependencies_predecessor_id', table_name='pjctrl_task_dependencies' ) # Drop the table op.drop_table('pjctrl_task_dependencies') # Drop the enum type sa.Enum(name='dependency_type_enum').drop(op.get_bind(), checkfirst=True) # Remove start_date column from tasks op.drop_column('pjctrl_tasks', 'start_date')