AI Analysis and Content Strategy fixes. Enhanced Strategy Routes refactoring.
This commit is contained in:
106
backend/scripts/add_actual_provider_name_column.py
Normal file
106
backend/scripts/add_actual_provider_name_column.py
Normal file
@@ -0,0 +1,106 @@
|
||||
"""
|
||||
Database Migration Script: Add actual_provider_name column to api_usage_logs table
|
||||
|
||||
This script adds the actual_provider_name column to track real providers
|
||||
(WaveSpeed, Google, HuggingFace, etc.) instead of just generic enum values.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Add parent directory to path - handle both direct execution and module import
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
parent_dir = os.path.dirname(script_dir)
|
||||
if parent_dir not in sys.path:
|
||||
sys.path.insert(0, parent_dir)
|
||||
|
||||
from sqlalchemy import text
|
||||
from services.database import get_db
|
||||
from loguru import logger
|
||||
|
||||
def add_actual_provider_name_column():
|
||||
"""Add actual_provider_name column to api_usage_logs table if it doesn't exist."""
|
||||
|
||||
db = next(get_db())
|
||||
|
||||
try:
|
||||
# Check if column already exists (SQLite compatible)
|
||||
try:
|
||||
result = db.execute(text("PRAGMA table_info(api_usage_logs)"))
|
||||
columns = [row[1] for row in result.fetchall()]
|
||||
column_exists = 'actual_provider_name' in columns
|
||||
|
||||
if column_exists:
|
||||
logger.info("Column 'actual_provider_name' already exists in api_usage_logs table")
|
||||
return
|
||||
except Exception as e:
|
||||
# If PRAGMA fails, try MySQL/PostgreSQL approach
|
||||
try:
|
||||
result = db.execute(text("""
|
||||
SELECT COUNT(*) as count
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_NAME = 'api_usage_logs'
|
||||
AND COLUMN_NAME = 'actual_provider_name'
|
||||
"""))
|
||||
column_exists = result.fetchone()[0] > 0
|
||||
if column_exists:
|
||||
logger.info("Column 'actual_provider_name' already exists in api_usage_logs table")
|
||||
return
|
||||
except:
|
||||
# Column check failed, try to add anyway (will fail if exists)
|
||||
pass
|
||||
|
||||
# Add the column
|
||||
logger.info("Adding 'actual_provider_name' column to api_usage_logs table...")
|
||||
try:
|
||||
db.execute(text("""
|
||||
ALTER TABLE api_usage_logs
|
||||
ADD COLUMN actual_provider_name VARCHAR(50) NULL
|
||||
"""))
|
||||
db.commit()
|
||||
logger.success("Successfully added 'actual_provider_name' column to api_usage_logs table")
|
||||
except Exception as alter_error:
|
||||
# Column might already exist, check again
|
||||
if 'duplicate' in str(alter_error).lower() or 'already exists' in str(alter_error).lower():
|
||||
logger.info("Column 'actual_provider_name' already exists (detected during ALTER)")
|
||||
db.rollback()
|
||||
return
|
||||
raise
|
||||
|
||||
# Optionally, backfill existing records with detected provider names
|
||||
logger.info("Backfilling existing records with detected provider names...")
|
||||
from services.subscription.provider_detection import detect_actual_provider
|
||||
from models.subscription_models import APIUsageLog, APIProvider
|
||||
|
||||
# Get all records without actual_provider_name
|
||||
logs = db.query(APIUsageLog).filter(
|
||||
APIUsageLog.actual_provider_name.is_(None)
|
||||
).all()
|
||||
|
||||
updated_count = 0
|
||||
for log in logs:
|
||||
try:
|
||||
actual_provider = detect_actual_provider(
|
||||
provider_enum=log.provider,
|
||||
model_name=log.model_used,
|
||||
endpoint=log.endpoint
|
||||
)
|
||||
log.actual_provider_name = actual_provider
|
||||
updated_count += 1
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to detect provider for log {log.id}: {e}")
|
||||
|
||||
db.commit()
|
||||
logger.success(f"Backfilled {updated_count} existing records with actual provider names")
|
||||
|
||||
except Exception as e:
|
||||
db.rollback()
|
||||
logger.error(f"Error adding actual_provider_name column: {e}")
|
||||
raise
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
if __name__ == "__main__":
|
||||
logger.info("Starting migration: Add actual_provider_name column")
|
||||
add_actual_provider_name_column()
|
||||
logger.info("Migration completed successfully")
|
||||
148
backend/scripts/create_research_tables.py
Normal file
148
backend/scripts/create_research_tables.py
Normal file
@@ -0,0 +1,148 @@
|
||||
"""
|
||||
Database Migration Script for Research Projects
|
||||
Creates the research_projects table for cross-device project persistence.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
# Add the backend directory to Python path
|
||||
backend_dir = Path(__file__).parent.parent
|
||||
sys.path.insert(0, str(backend_dir))
|
||||
|
||||
from sqlalchemy import create_engine, text
|
||||
from loguru import logger
|
||||
import traceback
|
||||
|
||||
# Import models - ResearchProject uses SubscriptionBase
|
||||
from models.subscription_models import Base as SubscriptionBase
|
||||
from models.research_models import ResearchProject
|
||||
from services.database import DATABASE_URL
|
||||
|
||||
def create_research_tables():
|
||||
"""Create research-related tables."""
|
||||
|
||||
try:
|
||||
# Create engine
|
||||
engine = create_engine(DATABASE_URL, echo=False)
|
||||
|
||||
# Create all tables (ResearchProject uses SubscriptionBase, so it will be created)
|
||||
logger.info("Creating research projects tables...")
|
||||
SubscriptionBase.metadata.create_all(bind=engine)
|
||||
logger.info("✅ Research tables created successfully")
|
||||
|
||||
# Verify table was created
|
||||
display_setup_summary(engine)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"❌ Error creating research tables: {e}")
|
||||
logger.error(traceback.format_exc())
|
||||
raise
|
||||
|
||||
def display_setup_summary(engine):
|
||||
"""Display a summary of the created tables."""
|
||||
|
||||
try:
|
||||
with engine.connect() as conn:
|
||||
logger.info("\n" + "="*60)
|
||||
logger.info("RESEARCH PROJECTS SETUP SUMMARY")
|
||||
logger.info("="*60)
|
||||
|
||||
# Check if table exists (SQLite)
|
||||
check_query = text("""
|
||||
SELECT name FROM sqlite_master
|
||||
WHERE type='table' AND name='research_projects'
|
||||
""")
|
||||
|
||||
result = conn.execute(check_query)
|
||||
table_exists = result.fetchone()
|
||||
|
||||
if table_exists:
|
||||
logger.info("✅ Table 'research_projects' created successfully")
|
||||
|
||||
# Get table schema
|
||||
schema_query = text("""
|
||||
SELECT sql FROM sqlite_master
|
||||
WHERE type='table' AND name='research_projects'
|
||||
""")
|
||||
result = conn.execute(schema_query)
|
||||
schema = result.fetchone()
|
||||
if schema:
|
||||
logger.info("\n📋 Table Schema:")
|
||||
logger.info(schema[0])
|
||||
|
||||
# Check indexes
|
||||
indexes_query = text("""
|
||||
SELECT name FROM sqlite_master
|
||||
WHERE type='index' AND tbl_name='research_projects'
|
||||
""")
|
||||
result = conn.execute(indexes_query)
|
||||
indexes = result.fetchall()
|
||||
|
||||
if indexes:
|
||||
logger.info(f"\n📊 Indexes ({len(indexes)}):")
|
||||
for idx in indexes:
|
||||
logger.info(f" • {idx[0]}")
|
||||
|
||||
else:
|
||||
logger.warning("⚠️ Table 'research_projects' not found after creation")
|
||||
|
||||
logger.info("\n" + "="*60)
|
||||
logger.info("NEXT STEPS:")
|
||||
logger.info("="*60)
|
||||
logger.info("1. The research_projects table is ready for use")
|
||||
logger.info("2. Projects will automatically save to database after intent analysis")
|
||||
logger.info("3. Users can resume projects from any device")
|
||||
logger.info("4. Use the 'My Projects' button to view saved projects")
|
||||
logger.info("="*60)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error displaying summary: {e}")
|
||||
|
||||
def check_existing_table(engine):
|
||||
"""Check if research_projects table already exists."""
|
||||
|
||||
try:
|
||||
with engine.connect() as conn:
|
||||
check_query = text("""
|
||||
SELECT name FROM sqlite_master
|
||||
WHERE type='table' AND name='research_projects'
|
||||
""")
|
||||
|
||||
result = conn.execute(check_query)
|
||||
table_exists = result.fetchone()
|
||||
|
||||
if table_exists:
|
||||
logger.info("ℹ️ Table 'research_projects' already exists")
|
||||
logger.info(" Running migration will ensure schema is up to date...")
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error checking existing table: {e}")
|
||||
return False
|
||||
|
||||
if __name__ == "__main__":
|
||||
logger.info("🚀 Starting research projects database migration...")
|
||||
|
||||
try:
|
||||
# Create engine to check existing table
|
||||
engine = create_engine(DATABASE_URL, echo=False)
|
||||
|
||||
# Check existing table
|
||||
table_exists = check_existing_table(engine)
|
||||
|
||||
# Create tables (idempotent - won't recreate if exists)
|
||||
create_research_tables()
|
||||
|
||||
logger.info("✅ Migration completed successfully!")
|
||||
|
||||
except KeyboardInterrupt:
|
||||
logger.info("Migration cancelled by user")
|
||||
sys.exit(0)
|
||||
except Exception as e:
|
||||
logger.error(f"❌ Migration failed: {e}")
|
||||
traceback.print_exc()
|
||||
sys.exit(1)
|
||||
@@ -134,7 +134,7 @@ def display_setup_summary(engine):
|
||||
logger.info("NEXT STEPS:")
|
||||
logger.info("="*60)
|
||||
logger.info("1. Update your FastAPI app to include subscription routes:")
|
||||
logger.info(" from api.subscription_api import router as subscription_router")
|
||||
logger.info(" from api.subscription import router as subscription_router")
|
||||
logger.info(" app.include_router(subscription_router)")
|
||||
logger.info("\n2. Update database service to include subscription models:")
|
||||
logger.info(" Add SubscriptionBase.metadata.create_all(bind=engine) to init_database()")
|
||||
|
||||
72
backend/scripts/update_basic_tier_limits.py
Normal file
72
backend/scripts/update_basic_tier_limits.py
Normal file
@@ -0,0 +1,72 @@
|
||||
"""
|
||||
Update Basic Tier Limits and OSS Model Pricing
|
||||
Updates existing subscription plans and pricing without recreating tables.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
# Add the backend directory to Python path
|
||||
backend_dir = Path(__file__).parent.parent
|
||||
sys.path.insert(0, str(backend_dir))
|
||||
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
from loguru import logger
|
||||
import traceback
|
||||
|
||||
from services.database import DATABASE_URL
|
||||
from services.subscription.pricing_service import PricingService
|
||||
|
||||
def update_pricing_and_plans():
|
||||
"""Update pricing and plans without recreating tables."""
|
||||
|
||||
try:
|
||||
# Create engine
|
||||
engine = create_engine(DATABASE_URL, echo=False)
|
||||
|
||||
# Create session
|
||||
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
||||
db = SessionLocal()
|
||||
|
||||
try:
|
||||
# Initialize pricing and plans (will update existing)
|
||||
pricing_service = PricingService(db)
|
||||
|
||||
logger.info("🔄 Updating default API pricing (including OSS models)...")
|
||||
pricing_service.initialize_default_pricing()
|
||||
logger.info("✅ Default API pricing updated")
|
||||
|
||||
logger.info("🔄 Updating default subscription plans (Basic tier limits)...")
|
||||
pricing_service.initialize_default_plans()
|
||||
logger.info("✅ Default subscription plans updated")
|
||||
|
||||
logger.info("🎉 Pricing and plans update completed successfully!")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"❌ Error updating pricing/plans: {e}")
|
||||
logger.error(traceback.format_exc())
|
||||
db.rollback()
|
||||
raise
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"❌ Error: {e}")
|
||||
logger.error(traceback.format_exc())
|
||||
raise
|
||||
|
||||
if __name__ == "__main__":
|
||||
logger.info("🚀 Updating Basic Tier Limits and OSS Model Pricing...")
|
||||
|
||||
try:
|
||||
update_pricing_and_plans()
|
||||
logger.info("✅ Update completed successfully!")
|
||||
|
||||
except KeyboardInterrupt:
|
||||
logger.info("Update cancelled by user")
|
||||
sys.exit(0)
|
||||
except Exception as e:
|
||||
logger.error(f"❌ Update failed: {e}")
|
||||
sys.exit(1)
|
||||
Reference in New Issue
Block a user