"""drawing uploads stored with the package (CR-007 / D8) The field wants the specific PDF attached, not a link to a Bluebeam session: a general foreman opens the package and sees exactly the sheet relevant to their scope, offline. The bytes live in this table - IN the same database as everything else, settled Aug 18: splitting files out was rejected because a backup that excludes the drawings is a backup you cannot restore from. The cost of that decision is bounded by the D8 numbers, enforced in the API: 5MB a file, PDFs and images only, 2GB per project with a warning at 80%. Additive only: a new table, no change to any existing one, so nothing to backfill and nothing to migrate. Revision ID: f3a9d2c1e8b7 Revises: e2a4c7d91b30 Create Date: 2026-08-19 11:20:00.000000 """ from alembic import op import sqlalchemy as sa # revision identifiers, used by Alembic. revision = 'f3a9d2c1e8b7' down_revision = 'e2a4c7d91b30' branch_labels = None depends_on = None def upgrade() -> None: op.create_table( 'wp_files', sa.Column('id', sa.String(length=40), nullable=False), sa.Column('wp_id', sa.String(length=40), nullable=False), sa.Column('project_id', sa.String(length=40), nullable=False), sa.Column('name', sa.String(length=300), nullable=False, server_default=''), sa.Column('mime', sa.String(length=100), nullable=False, server_default=''), sa.Column('size', sa.Integer(), nullable=False, server_default='0'), sa.Column('description', sa.String(length=500), nullable=False, server_default=''), sa.Column('data', sa.LargeBinary(), nullable=False), sa.Column('uploaded_by', sa.String(length=120), nullable=False, server_default=''), sa.Column('created_at', sa.DateTime(timezone=True), nullable=True), sa.PrimaryKeyConstraint('id'), ) op.create_index('ix_wp_files_wp_id', 'wp_files', ['wp_id']) op.create_index('ix_wp_files_project_id', 'wp_files', ['project_id']) def downgrade() -> None: op.drop_index('ix_wp_files_project_id', table_name='wp_files') op.drop_index('ix_wp_files_wp_id', table_name='wp_files') op.drop_table('wp_files')