Phase 0: Remove plan limit checks from billing views

- Updated limits endpoint to show only credits and account management limits
- Removed all operation limit references (keywords, clusters, content ideas, word count, images)
- Limits endpoint now focuses on credit usage by operation type
- Account management limits (users, sites) still shown
This commit is contained in:
IGNY8 VPS (Salman)
2025-11-16 18:51:40 +00:00
parent a10e89ab08
commit abbf6dbabb

View File

@@ -207,7 +207,10 @@ class CreditUsageViewSet(AccountModelViewSet):
@action(detail=False, methods=['get'], url_path='limits', url_name='limits')
def limits(self, request):
"""Get plan limits and current usage statistics"""
"""
Get account limits and credit usage statistics (Phase 0: Credit-only system).
Returns account management limits and credit usage only.
"""
# Try multiple ways to get account
account = getattr(request, 'account', None)
@@ -225,13 +228,7 @@ class CreditUsageViewSet(AccountModelViewSet):
except (AttributeError, UserModel.DoesNotExist, Exception) as e:
account = None
# Debug logging
import logging
logger = logging.getLogger(__name__)
logger.info(f'Limits endpoint - User: {getattr(request, "user", None)}, Account: {account}, Account has plan: {account.plan if account else False}')
if not account:
logger.warning(f'No account found in limits endpoint')
# Return empty limits instead of error - frontend will show "no data" message
return success_response(data={'limits': []}, request=request)
@@ -241,115 +238,16 @@ class CreditUsageViewSet(AccountModelViewSet):
return success_response(data={'limits': []}, request=request)
# Import models
from igny8_core.modules.planner.models import Keywords, Clusters, ContentIdeas
from igny8_core.modules.writer.models import Tasks, Images
from igny8_core.auth.models import User, Site
# Get current month boundaries
now = timezone.now()
start_of_month = now.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
start_of_day = now.replace(hour=0, minute=0, second=0, microsecond=0)
# Calculate usage statistics
limits_data = []
# Planner Limits
keywords_count = Keywords.objects.filter(account=account).count()
clusters_count = Clusters.objects.filter(account=account).count()
content_ideas_count = ContentIdeas.objects.filter(account=account).count()
clusters_today = Clusters.objects.filter(account=account, created_at__gte=start_of_day).count()
limits_data.extend([
{
'title': 'Keywords',
'limit': plan.max_keywords or 0,
'used': keywords_count,
'available': max(0, (plan.max_keywords or 0) - keywords_count),
'unit': 'keywords',
'category': 'planner',
'percentage': (keywords_count / (plan.max_keywords or 1)) * 100 if plan.max_keywords else 0
},
{
'title': 'Clusters',
'limit': plan.max_clusters or 0,
'used': clusters_count,
'available': max(0, (plan.max_clusters or 0) - clusters_count),
'unit': 'clusters',
'category': 'planner',
'percentage': (clusters_count / (plan.max_clusters or 1)) * 100 if plan.max_clusters else 0
},
{
'title': 'Content Ideas',
'limit': plan.max_content_ideas or 0,
'used': content_ideas_count,
'available': max(0, (plan.max_content_ideas or 0) - content_ideas_count),
'unit': 'ideas',
'category': 'planner',
'percentage': (content_ideas_count / (plan.max_content_ideas or 1)) * 100 if plan.max_content_ideas else 0
},
{
'title': 'Daily Cluster Limit',
'limit': plan.daily_cluster_limit or 0,
'used': clusters_today,
'available': max(0, (plan.daily_cluster_limit or 0) - clusters_today),
'unit': 'per day',
'category': 'planner',
'percentage': (clusters_today / (plan.daily_cluster_limit or 1)) * 100 if plan.daily_cluster_limit else 0
},
])
# Writer Limits
tasks_today = Tasks.objects.filter(account=account, created_at__gte=start_of_day).count()
tasks_month = Tasks.objects.filter(account=account, created_at__gte=start_of_month)
word_count_month = tasks_month.aggregate(total=Sum('word_count'))['total'] or 0
limits_data.extend([
{
'title': 'Monthly Word Count',
'limit': plan.monthly_word_count_limit or 0,
'used': word_count_month,
'available': max(0, (plan.monthly_word_count_limit or 0) - word_count_month),
'unit': 'words',
'category': 'writer',
'percentage': (word_count_month / (plan.monthly_word_count_limit or 1)) * 100 if plan.monthly_word_count_limit else 0
},
{
'title': 'Daily Content Tasks',
'limit': plan.daily_content_tasks or 0,
'used': tasks_today,
'available': max(0, (plan.daily_content_tasks or 0) - tasks_today),
'unit': 'per day',
'category': 'writer',
'percentage': (tasks_today / (plan.daily_content_tasks or 1)) * 100 if plan.daily_content_tasks else 0
},
])
# Image Limits
images_month = Images.objects.filter(account=account, created_at__gte=start_of_month).count()
images_today = Images.objects.filter(account=account, created_at__gte=start_of_day).count()
limits_data.extend([
{
'title': 'Monthly Images',
'limit': plan.monthly_image_count or 0,
'used': images_month,
'available': max(0, (plan.monthly_image_count or 0) - images_month),
'unit': 'images',
'category': 'images',
'percentage': (images_month / (plan.monthly_image_count or 1)) * 100 if plan.monthly_image_count else 0
},
{
'title': 'Daily Image Generation',
'limit': plan.daily_image_generation_limit or 0,
'used': images_today,
'available': max(0, (plan.daily_image_generation_limit or 0) - images_today),
'unit': 'per day',
'category': 'images',
'percentage': (images_today / (plan.daily_image_generation_limit or 1)) * 100 if plan.daily_image_generation_limit else 0
},
])
# AI Credits
# Credit Usage (Phase 0: Credit-only system)
credits_used_month = CreditUsageLog.objects.filter(
account=account,
created_at__gte=start_of_month
@@ -358,64 +256,89 @@ class CreditUsageViewSet(AccountModelViewSet):
# Get credits by operation type
cluster_credits = CreditUsageLog.objects.filter(
account=account,
operation_type='clustering',
operation_type__in=['clustering'],
created_at__gte=start_of_month
).aggregate(total=Sum('credits_used'))['total'] or 0
content_credits = CreditUsageLog.objects.filter(
account=account,
operation_type='content',
operation_type__in=['content', 'content_generation'],
created_at__gte=start_of_month
).aggregate(total=Sum('credits_used'))['total'] or 0
image_credits = CreditUsageLog.objects.filter(
account=account,
operation_type='image',
operation_type__in=['images', 'image_generation', 'image_prompt_extraction'],
created_at__gte=start_of_month
).aggregate(total=Sum('credits_used'))['total'] or 0
plan_credits = plan.monthly_ai_credit_limit or plan.credits_per_month or 0
idea_credits = CreditUsageLog.objects.filter(
account=account,
operation_type__in=['ideas', 'idea_generation'],
created_at__gte=start_of_month
).aggregate(total=Sum('credits_used'))['total'] or 0
# Use included_credits from plan (Phase 0: Credit-only)
plan_credits = plan.included_credits or plan.credits_per_month or 0
limits_data.extend([
{
'title': 'Monthly AI Credits',
'title': 'Monthly Credits',
'limit': plan_credits,
'used': credits_used_month,
'available': max(0, plan_credits - credits_used_month),
'unit': 'credits',
'category': 'ai',
'category': 'credits',
'percentage': (credits_used_month / plan_credits * 100) if plan_credits else 0
},
{
'title': 'Content AI Credits',
'limit': plan.monthly_content_ai_credits or 0,
'used': content_credits,
'available': max(0, (plan.monthly_content_ai_credits or 0) - content_credits),
'title': 'Current Balance',
'limit': None, # No limit - shows current balance
'used': None,
'available': account.credits,
'unit': 'credits',
'category': 'ai',
'percentage': (content_credits / (plan.monthly_content_ai_credits or 1)) * 100 if plan.monthly_content_ai_credits else 0
'category': 'credits',
'percentage': None
},
{
'title': 'Image AI Credits',
'limit': plan.monthly_image_ai_credits or 0,
'used': image_credits,
'available': max(0, (plan.monthly_image_ai_credits or 0) - image_credits),
'unit': 'credits',
'category': 'ai',
'percentage': (image_credits / (plan.monthly_image_ai_credits or 1)) * 100 if plan.monthly_image_ai_credits else 0
},
{
'title': 'Cluster AI Credits',
'limit': plan.monthly_cluster_ai_credits or 0,
'title': 'Clustering Credits',
'limit': None,
'used': cluster_credits,
'available': max(0, (plan.monthly_cluster_ai_credits or 0) - cluster_credits),
'available': None,
'unit': 'credits',
'category': 'ai',
'percentage': (cluster_credits / (plan.monthly_cluster_ai_credits or 1)) * 100 if plan.monthly_cluster_ai_credits else 0
'category': 'credits',
'percentage': None
},
{
'title': 'Content Generation Credits',
'limit': None,
'used': content_credits,
'available': None,
'unit': 'credits',
'category': 'credits',
'percentage': None
},
{
'title': 'Image Generation Credits',
'limit': None,
'used': image_credits,
'available': None,
'unit': 'credits',
'category': 'credits',
'percentage': None
},
{
'title': 'Idea Generation Credits',
'limit': None,
'used': idea_credits,
'available': None,
'unit': 'credits',
'category': 'credits',
'percentage': None
},
])
# General Limits
# Account Management Limits (kept - not operation limits)
users_count = User.objects.filter(account=account).count()
sites_count = Site.objects.filter(account=account).count()
@@ -426,7 +349,7 @@ class CreditUsageViewSet(AccountModelViewSet):
'used': users_count,
'available': max(0, (plan.max_users or 0) - users_count),
'unit': 'users',
'category': 'general',
'category': 'account',
'percentage': (users_count / (plan.max_users or 1)) * 100 if plan.max_users else 0
},
{
@@ -435,7 +358,7 @@ class CreditUsageViewSet(AccountModelViewSet):
'used': sites_count,
'available': max(0, (plan.max_sites or 0) - sites_count),
'unit': 'sites',
'category': 'general',
'category': 'account',
'percentage': (sites_count / (plan.max_sites or 1)) * 100 if plan.max_sites else 0
},
])