"""Add media library tables Revision ID: w1b2c3d4e5f6 Revises: v0a1b2c3d4e5 Create Date: 2026-01-06 10:00:00.000000 """ from collections.abc import Sequence import sqlalchemy as sa from alembic import op # revision identifiers, used by Alembic. revision: str = "w1b2c3d4e5f6" down_revision: str | None = "v0a1b2c3d4e5" branch_labels: str | Sequence[str] | None = None depends_on: str | Sequence[str] | None = None def upgrade() -> None: # Create media_files table op.create_table( "media_files", sa.Column("id", sa.Integer(), primary_key=True, index=True), sa.Column("vendor_id", sa.Integer(), sa.ForeignKey("vendors.id"), nullable=False), # File identification sa.Column("filename", sa.String(255), nullable=False), sa.Column("original_filename", sa.String(255)), sa.Column("file_path", sa.String(500), nullable=False), # File properties sa.Column("media_type", sa.String(20), nullable=False), # image, video, document sa.Column("mime_type", sa.String(100)), sa.Column("file_size", sa.Integer()), # Image/video dimensions sa.Column("width", sa.Integer()), sa.Column("height", sa.Integer()), # Thumbnail sa.Column("thumbnail_path", sa.String(500)), # Metadata sa.Column("alt_text", sa.String(500)), sa.Column("description", sa.Text()), sa.Column("folder", sa.String(100), default="general"), sa.Column("tags", sa.JSON()), sa.Column("extra_metadata", sa.JSON()), # Status sa.Column("is_optimized", sa.Boolean(), default=False), sa.Column("optimized_size", sa.Integer()), # Usage tracking sa.Column("usage_count", sa.Integer(), default=0), # Timestamps sa.Column("created_at", sa.DateTime(), server_default=sa.func.now()), sa.Column("updated_at", sa.DateTime(), onupdate=sa.func.now()), ) # Create indexes for media_files op.create_index("idx_media_vendor_id", "media_files", ["vendor_id"]) op.create_index("idx_media_vendor_folder", "media_files", ["vendor_id", "folder"]) op.create_index("idx_media_vendor_type", "media_files", ["vendor_id", "media_type"]) op.create_index("idx_media_filename", "media_files", ["filename"]) # Create product_media table (many-to-many relationship) op.create_table( "product_media", sa.Column("id", sa.Integer(), primary_key=True, index=True), sa.Column( "product_id", sa.Integer(), sa.ForeignKey("products.id", ondelete="CASCADE"), nullable=False, ), sa.Column( "media_id", sa.Integer(), sa.ForeignKey("media_files.id", ondelete="CASCADE"), nullable=False, ), # Usage type sa.Column("usage_type", sa.String(50), nullable=False, default="gallery"), # Display order for galleries sa.Column("display_order", sa.Integer(), default=0), # Variant-specific sa.Column("variant_id", sa.Integer()), # Timestamps sa.Column("created_at", sa.DateTime(), server_default=sa.func.now()), sa.Column("updated_at", sa.DateTime(), onupdate=sa.func.now()), # Unique constraint sa.UniqueConstraint("product_id", "media_id", "usage_type", name="uq_product_media_usage"), ) # Create indexes for product_media op.create_index("idx_product_media_product", "product_media", ["product_id"]) op.create_index("idx_product_media_media", "product_media", ["media_id"]) # Note: Unique constraint is defined in the table creation above via SQLAlchemy model # SQLite doesn't support adding constraints after table creation def downgrade() -> None: # Drop product_media table op.drop_index("idx_product_media_media", table_name="product_media") op.drop_index("idx_product_media_product", table_name="product_media") op.drop_table("product_media") # Drop media_files table op.drop_index("idx_media_filename", table_name="media_files") op.drop_index("idx_media_vendor_type", table_name="media_files") op.drop_index("idx_media_vendor_folder", table_name="media_files") op.drop_index("idx_media_vendor_id", table_name="media_files") op.drop_table("media_files")