feat(pos): фиксировать цены товаров в витринных комплектах
- Добавлено поле KitItem.unit_price для хранения зафиксированной цены - Витринные комплекты больше не обновляются при изменении цен товаров - Добавлен красный индикатор на карточке если цена неактуальна - Добавлен warning в модалке редактирования с кнопкой "Актуализировать" Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -81,6 +81,7 @@ def get_showcase_kits_for_pos():
|
||||
'product_kit__sku',
|
||||
'product_kit__price',
|
||||
'product_kit__sale_price',
|
||||
'product_kit__base_price',
|
||||
'showcase_id',
|
||||
'showcase__name'
|
||||
).annotate(
|
||||
@@ -109,6 +110,19 @@ def get_showcase_kits_for_pos():
|
||||
thumbnail_url = None
|
||||
kit_photos[photo.kit_id] = thumbnail_url
|
||||
|
||||
# Загружаем состав комплектов для проверки актуальности цен
|
||||
kit_items_data = {}
|
||||
for ki in KitItem.objects.filter(kit_id__in=kit_ids).select_related('product'):
|
||||
if ki.kit_id not in kit_items_data:
|
||||
kit_items_data[ki.kit_id] = []
|
||||
kit_items_data[ki.kit_id].append(ki)
|
||||
|
||||
# Считаем актуальные цены для каждого комплекта
|
||||
kit_actual_prices = {}
|
||||
for kit_id, items in kit_items_data.items():
|
||||
actual_price = sum((ki.product.actual_price or 0) * (ki.quantity or 0) for ki in items)
|
||||
kit_actual_prices[kit_id] = actual_price
|
||||
|
||||
# Формируем результат
|
||||
showcase_kits = []
|
||||
for item in all_items:
|
||||
@@ -125,6 +139,11 @@ def get_showcase_kits_for_pos():
|
||||
# Определяем актуальную цену
|
||||
price = item['product_kit__sale_price'] or item['product_kit__price']
|
||||
|
||||
# Проверяем актуальность цены (сравниваем сохранённую цену с актуальной ценой товаров)
|
||||
actual_price = kit_actual_prices.get(kit_id, Decimal('0'))
|
||||
base_price = item['product_kit__base_price']
|
||||
price_outdated = base_price and abs(float(base_price) - float(actual_price)) > 0.01
|
||||
|
||||
showcase_kits.append({
|
||||
'id': kit_id,
|
||||
'name': item['product_kit__name'],
|
||||
@@ -139,7 +158,9 @@ def get_showcase_kits_for_pos():
|
||||
# Количества
|
||||
'available_count': item['available_count'], # Сколько можно добавить
|
||||
'total_count': item['total_count'], # Всего на витрине (включая в корзине)
|
||||
'showcase_item_ids': available_item_ids # IDs только доступных
|
||||
'showcase_item_ids': available_item_ids, # IDs только доступных
|
||||
# Флаг неактуальной цены
|
||||
'price_outdated': price_outdated
|
||||
})
|
||||
|
||||
return showcase_kits
|
||||
@@ -954,15 +975,24 @@ def get_product_kit_details(request, kit_id):
|
||||
).select_related('showcase').first()
|
||||
|
||||
showcase_id = showcase_reservation.showcase.id if showcase_reservation else None
|
||||
|
||||
|
||||
# Собираем данные о составе
|
||||
items = [{
|
||||
'product_id': ki.product.id,
|
||||
'name': ki.product.name,
|
||||
'qty': str(ki.quantity),
|
||||
'price': str(ki.product.actual_price)
|
||||
} for ki in kit.kit_items.all()]
|
||||
|
||||
# Используем unit_price если есть (зафиксированная цена), иначе актуальную цену товара
|
||||
items = []
|
||||
for ki in kit.kit_items.all():
|
||||
# Зафиксированная цена или актуальная цена товара
|
||||
item_price = ki.unit_price if ki.unit_price is not None else ki.product.actual_price
|
||||
item_data = {
|
||||
'product_id': ki.product.id,
|
||||
'name': ki.product.name,
|
||||
'qty': str(ki.quantity),
|
||||
'price': str(item_price)
|
||||
}
|
||||
# Для временных комплектов добавляем актуальную цену из каталога для сравнения
|
||||
if kit.is_temporary and ki.unit_price is not None:
|
||||
item_data['actual_catalog_price'] = str(ki.product.actual_price)
|
||||
items.append(item_data)
|
||||
|
||||
# Фото (используем миниатюру для быстрой загрузки)
|
||||
photo_url = None
|
||||
if kit.photos.exists():
|
||||
@@ -1100,10 +1130,12 @@ def create_temp_kit_to_showcase(request):
|
||||
|
||||
# 2. Создаём KitItem для каждого товара из корзины
|
||||
for product_id, quantity in aggregated_items.items():
|
||||
product = products[product_id]
|
||||
KitItem.objects.create(
|
||||
kit=kit,
|
||||
product=products[product_id],
|
||||
quantity=quantity
|
||||
product=product,
|
||||
quantity=quantity,
|
||||
unit_price=product.actual_price # Фиксируем цену для временного комплекта
|
||||
)
|
||||
|
||||
# 3. Пересчитываем цену комплекта
|
||||
@@ -1318,10 +1350,12 @@ def update_product_kit(request, kit_id):
|
||||
# Обновляем состав
|
||||
kit.kit_items.all().delete()
|
||||
for product_id, quantity in aggregated_items.items():
|
||||
product = products[product_id]
|
||||
KitItem.objects.create(
|
||||
kit=kit,
|
||||
product=products[product_id],
|
||||
quantity=quantity
|
||||
product=product,
|
||||
quantity=quantity,
|
||||
unit_price=product.actual_price # Фиксируем актуальную цену
|
||||
)
|
||||
|
||||
kit.recalculate_base_price()
|
||||
|
||||
Reference in New Issue
Block a user