Merge branch 'main' into storefront-nuxt

This commit is contained in:
Egor Pavlovich Gorbunov 2025-09-17 18:58:22 +03:00
commit 3d4df235f2
2 changed files with 61 additions and 2 deletions

View file

@ -16,6 +16,7 @@ from django.db.models import (
When,
Max,
Prefetch,
BooleanField,
)
from django.db.models.functions import Coalesce
from django.utils.http import urlsafe_base64_decode
@ -92,6 +93,7 @@ class ProductFilter(FilterSet):
("price_order", "price"),
("sku", "sku"),
("?", "random"),
("personal_order_only", "personal_order_only"),
),
initial="uuid",
)
@ -279,8 +281,8 @@ class ProductFilter(FilterSet):
ordering_param = self.data.get("order_by", "")
if ordering_param:
order_fields = [field.strip() for field in ordering_param.split(",")]
if any(field.lstrip("-") == "rating" for field in order_fields):
order_fields_no_sign = [field.strip("-") for field in ordering_param.split(",")]
if "rating" in order_fields_no_sign:
feedback_qs = (
Feedback.objects.filter(order_product__product_id=OuterRef("pk"))
.values("order_product__product_id")
@ -293,6 +295,58 @@ class ProductFilter(FilterSet):
Value(0, output_field=FloatField()),
)
)
if ordering_param and any(f.lstrip("-") == "price" for f in ordering_param.split(",")):
qs = qs.annotate(
price_order=Coalesce(
Max("stocks__price"),
Value(0.0),
output_field=FloatField(),
)
)
qs = 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(),
)
)
requested = [part.strip() for part in ordering_param.split(",") if part.strip()] if ordering_param else []
mapped_requested = []
for part in requested:
desc = part.startswith("-")
key = part.lstrip("-")
if key == "price":
key = "price_order"
if key == "random":
key = "?"
mapped_requested.append(key)
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
if final_ordering:
qs = qs.order_by(*final_ordering)
return qs.distinct()

View file

@ -501,6 +501,7 @@ class ProductType(DjangoObjectType):
feedbacks_count = Int(description=_("number of feedbacks"))
personal_orders_only = Boolean(description=_("only available for personal orders"))
seo_meta = Field(SEOMetaType, description=_("SEO Meta snapshot"))
rating = Float(description=_("rating value from 1 to 10, inclusive, or 0 if not set."))
class Meta:
model = Product
@ -521,6 +522,7 @@ class ProductType(DjangoObjectType):
"attribute_groups",
"images",
"price",
"rating",
)
filter_fields = ["uuid", "name"]
description = _("products")
@ -528,6 +530,9 @@ class ProductType(DjangoObjectType):
def resolve_price(self: Product, _info) -> float:
return self.price or 0.0
def resolve_rating(self: Product, _info) -> float:
return self.rating or 0.0
def resolve_feedbacks(self: Product, _info):
if _info.context.user.has_perm("core.view_feedback"):
return Feedback.objects.filter(order_product__product=self)