#!/usr/bin/env python3 """ Seed szkript a jövőbiztos SaaS csomag-architektúra 1. fázisához. Létrehozza a 6 alap subscription tier-t a system.subscription_tiers táblában. Használat: docker compose exec sf_api python3 /app/backend/app/scripts/seed_packages.py Architektúra: A csomagok rules JSONB oszlopa egy szabványos struktúrát követ: { "type": "private" | "corporate", "pricing": {"monthly_price": float, "yearly_price": float, "currency": "EUR"}, "allowances": {"max_vehicles": int, "max_garages": int, "monthly_free_credits": int}, "entitlements": ["SRV_..."], "affiliate": {"commission_rate_percent": int, "referral_bonus_credits": int} } """ import asyncio import json import logging from sqlalchemy import select, delete from app.database import AsyncSessionLocal from app.models.core_logic import SubscriptionTier logging.basicConfig( level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s", ) logger = logging.getLogger("Seed-Packages") # --------------------------------------------------------------------------- # Csomagdefiníciók # --------------------------------------------------------------------------- PACKAGES = [ { "name": "private_free_v1", "rules": { "type": "private", "display_name": "Privát Ingyenes", "pricing": { "monthly_price": 0.0, "yearly_price": 0.0, "currency": "EUR", "credit_price": 0, }, "allowances": { "max_vehicles": 1, "max_garages": 1, "monthly_free_credits": 0, }, "entitlements": [], "affiliate": { "commission_rate_percent": 0, "referral_bonus_credits": 0, }, "lifecycle": { "is_public": True, }, }, "is_custom": False, }, { "name": "private_pro_v1", "rules": { "type": "private", "display_name": "Privát Pro", "pricing": { "monthly_price": 4.99, "yearly_price": 49.99, "currency": "EUR", "credit_price": 500, }, "allowances": { "max_vehicles": 3, "max_garages": 1, "monthly_free_credits": 50, }, "entitlements": ["SRV_DATA_EXPORT"], "affiliate": { "commission_rate_percent": 10, "referral_bonus_credits": 25, }, "lifecycle": { "is_public": True, }, }, "is_custom": False, }, { "name": "private_vip_v1", "rules": { "type": "private", "display_name": "Privát VIP", "pricing": { "monthly_price": 9.99, "yearly_price": 99.99, "currency": "EUR", "credit_price": 1200, }, "allowances": { "max_vehicles": 10, "max_garages": 1, "monthly_free_credits": 150, }, "entitlements": ["SRV_DATA_EXPORT", "SRV_AI_UPLOAD"], "affiliate": { "commission_rate_percent": 15, "referral_bonus_credits": 50, }, "lifecycle": { "is_public": True, }, }, "is_custom": False, }, { "name": "corp_premium_v1", "rules": { "type": "corporate", "display_name": "Céges Prémium", "pricing": { "monthly_price": 29.99, "yearly_price": 299.99, "currency": "EUR", "credit_price": 3000, }, "allowances": { "max_vehicles": 20, "max_garages": 3, "monthly_free_credits": 300, }, "entitlements": ["SRV_DATA_EXPORT", "SRV_AI_UPLOAD"], "affiliate": { "commission_rate_percent": 15, "referral_bonus_credits": 100, }, "lifecycle": { "is_public": True, }, }, "is_custom": False, }, { "name": "corp_premium_plus_v1", "rules": { "type": "corporate", "display_name": "Céges Prémium Plus", "pricing": { "monthly_price": 59.99, "yearly_price": 599.99, "currency": "EUR", "credit_price": 6000, }, "allowances": { "max_vehicles": 50, "max_garages": 10, "monthly_free_credits": 800, }, "entitlements": [ "SRV_DATA_EXPORT", "SRV_AI_UPLOAD", "SRV_ACCOUNTING_SYNC", ], "affiliate": { "commission_rate_percent": 20, "referral_bonus_credits": 250, }, "lifecycle": { "is_public": True, }, }, "is_custom": False, }, { "name": "corp_vip_v1", "rules": { "type": "corporate", "display_name": "Céges VIP", "pricing": { "monthly_price": 149.99, "yearly_price": 1499.99, "currency": "EUR", "credit_price": 15000, }, "allowances": { "max_vehicles": 200, "max_garages": 50, "monthly_free_credits": 2500, }, "entitlements": [ "SRV_DATA_EXPORT", "SRV_AI_UPLOAD", "SRV_ACCOUNTING_SYNC", "SRV_API_ACCESS", ], "affiliate": { "commission_rate_percent": 25, "referral_bonus_credits": 500, }, "lifecycle": { "is_public": True, }, }, "is_custom": False, }, ] async def seed(): logger.info("=" * 60) logger.info("Seed Packages - Advanced Subscription Tiers (Phase 1)") logger.info("=" * 60) async with AsyncSessionLocal() as db: # 1. Töröljük a meglévő rekordokat (tiszta lap) logger.info("Törlöm a meglévő subscription_tiers rekordokat...") await db.execute(delete(SubscriptionTier)) await db.commit() logger.info("✅ Meglévő rekordok törölve.") # 2. Beszúrjuk a 6 új csomagot inserted_count = 0 for pkg in PACKAGES: tier = SubscriptionTier( name=pkg["name"], rules=pkg["rules"], is_custom=pkg["is_custom"], ) db.add(tier) inserted_count += 1 logger.info(f" ➕ Hozzáadva: {pkg['name']}") await db.commit() logger.info(f"✅ {inserted_count} csomag sikeresen beszúrva.") # 3. Visszaigazolás: listázzuk ki az összes rekordot logger.info("-" * 60) logger.info("Visszaigazolás - system.subscription_tiers tartalma:") logger.info("-" * 60) result = await db.execute( select(SubscriptionTier).order_by(SubscriptionTier.id) ) tiers = result.scalars().all() for tier in tiers: rules_json = json.dumps(tier.rules, indent=2, ensure_ascii=False) logger.info(f"\n ID: {tier.id}") logger.info(f" Name: {tier.name}") logger.info(f" Is Custom: {tier.is_custom}") logger.info(f" Rules:\n{rules_json}") logger.info(" " + "-" * 40) logger.info(f"\n✅ Összesen {len(tiers)} aktív csomag a rendszerben.") # 4. JSONB példa kiírása if tiers: sample = tiers[0] logger.info("=" * 60) logger.info("JSONB PÉLDA (private_free_v1):") logger.info("=" * 60) logger.info(json.dumps(sample.rules, indent=2, ensure_ascii=False)) if __name__ == "__main__": asyncio.run(seed())