Initial commit - production deployment
This commit is contained in:
158
shared/clients/subscription_client.py
Executable file
158
shared/clients/subscription_client.py
Executable file
@@ -0,0 +1,158 @@
|
||||
"""
|
||||
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()
|
||||
Reference in New Issue
Block a user