Добавлена автогенерация и валидация уникальности артикулов для всех типов товаров

- Добавлен миксин SKUUniqueMixin для единообразной валидации артикулов
- Валидация проверяет уникальность SKU среди Product, ProductKit, ProductCategory, ConfigurableProduct
- Реализована автогенерация артикулов для ConfigurableProduct (формат VAR-XXXXXX)
- Добавлен новый тип счетчика 'configurable' в SKUCounter
- Обновлены формы Product, ProductKit, ProductCategory, ConfigurableProduct
- Рефакторинг методов clean() в формах: валидация имени вынесена в clean_name()
- Добавлена функция generate_configurable_sku() в sku_generator.py
- Обновлена функция ensure_sku_unique() для проверки ConfigurableProduct
- Добавлен метод save() в модель ConfigurableProduct для автогенерации SKU
- Обновлен шаблон configurableproduct_form.html с отображением help_text для SKU

Код стал чистым, без дублирования логики валидации.
This commit is contained in:
2025-12-30 10:47:03 +03:00
parent a95bd56b2b
commit 577401447b
6 changed files with 135 additions and 30 deletions

View File

@@ -5,12 +5,14 @@ New SKU format:
- Products: PROD-XXXXXX or PROD-XXXXXX-VARIANT
- Kits: KIT-XXXXXX
- Categories: CAT-XXXX
- Configurable Products: VAR-XXXXXX
Examples:
- PROD-000001
- PROD-000002-50
- KIT-000001
- CAT-0001
- VAR-000001
"""
import re
from string import ascii_uppercase
@@ -71,13 +73,13 @@ def ensure_sku_unique(base_sku, exclude_id=None, model_type=None):
Args:
base_sku (str): Базовый артикул для проверки
exclude_id (int): ID товара/комплекта/категории, который нужно исключить из проверки
model_type (str): Тип модели ('product', 'kit', 'category') для исключения из проверки
exclude_id (int): ID товара/комплекта/категории/вариативного товара, который нужно исключить из проверки
model_type (str): Тип модели ('product', 'kit', 'category', 'configurable') для исключения из проверки
Returns:
str: Уникальный артикул
"""
from products.models import Product, ProductKit, ProductCategory
from products.models import Product, ProductKit, ProductCategory, ConfigurableProduct
# Проверяем, существует ли базовый артикул
sku = base_sku
@@ -99,7 +101,12 @@ def ensure_sku_unique(base_sku, exclude_id=None, model_type=None):
category_exists = category_exists.exclude(id=exclude_id)
category_exists = category_exists.exists()
return product_exists or kit_exists or category_exists
configurable_exists = ConfigurableProduct.objects.filter(sku=sku_to_check)
if model_type == 'configurable' and exclude_id:
configurable_exists = configurable_exists.exclude(id=exclude_id)
configurable_exists = configurable_exists.exists()
return product_exists or kit_exists or category_exists or configurable_exists
# Если базовый артикул свободен, возвращаем его
if not sku_exists(sku):
@@ -210,3 +217,26 @@ def generate_category_sku():
unique_sku = ensure_sku_unique(base_sku, model_type='category')
return unique_sku
def generate_configurable_sku():
"""
Генерирует уникальный артикул для вариативного товара.
Формат: VAR-XXXXXX
Returns:
str: Сгенерированный артикул
"""
from products.models import SKUCounter
# Получаем следующий номер из глобального счетчика
next_number = SKUCounter.get_next_value('configurable')
# Форматируем номер с ведущими нулями (6 цифр)
base_sku = f"VAR-{next_number:06d}"
# Обеспечиваем уникальность
unique_sku = ensure_sku_unique(base_sku, model_type='configurable')
return unique_sku