Files
bakery-ia/shared/clients/subscription_client.py

158 lines
6.8 KiB
Python
Raw Permalink Normal View History

2025-11-30 09:12:40 +01:00
"""
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:
2026-01-15 20:45:49 +01:00
logger.error(f"Failed to get subscription, tenant_id={tenant_id}, error={str(e)}")
2025-11-30 09:12:40 +01:00
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:
2026-01-15 20:45:49 +01:00
logger.error(f"Failed to update subscription plan, tenant_id={tenant_id}, new_plan={new_plan}, error={str(e)}")
2025-11-30 09:12:40 +01:00
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()