"""Task management tables Revision ID: 002 Revises: 001 Create Date: 2024-01-XX """ from alembic import op import sqlalchemy as sa from sqlalchemy.dialects import mysql # revision identifiers, used by Alembic. revision = '002' down_revision = '001' branch_labels = None depends_on = None def upgrade() -> None: # Create pjctrl_spaces table op.create_table( 'pjctrl_spaces', sa.Column('id', sa.String(36), primary_key=True), sa.Column('name', sa.String(200), nullable=False), sa.Column('description', sa.Text, nullable=True), sa.Column('owner_id', sa.String(36), sa.ForeignKey('pjctrl_users.id'), nullable=False), sa.Column('is_active', sa.Boolean, default=True, nullable=False), sa.Column('created_at', sa.DateTime, server_default=sa.func.now(), nullable=False), sa.Column('updated_at', sa.DateTime, server_default=sa.func.now(), onupdate=sa.func.now(), nullable=False), ) op.create_index('idx_spaces_owner', 'pjctrl_spaces', ['owner_id']) op.create_index('idx_spaces_active', 'pjctrl_spaces', ['is_active']) # Create pjctrl_projects table op.create_table( 'pjctrl_projects', sa.Column('id', sa.String(36), primary_key=True), sa.Column('space_id', sa.String(36), sa.ForeignKey('pjctrl_spaces.id', ondelete='CASCADE'), nullable=False), sa.Column('title', sa.String(200), nullable=False), sa.Column('description', sa.Text, nullable=True), sa.Column('owner_id', sa.String(36), sa.ForeignKey('pjctrl_users.id'), nullable=False), sa.Column('budget', sa.Numeric(15, 2), nullable=True), sa.Column('start_date', sa.Date, nullable=True), sa.Column('end_date', sa.Date, nullable=True), sa.Column('security_level', sa.Enum('public', 'department', 'confidential', name='security_level_enum'), server_default='department', nullable=False), sa.Column('status', sa.String(50), server_default='active', nullable=False), sa.Column('department_id', sa.String(36), sa.ForeignKey('pjctrl_departments.id'), nullable=True), sa.Column('created_at', sa.DateTime, server_default=sa.func.now(), nullable=False), sa.Column('updated_at', sa.DateTime, server_default=sa.func.now(), onupdate=sa.func.now(), nullable=False), ) op.create_index('idx_projects_space', 'pjctrl_projects', ['space_id']) op.create_index('idx_projects_owner', 'pjctrl_projects', ['owner_id']) op.create_index('idx_projects_department', 'pjctrl_projects', ['department_id']) op.create_index('idx_projects_security', 'pjctrl_projects', ['security_level']) # Create pjctrl_task_statuses table op.create_table( 'pjctrl_task_statuses', sa.Column('id', sa.String(36), primary_key=True), sa.Column('project_id', sa.String(36), sa.ForeignKey('pjctrl_projects.id', ondelete='CASCADE'), nullable=False), sa.Column('name', sa.String(50), nullable=False), sa.Column('color', sa.String(7), server_default='#808080', nullable=False), sa.Column('position', sa.Integer, server_default='0', nullable=False), sa.Column('is_done', sa.Boolean, server_default='0', nullable=False), sa.Column('created_at', sa.DateTime, server_default=sa.func.now(), nullable=False), sa.UniqueConstraint('project_id', 'name', name='uk_status_name'), ) op.create_index('idx_statuses_project', 'pjctrl_task_statuses', ['project_id']) # Create pjctrl_tasks table op.create_table( 'pjctrl_tasks', sa.Column('id', sa.String(36), primary_key=True), sa.Column('project_id', sa.String(36), sa.ForeignKey('pjctrl_projects.id', ondelete='CASCADE'), nullable=False), sa.Column('parent_task_id', sa.String(36), sa.ForeignKey('pjctrl_tasks.id', ondelete='CASCADE'), nullable=True), sa.Column('title', sa.String(500), nullable=False), sa.Column('description', sa.Text, nullable=True), sa.Column('assignee_id', sa.String(36), sa.ForeignKey('pjctrl_users.id'), nullable=True), sa.Column('status_id', sa.String(36), sa.ForeignKey('pjctrl_task_statuses.id'), nullable=True), sa.Column('priority', sa.Enum('low', 'medium', 'high', 'urgent', name='priority_enum'), server_default='medium', nullable=False), sa.Column('original_estimate', sa.Numeric(8, 2), nullable=True), sa.Column('time_spent', sa.Numeric(8, 2), server_default='0', nullable=False), sa.Column('blocker_flag', sa.Boolean, server_default='0', nullable=False), sa.Column('due_date', sa.DateTime, nullable=True), sa.Column('position', sa.Integer, server_default='0', nullable=False), sa.Column('created_by', sa.String(36), sa.ForeignKey('pjctrl_users.id'), nullable=False), sa.Column('created_at', sa.DateTime, server_default=sa.func.now(), nullable=False), sa.Column('updated_at', sa.DateTime, server_default=sa.func.now(), onupdate=sa.func.now(), nullable=False), ) op.create_index('idx_tasks_project', 'pjctrl_tasks', ['project_id']) op.create_index('idx_tasks_parent', 'pjctrl_tasks', ['parent_task_id']) op.create_index('idx_tasks_assignee', 'pjctrl_tasks', ['assignee_id']) op.create_index('idx_tasks_status', 'pjctrl_tasks', ['status_id']) op.create_index('idx_tasks_due', 'pjctrl_tasks', ['due_date']) op.create_index('idx_tasks_blocker', 'pjctrl_tasks', ['blocker_flag']) def downgrade() -> None: op.drop_table('pjctrl_tasks') op.drop_table('pjctrl_task_statuses') op.drop_table('pjctrl_projects') op.drop_table('pjctrl_spaces') # Drop enums op.execute("DROP TYPE IF EXISTS priority_enum") op.execute("DROP TYPE IF EXISTS security_level_enum")