Features: 1) Add include_personal_ordered filter to handle personal orders; 2) Modify ordering filters to support annotation of price using Coalesce and Max;

Fixes: 1) Ensure email and phone number validation rejects duplicates in the user table;

Extra: 1) Minor adjustments to annotated queryset for order filter logic.
This commit is contained in:
Egor Pavlovich Gorbunov 2025-08-20 05:00:55 +03:00
parent 421e4a083f
commit 6e83562ee6
2 changed files with 25 additions and 3 deletions

View file

@ -14,6 +14,7 @@ from django.db.models import (
Subquery, Subquery,
Value, Value,
When, When,
Max,
) )
from django.db.models.functions import Coalesce from django.db.models.functions import Coalesce
from django.utils.http import urlsafe_base64_decode from django.utils.http import urlsafe_base64_decode
@ -73,6 +74,10 @@ class ProductFilter(FilterSet):
slug = CharFilter(field_name="slug", lookup_expr="exact", label=_("Slug")) slug = CharFilter(field_name="slug", lookup_expr="exact", label=_("Slug"))
is_digital = BooleanFilter(field_name="is_digital", label=_("Is Digital")) is_digital = BooleanFilter(field_name="is_digital", label=_("Is Digital"))
include_subcategories = BooleanFilter(method="filter_include_flag", label=_("Include sub-categories")) include_subcategories = BooleanFilter(method="filter_include_flag", label=_("Include sub-categories"))
include_personal_ordered = BooleanFilter(
method="filter_include_personal_ordered",
label=_("Include personal ordered"),
)
order_by = OrderingFilter( order_by = OrderingFilter(
fields=( fields=(
@ -82,7 +87,7 @@ class ProductFilter(FilterSet):
("slug", "slug"), ("slug", "slug"),
("created", "created"), ("created", "created"),
("modified", "modified"), ("modified", "modified"),
("stocks__price", "price"), ("price", "price"),
("?", "random"), ("?", "random"),
), ),
initial="uuid", initial="uuid",
@ -127,6 +132,14 @@ class ProductFilter(FilterSet):
Value(0, output_field=FloatField()), Value(0, output_field=FloatField()),
) )
) )
if "price" in order_fields:
self.queryset = self.queryset.annotate(
price=Coalesce(
Max("stocks__price"),
Value(0.0),
output_field=FloatField(),
)
)
def filter_name(self, queryset, _name, value): def filter_name(self, queryset, _name, value):
search_results = process_query(query=value, request=self.request)["products"] search_results = process_query(query=value, request=self.request)["products"]
@ -147,6 +160,11 @@ class ProductFilter(FilterSet):
raise BadRequest(_("there must be a category_uuid to use include_subcategories flag")) raise BadRequest(_("there must be a category_uuid to use include_subcategories flag"))
return queryset return queryset
def filter_include_personal_ordered(self, queryset, **_kwargs):
if self.data.get("include_personal_ordered", False):
queryset = queryset.filter(stocks__isnull=False, stocks__quantity__gt=0, stocks__price__gt=0)
return queryset
def filter_attributes(self, queryset, _name, value): def filter_attributes(self, queryset, _name, value):
if not value: if not value:
return queryset return queryset

View file

@ -111,12 +111,16 @@ class UpdateUser(BaseMutation):
email = kwargs.get("email") email = kwargs.get("email")
if email is not None and not is_valid_email(email): if (email is not None and not is_valid_email(email)) or User.objects.filter(email=email).exclude(
uuid=uuid
).exists():
raise BadRequest(_("malformed email")) raise BadRequest(_("malformed email"))
phone_number = kwargs.get("phone_number") phone_number = kwargs.get("phone_number")
if phone_number is not None and not is_valid_phone_number(phone_number): if (phone_number is not None and not is_valid_phone_number(phone_number)) or User.objects.filter(
phone_number=phone_number
).exclude(uuid=uuid).exists():
raise BadRequest(_(f"malformed phone number: {phone_number}")) raise BadRequest(_(f"malformed phone number: {phone_number}"))
password = kwargs.get("password", "") password = kwargs.get("password", "")