Files
orion/scripts/verify_setup.py
Samir Boulahtit d7a0ff8818 refactor: complete module-driven architecture migration
This commit completes the migration to a fully module-driven architecture:

## Models Migration
- Moved all domain models from models/database/ to their respective modules:
  - tenancy: User, Admin, Vendor, Company, Platform, VendorDomain, etc.
  - cms: MediaFile, VendorTheme
  - messaging: Email, VendorEmailSettings, VendorEmailTemplate
  - core: AdminMenuConfig
- models/database/ now only contains Base and TimestampMixin (infrastructure)

## Schemas Migration
- Moved all domain schemas from models/schema/ to their respective modules:
  - tenancy: company, vendor, admin, team, vendor_domain
  - cms: media, image, vendor_theme
  - messaging: email
- models/schema/ now only contains base.py and auth.py (infrastructure)

## Routes Migration
- Moved admin routes from app/api/v1/admin/ to modules:
  - menu_config.py -> core module
  - modules.py -> tenancy module
  - module_config.py -> tenancy module
- app/api/v1/admin/ now only aggregates auto-discovered module routes

## Menu System
- Implemented module-driven menu system with MenuDiscoveryService
- Extended FrontendType enum: PLATFORM, ADMIN, VENDOR, STOREFRONT
- Added MenuItemDefinition and MenuSectionDefinition dataclasses
- Each module now defines its own menu items in definition.py
- MenuService integrates with MenuDiscoveryService for template rendering

## Documentation
- Updated docs/architecture/models-structure.md
- Updated docs/architecture/menu-management.md
- Updated architecture validation rules for new exceptions

## Architecture Validation
- Updated MOD-019 rule to allow base.py in models/schema/
- Created core module exceptions.py and schemas/ directory
- All validation errors resolved (only warnings remain)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 21:02:56 +01:00

254 lines
7.7 KiB
Python

# scripts/verify_setup.py
"""Verify database setup and migration status using project configuration."""
import os
import sys
from urllib.parse import urlparse
from alembic.config import Config
from sqlalchemy import create_engine, text
from alembic import command
# Add project root to Python path
sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
from app.core.config import settings
def get_database_info():
"""Get database type and path from configuration."""
db_url = settings.database_url
parsed = urlparse(db_url)
db_type = parsed.scheme
if db_type == "sqlite":
# Extract path from sqlite:///./path or sqlite:///path
db_path = db_url.replace("sqlite:///", "")
if db_path.startswith("./"):
db_path = db_path[2:]
return db_type, db_path
return db_type, None
def verify_database_setup():
"""Verify database and migration setup using config."""
print("[VERIFY] Verifying database setup...")
print(f"[CONFIG] Database URL: {settings.database_url}")
print()
db_type, db_path = get_database_info()
print(f"[INFO] Database type: {db_type}")
if db_type == "sqlite":
if not os.path.exists(db_path):
print(f"[ERROR] Database file not found: {db_path}")
return False
print(f"[OK] Database file exists: {db_path}")
else:
print(f"[INFO] Using {db_type} database (connection will be tested)")
try:
# Create engine using the configured URL
engine = create_engine(settings.database_url)
with engine.connect() as conn:
# Get table list (works for both SQLite and PostgreSQL)
if db_type == "sqlite":
result = conn.execute(
text("SELECT name FROM sqlite_master WHERE type='table'")
)
else:
result = conn.execute(
text("SELECT tablename FROM pg_tables WHERE schemaname='public'")
)
tables = [row[0] for row in result.fetchall()]
print(f"[OK] Found {len(tables)} tables:")
# Expected tables from your models
expected_tables = [
"users",
"products",
"inventory",
"vendors",
"products",
"marketplace_import_jobs",
"alembic_version",
]
for table in sorted(tables):
if table == "alembic_version":
print(f" * {table} (migration tracking)")
elif table in expected_tables:
print(f" * {table}")
else:
print(f" ? {table} (unexpected)")
# Check for missing expected tables
missing_tables = set(expected_tables) - set(tables) - {"alembic_version"}
if missing_tables:
print(f"[WARNING] Missing expected tables: {missing_tables}")
# Check if alembic_version table exists
if "alembic_version" in tables:
result = conn.execute(text("SELECT version_num FROM alembic_version"))
version = result.fetchone()
if version:
print(f"[OK] Migration version: {version[0]}")
else:
print("[WARNING] No migration version recorded")
else:
print("[ERROR] No alembic_version table - migrations not initialized")
return False
except Exception as e:
print(f"[ERROR] Database connection failed: {e}")
print("[HINT] Check your DATABASE_URL in .env file")
return False
# Check Alembic configuration
try:
alembic_cfg = Config("alembic.ini")
print("[OK] Alembic configuration found")
# Try to get current migration
print()
print("[MIGRATE] Current migration status:")
command.current(alembic_cfg, verbose=True)
except Exception as e:
print(f"[ERROR] Alembic configuration issue: {e}")
return False
print()
print("[SUCCESS] Database setup verification completed!")
return True
def verify_model_structure():
"""Verify both database and API model structure."""
print("[MODELS] Verifying model structure...")
# Test database models
try:
from models.database.base import Base
print("[OK] Database Base imported")
print(
f"[INFO] Found {len(Base.metadata.tables)} database tables: {list(Base.metadata.tables.keys())}"
)
# Import specific models
from app.modules.inventory.models import Inventory
from app.modules.marketplace.models import MarketplaceImportJob, MarketplaceProduct
from app.modules.catalog.models import Product
from app.modules.tenancy.models import User
from app.modules.tenancy.models import Vendor
print("[OK] All database models imported successfully")
except ImportError as e:
print(f"[ERROR] Database model import failed: {e}")
return False
# Test API models
try:
import models.schema
print("[OK] API models package imported")
# Test specific API model imports
api_modules = [
"base",
"auth",
"product",
"inventory",
"vendor ",
"marketplace",
"admin",
"stats",
]
for module in api_modules:
try:
__import__(f"models.api.{module}")
print(f" * models.api.{module}")
except ImportError:
print(f" ? models.api.{module} (not found, optional)")
except ImportError as e:
print(f"[WARNING] API models import issue: {e}")
# This is not critical for database operations
return True
def check_project_structure():
"""Check overall project structure."""
print("\n[STRUCTURE] Checking project structure...")
critical_paths = [
"models/database/base.py",
"models/database/user.py",
"models/database/marketplace_products.py",
"models/database/inventory.py",
"app/core/config.py",
"alembic/env.py",
"alembic.ini",
]
for path in critical_paths:
if os.path.exists(path):
print(f" * {path}")
else:
print(f" X {path} (missing)")
# Check __init__.py files
init_files = [
"models/__init__.py",
"models/database/__init__.py",
"models/api/__init__.py",
]
print("\n[INIT] Checking __init__.py files...")
for init_file in init_files:
if os.path.exists(init_file):
print(f" * {init_file}")
else:
print(f" X {init_file} (missing - will cause import issues)")
if __name__ == "__main__":
success = True
check_project_structure()
if verify_model_structure():
success = verify_database_setup()
else:
success = False
if success:
print()
print("[READY] Your complete project structure is ready!")
print()
print("Database models: * SQLAlchemy models for data storage")
print("API models: * Pydantic models for request/response validation")
print("Migrations: * Alembic managing database schema")
print()
print("Next steps:")
print(" 1. Run 'make dev' to start your FastAPI server")
print(" 2. Visit http://localhost:8000/docs for interactive API docs")
print(
" 3. Use your API endpoints for authentication, products, inventory, etc."
)
sys.exit(0)
else:
print()
print("[FAILED] Project setup has issues that need to be resolved!")
sys.exit(1)