fix: Улучшения системы ценообразования комплектов

Исправлены 4 проблемы:
1. Расчёт цены первого товара - улучшена валидация в getProductPrice и calculateFinalPrice
2. Отображение actual_price в Select2 вместо обычной цены
3. Количество по умолчанию = 1 для новых форм компонентов
4. Auto-select текста при клике на поле количества для удобства редактирования

Изменённые файлы:
- products/forms.py: добавлен __init__ в KitItemForm для quantity.initial = 1
- products/templates/includes/select2-product-init.html: обновлена formatSelectResult
- products/templates/productkit_create.html: добавлен focus handler для auto-select
- products/templates/productkit_edit.html: добавлен focus handler для auto-select

🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-02 19:04:03 +03:00
parent c84a372f98
commit 6c8af5ab2c
120 changed files with 9035 additions and 3036 deletions

View File

@@ -0,0 +1,68 @@
"""
Сервисы для бизнес-логики Product модели.
Извлекает сложную логику из save() метода.
"""
class ProductSaveService:
"""
Сервис для обработки сохранения Product.
Извлекает variant_suffix, генерирует SKU и поисковые ключевые слова.
"""
@staticmethod
def prepare_product_for_save(product):
"""
Подготавливает продукт к сохранению:
- Извлекает variant_suffix из названия
- Генерирует SKU если не задан
- Создает базовые поисковые ключевые слова
Args:
product (Product): Экземпляр продукта
Returns:
Product: Обновленный экземпляр продукта
"""
from ..utils.sku_generator import parse_variant_suffix, generate_product_sku
# Автоматическое извлечение variant_suffix из названия
if not product.variant_suffix and product.name:
parsed_suffix = parse_variant_suffix(product.name)
if parsed_suffix:
product.variant_suffix = parsed_suffix
# Генерация артикула для новых товаров
if not product.sku:
product.sku = generate_product_sku(product)
# Автоматическая генерация ключевых слов для поиска
keywords_parts = [
product.name or '',
product.sku or '',
product.description or '',
]
if not product.search_keywords:
product.search_keywords = ' '.join(filter(None, keywords_parts))
return product
@staticmethod
def update_search_keywords_with_categories(product):
"""
Обновляет поисковые ключевые слова с названиями категорий.
Должен вызываться после сохранения, т.к. ManyToMany требует существующего объекта.
Args:
product (Product): Сохраненный экземпляр продукта
"""
# Добавляем названия категорий в search_keywords после сохранения
# (ManyToMany требует, чтобы объект уже существовал в БД)
if product.pk and product.categories.exists():
category_names = ' '.join([cat.name for cat in product.categories.all()])
if category_names and category_names not in product.search_keywords:
product.search_keywords = f"{product.search_keywords} {category_names}".strip()
# Используем update чтобы избежать рекурсии
from ..models.products import Product
Product.objects.filter(pk=product.pk).update(search_keywords=product.search_keywords)