fix: Исправить сохранение множественных товаров в комплект

ПРОБЛЕМА:
При создании комплекта с несколькими товарами сохранялся только первый товар.

ПРИЧИНЫ И РЕШЕНИЯ:

1. Неправильный префикс в JavaScript (productkit_create.html)
   - Динамически добавляемые формы создавались с префиксом kititem_set-
   - Django ожидает префикс kititem-
   - ИСПРАВЛЕНО: изменены все name атрибуты с kititem_set- на kititem-

2. NULL constraint для quantity (models.py)
   - Поле KitItem.quantity было NOT NULL
   - Пустые формы пытались сохраняться с NULL
   - ИСПРАВЛЕНО: добавлены null=True, blank=True к полю quantity

3. Неправильная валидация пустых форм (forms.py)
   - Не было логики для обработки пустых компонентов
   - ИСПРАВЛЕНО: пустые формы получают quantity=None, заполненные требуют quantity>0

4. Неправильный порядок сохранения (productkit_views.py)
   - Формсет не имел правильного prefixсе
   - ИСПРАВЛЕНО: явно установлен prefix='kititem' везде (get_context_data, form_valid)

 РЕЗУЛЬТАТ: Теперь можно создавать комплекты с неограниченным количеством товаров

🧪 ТЕСТИРОВАНО:
- Комплект 0 товаров ✓
- Комплект 1 товар ✓
- Комплект 3 товара ✓

🤖 Generated with Claude Code
This commit is contained in:
2025-10-23 23:48:39 +03:00
parent 59ba375404
commit 2fb6253d06
5 changed files with 999 additions and 295 deletions

View File

@@ -146,9 +146,12 @@ class KitItemForm(forms.ModelForm):
cleaned_data = super().clean()
product = cleaned_data.get('product')
variant_group = cleaned_data.get('variant_group')
quantity = cleaned_data.get('quantity')
# Если оба поля пусты - это пустая форма (не валидируем, она будет удалена)
if not product and not variant_group:
# Для пустых форм обнуляем количество
cleaned_data['quantity'] = None
return cleaned_data
# Валидация: должен быть указан либо product, либо variant_group (но не оба)
@@ -157,14 +160,56 @@ class KitItemForm(forms.ModelForm):
"Нельзя указывать одновременно товар и группу вариантов. Выберите что-то одно."
)
# Валидация: если выбран товар/группа, количество обязательно и должно быть > 0
if (product or variant_group):
if not quantity or quantity <= 0:
raise forms.ValidationError('Необходимо указать количество больше 0')
return cleaned_data
# Кастомный базовый формсет с валидацией на дубликаты
class BaseKitItemFormSet(forms.BaseInlineFormSet):
def clean(self):
"""Проверка на дубликаты товаров в комплекте"""
if any(self.errors):
# Не проверяем дубликаты если есть другие ошибки
return
products = []
variant_groups = []
for form in self.forms:
if self.can_delete and self._should_delete_form(form):
continue
product = form.cleaned_data.get('product')
variant_group = form.cleaned_data.get('variant_group')
# Проверка дубликатов товаров
if product:
if product in products:
raise forms.ValidationError(
f'Товар "{product.name}" добавлен в комплект более одного раза. '
f'Каждый товар может быть добавлен только один раз.'
)
products.append(product)
# Проверка дубликатов групп вариантов
if variant_group:
if variant_group in variant_groups:
raise forms.ValidationError(
f'Группа вариантов "{variant_group.name}" добавлена более одного раза. '
f'Каждая группа может быть добавлена только один раз.'
)
variant_groups.append(variant_group)
# Формсет для создания комплектов (с пустой формой для удобства)
KitItemFormSetCreate = inlineformset_factory(
ProductKit,
KitItem,
form=KitItemForm,
formset=BaseKitItemFormSet,
fields=['id', 'product', 'variant_group', 'quantity', 'notes'],
extra=1, # Показать 1 пустую форму для первого компонента
can_delete=True, # Разрешить удаление компонентов
@@ -178,6 +223,7 @@ KitItemFormSetUpdate = inlineformset_factory(
ProductKit,
KitItem,
form=KitItemForm,
formset=BaseKitItemFormSet,
fields=['id', 'product', 'variant_group', 'quantity', 'notes'],
extra=0, # НЕ показывать пустые формы при редактировании
can_delete=True, # Разрешить удаление компонентов