Исправление конфликта сигналов при отмене трансформации
Исправлена проблема, когда при отмене проведенной трансформации оба сигнала выполнялись последовательно:
- rollback_transformation_on_cancel возвращал резервы в 'reserved'
- release_reservations_on_draft_cancel ошибочно освобождал их в 'released'
Изменена проверка в release_reservations_on_draft_cancel: вместо проверки наличия партий Output (которые уже удалены) теперь проверяется статус резервов ('converted_to_transformation') или наличие поля converted_at, что работает независимо от порядка выполнения сигналов.
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
"""
|
||||
|
||||
from django.db.models.signals import post_save, pre_delete, post_delete
|
||||
from django.db.models import Q
|
||||
from django.db import transaction
|
||||
from django.dispatch import receiver
|
||||
from django.utils import timezone
|
||||
@@ -1533,19 +1534,21 @@ def reserve_on_transformation_input_create(sender, instance, created, **kwargs):
|
||||
"""
|
||||
При создании входного товара в черновике - резервируем его.
|
||||
"""
|
||||
# Резервируем только при создании нового входного товара
|
||||
if not created:
|
||||
return
|
||||
|
||||
# Резервируем только если трансформация в draft
|
||||
if instance.transformation.status != 'draft':
|
||||
return
|
||||
|
||||
# Создаем или обновляем резерв
|
||||
Reservation.objects.update_or_create(
|
||||
# Создаем резерв
|
||||
Reservation.objects.create(
|
||||
transformation_input=instance,
|
||||
product=instance.product,
|
||||
warehouse=instance.transformation.warehouse,
|
||||
defaults={
|
||||
'quantity': instance.quantity,
|
||||
'status': 'reserved'
|
||||
}
|
||||
quantity=instance.quantity,
|
||||
status='reserved'
|
||||
)
|
||||
|
||||
|
||||
@@ -1582,7 +1585,8 @@ def process_transformation_on_complete(sender, instance, created, **kwargs):
|
||||
allocations = StockBatchManager.write_off_by_fifo(
|
||||
product=trans_input.product,
|
||||
warehouse=instance.warehouse,
|
||||
quantity_to_write_off=trans_input.quantity
|
||||
quantity_to_write_off=trans_input.quantity,
|
||||
exclude_transformation=instance # Исключаем резервы этой трансформации
|
||||
)
|
||||
|
||||
# Суммируем себестоимость списанного
|
||||
@@ -1590,13 +1594,22 @@ def process_transformation_on_complete(sender, instance, created, **kwargs):
|
||||
total_input_cost += batch.cost_price * qty
|
||||
|
||||
# Обновляем резерв
|
||||
Reservation.objects.filter(
|
||||
reservations_updated = Reservation.objects.filter(
|
||||
transformation_input=trans_input,
|
||||
status='reserved'
|
||||
).update(
|
||||
status='converted_to_transformation',
|
||||
converted_at=timezone.now()
|
||||
)
|
||||
|
||||
# ВАЖНО: .update() не вызывает сигналы, поэтому нужно вручную обновить Stock
|
||||
if reservations_updated > 0:
|
||||
stock = Stock.objects.filter(
|
||||
product=trans_input.product,
|
||||
warehouse=instance.warehouse
|
||||
).first()
|
||||
if stock:
|
||||
stock.refresh_from_batches()
|
||||
|
||||
# 2. Создаем партии Output
|
||||
for trans_output in instance.outputs.all():
|
||||
@@ -1678,8 +1691,16 @@ def release_reservations_on_draft_cancel(sender, instance, **kwargs):
|
||||
if instance.status != 'cancelled':
|
||||
return
|
||||
|
||||
# Проверяем что это был черновик (нет созданных партий)
|
||||
if instance.outputs.filter(stock_batch__isnull=False).exists():
|
||||
# Проверяем, были ли резервы в статусе 'converted_to_transformation'
|
||||
# или имеют заполненное поле converted_at (что означает, что трансформация была проведена)
|
||||
# Это работает независимо от порядка выполнения сигналов
|
||||
has_converted_reservations = Reservation.objects.filter(
|
||||
transformation_input__transformation=instance
|
||||
).filter(
|
||||
Q(status='converted_to_transformation') | Q(converted_at__isnull=False)
|
||||
).exists()
|
||||
|
||||
if has_converted_reservations:
|
||||
return # Это была проведенная трансформация, обрабатывается другим сигналом
|
||||
|
||||
# Освобождаем все резервы
|
||||
|
||||
Reference in New Issue
Block a user