agentops/app/scripts/verify_sunset_subscriptions.py

122 lines
4.2 KiB
Python

#!/usr/bin/env python3
"""
Simple script to verify which subscriptions will be caught by the invoice webhook check.
This shows which subscriptions have both cancel_at_period_end=True and cancellation_reason='billing_model_change'.
"""
import os
import sys
import stripe
from datetime import datetime
import logging
# Setup logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
def main():
# Get environment variables
stripe_secret_key = os.getenv('STRIPE_SECRET_KEY')
if not stripe_secret_key:
logger.error("STRIPE_SECRET_KEY environment variable not set")
sys.exit(1)
stripe.api_key = stripe_secret_key
logger.info("Checking for sunset legacy subscriptions...")
# Counters
total_active = 0
sunset_legacy = 0
cancelling_other_reason = 0
not_cancelling = 0
sunset_subscriptions = []
try:
# Get all active subscriptions
has_more = True
starting_after = None
while has_more:
params = {
'status': 'active',
'limit': 100,
}
if starting_after:
params['starting_after'] = starting_after
subscriptions = stripe.Subscription.list(**params)
for sub in subscriptions.data:
total_active += 1
cancel_at_period_end = sub.get('cancel_at_period_end', False)
cancellation_reason = sub.get('metadata', {}).get('cancellation_reason')
# This is the exact check from the webhook handler
if cancel_at_period_end and cancellation_reason == 'billing_model_change':
sunset_legacy += 1
# Get customer email for display
customer_email = 'unknown'
try:
customer = stripe.Customer.retrieve(sub.get('customer'))
customer_email = customer.get('email', 'unknown')
except:
pass
# Calculate days until cancellation
current_period_end_ts = sub.get('current_period_end')
if current_period_end_ts:
current_period_end = datetime.fromtimestamp(current_period_end_ts)
days_until_cancel = (current_period_end - datetime.now()).days
cancel_date = current_period_end.strftime('%Y-%m-%d')
else:
days_until_cancel = -1
cancel_date = 'Unknown'
sunset_subscriptions.append(
{
'id': sub.get('id'),
'customer': customer_email,
'days_until_cancel': days_until_cancel,
'cancel_date': cancel_date,
}
)
elif cancel_at_period_end:
cancelling_other_reason += 1
else:
not_cancelling += 1
# Check if there are more pages
has_more = subscriptions.has_more
if has_more and subscriptions.data:
starting_after = subscriptions.data[-1].get('id')
except Exception as e:
logger.error(f"Error fetching subscriptions: {e}")
sys.exit(1)
# Display results
logger.info("\n=== VERIFICATION RESULTS ===")
logger.info(f"Total active subscriptions: {total_active}")
logger.info(f"Sunset legacy (will skip usage charges): {sunset_legacy}")
logger.info(f"Cancelling for other reasons: {cancelling_other_reason}")
logger.info(f"Not cancelling: {not_cancelling}")
if sunset_subscriptions:
logger.info("\n=== SUNSET SUBSCRIPTIONS (Usage charges will be skipped) ===")
for sub in sorted(sunset_subscriptions, key=lambda x: x['days_until_cancel']):
logger.info(
f"- {sub['id']} | {sub['customer']} | Cancels in {sub['days_until_cancel']} days ({sub['cancel_date']})"
)
logger.info("\n✅ These subscriptions will NOT receive usage charges on their final invoice.")
if __name__ == '__main__':
main()