Исправлен баг: ShowcaseItem теперь корректно переходит available → sold при cancelled → completed

Проблема:
- При переходе заказа cancelled → completed витринный букет оставался в статусе 'available'
- Логика финализации искала только ShowcaseItem в статусе 'reserved'
- НО при отмене (cancelled) ShowcaseItem переходит в 'available', а не остаётся в 'reserved'
- Итог: букет не финализировался, оставался свободным вместо проданного

Решение:
- inventory/signals.py: в сигнале create_sale_on_order_completion обновлена логика финализации
- Теперь ищем ShowcaseItem в статусах ['reserved', 'available']
- Для статуса 'reserved': вызываем mark_sold_from_reserved() (обычный flow)
- Для статуса 'available': вызываем mark_sold() (переход из отмены cancelled → completed)
- Оба метода корректно переводят букет в 'sold' и устанавливают sold_at

Flow переходов:
1. Обычный: draft → completed: ShowcaseItem reserved → sold 
2. Из отмены: cancelled → completed: ShowcaseItem available → sold  (ИСПРАВЛЕНО)
This commit is contained in:
2026-01-05 09:23:50 +03:00
parent 366ead7404
commit 6c497bbde3

View File

@@ -494,23 +494,34 @@ def create_sale_on_order_completion(sender, instance, created, **kwargs):
f"✓ Обновлено {updated_count} резервов для заказа {instance.order_number}: reserved → converted_to_sale" f"✓ Обновлено {updated_count} резервов для заказа {instance.order_number}: reserved → converted_to_sale"
) )
# === Финализация витринных экземпляров: reserved → sold === # === Финализация витринных экземпляров: reserved/available → sold ===
# Находим все витринные комплекты в этом заказе, которые в статусе reserved # Находим все витринные комплекты в этом заказе:
# - в статусе 'reserved' (обычный flow: создание черновика → завершение)
# - в статусе 'available' (переход из отмены: cancelled → completed)
from inventory.models import ShowcaseItem from inventory.models import ShowcaseItem
showcase_items_to_finalize = ShowcaseItem.objects.filter( showcase_items_to_finalize = ShowcaseItem.objects.filter(
sold_order_item__order=instance, sold_order_item__order=instance,
status='reserved' status__in=['reserved', 'available']
) )
finalized_count = 0 finalized_count = 0
for showcase_item in showcase_items_to_finalize: for showcase_item in showcase_items_to_finalize:
try: try:
showcase_item.mark_sold_from_reserved() if showcase_item.status == 'reserved':
# Обычный flow: reserved → sold
showcase_item.mark_sold_from_reserved()
logger.info(
f"✓ Витринный экземпляр #{showcase_item.id} финализирован: reserved → sold"
)
elif showcase_item.status == 'available':
# Переход из отмены: available → sold (минуя reserved)
# Используем mark_sold() который работает с available
showcase_item.mark_sold(showcase_item.sold_order_item)
logger.info(
f"✓ Витринный экземпляр #{showcase_item.id} финализирован: available → sold (из отмены)"
)
finalized_count += 1 finalized_count += 1
logger.info(
f"✓ Витринный экземпляр #{showcase_item.id} финализирован: reserved → sold"
)
except Exception as e: except Exception as e:
logger.error( logger.error(
f"❌ Ошибка финализации ShowcaseItem #{showcase_item.id}: {e}" f"❌ Ошибка финализации ShowcaseItem #{showcase_item.id}: {e}"