Files
ALwrity/backend/scripts/reset_basic_plan_usage.py

169 lines
7.0 KiB
Python
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
Quick script to reset usage counters for Basic plan users.
This fixes the issue where plan limits were updated but old usage data remained.
Resets all usage counters (calls, tokens, images) to 0 for the current billing period.
"""
import sys
import os
from pathlib import Path
from datetime import datetime, timezone
# Add the backend directory to Python path
backend_dir = Path(__file__).parent.parent
sys.path.insert(0, str(backend_dir))
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from loguru import logger
from models.subscription_models import SubscriptionPlan, SubscriptionTier, UserSubscription, UsageSummary, UsageStatus
from services.database import DATABASE_URL
from services.subscription import PricingService
def reset_basic_plan_usage():
"""Reset usage counters for all Basic plan users."""
try:
engine = create_engine(DATABASE_URL, echo=False)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
db = SessionLocal()
try:
# Find Basic plan
basic_plan = db.query(SubscriptionPlan).filter(
SubscriptionPlan.tier == SubscriptionTier.BASIC
).first()
if not basic_plan:
logger.error("❌ Basic plan not found in database!")
return False
# Get all Basic plan users
user_subscriptions = db.query(UserSubscription).filter(
UserSubscription.plan_id == basic_plan.id,
UserSubscription.is_active == True
).all()
logger.info(f"Found {len(user_subscriptions)} Basic plan user(s)")
pricing_service = PricingService(db)
reset_count = 0
for sub in user_subscriptions:
try:
# Get current billing period for this user
current_period = pricing_service.get_current_billing_period(sub.user_id) or datetime.now(timezone.utc).strftime("%Y-%m")
# Find usage summary for current period
usage_summary = db.query(UsageSummary).filter(
UsageSummary.user_id == sub.user_id,
UsageSummary.billing_period == current_period
).first()
if usage_summary:
# Store old values for logging
old_gemini = usage_summary.gemini_calls or 0
old_mistral = usage_summary.mistral_calls or 0
old_tokens = (usage_summary.mistral_tokens or 0) + (usage_summary.gemini_tokens or 0)
old_images = usage_summary.stability_calls or 0
old_total_calls = usage_summary.total_calls or 0
old_total_tokens = usage_summary.total_tokens or 0
# Reset all LLM provider counters
usage_summary.gemini_calls = 0
usage_summary.openai_calls = 0
usage_summary.anthropic_calls = 0
usage_summary.mistral_calls = 0
# Reset all token counters
usage_summary.gemini_tokens = 0
usage_summary.openai_tokens = 0
usage_summary.anthropic_tokens = 0
usage_summary.mistral_tokens = 0
# Reset image counter
usage_summary.stability_calls = 0
# Reset totals
usage_summary.total_calls = 0
usage_summary.total_tokens = 0
usage_summary.total_cost = 0.0
# Reset status to active
usage_summary.usage_status = UsageStatus.ACTIVE
usage_summary.updated_at = datetime.now(timezone.utc)
db.commit()
reset_count += 1
logger.info(f"\n✅ Reset usage for user {sub.user_id} (period {current_period}):")
logger.info(f" Calls: {old_gemini + old_mistral} (gemini: {old_gemini}, mistral: {old_mistral}) → 0")
logger.info(f" Tokens: {old_tokens} → 0")
logger.info(f" Images: {old_images} → 0")
logger.info(f" Total Calls: {old_total_calls} → 0")
logger.info(f" Total Tokens: {old_total_tokens} → 0")
else:
logger.info(f" No usage summary found for user {sub.user_id} (period {current_period}) - nothing to reset")
except Exception as reset_error:
logger.error(f" ❌ Error resetting usage for user {sub.user_id}: {reset_error}")
import traceback
logger.error(traceback.format_exc())
db.rollback()
if reset_count > 0:
logger.info(f"\n✅ Successfully reset usage counters for {reset_count} user(s)")
else:
logger.info("\n No usage counters to reset")
logger.info("\n" + "="*60)
logger.info("RESET COMPLETE")
logger.info("="*60)
logger.info("\n💡 Usage counters have been reset. Users can now use their new limits.")
logger.info(" Next API call will start counting from 0.")
return True
except Exception as e:
db.rollback()
logger.error(f"❌ Error resetting usage: {e}")
import traceback
logger.error(traceback.format_exc())
raise
finally:
db.close()
except Exception as e:
logger.error(f"❌ Failed to connect to database: {e}")
import traceback
logger.error(traceback.format_exc())
return False
if __name__ == "__main__":
logger.info("🚀 Starting Basic plan usage counter reset...")
logger.info("="*60)
logger.info("This will reset all usage counters (calls, tokens, images) to 0")
logger.info("for all Basic plan users in their current billing period.")
logger.info("="*60)
try:
success = reset_basic_plan_usage()
if success:
logger.info("\n✅ Script completed successfully!")
sys.exit(0)
else:
logger.error("\n❌ Script failed!")
sys.exit(1)
except KeyboardInterrupt:
logger.info("\n⚠️ Script cancelled by user")
sys.exit(1)
except Exception as e:
logger.error(f"\n❌ Unexpected error: {e}")
sys.exit(1)