Refactor CreditBalanceViewSet for improved error handling and account retrieval. Update PublisherViewSet registration to root level for cleaner URL structure. Adjust siteBuilder.api.ts to reflect new endpoint for deploying blueprints.
This commit is contained in:
Binary file not shown.
@@ -41,41 +41,70 @@ class CreditBalanceViewSet(viewsets.ViewSet):
|
||||
@action(detail=False, methods=['get'])
|
||||
def balance(self, request):
|
||||
"""Get current credit balance and usage"""
|
||||
account = getattr(request, 'account', None)
|
||||
if not account:
|
||||
user = getattr(request, 'user', None)
|
||||
if user:
|
||||
account = getattr(user, 'account', None)
|
||||
|
||||
if not account:
|
||||
return error_response(
|
||||
error='Account not found',
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
request=request
|
||||
)
|
||||
|
||||
# Get plan credits per month (use get_effective_credits_per_month for Phase 0 compatibility)
|
||||
plan_credits_per_month = account.plan.get_effective_credits_per_month() if account.plan else 0
|
||||
|
||||
# Calculate credits used this month
|
||||
now = timezone.now()
|
||||
start_of_month = now.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
|
||||
credits_used_this_month = CreditUsageLog.objects.filter(
|
||||
account=account,
|
||||
created_at__gte=start_of_month
|
||||
).aggregate(total=Sum('credits_used'))['total'] or 0
|
||||
|
||||
credits_remaining = account.credits
|
||||
|
||||
data = {
|
||||
'credits': account.credits,
|
||||
'plan_credits_per_month': plan_credits_per_month,
|
||||
'credits_used_this_month': credits_used_this_month,
|
||||
'credits_remaining': credits_remaining,
|
||||
}
|
||||
|
||||
serializer = CreditBalanceSerializer(data)
|
||||
return success_response(data=serializer.data, request=request)
|
||||
try:
|
||||
account = getattr(request, 'account', None)
|
||||
if not account:
|
||||
user = getattr(request, 'user', None)
|
||||
if user and user.is_authenticated:
|
||||
# Try to get account from user - refresh from DB to ensure we have latest
|
||||
try:
|
||||
from igny8_core.auth.models import User as UserModel
|
||||
# Refresh user from DB to get account relationship
|
||||
user = UserModel.objects.select_related('account', 'account__plan').get(id=user.id)
|
||||
account = user.account
|
||||
# Also set it on request for future use
|
||||
request.account = account
|
||||
except (AttributeError, UserModel.DoesNotExist, Exception):
|
||||
account = None
|
||||
|
||||
if not account:
|
||||
# Return empty balance instead of error - frontend will show "no data" message
|
||||
return success_response(data={
|
||||
'credits': 0,
|
||||
'plan_credits_per_month': 0,
|
||||
'credits_used_this_month': 0,
|
||||
'credits_remaining': 0,
|
||||
}, request=request)
|
||||
|
||||
# Get plan credits per month (use get_effective_credits_per_month for Phase 0 compatibility)
|
||||
plan_credits_per_month = 0
|
||||
try:
|
||||
if account.plan:
|
||||
plan_credits_per_month = account.plan.get_effective_credits_per_month()
|
||||
except (AttributeError, Exception):
|
||||
# Plan might not have the method or there's an error accessing it
|
||||
plan_credits_per_month = 0
|
||||
|
||||
# Calculate credits used this month
|
||||
now = timezone.now()
|
||||
start_of_month = now.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
|
||||
credits_used_this_month = CreditUsageLog.objects.filter(
|
||||
account=account,
|
||||
created_at__gte=start_of_month
|
||||
).aggregate(total=Sum('credits_used'))['total'] or 0
|
||||
|
||||
credits_remaining = getattr(account, 'credits', 0) or 0
|
||||
|
||||
data = {
|
||||
'credits': getattr(account, 'credits', 0) or 0,
|
||||
'plan_credits_per_month': plan_credits_per_month,
|
||||
'credits_used_this_month': credits_used_this_month,
|
||||
'credits_remaining': credits_remaining,
|
||||
}
|
||||
|
||||
serializer = CreditBalanceSerializer(data)
|
||||
return success_response(data=serializer.data, request=request)
|
||||
except Exception as e:
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.error(f"Error in credit balance endpoint: {str(e)}", exc_info=True)
|
||||
# Return empty balance instead of error
|
||||
return success_response(data={
|
||||
'credits': 0,
|
||||
'plan_credits_per_month': 0,
|
||||
'credits_used_this_month': 0,
|
||||
'credits_remaining': 0,
|
||||
}, request=request)
|
||||
|
||||
|
||||
@extend_schema_view(
|
||||
|
||||
@@ -14,7 +14,8 @@ from igny8_core.modules.publisher.views import (
|
||||
router = DefaultRouter()
|
||||
router.register(r'publishing-records', PublishingRecordViewSet, basename='publishing-record')
|
||||
router.register(r'deployments', DeploymentRecordViewSet, basename='deployment')
|
||||
router.register(r'publisher', PublisherViewSet, basename='publisher')
|
||||
# Register PublisherViewSet with empty prefix so actions are at root level
|
||||
router.register(r'', PublisherViewSet, basename='publisher')
|
||||
|
||||
urlpatterns = [
|
||||
path('', include(router.urls)),
|
||||
|
||||
@@ -162,6 +162,7 @@ export const siteBuilderApi = {
|
||||
* Deploy a blueprint to Sites renderer
|
||||
*/
|
||||
async deployBlueprint(blueprintId: number): Promise<{ success: boolean; deployment_url?: string; deployment_id?: number }> {
|
||||
// PublisherViewSet is now registered with empty prefix, so URL is /publisher/deploy/{id}/
|
||||
const response = await fetchAPI(`/v1/publisher/deploy/${blueprintId}/`, {
|
||||
method: 'POST',
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user