""" Subscription Service Client Client for interacting with subscription service functionality """ import structlog from typing import Dict, Any, Optional from sqlalchemy.ext.asyncio import AsyncSession from fastapi import Depends from shared.database.base import create_database_manager from app.repositories.subscription_repository import SubscriptionRepository from app.models.tenants import Subscription, Tenant from app.repositories.tenant_repository import TenantRepository from shared.subscription.plans import SubscriptionTier logger = structlog.get_logger() class SubscriptionServiceClient: """Client for subscription service operations""" def __init__(self, database_manager=None): self.database_manager = database_manager or create_database_manager() async def get_subscription(self, tenant_id: str) -> Dict[str, Any]: """Get subscription details for a tenant""" try: async with self.database_manager.get_session() as session: subscription_repo = SubscriptionRepository(Subscription, session) subscription = await subscription_repo.get_active_subscription(tenant_id) if not subscription: # Return default starter subscription if none found return { 'id': None, 'tenant_id': tenant_id, 'plan': SubscriptionTier.STARTER.value, 'status': 'active', 'monthly_price': 0, 'max_users': 5, 'max_locations': 1, 'max_products': 50, 'features': {} } return { 'id': str(subscription.id) if subscription.id else None, 'tenant_id': tenant_id, 'plan': subscription.plan, 'status': subscription.status, 'monthly_price': subscription.monthly_price, 'max_users': subscription.max_users, 'max_locations': subscription.max_locations, 'max_products': subscription.max_products, 'features': subscription.features or {} } except Exception as e: logger.error(f"Failed to get subscription, tenant_id={tenant_id}, error={str(e)}") raise async def update_subscription_plan(self, tenant_id: str, new_plan: str) -> Dict[str, Any]: """Update subscription plan for a tenant""" try: async with self.database_manager.get_session() as session: subscription_repo = SubscriptionRepository(Subscription, session) # Get existing subscription existing_subscription = await subscription_repo.get_active_subscription(tenant_id) if existing_subscription: # Update the existing subscription updated_subscription = await subscription_repo.update_subscription( existing_subscription.id, {'plan': new_plan} ) else: # Create a new subscription if none exists updated_subscription = await subscription_repo.create_subscription({ 'tenant_id': tenant_id, 'plan': new_plan, 'status': 'active', 'created_at': None # Let the database set this }) await session.commit() return { 'id': str(updated_subscription.id), 'tenant_id': tenant_id, 'plan': updated_subscription.plan, 'status': updated_subscription.status } except Exception as e: logger.error(f"Failed to update subscription plan, tenant_id={tenant_id}, new_plan={new_plan}, error={str(e)}") raise async def create_child_subscription(self, child_tenant_id: str, parent_tenant_id: str) -> Dict[str, Any]: """Create a child subscription inheriting from parent""" try: async with self.database_manager.get_session() as session: subscription_repo = SubscriptionRepository(Subscription, session) tenant_repo = TenantRepository(Tenant, session) # Get parent subscription to inherit plan parent_subscription = await subscription_repo.get_active_subscription(parent_tenant_id) if not parent_subscription: # If parent has no subscription, create child with starter plan plan = SubscriptionTier.STARTER.value else: plan = parent_subscription.plan # Create subscription for child tenant child_subscription = await subscription_repo.create_subscription({ 'tenant_id': child_tenant_id, 'plan': plan, 'status': 'active', 'created_at': None # Let the database set this }) await session.commit() # Update the child tenant's subscription tier await tenant_repo.update_tenant(child_tenant_id, { 'subscription_tier': plan }) await session.commit() return { 'id': str(child_subscription.id), 'tenant_id': child_tenant_id, 'plan': child_subscription.plan, 'status': child_subscription.status } except Exception as e: logger.error("Failed to create child subscription", child_tenant_id=child_tenant_id, parent_tenant_id=parent_tenant_id, error=str(e)) raise async def get_subscription_by_tenant(self, tenant_id: str) -> Optional[Dict[str, Any]]: """Get subscription by tenant ID""" return await self.get_subscription(tenant_id) async def get_tenant_subscription_tier(self, tenant_id: str) -> str: """Get the subscription tier for a tenant""" subscription = await self.get_subscription(tenant_id) return subscription.get('plan', SubscriptionTier.STARTER.value) # Dependency function for FastAPI async def get_subscription_service_client() -> SubscriptionServiceClient: """FastAPI dependency for subscription service client""" return SubscriptionServiceClient()