Add subcription feature 6
This commit is contained in:
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -606,3 +606,75 @@ class TenantRepository(TenantBaseRepository):
|
||||
customer_id=customer_id,
|
||||
error=str(e))
|
||||
raise DatabaseError(f"Failed to get tenant by customer_id: {str(e)}")
|
||||
|
||||
async def get_user_primary_tenant(self, user_id: str) -> Optional[Tenant]:
|
||||
"""
|
||||
Get the primary tenant for a user (the tenant they own)
|
||||
|
||||
Args:
|
||||
user_id: User ID to find primary tenant for
|
||||
|
||||
Returns:
|
||||
Tenant object if found, None otherwise
|
||||
"""
|
||||
try:
|
||||
logger.debug("Getting primary tenant for user", user_id=user_id)
|
||||
|
||||
# Query for tenant where user is the owner
|
||||
query = select(Tenant).where(Tenant.owner_id == user_id)
|
||||
|
||||
result = await self.session.execute(query)
|
||||
tenant = result.scalar_one_or_none()
|
||||
|
||||
if tenant:
|
||||
logger.debug("Found primary tenant for user",
|
||||
user_id=user_id,
|
||||
tenant_id=str(tenant.id))
|
||||
return tenant
|
||||
else:
|
||||
logger.debug("No primary tenant found for user", user_id=user_id)
|
||||
return None
|
||||
|
||||
except Exception as e:
|
||||
logger.error("Error getting primary tenant for user",
|
||||
user_id=user_id,
|
||||
error=str(e))
|
||||
raise DatabaseError(f"Failed to get primary tenant for user: {str(e)}")
|
||||
|
||||
async def get_any_user_tenant(self, user_id: str) -> Optional[Tenant]:
|
||||
"""
|
||||
Get any tenant that the user has access to (via tenant_members)
|
||||
|
||||
Args:
|
||||
user_id: User ID to find accessible tenants for
|
||||
|
||||
Returns:
|
||||
Tenant object if found, None otherwise
|
||||
"""
|
||||
try:
|
||||
logger.debug("Getting any accessible tenant for user", user_id=user_id)
|
||||
|
||||
# Query for tenant members where user has access
|
||||
from app.models.tenants import TenantMember
|
||||
|
||||
query = select(Tenant).join(
|
||||
TenantMember, Tenant.id == TenantMember.tenant_id
|
||||
).where(TenantMember.user_id == user_id)
|
||||
|
||||
result = await self.session.execute(query)
|
||||
tenant = result.scalar_one_or_none()
|
||||
|
||||
if tenant:
|
||||
logger.debug("Found accessible tenant for user",
|
||||
user_id=user_id,
|
||||
tenant_id=str(tenant.id))
|
||||
return tenant
|
||||
else:
|
||||
logger.debug("No accessible tenants found for user", user_id=user_id)
|
||||
return None
|
||||
|
||||
except Exception as e:
|
||||
logger.error("Error getting accessible tenant for user",
|
||||
user_id=user_id,
|
||||
error=str(e))
|
||||
raise DatabaseError(f"Failed to get accessible tenant for user: {str(e)}")
|
||||
|
||||
@@ -1545,6 +1545,52 @@ class SubscriptionOrchestrationService:
|
||||
tenant_id=tenant_id)
|
||||
return None
|
||||
|
||||
async def get_invoices(self, tenant_id: str) -> Dict[str, Any]:
|
||||
"""
|
||||
Get invoice history for a tenant's subscription
|
||||
|
||||
This is an orchestration method that coordinates between:
|
||||
1. SubscriptionService (to get subscription data)
|
||||
2. PaymentService (to get invoices from provider)
|
||||
|
||||
Args:
|
||||
tenant_id: Tenant ID
|
||||
|
||||
Returns:
|
||||
Dictionary with invoices data
|
||||
"""
|
||||
try:
|
||||
# Get subscription from database
|
||||
subscription = await self.subscription_service.get_subscription_by_tenant_id(tenant_id)
|
||||
|
||||
if not subscription:
|
||||
logger.warning("get_invoices_no_subscription",
|
||||
tenant_id=tenant_id)
|
||||
return {"invoices": []}
|
||||
|
||||
# Check if subscription has a customer ID
|
||||
if not subscription.customer_id:
|
||||
logger.warning("get_invoices_no_customer_id",
|
||||
tenant_id=tenant_id)
|
||||
return {"invoices": []}
|
||||
|
||||
# Get invoices from payment provider
|
||||
invoices_result = await self.payment_service.stripe_client.get_invoices(subscription.customer_id)
|
||||
|
||||
logger.info("invoices_retrieved",
|
||||
tenant_id=tenant_id,
|
||||
customer_id=subscription.customer_id,
|
||||
invoice_count=len(invoices_result.get("invoices", [])))
|
||||
|
||||
return invoices_result
|
||||
|
||||
except Exception as e:
|
||||
logger.error("get_invoices_failed",
|
||||
error=str(e),
|
||||
tenant_id=tenant_id,
|
||||
exc_info=True)
|
||||
return {"invoices": []}
|
||||
|
||||
async def update_payment_method(
|
||||
self,
|
||||
tenant_id: str,
|
||||
|
||||
@@ -252,7 +252,7 @@ class SubscriptionCreationFlowTester:
|
||||
|
||||
async def _verify_subscription_linked_to_tenant(self, subscription_id: str, tenant_id: str):
|
||||
"""Verify that the subscription is properly linked to the tenant"""
|
||||
url = f"{self.base_url}/api/v1/subscriptions/{tenant_id}/status"
|
||||
url = f"{self.base_url}/api/v1/tenants/{tenant_id}/subscription/status"
|
||||
|
||||
# Get access token for the user
|
||||
access_token = await self._get_user_access_token()
|
||||
@@ -280,7 +280,7 @@ class SubscriptionCreationFlowTester:
|
||||
|
||||
async def _verify_tenant_subscription_access(self, tenant_id: str):
|
||||
"""Verify that the tenant can access its subscription"""
|
||||
url = f"{self.base_url}/api/v1/subscriptions/{tenant_id}/active"
|
||||
url = f"{self.base_url}/api/v1/tenants/{tenant_id}/subscription/details"
|
||||
|
||||
# Get access token for the user
|
||||
access_token = await self._get_user_access_token()
|
||||
|
||||
Reference in New Issue
Block a user