Fix credit system: Add developer/system account bypass for credit checks

- CreditService.check_credits() now bypasses for:
  1. System accounts (aws-admin, default-account, default)
  2. Developer/admin users (if user provided)
  3. Accounts with developer users (fallback for Celery tasks)
- Updated check_credits_legacy() with same bypass logic
- AIEngine credit check now uses updated CreditService
- Fixes 52 console errors caused by credit checks blocking developers
- Developers can now use AI functions without credit restrictions
This commit is contained in:
IGNY8 VPS (Salman)
2025-11-16 19:40:44 +00:00
parent 8171014a7e
commit 066b81dd2a
2 changed files with 54 additions and 4 deletions

View File

@@ -193,6 +193,7 @@ class AIEngine:
self.tracker.update("PREP", 25, prep_message, meta=self.step_tracker.get_meta()) self.tracker.update("PREP", 25, prep_message, meta=self.step_tracker.get_meta())
# Phase 2.5: CREDIT CHECK - Check credits before AI call (25%) # Phase 2.5: CREDIT CHECK - Check credits before AI call (25%)
# Bypass for system accounts and developers (handled in CreditService)
if self.account: if self.account:
try: try:
from igny8_core.modules.billing.services import CreditService from igny8_core.modules.billing.services import CreditService
@@ -204,8 +205,9 @@ class AIEngine:
# Calculate estimated cost # Calculate estimated cost
estimated_amount = self._get_estimated_amount(function_name, data, payload) estimated_amount = self._get_estimated_amount(function_name, data, payload)
# Check credits BEFORE AI call # Check credits BEFORE AI call (CreditService handles developer/system account bypass)
CreditService.check_credits(self.account, operation_type, estimated_amount) # Note: user=None for Celery tasks, but CreditService checks account.is_system_account() and developer users
CreditService.check_credits(self.account, operation_type, estimated_amount, user=None)
logger.info(f"[AIEngine] Credit check passed: {operation_type}, estimated amount: {estimated_amount}") logger.info(f"[AIEngine] Credit check passed: {operation_type}, estimated amount: {estimated_amount}")
except InsufficientCreditsError as e: except InsufficientCreditsError as e:

View File

@@ -49,7 +49,7 @@ class CreditService:
return base_cost return base_cost
@staticmethod @staticmethod
def check_credits(account, operation_type, amount=None): def check_credits(account, operation_type, amount=None, user=None):
""" """
Check if account has sufficient credits for an operation. Check if account has sufficient credits for an operation.
@@ -57,10 +57,35 @@ class CreditService:
account: Account instance account: Account instance
operation_type: Type of operation operation_type: Type of operation
amount: Optional amount (word count, image count, etc.) amount: Optional amount (word count, image count, etc.)
user: Optional user instance (for developer/admin bypass)
Raises: Raises:
InsufficientCreditsError: If account doesn't have enough credits InsufficientCreditsError: If account doesn't have enough credits
""" """
# Bypass credit check for:
# 1. System accounts (aws-admin, default-account, default)
# 2. Developer/admin users (if user provided)
if account and account.is_system_account():
return True
if user:
try:
if hasattr(user, 'is_admin_or_developer') and user.is_admin_or_developer():
return True
if hasattr(user, 'is_system_account_user') and user.is_system_account_user():
return True
except (AttributeError, Exception):
pass
# Check if account has any developer users (fallback for Celery tasks without user context)
if account:
try:
from igny8_core.auth.models import User
if User.objects.filter(account=account, role='developer').exists():
return True
except (AttributeError, Exception):
pass
required = CreditService.get_credit_cost(operation_type, amount) required = CreditService.get_credit_cost(operation_type, amount)
if account.credits < required: if account.credits < required:
raise InsufficientCreditsError( raise InsufficientCreditsError(
@@ -69,17 +94,40 @@ class CreditService:
return True return True
@staticmethod @staticmethod
def check_credits_legacy(account, required_credits): def check_credits_legacy(account, required_credits, user=None):
""" """
Legacy method: Check if account has enough credits (for backward compatibility). Legacy method: Check if account has enough credits (for backward compatibility).
Args: Args:
account: Account instance account: Account instance
required_credits: Number of credits required required_credits: Number of credits required
user: Optional user instance (for developer/admin bypass)
Raises: Raises:
InsufficientCreditsError: If account doesn't have enough credits InsufficientCreditsError: If account doesn't have enough credits
""" """
# Bypass credit check for system accounts and developers
if account and account.is_system_account():
return
if user:
try:
if hasattr(user, 'is_admin_or_developer') and user.is_admin_or_developer():
return
if hasattr(user, 'is_system_account_user') and user.is_system_account_user():
return
except (AttributeError, Exception):
pass
# Check if account has any developer users (fallback for Celery tasks)
if account:
try:
from igny8_core.auth.models import User
if User.objects.filter(account=account, role='developer').exists():
return
except (AttributeError, Exception):
pass
if account.credits < required_credits: if account.credits < required_credits:
raise InsufficientCreditsError( raise InsufficientCreditsError(
f"Insufficient credits. Required: {required_credits}, Available: {account.credits}" f"Insufficient credits. Required: {required_credits}, Available: {account.credits}"