Enables multi-user project collaboration mirroring the shared calendar pattern. Includes ProjectMember model with permission levels, task assignment with auto-membership, optimistic locking, field allowlist for assignees, disconnect cascade, delta polling for projects and calendars, and full frontend integration with share sheet, assignment picker, permission gating, and notification handling. Migrations: 057 (indexes + version + comment user_id), 058 (project_members), 059 (project_task_assignments) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
70 lines
2.0 KiB
Python
70 lines
2.0 KiB
Python
"""project collab prep: indexes, task version, comment user_id
|
|
|
|
Revision ID: 057
|
|
Revises: 056
|
|
Create Date: 2025-01-01 00:00:00.000000
|
|
|
|
"""
|
|
from alembic import op
|
|
import sqlalchemy as sa
|
|
|
|
# revision identifiers, used by Alembic.
|
|
revision = "057"
|
|
down_revision = "056"
|
|
branch_labels = None
|
|
depends_on = None
|
|
|
|
|
|
def upgrade() -> None:
|
|
# 1a. Performance indexes for project_tasks
|
|
op.create_index(
|
|
"ix_project_tasks_project_id",
|
|
"project_tasks",
|
|
["project_id"],
|
|
)
|
|
op.create_index(
|
|
"ix_project_tasks_parent_task_id",
|
|
"project_tasks",
|
|
["parent_task_id"],
|
|
postgresql_where=sa.text("parent_task_id IS NOT NULL"),
|
|
)
|
|
op.create_index(
|
|
"ix_project_tasks_project_updated",
|
|
"project_tasks",
|
|
["project_id", sa.text("updated_at DESC")],
|
|
)
|
|
op.create_index(
|
|
"ix_projects_user_updated",
|
|
"projects",
|
|
["user_id", sa.text("updated_at DESC")],
|
|
)
|
|
|
|
# 1b. Add user_id to task_comments for multi-user attribution
|
|
op.add_column(
|
|
"task_comments",
|
|
sa.Column("user_id", sa.Integer(), sa.ForeignKey("users.id", ondelete="SET NULL"), nullable=True),
|
|
)
|
|
|
|
# 1c. Add version column to project_tasks for optimistic locking
|
|
op.add_column(
|
|
"project_tasks",
|
|
sa.Column("version", sa.Integer(), server_default="1", nullable=False),
|
|
)
|
|
|
|
# Calendar delta polling index (Phase 4 prep)
|
|
op.create_index(
|
|
"ix_events_calendar_updated",
|
|
"calendar_events",
|
|
["calendar_id", sa.text("updated_at DESC")],
|
|
)
|
|
|
|
|
|
def downgrade() -> None:
|
|
op.drop_index("ix_events_calendar_updated", table_name="calendar_events")
|
|
op.drop_column("project_tasks", "version")
|
|
op.drop_column("task_comments", "user_id")
|
|
op.drop_index("ix_projects_user_updated", table_name="projects")
|
|
op.drop_index("ix_project_tasks_project_updated", table_name="project_tasks")
|
|
op.drop_index("ix_project_tasks_parent_task_id", table_name="project_tasks")
|
|
op.drop_index("ix_project_tasks_project_id", table_name="project_tasks")
|