Add stock reservation auto-update system

- Add management command to recalculate quantity_reserved for all Stock records
- Add signals to automatically update Stock when Reservation changes
- Implement post_save signal for Reservation creation/updates
- Implement post_delete signal for Reservation deletion
- Both signals call Stock.refresh_from_batches() to recalculate quantities

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-08 11:07:35 +03:00
parent fcc7f2263d
commit d2f15b5126
2 changed files with 157 additions and 0 deletions

View File

@@ -337,6 +337,57 @@ def update_stock_on_writeoff(sender, instance, created, **kwargs):
stock.refresh_from_batches()
@receiver(post_save, sender=Reservation)
def update_stock_on_reservation_change(sender, instance, created, **kwargs):
"""
Сигнал: При создании или изменении резерва (Reservation) обновляем Stock.
Процесс:
1. При создании или изменении резерва пересчитываем quantity_reserved
2. Обновляем запись Stock для этого товара
"""
if not instance.product or not instance.warehouse:
return
# Получаем или создаем Stock запись
stock, _ = Stock.objects.get_or_create(
product=instance.product,
warehouse=instance.warehouse
)
# Пересчитываем остатки из всех активных партий и резервов
# refresh_from_batches() уже вызывает save()
stock.refresh_from_batches()
@receiver(post_delete, sender=Reservation)
def update_stock_on_reservation_delete(sender, instance, **kwargs):
"""
Сигнал: При удалении резерва (Reservation) обновляем Stock.
Процесс:
1. После удаления резерва пересчитываем quantity_reserved
2. Обновляем запись Stock для этого товара
"""
if not instance.product or not instance.warehouse:
return
try:
# Получаем Stock запись (не создаем новую при удалении)
stock = Stock.objects.get(
product=instance.product,
warehouse=instance.warehouse
)
# Пересчитываем остатки из всех активных партий и резервов
# refresh_from_batches() уже вызывает save()
stock.refresh_from_batches()
except Stock.DoesNotExist:
# Если Stock записи нет - ничего не делаем
pass
def _update_product_in_stock(product_id):
"""
Вспомогательная функция: обновить статус in_stock для товара на основе остатков.