Расширена валидация для возвращённых заказов: запрет любых статусов кроме отрицательных

Проблема:
Для заказа с is_returned=True без резервов (товар продан в другом заказе)
можно было установить промежуточные статусы (В доставке, Черновик и т.п.),
что не имеет смысла, т.к. физически продавать уже нечего.

Решение:
Валидация теперь проверяет ДО проверки is_positive_end:
- Если is_returned=True И резервов нет И статус НЕ отрицательный →
  запрещаем ЛЮБОЕ изменение статуса
- Разрешены только статусы с is_negative_end=True (отменён и т.п.)

Улучшено сообщение об ошибке:
- Убраны длинные объяснения
- Короткая структура с переносами строк
- Чёткое указание: «товары проданы в другом заказе»
- Действие: «создайте новый заказ»

Теперь возвращённый заказ без резервов навсегда остаётся в статусе
отрицательного исхода — как и должно быть в реальности.
This commit is contained in:
2025-12-12 00:03:10 +03:00
parent 503a00de74
commit 2dcdc0941f

View File

@@ -133,31 +133,33 @@ def create_sale_on_order_completion(sender, instance, created, **kwargs):
if not instance.status:
return
# Проверяем: это положительный финальный статус?
is_positive_end = instance.status.is_positive_end
if not is_positive_end:
return # Только для положительных финальных статусов (completed и т.п.)
# === ВАЛИДАЦИЯ: Запрет повторного completed для возвращённых заказов без резервов ===
# === ВАЛИДАЦИЯ: Запрет изменения статуса для возвращённых заказов без резервов ===
# Если заказ был возвращён (is_returned=True) и резервов нет, можно использовать
# только статусы отрицательного исхода (отменён и т.п.)
if instance.is_returned:
# Заказ уже был продан и возвращён — проверяем наличие резервов
has_reservations = Reservation.objects.filter(
order_item__order=instance
).exists()
if not has_reservations:
# Резервов нет — товар уже ушёл в другой заказ или был освобождён
logger.error(
f"❌ Заказ {instance.order_number} имеет флаг is_returned=True и не имеет резервов. "
f"Невозможно перевести в статус '{instance.status.name}'."
)
raise ValidationError(
f"Невозможно установить статус '{instance.status.name}' для заказа {instance.order_number}. "
f"Этот заказ уже был отменён после продажи, резервы отсутствуют. "
f"Товары могли быть проданы в другом заказе. "
f"Пожалуйста, оставьте статус отрицательного исхода (отменён) или создайте новый заказ."
)
# Резервов нет — разрешены только отрицательные статусы
if not instance.status.is_negative_end:
logger.error(
f"❌ Заказ {instance.order_number}: is_returned=True, резервов нет. "
f"Попытка установить '{instance.status.name}' запрещена."
)
raise ValidationError(
f"Невозможно изменить статус заказа {instance.order_number}.\n\n"
f"Этот заказ был отменён после продажи, товары проданы в другом заказе.\n"
f"Разрешены только статусы отрицательного исхода (отменён).\n\n"
f"Для новой продажи создайте новый заказ."
)
# Проверяем: это положительный финальный статус?
is_positive_end = instance.status.is_positive_end
if not is_positive_end:
return # Только для положительных финальных статусов (completed и т.п.)
# Защита от повторного списания: проверяем, не созданы ли уже Sale для этого заказа
if Sale.objects.filter(order=instance).exists():