"""add saved ideas Revision ID: 20260428_add_saved_ideas Revises: 20260428_add_platform_memberships Create Date: 2026-04-28 """ from __future__ import annotations from alembic import op import sqlalchemy as sa try: from sqlalchemy.dialects.postgresql import JSONB except Exception: # pragma: no cover JSONB = sa.JSON revision = "20260428_add_saved_ideas" down_revision = "20260428_add_platform_memberships" branch_labels = None depends_on = None def _json_type(bind): return JSONB() if bind.dialect.name == "postgresql" else sa.JSON() def _table_exists(bind, table_name: str) -> bool: return sa.inspect(bind).has_table(table_name) def upgrade() -> None: bind = op.get_bind() if _table_exists(bind, "saved_ideas"): return json_type = _json_type(bind) op.create_table( "saved_ideas", sa.Column("id", sa.Integer(), primary_key=True, autoincrement=True), sa.Column("tenant_id", sa.BigInteger(), nullable=False), sa.Column("created_at", sa.TIMESTAMP(), server_default=sa.func.now(), nullable=False), sa.Column("updated_at", sa.TIMESTAMP(), server_default=sa.func.now(), nullable=False), sa.Column("user_id", sa.BigInteger(), sa.ForeignKey("users.id"), nullable=False), sa.Column("idea_id", sa.String(length=64), nullable=False), sa.Column("title", sa.String(length=255), nullable=False), sa.Column("raw_text", sa.Text(), nullable=False), sa.Column("summary", sa.Text(), nullable=False), sa.Column("source_type", sa.String(length=32), nullable=False, server_default="project_launch"), sa.Column("source_ref", sa.String(length=255), nullable=True), sa.Column("input_mode", sa.String(length=32), nullable=False, server_default="idea"), sa.Column("attachments", json_type, nullable=False), sa.Column("status", sa.String(length=32), nullable=False, server_default="saved"), sa.Column("ai_summary", sa.Text(), nullable=True), sa.Column("missing_questions", json_type, nullable=False), sa.Column("readiness_score", sa.Float(), nullable=False, server_default="0"), sa.Column("launch_draft_id", sa.String(length=64), nullable=True), sa.Column("promoted_project_id", sa.BigInteger(), sa.ForeignKey("projects.id"), nullable=True), sa.Column("promoted_at", sa.TIMESTAMP(), nullable=True), sa.Column("archived_at", sa.TIMESTAMP(), nullable=True), sa.UniqueConstraint("tenant_id", "idea_id", name="uq_saved_ideas_tenant_idea_id"), ) op.create_index("ix_saved_ideas_tenant_id", "saved_ideas", ["tenant_id"], unique=False) op.create_index("ix_saved_ideas_user_id", "saved_ideas", ["user_id"], unique=False) op.create_index("ix_saved_ideas_idea_id", "saved_ideas", ["idea_id"], unique=False) op.create_index("ix_saved_ideas_source_type", "saved_ideas", ["source_type"], unique=False) op.create_index("ix_saved_ideas_status", "saved_ideas", ["status"], unique=False) op.create_index("ix_saved_ideas_launch_draft_id", "saved_ideas", ["launch_draft_id"], unique=False) op.create_index("ix_saved_ideas_promoted_project_id", "saved_ideas", ["promoted_project_id"], unique=False) def downgrade() -> None: bind = op.get_bind() if not _table_exists(bind, "saved_ideas"): return for index_name in ( "ix_saved_ideas_promoted_project_id", "ix_saved_ideas_launch_draft_id", "ix_saved_ideas_status", "ix_saved_ideas_source_type", "ix_saved_ideas_idea_id", "ix_saved_ideas_user_id", "ix_saved_ideas_tenant_id", ): op.drop_index(index_name, table_name="saved_ideas") op.drop_table("saved_ideas")