diff --git a/core/filters.py b/core/filters.py index d2a65373..98e31eca 100644 --- a/core/filters.py +++ b/core/filters.py @@ -96,7 +96,6 @@ class ProductFilter(FilterSet): ("price_order", "price"), ("sku", "sku"), ("?", "random"), - ("personal_order_only", "personal_order_only"), ), initial="uuid", ) @@ -312,10 +311,11 @@ class ProductFilter(FilterSet): key = "?" mapped_requested.append(key) continue + if key == "personal_order_only": + continue 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"] if not has_personal_in_request else []) + mapped_requested + final_ordering = ["personal_order_only"] + mapped_requested if final_ordering: qs = qs.order_by(*final_ordering) diff --git a/core/graphene/schema.py b/core/graphene/schema.py index 046f695d..5382cb66 100644 --- a/core/graphene/schema.py +++ b/core/graphene/schema.py @@ -1,6 +1,7 @@ import logging from django.core.cache import cache +from django.db.models import Max, Case, When, Value, IntegerField, BooleanField from django.utils import timezone from django.core.exceptions import PermissionDenied from graphene import Field, List, ObjectType, Schema @@ -148,7 +149,7 @@ class Query(ObjectType): product = Product.objects.get(uuid=kwargs["uuid"]) if product.is_active and product.brand.is_active and product.category.is_active: info.context.user.add_to_recently_viewed(product.uuid) - return ( + base_qs = ( Product.objects.all().select_related("brand", "category").prefetch_related("images", "stocks") if info.context.user.has_perm("core.view_product") else Product.objects.filter( @@ -162,6 +163,35 @@ class Query(ObjectType): .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 def resolve_orders(_parent, info, **kwargs): orders = Order.objects