Проблема:
При отмене заказа (completed → cancelled) резервы корректно возвращались
в статус 'reserved', но ShowcaseItem оставались в статусе 'sold'.
Из-за этого витринные букеты не отображались в POS после отмены заказа,
хотя физически должны были вернуться на витрину.
Решение:
В существующий сигнал rollback_sale_on_status_change добавлена логика
возврата витринных экземпляров на витрину:
1. После отката Sale и Reservation находим все ShowcaseItem, проданные
в рамках отменяемого заказа (sold_order_item__order=instance)
2. Для каждого экземпляра:
- Меняем status: sold → available
- Очищаем sold_order_item = None
- Очищаем sold_at = None
- НЕ трогаем showcase и product_kit (букет остаётся на той же витрине)
3. Логируем количество возвращённых экземпляров
Преимущества:
- Элегантно: вся логика отката в одном месте (сигнал)
- Транзакционно: откат Sale, Reservation и ShowcaseItem в одной транзакции
- Универсально: работает для POS и обычных заказов
- Без костылей: используем существующую архитектуру сигналов
Теперь при отмене заказа витринный букет автоматически возвращается
на витрину и снова виден в POS - как в реальной жизни.