Проблема: товары отображались как "нет в наличии" несмотря на наличие остатков на складе. Причина: сигналы на обновление Product.in_stock срабатывают только при изменении Stock через Django ORM. Если Stock была создана напрямую (импорт, миграция и т.д.), сигналы не срабатывали. Решение: 1. Исправлена логика сигналов (inventory/signals.py): - Добавлен импорт post_delete для правильной обработки удаления Stock - Изменён pre_delete на post_delete для более надёжной проверки остатков - Сигналы теперь правильно срабатывают при любом изменении Stock 2. Добавлена миграция (products/migrations/0004_fix_product_in_stock.py): - Пересчитывает in_stock для всех существующих товаров на основе Stock.quantity_available - Товар считается в наличии если есть хотя бы один Stock с quantity_available > 0 - Обратима и безопасна (может быть отменена) 3. Добавлена команда управления (products/management/commands/update_product_in_stock.py): - Позволяет вручную пересчитать in_stock если потребуется - Поддерживает параметр --verbose для подробного логирования - Может быть запущена по расписанию или вручную После этого исправления: - Все товары с остатками на складе автоматически обновляют статус in_stock - Сигналы срабатывают при любом изменении Stock (создание, обновление, удаление) - Отображение наличия товаров в UI будет корректным 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
81 lines
2.8 KiB
Python
81 lines
2.8 KiB
Python
#!/usr/bin/env python
|
||
"""
|
||
Скрипт для исправления статуса Product.in_stock на основе текущих остатков в Stock.
|
||
Пересчитывает in_stock для всех товаров, которые имеют остатки на складе.
|
||
"""
|
||
|
||
import os
|
||
import sys
|
||
import django
|
||
|
||
# Добавляем путь к myproject
|
||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'myproject'))
|
||
os.chdir(os.path.join(os.path.dirname(__file__), 'myproject'))
|
||
|
||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
|
||
django.setup()
|
||
|
||
from decimal import Decimal
|
||
from products.models import Product
|
||
from inventory.models import Stock
|
||
|
||
def fix_product_in_stock():
|
||
"""
|
||
Исправить статус in_stock для всех товаров.
|
||
|
||
Логика:
|
||
- Если для товара есть Stock с quantity_available > 0 → in_stock = True
|
||
- Если нет таких Stock или все пусты → in_stock = False
|
||
"""
|
||
print("\n" + "="*80)
|
||
print("ИСПРАВЛЕНИЕ СТАТУСА НАЛИЧИЯ ТОВАРОВ")
|
||
print("="*80 + "\n")
|
||
|
||
# Получаем все товары
|
||
all_products = Product.all_objects.all()
|
||
total = all_products.count()
|
||
updated = 0
|
||
no_stock = 0
|
||
|
||
print(f"Всего товаров в системе: {total}\n")
|
||
|
||
for product in all_products:
|
||
# Проверяем есть ли остаток
|
||
has_stock = Stock.objects.filter(
|
||
product=product,
|
||
quantity_available__gt=0
|
||
).exists()
|
||
|
||
# Обновляем in_stock если статус изменился
|
||
if product.in_stock != has_stock:
|
||
Product.all_objects.filter(id=product.id).update(in_stock=has_stock)
|
||
status = "ДОБАВЛЕН В НАЛИЧИЕ" if has_stock else "УБРАН ИЗ НАЛИЧИЯ"
|
||
print(f"✓ {product.name:50} → {status}")
|
||
updated += 1
|
||
else:
|
||
if not has_stock:
|
||
no_stock += 1
|
||
|
||
print("\n" + "="*80)
|
||
print(f"РЕЗУЛЬТАТЫ:")
|
||
print(f" - Всего товаров: {total}")
|
||
print(f" - Обновлено: {updated}")
|
||
print(f" - Товаров без наличия: {no_stock}")
|
||
print("="*80 + "\n")
|
||
|
||
# Проверка
|
||
print("ПРОВЕРКА:")
|
||
in_stock_count = Product.all_objects.filter(in_stock=True).count()
|
||
out_of_stock_count = Product.all_objects.filter(in_stock=False).count()
|
||
print(f" - Товаров в наличии: {in_stock_count}")
|
||
print(f" - Товаров не в наличии: {out_of_stock_count}")
|
||
print("="*80 + "\n")
|
||
|
||
if __name__ == '__main__':
|
||
try:
|
||
fix_product_in_stock()
|
||
except Exception as e:
|
||
print(f"\nОШИБКА: {e}")
|
||
import traceback
|
||
traceback.print_exc()
|