Compare commits
6 Commits
8a9dd44c50
...
1531f41226
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1531f41226 | ||
|
|
37a64fa1ef | ||
|
|
c4daeb1870 | ||
|
|
79aab68acd | ||
|
|
11a5a66c8b | ||
|
|
ab292de06c |
@@ -193,7 +193,6 @@ 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
|
||||||
@@ -205,9 +204,8 @@ 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 (CreditService handles developer/system account bypass)
|
# Check credits BEFORE AI call
|
||||||
# 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)
|
||||||
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:
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ class CreditService:
|
|||||||
return base_cost
|
return base_cost
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def check_credits(account, operation_type, amount=None, user=None):
|
def check_credits(account, operation_type, amount=None):
|
||||||
"""
|
"""
|
||||||
Check if account has sufficient credits for an operation.
|
Check if account has sufficient credits for an operation.
|
||||||
|
|
||||||
@@ -57,35 +57,10 @@ 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(
|
||||||
@@ -94,40 +69,17 @@ class CreditService:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def check_credits_legacy(account, required_credits, user=None):
|
def check_credits_legacy(account, required_credits):
|
||||||
"""
|
"""
|
||||||
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}"
|
||||||
|
|||||||
@@ -309,17 +309,26 @@ class ModuleEnableSettingsViewSet(AccountModelViewSet):
|
|||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
"""Get module enable settings for current account"""
|
"""Get module enable settings for current account"""
|
||||||
# Don't filter here - list() and retrieve() handle get_or_create
|
# Return queryset filtered by account - but list() will handle get_or_create
|
||||||
# This prevents empty queryset from causing 404 errors
|
queryset = super().get_queryset()
|
||||||
return ModuleEnableSettings.objects.all()
|
# Filter by account if available
|
||||||
|
account = getattr(self.request, 'account', None)
|
||||||
|
if not account:
|
||||||
|
user = getattr(self.request, 'user', None)
|
||||||
|
if user:
|
||||||
|
account = getattr(user, 'account', None)
|
||||||
|
if account:
|
||||||
|
queryset = queryset.filter(account=account)
|
||||||
|
return queryset
|
||||||
|
|
||||||
def list(self, request, *args, **kwargs):
|
def list(self, request, *args, **kwargs):
|
||||||
"""Get or create module enable settings for current account"""
|
"""Get or create module enable settings for current account"""
|
||||||
|
try:
|
||||||
account = getattr(request, 'account', None)
|
account = getattr(request, 'account', None)
|
||||||
if not account:
|
if not account:
|
||||||
user = getattr(request, 'user', None)
|
user = getattr(request, 'user', None)
|
||||||
if user and hasattr(user, 'account'):
|
if user and hasattr(user, 'account'):
|
||||||
account = getattr(user, 'account', None)
|
account = user.account
|
||||||
|
|
||||||
if not account:
|
if not account:
|
||||||
return error_response(
|
return error_response(
|
||||||
@@ -329,9 +338,22 @@ class ModuleEnableSettingsViewSet(AccountModelViewSet):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Get or create settings for account (one per account)
|
# Get or create settings for account (one per account)
|
||||||
settings, created = ModuleEnableSettings.objects.get_or_create(account=account)
|
try:
|
||||||
|
settings = ModuleEnableSettings.objects.get(account=account)
|
||||||
|
except ModuleEnableSettings.DoesNotExist:
|
||||||
|
# Create default settings for account
|
||||||
|
settings = ModuleEnableSettings.objects.create(account=account)
|
||||||
|
|
||||||
serializer = self.get_serializer(settings)
|
serializer = self.get_serializer(settings)
|
||||||
return success_response(data=serializer.data, request=request)
|
return success_response(data=serializer.data, request=request)
|
||||||
|
except Exception as e:
|
||||||
|
import traceback
|
||||||
|
error_trace = traceback.format_exc()
|
||||||
|
return error_response(
|
||||||
|
error=f'Failed to load module enable settings: {str(e)}',
|
||||||
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
request=request
|
||||||
|
)
|
||||||
|
|
||||||
def retrieve(self, request, pk=None, *args, **kwargs):
|
def retrieve(self, request, pk=None, *args, **kwargs):
|
||||||
"""Get module enable settings for current account"""
|
"""Get module enable settings for current account"""
|
||||||
|
|||||||
Reference in New Issue
Block a user