"""CSV-Import: Templates, Batches, Kategorisierungs-Regeln, Transaktions-Herkunft. Revision ID: 0005 Revises: 0004 Create Date: 2026-08-19 """ from alembic import op import sqlalchemy as sa revision = "0005" down_revision = "0004" branch_labels = None depends_on = None def upgrade() -> None: op.create_table( "import_templates", sa.Column("id", sa.Integer(), primary_key=True), sa.Column("owner_id", sa.Integer(), sa.ForeignKey("users.id", ondelete="CASCADE"), nullable=False), sa.Column("name", sa.String(length=120), nullable=False), sa.Column("delimiter", sa.String(length=2), nullable=False, server_default=";"), sa.Column("decimal_sep", sa.String(length=1), nullable=False, server_default=","), sa.Column("date_format", sa.String(length=32), nullable=False, server_default="%d.%m.%Y"), sa.Column("encoding", sa.String(length=16), nullable=False, server_default="utf-8"), sa.Column("has_header", sa.Boolean(), nullable=False, server_default=sa.text("1")), sa.Column("skip_rows", sa.Integer(), nullable=False, server_default=sa.text("0")), sa.Column("amount_mode", sa.String(length=32), nullable=False, server_default="signed"), sa.Column("column_map", sa.Text(), nullable=False, server_default="{}"), sa.Column("created_at", sa.DateTime(timezone=True), nullable=True), ) op.create_index("ix_import_templates_owner_id", "import_templates", ["owner_id"]) op.create_table( "import_batches", sa.Column("id", sa.Integer(), primary_key=True), sa.Column("owner_id", sa.Integer(), sa.ForeignKey("users.id", ondelete="CASCADE"), nullable=False), sa.Column("account_id", sa.Integer(), sa.ForeignKey("accounts.id", ondelete="CASCADE"), nullable=False), sa.Column("template_id", sa.Integer(), sa.ForeignKey("import_templates.id", ondelete="SET NULL"), nullable=True), sa.Column("filename", sa.String(length=255), nullable=False, server_default=""), sa.Column("row_count", sa.Integer(), nullable=False, server_default=sa.text("0")), sa.Column("imported_count", sa.Integer(), nullable=False, server_default=sa.text("0")), sa.Column("status", sa.String(length=32), nullable=False, server_default="committed"), sa.Column("created_at", sa.DateTime(timezone=True), nullable=True), ) op.create_index("ix_import_batches_owner_id", "import_batches", ["owner_id"]) op.create_table( "categorization_rules", sa.Column("id", sa.Integer(), primary_key=True), sa.Column("owner_id", sa.Integer(), sa.ForeignKey("users.id", ondelete="CASCADE"), nullable=False), sa.Column("match_field", sa.String(length=32), nullable=False, server_default="payee"), sa.Column("pattern", sa.String(length=255), nullable=False), sa.Column("category_id", sa.Integer(), sa.ForeignKey("categories.id", ondelete="CASCADE"), nullable=True), sa.Column("priority", sa.Integer(), nullable=False, server_default=sa.text("0")), sa.Column("hits", sa.Integer(), nullable=False, server_default=sa.text("0")), sa.Column("created_at", sa.DateTime(timezone=True), nullable=True), sa.UniqueConstraint("owner_id", "match_field", "pattern", name="uq_rule_owner_field_pattern"), ) op.create_index("ix_categorization_rules_owner_id", "categorization_rules", ["owner_id"]) # Transaktions-Herkunft (für Undo + Duplikaterkennung). op.add_column("transactions", sa.Column("import_batch_id", sa.Integer(), nullable=True)) op.add_column("transactions", sa.Column("import_hash", sa.String(length=64), nullable=True)) op.create_index("ix_transactions_import_batch_id", "transactions", ["import_batch_id"]) op.create_index("ix_transactions_import_hash", "transactions", ["import_hash"]) def downgrade() -> None: op.drop_index("ix_transactions_import_hash", table_name="transactions") op.drop_index("ix_transactions_import_batch_id", table_name="transactions") with op.batch_alter_table("transactions") as batch: batch.drop_column("import_hash") batch.drop_column("import_batch_id") op.drop_index("ix_categorization_rules_owner_id", table_name="categorization_rules") op.drop_table("categorization_rules") op.drop_index("ix_import_batches_owner_id", table_name="import_batches") op.drop_table("import_batches") op.drop_index("ix_import_templates_owner_id", table_name="import_templates") op.drop_table("import_templates")