Features: 1) Add annotations for has_stock, has_price, and personal_order_only in product query to enhance filtering and sorting; 2) Implement conditional ordering by personal_order_only in product query;

Fixes: 1) Remove redundant `personal_order_only` mapping from filters to fix duplicate processing; 2) Adjust sorting logic to avoid appending unneeded `personal_order_only` in filters;

Extra: 1) Add missing imports for Django model annotations and fields; 2) Refactor product query for clarity and improved handling of availability and price conditions.
This commit is contained in:
Egor Pavlovich Gorbunov 2025-10-02 15:08:20 +03:00
parent fa97a582d3
commit a344014d9f
2 changed files with 34 additions and 4 deletions

View file

@ -96,7 +96,6 @@ class ProductFilter(FilterSet):
("price_order", "price"), ("price_order", "price"),
("sku", "sku"), ("sku", "sku"),
("?", "random"), ("?", "random"),
("personal_order_only", "personal_order_only"),
), ),
initial="uuid", initial="uuid",
) )
@ -312,10 +311,11 @@ class ProductFilter(FilterSet):
key = "?" key = "?"
mapped_requested.append(key) mapped_requested.append(key)
continue continue
if key == "personal_order_only":
continue
mapped_requested.append(f"-{key}" if desc else key) mapped_requested.append(f"-{key}" if desc else key)
has_personal_in_request = any(p.lstrip("-") == "personal_order_only" for p in mapped_requested) final_ordering = ["personal_order_only"] + mapped_requested
final_ordering = (["personal_order_only"] if not has_personal_in_request else []) + mapped_requested
if final_ordering: if final_ordering:
qs = qs.order_by(*final_ordering) qs = qs.order_by(*final_ordering)

View file

@ -1,6 +1,7 @@
import logging import logging
from django.core.cache import cache from django.core.cache import cache
from django.db.models import Max, Case, When, Value, IntegerField, BooleanField
from django.utils import timezone from django.utils import timezone
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from graphene import Field, List, ObjectType, Schema from graphene import Field, List, ObjectType, Schema
@ -148,7 +149,7 @@ class Query(ObjectType):
product = Product.objects.get(uuid=kwargs["uuid"]) product = Product.objects.get(uuid=kwargs["uuid"])
if product.is_active and product.brand.is_active and product.category.is_active: if product.is_active and product.brand.is_active and product.category.is_active:
info.context.user.add_to_recently_viewed(product.uuid) info.context.user.add_to_recently_viewed(product.uuid)
return ( base_qs = (
Product.objects.all().select_related("brand", "category").prefetch_related("images", "stocks") Product.objects.all().select_related("brand", "category").prefetch_related("images", "stocks")
if info.context.user.has_perm("core.view_product") if info.context.user.has_perm("core.view_product")
else Product.objects.filter( else Product.objects.filter(
@ -162,6 +163,35 @@ class Query(ObjectType):
.prefetch_related("images", "stocks") .prefetch_related("images", "stocks")
) )
base_qs = (
base_qs.annotate(
has_stock=Max(
Case(
When(stocks__quantity__gt=0, then=Value(1)),
default=Value(0),
output_field=IntegerField(),
)
),
has_price=Max(
Case(
When(stocks__price__gt=0, then=Value(1)),
default=Value(0),
output_field=IntegerField(),
)
),
)
.annotate(
personal_order_only=Case(
When(has_stock=0, has_price=1, then=Value(True)),
default=Value(False),
output_field=BooleanField(),
)
)
.order_by("personal_order_only")
)
return base_qs
@staticmethod @staticmethod
def resolve_orders(_parent, info, **kwargs): def resolve_orders(_parent, info, **kwargs):
orders = Order.objects orders = Order.objects