Fix cart lock validation and error handling improvements
## 1. Add cart lock validation to sell_from_showcase() - Prevent selling showcase kits locked in another cashier's cart - Check cart_lock_expires_at before allowing direct sales - Return clear error message with lock holder's name and time remaining - File: inventory/services/showcase_manager.py ## 2. Improve error handling in POS create_temp_kit_to_showcase() - Add detailed logging for all error types (JSON, validation, generic) - Provide user-friendly error messages instead of generic 500 - Log full context (kit name, showcase ID, items, user) for debugging - Categorize errors: stock issues, integrity, locks, not found - File: pos/views.py ## 3. Fix critical bug in create_temporary_kit() - Replace non-existent is_active field with status='active' - Affects 3 locations: kit creation, product lookup, kit duplication - This was causing 500 errors when creating temporary kits from order edit - File: products/services/kit_service.py ## 4. Improve error handling in create_temporary_kit_api() - Add comprehensive logging for order creation endpoint - Provide specific error messages for common failure scenarios - Help diagnose issues when creating kits from order editing UI - File: products/views/api_views.py These changes complete the Soft Lock system and fix the 500 error issue. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -57,7 +57,7 @@ def create_temporary_kit(
|
||||
name=name.strip(),
|
||||
description=description.strip() if description else '',
|
||||
is_temporary=True,
|
||||
is_active=True,
|
||||
status='active',
|
||||
order=order,
|
||||
price_adjustment_type='none'
|
||||
)
|
||||
@@ -72,7 +72,7 @@ def create_temporary_kit(
|
||||
continue
|
||||
|
||||
try:
|
||||
product = Product.objects.get(pk=product_id, is_active=True)
|
||||
product = Product.objects.get(pk=product_id, status='active')
|
||||
KitItem.objects.create(
|
||||
kit=kit,
|
||||
product=product,
|
||||
@@ -135,7 +135,7 @@ def duplicate_kit(kit: ProductKit, new_name: Optional[str] = None) -> ProductKit
|
||||
price_adjustment_value=kit.price_adjustment_value,
|
||||
sale_price=kit.sale_price,
|
||||
is_temporary=False, # Копия всегда постоянная
|
||||
is_active=kit.is_active
|
||||
status=kit.status
|
||||
)
|
||||
|
||||
# Копируем категории
|
||||
|
||||
@@ -4,9 +4,13 @@ API представления для приложения products.
|
||||
from django.http import JsonResponse
|
||||
from django.db import models
|
||||
from django.core.cache import cache
|
||||
from django.core.exceptions import ValidationError
|
||||
import logging
|
||||
|
||||
from ..models import Product, ProductVariantGroup, ProductKit
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def search_products_and_variants(request):
|
||||
"""
|
||||
@@ -629,20 +633,68 @@ def create_temporary_kit_api(request):
|
||||
})
|
||||
|
||||
except ValueError as e:
|
||||
logger.warning(f'Validation error при создании временного комплекта: {str(e)}')
|
||||
return JsonResponse({
|
||||
'success': False,
|
||||
'error': str(e)
|
||||
}, status=400)
|
||||
except json.JSONDecodeError:
|
||||
except json.JSONDecodeError as e:
|
||||
logger.error(f'JSON decode error при создании временного комплекта: {str(e)}')
|
||||
return JsonResponse({
|
||||
'success': False,
|
||||
'error': 'Некорректный JSON'
|
||||
'error': 'Некорректный JSON в запросе'
|
||||
}, status=400)
|
||||
except ValidationError as e:
|
||||
logger.error(f'Django ValidationError при создании временного комплекта: {str(e)}', exc_info=True)
|
||||
return JsonResponse({
|
||||
'success': False,
|
||||
'error': f'Ошибка валидации: {str(e)}'
|
||||
}, status=400)
|
||||
except Exception as e:
|
||||
return JsonResponse({
|
||||
'success': False,
|
||||
'error': f'Ошибка при создании комплекта: {str(e)}'
|
||||
}, status=500)
|
||||
# Детальное логирование для диагностики 500 ошибок
|
||||
try:
|
||||
data = json.loads(request.body)
|
||||
name = data.get('name', 'N/A')
|
||||
order_id = data.get('order_id', 'N/A')
|
||||
components_count = len(data.get('components', []))
|
||||
except:
|
||||
name = 'N/A'
|
||||
order_id = 'N/A'
|
||||
components_count = 'N/A'
|
||||
|
||||
logger.error(
|
||||
f'Непредвиденная ошибка при создании временного комплекта:\n'
|
||||
f' Название: {name}\n'
|
||||
f' Заказ ID: {order_id}\n'
|
||||
f' Количество компонентов: {components_count}\n'
|
||||
f' Пользователь: {request.user.username if request.user.is_authenticated else "Anonymous"}\n'
|
||||
f' Ошибка: {str(e)}',
|
||||
exc_info=True
|
||||
)
|
||||
|
||||
# Проверяем на типичные ошибки и даём понятные сообщения
|
||||
error_msg = str(e).lower()
|
||||
|
||||
if 'недостаточно' in error_msg or 'insufficient' in error_msg or 'stock' in error_msg:
|
||||
return JsonResponse({
|
||||
'success': False,
|
||||
'error': f'Недостаточно товара на складе. {str(e)}'
|
||||
}, status=400)
|
||||
elif 'integrity' in error_msg or 'constraint' in error_msg:
|
||||
return JsonResponse({
|
||||
'success': False,
|
||||
'error': 'Ошибка целостности данных. Проверьте, что все товары существуют.'
|
||||
}, status=400)
|
||||
elif 'not found' in error_msg or 'does not exist' in error_msg or 'не найден' in error_msg:
|
||||
return JsonResponse({
|
||||
'success': False,
|
||||
'error': f'Объект не найден: {str(e)}'
|
||||
}, status=404)
|
||||
else:
|
||||
return JsonResponse({
|
||||
'success': False,
|
||||
'error': f'Не удалось создать комплект: {str(e)}. Проверьте консоль сервера для деталей.'
|
||||
}, status=500)
|
||||
|
||||
|
||||
def create_tag_api(request):
|
||||
|
||||
Reference in New Issue
Block a user