diff --git a/myproject/products/templates/products/productkit_create.html b/myproject/products/templates/products/productkit_create.html new file mode 100644 index 0000000..86ce25e --- /dev/null +++ b/myproject/products/templates/products/productkit_create.html @@ -0,0 +1,363 @@ +{% extends 'base.html' %} + +{% block title %}Создать комплект{% endblock %} + +{% block content %} +
+ + + +
+
+
+
+

+ Создание нового комплекта +

+ Шаг 1 из 2: Базовая информация +
+ +
+ +
+ + Как это работает: Сначала создайте комплект с базовой информацией, + затем вы сможете добавить товары на следующем шаге. +
+ + {% if form.non_field_errors %} + + {% endif %} + +
+ {% csrf_token %} + + +
+
+ Основная информация +
+ + +
+ + {{ form.name }} + {% if form.name.help_text %} + {{ form.name.help_text }} + {% endif %} + {% if form.name.errors %} +
{{ form.name.errors }}
+ {% endif %} +
+ + +
+ + {{ form.description }} + {% if form.description.help_text %} + {{ form.description.help_text }} + {% endif %} + {% if form.description.errors %} +
{{ form.description.errors }}
+ {% endif %} +
+ + +
+ +
+ {{ form.categories }} +
+ {% if form.categories.errors %} +
{{ form.categories.errors }}
+ {% endif %} +
+ + +
+ +
+ {{ form.tags }} +
+ {% if form.tags.errors %} +
{{ form.tags.errors }}
+ {% endif %} +
+
+ + +
+
+ Фотографии комплекта +
+ +
+ + + + Выберите фото для комплекта (можно выбрать несколько, до 10 штук) + + + + +
+
+ + +
+
+ Ценообразование +
+ +
+ + Обратите внимание: Метод ценообразования можно настроить после добавления товаров в комплект. + По умолчанию цена будет рассчитываться как сумма цен входящих товаров. +
+ + +
+ + {{ form.pricing_method }} + {% if form.pricing_method.help_text %} + {{ form.pricing_method.help_text }} + {% endif %} + {% if form.pricing_method.errors %} +
{{ form.pricing_method.errors }}
+ {% endif %} +
+ + + + + + + + + +
+ + +
+
+ +
+ +
+ +
+ + {{ form.sku }} + {% if form.sku.help_text %} + {{ form.sku.help_text }} + {% endif %} + {% if form.sku.errors %} +
{{ form.sku.errors }}
+ {% endif %} +
+ + +
+ {{ form.is_active }} + + {% if form.is_active.errors %} +
{{ form.is_active.errors }}
+ {% endif %} +
+
+
+ + +
+ + Отмена + + +
+
+
+
+ + +
+ 💡 Совет: После создания базовой информации вы попадёте на страницу редактирования, + где сможете добавить товары в комплект через удобный поиск. +
+
+
+
+ + + + +{% endblock %} diff --git a/myproject/products/templates/products/productkit_edit.html b/myproject/products/templates/products/productkit_edit.html new file mode 100644 index 0000000..517c085 --- /dev/null +++ b/myproject/products/templates/products/productkit_edit.html @@ -0,0 +1,1085 @@ +{% extends 'base.html' %} + +{% block title %}Редактировать комплект: {{ object.name }}{% endblock %} + +{% block content %} +
+ + + +
+
+
+
+

+ Редактирование: {{ object.name }} +

+ Шаг 2 из 2: Добавление товаров и настройка +
+
+
+ {% csrf_token %} + + {% if form.non_field_errors %} + + {% endif %} + + +
+
Управление фотографиями
+ + + {% if object and productkit_photos %} +
+
Текущие фотографии ({{ photos_count }})
+
+ {% for photo in productkit_photos %} +
+
+ +
+ Фото комплекта +
+
+ {% if photo.order == 0 %} +
⭐ Главное
+ {% else %} + + ⭐ Главным + + {% endif %} + + + + + 🗑️ Удалить + + + Позиция: {{ photo.order }} +
+
+
+ + + + {% endfor %} +
+
+ {% endif %} + + +
+ + + + {% if object %} + Выберите фото для добавления к комплекту (можно выбрать несколько, до 10 штук всего) + {% else %} + Выберите фото для комплекта (можно выбрать несколько, до 10 штук) + {% endif %} + + + + +
+
+ +
+ + +
Основная информация
+ + +
+ {{ form.name.label_tag }} + {{ form.name }} + {% if form.name.help_text %} + {{ form.name.help_text }} + {% endif %} + {% if form.name.errors %} +
{{ form.name.errors }}
+ {% endif %} +
+ + +
+ {{ form.sku.label_tag }} + {{ form.sku }} + {% if form.sku.help_text %} + {{ form.sku.help_text }} + {% endif %} + {% if form.sku.errors %} +
{{ form.sku.errors }}
+ {% endif %} +
+ + +
+
+ + + Новая + +
+
+ {{ form.categories }} +
+ {% if form.categories.help_text %} + {{ form.categories.help_text }} + {% endif %} + {% if form.categories.errors %} +
{{ form.categories.errors }}
+ {% endif %} +
+ + +
+ {{ form.description.label_tag }} + {{ form.description }} + {% if form.description.help_text %} + {{ form.description.help_text }} + {% endif %} + {% if form.description.errors %} +
{{ form.description.errors }}
+ {% endif %} +
+ + +
+
Автоматический расчет стоимости
+
+
+ Сумма товаров: + 0.00 ₽ +
+
+ Количество товаров: + 0 +
+
+ + Сумма автоматически пересчитывается при добавлении/удалении товаров и изменении количества + +
+ + {% for field in form %} + {% if field.name not in 'name,sku,categories,description,tags' %} + {% if field.name == 'fixed_price' %} + + + {% endif %} + +
+ {{ field.label_tag }} + + {% if field.name == 'tags' %} +
+ {{ field }} +
+ {% else %} + {{ field }} + {% endif %} + + {% if field.help_text %} + {{ field.help_text }} + {% endif %} + + {% if field.errors %} +
{{ field.errors }}
+ {% endif %} +
+ {% endif %} + {% endfor %} + + +
+ {{ form.tags.label_tag }} +
+ {{ form.tags }} +
+ {% if form.tags.help_text %} + {{ form.tags.help_text }} + {% endif %} + {% if form.tags.errors %} +
{{ form.tags.errors }}
+ {% endif %} +
+ +
+ + +
Состав комплекта
+ +
+ + Подсказка: Добавьте компоненты комплекта ниже. Каждый компонент может быть либо конкретным товаром, либо группой вариантов (например, розы разных размеров). +
+ + +
+
+
+ Быстрое добавление товара +
+
+
+
+ + +
+ + + + Товар добавится автоматически при клике на результат поиска + +
+
+ + + {{ kititem_formset.management_form }} + + + {% if kititem_formset.non_form_errors %} +
+ {% for error in kititem_formset.non_form_errors %} + {{ error }} + {% endfor %} +
+ {% endif %} + + +
+ {% for kititem_form in kititem_formset %} +
+ + {{ kititem_form.id }} + +
+ Компонент #{{ forloop.counter }} + {% if kititem_form.DELETE %} +
+ {{ kititem_form.DELETE }} + +
+ {% endif %} +
+ +
+ {% if kititem_form.non_field_errors %} +
+ {% for error in kititem_form.non_field_errors %} + {{ error }} + {% endfor %} +
+ {% endif %} + +
+
+ + {{ kititem_form.product }} + {% if kititem_form.product.errors %} +
{{ kititem_form.product.errors }}
+ {% endif %} + Конкретный товар (если выбран, группа вариантов не нужна) +
+ +
+ + {{ kititem_form.variant_group }} + {% if kititem_form.variant_group.errors %} +
{{ kititem_form.variant_group.errors }}
+ {% endif %} + Группа вариантов (если выбрана, конкретный товар не нужен) +
+
+ +
+
+ + {{ kititem_form.quantity }} + {% if kititem_form.quantity.errors %} +
{{ kititem_form.quantity.errors }}
+ {% endif %} +
+ +
+ + {{ kititem_form.notes }} + {% if kititem_form.notes.errors %} +
{{ kititem_form.notes.errors }}
+ {% endif %} +
+
+
+
+ {% endfor %} +
+ + +
+ +
+ + +
+ Отмена +
+ + +
+
+
+
+
+
+
+
+ + +{% endblock %} diff --git a/myproject/products/views/productkit_views.py b/myproject/products/views/productkit_views.py index e70596b..a0d6bf6 100644 --- a/myproject/products/views/productkit_views.py +++ b/myproject/products/views/productkit_views.py @@ -83,72 +83,47 @@ class ProductKitListView(LoginRequiredMixin, PermissionRequiredMixin, ListView): class ProductKitCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateView): """ - View для создания нового комплекта с компонентами. + View для создания нового комплекта (только базовая информация). + После создания redirect на страницу редактирования для добавления товаров. """ model = ProductKit form_class = ProductKitForm - template_name = 'products/productkit_form.html' + template_name = 'products/productkit_create.html' permission_required = 'products.add_productkit' - def get_context_data(self, **kwargs): - context = super().get_context_data(**kwargs) - - if self.request.POST: - context['kititem_formset'] = KitItemFormSetCreate(self.request.POST, instance=self.object) - else: - context['kititem_formset'] = KitItemFormSetCreate(instance=self.object) - - return context - def form_valid(self, form): - # Получаем формсет из POST - kititem_formset = KitItemFormSetCreate(self.request.POST, instance=self.object) + try: + with transaction.atomic(): + # Сохраняем основную форму + self.object = form.save() - # Проверяем валидность формсета - if kititem_formset.is_valid(): - try: - with transaction.atomic(): - # Сохраняем основную форму - self.object = form.save() + # Обработка фотографий + handle_photos(self.request, self.object, ProductKitPhoto, 'kit') - # Сохраняем компоненты - kititem_formset.instance = self.object - kititem_formset.save() + messages.success( + self.request, + f'Комплект "{self.object.name}" создан! Теперь добавьте товары в комплект.' + ) - # Обработка фотографий - handle_photos(self.request, self.object, ProductKitPhoto, 'kit') + # Всегда redirect на страницу редактирования для добавления товаров + return redirect('products:productkit-update', pk=self.object.pk) - messages.success(self.request, f'Комплект "{self.object.name}" успешно создан!') - - # Проверяем, какую кнопку нажали - if self.request.POST.get('action') == 'continue': - return redirect('products:productkit-update', pk=self.object.pk) - else: - return redirect('products:productkit-list') - except Exception as e: - messages.error(self.request, f'Ошибка при сохранении: {str(e)}') - return self.form_invalid(form) - else: - # Если формсет невалиден, показываем форму с ошибками - messages.error(self.request, 'Пожалуйста, исправьте ошибки в компонентах комплекта.') + except Exception as e: + messages.error(self.request, f'Ошибка при сохранении: {str(e)}') return self.form_invalid(form) - def form_invalid(self, form): - # Получаем формсет для отображения ошибок - context = self.get_context_data(form=form) - return self.render_to_response(context) - def get_success_url(self): - return reverse_lazy('products:productkit-list') + # Этот метод не используется, т.к. мы делаем redirect в form_valid + return reverse_lazy('products:productkit-update', kwargs={'pk': self.object.pk}) class ProductKitUpdateView(LoginRequiredMixin, PermissionRequiredMixin, UpdateView): """ - View для редактирования существующего комплекта. + View для редактирования существующего комплекта и добавления товаров. """ model = ProductKit form_class = ProductKitForm - template_name = 'products/productkit_form.html' + template_name = 'products/productkit_edit.html' permission_required = 'products.change_productkit' def get_context_data(self, **kwargs):