feat(products): обеспечить уникальность единицы продажи по умолчанию и улучшить UI формы
Добавлено ограничение на уровне базы данных и валидация форм для обеспечения, что у товара может быть только одна единица продажи с флагом "по умолчанию". Переработан интерфейс маркетинговых флагов и единиц продажи для улучшения UX. Основные изменения: - Добавлен UniqueConstraint в модель ProductSalesUnit для валидации на уровне БД - Создан BaseProductSalesUnitFormSet с кастомной валидацией формы - Обновлен метод save() для корректной обработки новых и существующих записей - Добавлена транзакционная обертка в представлениях ProductCreateView и ProductUpdateView - Переработан блок маркетинговых флагов с карточным дизайном и интерактивными переключателями - Переработан блок единиц продажи в табличный вид с улучшенным UX - Добавлена клиентская логика для взаимного исключения чекбоксов "По умолчанию
This commit is contained in:
@@ -122,34 +122,35 @@ class ProductCreateView(LoginRequiredMixin, ManagerOwnerRequiredMixin, CreateVie
|
||||
return context
|
||||
|
||||
def form_valid(self, form):
|
||||
from django.db import IntegrityError
|
||||
from django.db import IntegrityError, transaction
|
||||
|
||||
context = self.get_context_data()
|
||||
sales_unit_formset = context['sales_unit_formset']
|
||||
|
||||
try:
|
||||
# Сначала сохраняем товар
|
||||
self.object = form.save()
|
||||
with transaction.atomic():
|
||||
# Сначала сохраняем товар
|
||||
self.object = form.save()
|
||||
|
||||
# Затем сохраняем единицы продажи
|
||||
if sales_unit_formset.is_valid():
|
||||
sales_unit_formset.instance = self.object
|
||||
sales_unit_formset.save()
|
||||
else:
|
||||
# Если formset невалиден, показываем ошибки
|
||||
for error in sales_unit_formset.errors:
|
||||
if error:
|
||||
messages.warning(self.request, f'Ошибка в единицах продажи: {error}')
|
||||
# Затем сохраняем единицы продажи
|
||||
if sales_unit_formset.is_valid():
|
||||
sales_unit_formset.instance = self.object
|
||||
sales_unit_formset.save()
|
||||
else:
|
||||
# Если formset невалиден, показываем ошибки
|
||||
for error in sales_unit_formset.errors:
|
||||
if error:
|
||||
messages.warning(self.request, f'Ошибка в единицах продажи: {error}')
|
||||
|
||||
# Обработка загрузки фотографий
|
||||
photo_errors = handle_photos(self.request, self.object, ProductPhoto, 'product')
|
||||
if photo_errors:
|
||||
for error in photo_errors:
|
||||
# Если это предупреждение о лимите фото - warning, иначе - error
|
||||
if 'Загружено' in error and 'обработано только' in error:
|
||||
messages.warning(self.request, error)
|
||||
else:
|
||||
messages.error(self.request, error)
|
||||
# Обработка загрузки фотографий
|
||||
photo_errors = handle_photos(self.request, self.object, ProductPhoto, 'product')
|
||||
if photo_errors:
|
||||
for error in photo_errors:
|
||||
# Если это предупреждение о лимите фото - warning, иначе - error
|
||||
if 'Загружено' in error and 'обработано только' in error:
|
||||
messages.warning(self.request, error)
|
||||
else:
|
||||
messages.error(self.request, error)
|
||||
|
||||
messages.success(self.request, f'Товар "{form.instance.name}" успешно создан!')
|
||||
return super().form_valid(form)
|
||||
@@ -157,7 +158,13 @@ class ProductCreateView(LoginRequiredMixin, ManagerOwnerRequiredMixin, CreateVie
|
||||
except IntegrityError as e:
|
||||
# Обработка ошибки дублирования slug'а или других unique constraints
|
||||
error_msg = str(e).lower()
|
||||
if 'slug' in error_msg or 'duplicate key' in error_msg:
|
||||
if 'unique_default_sales_unit_per_product' in error_msg or 'is_default' in error_msg:
|
||||
messages.error(
|
||||
self.request,
|
||||
'Ошибка: у товара может быть только одна единица продажи по умолчанию. '
|
||||
'Пожалуйста, выберите только одну единицу как "по умолчанию".'
|
||||
)
|
||||
elif 'slug' in error_msg or 'duplicate key' in error_msg:
|
||||
messages.error(
|
||||
self.request,
|
||||
f'Ошибка: товар с названием "{form.instance.name}" уже существует. '
|
||||
@@ -249,34 +256,35 @@ class ProductUpdateView(LoginRequiredMixin, ManagerOwnerRequiredMixin, UpdateVie
|
||||
return context
|
||||
|
||||
def form_valid(self, form):
|
||||
from django.db import IntegrityError
|
||||
from django.db import IntegrityError, transaction
|
||||
|
||||
context = self.get_context_data()
|
||||
sales_unit_formset = context['sales_unit_formset']
|
||||
|
||||
try:
|
||||
# Сначала сохраняем товар
|
||||
self.object = form.save()
|
||||
with transaction.atomic():
|
||||
# Сначала сохраняем товар
|
||||
self.object = form.save()
|
||||
|
||||
# Затем сохраняем единицы продажи
|
||||
if sales_unit_formset.is_valid():
|
||||
sales_unit_formset.instance = self.object
|
||||
sales_unit_formset.save()
|
||||
else:
|
||||
# Если formset невалиден, показываем ошибки
|
||||
for error in sales_unit_formset.errors:
|
||||
if error:
|
||||
messages.warning(self.request, f'Ошибка в единицах продажи: {error}')
|
||||
# Затем сохраняем единицы продажи
|
||||
if sales_unit_formset.is_valid():
|
||||
sales_unit_formset.instance = self.object
|
||||
sales_unit_formset.save()
|
||||
else:
|
||||
# Если formset невалиден, показываем ошибки
|
||||
for error in sales_unit_formset.errors:
|
||||
if error:
|
||||
messages.warning(self.request, f'Ошибка в единицах продажи: {error}')
|
||||
|
||||
# Обработка загрузки фотографий
|
||||
photo_errors = handle_photos(self.request, self.object, ProductPhoto, 'product')
|
||||
if photo_errors:
|
||||
for error in photo_errors:
|
||||
# Если это предупреждение о лимите фото - warning, иначе - error
|
||||
if 'Загружено' in error and 'обработано только' in error:
|
||||
messages.warning(self.request, error)
|
||||
else:
|
||||
messages.error(self.request, error)
|
||||
# Обработка загрузки фотографий
|
||||
photo_errors = handle_photos(self.request, self.object, ProductPhoto, 'product')
|
||||
if photo_errors:
|
||||
for error in photo_errors:
|
||||
# Если это предупреждение о лимите фото - warning, иначе - error
|
||||
if 'Загружено' in error and 'обработано только' in error:
|
||||
messages.warning(self.request, error)
|
||||
else:
|
||||
messages.error(self.request, error)
|
||||
|
||||
messages.success(self.request, f'Товар "{form.instance.name}" успешно обновлен!')
|
||||
return super().form_valid(form)
|
||||
@@ -284,7 +292,13 @@ class ProductUpdateView(LoginRequiredMixin, ManagerOwnerRequiredMixin, UpdateVie
|
||||
except IntegrityError as e:
|
||||
# Обработка ошибки дублирования slug'а или других unique constraints
|
||||
error_msg = str(e).lower()
|
||||
if 'slug' in error_msg or 'duplicate key' in error_msg:
|
||||
if 'unique_default_sales_unit_per_product' in error_msg or 'is_default' in error_msg:
|
||||
messages.error(
|
||||
self.request,
|
||||
'Ошибка: у товара может быть только одна единица продажи по умолчанию. '
|
||||
'Пожалуйста, выберите только одну единицу как "по умолчанию".'
|
||||
)
|
||||
elif 'slug' in error_msg or 'duplicate key' in error_msg:
|
||||
messages.error(
|
||||
self.request,
|
||||
f'Ошибка: товар с названием "{form.instance.name}" уже существует. '
|
||||
|
||||
Reference in New Issue
Block a user