Files
bakery-ia/services/tenant/scripts/demo/seed_demo_subscriptions.py

237 lines
6.9 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
2025-10-17 07:31:14 +02:00
# -*- coding: utf-8 -*-
"""
Demo Subscription Seeding Script for Tenant Service
Creates subscriptions for demo template tenants
This script creates subscription records for the demo template tenants
so they have proper subscription limits and features.
Usage:
python /app/scripts/demo/seed_demo_subscriptions.py
Environment Variables Required:
TENANT_DATABASE_URL - PostgreSQL connection string for tenant database
LOG_LEVEL - Logging level (default: INFO)
"""
import asyncio
import uuid
import sys
import os
from datetime import datetime, timezone, timedelta
from pathlib import Path
# Add app to path
sys.path.insert(0, str(Path(__file__).parent.parent.parent))
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy import select
import structlog
from app.models.tenants import Subscription
# Configure logging
structlog.configure(
processors=[
structlog.stdlib.add_log_level,
structlog.processors.TimeStamper(fmt="iso"),
structlog.dev.ConsoleRenderer()
]
)
logger = structlog.get_logger()
# Fixed Demo Tenant IDs (must match tenant service)
DEMO_TENANT_SAN_PABLO = uuid.UUID("a1b2c3d4-e5f6-47a8-b9c0-d1e2f3a4b5c6")
DEMO_TENANT_LA_ESPIGA = uuid.UUID("b2c3d4e5-f6a7-48b9-c0d1-e2f3a4b5c6d7")
SUBSCRIPTIONS_DATA = [
{
"tenant_id": DEMO_TENANT_SAN_PABLO,
"plan": "enterprise",
"status": "active",
"monthly_price": 0.0, # Free for demo
"max_users": -1, # Unlimited users
"max_locations": -1, # Unlimited locations
"max_products": -1, # Unlimited products
"features": {
"inventory_management": "advanced",
"demand_prediction": "advanced",
"production_reports": "advanced",
"analytics": "predictive",
"support": "priority",
"ai_model_configuration": "advanced",
"multi_location": True,
"custom_integrations": True,
"api_access": True,
"dedicated_support": True
},
"trial_ends_at": None,
"next_billing_date": datetime.now(timezone.utc) + timedelta(days=90), # 90 days for demo
},
{
"tenant_id": DEMO_TENANT_LA_ESPIGA,
"plan": "enterprise",
"status": "active",
"monthly_price": 0.0, # Free for demo
"max_users": -1, # Unlimited users
"max_locations": -1, # Unlimited locations
"max_products": -1, # Unlimited products
"features": {
"inventory_management": "advanced",
"demand_prediction": "advanced",
"production_reports": "advanced",
"analytics": "predictive",
"support": "priority",
"ai_model_configuration": "advanced",
"multi_location": True,
"custom_integrations": True,
"api_access": True,
"dedicated_support": True
},
"trial_ends_at": None,
"next_billing_date": datetime.now(timezone.utc) + timedelta(days=90),
}
]
async def seed_subscriptions(db: AsyncSession) -> dict:
"""
Seed subscriptions for demo template tenants
Returns:
Dict with seeding statistics
"""
logger.info("=" * 80)
logger.info("💳 Starting Demo Subscription Seeding")
logger.info("=" * 80)
created_count = 0
updated_count = 0
for subscription_data in SUBSCRIPTIONS_DATA:
tenant_id = subscription_data["tenant_id"]
# Check if subscription already exists for this tenant
result = await db.execute(
select(Subscription).where(
Subscription.tenant_id == tenant_id,
Subscription.status == "active"
)
)
existing_subscription = result.scalars().first()
if existing_subscription:
logger.info(
"Subscription already exists - updating",
tenant_id=str(tenant_id),
subscription_id=str(existing_subscription.id)
)
# Update existing subscription
for key, value in subscription_data.items():
if key != "tenant_id": # Don't update the tenant_id
setattr(existing_subscription, key, value)
existing_subscription.updated_at = datetime.now(timezone.utc)
updated_count += 1
else:
logger.info(
"Creating new subscription",
tenant_id=str(tenant_id),
plan=subscription_data["plan"]
)
# Create new subscription
subscription = Subscription(**subscription_data)
db.add(subscription)
created_count += 1
# Commit all changes
await db.commit()
logger.info("=" * 80)
logger.info(
"✅ Demo Subscription Seeding Completed",
created=created_count,
updated=updated_count,
total=len(SUBSCRIPTIONS_DATA)
)
logger.info("=" * 80)
return {
"service": "subscriptions",
"created": created_count,
"updated": updated_count,
"total": len(SUBSCRIPTIONS_DATA)
}
async def main():
"""Main execution function"""
logger.info("Demo Subscription Seeding Script Starting")
logger.info("Log Level: %s", os.getenv("LOG_LEVEL", "INFO"))
# Get database URL from environment
database_url = os.getenv("TENANT_DATABASE_URL") or os.getenv("DATABASE_URL")
if not database_url:
logger.error("❌ TENANT_DATABASE_URL or DATABASE_URL environment variable must be set")
return 1
# Convert to async URL if needed
if database_url.startswith("postgresql://"):
database_url = database_url.replace("postgresql://", "postgresql+asyncpg://", 1)
logger.info("Connecting to tenant database")
# Create engine and session
engine = create_async_engine(
database_url,
echo=False,
pool_pre_ping=True,
pool_size=5,
max_overflow=10
)
async_session = sessionmaker(
engine,
class_=AsyncSession,
expire_on_commit=False
)
try:
async with async_session() as session:
result = await seed_subscriptions(session)
logger.info("")
logger.info("📊 Seeding Summary:")
logger.info(f" ✅ Created: {result['created']}")
logger.info(f" 🔄 Updated: {result['updated']}")
logger.info(f" 📦 Total: {result['total']}")
logger.info("")
logger.info("🎉 Success! Demo subscriptions are ready.")
logger.info("")
return 0
except Exception as e:
logger.error("=" * 80)
logger.error("❌ Demo Subscription Seeding Failed")
logger.error("=" * 80)
logger.error("Error: %s", str(e))
logger.error("", exc_info=True)
return 1
finally:
await engine.dispose()
if __name__ == "__main__":
exit_code = asyncio.run(main())
sys.exit(exit_code)