"""Alembic Environment Configuration""" from logging.config import fileConfig from sqlalchemy import pool from sqlalchemy import create_engine from alembic import context # Import models directly (avoid env file issues) from sqlalchemy import Column, Integer, String, DateTime, Float, Boolean, Text, JSON from sqlalchemy.ext.declarative import declarative_base from datetime import datetime Base = declarative_base() # Import models manually class Invoice(Base): __tablename__ = "invoices" id = Column(Integer, primary_key=True) email_id = Column(String, index=True) email_subject = Column(String, nullable=True) email_from = Column(String, nullable=True) email_date = Column(DateTime, nullable=True) invoice_number = Column(String, index=True, nullable=True) invoice_date = Column(DateTime, nullable=True) invoice_amount = Column(Float, nullable=True) invoice_tax_amount = Column(Float, nullable=True) invoice_tax_rate = Column(Float, nullable=True) invoice_tax_type = Column(String, nullable=True) issuer_name = Column(String, nullable=True) issuer_address = Column(Text, nullable=True) file_path = Column(String, nullable=True) file_name = Column(String, nullable=True) storage_year = Column(Integer, nullable=True) storage_path = Column(String, nullable=True) processed = Column(Boolean, default=False) processing_error = Column(Text, nullable=True) confidence_score = Column(Float, nullable=True) created_at = Column(DateTime, default=datetime.utcnow) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) class EmailLog(Base): __tablename__ = "email_logs" id = Column(Integer, primary_key=True) email_id = Column(String, unique=True, index=True) email_subject = Column(String, nullable=True) email_from = Column(String, nullable=True) email_date = Column(DateTime, nullable=True) email_folder = Column(String, nullable=True) matched_keywords = Column(JSON, nullable=True) has_attachment = Column(Boolean, default=False) attachment_type = Column(String, nullable=True) processed = Column(Boolean, default=False) processing_result = Column(String, nullable=True) invoice_id = Column(Integer, nullable=True) created_at = Column(DateTime, default=datetime.utcnow) class InvoiceDetail(Base): __tablename__ = "invoice_details" id = Column(Integer, primary_key=True) invoice_id = Column(Integer, nullable=False, index=True) raw_text = Column(Text, nullable=True) parsed_data = Column(JSON, nullable=True) confidence_breakdown = Column(JSON, nullable=True) processing_notes = Column(Text, nullable=True) created_at = Column(DateTime, default=datetime.utcnow) class User(Base): __tablename__ = "users" id = Column(Integer, primary_key=True) username = Column(String, unique=True, index=True) hashed_password = Column(String) is_active = Column(Boolean, default=True) created_at = Column(DateTime, default=datetime.utcnow) # Set target metadata for autogenerate target_metadata = Base.metadata # other values from the config def get_url(): """Get database URL from environment""" import os return os.getenv("DATABASE_URL", "postgresql+psycopg2://postgres:postgres@localhost:5432/invoice_check") def run_migrations_offline() -> None: """Run migrations in 'offline' mode.""" url = get_url() context.configure( url=url, target_metadata=target_metadata, literal_binds=True, dialect_opts={"paramstyle": "named"}, render_as_batch=True, ) with context.begin_transaction(): context.run_migrations() def run_migrations_online() -> None: """Run migrations in 'online' mode.""" url = get_url() connectable = create_engine( url, poolclass=pool.NullPool, ) with connectable.connect() as connection: context.configure( connection=connection, target_metadata=target_metadata, render_as_batch=True, ) with context.begin_transaction(): context.run_migrations() if context.is_offline_mode(): run_migrations_offline() else: run_migrations_online()