From 3f1f73ea16ad2101eb0b08f14691b3190c353ab4 Mon Sep 17 00:00:00 2001 From: Andrey Smakotin Date: Mon, 8 Dec 2025 18:30:32 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=20SQL=20=D1=81=D0=BA=D1=80=D0=B8=D0=BF=D1=82=20=D0=B4?= =?UTF-8?q?=D0=BB=D1=8F=20=D0=BE=D1=87=D0=B8=D1=81=D1=82=D0=BA=D0=B8=20?= =?UTF-8?q?=D0=B2=D0=B8=D1=82=D1=80=D0=B8=D0=BD=D0=BD=D1=8B=D1=85=20=D0=BA?= =?UTF-8?q?=D0=BE=D0=BC=D0=BF=D0=BB=D0=B5=D0=BA=D1=82=D0=BE=D0=B2=20=D0=B1?= =?UTF-8?q?=D0=B5=D0=B7=20=D1=80=D0=B5=D0=B7=D0=B5=D1=80=D0=B2=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- myproject/cleanup_orphaned_kits.sql | 50 +++++++++++++++++++++++++++ myproject/cleanup_showcase_kits.py | 52 +++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+) create mode 100644 myproject/cleanup_orphaned_kits.sql create mode 100644 myproject/cleanup_showcase_kits.py diff --git a/myproject/cleanup_orphaned_kits.sql b/myproject/cleanup_orphaned_kits.sql new file mode 100644 index 0000000..c9aafbf --- /dev/null +++ b/myproject/cleanup_orphaned_kits.sql @@ -0,0 +1,50 @@ +-- Скрипт для очистки витринных комплектов без резервов +-- Используется для схемы tenant: anatol + +-- Переключаемся на схему anatol +SET search_path TO anatol; + +-- 1. Проверяем проблемные комплекты (READ ONLY) +-- Витринные комплекты без зарезервированных компонентов + +SELECT + pk.id, + pk.name, + s.name as showcase_name, + pk.status, + pk.is_temporary, + (SELECT COUNT(*) FROM inventory_reservation r + WHERE r.product_kit_id = pk.id + AND r.showcase_id = pk.showcase_id + AND r.status = 'reserved') as reserved_count +FROM products_productkit pk +INNER JOIN inventory_showcase s ON pk.showcase_id = s.id +WHERE pk.is_temporary = TRUE + AND pk.showcase_id IS NOT NULL + AND pk.status = 'active' + AND NOT EXISTS ( + SELECT 1 FROM inventory_reservation r + WHERE r.product_kit_id = pk.id + AND r.showcase_id = pk.showcase_id + AND r.status = 'reserved' + ); + +-- 2. Удалить проблемные комплекты (ОПАСНО! Сначала проверьте результат выше) +-- Раскомментируйте следующие строки для удаления: + +/* +DELETE FROM products_productkit +WHERE id IN ( + SELECT pk.id + FROM products_productkit pk + WHERE pk.is_temporary = TRUE + AND pk.showcase_id IS NOT NULL + AND pk.status = 'active' + AND NOT EXISTS ( + SELECT 1 FROM inventory_reservation r + WHERE r.product_kit_id = pk.id + AND r.showcase_id = pk.showcase_id + AND r.status = 'reserved' + ) +); +*/ diff --git a/myproject/cleanup_showcase_kits.py b/myproject/cleanup_showcase_kits.py new file mode 100644 index 0000000..6c055af --- /dev/null +++ b/myproject/cleanup_showcase_kits.py @@ -0,0 +1,52 @@ +""" +Скрипт для очистки витринных комплектов без резервов. +Запуск: python manage.py shell < cleanup_showcase_kits.py +""" +from django.db import connection +from products.models import ProductKit +from inventory.models import Reservation + +# Устанавливаем схему tenant +schema_name = 'anatol' +with connection.cursor() as cursor: + cursor.execute(f'SET search_path TO {schema_name}') + +print('=' * 70) +print(f'ОЧИСТКА ВИТРИННЫХ КОМПЛЕКТОВ БЕЗ РЕЗЕРВОВ (схема: {schema_name})') +print('=' * 70) + +# Находим все активные витринные комплекты +showcase_kits = ProductKit.objects.filter( + is_temporary=True, + showcase__isnull=False, + status='active' +).select_related('showcase') + +orphaned_kits = [] + +for kit in showcase_kits: + # Проверяем наличие зарезервированных компонентов + has_reservations = Reservation.objects.filter( + product_kit=kit, + showcase=kit.showcase, + status='reserved' + ).exists() + + if not has_reservations: + orphaned_kits.append(kit) + +if not orphaned_kits: + print('\n✅ Проблемных комплектов не найдено. Все витринные комплекты имеют резервы.\n') +else: + print(f'\n⚠️ Найдено {len(orphaned_kits)} витринных комплектов БЕЗ РЕЗЕРВОВ:\n') + + for kit in orphaned_kits: + print( + f' • ID: {kit.id} | "{kit.name}" | Витрина: {kit.showcase.name} | ' + f'Цена: {kit.actual_price} руб.' + ) + + print('\n📝 Для удаления запустите скрипт с подтверждением') + print('Или удалите вручную через админку Django\n') + +print('=' * 70)