Enhance API response handling and implement unified API standard across multiple modules. Added feature flags for unified exception handling and debug throttling in settings. Updated pagination and response formats in various viewsets to align with the new standard. Improved error handling and response validation in frontend components for better user feedback.

This commit is contained in:
IGNY8 VPS (Salman)
2025-11-15 20:18:42 +00:00
parent 94f243f4a2
commit a75ebf2584
18 changed files with 1974 additions and 642 deletions

View File

@@ -1,5 +1,6 @@
"""
ViewSets for Billing API
Unified API Standard v1.0 compliant
"""
from rest_framework import viewsets, status, permissions
from rest_framework.decorators import action
@@ -10,6 +11,8 @@ from datetime import timedelta
from decimal import Decimal
from igny8_core.api.base import AccountModelViewSet
from igny8_core.api.pagination import CustomPageNumberPagination
from igny8_core.api.response import success_response, error_response
from igny8_core.api.throttles import DebugScopedRateThrottle
from igny8_core.api.authentication import JWTAuthentication, CSRFExemptSessionAuthentication
from .models import CreditTransaction, CreditUsageLog
from .serializers import (
@@ -23,9 +26,12 @@ from .exceptions import InsufficientCreditsError
class CreditBalanceViewSet(viewsets.ViewSet):
"""
ViewSet for credit balance operations
Unified API Standard v1.0 compliant
"""
permission_classes = [permissions.IsAuthenticated]
authentication_classes = [JWTAuthentication, CSRFExemptSessionAuthentication]
throttle_scope = 'billing'
throttle_classes = [DebugScopedRateThrottle]
@action(detail=False, methods=['get'])
def balance(self, request):
@@ -37,9 +43,10 @@ class CreditBalanceViewSet(viewsets.ViewSet):
account = getattr(user, 'account', None)
if not account:
return Response(
{'error': 'Account not found'},
status=status.HTTP_400_BAD_REQUEST
return error_response(
error='Account not found',
status_code=status.HTTP_400_BAD_REQUEST,
request=request
)
# Get plan credits per month
@@ -63,18 +70,21 @@ class CreditBalanceViewSet(viewsets.ViewSet):
}
serializer = CreditBalanceSerializer(data)
return Response(serializer.data)
return success_response(data=serializer.data, request=request)
class CreditUsageViewSet(viewsets.ReadOnlyModelViewSet):
"""
ViewSet for credit usage logs
Unified API Standard v1.0 compliant
"""
queryset = CreditUsageLog.objects.all()
serializer_class = CreditUsageLogSerializer
permission_classes = [permissions.IsAuthenticated]
authentication_classes = [JWTAuthentication, CSRFExemptSessionAuthentication]
pagination_class = CustomPageNumberPagination
throttle_scope = 'billing'
throttle_classes = [DebugScopedRateThrottle]
filter_backends = []
@@ -116,9 +126,10 @@ class CreditUsageViewSet(viewsets.ReadOnlyModelViewSet):
account = getattr(user, 'account', None)
if not account:
return Response(
{'error': 'Account not found'},
status=status.HTTP_400_BAD_REQUEST
return error_response(
error='Account not found',
status_code=status.HTTP_400_BAD_REQUEST,
request=request
)
# Get date range from query params
@@ -192,7 +203,7 @@ class CreditUsageViewSet(viewsets.ReadOnlyModelViewSet):
}
serializer = UsageSummarySerializer(data)
return Response(serializer.data)
return success_response(data=serializer.data, request=request)
@action(detail=False, methods=['get'], url_path='limits', url_name='limits')
def limits(self, request):
@@ -222,12 +233,12 @@ class CreditUsageViewSet(viewsets.ReadOnlyModelViewSet):
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 Response({'limits': []})
return success_response(data={'limits': []}, request=request)
plan = account.plan
if not plan:
# Return empty limits instead of error - allows frontend to show "no plan" message
return Response({'limits': []})
return success_response(data={'limits': []}, request=request)
# Import models
from igny8_core.modules.planner.models import Keywords, Clusters, ContentIdeas
@@ -430,18 +441,21 @@ class CreditUsageViewSet(viewsets.ReadOnlyModelViewSet):
])
# Return data directly - serializer validation not needed for read-only endpoint
return Response({'limits': limits_data})
return success_response(data={'limits': limits_data}, request=request)
class CreditTransactionViewSet(viewsets.ReadOnlyModelViewSet):
"""
ViewSet for credit transaction history
Unified API Standard v1.0 compliant
"""
queryset = CreditTransaction.objects.all()
serializer_class = CreditTransactionSerializer
permission_classes = [permissions.IsAuthenticated]
authentication_classes = [JWTAuthentication, CSRFExemptSessionAuthentication]
pagination_class = CustomPageNumberPagination
throttle_scope = 'billing'
throttle_classes = [DebugScopedRateThrottle]
def get_queryset(self):
"""Get transactions for current account"""