Add subcription feature 3
This commit is contained in:
@@ -82,15 +82,29 @@ class SubscriptionRepository(TenantBaseRepository):
|
||||
else:
|
||||
subscription_data["next_billing_date"] = datetime.utcnow() + timedelta(days=30)
|
||||
|
||||
# Check if subscription with this subscription_id already exists to prevent duplicates
|
||||
if subscription_data.get('subscription_id'):
|
||||
existing_subscription = await self.get_by_provider_id(subscription_data['subscription_id'])
|
||||
if existing_subscription:
|
||||
# Update the existing subscription instead of creating a duplicate
|
||||
updated_subscription = await self.update(str(existing_subscription.id), subscription_data)
|
||||
|
||||
logger.info("Existing subscription updated",
|
||||
subscription_id=subscription_data['subscription_id'],
|
||||
tenant_id=subscription_data.get('tenant_id'),
|
||||
plan=subscription_data.get('plan'))
|
||||
|
||||
return updated_subscription
|
||||
|
||||
# Create subscription
|
||||
subscription = await self.create(subscription_data)
|
||||
|
||||
|
||||
logger.info("Subscription created successfully",
|
||||
subscription_id=subscription.id,
|
||||
tenant_id=subscription.tenant_id,
|
||||
plan=subscription.plan,
|
||||
monthly_price=subscription.monthly_price)
|
||||
|
||||
|
||||
return subscription
|
||||
|
||||
except (ValidationError, DuplicateRecordError):
|
||||
@@ -514,7 +528,8 @@ class SubscriptionRepository(TenantBaseRepository):
|
||||
"""Create a subscription not linked to any tenant (for registration flow)"""
|
||||
try:
|
||||
# Validate required data for tenant-independent subscription
|
||||
required_fields = ["user_id", "plan", "subscription_id", "customer_id"]
|
||||
# user_id may not exist during registration, so validate other required fields
|
||||
required_fields = ["plan", "subscription_id", "customer_id"]
|
||||
validation_result = self._validate_tenant_data(subscription_data, required_fields)
|
||||
|
||||
if not validation_result["is_valid"]:
|
||||
@@ -567,16 +582,41 @@ class SubscriptionRepository(TenantBaseRepository):
|
||||
else:
|
||||
subscription_data["next_billing_date"] = datetime.utcnow() + timedelta(days=30)
|
||||
|
||||
# Create tenant-independent subscription
|
||||
subscription = await self.create(subscription_data)
|
||||
|
||||
logger.info("Tenant-independent subscription created successfully",
|
||||
subscription_id=subscription.id,
|
||||
user_id=subscription.user_id,
|
||||
plan=subscription.plan,
|
||||
monthly_price=subscription.monthly_price)
|
||||
|
||||
return subscription
|
||||
# Check if subscription with this subscription_id already exists
|
||||
existing_subscription = await self.get_by_provider_id(subscription_data['subscription_id'])
|
||||
if existing_subscription:
|
||||
# Update the existing subscription instead of creating a duplicate
|
||||
updated_subscription = await self.update(str(existing_subscription.id), subscription_data)
|
||||
|
||||
logger.info("Existing tenant-independent subscription updated",
|
||||
subscription_id=subscription_data['subscription_id'],
|
||||
user_id=subscription_data.get('user_id'),
|
||||
plan=subscription_data.get('plan'))
|
||||
|
||||
return updated_subscription
|
||||
else:
|
||||
# Create new subscription, but handle potential duplicate errors
|
||||
try:
|
||||
subscription = await self.create(subscription_data)
|
||||
|
||||
logger.info("Tenant-independent subscription created successfully",
|
||||
subscription_id=subscription.id,
|
||||
user_id=subscription.user_id,
|
||||
plan=subscription.plan,
|
||||
monthly_price=subscription.monthly_price)
|
||||
|
||||
return subscription
|
||||
except DuplicateRecordError:
|
||||
# Another process may have created the subscription between our check and create
|
||||
# Try to get the existing subscription and return it
|
||||
final_subscription = await self.get_by_provider_id(subscription_data['subscription_id'])
|
||||
if final_subscription:
|
||||
logger.info("Race condition detected: subscription already created by another process",
|
||||
subscription_id=subscription_data['subscription_id'])
|
||||
return final_subscription
|
||||
else:
|
||||
# This shouldn't happen, but re-raise the error if we can't find it
|
||||
raise
|
||||
|
||||
except (ValidationError, DuplicateRecordError):
|
||||
raise
|
||||
@@ -700,3 +740,29 @@ class SubscriptionRepository(TenantBaseRepository):
|
||||
logger.error("Failed to cleanup orphaned subscriptions",
|
||||
error=str(e))
|
||||
raise DatabaseError(f"Cleanup failed: {str(e)}")
|
||||
|
||||
async def get_by_customer_id(self, customer_id: str) -> List[Subscription]:
|
||||
"""
|
||||
Get subscriptions by Stripe customer ID
|
||||
|
||||
Args:
|
||||
customer_id: Stripe customer ID
|
||||
|
||||
Returns:
|
||||
List of Subscription objects
|
||||
"""
|
||||
try:
|
||||
query = select(Subscription).where(Subscription.customer_id == customer_id)
|
||||
result = await self.session.execute(query)
|
||||
subscriptions = result.scalars().all()
|
||||
|
||||
logger.debug("Found subscriptions by customer_id",
|
||||
customer_id=customer_id,
|
||||
count=len(subscriptions))
|
||||
return subscriptions
|
||||
|
||||
except Exception as e:
|
||||
logger.error("Error getting subscriptions by customer_id",
|
||||
customer_id=customer_id,
|
||||
error=str(e))
|
||||
raise DatabaseError(f"Failed to get subscriptions by customer_id: {str(e)}")
|
||||
|
||||
Reference in New Issue
Block a user