Добавлена защита от удаления дефолтных Склада и Витрины

Проблема: при создании тенанта автоматически создаются дефолтные
Склад и Витрина. Если пользователь удалит их, система может сломаться:
POS, создание заказов и резервирование перестанут работать.

Решение: реализована строгая валидация + мягкое удаление для витрин.

Изменения в inventory/views/warehouse.py:
- Добавлена валидация перед деактивацией склада:
  * Блокировка деактивации последнего активного склада
  * Проверка ненулевых остатков товаров
  * Проверка активных резервов
  * Предупреждение при деактивации дефолтного склада

Изменения в inventory/views/showcase.py:
- ShowcaseListView: по умолчанию показывает только активные витрины
- ShowcaseDeleteView: изменена логика с жесткого на мягкое удаление
- Добавлена валидация перед деактивацией витрины:
  * Блокировка деактивации последней активной витрины склада
  * Проверка активных резервов
  * Проверка физических экземпляров комплектов (ShowcaseItem)
  * Предупреждение при деактивации дефолтной витрины

Изменения в inventory/forms_showcase.py:
- Проверка уникальности названия витрины учитывает только активные

Изменения в inventory/admin.py:
- ShowcaseAdmin: добавлены методы delete_model() и delete_queryset()
  для блокировки удаления последней витрины через админку
- WarehouseAdmin: добавлены методы delete_model() и delete_queryset()
  для блокировки удаления последнего склада через админку

Преимущества:
 Система не сломается - всегда есть хотя бы один активный склад/витрина
 Данные в безопасности - мягкое удаление для обеих сущностей
 Понятные сообщения об ошибках для пользователя
 Защита работает как в UI, так и в Django Admin

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-03 19:52:01 +03:00
parent e6fb30aa02
commit 0f09702094
4 changed files with 244 additions and 27 deletions

View File

@@ -55,13 +55,13 @@ class ShowcaseForm(forms.ModelForm):
self.initial['warehouse'] = default_warehouse.id
def clean_name(self):
"""Проверка уникальности названия витрины в рамках склада"""
"""Проверка уникальности названия витрины в рамках склада (среди активных)"""
name = self.cleaned_data.get('name')
warehouse = self.cleaned_data.get('warehouse')
if name and warehouse:
# Проверяем уникальность названия в рамках склада
queryset = Showcase.objects.filter(name=name, warehouse=warehouse)
# Проверяем уникальность названия в рамках склада (только среди активных)
queryset = Showcase.objects.filter(name=name, warehouse=warehouse, is_active=True)
# При редактировании исключаем текущий экземпляр
if self.instance and self.instance.pk:
@@ -69,7 +69,7 @@ class ShowcaseForm(forms.ModelForm):
if queryset.exists():
raise ValidationError(
f'Витрина с названием "{name}" уже существует на складе "{warehouse.name}". '
f'Активная витрина с названием "{name}" уже существует на складе "{warehouse.name}". '
'Пожалуйста, выберите другое название.'
)