Исправлено: резервирование теперь работает с единицами продажи
- Проблема: сигнал на Order срабатывал ДО вычисления quantity_in_base_units в OrderItem.save() - Решение: переместили резервирование на сигнал post_save для OrderItem - Теперь quantity_in_base_units гарантированно вычислено перед резервированием - Изменения: - signals.py: reserve_stock_on_order_create → reserve_stock_on_item_create - Сигнал теперь на OrderItem вместо Order - Резервы создаются для каждой позиции отдельно после её сохранения
This commit is contained in:
@@ -121,14 +121,16 @@ def check_released_reservations_available(order):
|
||||
return True
|
||||
|
||||
|
||||
@receiver(post_save, sender=Order)
|
||||
def reserve_stock_on_order_create(sender, instance, created, **kwargs):
|
||||
@receiver(post_save, sender='orders.OrderItem')
|
||||
def reserve_stock_on_item_create(sender, instance, created, **kwargs):
|
||||
"""
|
||||
Сигнал: При создании нового заказа зарезервировать товар.
|
||||
Сигнал: При создании позиции заказа резервируем товар.
|
||||
|
||||
ВАЖНО: Срабатывает ПОСЛЕ OrderItem.save(), когда quantity_in_base_units уже вычислено!
|
||||
|
||||
Процесс:
|
||||
1. Проверяем, новый ли заказ (создан только что)
|
||||
2. Для обычных товаров - создаём резерв напрямую
|
||||
1. Проверяем, новая ли позиция (создана только что)
|
||||
2. Для обычных товаров - создаём резерв с учетом единиц продажи
|
||||
3. Для комплектов - резервируем компоненты (группируя одинаковые товары)
|
||||
4. Статус резерва = 'reserved'
|
||||
5. Проверяем на существующие резервы (защита от дубликатов)
|
||||
@@ -136,40 +138,40 @@ def reserve_stock_on_order_create(sender, instance, created, **kwargs):
|
||||
from collections import defaultdict
|
||||
|
||||
if not created:
|
||||
return # Только для новых заказов
|
||||
return # Только для новых позиций
|
||||
|
||||
order = instance.order
|
||||
|
||||
# Определяем склад (используем склад самовывоза из заказа или первый активный)
|
||||
warehouse = instance.pickup_warehouse or Warehouse.objects.filter(is_active=True).first()
|
||||
warehouse = order.pickup_warehouse or Warehouse.objects.filter(is_active=True).first()
|
||||
|
||||
if not warehouse:
|
||||
# Если нет активных складов, зарезервировать не можем
|
||||
# Можно логировать ошибку или выбросить исключение
|
||||
return
|
||||
|
||||
# Для каждого товара в заказе
|
||||
for item in instance.items.all():
|
||||
if item.product:
|
||||
# Резервируем товар или комплект
|
||||
if instance.product:
|
||||
# Обычный товар - резервируем с учетом единиц продажи
|
||||
# Используем quantity_in_base_units если заполнено, иначе quantity
|
||||
reservation_quantity = item.quantity_in_base_units if item.quantity_in_base_units else Decimal(str(item.quantity))
|
||||
# quantity_in_base_units УЖЕ вычислено в OrderItem.save()
|
||||
reservation_quantity = instance.quantity_in_base_units if instance.quantity_in_base_units else Decimal(str(instance.quantity))
|
||||
_create_or_update_reservation(
|
||||
item,
|
||||
item.product,
|
||||
instance,
|
||||
instance.product,
|
||||
warehouse,
|
||||
reservation_quantity,
|
||||
sales_unit=item.sales_unit
|
||||
sales_unit=instance.sales_unit
|
||||
)
|
||||
|
||||
elif item.product_kit and item.kit_snapshot:
|
||||
elif instance.product_kit and instance.kit_snapshot:
|
||||
# Комплект - резервируем КОМПОНЕНТЫ из снимка
|
||||
# Группируем одинаковые товары для создания одного резерва
|
||||
product_quantities = defaultdict(Decimal)
|
||||
|
||||
for kit_item in item.kit_snapshot.items.select_related('original_product'):
|
||||
for kit_item in instance.kit_snapshot.items.select_related('original_product'):
|
||||
if kit_item.original_product:
|
||||
# Суммируем количество: qty компонента * qty комплектов в заказе
|
||||
product_quantities[kit_item.original_product_id] += (
|
||||
kit_item.quantity * Decimal(str(item.quantity))
|
||||
kit_item.quantity * Decimal(str(instance.quantity))
|
||||
)
|
||||
|
||||
# Создаём по одному резерву на каждый уникальный товар
|
||||
@@ -177,7 +179,7 @@ def reserve_stock_on_order_create(sender, instance, created, **kwargs):
|
||||
for product_id, total_qty in product_quantities.items():
|
||||
product = Product.objects.get(pk=product_id)
|
||||
_create_or_update_reservation(
|
||||
item, product, warehouse, total_qty, product_kit=item.product_kit
|
||||
instance, product, warehouse, total_qty, product_kit=instance.product_kit
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user