STripe Paymen and PK payemtns and many othe rbacekd and froentened issues

This commit is contained in:
IGNY8 VPS (Salman)
2026-01-07 05:51:36 +00:00
parent 87d1662a18
commit 0386d4bf33
24 changed files with 1079 additions and 174 deletions

View File

@@ -627,10 +627,9 @@ def _process_subscription_payment(account, plan_id: str, capture_result: dict) -
}
)
# Create invoice
invoice = InvoiceService.create_subscription_invoice(
account=account,
plan=plan,
# Get existing pending invoice or create new one (avoids duplicates)
invoice, invoice_created = InvoiceService.get_or_create_subscription_invoice(
subscription=subscription,
billing_period_start=now,
billing_period_end=period_end,
)

View File

@@ -10,7 +10,7 @@ Endpoints:
"""
import stripe
import logging
from datetime import datetime
from datetime import datetime, timezone as dt_timezone, timedelta
from django.conf import settings
from django.utils import timezone
from django.views.decorators.csrf import csrf_exempt
@@ -402,6 +402,7 @@ def _activate_subscription(account, stripe_subscription_id: str, plan_id: str, s
# Get subscription details from Stripe
try:
stripe_sub = stripe.Subscription.retrieve(stripe_subscription_id)
logger.info(f"Retrieved Stripe subscription: {stripe_subscription_id}")
except Exception as e:
logger.error(f"Failed to retrieve Stripe subscription {stripe_subscription_id}: {e}")
return
@@ -413,6 +414,40 @@ def _activate_subscription(account, stripe_subscription_id: str, plan_id: str, s
logger.error(f"Plan {plan_id} not found for subscription activation")
return
# Extract period dates from Stripe subscription
# Note: In newer Stripe API, current_period_start/end are on subscription items, not the subscription
try:
# Convert to dict for easier access
sub_dict = stripe_sub.to_dict_recursive() if hasattr(stripe_sub, 'to_dict_recursive') else dict(stripe_sub)
# Try to get period from subscription items first (new API)
items = sub_dict.get('items', {}).get('data', [])
if items:
first_item = items[0]
period_start = first_item.get('current_period_start')
period_end = first_item.get('current_period_end')
else:
# Fallback to subscription level (old API)
period_start = sub_dict.get('current_period_start')
period_end = sub_dict.get('current_period_end')
# If still not found, use billing_cycle_anchor or start_date
if not period_start:
period_start = sub_dict.get('billing_cycle_anchor') or sub_dict.get('start_date') or sub_dict.get('created')
if not period_end:
# Default to 30 days from start
period_end = period_start + (30 * 24 * 60 * 60) if period_start else None
cancel_at_end = sub_dict.get('cancel_at_period_end', False)
logger.info(f"Extracted period: start={period_start}, end={period_end}, cancel_at_end={cancel_at_end}")
except Exception as e:
logger.error(f"Failed to extract period dates from Stripe subscription: {e}")
# Use current time as fallback
period_start = timezone.now().timestamp()
period_end = (timezone.now() + timedelta(days=30)).timestamp()
cancel_at_end = False
with transaction.atomic():
# Create or update subscription
subscription, created = Subscription.objects.update_or_create(
@@ -422,27 +457,29 @@ def _activate_subscription(account, stripe_subscription_id: str, plan_id: str, s
'stripe_subscription_id': stripe_subscription_id,
'status': 'active',
'current_period_start': datetime.fromtimestamp(
stripe_sub.current_period_start,
tz=timezone.utc
period_start,
tz=dt_timezone.utc
),
'current_period_end': datetime.fromtimestamp(
stripe_sub.current_period_end,
tz=timezone.utc
period_end,
tz=dt_timezone.utc
),
'cancel_at_period_end': stripe_sub.cancel_at_period_end,
'cancel_at_period_end': cancel_at_end,
}
)
# Create invoice record
# Get existing pending invoice or create new one (avoids duplicates)
amount = session.get('amount_total', 0) / 100 # Convert from cents
currency = session.get('currency', 'usd').upper()
invoice = InvoiceService.create_subscription_invoice(
account=account,
plan=plan,
invoice, invoice_created = InvoiceService.get_or_create_subscription_invoice(
subscription=subscription,
billing_period_start=subscription.current_period_start,
billing_period_end=subscription.current_period_end,
)
if not invoice_created:
logger.info(f"Found existing pending invoice {invoice.invoice_number} for subscription")
# Mark invoice as paid
InvoiceService.mark_paid(
@@ -481,10 +518,15 @@ def _activate_subscription(account, stripe_subscription_id: str, plan_id: str, s
}
)
# Update account status if needed
# Update account status and plan
update_fields = ['updated_at']
if account.status != 'active':
account.status = 'active'
account.save(update_fields=['status', 'updated_at'])
update_fields.append('status')
if account.plan_id != plan.id:
account.plan = plan
update_fields.append('plan')
account.save(update_fields=update_fields)
logger.info(
f"Subscription activated for account {account.id}: "
@@ -659,15 +701,33 @@ def _handle_subscription_updated(subscription_data: dict):
stripe_status = subscription_data.get('status')
new_status = status_map.get(stripe_status, 'active')
# Update period dates
subscription.current_period_start = datetime.fromtimestamp(
subscription_data.get('current_period_start'),
tz=timezone.utc
)
subscription.current_period_end = datetime.fromtimestamp(
subscription_data.get('current_period_end'),
tz=timezone.utc
)
# Extract period dates - check subscription items first (new API), then subscription level
items = subscription_data.get('items', {}).get('data', [])
if items:
first_item = items[0]
period_start = first_item.get('current_period_start')
period_end = first_item.get('current_period_end')
else:
period_start = subscription_data.get('current_period_start')
period_end = subscription_data.get('current_period_end')
# Fallback to billing_cycle_anchor if period dates not found
if not period_start:
period_start = subscription_data.get('billing_cycle_anchor') or subscription_data.get('start_date')
if not period_end and period_start:
period_end = period_start + (30 * 24 * 60 * 60) # Default 30 days
# Only update period dates if we have valid values
if period_start:
subscription.current_period_start = datetime.fromtimestamp(
period_start,
tz=dt_timezone.utc
)
if period_end:
subscription.current_period_end = datetime.fromtimestamp(
period_end,
tz=dt_timezone.utc
)
subscription.cancel_at_period_end = subscription_data.get('cancel_at_period_end', False)
subscription.status = new_status
subscription.save()