diff --git a/alembic/versions/eed20ee8cc26_add_is_sent_column.py b/alembic/versions/eed20ee8cc26_add_is_sent_column.py new file mode 100644 index 0000000..169416b --- /dev/null +++ b/alembic/versions/eed20ee8cc26_add_is_sent_column.py @@ -0,0 +1,194 @@ +"""add_is_sent_column + +Revision ID: eed20ee8cc26 +Revises: 567cd83d63c2 +Create Date: 2026-05-09 15:28:04.189854 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision: str = 'eed20ee8cc26' +down_revision: Union[str, Sequence[str], None] = '567cd83d63c2' +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + """Upgrade schema.""" + # ### commands auto generated by Alembic - please adjust! ### + op.drop_index(op.f('idx_crawl_results_crawled_at'), table_name='crawl_results') + op.drop_table('crawl_results') + op.drop_table('auto_announcements') + op.drop_index(op.f('idx_dahuagov_content_hash'), table_name='dahuagov_announcements') + op.drop_index(op.f('idx_dahuagov_created_at'), table_name='dahuagov_announcements') + op.drop_index(op.f('idx_dahuagov_publish_date'), table_name='dahuagov_announcements') + op.drop_table('dahuagov_announcements') + op.drop_table('manual_announcements') + op.drop_table('announcement_sources') + op.add_column('announcements', sa.Column('is_sent', sa.Boolean(), nullable=False, server_default=sa.false())) + op.alter_column('announcements', 'purchase_name', + existing_type=sa.VARCHAR(length=200), + nullable=False) + op.alter_column('announcements', 'content_url', + existing_type=sa.TEXT(), + nullable=False) + op.alter_column('announcements', 'content_hash', + existing_type=sa.VARCHAR(length=32), + type_=sa.String(length=64), + nullable=False) + op.alter_column('announcements', 'crawl_mode', + existing_type=sa.VARCHAR(length=20), + nullable=False, + existing_server_default=sa.text("'auto'::character varying")) + op.alter_column('announcements', 'is_new', + existing_type=sa.BOOLEAN(), + nullable=False, + existing_server_default=sa.text('true')) + op.alter_column('announcements', 'keyword_matched', + existing_type=sa.BOOLEAN(), + nullable=False, + existing_server_default=sa.text('false')) + op.alter_column('announcements', 'created_at', + existing_type=postgresql.TIMESTAMP(), + nullable=False, + existing_server_default=sa.text('CURRENT_TIMESTAMP')) + op.alter_column('announcements', 'updated_at', + existing_type=postgresql.TIMESTAMP(), + nullable=False, + existing_server_default=sa.text('CURRENT_TIMESTAMP')) + op.drop_index(op.f('idx_announcements_content_hash'), table_name='announcements') + op.drop_index(op.f('idx_announcements_created_at'), table_name='announcements') + op.drop_index(op.f('idx_announcements_publish_date'), table_name='announcements') + op.drop_index(op.f('idx_announcements_source_code'), table_name='announcements') + op.drop_column('announcements', 'date_filtered') + op.drop_column('announcements', 'crawled_at') + op.drop_column('announcements', 'is_today') + # ### end Alembic commands ### + + +def downgrade() -> None: + """Downgrade schema.""" + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('announcements', sa.Column('is_today', sa.BOOLEAN(), server_default=sa.text('false'), autoincrement=False, nullable=True)) + op.add_column('announcements', sa.Column('crawled_at', postgresql.TIMESTAMP(), autoincrement=False, nullable=True)) + op.add_column('announcements', sa.Column('date_filtered', sa.BOOLEAN(), server_default=sa.text('true'), autoincrement=False, nullable=True)) + op.create_index(op.f('idx_announcements_source_code'), 'announcements', ['source_code'], unique=False) + op.create_index(op.f('idx_announcements_publish_date'), 'announcements', [sa.literal_column('publish_date DESC')], unique=False) + op.create_index(op.f('idx_announcements_created_at'), 'announcements', [sa.literal_column('created_at DESC')], unique=False) + op.create_index(op.f('idx_announcements_content_hash'), 'announcements', ['content_hash'], unique=False) + op.alter_column('announcements', 'updated_at', + existing_type=postgresql.TIMESTAMP(), + nullable=True, + existing_server_default=sa.text('CURRENT_TIMESTAMP')) + op.alter_column('announcements', 'created_at', + existing_type=postgresql.TIMESTAMP(), + nullable=True, + existing_server_default=sa.text('CURRENT_TIMESTAMP')) + op.alter_column('announcements', 'keyword_matched', + existing_type=sa.BOOLEAN(), + nullable=True, + existing_server_default=sa.text('false')) + op.alter_column('announcements', 'is_new', + existing_type=sa.BOOLEAN(), + nullable=True, + existing_server_default=sa.text('true')) + op.alter_column('announcements', 'crawl_mode', + existing_type=sa.VARCHAR(length=20), + nullable=True, + existing_server_default=sa.text("'auto'::character varying")) + op.alter_column('announcements', 'content_hash', + existing_type=sa.String(length=64), + type_=sa.VARCHAR(length=32), + nullable=True) + op.alter_column('announcements', 'content_url', + existing_type=sa.TEXT(), + nullable=True) + op.alter_column('announcements', 'purchase_name', + existing_type=sa.VARCHAR(length=200), + nullable=True) + op.drop_column('announcements', 'is_sent') + op.create_table('announcement_sources', + sa.Column('code', sa.VARCHAR(length=50), autoincrement=False, nullable=False), + sa.Column('category_id', sa.INTEGER(), autoincrement=False, nullable=False), + sa.Column('name', sa.VARCHAR(length=100), autoincrement=False, nullable=False), + sa.Column('type', sa.VARCHAR(length=50), autoincrement=False, nullable=False), + sa.PrimaryKeyConstraint('code', name=op.f('announcement_sources_pkey')) + ) + op.create_table('manual_announcements', + sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False), + sa.Column('title', sa.VARCHAR(length=500), autoincrement=False, nullable=False), + sa.Column('publish_date', postgresql.TIMESTAMP(), autoincrement=False, nullable=False), + sa.Column('purchase_name', sa.VARCHAR(length=200), autoincrement=False, nullable=True), + sa.Column('content_url', sa.TEXT(), autoincrement=False, nullable=True), + sa.Column('source_code', sa.VARCHAR(length=50), autoincrement=False, nullable=False), + sa.Column('source_name', sa.VARCHAR(length=100), autoincrement=False, nullable=False), + sa.Column('announcement_type', sa.VARCHAR(length=50), autoincrement=False, nullable=False), + sa.Column('crawled_at', postgresql.TIMESTAMP(), autoincrement=False, nullable=True), + sa.Column('created_at', postgresql.TIMESTAMP(), server_default=sa.text('CURRENT_TIMESTAMP'), autoincrement=False, nullable=True), + sa.Column('updated_at', postgresql.TIMESTAMP(), server_default=sa.text('CURRENT_TIMESTAMP'), autoincrement=False, nullable=True), + sa.Column('content_hash', sa.VARCHAR(length=32), autoincrement=False, nullable=True), + sa.Column('keyword_matched', sa.BOOLEAN(), server_default=sa.text('false'), autoincrement=False, nullable=True), + sa.Column('date_filtered', sa.BOOLEAN(), server_default=sa.text('true'), autoincrement=False, nullable=True), + sa.Column('is_new', sa.BOOLEAN(), server_default=sa.text('true'), autoincrement=False, nullable=True), + sa.Column('is_today', sa.BOOLEAN(), server_default=sa.text('false'), autoincrement=False, nullable=True), + sa.PrimaryKeyConstraint('id', name=op.f('manual_announcements_pkey')) + ) + op.create_table('dahuagov_announcements', + sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False), + sa.Column('title', sa.VARCHAR(length=500), autoincrement=False, nullable=False), + sa.Column('publish_date', postgresql.TIMESTAMP(), autoincrement=False, nullable=False), + sa.Column('purchase_name', sa.VARCHAR(length=200), autoincrement=False, nullable=True), + sa.Column('content_url', sa.TEXT(), autoincrement=False, nullable=True), + sa.Column('source_code', sa.VARCHAR(length=50), server_default=sa.text("'dahuagov'::character varying"), autoincrement=False, nullable=False), + sa.Column('source_name', sa.VARCHAR(length=100), server_default=sa.text("'大化县政府网采购公告'::character varying"), autoincrement=False, nullable=False), + sa.Column('announcement_type', sa.VARCHAR(length=50), server_default=sa.text("'purchase'::character varying"), autoincrement=False, nullable=False), + sa.Column('crawled_at', postgresql.TIMESTAMP(), autoincrement=False, nullable=True), + sa.Column('created_at', postgresql.TIMESTAMP(), server_default=sa.text('CURRENT_TIMESTAMP'), autoincrement=False, nullable=True), + sa.Column('updated_at', postgresql.TIMESTAMP(), server_default=sa.text('CURRENT_TIMESTAMP'), autoincrement=False, nullable=True), + sa.Column('content_hash', sa.VARCHAR(length=32), autoincrement=False, nullable=True), + sa.Column('is_new', sa.BOOLEAN(), server_default=sa.text('true'), autoincrement=False, nullable=True), + sa.PrimaryKeyConstraint('id', name=op.f('dahuagov_announcements_pkey')), + sa.UniqueConstraint('content_hash', name=op.f('dahuagov_announcements_content_hash_key'), postgresql_include=[], postgresql_nulls_not_distinct=False) + ) + op.create_index(op.f('idx_dahuagov_publish_date'), 'dahuagov_announcements', [sa.literal_column('publish_date DESC')], unique=False) + op.create_index(op.f('idx_dahuagov_created_at'), 'dahuagov_announcements', [sa.literal_column('created_at DESC')], unique=False) + op.create_index(op.f('idx_dahuagov_content_hash'), 'dahuagov_announcements', ['content_hash'], unique=False) + op.create_table('auto_announcements', + sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False), + sa.Column('title', sa.VARCHAR(length=500), autoincrement=False, nullable=False), + sa.Column('publish_date', postgresql.TIMESTAMP(), autoincrement=False, nullable=False), + sa.Column('purchase_name', sa.VARCHAR(length=200), autoincrement=False, nullable=True), + sa.Column('content_url', sa.TEXT(), autoincrement=False, nullable=True), + sa.Column('source_code', sa.VARCHAR(length=50), autoincrement=False, nullable=False), + sa.Column('source_name', sa.VARCHAR(length=100), autoincrement=False, nullable=False), + sa.Column('announcement_type', sa.VARCHAR(length=50), autoincrement=False, nullable=False), + sa.Column('crawled_at', postgresql.TIMESTAMP(), autoincrement=False, nullable=True), + sa.Column('created_at', postgresql.TIMESTAMP(), server_default=sa.text('CURRENT_TIMESTAMP'), autoincrement=False, nullable=True), + sa.Column('updated_at', postgresql.TIMESTAMP(), server_default=sa.text('CURRENT_TIMESTAMP'), autoincrement=False, nullable=True), + sa.Column('content_hash', sa.VARCHAR(length=32), autoincrement=False, nullable=True), + sa.Column('keyword_matched', sa.BOOLEAN(), server_default=sa.text('false'), autoincrement=False, nullable=True), + sa.Column('date_filtered', sa.BOOLEAN(), server_default=sa.text('true'), autoincrement=False, nullable=True), + sa.Column('is_new', sa.BOOLEAN(), server_default=sa.text('true'), autoincrement=False, nullable=True), + sa.Column('is_today', sa.BOOLEAN(), server_default=sa.text('false'), autoincrement=False, nullable=True), + sa.PrimaryKeyConstraint('id', name=op.f('auto_announcements_pkey')), + sa.UniqueConstraint('content_hash', name=op.f('auto_announcements_content_hash_key'), postgresql_include=[], postgresql_nulls_not_distinct=False) + ) + op.create_table('crawl_results', + sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False), + sa.Column('source_code', sa.VARCHAR(length=50), autoincrement=False, nullable=False), + sa.Column('status', sa.VARCHAR(length=20), autoincrement=False, nullable=False), + sa.Column('total_count', sa.INTEGER(), server_default=sa.text('0'), autoincrement=False, nullable=True), + sa.Column('new_count', sa.INTEGER(), server_default=sa.text('0'), autoincrement=False, nullable=True), + sa.Column('error_message', sa.TEXT(), autoincrement=False, nullable=True), + sa.Column('crawled_at', postgresql.TIMESTAMP(), server_default=sa.text('CURRENT_TIMESTAMP'), autoincrement=False, nullable=True), + sa.Column('duration', sa.DOUBLE_PRECISION(precision=53), server_default=sa.text('0.0'), autoincrement=False, nullable=True), + sa.ForeignKeyConstraint(['source_code'], ['announcement_sources.code'], name=op.f('crawl_results_source_code_fkey')), + sa.PrimaryKeyConstraint('id', name=op.f('crawl_results_pkey')) + ) + op.create_index(op.f('idx_crawl_results_crawled_at'), 'crawl_results', [sa.literal_column('crawled_at DESC')], unique=False) + # ### end Alembic commands ###