Add subcription feature 9
This commit is contained in:
@@ -1324,7 +1324,9 @@ class StripeClient(PaymentProvider):
|
||||
async def update_subscription(
|
||||
self,
|
||||
subscription_id: str,
|
||||
new_price_id: str
|
||||
new_price_id: str,
|
||||
proration_behavior: str = 'create_prorations',
|
||||
preserve_trial: bool = False
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
Update subscription price (plan upgrade/downgrade)
|
||||
@@ -1332,35 +1334,69 @@ class StripeClient(PaymentProvider):
|
||||
Args:
|
||||
subscription_id: Subscription ID
|
||||
new_price_id: New price ID
|
||||
proration_behavior: How to handle proration ('create_prorations', 'none', 'always_invoice')
|
||||
- 'none': No proration charges (useful during trial)
|
||||
- 'create_prorations': Create prorated charges (default)
|
||||
- 'always_invoice': Always create an invoice
|
||||
preserve_trial: If True, preserves the trial period after upgrade
|
||||
|
||||
Returns:
|
||||
Subscription update result
|
||||
Subscription update result including trial info
|
||||
"""
|
||||
try:
|
||||
subscription = stripe.Subscription.retrieve(subscription_id)
|
||||
|
||||
updated_subscription = stripe.Subscription.modify(
|
||||
subscription_id,
|
||||
items=[{
|
||||
# Check if subscription is currently trialing
|
||||
is_trialing = subscription.status == 'trialing'
|
||||
trial_end = subscription.trial_end
|
||||
|
||||
# Build the modification params
|
||||
modify_params = {
|
||||
'items': [{
|
||||
'id': subscription['items']['data'][0].id,
|
||||
'price': new_price_id,
|
||||
}],
|
||||
proration_behavior='create_prorations',
|
||||
idempotency_key=f"update_sub_{uuid.uuid4()}"
|
||||
'proration_behavior': proration_behavior,
|
||||
'idempotency_key': f"update_sub_{uuid.uuid4()}"
|
||||
}
|
||||
|
||||
# Preserve trial period if requested and currently trialing
|
||||
# When changing plans during trial, Stripe will by default end the trial
|
||||
# By explicitly setting trial_end, we preserve it
|
||||
if preserve_trial and is_trialing and trial_end:
|
||||
modify_params['trial_end'] = trial_end
|
||||
logger.info(
|
||||
"Preserving trial period during upgrade",
|
||||
extra={
|
||||
"subscription_id": subscription_id,
|
||||
"trial_end": trial_end
|
||||
}
|
||||
)
|
||||
|
||||
updated_subscription = stripe.Subscription.modify(
|
||||
subscription_id,
|
||||
**modify_params
|
||||
)
|
||||
|
||||
logger.info(
|
||||
"Subscription updated",
|
||||
extra={
|
||||
"subscription_id": subscription_id,
|
||||
"new_price_id": new_price_id
|
||||
"new_price_id": new_price_id,
|
||||
"proration_behavior": proration_behavior,
|
||||
"was_trialing": is_trialing,
|
||||
"new_status": updated_subscription.status
|
||||
}
|
||||
)
|
||||
|
||||
return {
|
||||
'subscription_id': updated_subscription.id,
|
||||
'status': updated_subscription.status,
|
||||
'current_period_end': updated_subscription.current_period_end
|
||||
'current_period_start': updated_subscription.current_period_start,
|
||||
'current_period_end': updated_subscription.current_period_end,
|
||||
'trial_end': updated_subscription.trial_end,
|
||||
'is_trialing': updated_subscription.status == 'trialing',
|
||||
'customer_id': updated_subscription.customer
|
||||
}
|
||||
|
||||
except stripe.error.StripeError as e:
|
||||
@@ -1537,6 +1573,13 @@ class StripeClient(PaymentProvider):
|
||||
try:
|
||||
invoices = stripe.Invoice.list(customer=customer_id, limit=10)
|
||||
|
||||
# Debug: Log all invoice IDs and amounts to see what Stripe returns
|
||||
logger.info("stripe_invoices_retrieved",
|
||||
customer_id=customer_id,
|
||||
invoice_count=len(invoices.data),
|
||||
invoice_ids=[inv.id for inv in invoices.data],
|
||||
invoice_amounts=[inv.amount_due for inv in invoices.data])
|
||||
|
||||
return {
|
||||
'invoices': [
|
||||
{
|
||||
@@ -1545,7 +1588,12 @@ class StripeClient(PaymentProvider):
|
||||
'amount_paid': inv.amount_paid / 100,
|
||||
'status': inv.status,
|
||||
'created': inv.created,
|
||||
'invoice_pdf': inv.invoice_pdf
|
||||
'invoice_pdf': inv.invoice_pdf,
|
||||
'hosted_invoice_url': inv.hosted_invoice_url,
|
||||
'number': inv.number,
|
||||
'currency': inv.currency,
|
||||
'description': inv.description,
|
||||
'trial': inv.amount_due == 0 # Mark trial invoices
|
||||
}
|
||||
for inv in invoices.data
|
||||
]
|
||||
|
||||
@@ -48,6 +48,10 @@ class BaseFastAPIService:
|
||||
database_manager: Optional[DatabaseManager] = None,
|
||||
expected_tables: Optional[List[str]] = None,
|
||||
custom_health_checks: Optional[Dict[str, Callable[[], Any]]] = None,
|
||||
redis_enabled: bool = False,
|
||||
redis_url: Optional[str] = None,
|
||||
redis_db: int = 0,
|
||||
redis_max_connections: int = 50,
|
||||
enable_metrics: bool = True,
|
||||
enable_health_checks: bool = True,
|
||||
enable_cors: bool = True,
|
||||
@@ -80,6 +84,14 @@ class BaseFastAPIService:
|
||||
setup_logging(service_name, log_level)
|
||||
self.logger = structlog.get_logger()
|
||||
|
||||
# Initialize Redis client if enabled
|
||||
self.redis_enabled = redis_enabled
|
||||
self.redis_client = None
|
||||
self.redis_initialized = False
|
||||
|
||||
if redis_enabled:
|
||||
self._initialize_redis(redis_url, redis_db, redis_max_connections)
|
||||
|
||||
# Will be set during app creation
|
||||
self.app: Optional[FastAPI] = None
|
||||
self.health_manager = None
|
||||
|
||||
Reference in New Issue
Block a user