Рефакторинг: убрано дублирование валидации витринных комплектов

Проблема:
Валидация showcase_items выполнялась в двух местах:
1. В pos/views.py - проверка status='in_cart' БЕЗ блокировки БД
2. В showcase_manager.py - перезагрузка с select_for_update() и повторная проверка

Это создавало:
- Дублирование кода и логики
- Возможность race condition между двумя запросами
- Избыточные обращения к БД
- Мертвый код (неработающие logger.info)

Решение (best practices):
1. Views только загружают объекты по ID без фильтров по статусу
2. ВСЯ валидация и бизнес-логика в одном месте - ShowcaseManager.sell_showcase_items
3. select_for_update() гарантирует актуальность данных и блокировку на уровне БД
4. Удален мертвый код (logger.info которые не выполнялись)
5. Убрано избыточное логирование ошибок валидации

Результат:
- Единое место ответственности (Single Responsibility)
- Нет дублирования
- Атомарная транзакция с блокировкой
- Чистый, понятный код без костылей
This commit is contained in:
2025-12-11 22:27:15 +03:00
parent 0d72c36739
commit 95cb1c4bac

View File

@@ -1468,27 +1468,11 @@ def pos_checkout(request):
# Продаём экземпляры через ShowcaseManager
if showcase_item_ids:
# Логируем для отладки
logger.info(f'POS Checkout: попытка продать showcase_item_ids={showcase_item_ids}')
# Проверяем что все экземпляры заблокированы на текущего пользователя
# ShowcaseManager.sell_showcase_items выполнит всю валидацию с блокировкой БД
showcase_items = list(ShowcaseItem.objects.filter(
id__in=showcase_item_ids,
status='in_cart',
locked_by_user=request.user
id__in=showcase_item_ids
))
logger.info(f'POS Checkout: найдено {len(showcase_items)} заблокированных экземпляров из {len(showcase_item_ids)} запрошенных')
if len(showcase_items) != len(showcase_item_ids):
# Не все экземпляры доступны
missing_ids = set(showcase_item_ids) - set(item.id for item in showcase_items)
logger.warning(f'POS Checkout: недоступные showcase_item_ids={missing_ids}')
raise ValidationError(
f'Некоторые экземпляры букета уже не заблокированы на вас. '
f'Обновите страницу и попробуйте снова.'
)
if showcase_items:
result = ShowcaseManager.sell_showcase_items(showcase_items, order_item)
if not result['success']:
@@ -1532,10 +1516,8 @@ def pos_checkout(request):
})
except (Customer.DoesNotExist, Warehouse.DoesNotExist, Product.DoesNotExist, ProductKit.DoesNotExist) as e:
logger.error(f'POS Checkout: объект не найден: {str(e)}')
return JsonResponse({'success': False, 'error': 'Объект не найден'}, status=404)
except ValidationError as e:
logger.error(f'POS Checkout: ошибка валидации: {str(e)}', exc_info=True)
return JsonResponse({'success': False, 'error': str(e)}, status=400)
except json.JSONDecodeError:
return JsonResponse({'success': False, 'error': 'Неверный формат JSON'}, status=400)