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:
@@ -386,3 +386,126 @@ def update_product_in_stock_on_stock_delete(sender, instance, **kwargs):
|
||||
"""
|
||||
product_id = instance.product_id
|
||||
_update_product_in_stock(product_id)
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# Сигналы для автоматического обновления себестоимости товара (cost_price)
|
||||
# ============================================================================
|
||||
|
||||
|
||||
@receiver(post_save, sender=StockBatch)
|
||||
def update_product_cost_on_batch_change(sender, instance, created, **kwargs):
|
||||
"""
|
||||
Сигнал: При создании или изменении партии (StockBatch) автоматически
|
||||
обновляется себестоимость товара (Product.cost_price).
|
||||
|
||||
Процесс:
|
||||
1. Проверяем, есть ли связанный товар
|
||||
2. Вызываем ProductCostCalculator для пересчета средневзвешенной стоимости
|
||||
3. Обновляем поле cost_price в БД
|
||||
|
||||
Триггеры:
|
||||
- Создание новой партии (поступление товара)
|
||||
- Изменение количества в партии
|
||||
- Изменение стоимости партии
|
||||
"""
|
||||
if not instance.product:
|
||||
return
|
||||
|
||||
# Импортируем здесь чтобы избежать circular import
|
||||
from products.services.cost_calculator import ProductCostCalculator
|
||||
|
||||
try:
|
||||
# Пересчитываем и обновляем себестоимость товара
|
||||
ProductCostCalculator.update_product_cost(instance.product, save=True)
|
||||
except Exception as e:
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.error(
|
||||
f"Ошибка при обновлении себестоимости товара {instance.product.sku} "
|
||||
f"после изменения партии {instance.id}: {e}",
|
||||
exc_info=True
|
||||
)
|
||||
|
||||
|
||||
@receiver(post_delete, sender=StockBatch)
|
||||
def update_product_cost_on_batch_delete(sender, instance, **kwargs):
|
||||
"""
|
||||
Сигнал: При удалении партии (StockBatch) автоматически
|
||||
обновляется себестоимость товара.
|
||||
|
||||
Процесс:
|
||||
1. После удаления партии пересчитываем себестоимость
|
||||
2. Если партий не осталось - cost_price становится 0.00
|
||||
"""
|
||||
if not instance.product:
|
||||
return
|
||||
|
||||
# Импортируем здесь чтобы избежать circular import
|
||||
from products.services.cost_calculator import ProductCostCalculator
|
||||
|
||||
try:
|
||||
# Пересчитываем и обновляем себестоимость товара
|
||||
ProductCostCalculator.update_product_cost(instance.product, save=True)
|
||||
except Exception as e:
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.error(
|
||||
f"Ошибка при обновлении себестоимости товара после удаления партии: {e}",
|
||||
exc_info=True
|
||||
)
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# Сигналы для динамического пересчета цен комплектов
|
||||
# ============================================================================
|
||||
|
||||
|
||||
@receiver(post_save, sender='products.Product')
|
||||
def update_kit_prices_on_product_change(sender, instance, created, **kwargs):
|
||||
"""
|
||||
Сигнал: При изменении цены товара (price или sale_price)
|
||||
автоматически пересчитываются цены всех комплектов, где используется этот товар.
|
||||
|
||||
Процесс:
|
||||
1. Находим все KitItem с этим товаром
|
||||
2. Для каждого комплекта вызываем recalculate_base_price()
|
||||
3. base_price и price обновляются в БД
|
||||
|
||||
Триггеры:
|
||||
- Изменение price (основная цена товара)
|
||||
- Изменение sale_price (цена со скидкой товара)
|
||||
"""
|
||||
from products.models import KitItem
|
||||
|
||||
# Если это создание товара (не обновление), нет комплектов для пересчета
|
||||
if created:
|
||||
return
|
||||
|
||||
# Находим все KitItem с этим товаром
|
||||
kit_items = KitItem.objects.filter(product=instance)
|
||||
|
||||
if not kit_items.exists():
|
||||
return # Товар не используется в комплектах
|
||||
|
||||
# Для каждого комплекта пересчитываем цены
|
||||
kits_to_update = set()
|
||||
for item in kit_items:
|
||||
kits_to_update.add(item.kit_id)
|
||||
|
||||
# Обновляем цены каждого комплекта
|
||||
from products.models import ProductKit
|
||||
for kit_id in kits_to_update:
|
||||
try:
|
||||
kit = ProductKit.objects.get(id=kit_id)
|
||||
kit.recalculate_base_price()
|
||||
except ProductKit.DoesNotExist:
|
||||
pass
|
||||
except Exception as e:
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.error(
|
||||
f"Ошибка при пересчете цены комплекта {kit_id} "
|
||||
f"после изменения цены товара {instance.sku}: {e}",
|
||||
exc_info=True
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user