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

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