Исправлен порядок обработки ShowcaseItem при переходе cancelled → completed

Проблема:
- При переходе cancelled → completed срабатывали ОБА сигнала:
  1. reserve_stock_on_uncancellation переводил ShowcaseItem: available → reserved
  2. create_sale_on_order_completion искал букеты в available, но они уже в reserved
  3. Букеты оставались в reserved вместо sold

Решение:
- inventory/signals.py: в reserve_stock_on_uncancellation добавлена проверка current_status.is_positive_end
- Если текущий статус положительный финальный (completed) - ShowcaseItem НЕ трогаем
- Оставляем в available для финализации в create_sale_on_order_completion
- Если текущий статус нейтральный (draft/pending) - переводим available → reserved как раньше

Flow теперь работает корректно:
1. cancelled → draft/pending: ShowcaseItem available → reserved 
2. cancelled → completed: ShowcaseItem available → sold  (ИСПРАВЛЕНО!)
   - reserve_stock_on_uncancellation пропускает (видит is_positive_end)
   - create_sale_on_order_completion финализирует: available → sold

Защита от race condition между двумя сигналами.
This commit is contained in:
2026-01-05 09:41:29 +03:00
parent 6095729409
commit 0faae69c63

View File

@@ -1236,8 +1236,18 @@ def reserve_stock_on_uncancellation(sender, instance, created, **kwargs):
# === Возвращаем ShowcaseItem из available обратно в reserved === # === Возвращаем ShowcaseItem из available обратно в reserved ===
# При отмене (cancelled) ShowcaseItem переходит в 'available'. # При отмене (cancelled) ShowcaseItem переходит в 'available'.
# При возврате к нейтральному статусу нужно вернуть в 'reserved'. # При возврате к нейтральному статусу нужно вернуть в 'reserved'.
# НО: При переходе в положительный финальный статус - НЕ трогаем!
# (create_sale_on_order_completion сам переведёт available → sold)
from inventory.models import ShowcaseItem from inventory.models import ShowcaseItem
# Проверяем: если текущий статус положительный финальный, то пропускаем
if current_status.is_positive_end:
logger.info(
f"🔄 Переход к положительному финальному статусу '{current_status.name}'. "
f"ShowcaseItem остаются в 'available' для финализации в create_sale_on_order_completion."
)
else:
# Переход к нейтральному статусу - возвращаем в reserved
# Находим все ShowcaseItem которые были освобождены при отмене # Находим все ShowcaseItem которые были освобождены при отмене
# (у них sold_order_item сброшен в return_to_available, нужно найти через резервы) # (у них sold_order_item сброшен в return_to_available, нужно найти через резервы)
for order_item in showcase_order_items: for order_item in showcase_order_items: