Add stock availability display to product list and detail views
- Add total_available, total_reserved, total_free annotations to product queries - Display free stock (green/red) with reserved count in product list - Show detailed stock info in product detail page (moved to top) - Make reservation count clickable to view filtered reservations - Add product filter support to ReservationListView - Add product link in reservation list for easy navigation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -5,7 +5,8 @@ from django.contrib import messages
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin
|
||||
from django.views.generic import ListView, CreateView, DetailView, UpdateView, DeleteView
|
||||
from django.urls import reverse_lazy
|
||||
from django.db.models import Q
|
||||
from django.db.models import Q, Sum, Value, DecimalField
|
||||
from django.db.models.functions import Coalesce
|
||||
from itertools import chain
|
||||
|
||||
from ..models import Product, ProductCategory, ProductTag, ProductKit
|
||||
@@ -162,8 +163,14 @@ class ProductDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView)
|
||||
permission_required = 'products.view_product'
|
||||
|
||||
def get_queryset(self):
|
||||
# Предзагрузка фотографий для избежания N+1 запросов
|
||||
return super().get_queryset().prefetch_related('photos')
|
||||
# Предзагрузка фотографий и аннотация остатков
|
||||
total_available = Coalesce(Sum('stocks__quantity_available'), Value(0), output_field=DecimalField())
|
||||
total_reserved = Coalesce(Sum('stocks__quantity_reserved'), Value(0), output_field=DecimalField())
|
||||
return super().get_queryset().prefetch_related('photos').annotate(
|
||||
total_available=total_available,
|
||||
total_reserved=total_reserved,
|
||||
total_free=total_available - total_reserved,
|
||||
)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
@@ -253,7 +260,14 @@ class CombinedProductListView(LoginRequiredMixin, PermissionRequiredMixin, ListV
|
||||
type_filter = self.request.GET.get('type', 'all')
|
||||
|
||||
# Получаем товары и комплекты (только постоянные комплекты)
|
||||
products = Product.objects.prefetch_related('categories', 'photos', 'tags')
|
||||
# Аннотируем товары данными об остатках из агрегированной таблицы Stock
|
||||
total_available = Coalesce(Sum('stocks__quantity_available'), Value(0), output_field=DecimalField())
|
||||
total_reserved = Coalesce(Sum('stocks__quantity_reserved'), Value(0), output_field=DecimalField())
|
||||
products = Product.objects.prefetch_related('categories', 'photos', 'tags').annotate(
|
||||
total_available=total_available,
|
||||
total_reserved=total_reserved,
|
||||
total_free=total_available - total_reserved,
|
||||
)
|
||||
kits = ProductKit.objects.filter(is_temporary=False).prefetch_related('categories', 'photos', 'tags')
|
||||
|
||||
# Применяем фильтры
|
||||
|
||||
Reference in New Issue
Block a user