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:
@@ -144,7 +144,7 @@ class ShowcaseManager:
|
||||
reservations = Reservation.objects.filter(
|
||||
showcase=showcase,
|
||||
status='reserved'
|
||||
).select_related('product')
|
||||
).select_related('product', 'locked_by_user')
|
||||
|
||||
if not reservations.exists():
|
||||
return {
|
||||
@@ -153,6 +153,26 @@ class ShowcaseManager:
|
||||
'message': f'На витрине "{showcase.name}" нет зарезервированных товаров'
|
||||
}
|
||||
|
||||
# Проверяем блокировки корзины (Soft Lock)
|
||||
# Если комплект заблокирован в корзине другого кассира, запрещаем продажу
|
||||
active_locks = reservations.filter(
|
||||
cart_lock_expires_at__gt=timezone.now(),
|
||||
cart_lock_expires_at__isnull=False
|
||||
)
|
||||
|
||||
if active_locks.exists():
|
||||
lock = active_locks.first()
|
||||
time_left = (lock.cart_lock_expires_at - timezone.now()).total_seconds() / 60
|
||||
locker_name = lock.locked_by_user.username if lock.locked_by_user else 'неизвестный кассир'
|
||||
|
||||
return {
|
||||
'success': False,
|
||||
'order': None,
|
||||
'message': f'Комплект заблокирован в корзине кассира "{locker_name}". '
|
||||
f'Блокировка истечёт через {int(time_left)} мин. '
|
||||
f'Дождитесь освобождения или попросите кассира удалить букет из корзины.'
|
||||
}
|
||||
|
||||
# Получаем статус "Завершён" для POS-продаж
|
||||
completed_status = OrderStatus.objects.filter(
|
||||
code='completed',
|
||||
|
||||
Reference in New Issue
Block a user