Spaces:
Running
Running
| from sqlalchemy import create_engine, text | |
| from sqlalchemy.ext.declarative import declarative_base | |
| from sqlalchemy.orm import sessionmaker | |
| import os | |
| from app.config import settings | |
| DATABASE_URL = settings.database_url or os.getenv("DATABASE_URL", "sqlite:///./amazon_intel.db") | |
| if DATABASE_URL.startswith("sqlite"): | |
| engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False}) | |
| else: | |
| engine = create_engine(DATABASE_URL, pool_pre_ping=True, pool_recycle=300) | |
| SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) | |
| Base = declarative_base() | |
| def migrate_schema(): | |
| """Add columns when schema evolves (SQLite + PostgreSQL).""" | |
| user_alters_sqlite = [ | |
| "ALTER TABLE users ADD COLUMN token_version INTEGER DEFAULT 0", | |
| "ALTER TABLE users ADD COLUMN auth_provider VARCHAR(20) DEFAULT 'email'", | |
| "ALTER TABLE users ADD COLUMN firebase_uid VARCHAR(128)", | |
| ] | |
| user_alters_pg = [ | |
| "ALTER TABLE users ADD COLUMN IF NOT EXISTS token_version INTEGER DEFAULT 0", | |
| "ALTER TABLE users ADD COLUMN IF NOT EXISTS auth_provider VARCHAR(20) DEFAULT 'email'", | |
| "ALTER TABLE users ADD COLUMN IF NOT EXISTS firebase_uid VARCHAR(128)", | |
| ] | |
| sqlite_product_alters = [ | |
| "ALTER TABLE products ADD COLUMN seller_count INTEGER", | |
| "ALTER TABLE products ADD COLUMN buy_box_winner VARCHAR(255)", | |
| "ALTER TABLE products ADD COLUMN buy_box_price NUMERIC(10,2)", | |
| "ALTER TABLE products ADD COLUMN buy_box_is_fba BOOLEAN DEFAULT 1", | |
| "ALTER TABLE products ADD COLUMN is_amazon_sold BOOLEAN DEFAULT 0", | |
| "ALTER TABLE products ADD COLUMN last_data_source VARCHAR(20) DEFAULT 'cached'", | |
| "ALTER TABLE products ADD COLUMN upc VARCHAR(20)", | |
| "ALTER TABLE products ADD COLUMN has_buy_box BOOLEAN DEFAULT 1", | |
| "ALTER TABLE products ADD COLUMN package_weight_lbs NUMERIC(8,3)", | |
| "ALTER TABLE products ADD COLUMN other_sellers_json TEXT", | |
| "ALTER TABLE products ADD COLUMN offers_source VARCHAR(30)", | |
| "ALTER TABLE products ADD COLUMN marketplace VARCHAR(8) DEFAULT 'us'", | |
| "ALTER TABLE products ADD COLUMN currency VARCHAR(8) DEFAULT 'USD'", | |
| ] | |
| pg_product_alters = [ | |
| "ALTER TABLE products ADD COLUMN IF NOT EXISTS upc VARCHAR(20)", | |
| "ALTER TABLE products ADD COLUMN IF NOT EXISTS has_buy_box BOOLEAN DEFAULT TRUE", | |
| "ALTER TABLE products ADD COLUMN IF NOT EXISTS package_weight_lbs NUMERIC(8,3)", | |
| "ALTER TABLE products ADD COLUMN IF NOT EXISTS other_sellers_json TEXT", | |
| "ALTER TABLE products ADD COLUMN IF NOT EXISTS offers_source VARCHAR(30)", | |
| "ALTER TABLE products ADD COLUMN IF NOT EXISTS marketplace VARCHAR(8) DEFAULT 'us'", | |
| "ALTER TABLE products ADD COLUMN IF NOT EXISTS currency VARCHAR(8) DEFAULT 'USD'", | |
| ] | |
| is_pg = DATABASE_URL.startswith("postgresql") | |
| with engine.connect() as conn: | |
| for sql in (user_alters_pg if is_pg else user_alters_sqlite): | |
| try: | |
| conn.execute(text(sql)) | |
| conn.commit() | |
| except Exception: | |
| pass | |
| # Google-only accounts may have no password | |
| if is_pg: | |
| try: | |
| conn.execute(text("ALTER TABLE users ALTER COLUMN password_hash DROP NOT NULL")) | |
| conn.commit() | |
| except Exception: | |
| pass | |
| if DATABASE_URL.startswith("sqlite"): | |
| for sql in sqlite_product_alters: | |
| try: | |
| conn.execute(text(sql)) | |
| conn.commit() | |
| except Exception: | |
| pass | |
| if is_pg: | |
| for sql in pg_product_alters: | |
| try: | |
| conn.execute(text(sql)) | |
| conn.commit() | |
| except Exception: | |
| pass | |
| # Prefer (asin, marketplace) uniqueness so US + AE can coexist | |
| for sql in ( | |
| "UPDATE products SET marketplace = 'us' WHERE marketplace IS NULL", | |
| "UPDATE products SET currency = 'USD' WHERE currency IS NULL AND (marketplace = 'us' OR marketplace IS NULL)", | |
| "ALTER TABLE products DROP CONSTRAINT IF EXISTS products_asin_key", | |
| "ALTER TABLE products DROP CONSTRAINT IF EXISTS ix_products_asin", | |
| "CREATE UNIQUE INDEX IF NOT EXISTS uq_products_asin_marketplace ON products (asin, marketplace)", | |
| ): | |
| try: | |
| conn.execute(text(sql)) | |
| conn.commit() | |
| except Exception: | |
| pass | |
| else: | |
| for sql in ( | |
| "UPDATE products SET marketplace = 'us' WHERE marketplace IS NULL", | |
| "UPDATE products SET currency = 'USD' WHERE currency IS NULL", | |
| ): | |
| try: | |
| conn.execute(text(sql)) | |
| conn.commit() | |
| except Exception: | |
| pass | |
| def get_db(): | |
| db = SessionLocal() | |
| try: | |
| yield db | |
| finally: | |
| db.close() | |