Добавлен расчёт и отображение доступного количества комплектов

- Добавлен метод calculate_available_quantity() в модель ProductKit для точного расчёта максимального количества комплектов на основе свободных остатков компонентов
- Обновлён метод check_availability() для использования нового расчёта (обратная совместимость)
- Удалён устаревший сервис kit_availability.py

Исправлено отображение остатков комплектов:
- products_list.html: вместо прочерка показывается количество комплектов
- catalog.html: добавлено отображение доступного количества комплектов с цветовой индикацией
- POS terminal.js: в карточке товара показывается конкретное количество вместо общего 'В наличии'

Обновлены представления:
- ProductsListView: аннотирует комплекты атрибутом total_free
- CatalogView: рассчитывает доступное количество для каждого комплекта
- POS get_products(): убран хардкод, используется реальный расчёт по складу
This commit is contained in:
2026-01-06 01:02:28 +03:00
parent 2aba3d2404
commit d44ae0b598
12 changed files with 130 additions and 176 deletions

View File

@@ -12,6 +12,7 @@ from .models import Order, OrderItem, Address, OrderStatus, Transaction, Payment
from .forms import OrderForm, OrderItemFormSet, OrderItemForm, OrderStatusForm, TransactionForm
from .filters import OrderFilter
from .services.address_service import AddressService
from inventory.models import Reservation
import json
@@ -1067,6 +1068,7 @@ def create_order_from_pos(request):
showcase_item_ids = item_data.get('showcase_item_ids', [])
if not showcase_item_ids:
logger.warning(f"⚠️ Пустой список showcase_item_ids для комплекта {kit.name}")
continue
# Создаём OrderItem с флагом is_from_showcase
@@ -1086,8 +1088,29 @@ def create_order_from_pos(request):
locked_by_user=request.user
)
reserved_count = 0
component_count = 0
for showcase_item in showcase_items:
showcase_item.reserve_for_order(order_item)
reserved_count += 1
# КРИТИЧНО: Привязываем существующие резервы компонентов к OrderItem
# Эти резервы были созданы при добавлении букета на витрину
component_reservations = Reservation.objects.filter(
showcase_item=showcase_item,
status='reserved'
)
for reservation in component_reservations:
reservation.order_item = order_item
reservation.save(update_fields=['order_item'])
component_count += 1
logger.info(
f"✓ Витринный комплект '{kit.name}': зарезервировано {reserved_count} экз., "
f"привязано {component_count} резервов компонентов к OrderItem #{order_item.id}"
)
# 5. Пересчитываем стоимость заказа
order.calculate_total()