Merge branch 'main' into storefront-nuxt
This commit is contained in:
commit
3d4df235f2
2 changed files with 61 additions and 2 deletions
|
|
@ -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()
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in a new issue